Introduction

Micromagnetic simulations are widely used in a range of applications, from magnetic storage technologies and the design of hard and soft magnetic materials, to the modern fields of magnonics, spintronics, or even neuromorphic computing. A finite difference approximation has been proven useful for many applications due to its simplicity and its high performance, compared with the more flexible finite element approach.

Currently, there are already many open-source finite difference codes available, like OOMMF1, mumax32, magnum.af3, magnum.fd4, fidimag5, to mention just a few. However, for the development of new algorithms or for bleeding edge simulations one often needs to modify or extend the provided tools. For example post-processing of the created data often requires the setup of a seperate tool-chain. magnum.np provides a very flexible interface which allows the combination of many of these tasks into a single framework. It should bridge the gap between development codes, which are used for the testing of new methods, and production codes which are highly optimized for one specific task.

Complex algorithms can be easily built on top of the available core functions. Possible examples include an eigenmode solver for the calculation of small magnetization fluctuations, the calculation of the dispersion relation of magnonic devices, or the string-method for the calculation of energy barriers between different energy minima6,7,8.

Due to the use of PyTorch’s autograd method magnum.np is also well suited for solving inverse design problems. Inverse design refers to a design approach where the desired properties and functionalities of a system are specified first, and then the optimal structure or materials are determined to achieve those properties. It involves working backwards from the desired output to determine the necessary input parameters.

Recently, some inverse micromagnetic problems have been reported9,10,11, where the magnetic systems have been optimized for a specific task. Providing a gradient of the objective function with regard to the design variables allow to use very efficient gradient-based optimization methods. Using PyTorch’s autograd features, it is easily possible to define the design variables as differentiable and after the micromagnetic simulation (forward problem) has been performed the corresponding gradient can be computed using reverse-mode auto-differentiation.

Magnum.np is open-source under the GPL3 licence and can be found at https://gitlab.com/magnum.np/magnum.np. Different demo scripts are part of the source code and can be tested online using Google Colab12, without the need for local installations or specialized hardware like GPUs. A list of demos can be found on the project gitlab page https://gitlab.com/magnum.np/magnum.np#documented-demos.

Design

In contrast to many available micromagnetic codes magnum.np follows a high-level approach for easy readability, maintainance and development. The Python programming language combined with PyTorch offers a powerful environment, which allows to write high-level code, but still get competitive performance due to proper vectorization.

PyTorch13 has been chosen as backend since it allows transparently switching between CPU and GPU without modification of the code. Also the use of single or double precision arithmethic can be switched easily (e.g. use torch.set_default_dtype). Furthermore, it offers a very flexible tensor interface, based on the the Numpy Array API. Directly using torch tensors for calculation avoids the need for custom vector classes and allows using pytorch functions without the need for any wrapping code.

As a nice benefit of using PyTorch, one can directly use inverse operations via the PyTorch’s autograd feature14. Even the utilization of deep neural networks in combination with classical micromagnetics would become feasable15.

One key philosophy of the magnum.np design is to utilize few well-known libraries in order to delegate work, but keep its own code clean and compact. On the other hand we try to keep the number of dependencies as small as possible, in order to improve maintainability. As an example pyvista is used for simple reading or writing VTK files, but also offers many additional capabilities (mesh formats, visualization, etc.).

Figure 1 summarizes the most important building blocks and features.

Figure 1
figure 1

Overview of the high-level interface of magnum.np.

The state class contains the actual state of the simulation like time t, magnetization \(\varvec{m}\) or in case of an Oersted field the corresponding current density \(\varvec{j}\). It also contains the information about mesh and materials. The finite difference method is based on an equidistant rectangular mesh consisting of \(n_x \times n_y \times n_z\) cells, with a grid spacing \((\Delta x, \Delta y, \Delta z)\) and an origin \((x_0, y_0, z_0)\). Thus the index set (ijk) is sufficient to identify an individual cell center:

$$\begin{aligned} \varvec{x}_{i,j,k} = \begin{pmatrix} x_i \\ x_j \\ x_k\end{pmatrix} = \begin{pmatrix} x_0 + i \; \Delta x \\ y_0 + j \; \Delta y \\ z_0 + k \; \Delta z \end{pmatrix} = \varvec{x}_0 + \Delta \varvec{x} \quad \text {with} \quad \begin{matrix} i = 0...n_x-1 \\ j = 0...n_y-1 \\ k = 0...n_z-1 \end{matrix} \end{aligned}$$
(1)

