feeLLGood – finite element LLG object oriented development

feeLLGood – Reference

In order to perform a micromagnetic simulation with feeLLGood, you need two files:

  1. A mesh of the object you want to simulate, which should be in the MSH format of the GMSH mesh generator
  2. a configuration file with all the settings for the simulation, formatted in YAML.

In the MSH format, volume and surface regions are identified by both a three-digit numeric index and an optional name. FeeLLGood identifies the regions by their names. Thus, it is essential that all the regions in the supplied mesh are named.

The structure of the configuration file, and the meaning of the individual settings are documented in this page.

Program invocation

When invoked with the option -h or --help, feeLLGood displays a short help message:

$ feellgood --help
Usage: feellgood [options] settings_file
  -h --help            display short help and exit
  -V --version         display version information and exit
     --print-defaults  print default settings and exit
     --verify          verify a settings file and exit
  -v --verbose         enable verbose mode
     --seed            set random seed

On first use, the most useful option is --print-defaults. When invoked with this option, feeLLGood prints its default settings on its standard output, in the format it expects from its configuration file. This can be saved to a file in order to serve as a template:

$ feellgood --print-defaults > settings.yml

The resulting file is in YAML format. It has lots of comments (everything after a # sign) documenting the file structure and the meaning of the individual settings. With the comments stripped, the beginning of file looks like this:

  directory: .
  evol_time_step: 5e-13
  final_time: 1e-10
    - t
    - <Mx>
    - <My>
    - <Mz>
    - E_ex
    - E_demag
    - E_zeeman
    - E_tot

Edit this file to match the simulation you want to perform. You can remove the existing comments and add your own. You can also remove all the settings that you intend to leave at their default values. When done, you can ask feeLLGood to check the validity of your edited configuration. FeeLLGood will then merge your file with its own defaults and print the resulting complete configuration:

$ feellgood --verify settings.yml
  directory: .
  file_basename: my-simulation
  evol_time_step: 2e-12

If everything looks as you expect, you can then start the simulation by calling feeLLGood with the name of the configuration file as its only argument:

$ feellgood settings.yml

You may also use the option --verbose (or its alias -v) to enable verbose mode. In this mode, feeLLGood prints lots of information on the running simulation. It is useful when finely tuning the simulation parameters, and for getting timing data. Without this option, the program provides much less feedback.

As it starts, feeLLGood prints a randomly chosen number it uses to seed its pseudo-random number generator. If you need to reproduce a previous run exactly, down to the rounding errors, you may run feeLLGood again with the option --seed followed by the seed used in the run you want to reproduce.

If you are generating the configuration settings programmatically, you may want to provide them to feeLLGood without writing them to a file. This can be achieved by using “-” (an ASCII hyphen) as the name of the configuration file, which will be interpreted as “standard input”. You can then pipe the settings to feeLLGood.

Configuration file

There are several ways of creating the configuration file:

The examples directory contains some scripts showing how to use the settingsMaker.py module.

The configuration file has a tree-like structure, with multiple sub-trees (henceforth called “sections”) holding the simulation parameters. As an example, an excerpt of the file may look like this:

  directory: simulation-outputs
  filename: ellipsoid.msh
  length_unit: 1e-10
      Ae: 1e-11
      Js: 1

This requests a simulation of the object described by the mesh ellipsoid.msh, with coordinates in ångströms. There is a single volume region named “ellipsoid_volume”, with an exchange constant of 10-11 J/m and a magnetization of 1 T/µ0. There is also a single surface region, named “ellipsoid_surface”. The output files will be stored in the directory simulation-outputs.

The following sections describe all the available parameters. In the sections names, the syntax “foo.bar” means “parameter "bar" of section "foo".” Items within chevrons (like <region_name>) are meant to be replaced (here: by the identifier of a region).


This section defines what data will be saved by feeLLGood, and in which files.


String holding the name of the directory where the files with the simulation results will be written. The default value (namely “.”) means the working directory from where the feeLLGood process is started.

If the directory does not exist, feeLLGood will create it.


String with the base name used to create the output file names. feeLLGood will generate the following files:

If this is missing or empty, it defaults to the name of the mesh file, with the directory components and the file extension (if any) removed.


Number. The global quantities listed in the array outputs.evol_columns will be saved to the evolution file on this time step, in seconds. This is different from the integration time step, which is set adaptively and may be smaller than outputs.evol_time_step.


Number. The ending time of the simulation, in seconds. The start time is \(t = 0\).


Array of strings. Defines what columns of data are written in the evolution file. Defaults to:

- t
- <Mx>
- <My>
- <Mz>
- E_ex
- E_demag
- E_zeeman
- E_tot

The available columns are:

Keyword Physical meaning
"iter" Iteration
"t" Time
"dt" Time increment
"max_dm" Maximum of the variation of the magnetization
"<Mx>" Average value of Mx
"<My>" Average value of My
"<Mz>" Average value of Mz
"<dMx/dt>" Average value of speed of Mx
"<dMy/dt>" Average value of speed of My
"<dMz/dt>" Average value of speed of Mz
"E_ex" Exchange energy
"E_aniso" Anisotropy energy
"E_demag" Demagnetizing energy
"E_zeeman" Zeeman energy
"E_tot" Total energy
"Hx" Applied field Hx
"Hy" Applied field Hy
"Hz" Applied field Hz

The columns of the evolution file will be in the order of the outputs.evol_columns array.


Either an integer or false. If this is an integer, every outputs.mag_config_every time steps (as defined in outputs.evol_time_step), the magnetization configuration will be saved to a text file with the .sol extension. The first line of the file is of the form ## time: <time_in_seconds>. The rest is tab-separated numbers in 5 columns:

Beware that a massive amount of data may be generated if this value is too small.

If outputs.mag_config_every is false, the magnetization configuration will never be saved.


This section keeps all the information relative to the tetrahedral mesh used by the finite element solver.


String with the full name of the mesh file. It must be first order tetrahedrons and triangles, and format .msh either text or binary.


Number. Value, in meters, of the length unit used in the mesh file.

Beware that some versions of GMSH, when dealing with very small coordinates, fail to write enough significant digits to the output file. For this reason, it is recommended to build the mesh using nanometers, in which case the length unit is 1e-9.


This section and the next one (mesh.surface_regions) define the material parameters. The regions are defined in the mesh file, and are identified by names.


Number. Exchange constant, in J/m.


Number. Magnetization, in T/µ0.


Number. Second order magnetocrystalline anisotropy constant in J/m3.


Array of 3 numbers. Unit vector along the anisotropy axis.

The second order anisotropy energy density is \(E/V = -K (\mathbf{m}\cdot\mathbf{u}_k)^2\).


Number. Cubic magnetocrystalline anisotropy constant, in J/m3.

mesh.volume_regions.<region_name>.ex, .ey, and .ez

Arrays of 3 numbers. Unit vectors along the principal directions of the cubic anisotropy.


ex: [1, 0, 0]
ey: [0, 1, 0]
ez: [0, 0, 1]

The cubic anisotropy energy density is \(E/V = K_3 (\alpha^2\beta^2 + \beta^2\gamma^2 + \gamma^2\alpha^2)\), where \(\mathbf{m}\) is the reduced magnetization, \(\alpha = \mathbf{m}\cdot\mathbf{e}_x\), \(\beta = \mathbf{m}\cdot\mathbf{e}_y\) and \(\gamma = \mathbf{m}\cdot\mathbf{e}_z\).


Number. Dimensionless damping parameter.


Boolean. If true, the surface charges will be removed when computing their contribution to the demagnetizing field. This can be used to fake very long media.


Number. Second order surface anisotropy constant, in J/m2.


Array of 3 numbers. Unit vector along the surface anisotropy axis.


Initial magnetization configuration. It may be provided in three different ways:

  1. As the name of a file, in the format of feeLLGood's “.sol” output files:

    initial_magnetization: my_initial_mag_field.sol
  2. As an array of three analytic expressions for the x, y and z components of the magnetization:

    initial_magnetization: [1-(z/50e-9)**2/2, 0, tanh(z/50e-9)]

    The independent variables of these expressions are the Cartesian coordinates (x, y, z). The coordinate system is the one used in the mesh file, but scaled such that x, y and z are in meters.

    The expressions must be enclosed in double quotes (") if they contain commas, otherwise the quotes are optional. Note that, if using the JSON format, quotes are mandatory save for constant expressions provided as plain numbers:

    "initial_magnetization": ["1-(z/50e-9)**2/2", 0, "tanh(z/50e-9)"],
  3. As a JavaScript function expression taking three numeric parameters (the x, y and z coordinates) and returning an array of three numbers. YAML multiline strings provide a convenient syntax for writing such a function:

    initial_magnetization: |
      function(x, y, z) {
        var delta = 50e-9,
            u = z / delta;
        return [1 - u**2/2, 0, tanh(u)];

If using an array of expressions or a JavaScript function, the magnetization vector need not be normalized: feeLLGood will normalize it while evaluating the expressions. Beware that the vector must never be zero.

See Duktape syntax for how to write expressions and functions.


Optional section, to be provided if you need to recenter the whole magnetization vector field. If enabled, the whole magnetization distribution will be translated along the X, Y or Z direction, in order to follow a domain wall and simulate its motion in a sample that is infinite along that direction.

Recentering should only be enabled on meshes built by extrusion, as it relies on translational invariance.


Boolean. Whether to enable recentering.


String. The direction of the recentering. It musts be uppercase "X", "Y" or "Z".


Number. If \(|avg(m_{direction})| \ge |threshold|\) is true, then feellgood will recenter. Threshold value should be choosen carefully to avoid the situation when a domain wall is affected by the edge of the mesh along the recentering direction. If the domain wall is highly distorted there is a risk that the recentering procedure fails, because of the wrong estimation of the translation vector to apply on the magnetization vector field.


Applied magnetic field. It can be provided in two forms:

  1. As an array of three analytic expressions for the x, y and z components of the field:

    Bext: [0.6*cos(5e8*t), 0.6*sin(5e8*t), 0]

    The independent variable of these expressions is the time t, in seconds.

    The expressions may be enclosed in double quotes ("). As for initial_magnetization, the quotes are mandatory for expressions containing commas and, in JSON format, for anything but plain numbers.

  2. As a JavaScript function expression taking one numeric parameter (the time t, in seconds) and returning an array of three numbers:

    Bext: |
      function(t) {
        var a = 0.6,  // amplitude = 0.6 T
            omega = 5e8;
        return [a * cos(omega*t), a * sin(omega*t), 0];

See Duktape syntax for how to write expressions and functions.


This section defines the parameters used to simulate a spin transfer torque. This feature is a work in progress, not ready for general use. Furthermore, the set of user-defined parameters is not settled yet. For this reason, the contents of the section is not yet documented.


Integer. Number of threads used by ScalFMM to compute the demagnetizing field.

The optimal value is hard to guess, as it depends both on the computer being used (number of cores and hardware threads, cache hierarchy) and the problem being solved (mostly the number of nodes in the mesh). We recommend trying different values, keeping in mind that the optimum may be significantly smaller than the number of available hardware threads (given by the output of the command getconf _NPROCESSORS_ONLN).

If this parameter is missing or non-positive, it defaults to the number of available physical threads.


Section for configuring the solver of the finite element magnetization problem. The solver uses a bicgstab stabilized biconjugate gradient algorithm, with an Incomplete Lower Upper (ILU) preconditioner. Advanced users may want to tune the behaviour of the solver through its preconditioner. Depending on the nature of the mesh and the distance from the initial guess of the magnetization distribution to the solution, it might be interesting to tune both ILU_tolerance and ILU_fill_factor. As a rule of thumb, the smaller ILU_tolerance, and the bigger ILU_fill_factor, the more precise is the LU factorization, leading to less bicgstab iterations. These parameters do not affect the precision of the result of the bicgstab solver, which is fixed by the parameter tolerance.


Integer. Number of threads the solver will use to perform the matrix assembly.

See the comment under demagnetizing_field_solver.nb_threads.


Integer. Maximum number of iterations to perform at each time-step.


Number. Numeric tolerance of the bicgstab algorithm, used as an iteration stopping criterion.


Number. ILU_tolerance is a relative threshold: any coefficient smaller than this is discarded in the approximated LU factorization. The value zero means complete LU factorization, which is not desirable for a preconditioner. See the Eigen documentation for more information.


Integer. Number of coefficients per row to keep in the ILU factorization. See the Eigen documentation for more information.


Section holding the parameters relative to the time integration of the LLG equation.


Number. Maximum allowed value for \(du\), the variation of the normalized magnetization \(u\) in a time step. If max(du) is too big, the simulations are probably very altered by artefacts, since the magnetization may vary locally too fast.

time_integration.min(dt) and .max(dt)

Numbers. Minimum and maximum allowed value for the integration time step dt. When the time-integrator is not satisfying the conditions on du, the time step is halved until it reaches an acceptable du, or the minimum min(dt) value.

Duktape syntax

Both the initial magnetization and the time-dependent applied field can be provided as either a set of analytic expressions, or as a JavaScript function literal. FeeLLGood uses the Duktape JavaScript engine to interpret them. Duktape supports the ECMAScript 5.1 language syntax. Though it does have a few post-ES5 features, most modern JavaScript constructs (let, class, arrow functions…) are not supported.

For convenience, feeLLGood copies all the members of the Math object to the global object, meaning they can be accessed without the Math. prefix. It also adds some common functions missing from ECMAScript 5. The main primaries for building numeric expressions are: