nmag-python-3 0.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. anisotropy/__init__.py +28 -0
  2. anisotropy/anisotropy.py +13 -0
  3. anisotropy/evaluation.py +70 -0
  4. anisotropy/model.py +200 -0
  5. anisotropy/predefined.py +202 -0
  6. anisotropy/py.typed +1 -0
  7. anisotropy/values.py +84 -0
  8. mag_material/__init__.py +3 -0
  9. mag_material/mag_material.py +231 -0
  10. mag_material/parameters.py +150 -0
  11. mag_material/py.typed +1 -0
  12. nmag/__init__.py +36 -0
  13. nmag/backends.py +493 -0
  14. nmag/checkpoint.py +327 -0
  15. nmag/config.py +174 -0
  16. nmag/demag/__init__.py +39 -0
  17. nmag/demag/bem_operator.py +149 -0
  18. nmag/demag/geometry.py +134 -0
  19. nmag/demag/lindholm.py +133 -0
  20. nmag/demag/lindholm_fast.py +463 -0
  21. nmag/demag/linear.py +489 -0
  22. nmag/dynamics/__init__.py +255 -0
  23. nmag/output.py +27 -0
  24. nmag/parallel.py +45 -0
  25. nmag/py.typed +1 -0
  26. nmag/resources.py +38 -0
  27. nmag/simulation/__init__.py +519 -0
  28. nmag/simulation/anisotropy/__init__.py +5 -0
  29. nmag/simulation/anisotropy/fields.py +56 -0
  30. nmag/simulation/anisotropy/materials.py +138 -0
  31. nmag/simulation/demag/__init__.py +1 -0
  32. nmag/simulation/demag/bem/__init__.py +11 -0
  33. nmag/simulation/demag/bem/diagnostics.py +73 -0
  34. nmag/simulation/demag/bem/dirichlet.py +85 -0
  35. nmag/simulation/demag/bem/hierarchical.py +74 -0
  36. nmag/simulation/demag/bem/operator.py +292 -0
  37. nmag/simulation/demag/fem/__init__.py +11 -0
  38. nmag/simulation/demag/fem/assembly.py +114 -0
  39. nmag/simulation/demag/fem/charges.py +38 -0
  40. nmag/simulation/demag/fem/geometry.py +261 -0
  41. nmag/simulation/demag/fields/__init__.py +11 -0
  42. nmag/simulation/demag/fields/auxiliary.py +186 -0
  43. nmag/simulation/demag/fields/probe.py +77 -0
  44. nmag/simulation/demag/fields/recovery.py +207 -0
  45. nmag/simulation/demag/solver.py +17 -0
  46. nmag/simulation/dynamics/__init__.py +92 -0
  47. nmag/simulation/dynamics/advance.py +199 -0
  48. nmag/simulation/dynamics/integrator.py +263 -0
  49. nmag/simulation/exchange/__init__.py +13 -0
  50. nmag/simulation/exchange/coefficients.py +185 -0
  51. nmag/simulation/exchange/fields.py +106 -0
  52. nmag/simulation/exchange/llg_rhs.py +218 -0
  53. nmag/simulation/fields/__init__.py +19 -0
  54. nmag/simulation/fields/arrays.py +111 -0
  55. nmag/simulation/fields/availability.py +188 -0
  56. nmag/simulation/fields/averages.py +293 -0
  57. nmag/simulation/fields/derived.py +164 -0
  58. nmag/simulation/fields/maxangle.py +163 -0
  59. nmag/simulation/fields/probes.py +106 -0
  60. nmag/simulation/implicit_dynamics.py +221 -0
  61. nmag/simulation/mesh/__init__.py +13 -0
  62. nmag/simulation/mesh/geometry.py +153 -0
  63. nmag/simulation/mesh/materials.py +299 -0
  64. nmag/simulation/mesh/probe.py +234 -0
  65. nmag/simulation/restart.py +103 -0
  66. nmag/simulation/support.py +224 -0
  67. nmag_python_3-0.0.2.dist-info/METADATA +157 -0
  68. nmag_python_3-0.0.2.dist-info/RECORD +147 -0
  69. nmag_python_3-0.0.2.dist-info/WHEEL +5 -0
  70. nmag_python_3-0.0.2.dist-info/licenses/LICENSE +339 -0
  71. nmag_python_3-0.0.2.dist-info/top_level.txt +8 -0
  72. nmesh/__init__.py +130 -0
  73. nmesh/backend.py +286 -0
  74. nmesh/geometry/__init__.py +52 -0
  75. nmesh/geometry/boolean_operations.py +157 -0
  76. nmesh/geometry/primitives.py +453 -0
  77. nmesh/geometry/transform.py +126 -0
  78. nmesh/io/__init__.py +50 -0
  79. nmesh/io/ascii.py +132 -0
  80. nmesh/io/legacy_nmesh_hdf5.py +318 -0
  81. nmesh/io/meshio_support.py +170 -0
  82. nmesh/mesh_generation.py +182 -0
  83. nmesh/mesh_io.py +227 -0
  84. nmesh/mesh_model.py +147 -0
  85. nmesh/mesh_utilities.py +79 -0
  86. nmesh/mesher/__init__.py +21 -0
  87. nmesh/mesher/driver.py +146 -0
  88. nmesh/mesher/meshing_defaults.py +252 -0
  89. nmesh/mesher/meshing_parameters.py +185 -0
  90. nmesh/mesher/parity.py +21 -0
  91. nmesh/mesher/parity_canonical.py +142 -0
  92. nmesh/mesher/parity_comparison.py +191 -0
  93. nmesh/mesher/parity_metrics.py +114 -0
  94. nmesh/mesher/periodic.py +97 -0
  95. nmesh/mesher/relaxation/__init__.py +14 -0
  96. nmesh/mesher/relaxation/_constants.py +20 -0
  97. nmesh/mesher/relaxation/_types.py +15 -0
  98. nmesh/mesher/relaxation/density.py +170 -0
  99. nmesh/mesher/relaxation/engine/__init__.py +18 -0
  100. nmesh/mesher/relaxation/engine/state.py +155 -0
  101. nmesh/mesher/relaxation/engine/steps.py +248 -0
  102. nmesh/mesher/relaxation/engine/topology.py +230 -0
  103. nmesh/mesher/relaxation/forces/__init__.py +96 -0
  104. nmesh/mesher/relaxation/forces/jit.py +102 -0
  105. nmesh/mesher/relaxation/forces/neighbors.py +186 -0
  106. nmesh/mesher/relaxation/forces/simplex.py +302 -0
  107. nmesh/mesher/relaxation/forces/summary.py +207 -0
  108. nmesh/mesher/relaxation/forces/types.py +92 -0
  109. nmesh/mesher/relaxation/geometry/__init__.py +6 -0
  110. nmesh/mesher/relaxation/geometry/builder.py +154 -0
  111. nmesh/mesher/relaxation/geometry/model.py +194 -0
  112. nmesh/mesher/relaxation/seeding/__init__.py +74 -0
  113. nmesh/mesher/relaxation/seeding/periodic.py +88 -0
  114. nmesh/mesher/relaxation/seeding/points.py +88 -0
  115. nmesh/mesher/relaxation/seeding/sampling.py +142 -0
  116. nmesh/mesher/relaxation/topology/__init__.py +297 -0
  117. nmesh/mesher/relaxation/topology/finalize.py +78 -0
  118. nmesh/mesher/relaxation/topology/recovery.py +310 -0
  119. nmesh/mesher/sectioned_config.py +70 -0
  120. nmesh/nmesh.py +99 -0
  121. nmesh/py.typed +1 -0
  122. nmesh/utils/__init__.py +33 -0
  123. nmesh/utils/array_list_utils.py +128 -0
  124. nmesh/utils/constants.py +22 -0
  125. nmesh/utils/timing_memory_utils.py +51 -0
  126. nmesh/utils/types.py +13 -0
  127. si/constants.py +49 -0
  128. si/physical.py +722 -0
  129. si/py.typed +1 -0
  130. simulation/__init__.py +1 -0
  131. simulation/clock.py +237 -0
  132. simulation/data_writer.py +273 -0
  133. simulation/data_writer_collection.py +267 -0
  134. simulation/hysteresis.py +74 -0
  135. simulation/hysteresis_runner.py +286 -0
  136. simulation/hysteresis_schedule.py +180 -0
  137. simulation/inference/__init__.py +3 -0
  138. simulation/inference/inference.py +95 -0
  139. simulation/py.typed +1 -0
  140. simulation/quantity.py +88 -0
  141. simulation/simulation_core.py +458 -0
  142. throttler/__init__.py +3 -0
  143. throttler/py.typed +1 -0
  144. throttler/throttler.py +55 -0
  145. when/__init__.py +3 -0
  146. when/py.typed +1 -0
  147. when/when.py +416 -0