Internally, physical fields are stored as multi-dimensional PyTorch tensors, where one value is stored for each cell (e.g. scalar fields are stored as \((n_x, n_y, n_z, 1)\) tensors). Using Numpy Array API features like slicing or fancy indexing allows simple modification of the corresponding data. Furthermore, it allows the use of the same expression for constant and non-constant materials, which contains one material parameter for each cell of the mesh. This avoids additional storage in case of constant materials, without the need for independent code branches. By using overloading of the __call__ operator, it is even possible to allow time dependent material parameters in a transparent way.

It is often very useful to select sub-regions within the mesh, e.g. for defining location dependent material parameters, or evaluate the magnetization only in a part of the geometry. We call these sub-regions “domains” and they are easily represented by boolean tensors, which can be created by low-level tensor operation or by using SpatialCoordinate - a list of tensors (xyz) which store the physical location of each cell. Using these coordinate tensors allows to specify domains by simple analytic expressions (e.g. \(x^2 + y^2 < r^2\) for a circle with radius r). The same coordinate tensors can also be used to parametrize magnetic configurations like vortices or skyrmions (see e.g. Listing 1 with the corresponding magnetization visualized in Fig. 2).

Listing 1:
figure a

Parametrization of a vortex configuration within a disk with radius r = 20nm using SpatialCoordinate

Figure 2
figure 2

Resulting magnetization created using the parametrization in Listing 1. The color visualizes the x-component of the magnetization. The gray color outside of the disk shows that the magnetization is zero, outside of the magnetic domain.

The actual state can be stored by means of loggers. The ScalarLogger is able to log arbitrary scalar functions depending on the current state (e.g. average magnetization, field at a certain point, GMR signal, ...). The FieldLogger stores arbitrary field data using VTK.

Due to the very flexible interface it is also intendend to add utility function for various application cases to the magnum.np library. In many cases pre- and post-processing is already done in some high-level python scripts, which makes it possible to directly reuse those codes in magnum.np at least on CPU. In many cases time-critical routines can be easily translated into PyTorch code, which then also runs on the GPU, due to the common Numpy Array API. Examples of such utility functions which are already included within magnum.np are Voronoi mesh generators, several imaging tools for post-processing – like Lorentz Transmission Electron Microscopy(LTEM) or Magnetic Force Microscopy(MFM) – or the calculation of a dispersion relation from time-domain micromagnetic simulations.

Landau–Lifshitz–Gilbert equation

Dynamic micromagnetism is described by the Landau–Lifshitz–Gilbert equation

$$\begin{aligned} \dot{\varvec{m}} = -\frac{\gamma }{1+\alpha ^2} \left[ \varvec{m} \times \varvec{h}^\text {eff} + \alpha \, \varvec{m} \times \left( \varvec{m} \times \varvec{h}^\text {eff} \right) \right] , \end{aligned}$$
(2)

with the reduced magnetization \(\varvec{m}\), the reduced gyromagnetic ratio \(\gamma = 2.21 \times 10^{5}\text {m/As}\), the dimensionless damping constant \(\alpha\), and the effective field \(\varvec{h}^\text {eff}\). The effective field may contain several contributions like the magnetostatic strayfield, or the quantummechanical exchange interaction (see “Field terms” section for the detailed descriptions of possible field terms).

For the solution of the Eq. (2) in time-domain most finite difference codes use explicit Runge–Kutta (RK) methods of different order. Magnum.np by default uses the Runge–Kutta–Fehlberg Method (RKF45)16, which uses a 4th order approximation with a 5th order error control. Explicit RK methods, are very common, due to their simplicity and they are well suited for modern GPU computing. Additionally, third party solvers can be easily added, since many libraries already provide a proper python interface. For example wrappers for Scipy (CPU-only) and TorchDiffEq solvers are provided. Those solvers include more complicated solver methods like implicit BDF17, which are well suited for stiff problems.

Often one is only iterested in the magnetic groundstate, in which case the LLG can be integrated with a high damping constant (and optionally without the precession term). Alternatively, the micromagnetic energy18,19 can be minimized directly, which is often much more efficient. However, special care has to be taken since, standard conjugate gradient method may fail to produce correct results20.

Field terms

The following section shows some implementation details of the effective field terms. Due to the flexible interface new field terms can easily be added even without modifying the core library.

All field terms which are linear in the magnetization \(\varvec{m}\) inherit from the LinearFieldTerm class, in order to allow a common calculation of the energy using

$$\begin{aligned} {\mathcal {E}}^\text {lin} = -\frac{1}{2} \mu _0 \int M_s \, \varvec{m} \cdot \varvec{h}^\text {lin} \,\text {d}\varvec{x}, \end{aligned}$$
(3)

with the corresponding (continuous) field \(\varvec{h}^\text {lin}\), the saturation magnetization \(M_s\), and the vacuum permeability \(\mu _0\).

