Introduction
In the macromagnetic simulations we distinguish between the following contributions that constitute the \(\mathbf{H}_\textrm{eff}\):
where each component corresponds, respectively, to the applied external field, interlayer exchange coupling (IEC), Oersted field, anisotropy field, demagnetising, dipole, thermal, and \(1/f\) noise field. The \(^*\) superscripts denote the stochastic contributions (those require a stochastic solver, more on that in the Macromagnetic models section).
In-API classification
We will go through the contributions step by step. However, before we do that, it is useful to mention that the contributions can be divided into 3 categories with respect to their relationship with a Driver
system:
ScalarDriver
driven contributions: \(\mathbf{H}_\textrm{K}\), \(\mathbf{H}_\textrm{th}\), and \(\mathbf{H}_\textrm{IEC}\) Those contributions have their magnitude changed only. The exception is \(\mathbf{H}_\textrm{K}\) which has a constant axis passed in the constructor of aLayer
object. Other than that, only the magnitude of those effect may be controlled, their direction is computed internally, as it depends on the \(\mathbf{m}\) vectors.AxialDriver
driven contributions: \(\mathbf{H}_\textrm{ext}\), \(\mathbf{H}_\textrm{Oe}\). Axial contributions can have magntidue controllers in any of the 3 directions, along x, y and z axis. SinceAxialDriver
consists of 3ScalarDrivers
(one for each axis), it is easy to manipulate each axis independently, magnitudewise.- static contributions \({H}_\textrm{dipole}\), and \(\mathbf{H}_\textrm{demag}\).
Static contributions are not driven by any
Driver
system, they are simply added to the \(\mathbf{H}_\textrm{eff}\) field. This may be subject to change in future API versions.
Note
Almost every contribution may be set either using Layer
api or Junction
api. They both have the same set of arguments, and the naming convention is such that if e.g. Layer
has a method setContribution
, then Junction
has a method setLayerContribution
and requires one additional argument specyfing the layer id (or all
if it is to be set for all layers in the Junction
). There are some exceptions to this, e.g. setLayerIEC
, which is only defined for two or more layers, therefore it cannot be set from a Layer
object.
External field
The external field is the simplest contribution to the effective field. It is the sum of the applied fields.
Name | Unit | Description |
---|---|---|
\(H_\textrm{x}\) | A/m | Value of field in x direction |
\(H_\textrm{y}\) | A/m | Value of field in y direction |
\(H_\textrm{z}\) | A/m | Value of field in y direction |
layer.setExternalFieldDriver(
AxialDriver(
ScalarDriver.getConstantDriver(100),
ScalarDriver.getConstantDriver(0),
ScalarDriver.getSineDriver(0, 300, 20e39, 0)
)
)
or for the Junctions
api:
device.setLayerExternalFieldDriver(
"free", # this value of course depends on the layer id
AxialDriver(
ScalarDriver.getConstantDriver(100),
ScalarDriver.getConstantDriver(0),
ScalarDriver.getSineDriver(0, 300, 20e39, 0)
)
)
Oersted field
The Oersted field is the field generated by the flow of current. Currently it is separated from the external field, but it is set the same way, irrespective of the actual current setting in the API. This may be subject to change.
Name | Unit | Description |
---|---|---|
\(H_\textrm{x}\) | A/m | Value of field in x direction |
\(H_\textrm{y}\) | A/m | Value of field in y direction |
\(H_\textrm{z}\) | A/m | Value of field in y direction |
layer.setOerstedFieldDriver(
AxialDriver(
ScalarDriver.getConstantDriver(100),
ScalarDriver.getConstantDriver(0),
ScalarDriver.getSineDriver(0, 300, 20e39, 0)
)
)
or for the Junctions
api:
device.setLayerOerstedFieldDriver(
"free", # this value of course depends on the layer id
AxialDriver(
ScalarDriver.getConstantDriver(100),
ScalarDriver.getConstantDriver(0),
ScalarDriver.getSineDriver(0, 300, 20e39, 0)
)
)
Exchange field -- IEC
Interlayer exchange coupling is a scalar driven field contribution. It governs the RKKY-like interaction between magnetic layers.
Name | Unit | Description |
---|---|---|
\(J_\textrm{linear}\) | \(J/m^2\) | Linear value of the IEC contribution |
\(J_\textrm{quad}\) | \(J/m^2\) | Linear value of the IEC contribution |
layerA | str |
Layer id of a participating layer |
layerB | str |
Layer id of other participating layer |
Linear layer is being set with:
device.setIECDriver(
"free" # this value of course depends on the layer id
"bottom", # this value of course depends on the layer id
ScalarDriver.getConstantDriver(1e-4)
)
and quadratic:
device.setQuadIECDriver(
"free" # this value of course depends on the layer id
"bottom", # this value of course depends on the layer id
ScalarDriver.getConstantDriver(1e-6)
)
The resulting interaction field for layer 1 \(\mathbf{m}_1\) is computed as:
Dipole and demag
Those two contributions have different origins, but in CMTJ
they share a similar api and way of computation.
Both are given by tensors, and may be computed externally.
where \(\mathbf{N}_\textrm{dipole}\) is the dipole tensor of the layer. The demag field is the same way, but with the tensor \(\mathbf{N}_\textrm{demag}\) of the layer.
Since demag
tensor is inherent to the geometry (shape) of the system, it is passed in the Layer
object.
Name | Unit | Description |
---|---|---|
\(\mathbf{N}_{inter}\) | - | Tensor of the interaction for dipole or demag |
The dipole
depends on the external interaction and may be due any magnetic interaction a device or layer has with any other magnetic object. Therefore, it is passed in the Layer
API as:
layer.setTopDipoleTensor(
[
CVector(0, 5e-8, 1e-24),
CVector(5e-8, -2e-6, 0),
CVector(1e-23, 0, 1e-23),
]
)
layer.setBottomDipoleTensor(
[
CVector(0, 5e-8, 1e-24),
CVector(5e-8, -2e-6, 0),
CVector(1e-23, 0, 1e-23),
]
)
Under the hood we simply sum the contributions from both:
We set for top
and bottom
separately since it may come for instance from top and bottom layer and thus top or bottom may be different. Effectively, you can just pass either, where you sum the dipole tensors and it'll have the same effect. However, API makes this convenient separation to logically separate those contributions.
Note
Dipole tensor for now is only set from the Layer API. We may add a function for adding it in the Junction API as well in near future.
Anisotropy
Anisotropy computation has two components -- axis \(\mathbf{a}\) which is in CMTJ a vector, and value \(K_\textrm{u}\) which is a scalar. The axis is passed in the Layer
constructor under anis
parameter. The scalar value, however, is driven with a ScalarDriver
object and can be dynamically operated from either Layer
or Junction
API.
Name | Unit | Description |
---|---|---|
\(\mathbf{K}_\textrm{u}\) | \(J/m^3\) | Value of the anisotropy constant |
layer.setAnisotropyDriver(
ScalarDriver.getConstantDriver(1e6)
)
or Junction
API:
device.setLayerAnisotropyDriver(
"free", # this value of course depends on the layer id
ScalarDriver.getConstantDriver(1e6)
)
The resulting anisotropy field is computed as: