diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..fcd0be2 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,19 @@ +*.jpg +*.png +deprecated/ +build/ +scratch/ +*.egg-info/ +__pycache__/ +*.pyc +*.pyo +*.pyd +*.so +.eggs/ +.ipynb_checkpoints/ +.vscode/ +.idea/ +assets/ +articles/ +examples/ +docs/ diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..fb6fd83 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,2 @@ +include cmtj/__init__.pyi +include cmtj/py.typed diff --git a/README.md b/README.md index e3d4b29..8555abb 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ python3 -m pip install cmtj 3. Straight from source: ```bash -python3 -m pip install https://github.com/LemurPwned/cmtj.git +python3 -m pip install git+https://github.com/LemurPwned/cmtj.git ``` 4. Clone the repository: @@ -84,7 +84,7 @@ The package requires (if `utils` subpackage is used): ## Documentation and examples -Documentation: [https://lemurpwned.github.io/cmtj](https://lemurpwned.github.io/cmtj) +Documentation: [https://lemurpwned.github.io/cmtj](https://lemurpwned.github.io/cmtj). There are many examples available, check out the [examples section in the docs](https://lemurpwned.github.io/cmtj/experimental-methods/introduction/) ## Extensions diff --git a/cmtj/__init__.pyi b/cmtj/__init__.pyi index 640c347..66f5e1f 100644 --- a/cmtj/__init__.pyi +++ b/cmtj/__init__.pyi @@ -216,20 +216,17 @@ class Junction: :param SMR_Y: Spin magnetoresistance transverse :param AHE: Anomalous Hall effect resistance offset (transverse only) """ + ... @overload def __init__(*args, **kwargs) -> Any: ... def clearLog(self) -> Dict[str, Any]: - """ - Reset current simulation state` - """ + """Reset current simulation state.""" ... def getLayerMagnetisation(self, layer_id: str) -> CVector: ... def getLog(self) -> Dict[str, List[float]]: - """ - Retrieve the simulation log [data]. - """ + """Retrieve the simulation log [data].""" ... def getMagnetoresistance(self) -> List[float]: ... @@ -329,7 +326,7 @@ class Layer: demagTensor: List[CVector], temperature: float = ..., damping: float = ..., - ) -> None: + ) -> Layer: """ The basic structure is a magnetic layer. Its parameters are defined by the constructor and may be altered @@ -342,7 +339,6 @@ class Layer: :param Ms: magnetisation saturation. Unit: Tesla [T]. :param thickness: thickness of the layer. Unit: meter [m]. :param cellSurface: surface of the layer, for volume calculation. Unit: meter^2 [m^2]. - :param dipoleTensor: dipole tensor of the layer. :param damping: often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless """ ... @@ -359,7 +355,7 @@ class Layer: damping: float = 0.11, fieldLikeTorque: float = 0, dampingLikeTorque: float = 0, - ) -> "Layer": + ) -> Layer: """ Create SOT layer -- including damping and field-like torques that are calculated based on the effective Spin Hall angles. @@ -369,7 +365,6 @@ class Layer: :param Ms: magnetisation saturation. Unit: Tesla [T]. :param thickness: thickness of the layer. Unit: meter [m]. :param cellSurface: surface of the layer, for volume calculation. Unit: meter^2 [m^2]. - :param dipoleTensor: dipole tensor of the layer. :param temperature: resting temperature of the layer. Unit: Kelvin [K]. :param damping: often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless. """ @@ -388,7 +383,7 @@ class Layer: SlonczewskiSpacerLayerParameter: float = 1.0, beta: float = 0.0, spinPolarisation: float = 0.0, - ) -> "Layer": + ) -> Layer: """ Create STT layer -- with the standard Slomczewski formulation. :param id: identifiable name for a layer -- e.g. "bottom" or "free". @@ -397,7 +392,6 @@ class Layer: :param Ms: magnetisation saturation. Unit: Tesla [T]. :param thickness: thickness of the layer. Unit: meter [m]. :param cellSurface: surface of the layer, for volume calculation. Unit: meter^2 [m^2]. - :param dipoleTensor: dipole tensor of the layer. :param damping: often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless. :param SlonczewskiSpacerLayerParameter: Slomczewski parameter. Often marked as lambda. :param beta: beta parameter that scales FL/DL ratio. @@ -469,7 +463,6 @@ class ScalarDriver: """ Constant driver produces a constant signal of a fixed amplitude. :param constantValue: constant value of the driver (constant offset/amplitude) - """ ... @@ -497,7 +490,6 @@ class ScalarDriver: :param amplitude: amplitude of the sine wave :param frequency: frequency of the sine :param phase: phase of the sine in radians. - """ ... diff --git a/cmtj/llgb/__init__.pyi b/cmtj/llgb/__init__.pyi new file mode 100644 index 0000000..e06aea7 --- /dev/null +++ b/cmtj/llgb/__init__.pyi @@ -0,0 +1,51 @@ +from typing import Dict, List, Tuple + +import cmtj + +class LLGBJunction: + def __init__(self, layers: List[LLGBLayer]) -> None: ... + def clearLog(self) -> None: ... + def getLog(self) -> Dict[str, List[float]]: ... + def runSimulation( + self, + totalTime: float, + timeStep: float = ..., + writeFrequency: float = ..., + log: bool = ..., + solverMode: cmtj.SolverMode = ..., + ) -> None: ... + def saveLogs(self, arg0: str) -> None: ... + def setLayerExternalFieldDriver( + self, arg0: str, arg1: cmtj.AxialDriver + ) -> None: ... + def setLayerTemperatureDriver(self, arg0: str, arg1: cmtj.ScalarDriver) -> None: ... + +class LLGBLayer: + def __init__( + self, + id: str, + mag: cmtj.CVector, + anis: cmtj.CVector, + Ms: float, + thickness: float, + cellSurface: float, + demagTensor: List[cmtj.CVector], + damping: float, + Tc: float, + susceptibility: float, + me: float, + ) -> None: ... + def setAnisotropyDriver(self, arg0: cmtj.ScalarDriver) -> None: ... + def setExternalFieldDriver(self, arg0: cmtj.AxialDriver) -> None: ... + def setTemperatureDriver(self, arg0: cmtj.ScalarDriver) -> None: ... + +def MFAWeissCurie( + me: float, + T: float, + J0: float, + relax: float = ..., + tolerance: float = ..., + maxIter: int = ..., +) -> Tuple[float, float]: ... +def langevin(arg0: float) -> float: ... +def langevinDerivative(arg0: float) -> float: ... diff --git a/cmtj/utils/general.py b/cmtj/utils/general.py index 3844f1e..3910b69 100644 --- a/cmtj/utils/general.py +++ b/cmtj/utils/general.py @@ -16,6 +16,7 @@ class VectorObj: :param phi: positive x-axis (in xy plane) angle in radians :param mag: magnitude of the vector, if not set defaults to 1 *unit vector* """ + theta: float # in radians phi: float # rad mag: float = 1 @@ -41,7 +42,8 @@ def __hash__(self) -> int: return hash(str(self)) def __eq__(self, __value: "VectorObj") -> bool: - return self.theta == __value.theta and self.phi == __value.phi and self.mag == __value.mag + return (self.theta == __value.theta and self.phi == __value.phi + and self.mag == __value.mag) def _componentwise_mul(self, other): coors = self.get_cartesian() @@ -61,13 +63,16 @@ def from_spherical(theta, phi, mag=1): """Creates a Cartesian vector from spherical components""" return [ mag * math.sin(theta) * math.cos(phi), - mag * math.sin(theta) * math.sin(phi), mag * math.cos(theta) + mag * math.sin(theta) * math.sin(phi), + mag * math.cos(theta), ] @staticmethod def from_cartesian(x: float, y: float, z: float): """Creates a spherical vector from Cartesian components""" mag = math.sqrt(x**2 + y**2 + z**2) + if mag == 0: + return VectorObj(0, 0, 0) theta = math.acos(z / mag) phi = math.atan2(y, x) return VectorObj(theta, phi, mag) @@ -76,6 +81,8 @@ def from_cartesian(x: float, y: float, z: float): def from_cvector(cvector: CVector): """Creates a spherical vector from Cartesian components""" mag = cvector.length() + if mag == 0: + return VectorObj(0, 0, 0) theta = math.acos(cvector.z / mag) phi = math.atan2(cvector.y, cvector.x) return VectorObj(theta, phi, mag) diff --git a/docker/Dockerfile.wheel b/docker/Dockerfile.wheel new file mode 100644 index 0000000..b22c634 --- /dev/null +++ b/docker/Dockerfile.wheel @@ -0,0 +1,22 @@ +FROM python:3.9 + +# let's copy all the necessary files +# we install our only 2 dependencies :) and vim for nice workflow +RUN apt-get update && \ + apt-get install -y build-essential libfftw3-dev git python3 python3-pip vim +RUN python3 -m pip install --upgrade pip +WORKDIR /scratch + +COPY setup.py /scratch +COPY setup.cfg /scratch +COPY python /scratch/python +COPY core /scratch/core +COPY third_party /scratch/third_party +COPY cmtj /scratch/cmtj + +RUN python3 -m setup bdist_wheel && \ + python3 -m pip install dist/*.whl numpy scipy tqdm + +WORKDIR /app +RUN python3 -c "import cmtj; from cmtj.utils import FieldScan" && \ + python3 -c "import cmtj; from cmtj import Layer" diff --git a/docs/docgen.py b/docs/docgen.py index db3e53c..bd9f2b3 100644 --- a/docs/docgen.py +++ b/docs/docgen.py @@ -1,12 +1,17 @@ import glob +import logging import os import re from dataclasses import dataclass +log = logging.getLogger("mkdocs") + py_signature = r"(def (.+?) -> ([\'\[\]\,\sA-z]+)\:)" c_py_signature = re.compile(py_signature) -joint_py = r"(?s)(def (.+?) -> ([\'\[\]\,\sA-z]+)\:)\n{0,}\s{8}(\"{3}(.+?)\"{3})" +# old regex that does not allow for optional docstrings and quoted rtype +# joint_py = r"(?s)(def (.+?) -> ([\"\'\[\]\,\sA-z]+)\:)\n{0,}\s{8}(\"{3}(.+?)\"{3})" +joint_py = r"(?s)(def (.+?) -> ([\"\'\[\]\,\sA-z]+)\:)(?:\n\s*(\"{3}(.+?)\"{3}))?" c_joint_py = re.compile(joint_py) pydoc_regex = r"(?s)(\"{3}(.+?)\"{3})" @@ -81,6 +86,7 @@ def py_signature_to_markdown(self): def extract_python_docs(file_text): for captured in c_joint_py.findall(file_text): + print(captured) if captured: yield PythonDocstring( signature=captured[1].strip().replace("\n", ""), @@ -109,10 +115,16 @@ def create_api_markdown_file(src_filename): class_docs = ftext.split("class")[1:] for i, doc_ in enumerate(class_docs): + doc_ = ( + doc_.strip() + .replace("@staticmethod", "") + .replace("@classmethod", "") + .replace("@overload", "") + ) class_name = doc_.partition("\n")[0].replace(":", "").strip() print(i, class_name) md_fn += f"## `{class_name}`" - for g in extract_python_docs(doc_): + for g in extract_python_docs(doc_.replace("...", "...\n")): sig = g.py_signature_to_markdown() md_fn += f"\n{sig}\n" md_fn += " \n" @@ -123,10 +135,14 @@ def create_api_markdown_file(src_filename): f.write(md_fn) -if __name__ == "__main__": +def on_startup(command, dirty, **kwargs): fn_lists = [ *glob.glob(os.path.join(os.path.dirname(__file__), "..", "cmtj/*/*.pyi")), *glob.glob(os.path.join(os.path.dirname(__file__), "..", "cmtj/*.pyi")), ] for fn in fn_lists: create_api_markdown_file(fn) + + +if __name__ == "__main__": + on_startup() diff --git a/docs/gen-docs/cmtj.md b/docs/gen-docs/cmtj.md index 03bc8d7..52565d0 100644 --- a/docs/gen-docs/cmtj.md +++ b/docs/gen-docs/cmtj.md @@ -1,12 +1,96 @@ ## `AxialDriver` +### `__init__(self, x_driver: ScalarDriver, y_driver: ScalarDriver, z_driver: ScalarDriver)` + +### `__init__(self, arg0: List[ScalarDriver])` + +### `__init__(*args, **kwargs)` + +### `applyMask(self, arg0: CVector)` + +### `applyMask(self, arg0: List[int])` + +### `applyMask(*args, **kwargs)` + +### `getCurrentAxialDrivers(self, arg0: float)` + +### `getVectorAxialDriver(self, arg0: float, arg1: float)` + ## `Axis` +### `__init__(self, value: int)` + +### `__eq__(self, other: object)` + +### `__getstate__(self)` + +### `__hash__(self)` + +### `__index__(self)` + +### `__int__(self)` + +### `__ne__(self, other: object)` + +### `__setstate__(self, state: int)` + +### `name(self)` + +### `__doc__(self)` + +### `__members__(self)` + ## `CVector` +### `__init__(self, x: float, y: float, z: float)` + +### `length(self)` + +### `normalize(self)` + +### `tolist(self)` + +### `__add__(self, arg0: CVector)` + +### `__eq__(self, arg0: CVector)` + +### `__getitem__(self, arg0: int)` + +### `__iter__(self) -> typing.Iterator[float]: ...def __iadd__(self, arg0: CVector)` + +### `__imul__(self, arg0: float)` + +### `__isub__(self, arg0: CVector)` + +### `__len__(self)` + +### `__mul__(self, arg0: float)` + +### `__ne__(self, arg0: CVector)` + +### `__rmul__(self, arg0: float)` + +### `__sub__(self, arg0: CVector)` + +### `x(self)` + +### `x(self, val: float)` + +### `y(self)` + +### `y(self, val: float)` + +### `z(self)` + +### `z(self, val: float)` + ## `Junction` -### `__init__(self, layers: List[Layer], filename: str = ...) -> None: ...@overloaddef __init__(self, layers: List[Layer], filename: str, Rp: float = ..., Rap: float = ...) -> None: ...@overloaddef __init__(self,layers: List[Layer],filename: str,Rx0: List[float],Ry0: List[float],AMR_X: List[float],AMR_Y: List[float],SMR_X: List[float],SMR_Y: List[float],AHE: List[float],)` +### `__init__(self, layers: List[Layer], filename: str = ...)` + +### `__init__(self, layers: List[Layer], filename: str, Rp: float = ..., Rap: float = ...)` + +### `__init__(self,layers: List[Layer],filename: str,Rx0: List[float],Ry0: List[float],AMR_X: List[float],AMR_Y: List[float],SMR_X: List[float],SMR_Y: List[float],AHE: List[float],)` Creates a junction with a STRIP magnetoresistance. Each of the Rx0, Ry, AMR, AMR and SMR is list matching the @@ -14,28 +98,45 @@ length of the layers passed (they directly correspond to each layer). Calculates the magnetoresistance as per: **see reference**: Spin Hall magnetoresistance in metallic bilayers by Kim, J. et al. -### `__init__(*args, **kwargs) -> Any: ...def clearLog(self)` +#### **Parameters** + +| Name | Type | Description | Default | +| ----------- | ------------- | ------------------------------------------ | ------- | +| **`Rx0`** | `List[float]` | Magnetoresistance offset longitudinal | `-` | +| **`Ry0`** | `List[float]` | Magnetoresistance offset transverse | `-` | +| **`AMR_X`** | `List[float]` | Anisotropic magnetoresistance longitudinal | `-` | +| **`AMR_Y`** | `List[float]` | Anisotropic magnetoresistance transverse | `-` | +| **`SMR_X`** | `List[float]` | Spin magnetoresistance longitudinal | `-` | +| **`SMR_Y`** | `List[float]` | Spin magnetoresistance transverse | `-` | + +### `__init__(*args, **kwargs)` -Reset current simulation state` +### `clearLog(self)` -### `getLayerMagnetisation(self, layer_id: str) -> CVector: ...def getLog(self)` +Reset current simulation state + +### `getLayerMagnetisation(self, layer_id: str)` + +### `getLog(self)` Retrieve the simulation log [data]. -### `getMagnetoresistance(self) -> List[float]: ...def runSimulation(self,totalTime: float,timeStep: float = ...,writeFrequency: float = ...,persist: bool = ...,log: bool = ...,calculateEnergies: bool = ...,)` +### `getMagnetoresistance(self)` + +### `runSimulation(self,totalTime: float,timeStep: float = ...,writeFrequency: float = ...,persist: bool = ...,log: bool = ...,calculateEnergies: bool = ...,)` Main run simulation function. Use it to run the simulation. #### **Parameters** -| Name | Type | Description | Default | -| -------------------- | ---- | -------------------------------------------------------------------------------------- | ------- | -| **`totalTime`** | `-` | total time of a simulation, give it in seconds. Typical length is in ~couple ns. | `-` | -| **`timeStep`** | `-` | the integration step of the RK45 method. Default is 1e-13 | `-` | -| **`writeFrequency`** | `-` | how often is the log saved to? Must be no smaller than `timeStep`. Default is 1e-11. | `-` | -| **`persist`** | `-` | whether to save to the filename specified in the Junction constructor. Default is true | `-` | -| **`log`** | `-` | if you want some verbosity like timing the simulation. Default is false | `-` | +| Name | Type | Description | Default | +| -------------------- | ------- | -------------------------------------------------------------------------------------- | ------- | +| **`totalTime`** | `float` | total time of a simulation, give it in seconds. Typical length is in ~couple ns. | `-` | +| **`timeStep`** | `float` | the integration step of the RK45 method. Default is 1e-13 | `...` | +| **`writeFrequency`** | `float` | how often is the log saved to? Must be no smaller than `timeStep`. Default is 1e-11. | `...` | +| **`persist`** | `bool` | whether to save to the filename specified in the Junction constructor. Default is true | `...` | +| **`log`** | `bool` | if you want some verbosity like timing the simulation. Default is false | `...` | ### `setIECDriver(self, bottom_layer: str, top_layer: str, driver: ScalarDriver)` @@ -61,7 +162,19 @@ between bottomLyaer or topLayer, order is irrelevant. | ----------------- | ---- | ------------------ | ------- | | **`bottomLayer`** | `-` | the first layer id | `-` | -### `setLayerTemperatureDriver(self, layer_id: str, driver: ScalarDriver) -> None: ...def setLayerAnisotropyDriver(self, layer_id: str, driver: ScalarDriver) -> None: ...def setLayerCurrentDriver(self, layer_id: str, driver: ScalarDriver) -> None: ...def setLayerExternalFieldDriver(self, layer_id: str, driver: AxialDriver) -> None: ...def setLayerMagnetisation(self, layer_id: str, mag: CVector) -> None: ...@overloaddef setLayerOerstedFieldDriver(self, layer_id: str, driver: AxialDriver) -> None: ...def setLayerDampingLikeTorqueDriver(self, layer_id: str, driver: ScalarDriver)` +### `setLayerTemperatureDriver(self, layer_id: str, driver: ScalarDriver)` + +### `setLayerAnisotropyDriver(self, layer_id: str, driver: ScalarDriver)` + +### `setLayerCurrentDriver(self, layer_id: str, driver: ScalarDriver)` + +### `setLayerExternalFieldDriver(self, layer_id: str, driver: AxialDriver)` + +### `setLayerMagnetisation(self, layer_id: str, mag: CVector)` + +### `setLayerOerstedFieldDriver(self, layer_id: str, driver: AxialDriver)` + +### `setLayerDampingLikeTorqueDriver(self, layer_id: str, driver: ScalarDriver)` Set the damping like torque driver for a layer. @@ -105,17 +218,51 @@ Use `setReferenceLayer` function to do that. #### **Parameters** -| Name | Type | Description | Default | -| ------------------ | --------- | ------------------------------------------------------------------------------------ | ------- | -| **`id`** | `str` | identifiable name for a layer -- e.g. "bottom" or "free". | `-` | -| **`mag`** | `CVector` | initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence. | `-` | -| **`anis`** | `CVector` | anisotropy of the layer. A normalised vector | `-` | -| **`Ms`** | `float` | magnetisation saturation. Unit: Tesla [T]. | `-` | -| **`thickness`** | `float` | thickness of the layer. Unit: meter [m]. | `-` | -| **`cellSurface`** | `float` | surface of the layer, for volume calculation. Unit: meter^2 [m^2]. | `-` | -| **`dipoleTensor`** | `-` | dipole tensor of the layer. | `-` | +| Name | Type | Description | Default | +| ----------------- | --------- | ------------------------------------------------------------------------------------ | ------- | +| **`id`** | `str` | identifiable name for a layer -- e.g. "bottom" or "free". | `-` | +| **`mag`** | `CVector` | initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence. | `-` | +| **`anis`** | `CVector` | anisotropy of the layer. A normalised vector | `-` | +| **`Ms`** | `float` | magnetisation saturation. Unit: Tesla [T]. | `-` | +| **`thickness`** | `float` | thickness of the layer. Unit: meter [m]. | `-` | +| **`cellSurface`** | `float` | surface of the layer, for volume calculation. Unit: meter^2 [m^2]. | `-` | + +### `createSOTLayer(id: str,mag: CVector,anis: CVector,Ms: float,thickness: float,cellSurface: float,demagTensor: List[CVector],damping: float = 0.11,fieldLikeTorque: float = 0,dampingLikeTorque: float = 0,)` + +Create SOT layer -- including damping and field-like torques that are +calculated based on the effective Spin Hall angles. + +#### **Parameters** + +| Name | Type | Description | Default | +| ----------------- | --------- | ------------------------------------------------------------------------------------ | ------- | +| **`id`** | `str` | identifiable name for a layer -- e.g. "bottom" or "free". | `-` | +| **`mag`** | `CVector` | initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence. | `-` | +| **`anis`** | `CVector` | anisotropy of the layer. A normalised vector | `-` | +| **`Ms`** | `float` | magnetisation saturation. Unit: Tesla [T]. | `-` | +| **`thickness`** | `float` | thickness of the layer. Unit: meter [m]. | `-` | +| **`cellSurface`** | `float` | surface of the layer, for volume calculation. Unit: meter^2 [m^2]. | `-` | +| **`temperature`** | `-` | resting temperature of the layer. Unit: Kelvin [K]. | `-` | + +### `createSTTLayer(id: str,mag: CVector,anis: CVector,Ms: float,thickness: float,cellSurface: float,demagTensor: List[CVector],damping: float = 0.011,SlonczewskiSpacerLayerParameter: float = 1.0,beta: float = 0.0,spinPolarisation: float = 0.0,)` + +Create STT layer -- with the standard Slomczewski formulation. + +#### **Parameters** -### `createSOTLayer(id: str,mag: CVector,anis: CVector,Ms: float,thickness: float,cellSurface: float,demagTensor: List[CVector],damping: float = 0.11,fieldLikeTorque: float = 0,dampingLikeTorque: float = 0,) -> "Layer":"""Create SOT layer -- including damping and field-like torques that arecalculated based on the effective Spin Hall angles.:param id: identifiable name for a layer -- e.g. "bottom" or "free".:param mag: initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence.:param anis: anisotropy of the layer. A normalised vector:param Ms: magnetisation saturation. Unit: Tesla [T].:param thickness: thickness of the layer. Unit: meter [m].:param cellSurface: surface of the layer, for volume calculation. Unit: meter^2 [m^2].:param dipoleTensor: dipole tensor of the layer.:param temperature: resting temperature of the layer. Unit: Kelvin [K].:param damping: often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless."""...@staticmethoddef createSTTLayer(id: str,mag: CVector,anis: CVector,Ms: float,thickness: float,cellSurface: float,demagTensor: List[CVector],damping: float = 0.011,SlonczewskiSpacerLayerParameter: float = 1.0,beta: float = 0.0,spinPolarisation: float = 0.0,) -> "Layer":"""Create STT layer -- with the standard Slomczewski formulation.:param id: identifiable name for a layer -- e.g. "bottom" or "free".:param mag: initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence.:param anis: anisotropy of the layer. A normalised vector:param Ms: magnetisation saturation. Unit: Tesla [T].:param thickness: thickness of the layer. Unit: meter [m].:param cellSurface: surface of the layer, for volume calculation. Unit: meter^2 [m^2].:param dipoleTensor: dipole tensor of the layer.:param damping: often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless.:param SlonczewskiSpacerLayerParameter: Slomczewski parameter. Often marked as lambda.:param beta: beta parameter that scales FL/DL ratio.:param spinPolarisation: the spin effectiveness."""...def setAnisotropyDriver(self, driver: ScalarDriver)` +| Name | Type | Description | Default | +| ------------------------------------- | --------- | ---------------------------------------------------------------------------------------------- | ------- | +| **`id`** | `str` | identifiable name for a layer -- e.g. "bottom" or "free". | `-` | +| **`mag`** | `CVector` | initial magnetisation. Must be normalised (norm of 1). Used for quicker convergence. | `-` | +| **`anis`** | `CVector` | anisotropy of the layer. A normalised vector | `-` | +| **`Ms`** | `float` | magnetisation saturation. Unit: Tesla [T]. | `-` | +| **`thickness`** | `float` | thickness of the layer. Unit: meter [m]. | `-` | +| **`cellSurface`** | `float` | surface of the layer, for volume calculation. Unit: meter^2 [m^2]. | `-` | +| **`damping`** | `float` | often marked as alpha in the LLG equation. Damping of the layer. Default 0.011. Dimensionless. | `0.011` | +| **`SlonczewskiSpacerLayerParameter`** | `float` | Slomczewski parameter. Often marked as lambda. | `1.0` | +| **`beta`** | `float` | beta parameter that scales FL/DL ratio. | `0.0` | + +### `setAnisotropyDriver(self, driver: ScalarDriver)` Set anisotropy driver for the layer. It's scalar. The axis is determined in the layer constructor @@ -125,7 +272,13 @@ It's scalar. The axis is determined in the layer constructor Set a driver for the temperature of the layer. Automatically changes the solver to Euler-Heun. -### `setExternalFieldDriver(self, driver: AxialDriver) -> None: ...def setMagnetisation(self, mag: CVector) -> None: ...def setOerstedFieldDriver(self, driver: AxialDriver) -> None: ...def setDampingLikeTorqueDriver(self, driver: ScalarDriver)` +### `setExternalFieldDriver(self, driver: AxialDriver)` + +### `setMagnetisation(self, mag: CVector)` + +### `setOerstedFieldDriver(self, driver: AxialDriver)` + +### `setDampingLikeTorqueDriver(self, driver: ScalarDriver)` Set a driver for the damping like torque of the layer. @@ -133,7 +286,11 @@ Set a driver for the damping like torque of the layer. Set a driver for the field like torque of the layer. -### `setReferenceLayer(self, ref: CVector) -> None: ...@overloaddef setReferenceLayer(self, ref: "Reference") -> None: ...def setTopDipoleTensor(self, tensor: List[CVector])` +### `setReferenceLayer(self, ref: CVector)` + +### `setReferenceLayer(self, ref: "Reference")` + +### `setTopDipoleTensor(self, tensor: List[CVector])` Set a dipole tensor from the top layer. @@ -165,17 +322,23 @@ the axis is to be id. ## `ScalarDriver` -### `__init__(self, *args, **kwargs) -> None: ...@staticmethoddef getConstantDriver(constantValue: float) -> "ScalarDriver":"""Constant driver produces a constant signal of a fixed amplitude.:param constantValue: constant value of the driver (constant offset/amplitude)"""...@staticmethoddef getPulseDriver(constantValue: float, amplitude: "ScalarDriver", period: float, cycle: float)` +### `__init__(self, *args, **kwargs)` + +### `getConstantDriver(constantValue: float)` + +Constant driver produces a constant signal of a fixed amplitude. + +### `getPulseDriver(constantValue: float, amplitude: "ScalarDriver", period: float, cycle: float)` Produces a square pulse of certain period and cycle #### **Parameters** -| Name | Type | Description | Default | -| ------------------- | ---- | -------------------------------------------------------------------------- | ------- | -| **`constantValue`** | `-` | offset (vertical) of the pulse. The pulse amplitude will be added to this. | `-` | -| **`amplitude`** | `-` | amplitude of the pulse signal | `-` | -| **`period`** | `-` | period of the signal in seconds | `-` | +| Name | Type | Description | Default | +| ------------------- | ---------------- | -------------------------------------------------------------------------- | ------- | +| **`constantValue`** | `float` | offset (vertical) of the pulse. The pulse amplitude will be added to this. | `-` | +| **`amplitude`** | `"ScalarDriver"` | amplitude of the pulse signal | `-` | +| **`period`** | `float` | period of the signal in seconds | `-` | ### `getSineDriver(constantValue: float, amplitude: "ScalarDriver", frequency: float, phase: float)` @@ -189,9 +352,9 @@ Produces a sinusoidal signal with some offset (constantValue), amplitude frequen | **`amplitude`** | `"ScalarDriver"` | amplitude of the sine wave | `-` | | **`frequency`** | `float` | frequency of the sine | `-` | -### `getStepDriver(constantValue: float, amplitude: float, timeStart: float, timeStop: float) -> "ScalarDriver":"""Get a step driver. It has amplitude between timeStart and timeStop and 0 elsewhere:param constantValue: offset of the pulse (vertical):param amplitude: amplitude that is added on top of the constantValue:param timeStart: start of the pulse:param timeStop: when the pulse ends"""...@staticmethoddef getTrapezoidDriver(constantValue: float,amplitude: float,timeStart,edgeTime: float,steadyTime: float,)` +### `getStepDriver(constantValue: float, amplitude: float, timeStart: float, timeStop: float)` -Create Trapezoid driver. Has a rising and a falling edge. +Get a step driver. It has amplitude between timeStart and timeStop and 0 elsewhere #### **Parameters** @@ -200,7 +363,19 @@ Create Trapezoid driver. Has a rising and a falling edge. | **`constantValue`** | `float` | offset of the pulse (vertical) | `-` | | **`amplitude`** | `float` | amplitude that is added on top of the constantValue | `-` | | **`timeStart`** | `float` | start of the pulse | `-` | -| **`edgeTime`** | `-` | time it takes to reach the maximum amplitude | `-` | + +### `getTrapezoidDriver(constantValue: float,amplitude: float,timeStart,edgeTime: float,steadyTime: float,)` + +Create Trapezoid driver. Has a rising and a falling edge. + +#### **Parameters** + +| Name | Type | Description | Default | +| ------------------- | ------- | --------------------------------------------------- | ------- | +| **`constantValue`** | `float` | offset of the pulse (vertical) | `-` | +| **`amplitude`** | `float` | amplitude that is added on top of the constantValue | `-` | +| **`timeStart`** | `-` | start of the pulse | `-` | +| **`edgeTime`** | `float` | time it takes to reach the maximum amplitude | `-` | ### `getGaussianImpulseDriver(constantValue: float, amplitude: float, t0: float, sigma: float)` diff --git a/docs/gen-docs/noise.md b/docs/gen-docs/noise.md index acfc8ae..21df91f 100644 --- a/docs/gen-docs/noise.md +++ b/docs/gen-docs/noise.md @@ -1,6 +1,8 @@ ## `BufferedAlphaNoise` -### `__init__(self, bufferSize: int, alpha: float, std: float, scale: float) -> None: ...def fillBuffer(self)` +### `__init__(self, bufferSize: int, alpha: float, std: float, scale: float)` + +### `fillBuffer(self)` Fill the buffer with the noise. This method is called only once. @@ -10,6 +12,10 @@ Produce the next sample of the noise. ## `VectorAlphaNoise` -### `__init__(self,bufferSize: int,alpha: float,std: float,scale: float,axis: cmtj.Axis = cmtj.Axis.all,) -> None: ...def getPrevSample(self) -> cmtj.CVector:"""Get the previous sample of the noise in a vector form."""...def getScale(self)` +### `__init__(self,bufferSize: int,alpha: float,std: float,scale: float,axis: cmtj.Axis = cmtj.Axis.all,)` + +### `getPrevSample(self) -> cmtj.CVector:"""Get the previous sample of the noise in a vector form."""...def getScale(self)` Get the scale of the noise. + +### `tick(self)` diff --git a/docs/index.md b/docs/index.md index 5fc83d3..e3d4b29 100644 --- a/docs/index.md +++ b/docs/index.md @@ -30,7 +30,7 @@ ## Short description -A name may be misleading -- the MTJ (Magnetic Tunnel Junctions) are not the only structures that may be simulated. +The `cmtj` name may be misleading -- the MTJ (Magnetic Tunnel Junctions) are not the only structures that may be simulated. The library allows for macromagnetic simulation of various multilayer spintronic structures. The package uses C++ implementation of (s)LLGS (stochastic Landau-Lifschitz-Gilbert-Slonczewski) equation with various field contributions included for instance: anisotropy, interlayer exchange coupling, demagnetisation, dipole fields etc. It is also possible to connect devices in parallel or in series to have electrically coupled arrays. @@ -42,8 +42,8 @@ Check out the [streamlit hosted demo here](http://cmtj-simulations.streamlit.app #### Installation :rocket: +The recommended way is to use the `pip` package manager and virtualenv (or conda). Installation is as easy as doing: -A recommended way is to use the `pip` package manager and virtualenv (or conda). 1. With `virtualenv` (recommended): diff --git a/mkdocs.yml b/mkdocs.yml index 3fee2cc..a73a88b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,6 +9,7 @@ edit_uri: "" hooks: - scripts/readme_copy.py + - docs/docgen.py nav: - Home: index.md @@ -45,6 +46,7 @@ nav: - Miscellanous: api/general-reference.md - Stack: gen-docs/stack.md - Noise: gen-docs/noise.md + - LLGB: gen-docs/llgb.md - Examples: - Library introduction: tutorials/CMTJBindingsTutorial.ipynb - Trajectories: tutorials/trajectory.ipynb diff --git a/setup.py b/setup.py index fc916bc..099e944 100644 --- a/setup.py +++ b/setup.py @@ -6,7 +6,7 @@ from setuptools import Extension, find_namespace_packages, setup from setuptools.command.build_ext import build_ext -__version__ = "1.5.2" +__version__ = "1.5.3" """ As per https://github.com/pybind/python_example @@ -129,6 +129,7 @@ def build_extensions(self): def find_stubs(path: Path): + """Actually only MANIFEST.in is needed for this. Leaving JIC.""" return [str(pyi.relative_to(path)) for pyi in path.rglob("*.pyi")] @@ -144,7 +145,11 @@ def find_stubs(path: Path): include_package_data=True, namespace_packages=["cmtj"], packages=find_namespace_packages(include=["cmtj.*"]), - package_data={"cmtj": [*find_stubs(path=Path("cmtj"))]}, + package_data={ + "cmtj": [ + *find_stubs(path=Path("cmtj")), + ] + }, setup_requires=["pybind11>=2.6.1"], cmdclass={"build_ext": BuildExt}, zip_safe=False,