In the following several field contributions will be described including a continuous formulation as well as the used discretization. For example the discretized version of the linear field energy can be written as

$$\begin{aligned} E^\text {lin} = -\frac{1}{2} \mu _0 V \sum _{\varvec{i}} M_s \, \varvec{m}_{\varvec{i}} \cdot \varvec{h}_{\varvec{i}}^\text {lin}, \end{aligned}$$
(4)

with the cell volume \(V = \Delta x \, \Delta y \, \Delta z\). \(x_{\varvec{i}}\) describes a discretized quantity x at the cell with index \(\varvec{i}\). Some indices \(\varvec{i}\) will be omitted for sake of better readability (e.g. for the material parameter \(M_s\)).

Anisotropy field

Spin orbit coupling gives rise to an anisotropy field which favors the alignment of the magnetization into certain axes. Depending on the crystal structure one or more of such easy axis may be observed. E.g. material with tetragonal or hexagonal structure show a uniaxial anisotropy which gives rise the the following interaction field

$$\begin{aligned} \varvec{h}^\text {u}(\varvec{x}) = \frac{2 K_\text {u1}}{\mu _0 \, M_s} \; \varvec{e}_\text {u} \; (\varvec{e}_\text {u} \cdot \varvec{m}) + \frac{4 K_\text {u2}}{\mu _0 \, M_s} \; \varvec{e}_\text {u} \; (\varvec{e}_\text {u} \cdot \varvec{m})^3, \end{aligned}$$
(5)

where \(K_\text {u1}\) and \(K_\text {u2}\) are the first and second order uniaxial anisotropy constants, respectively, and \(\varvec{e}_\text {u}\) is the corresponding easy axis. Since the anisotropy is a local interaction, its discretization is straight forward and will be ommited. The corresponding source code is shown in Listing 2.

Listing 2:
figure b

Implementation of the first order uniaxial anisotropy field.

Since the uniaxial anistropy field is a linear field term, only the field needs to be implemented, whereas the energy is inherited from the LinearFieldTerm. Material parameters are accessed from state.material which returns the material for each cell at the time state.t. The actual field expression is very close to the mathematical formulation, which makes the code easy to ready and adapt for similar use cases.

For a cubic crystal structure the corresponding cubic anisotropy field is given by

$$\begin{aligned} \varvec{h}^\text {c}(\varvec{x}) = -\frac{2 K_\text {c1}}{\mu _0 \, M_s} \; \begin{pmatrix} m_1 \, m_2^2 + m_1 \, m_3^2 \\ m_2 \, m_3^2 + m_2 \, m_1^2 \\ m_3 \, m_1^2 + m_3 \, m_2^2\end{pmatrix} -\frac{2 K_\text {c2}}{\mu _0 \, M_s} \; \begin{pmatrix} m_1 \, m_2^2 \, m_3^2 \\ m_1^2 \, m_2 \, m_3^2 \\ m_1^2 \, m_2^2 \, m_3\end{pmatrix}, \end{aligned}$$
(6)

where \(K_\text {u1}\) and \(K_\text {u2}\) are the corresponding first and second order cubic anisotropy constants. \(m_1\), \(m_2\) and \(m_3\) are the magnetization components in three orthogonal principal axes.

Exchange field

The quantum mechanical exchange interaction favours the parallel alignment of neigboring spins. Variation of the micromagnetic energy gives rise the the following exchange field

$$\begin{aligned} \varvec{h}^\text {ex}(\varvec{x}) = \frac{2}{\mu _0 \, M_s} \nabla \cdot \left( A \, \nabla \varvec{m} \right) , \end{aligned}$$
(7)

combined with a proper boundary condition21 for the magnetization \(\varvec{m}\), which can be expressed as

$$\begin{aligned} B = 2 A \, \frac{\partial \varvec{m}}{\partial \varvec{n}} \end{aligned}$$
(8)

The boundary condition is important for the correct treatment of the outer system boundaries, but also for interface between different materials. In general the jump of B over an interface \(\Gamma\) needs to vanish (\([\![B]\!] _\Gamma = 0\)). In case of an outer boundary this leads to the well-known \(\frac{\partial \varvec{m}}{\partial \varvec{n}} = 0\), if no further field contibutions (like e.g. DMI) are considered.

The discretized expression of the exchange field considering spacially varying material parameters22 is finally given by

$$\begin{aligned} \varvec{h}^\text {ex}_{\varvec{i}} = \frac{2}{\mu _0 \, M_{s,\varvec{i}}} \; \sum _{k=\pm x, \pm y,\pm z} \frac{2}{\Delta _k^2} \frac{A_{\varvec{i}+\varvec{e}_k} \; A_{\varvec{i}}}{A_{\varvec{i}+\varvec{e}_k} + A_{\varvec{i}}} \; \left( \varvec{m}_{\varvec{i}+\varvec{e}_k} - \varvec{m}_{\varvec{i}} \right) \end{aligned}$$
(9)