@@ -0,0 +1,231 @@
1
+ """
2
+ Definition of the MagMaterial class, which allows to define a magnetic
3
+ material and all its parameters (saturation magnetisation, exchange coupling,
4
+ etc.)
5
+ """
6
+
7
+ import logging
8
+ from typing import Any, Protocol, cast
9
+
10
+ from anisotropy import PredefinedAnisotropy
11
+ from si.physical import SI
12
+
13
+ from .parameters import (
14
+ AnisotropyFunction,
15
+ MaterialScalar,
16
+ resolve_material_parameters,
17
+ )
18
+
19
+ log = logging.getLogger("nmag")
20
+
21
+
22
+ class _SIConstants(Protocol):
23
+ boltzmann_constant: SI
24
+ gamma0: SI
25
+ mu0: SI
26
+ bohr_magneton: SI
27
+ positron_charge: SI
28
+
29
+
30
+ _constants_cache: _SIConstants | None = None
31
+
32
+
33
+ def _si_constants() -> _SIConstants:
34
+ global _constants_cache
35
+ if _constants_cache is None:
36
+ from si import constants
37
+
38
+ _constants_cache = cast(_SIConstants, constants)
39
+ return _constants_cache
40
+
41
+
42
+ class MagMaterial:
43
+ """Define the physical parameters assigned to a magnetic mesh region.
44
+
45
+ Args:
46
+ name: Unique material name used in field and output labels.
47
+ Ms: Saturation magnetization, compatible with A/m.
48
+ llg_damping: Dimensionless Gilbert damping coefficient.
49
+ llg_gamma_G: Gyromagnetic ratio used by the LLG equation.
50
+ llg_normalisationfactor: Coefficient for numerical norm correction.
51
+ llg_xi: Dimensionless nonadiabatic Zhang-Li coefficient.
52
+ llg_polarisation: Dimensionless spin-current polarization.
53
+ do_precession: Include the precessional LLG term when true.
54
+ exchange_coupling: Exchange constant, compatible with J/m.
55
+ anisotropy: Predefined anisotropy or custom energy callable.
56
+ anisotropy_order: Polynomial order required for a custom callable.
57
+ properties: Compatibility property labels. Most users should omit this.
58
+ scale_volume_charges: Multiplier for interior demagnetization volume
59
+ charge. Boundary surface charges remain physical and unscaled.
60
+
61
+ Raises:
62
+ TypeError: If a parameter has an unsupported type or dimensions.
63
+ ValueError: If a value is non-finite, physically invalid, or a custom
64
+ anisotropy omits its order.
65
+ """
66
+
67
+ def __init__(
68
+ self,
69
+ name: str,
70
+ Ms: SI | None = None,
71
+ llg_damping: MaterialScalar = 0.5,
72
+ llg_gamma_G: SI | None = None,
73
+ llg_normalisationfactor: SI | None = None,
74
+ llg_xi: MaterialScalar = 0.0,
75
+ llg_polarisation: MaterialScalar = 0.0,
76
+ do_precession: bool = True,
77
+ exchange_coupling: SI | None = None,
78
+ anisotropy: PredefinedAnisotropy | AnisotropyFunction | None = None,
79
+ anisotropy_order: int | None = None,
80
+ properties: list[str] | None = None,
81
+ scale_volume_charges: float = 1.0,
82
+ ) -> None:
83
+ """Initialize a material after validating units and physical values."""
84
+ parameters = resolve_material_parameters(
85
+ name,
86
+ ms=Ms,
87
+ damping=llg_damping,
88
+ gamma=llg_gamma_G,
89
+ normalisation=llg_normalisationfactor,
90
+ xi=llg_xi,
91
+ polarisation=llg_polarisation,
92
+ do_precession=do_precession,
93
+ exchange=exchange_coupling,
94
+ anisotropy=anisotropy,
95
+ anisotropy_order=anisotropy_order,
96
+ properties=properties,
97
+ scale_volume_charges=scale_volume_charges,
98
+ )
99
+
100
+ self.name = name
101
+ self.Ms = parameters.ms
102
+ self.llg_gamma_G = parameters.gamma
103
+ self.llg_damping = parameters.damping
104
+ self.llg_normalisationfactor = parameters.normalisation
105
+ self.llg_xi = parameters.xi
106
+ self.llg_polarisation = parameters.polarisation
107
+ self.do_precession = parameters.do_precession
108
+ self.properties = parameters.properties
109
+ self.exchange_coupling = parameters.exchange
110
+ self.scale_volume_charges = parameters.scale_volume_charges
111
+ self.anisotropy = parameters.anisotropy
112
+ self.anisotropy_order = parameters.anisotropy_order
113
+
114
+ # SU units units for backwards compatibility, they used to be stripped
115
+ # of units, but now we can do calculations with the units attached
116
+ self.su_Ms = self.Ms
117
+ self.su_llg_gamma_G = self.llg_gamma_G
118
+ self.su_llg_damping = self.llg_damping
119
+ self.su_llg_normalisationfactor = self.llg_normalisationfactor
120
+ self.su_exchange_coupling = self.exchange_coupling
121
+
122
+ gilbert_to_ll = 1.0 / (1.0 + self.su_llg_damping**2)
123
+ self.su_llg_coeff1 = -self.su_llg_gamma_G * gilbert_to_ll
124
+ self.su_llg_coeff2 = self.su_llg_coeff1 * self.su_llg_damping
125
+
126
+ if not self.do_precession:
127
+ log.info(
128
+ "Setting su_llg_coeff1 to zero; thus no precession for material '%s'", self.name
129
+ )
130
+ self.su_llg_coeff1 = 0.0
131
+
132
+ self.su_anisotropy = self.anisotropy
133
+ self._derived_su_constants: dict[str, MaterialScalar] | None = None
134
+
135
+ self.extended_print = False
136
+ if log.isEnabledFor(logging.INFO):
137
+ log.info("Created new Material:\n %s", self)
138
+
139
+ def _derived_su_values(self) -> dict[str, MaterialScalar]:
140
+ if self._derived_su_constants is None:
141
+ constants = _si_constants()
142
+ thermal_factor = (2.0 * constants.boltzmann_constant * self.llg_damping) / (
143
+ -constants.gamma0 * constants.mu0 * self.Ms
144
+ )
145
+ gilbert_to_ll = 1.0 / (1.0 + self.su_llg_damping**2)
146
+ polarisation = (
147
+ self.llg_polarisation.in_units_of(SI(1))
148
+ if isinstance(self.llg_polarisation, SI)
149
+ else float(self.llg_polarisation)
150
+ )
151
+ xi = self.llg_xi.in_units_of(SI(1)) if isinstance(self.llg_xi, SI) else float(self.llg_xi)
152
+ bohr_magneton = float(
153
+ cast(Any, 1.0 * constants.bohr_magneton).to("J/T").magnitude
154
+ )
155
+ charge = float(cast(Any, 1.0 * constants.positron_charge).to("C").magnitude)
156
+ ms = self.Ms.in_units_of(SI("A/m"))
157
+ su_f = (
158
+ SI(0.0, "m^3/A/s")
159
+ if ms == 0.0
160
+ else SI(
161
+ -gilbert_to_ll
162
+ * polarisation
163
+ * bohr_magneton
164
+ / (charge * ms * (1.0 + xi * xi)),
165
+ "m^3/A/s",
166
+ )
167
+ )
168
+ self._derived_su_constants = {
169
+ "thermal_factor": thermal_factor,
170
+ "su_thermal_factor": thermal_factor,
171
+ "su_llg_stt_prefactor": 0.0 if su_f == 0.0 else 1.0,
172
+ "su_llg_stt_nadiab": su_f * (xi - self.su_llg_damping),
173
+ "su_llg_stt_adiab": su_f * (1.0 + self.su_llg_damping * xi),
174
+ "su_exch_prefactor": (
175
+ 2.0 * self.su_exchange_coupling / (constants.mu0 * self.su_Ms)
176
+ ),
177
+ }
178
+ return self._derived_su_constants
179
+
180
+ @property
181
+ def thermal_factor(self) -> MaterialScalar:
182
+ return self._derived_su_values()["thermal_factor"]
183
+
184
+ @property
185
+ def su_thermal_factor(self) -> MaterialScalar:
186
+ return self._derived_su_values()["su_thermal_factor"]
187
+
188
+ @property
189
+ def su_llg_stt_prefactor(self) -> MaterialScalar:
190
+ return self._derived_su_values()["su_llg_stt_prefactor"]
191
+
192
+ @property
193
+ def su_llg_stt_nadiab(self) -> MaterialScalar:
194
+ return self._derived_su_values()["su_llg_stt_nadiab"]
195
+
196
+ @property
197
+ def su_llg_stt_adiab(self) -> MaterialScalar:
198
+ return self._derived_su_values()["su_llg_stt_adiab"]
199
+
200
+ @property
201
+ def su_exch_prefactor(self) -> MaterialScalar:
202
+ return self._derived_su_values()["su_exch_prefactor"]
203
+
204
+ def __str__(self) -> str:
205
+ repr_str = f"Material '{self.name}'\n"
206
+
207
+ attrs = list(filter(lambda a: a[0] != "_", dir(self)))
208
+
209
+ if not self.extended_print:
210
+ attrs = [
211
+ "name",
212
+ "Ms",
213
+ "exchange_coupling",
214
+ "anisotropy",
215
+ "anisotropy_order",
216
+ "llg_gamma_G",
217
+ "llg_damping",
218
+ "llg_normalisationfactor",
219
+ "do_precession",
220
+ "llg_polarisation",
221
+ "llg_xi",
222
+ "thermal_factor",
223
+ "extended_print",
224
+ ]
225
+
226
+ for attr in attrs:
227
+ if hasattr(self, attr):
228
+ value_str = str(getattr(self, attr))
229
+ repr_str += f" {attr:>25} = {value_str}\n"
230
+
231
+ return repr_str
@@ -0,0 +1,150 @@
1
+ """Normalization and validation for :class:`mag_material.MagMaterial` inputs."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import math
6
+ from dataclasses import dataclass
7
+ from functools import lru_cache
8
+ from typing import cast
9
+
10
+ from anisotropy import EnergyFunction, PredefinedAnisotropy
11
+ from si.physical import SI
12
+
13
+ MaterialScalar = SI | float
14
+ AnisotropyFunction = EnergyFunction
15
+
16
+
17
+ @dataclass(slots=True)
18
+ class MaterialParameters:
19
+ """Fully resolved constructor values for a magnetic material."""
20
+
21
+ ms: SI
22
+ damping: MaterialScalar
23
+ gamma: SI
24
+ normalisation: SI
25
+ xi: MaterialScalar
26
+ polarisation: MaterialScalar
27
+ do_precession: bool
28
+ exchange: SI
29
+ anisotropy: PredefinedAnisotropy | AnisotropyFunction | None
30
+ anisotropy_order: int | None
31
+ properties: list[str]
32
+ scale_volume_charges: float
33
+
34
+
35
+ @lru_cache(maxsize=1)
36
+ def _expected_parameter_units() -> tuple[tuple[str, SI], ...]:
37
+ one = SI(1)
38
+ return (
39
+ ("Ms", SI(1, "A/m")),
40
+ ("llg_gamma_G", SI(1, "m/A/s")),
41
+ ("llg_damping", one),
42
+ ("llg_normalisationfactor", SI(1, "1/s")),
43
+ ("llg_xi", one),
44
+ ("llg_polarisation", one),
45
+ ("exchange_coupling", SI(1, "J/m")),
46
+ )
47
+
48
+
49
+ def _value_by_public_name(parameters: MaterialParameters, name: str) -> MaterialScalar:
50
+ values: dict[str, MaterialScalar] = {
51
+ "Ms": parameters.ms,
52
+ "llg_gamma_G": parameters.gamma,
53
+ "llg_damping": parameters.damping,
54
+ "llg_normalisationfactor": parameters.normalisation,
55
+ "llg_xi": parameters.xi,
56
+ "llg_polarisation": parameters.polarisation,
57
+ "exchange_coupling": parameters.exchange,
58
+ }
59
+ return values[name]
60
+
61
+
62
+ def _validate_units(name: str, parameters: MaterialParameters) -> None:
63
+ for attribute, expected_unit in _expected_parameter_units():
64
+ value = _value_by_public_name(parameters, attribute)
65
+ value_to_check = value._quantity if isinstance(value, SI) else value
66
+ if not expected_unit._quantity.is_compatible_with(value_to_check):
67
+ raise TypeError(
68
+ f"The argument '{attribute}' for material '{name}' requires units compatible "
69
+ f"with {expected_unit.dens_str()}, but received a value of '{value}'."
70
+ )
71
+
72
+
73
+ def _resolve_anisotropy(
74
+ anisotropy: PredefinedAnisotropy | AnisotropyFunction | None,
75
+ anisotropy_order: int | None,
76
+ ) -> tuple[PredefinedAnisotropy | AnisotropyFunction | None, int | None]:
77
+ if isinstance(anisotropy, PredefinedAnisotropy):
78
+ if anisotropy_order is not None:
79
+ raise ValueError(
80
+ "Cannot specify custom 'anisotropy_order' when using a predefined anisotropy."
81
+ )
82
+ if not anisotropy.has_function() or anisotropy.order is None:
83
+ raise ValueError("A material anisotropy must provide an energy function and order.")
84
+ return anisotropy, anisotropy.order
85
+ if anisotropy is None:
86
+ if anisotropy_order is not None:
87
+ raise ValueError("anisotropy_order requires an anisotropy energy function.")
88
+ return None, None
89
+ if not callable(anisotropy):
90
+ raise TypeError("anisotropy must be a PredefinedAnisotropy, callable, or None.")
91
+ custom_order = cast(object, anisotropy_order)
92
+ if (
93
+ custom_order is None
94
+ or type(custom_order) is bool
95
+ or not isinstance(custom_order, int)
96
+ or custom_order <= 0
97
+ ):
98
+ raise ValueError(
99
+ "You must specify 'anisotropy_order' as a positive integer when using a custom "
100
+ "anisotropy function."
101
+ )
102
+ return anisotropy, anisotropy_order
103
+
104
+
105
+ def resolve_material_parameters(
106
+ name: str,
107
+ *,
108
+ ms: SI | None,
109
+ damping: MaterialScalar,
110
+ gamma: SI | None,
111
+ normalisation: SI | None,
112
+ xi: MaterialScalar,
113
+ polarisation: MaterialScalar,
114
+ do_precession: bool,
115
+ exchange: SI | None,
116
+ anisotropy: PredefinedAnisotropy | AnisotropyFunction | None,
117
+ anisotropy_order: int | None,
118
+ properties: list[str] | None,
119
+ scale_volume_charges: float,
120
+ ) -> MaterialParameters:
121
+ """Apply legacy defaults and reject invalid material constructor values."""
122
+ try:
123
+ resolved_volume_charge_scale = float(scale_volume_charges)
124
+ except (TypeError, ValueError) as error:
125
+ raise TypeError("scale_volume_charges must be a finite real number.") from error
126
+ if not math.isfinite(resolved_volume_charge_scale):
127
+ raise ValueError("scale_volume_charges must be finite.")
128
+
129
+ resolved_anisotropy, resolved_order = _resolve_anisotropy(anisotropy, anisotropy_order)
130
+ parameters = MaterialParameters(
131
+ ms=SI(0.86e6, "A/m") if ms is None else ms,
132
+ damping=damping,
133
+ gamma=SI(2.210173e5, "m/A/s") if gamma is None else gamma,
134
+ normalisation=SI(0.1e12, "1/s") if normalisation is None else normalisation,
135
+ xi=xi,
136
+ polarisation=polarisation,
137
+ do_precession=do_precession,
138
+ exchange=SI(1.3e-11, "J/m") if exchange is None else exchange,
139
+ anisotropy=resolved_anisotropy,
140
+ anisotropy_order=resolved_order,
141
+ properties=["magnetic", "material"] if properties is None else properties,
142
+ scale_volume_charges=resolved_volume_charge_scale,
143
+ )
144
+ _validate_units(name, parameters)
145
+ if parameters.exchange < 0.0:
146
+ raise ValueError(
147
+ "The exchange coupling constant must be positive. For "
148
+ f"material '{name}', you specified: {parameters.exchange}."
149
+ )
150
+ return parameters
mag_material/py.typed ADDED
@@ -0,0 +1 @@
1
+ # Marker for PEP 561 inline type information.
nmag/__init__.py ADDED
@@ -0,0 +1,36 @@
1
+ """Public Python 3 entrypoint for the nmag rewrite."""
2
+
3
+ from anisotropy import (
4
+ PredefinedAnisotropy,
5
+ cubic_anisotropy,
6
+ uniaxial_anisotropy,
7
+ want_anisotropy,
8
+ )
9
+ from mag_material import MagMaterial
10
+ from si.physical import SI, Physical
11
+
12
+ from .config import ACCELERATOR_ENV, HierarchicalBemConfig, NmagConfig, RustKernel
13
+ from .demag.bem_operator import BemOperatorStats
14
+ from .dynamics import IntegratorConfig, IntegratorStats
15
+ from .parallel import ParallelRuntimeInfo, parallel_runtime_info
16
+ from .simulation import Simulation
17
+
18
+ __all__ = [
19
+ "MagMaterial",
20
+ "NmagConfig",
21
+ "HierarchicalBemConfig",
22
+ "BemOperatorStats",
23
+ "IntegratorConfig",
24
+ "IntegratorStats",
25
+ "ParallelRuntimeInfo",
26
+ "Physical",
27
+ "PredefinedAnisotropy",
28
+ "SI",
29
+ "Simulation",
30
+ "RustKernel",
31
+ "ACCELERATOR_ENV",
32
+ "cubic_anisotropy",
33
+ "parallel_runtime_info",
34
+ "uniaxial_anisotropy",
35
+ "want_anisotropy",
36
+ ]