From 7bd250ecc2166f2a9244f9b7f03f5941cad27829 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Thu, 4 May 2023 18:46:32 +0200 Subject: [PATCH 1/8] Support scalar and vector values for Zhang Li u --- micromagneticmodel/dynamics/zhangli.py | 30 ++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 8f5ecf2..e392bf0 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -1,15 +1,35 @@ import collections +import numbers import discretisedfield as df +import numpy as np import ubermagutil as uu import ubermagutil.typesystem as ts from .dynamicsterm import DynamicsTerm +class ScalarVector3(ts.Descriptor): + # custom type for Zhand-Li current density u + def __set__(self, instance, value): + if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): + raise TypeError("Cannot set {self.name} with {type(value)}.") + if isinstance(value, numbers.Real): + pass + elif isinstance(value, df.Field): + if value.nvdim not in (1, 3): + raise ValueError("Cannot set {self.name} with {value.nvdim=}.") + else: + if not all(isinstance(elem, numbers.Real) for elem in value): + raise ValueError( + "Can only set {self.name} with elements of type numbers.Real." + ) + super().__set__(instance, value) + + @uu.inherit_docs @ts.typesystem( - u=ts.Parameter(descriptor=ts.Scalar(), otherwise=df.Field), + u=ScalarVector3(), beta=ts.Scalar(), func=ts.Typed(expected_type=collections.abc.Callable), dt=ts.Scalar(positive=True), @@ -42,10 +62,12 @@ class ZhangLi(DynamicsTerm): A single scalar value can be passed. - u : number.Real, discretisedfield.Field + u : number.Real, array-like, discretisedfield.Field - `numbers.Real` can be passed, or alternatively - ``discretisedfield.Field`` can be passed. + Velocity of the spin current in m/s. If a scalar value or ``Field`` with + ``nvdim==1`` is passed, the current is assumed to flow in x direction. A vector + or a ``Field`` with ``nvdim==3`` can be used to specify arbitrary current + direction. func : callable, optional From 539ae907e51cabc1f2267353517a9e6ae4a586b8 Mon Sep 17 00:00:00 2001 From: Martin Lang <67915889+lang-m@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:01:56 +0100 Subject: [PATCH 2/8] Apply suggestions from code review --- micromagneticmodel/dynamics/zhangli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index e392bf0..13f7406 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -9,8 +9,8 @@ from .dynamicsterm import DynamicsTerm -class ScalarVector3(ts.Descriptor): - # custom type for Zhand-Li current density u +class Scalar_Vector3(ts.Descriptor): + """custom type for Zhand-Li current density u."" def __set__(self, instance, value): if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): raise TypeError("Cannot set {self.name} with {type(value)}.") @@ -29,7 +29,7 @@ def __set__(self, instance, value): @uu.inherit_docs @ts.typesystem( - u=ScalarVector3(), + u=Scalar_Vector3(), beta=ts.Scalar(), func=ts.Typed(expected_type=collections.abc.Callable), dt=ts.Scalar(positive=True), @@ -64,7 +64,7 @@ class ZhangLi(DynamicsTerm): u : number.Real, array-like, discretisedfield.Field - Velocity of the spin current in m/s. If a scalar value or ``Field`` with + Spin-drift velocity in m/s. If a scalar value or ``Field`` with ``nvdim==1`` is passed, the current is assumed to flow in x direction. A vector or a ``Field`` with ``nvdim==3`` can be used to specify arbitrary current direction. From 65bc9439411659185e56197a8e62de36e1b00915 Mon Sep 17 00:00:00 2001 From: Martin Lang <67915889+lang-m@users.noreply.github.com> Date: Fri, 1 Mar 2024 15:02:31 +0100 Subject: [PATCH 3/8] Apply suggestions from code review --- micromagneticmodel/dynamics/zhangli.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 13f7406..568d997 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -10,7 +10,7 @@ class Scalar_Vector3(ts.Descriptor): - """custom type for Zhand-Li current density u."" + """custom type for Zhand-Li current density u.""" def __set__(self, instance, value): if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): raise TypeError("Cannot set {self.name} with {type(value)}.") From acf901b48f435d04c64655b9ecc6506e01817134 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 1 Mar 2024 14:02:39 +0000 Subject: [PATCH 4/8] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- micromagneticmodel/dynamics/zhangli.py | 1 + 1 file changed, 1 insertion(+) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 568d997..3c946aa 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -11,6 +11,7 @@ class Scalar_Vector3(ts.Descriptor): """custom type for Zhand-Li current density u.""" + def __set__(self, instance, value): if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): raise TypeError("Cannot set {self.name} with {type(value)}.") From dd34535eda3ec48cc7535b0875d96f669e529230 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Thu, 9 May 2024 09:37:16 +0200 Subject: [PATCH 5/8] Fix strings --- micromagneticmodel/dynamics/zhangli.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 3c946aa..821516b 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -14,16 +14,16 @@ class Scalar_Vector3(ts.Descriptor): def __set__(self, instance, value): if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): - raise TypeError("Cannot set {self.name} with {type(value)}.") + raise TypeError(f"Cannot set {self.name} with {type(value)}.") if isinstance(value, numbers.Real): pass elif isinstance(value, df.Field): if value.nvdim not in (1, 3): - raise ValueError("Cannot set {self.name} with {value.nvdim=}.") + raise ValueError(f"Cannot set {self.name} with {value.nvdim=}.") else: if not all(isinstance(elem, numbers.Real) for elem in value): raise ValueError( - "Can only set {self.name} with elements of type numbers.Real." + f"Can only set {self.name} with elements of type numbers.Real." ) super().__set__(instance, value) From 353e615767204640c6ca0ed5a00c7e53f54eadcb Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Sun, 9 Jun 2024 15:13:28 +0200 Subject: [PATCH 6/8] Additional test cases for Zhang Li u --- micromagneticmodel/tests/test_zhangli.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/micromagneticmodel/tests/test_zhangli.py b/micromagneticmodel/tests/test_zhangli.py index a65aa7a..e993b5a 100644 --- a/micromagneticmodel/tests/test_zhangli.py +++ b/micromagneticmodel/tests/test_zhangli.py @@ -14,7 +14,9 @@ def setup_method(self): (-1.0, 2.0), (0, 5e-11), (19, -1e-12), + ((1, -2, 0), 1), ({"r1": 1, "r2": 2}, 0.5), + ({"r1": (1, 0, 0), "r2": (0, 0, 2)}, 0.5), ] self.invalid_args = [ ((1, -2), 1), @@ -22,6 +24,7 @@ def setup_method(self): ((0, 0, 0, 9), 5e-11), (11, -1e-12 + 2j), (1, {"r1 2": 1, "r2": 2}), + ({"r1": 1, "r2": (0, 0, 2)}, 0.5), ] def test_init_valid_args(self): From d86bae0e04874f2d54cfbbf9e775ce42e3257299 Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Sun, 9 Jun 2024 15:14:59 +0200 Subject: [PATCH 7/8] Allow dict for defining Zhang Li u inside subregions --- micromagneticmodel/dynamics/zhangli.py | 30 ++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 821516b..3182e6a 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -13,13 +13,30 @@ class Scalar_Vector3(ts.Descriptor): """custom type for Zhand-Li current density u.""" def __set__(self, instance, value): - if not isinstance(value, (numbers.Real, tuple, list, np.ndarray, df.Field)): + if not isinstance( + value, (numbers.Real, tuple, list, np.ndarray, dict, df.Field) + ): raise TypeError(f"Cannot set {self.name} with {type(value)}.") if isinstance(value, numbers.Real): pass elif isinstance(value, df.Field): if value.nvdim not in (1, 3): raise ValueError(f"Cannot set {self.name} with {value.nvdim=}.") + elif isinstance(value, dict): + if all(isinstance(elem, numbers.Real) for elem in value.values()): + pass + elif any( + not isinstance(elem, (tuple, list, np.ndarray)) + or len(elem) != 3 + or not all(isinstance(item, numbers.Real) for item in elem) + for elem in value.values() + ): + raise ValueError( + f"Can only set {self.name} with a 'dict' containing either only" + "scalar values or only vector values." + ) + elif len(value) != 3: + raise ValueError(f"Can only set {self.name} with a vector with 3 elements.") else: if not all(isinstance(elem, numbers.Real) for elem in value): raise ValueError( @@ -63,12 +80,13 @@ class ZhangLi(DynamicsTerm): A single scalar value can be passed. - u : number.Real, array-like, discretisedfield.Field + u : number.Real, array-like, dict, discretisedfield.Field - Spin-drift velocity in m/s. If a scalar value or ``Field`` with - ``nvdim==1`` is passed, the current is assumed to flow in x direction. A vector - or a ``Field`` with ``nvdim==3`` can be used to specify arbitrary current - direction. + Spin-drift velocity in m/s. If a scalar value or ``Field`` with ``nvdim==1`` is + passed, the current is assumed to flow in x direction. A vector (array_like of + length 3) or a ``Field`` with ``nvdim==3`` can be used to specify arbitrary + current direction. When using a ``dict`` either all elements must be scalar + (current in x direction) or a vector must be used for each key. func : callable, optional From 48857368331aa3279187a1ce8952c3764265f0ef Mon Sep 17 00:00:00 2001 From: Martin Lang Date: Sun, 9 Jun 2024 16:29:11 +0200 Subject: [PATCH 8/8] Update doctest for ZhangLi: vector value for u is allowed --- micromagneticmodel/dynamics/zhangli.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/micromagneticmodel/dynamics/zhangli.py b/micromagneticmodel/dynamics/zhangli.py index 3182e6a..7442cc1 100644 --- a/micromagneticmodel/dynamics/zhangli.py +++ b/micromagneticmodel/dynamics/zhangli.py @@ -134,13 +134,9 @@ class ZhangLi(DynamicsTerm): ... return np.sin(omega * t) >>> zhangli = mm.ZhangLi(beta=0.01, u=5e6, func=sin_wave, dt=1e-13) - 4. An attempt to define the Zhang-Li dynamics term using a wrong value - (here using a vector ``u`` where a scalar value is required). + 4. Defining the Zhang-Li dynamics term using vector. - >>> zhangli = mm.ZhangLi(beta=-1, u=(0, 0, 1)) # vector value - Traceback (most recent call last): - ... - TypeError: ... + >>> zhangli = mm.ZhangLi(beta=0.1, u=(0, 0, 1e12)) """