where A is the exchange constant and \(\Delta _k\) is the grid-spacing in direction k. The index \(\varvec{i} = (i,j,k)\) indicates the cell for which the field should be evaluated, whereas the index \(\varvec{i} \pm \varvec{e}_k\) means the index of the next neighbor in the direction \(\pm \varvec{e}_k\). Note that the harmonic mean of the exchange constants occurs in front of each next-neighbor difference, which makes it vanish if a cell is located on the boundary. This is important to fulfill the correct boundary conditions \(\frac{\partial \varvec{m}}{\partial \varvec{n}} = 0\). In case of a homogeneous exchange constant this term simplifies to the well known expression

$$\begin{aligned} \varvec{h}^\text {ex}_{\varvec{i}} = \frac{2 \, A}{\mu _0 \, M_{s,\varvec{i}}} \; \sum _\text {k=x,y,z} \frac{\varvec{m}_{\varvec{i}+\varvec{e}_k} -2 \, \varvec{m}_{\varvec{i}} + \varvec{m}_{\varvec{i}-\varvec{e}_k}}{\Delta _k^2} \end{aligned}$$
(10)

DMI field

Due to the spin-orbit coupling some materials show an additional antisymmetric exchange interaction called Dzyaloshinskii–Moriya interaction23,24. A general DMI field can be written as

$$\begin{aligned} \varvec{h}^\text {dmi}(\varvec{x}) = \frac{2 \, D}{\mu _0 \, M_s} \; \sum _{k=x,y,z} \varvec{e}^\text {dmi}_k \times \frac{\partial \varvec{m}}{\partial _k}, \end{aligned}$$
(11)

with the DMI strength D and the DMI vectors \(\varvec{e}^\text {dmi}_k\), which describe which components of the gradient of \(\varvec{m}\) contribute to which component of the corresponding field. It is assumed that \(\varvec{e}^\text {dmi}_{-k} = -\varvec{e}^\text {dmi}_k\).

Different kinds of DMI can be simply implemented by specifying the corresponding DMI vectors. For example the continuous interface DMI field for interface normals in z direction and DMI strength \(D_i\) is given by

$$\begin{aligned} \begin{aligned} \varvec{h}^\text {dmi,i}(\varvec{x})&= -\frac{2 \, D_i}{\mu _0 \, M_s} \; \left[ \nabla \left( \varvec{e}_z \cdot \varvec{m} \right) - \left( \nabla \cdot \varvec{m} \right) \, \varvec{e}_z\right] \\&= \frac{2 \, D_i}{\mu _0 \, M_s} \; \left[ \varvec{e}_y \times \frac{\partial \varvec{m}}{\partial x} - \varvec{e}_x \times \frac{\partial \varvec{m}}{\partial y}\right] , \end{aligned} \end{aligned}$$
(12)

Thus, the corresponding DMI vectors for interface DMI result in \(\varvec{e}^\text {dmi} = (\varvec{e}_y, -\varvec{e}_x, 0)\). See Table 1 for a summary of the most common DMI types.

Table 1 Most common DMI types with the corresponding symmetry class and DMI vectors.

Finally, Eq. (11) is discretized using central finite differences. For constant \(D_i\) this results in

$$\begin{aligned} \varvec{h}^\text {dmi}_{\varvec{i}} = \frac{2}{\mu _0 \, M_{s,\varvec{i}}} \; \sum _{k=\pm x, \pm y,\pm z} \tilde{D}_{\varvec{i},k} \; \frac{\varvec{e}^\text {dmi}_k \times \varvec{m}_{\varvec{i}+\varvec{e}_k}}{2 \, \Delta _k}, \end{aligned}$$
(13)

where \(\tilde{D}_{\varvec{i},k}\) is the effective DMI coupling strength between cell \(\varvec{i}\) and \(\varvec{i}+\varvec{e}_k\). Similar to the case of the exchange field, the harmonic mean is used for the avarage coupling strengths:

$$\begin{aligned} \tilde{D}_{\varvec{i},k} = \frac{2 \, D_{\varvec{i}} \, D_{\varvec{i}+\varvec{e}_k}}{D_{\varvec{i}} + D_{\varvec{i}+\varvec{e}_k}} \end{aligned}$$
(14)

Note, that if DMI interactions are in place \(\frac{\partial \varvec{m}}{\partial \varvec{n}} = 0\) does no longer hold. Instead, inhomogeneous Neumann boundary conditions occur (see e.g. Eqs. 1115 in2), which leads to a coupling of exchange and DMI interaction. The exchange field could no longer be calculated independent of the DMI interaction.

