-
Notifications
You must be signed in to change notification settings - Fork 1
Jump diffusion model #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
32acbe8
d2c80c0
6749a8b
8d6906d
7211f38
2c32af9
01a5d6b
9012056
6367366
e071164
a87c053
a1901ff
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,24 +3,20 @@ | |
|
|
||
| from typing import Dict | ||
| from typing import List | ||
| from typing import Union | ||
|
|
||
| import numpy as np | ||
| import scipp as sc | ||
| from easyscience.variable import DescriptorNumber | ||
| from easyscience.variable import Parameter | ||
| from numpy.typing import ArrayLike | ||
| from scipp.constants import hbar as scipp_hbar | ||
|
|
||
| from easydynamics.sample_model.component_collection import ComponentCollection | ||
| from easydynamics.sample_model.components import Lorentzian | ||
| from easydynamics.sample_model.diffusion_model.diffusion_model_base import DiffusionModelBase | ||
| from easydynamics.utils.utils import Numeric | ||
| from easydynamics.utils.utils import Q_type | ||
| from easydynamics.utils.utils import _validate_and_convert_Q | ||
|
|
||
| Numeric = Union[float, int] | ||
|
|
||
| Q_type = np.ndarray | Numeric | list | ArrayLike | ||
|
|
||
|
|
||
| class BrownianTranslationalDiffusion(DiffusionModelBase): | ||
| """Model of Brownian translational diffusion, consisting of a | ||
|
|
@@ -46,7 +42,6 @@ def __init__( | |
| unit: str | sc.Unit = 'meV', | ||
| scale: Numeric = 1.0, | ||
| diffusion_coefficient: Numeric = 1.0, | ||
| diffusion_unit: str = 'm**2/s', | ||
| ): | ||
| """Initialize a new BrownianTranslationalDiffusion model. | ||
|
|
||
|
|
@@ -62,65 +57,35 @@ def __init__( | |
| Defaults to "meV". | ||
| scale : float or Parameter, optional | ||
| Scale factor for the diffusion model. | ||
| diffusion_coefficient : float or Parameter, optional | ||
| Diffusion coefficient D. If a number is provided, | ||
| it is assumed to be in the unit given by diffusion_unit. | ||
| diffusion_coefficient : Number, optional | ||
| Diffusion coefficient D in m^2/s. | ||
| Defaults to 1.0. | ||
| diffusion_unit : str, optional | ||
| Unit for the diffusion coefficient D. Default is m**2/s. | ||
| Options are 'meV*Å**2' or 'm**2/s' | ||
| """ | ||
| if not isinstance(scale, (Parameter, Numeric)): | ||
| if not isinstance(scale, Numeric): | ||
| raise TypeError('scale must be a number.') | ||
|
|
||
| if not isinstance(diffusion_coefficient, (Parameter, Numeric)): | ||
| if not isinstance(diffusion_coefficient, Numeric): | ||
| raise TypeError('diffusion_coefficient must be a number.') | ||
|
|
||
| if not isinstance(diffusion_unit, str): | ||
| raise TypeError("diffusion_unit must be 'meV*Å**2' or 'm**2/s'.") | ||
|
|
||
| if diffusion_unit == 'meV*Å**2' or diffusion_unit == 'meV*angstrom**2': | ||
| # In this case, hbar is absorbed in the unit of D | ||
| self._hbar = DescriptorNumber('hbar', 1.0) | ||
| elif diffusion_unit == 'm**2/s' or diffusion_unit == 'm^2/s': | ||
| self._hbar = DescriptorNumber.from_scipp('hbar', scipp_hbar) | ||
| else: | ||
| raise ValueError("diffusion_unit must be 'meV*Å**2' or 'm**2/s'.") | ||
|
|
||
| scale = Parameter(name='scale', value=float(scale), fixed=False, min=0.0) | ||
|
|
||
| diffusion_coefficient = Parameter( | ||
| name='diffusion_coefficient', | ||
| value=float(diffusion_coefficient), | ||
| fixed=False, | ||
| unit=diffusion_unit, | ||
| unit='m**2/s', | ||
| ) | ||
| super().__init__( | ||
| display_name=display_name, | ||
| unique_name=unique_name, | ||
| unit=unit, | ||
| scale=scale, | ||
| ) | ||
| self._hbar = DescriptorNumber.from_scipp('hbar', scipp_hbar) | ||
| self._angstrom = DescriptorNumber('angstrom', 1e-10, unit='m') | ||
| self._scale = scale | ||
| self._diffusion_coefficient = diffusion_coefficient | ||
|
|
||
| @property | ||
| def scale(self) -> Parameter: | ||
| """Get the scale parameter of the diffusion model. | ||
|
|
||
| Returns | ||
| ------- | ||
| Parameter | ||
| Scale parameter. | ||
| """ | ||
| return self._scale | ||
|
|
||
| @scale.setter | ||
| def scale(self, scale: Numeric) -> None: | ||
| """Set the scale parameter of the diffusion model.""" | ||
| if not isinstance(scale, (Numeric)): | ||
| raise TypeError('scale must be a number.') | ||
| self._scale.value = scale | ||
| # ------------------------------------------------------------------ | ||
| # Properties | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| @property | ||
| def diffusion_coefficient(self) -> Parameter: | ||
|
|
@@ -136,10 +101,14 @@ def diffusion_coefficient(self) -> Parameter: | |
| @diffusion_coefficient.setter | ||
| def diffusion_coefficient(self, diffusion_coefficient: Numeric) -> None: | ||
| """Set the diffusion coefficient parameter D.""" | ||
| if not isinstance(diffusion_coefficient, (Numeric)): | ||
| if not isinstance(diffusion_coefficient, Numeric): | ||
| raise TypeError('diffusion_coefficient must be a number.') | ||
| self._diffusion_coefficient.value = diffusion_coefficient | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # Other methods | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| def calculate_width(self, Q: Q_type) -> np.ndarray: | ||
| """Calculate the half-width at half-maximum (HWHM) for the | ||
| diffusion model. | ||
|
|
@@ -265,6 +234,10 @@ def create_component_collections( | |
|
|
||
| return component_collection_list | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # Private methods | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| def _write_width_dependency_expression(self, Q: float) -> str: | ||
| """Write the dependency expression for the width as a function | ||
| of Q to make dependent Parameters. | ||
|
|
@@ -316,6 +289,10 @@ def _write_area_dependency_map_expression(self) -> Dict[str, DescriptorNumber]: | |
| 'scale': self.scale, | ||
| } | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # dunder methods | ||
| # ------------------------------------------------------------------ | ||
|
|
||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same for diffusion_coefficient and all other repr I've made so far... I'll streamline them once I know what I want, which is after the Job class :) but it's a good point! |
||
| def __repr__(self): | ||
| """String representation of the BrownianTranslationalDiffusion | ||
| model. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,17 +1,14 @@ | ||
| # SPDX-FileCopyrightText: 2025-2026 EasyDynamics contributors <https://github.com/easyscience> | ||
| # SPDX-License-Identifier: BSD-3-Clause | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Any particular reason you deleted the license header?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Copy/paste from old code going wrong |
||
| import numpy as np | ||
| import scipp as sc | ||
| from easyscience.base_classes.model_base import ModelBase | ||
| from easyscience.variable import DescriptorNumber | ||
| from numpy.typing import ArrayLike | ||
| from easyscience.variable import Parameter | ||
| from scipp import UnitError | ||
|
|
||
| from easydynamics.utils.utils import Numeric | ||
|
|
||
| Q_type = np.ndarray | Numeric | list | ArrayLike | ||
|
|
||
|
|
||
| class DiffusionModelBase(ModelBase): | ||
| """Base class for constructing diffusion models.""" | ||
|
|
@@ -20,6 +17,7 @@ def __init__( | |
| self, | ||
| display_name='MyDiffusionModel', | ||
| unique_name: str | None = None, | ||
| scale: Numeric = 1.0, | ||
| unit: str | sc.Unit = 'meV', | ||
| ): | ||
| """Initialize a new DiffusionModel. | ||
|
|
@@ -31,6 +29,10 @@ def __init__( | |
| unit : str or sc.Unit, optional | ||
| Unit of the diffusion model. Defaults to "meV". | ||
| """ | ||
| if not isinstance(scale, Numeric): | ||
| raise TypeError('scale must be a number.') | ||
|
|
||
| scale = Parameter(name='scale', value=float(scale), fixed=False, min=0.0) | ||
|
|
||
| try: | ||
| test = DescriptorNumber(name='test', value=1, unit=unit) | ||
|
|
@@ -42,6 +44,11 @@ def __init__( | |
|
|
||
| super().__init__(display_name=display_name, unique_name=unique_name) | ||
| self._unit = unit | ||
| self._scale = scale | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # Properties | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| @property | ||
| def unit(self) -> str: | ||
|
|
@@ -62,6 +69,28 @@ def unit(self, unit_str: str) -> None: | |
| ) | ||
| ) # noqa: E501 | ||
|
|
||
| @property | ||
| def scale(self) -> Parameter: | ||
| """Get the scale parameter of the diffusion model. | ||
|
|
||
| Returns | ||
| ------- | ||
| Parameter | ||
| Scale parameter. | ||
| """ | ||
| return self._scale | ||
|
|
||
| @scale.setter | ||
| def scale(self, scale: Numeric) -> None: | ||
| """Set the scale parameter of the diffusion model.""" | ||
| if not isinstance(scale, Numeric): | ||
| raise TypeError('scale must be a number.') | ||
| self._scale.value = scale | ||
|
|
||
| # ------------------------------------------------------------------ | ||
| # dunder methods | ||
| # ------------------------------------------------------------------ | ||
|
|
||
| def __repr__(self): | ||
| """String representation of the Diffusion model.""" | ||
| return f'{self.__class__.__name__}(display_name={self.display_name}, unit={self.unit})' | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo here, scale is numeric