Numerics, stability, and performance

Vectorized corner evaluation

For each magnet, Microcubed evaluates all eight corner contributions together using NumPy arrays. In a local benchmark with 10,000 evaluation points, this reduced execution time relative to a Python loop over the corners as follows:

Quantity

Corner loop

Vectorized

Speed-up

Bfield

7.49 ms

4.09 ms

1.83×

dBfield

16.80 ms

7.85 ms

2.14×

These values are not a hardware-independent performance guarantee. They record the scale and setup of one benchmark; the CPU, NumPy version, array layout, and point distribution all affect the result.

Stable evaluation on extended edge lines

The individual terms in the analytical corner formulas contain expressions such as \(\log(r+z)\). On a negatively extended edge line, two terms can tend to \(-\infty\) although their difference remains finite. Microcubed evaluates such logarithms pairwise as a stable logarithm of a quotient.

At the same exceptional positions, the analytical gradient can contain removable 0/0 forms. Non-finite columns outside the magnet are replaced locally by a symmetric finite difference of the stable field implementation. Regular points continue to use the analytical derivatives.

Result cache

Arrangement.Bfield and Arrangement.dBfield use an LRU cache holding up to 20 point arrays. A cache key includes the array shape, data type, and a SHA-256 digest of its contents.

This is useful when exactly the same points are evaluated repeatedly, for example while redrawing a plot. For a single small calculation, hashing the input adds some overhead.

Summing many magnets

An arrangement uses linear superposition:

\[ \mathbf B_\mathrm{total}(\mathbf r) =\sum_{m=1}^{N_m}\mathbf B_m(\mathbf r). \]

Execution time therefore scales approximately with \(N_mN_p\), the number of magnets times the number of points. For very large problems, consider:

  • reducing the sampling-grid resolution;

  • evaluating only the required spatial region;

  • using coarser magnet segments for non-cuboidal bodies;

  • using the integrated Rust backend for parallel calculation;

  • reusing identical point arrays to benefit from caching; and

  • processing the points in chunks when memory is limited.

Memory use and chunking

Vectorization creates temporary arrays spanning eight corners and all evaluation points. dBfield requires more intermediate arrays than Bfield. For millions of points, process the data in chunks:

import numpy as np


def field_in_chunks(source, points, chunk_size=100_000):
    return np.hstack(
        [source.Bfield(points[:, start : start + chunk_size]) for start in range(0, points.shape[1], chunk_size)]
    )

Convergence checks for scientific use

Publication-quality calculations should include at least the following convergence checks:

  1. Sampling resolution: refine the plotting or measurement grid.

  2. Geometry segmentation: reduce dx for non-cuboidal bodies.

  3. Surface distance: report errors as a function of distance from the magnet surface.

  4. Gradients: compare the analytical gradient with finite differences at several step sizes.

  5. Reference solver: halve the OOMMF cell size at least twice and estimate the observed convergence order.

A single favorable error metric is not a substitute for these studies.