However, since the Neumann boundary conditions are only approximately fulfilled due to the finite difference approximation, magnum.np uses an alternative formulation of the discrete boundary conditions that simply ignores the non-existing values on the boundary, which is consistent with the effective coupling strengths in Eq. (14). Although, this approach seems less profound, it has been used in some well-known micromagnetic simulation packages, like fidimag5 or mumax3(openBC)2, and shows good agreements for many standard problems25.

Demagnetization field

The dipole-dipole interaction gives rise to a long-range interaction. The integral formulation of the corresponding Maxwell equations can be represented as convolution of the magnetization with a proper demagnetization kernel \(\varvec{N}\)

$$\begin{aligned} \varvec{h}^\text {dem}(\varvec{x}) = \int \limits _\Omega \varvec{N}(\varvec{x} - \varvec{x}') \, \varvec{M}(\varvec{x}') \, \,\text {d}\varvec{x}' \end{aligned}$$
(15)

Discretization on equidistant grids results in a discrete convolution which can be efficiently solved by a Fourier method. The discrete convolution theorem combined with zero-padding of the magnetization allows to replace the convolution in real space, with a point-wise multiplication in Fourier space. The discrete version of Eq. (15) reads like

$$\begin{aligned} \varvec{h}^\text {dem}_{\varvec{i}} = \sum \limits _{\varvec{j}} \varvec{N}_{\varvec{i} - \varvec{j}} \, \varvec{M}_{\varvec{j}}, \end{aligned}$$
(16)

and is visualized in Fig. 3

Figure 3
figure 3

Discrete convolution of the magnetization \(\varvec{M}\) with the demagnetization kernel \(\varvec{N}\). The color blocks in the result matrix represent the multiplications of the respective input values. Figure taken from21 with kind permission of The European Physical Journal (EPJ).

The average interaction from one cell to another can be calculated analytically using Newell’s formula26. More information about the implementation details can be found in27, where the demagnetization field has been implemented using numpy.

As shown in Fig. 4 the Newell formula is prone to fluctuations if the distance of source and target cell is too large28. Thus, it is favourable to use Newell’s formula only for the p next neighbors of a cell. For the long-range interaction one uses a simple dipole field

$$\begin{aligned} \varvec{h}^\text {dipole}(\varvec{x}) = \frac{1}{4 \pi } \frac{3 \varvec{x} \, (\varvec{M} \cdot \varvec{x}) - \vert x \vert ^2 \, \varvec{M}}{\vert x \vert ^5}, \end{aligned}$$
(17)

with the magnetic moment \(\varvec{M} = V \, M_s \, \varvec{m}\) for a cell volume V.

The difference of Newell- and dipole-field is also visualized in Fig. 4. Choosing \(p=20\) as default gives accurate results for the near-field, but avoid fluctuations to the long-range interactions. One further positive effect of using the dipole field for long-range interaction is that the setup of the demagnetization gets much faster and there is no need for caching the kernel to disk.

Figure 4
figure 4

Comparison of the numerical strayfield caluclation using Newell’s equations26, the Dipole appoximation (17), and the differnce of both increasing cell distance.

In case of multiple thin layers, which are not equi-distantly spaced, it is possible to only use the convolution theorem in the two lateral dimensions3. The asymptotic runtime in this case amounts to \({\mathcal {O}}(n_{xy} \, \log n_{xy} \, n_z^2)\), where \(n_{xy}\) are the number of cells within the lateral dimensions and \(n_z\) is the number of non-equidistant layers.

True periodic boundary conditions can be used to suppress the influence of the shape anisotropy due to the global demagnetization factor. This is crucial when simulating the microstructure of magnetic materials. The differential version of the corresponding Maxwell equations can be solved efficiently by means of the Fast Fourier Transfrom, which intrinsically fulfills the proper periodic boundary conditions29.

Oersted field

For many applications like the optimization of spinwave excitation antennas30,31 or spin orbit torque enabled devices32,33 the Oersted field created by a given current density has an important influence. For continuous current density \(\varvec{j}\) it can be calculated by means of the Biot-Savart law

