Setting up a micromagnetic problem
A micromagnetic problem is defined by a single problem object that is filled
with parameters and then handed to the Fortran solver. The Matlab and the
Python interfaces expose the same set of parameters, but they use slightly
different names; the naming used by Fortran is dictated by the subroutine
getProblemFieldnames in MagTenseMicroMagIO.f90.
The authoritative lists of parameters are
Matlab: DefaultMicroMagProblem.m
Python: micromag.py
and a side-by-side listing is given in Micromagnetic parameter reference.
Matlab problem setup
In Matlab a problem is created with DefaultMicroMagProblem(nx,ny,nz), which
returns an object with all parameters set to sensible defaults for a uniform
grid with nx*ny*nz cells. Parameters are then overwritten, and a number of
set... helper methods map human-readable names onto the integer flags that
Fortran expects. Finally the object is converted to a plain struct and passed
to the MEX-file:
addpath('MagTense/matlab/MEX_files');
addpath('MagTense/matlab/util');
mu0 = 4*pi*1e-7;
resolution = [36,9,1];
problem = DefaultMicroMagProblem( resolution(1), resolution(2), resolution(3) );
problem.grid_L = [500e-9,125e-9,3e-9]; % m
% Solver and hardware options
problem = problem.setMicroMagSolver( 'Dynamic' );
problem = problem.setUseCuda( true );
problem = problem.setUseCVODE( false );
% Material parameters
problem.A0 = 1.3e-11; % J/m
problem.Ms = 8e5*ones(prod(resolution),1); % A/m
problem.K0 = zeros(prod(resolution),1); % J/m^3
problem.alpha = 4.42e3; % m/(A s)
problem.gamma = 2.21e5; % m/(A s)
% Initial state, normalised internally if it is not already
problem.m0(:,1) = 1/sqrt(3);
problem.m0(:,2) = 1/sqrt(3);
problem.m0(:,3) = 1/sqrt(3);
% Output times and the applied field as a function of time
problem = problem.setTime( linspace(0,1e-9,200) );
HystDir = 1/mu0*[-24.6,4.3,0]/1000;
problem = problem.setHext( @(t) (t>-1)'.*HystDir, linspace(0,1e-9,2000) );
% Solve
solution = struct();
solution = problem.MagTenseLandauLifshitzSolver_mex( struct(problem), solution );
The struct(problem) call performs a final consistency check before the data
is handed to Fortran: scalar values of Ms, A0, K0, K1 and
K2 are expanded to one value per cell, and m0 is normalised to unit
length. It also prints an estimate of the memory needed by the demagnetization
tensor.
problem.MagTenseLandauLifshitzSolver_mex is a function handle that
setUseCuda sets, pointing either at MagTenseLandauLifshitzSolver_mex or
at MagTenseLandauLifshitzSolverNoCUDA_mex.
Note
setUseCuda is what selects the MEX-file, so call it once - with
false for a CPU run - before invoking the solver through
problem.MagTenseLandauLifshitzSolver_mex. The MEX-file can also be
called directly by name.
Python problem setup
In Python the problem is a MicromagProblem object. Most parameters are
constructor arguments, the remaining ones are plain attributes that can be
assigned after construction. The applied field is passed as a callable to the
run method rather than being stored on the problem:
import numpy as np
from magtense.micromag import MicromagProblem
mu0 = 4 * np.pi * 1e-7
res = (36, 9, 1)
problem = MicromagProblem(
res=res,
grid_L=[500e-9, 125e-9, 3e-9],
grid_type="uniform",
solver="dynamic",
m0=1 / np.sqrt(3),
A0=1.3e-11,
Ms=8e5,
K0=0.0,
alpha=4.42e3,
gamma=2.21e5,
cuda=False,
cvode=False,
)
h_ext = np.array([-24.6, 4.3, 0]) / 1000 / mu0
def h_ext_fct(t):
# Constant in time; must return an (nt_h_ext, 3) array
return np.outer(np.ones_like(t), h_ext)
t_out, M_out, pts, H_exc, H_ext, H_dem, H_ani, *_ = problem.run_simulation(
t_end=1e-9, nt=200, fct_h_ext=h_ext_fct, nt_h_ext=2000
)
m0 accepts a scalar (all components set to that value), an (ntot,3)
array, or None, in which case a random unit vector is drawn for every cell.
As in Matlab, m0 is normalised to unit length on assignment.
The three run methods are
run_simulation(t_end, nt, fct_h_ext, nt_h_ext)- a single solve, used for both the dynamic and the explicit solver;run_hysteresis(H_ext)- a predefined sequence of applied fields, see Hysteresis simulations;run_hysteresis_adaptive(...)- a field sweep where the solver picks the field steps itself, see Adaptive hysteresis.
Units and conventions
Quantity |
Unit |
Comment |
|---|---|---|
Lengths, grid size |
m |
|
Saturation magnetization \(M_s\) |
A/m |
divide a value in tesla by \(\mu_0\) |
Applied and effective fields |
A/m |
|
Exchange constant \(A_0\) |
J/m |
often written \(A_\mathrm{ex}\) |
Anisotropy constants \(K_0, K_1, K_2\) |
J/m3 |
|
Damping \(\alpha\), precession \(\gamma\) |
m/(A s) |
Landau-Lifshitz form, see The equation that is solved |
Time |
s |
|
Temperature |
K |
The returned magnetization M is the reduced magnetization
\(\mathbf{m}\), i.e. it is normalised to unit length and must be multiplied
by \(M_s\) to obtain A/m.