Demag field - FMM

Calculating the demagnetization (stray) field is typically the most computationally demanding part of a micromagnetic simulation. MagTense’s default approach - the fully analytical demagnetization tensor - is exact, with memory and work that scale as \(O(N^2)\) in the number of cells.

For very large systems MagTense includes an implementation of the Fast Multipole Method (FMM), which reduces the computational complexity to \(O(N)\) while keeping the analytical tensor for all near-field interactions.

Note

The FMM path is selected explicitly with use_fmm, in a library built with USE_FMM3D=1, so a problem keeps its demagnetization path when the library is rebuilt.

Implementation and attribution

The FMM acceleration in MagTense is built upon the FMM3D library developed by the Flatiron Institute.

  • Core library: Flatiron Institute FMM3D

  • Linking: MagTense links against a fork, Ximtecs/FMM3D, which contains updated build configurations and makefiles to allow integration with the MagTense Fortran core.

Compilation

To enable FMM support during the build, include the FMM flag in the make command. This links the FMM3D libraries and enables the specialised Fortran modules:

make USE_FMM3D=1

On Linux, $(MagTense)/external/FMM3D/local must be on LD_LIBRARY_PATH when building. USE_FMM3D=1 is what compiles the FMM source and activates the use_fmm flag.

Optimization: persistent tree structure

In micromagnetic simulations the spatial distribution of cells is static throughout the simulation. To exploit this, MagTense uses a magtense-local tree structure that caches the octree setup between consecutive calls to the solver. By reusing the tree, the cost of re-partitioning space at every time step is eliminated.

Note

MagTense uses a fully grown (uniform) tree, ifunif = 1, which is what lets the cached tree be reused unchanged from call to call.

Near-field evaluation and neighbour tensors

In standard FMM implementations, near-field interactions are handled by a direct point-to-point (P2P) evaluation. MagTense replaces this by the high-precision analytical demagnetization tensors for all near-field interactions:

  1. Neighbour identification: based on List 1 from the FMM tree creation, MagTense identifies neighbour pairs, i.e. cells within the same or adjacent leaf nodes.

  2. Sparse neighbour tensor: a sparse tensor structure is created to map these neighbour interactions.

  3. Analytical calculation: the exact analytical demagnetization tensor is evaluated for every neighbour pair.

  4. Sparse matrix storage: the values are converted into a sparse matrix. On CPU this is an Intel MKL sparse matrix; on GPU it is stored persistently in global memory for CUDA evaluation at each time step.

The macrogeometry and sample Sample shape correction are applied on the FMM path as well, so switching to FMM does not change those terms.

FMM input variables

Python

Matlab

Type

Description

use_fmm

use_fmm

int

1 to use the FMM demagnetization path, 0 for the dense analytical tensor. Default 0.

fmm_eps

fmm_eps

float

Requested accuracy, which controls the exponential order of the plane-wave expansion. Default 1e-4.

fmm_nterms

fmm_nterms

int

Multipole expansion order. A negative value (default -1) derives the order from fmm_eps during the tree build.

ifunif

ifunif

int

Tree type. MagTense uses the uniform tree, 1.

nlmin

nlmin

int

Minimum level of the octree hierarchy. Default 1.

nlmax

nlmax

int

Maximum level of the octree hierarchy, which for the uniform tree is its depth. Default 5.

allow_fmm_short_circuit

fmm_short

int

1 to fall back to the direct calculation for small problems, 0 to force FMM. Default 1.

fmm_min_n

fmm_min_n

int

Cell count below which FMM is disabled when the short circuit is allowed. Default 20000.

When the short circuit triggers, the solver reports MagTense: problem smaller than fmm_min_n - disabling FMM and using the full demag tensor and continues with the dense tensor. The test is made before the octree is built, so a small or effectively one-dimensional geometry never reaches the tree construction.

The FMM path works with rectangular-prism cells, i.e. the uniform and unstructuredPrisms grid types, taking the cell dimensions from the uniform-grid spacings dx, dy and dz or from the per-cell grid_abc of an unstructured prism grid.

FMM Python example

problem.use_fmm = 1
problem.fmm_eps = 1e-4
problem.fmm_nterms = 12
problem.ifunif = 1
problem.nlmin = 1
problem.nlmax = 2
problem.allow_fmm_short_circuit = 1
problem.fmm_min_n = 20000

result = problem.run_simulation(
    t_end=t_end, nt=nt, fct_h_ext=h_ext_fct, nt_h_ext=nt_h_ext
)

FMM Matlab example

problem.use_fmm    = int32(1);
problem.fmm_eps    = 1e-4;
problem.fmm_nterms = int32(12);
problem.ifunif     = int32(1);
problem.nlmin      = int32(1);
problem.nlmax      = int32(2);
problem.fmm_short  = int32(1);
problem.fmm_min_n  = int32(20000);