$$\begin{aligned} \varvec{h}^\text {oersted}(\varvec{x}) = \frac{1}{4 \pi } \int \varvec{j}(\varvec{x}') \times \frac{\varvec{x}-\varvec{x}'}{\vert \varvec{x}-\varvec{x}'\vert ^3} \, \,\text {d}\varvec{x}' \end{aligned}$$
(18)

Most common finite difference micromagnetic codes offer the possibility to use arbitrary external fields, but lack the ability to calculate the Oersted field directly. Fortunately, the Oersted field has a similar structure to the demagnetization field and the occuring integral equations can be solved analytically34. This makes it possible to consider current densities which vary in space and time, since the corresponding field can be updated at each time-step.

As with the demagnetization field the far-field is approximated by the field of a singular current density, which avoids numerical fluctuations.

Spin-torque fields

Modern spintronic devices are based on different kinds of spin-torque fields35,36, which describe the interaction of the magnetization with the electron spin. An overview about models and numerical methods used to simulate spintronic devices can be found in21.

In general arbitrary spin torque contributions can be described by the following field

$$\begin{aligned} \varvec{h}^\text {st}(\varvec{x}) = -\frac{j_e \hbar }{2 e \mu _0 M_s} \left[ \eta _\text {damp} \, \varvec{m} \times \varvec{p} + \eta _\text {field} \, \varvec{p} \right] , \end{aligned}$$
(19)

with the current density \(j_e\), the reduced Planck constant \(\hbar\), the elementary charge e, and the polarization of the electrons \(\varvec{p}\). \(\eta _\text {damp}\) and \(\eta _\text {field}\) are material parameters which describe the amplitude of damping- and field-like torque37.

In case of Spin–Orbit-Torqe (SOT) \(\eta _\text {field}\) and \(\eta _\text {damp}\) are constant material parameters, whereas for the Spin-Transfer-Torque inside of magnetic multilayer structures those parameters additionally depend on \(\vartheta\)—the angle between \(\varvec{m}\) and \(\varvec{p}\). Expressions for the angular dependence are e.g. introduced in the original work of Slonczewski38 or more generally in39.

Spin-Transfer-Torque can also occur in bulk material inside regions with high magnetization gradients like domain walls, or vortex-like structures. The following field has been proposed by Zhang and Li40 for this case:

$$\begin{aligned} \varvec{h}^\text {stt,zl}(\varvec{x}) = \frac{b}{\gamma } \left[ \varvec{m} \times (\varvec{j}_e \cdot \nabla ) \varvec{m} + \xi \; (\varvec{j}_e \cdot \nabla ) \varvec{m} \right] , \end{aligned}$$
(20)

with the reduced gyromagnetic ratio \(\gamma\), the degree of nonadiabacity \(\xi\). b is the polarization rate of the conducting electrons and can be written as

$$\begin{aligned} b = \frac{\beta \mu _B}{e M_s (1+\xi ^2)}, \end{aligned}$$
(21)

with the Bohr magneton \(\mu _B\), and the dimensionless polarization rate \(\beta\).

The muMAG Standard Problem #5 is included in the magnum.np source code for demonstration of the Zhang-Li spin-torque.

Interlayer-exchange field

The Ruderman–Kittel–Kasuya–Yosida (RKKY) interaction41 gives rise to an exchange coupling of the magnetic layers in multilayer structures which are separated by a non-magnetic layer. The corresponding continuous interaction energy can be written as

$$\begin{aligned} E^\text {rkky} = -\int \limits _\Gamma J_\text {rkky} \, \varvec{m}_1 \cdot \varvec{m}_2 \, \,\text {d}\varvec{A}, \end{aligned}$$
(22)

where \(\Gamma\) is the interface between two layers with magnetizations \(\varvec{m}_1\) and \(\varvec{m}_2\), respectively. \(J_\text {rkky}\) is the coupling constant which oscillates with respect to the spacer layer thickness.

When discretizing the RKKY field using finite difference in many cases the spacer layer is not discretized. Instead the interaction constant \(J_\text {rkky}\) is scaled by the spacer layer thickness. Additionally, one has to make sure that the two layers are not coupled by the classical exchange interaction. In magnum.np the corresponding exchange field can be defined on subdomains, so there is no coupling via the interface.

The magnetizations \(\varvec{m}_1\), \(\varvec{m}_2\) should be evaluated directly at the interface. Since the magnetization is only available at the cell centers, most finite difference codes use a lowest order approximation which directly uses those center values. magnum.np also allows to use higher order approximations, which show significantly better convergence if partial domain walls are formed at the interface42.

For \(\varvec{m}_1\) the following expression can be found:

$$\begin{aligned} \varvec{m}_1 = {\left\{ \begin{array}{ll} \varvec{m}_{\varvec{i}} &{} \text {if order} = 0 \\ \frac{3}{2} \, \varvec{m}_{\varvec{i}} - \frac{1}{2} \, \varvec{m}_{\varvec{i}-1} &{} \text {if order} = 1 \\ \frac{15}{8} \, \varvec{m}_{\varvec{i}} - \frac{5}{4} \, \varvec{m}_{\varvec{i}-1} + \frac{3}{8} \, \varvec{m}_{\varvec{i}-2} &{} \text {if order} = 2 \\ \end{array}\right. } \end{aligned}$$
(23)

where \(\varvec{m}_{\varvec{i}}\) denotes the magnetization of the cell adjacent to the interface insided of layer 1, where the field should be evaluated. \(\varvec{m}_{\varvec{i}-1}\) and \(\varvec{m}_{\varvec{i}-2}\) are its first and second next neighbor, respectively. A similar expression is given for \(\varvec{m}_2\), but indices \(\varvec{i}\) are replaced with the corresponding indices \(\varvec{j}\) of cells inside of layer 2.

Finally, the discretization of the RKKY field corresponding to the energy Eq. (22) yields

$$\begin{aligned} \varvec{h}^\text {rkky}_{\varvec{i}} = \frac{J_\text {rkky}}{\mu _0 \, M_s \, \Delta _z} \left[ \varvec{m}_2 - \left( \varvec{m}_1 \cdot \varvec{m}_2 \right) \varvec{m}_1 \right] , \end{aligned}$$
(24)

with the cell thickness \(\Delta _z\) and the indices \(\varvec{i}\) and \(\varvec{j}\) of two adjacent cells in layer i and j. Note that the second term stems from a modified boundary condition for the classical exchange field, if higher order approximations are used.

Thermal field

Thermal fluctuation can be considered in micromagnetic simulations by adding a stochastic thermal field \(\varvec{h}^\text {th}\), which is characterized by

$$\begin{aligned} \begin{aligned} \langle \varvec{h}^\text {th}_{\varvec{i}}\rangle&= 0 \\ \langle \varvec{h}_{\varvec{i}}^\text {th}(t_0) \; \varvec{h}_{\varvec{j}}^\text {th}(t_1)\rangle&= \frac{2 \alpha k_B T}{\mu _0 M_s \gamma V \Delta t} \; \delta (t_1-t_0) \; \delta _{\varvec{i}\varvec{j}} \end{aligned} \end{aligned}$$
(25)

with the Boltzmann constant \(k_B\), the temperature T, the dimensionless damping parameter \(\alpha\), the cell volume V, and the timestep \(\Delta t\). \(\langle . \rangle\) denotes the ensemble average. The two delta functions indicate that the thermal noise is spatially and temporally uncorrelated. The actual thermal field can then be calculated by

$$\begin{aligned} \varvec{h}^\text {th}_{\varvec{i}} = \varvec{\eta }_{\varvec{i}} \sqrt{\frac{2 \alpha k_B T}{\mu _0 M_s \gamma V \Delta t}}, \end{aligned}$$
(26)

where \(\varvec{\eta }_{\varvec{i}}\) is a random vector drawn from a standard normal distribution for each time-step.

When numerically integrating stochastic differential equations, a drift term can occur if not using the correct statistics within the numerical methods. Although some higher-order Runge-Kutta schemes exist, they become increasingly complex. Fortunately, it has been proven that in case of the LLG the drift term only changes the length of the magnetization, which is fixed anyway. Thus, it is possible to straight forwardly use available adaptive higher order schemes for the solution of the stochastic LLG43.

Timings

Benchmarks of the field terms are presented in Fig. 5. The results show that for systems larger than about \(N = 10^6\) elements, the demagnetization field is the dominating field term and it is less than a factor 2 slower than the mumax3 version. However, these timings have been performed without any low-level optimization. Instead magnum.np utilizes high-level optimization, that does not influence the simplicity of the code. For example just-in-time compilers (like PyTorch-compile, numba, nvidia-warp, etc.) are used to improve the performance of the code. For all local field contributions this works increadibly well and the resulting timings are even outperforming mumax3. Optimized timing using torch.compile of the recently published version 2.0 of PyTorch are included in Fig. 5. Unfortunately, torch.compile does not yet support complex datatypes, which prevents it from being used to calculate the demagnetization field.

In case of the demagnetization field an optimized padding for the 3D FFT which is not yet provided by PyTorch, could give some further speedup.

Figure 5
figure 5

Benchmarking (a) demagnetization field and (b) exchange field for different system sizes N on an Intel(R) Xeon 6326 CPU @ 2.90 GHz using one NVIDIA A100 80GB GPU (CUDA Driver 11.8). An average of 10000 evaluations has been measured for each field term. Before measurent begins, 1000 warm-up loops are used to ensure that the GPU has reached its maximum performance state. Single precision arithmetics are used for comparison with mumax3.

Examples

The following section provides some examples which should demonstrate the ease of use and the power of the magnum.np interface. Due to the python/PyTorch interface pre- and post-processing can be done in a single script (or at least in the same scripting language) and allows to keep the complete simulation framework as simple as possible. The presented code focuses on complex examples which would be more elaborate to setup with other micromagnetic codes. In the magnum.np source code44 several other examples are included, such as hysteresis loop calculations, simulation of soft magnetic composites, an RKKY standard problem and the muMAG standard problems. Further examples will be continously added.

Spintronic devices

The first example demonstrates the creation and manipulation of skyrmions in magnetic thin films, that can be patterned by means of ion radiation techniques to locally alter the magnetic materials of the system45. This simulation technique is also useful for the numerical modeling of structued Pt-layers on top of the thin-film that create a location-dependent DMI interaction as realized recently in an experimental work46.

Listing 3 shows the material definition for the spintronic demo, where the anisotropy constant is altered in the irradiated region. A rectangular mesh with \(\varvec{n}\) cells and a grid spacing \(\varvec{dx}\) is created and integer domain-ids are read from an unstructured mesh file by means of the mesh_reader. Boolean domain arrays can then be derived and in turn be used to set location dependent material parameters, which will influences the local skyrmion densities.

Listing 3:
figure c

Mesh creation and boolean domains read from an external unstructured grid file “mesh.msh”, which are used to define location dependent material parameters.

A random initial magnetization is set and the default RKF45 solver is used for time-integration. Several logging capabilities allow to flexibly log scalar- and field-data to files. Custom python functions that return derived quantities, such as the Induction Map (IM) or the Lorentz Transmission Electron Microscopy (LTEM) image of the magnetization state, can simply be added as log entries. Listing 4 shows the corresponding code and the results are visualized in Fig. 6. One can see that the density of skyrmions in the irradiated region is increased significantly compared to the outside region. The lower anisotropy allows the nucleation of not only skyrmions, but also trivial type-II bubbles, and antiskyrmions47.

Figure 6
figure 6

Visualization of the created skyrmions at \(\mu _0 H_z={250}\text {mT}\) using (a) an Induction Map, (b) an underfocus Lorentz Transmission Electron Microscopy image, or (c) the z-component of the magnetization.

Listing 4:
figure d

Setup of time-integration for 20 ns and logging. Scalar data, like time t and avarage magnetization 〈m〉, will be written to a column based text field. Field data, like the magnetization m as well as a corresponding LTEM image, will be written to .vti files utilizing pyvista.

Inverse design

Finding the optimal shape of magnetic components for certain applications is an essential, but quite challenging task. An automated topology optimization requires the efficient calculation of the so-called forward problem, as well as the corresponding gradients (compare e.g.48,49). The following example should demonstrate how magnum.np can be used to solve inverse problems, by utilizing PyTorch’s autograd mechanism.

The field created by a magnetization at a certain location \(\varvec{x}_0\) should be maximized. The objective function J which should be minimized could thus be defined as \(J[\varvec{m}] = h_y(\varvec{x}_0)\)). The forward problem is simply an evaluation of the demagnetization field. The optimization requires the calculation of the gradient \(\varvec{g} = \frac{\partial J}{\partial \varvec{m}}\). The magnetization should always point in y direction, and its magnitude \(m_y\) saturates at \(M_s\).

The optimal magnetization which leads to the maximum field at the evaluation point can be found by using an gradient-based optimization method (e.g. Conjugate Gradient). Since this simple example is linear, the optimal solution is found after a single iteration. Depending on the sign of the gradient the optimal magnetization within each cell is 1, if the calculated gradient is positive and 0 otherwise. Listing 5 summarizes how the gradient calculation is performed. The optimized magnetization is visualized in Fig. 7 and shows perfect agreement with the analytical result.

Figure 7
figure 7

Optimal topology that maximizes the z-component of the strayfield at the marked cell. Only cells with a positive gradient are shown. The logarithmic color scheme represents the sensitivity of the objective function on the magnetization within the corresponding cell (red means a large sensitivity). The dotted line shows the analytic result \(x < \sqrt{2} \, y\).

Listing 5:
figure e

Full topology optimization example which solves the inverse strayfield problem utilizing PyTorch’s autograd mechanism.

Conclusion

An overview of the basic design ideas of magnum.np has been given. Equations and references for the most important field contributions as well as solving methods are included for clarification. Some typical applications are provided in order to demonstrate the ease of use and the power of the provided python-base interface. Furthermore the use of PyTorch extends magnum.np’s capabilities to inverse probems and allows seamlessly running applications on CPU and GPU without any modification of the code. The openness of the project should encourage other developers to contribute code and use magnum.np as a framework for the development and testing of new algorithms, while still getting reasonable performance and generality.