Before beginning with mumax3, it is probably most useful to watch through the mumax3 workshop, which gives a very good overview of what mumax can do and how to make it work. You don’t have to understand every detail that comes up, of course.
- mumax3 workshop
- https://mumax.ugent.be/mumax3-workshop/
- Examples
- https://mumax.github.io/examples.html
- All available functions
- http://mumax.github.io/api.html
- Setting up your code and definitions
- https://mumax.github.io/api.html
- the mumax3 forum
- https://groups.google.com/g/mumax2
Breakdown of the MUMAX TEMPLATE
In this section I have broken up the template file into several blocks of code with explanation in between. The contents of the template file are directly generated from this documentation so you can assume that what you read in the blocks is exactly what is in the template, in the order in which it appears here.
// PLEASE USE THIS TEMPLATE WHEN BEGINNING A NEW FIELD SWEEP SIMULATION, THIS
// WILL ENSURE THAT OUR DATA PROCESSING PROGRAMS WORK PROPERLY WITH THE OUTPUT
// YOU GENERATE
First we specify the dimensions of our simulation in meters. Remember that
// Sizes in meters
x := 170e-9
y := 170e-9
z := 10e-9
xGridsize := 128
yGridsize := 128
zGridSize := 2
SetGridsize(xGridsize, yGridsize, zGridsize)
SetCellsize(x/xGridsize, y/yGridsize, z/zGridsize)
randSeed(2)
The grid is mumax’s way of discretizing the problem. We chop our simulation into
a lattice of cuboid cells. In the example above we define a grid of
For the purposes of the simulation we pretend that the moment is uniform within each cell of the grid. Most other material properties are assigned per-cell as you’ll see later.
Note: The dimensions of the grid can have a significant impact on the runtime of
the simulation. Obviously making a grid with fewer cells results in a faster
run, but to keep our simulations physical we need, at a minimum, for the
dimensions of the cells to be
Note: It is important to choose grid dimensions whose prime factors are
small. The developers reccomend only using dimensions where the largest prime
factor is at most 7 (so-called
//Permalloy Properties
Msat = 800e3
Aex = 13e-12
alpha = 0.007
These are material parameters that we are assigning to the entire grid. If we wanted to we could assign different parameter values to individual cells. For those interested, the prodedure is covered in the “Regions” section of https://mumax.github.io/examples.html.
//Corner
//EdgeSmooth = 8
sq := rect(x, y)
//THE FOLLOWING CORNER CODE MAY NEED REVISING, HAS NOT BEEN TESTED SINCE OTHER SUBSTANTIAL CHANGES 9/8/2022
//cornerDiameter := 100e-9
//cornerCircle := cylinder(cornerDiameter, cornerDiameter)
//andSquare := rect(cornerDiameter, cornerDiameter).transl(cornerDiameter/2, cornerDiameter/2, 0)
//quarterCircle := cornerCircle.intersect(andSquare)
//subSquare := rect(cornerDiameter/2, cornerDiameter/2).transl(cornerDiameter/4, cornerDiameter/4, 0)
//corner := subSquare.sub(quarterCircle)
//topRight := corner.transl(xLength/2 - cornerDiameter/2, yLength/2 - cornerDiameter/2, 0)
//topLeft := topRight.rotz(90*pi/180)
//bottomLeft := topRight.rotz(180*pi/180)
//bottomRight := topRight.rotz(270*pi/180)
//roundedRect := rect(xLength, yLength).sub(topRight).sub(topLeft).sub(bottomLeft).sub(bottomRight)
The only part of this section that is currently being used is where we define sq
to be a rectangular geometry spanning our grid. In the block below we augment
it, adding roughness to the edge.
//Rough Edges
cuttersize := 5e-9
//The following line makes sure the "cutter" for the edge roughness is an integer number of cells large
cutterCell:=ceil(cuttersize/min(x/xGridsize, y/yGridsize))*min(x/xGridsize, y/yGridsize)
print(min(x/xGridsize, y/yGridsize))
print(cutterCell)
cutterRect := rect(cutterCell, cutterCell)
//Top
for i := 0.0; i <= x/(cutterCell); i++{
if rand()<0.5 {
sq = sq.sub(cutterRect.transl(i * cutterCell - x/2, y/2 - cutterCell/2, 0))
}
}
//Bottom
for i := 0.0; i <= x/(cutterCell); i++{
if rand()<0.5 {
sq = sq.sub(cutterRect.transl(i * cutterCell - x/2, -y/2 + cutterCell/2, 0))
}
}
//Left
for i := 0.0; i <= x/(cutterCell); i++{
if rand()<0.5 {
sq = sq.sub(cutterRect.transl(-x/2 + cutterCell/2, i * cutterCell - y/2,0))
}
}
//Right
for i := 0.0; i <= x/(cutterCell); i++{
if rand()<0.5 {
sq = sq.sub(cutterRect.transl(x/2 - cutterCell/2, i * cutterCell - y/2,0))
}
}
setgeom(sq)
saveas(geom, "DotShape")
We generate a square that is the size of an integer number of cells, then go
around the edges of our simulation taking out cell-size chunks of our geometry
with a probability of
//Initial Maznetization
m = vortex(1,1)
relax()
Here we set an initial configuration of a vortex state, then use the relax()
function to settle into a stable local minimum that is nearby.
//Minimization parameters
MinimizerStop = 1e-6
We don’t use the minimize()
function in this template so this piece of code has
no effect on this simulation. (Not to mention that the default value of this
variable is already 1e-6
as discussed below).
Instead we use the relax()
function whose analogous parameter is
RelaxTorqueThreshold
. One should be mindful of changing the value of this
however. The API states that it is by default at -1
which says ”relax()
will
stop when the average torque is steady or increasing.”
Discussion of the minimize()
function from the author of the function can be
found here. But to paraphrase, the minimize()
function:
- Stops simulation time
t
- Turns off thermal excitation
- Computes the gradient of the total energy and performs a steepest descent algorithm to step toward an energy minimum
- We stop iterating once the maximum of the magnitudes of magnetization change
dm
of the past$n$ steps is less thanMinimizerStop
(where$n=$ MinimizerSamples
).
Note: The default value for MinimizerStop
is 1e-6
and the default value for
MinimizerSamples
is 10
.
The paper that outlines this model (doi:10.1063/1.4862839) demonstrates a case
in which this method is roughly 2x as fast as a finite difference method. A
poster here claims that the minimize()
function could be “potentially orders of
magnitude [faster]”, but does not give a source or further explanation.
Limitations of this method are suggested in the post above from the author, and from the examples page of the mumax website. Specifically, they include a difficulty with accurate handling of “stiff” states (ie. vortices), and states of high energy (ie. random magnetization).
The relax()
function: (according to this post)
- Stops simulation time
t
- Turns off thermal excitation
- Minimizes the energy (somehow?) using the LLG equation without the precession term, stopping when it hits a noise floor.
- Minimizes the torque (which is said to be more resistant to numerical noise).
However this description is puzzling to me and leaves out significant details
that would differentiate the relax()
and minimize()
method.
To summarise:
- Use
minimize()
when you want something fast or you’re dealing with low energies. - Use
relax()
when you want something accurate or you’re dealing with high energies, vortices, and random magnetization.
//Setting the following quantity to zero allows the Dt to change dynamically to minimize error while maximizing the time step
FixDt =0
The default for FixDt
is 0 so this line currently has no effect on the
simulation.
//Temperature Settings
Temp = 293 // in kelvin
TableAdd(Temp)
The temperature setting determines the thermal excitations. The TableAdd()
function adds a value to our output table. So then when we run tablesave()
we
write those values to our output table as they are at that point in time.
//Field Sweep Settings
Bmax := 70.0e-3
Bstep := 5.0e-4
TableAdd(B_ext)
TableAdd(E_therm)
TableAdd(E_Zeeman)
TableAdd(E_demag)
TableAdd(E_exch)
TableAdd(E_total)
TableAdd(MaxAngle)
Here we define the radius of our field sweep measured in Tesla. Then below we sweep along the x-axis, then along the y-axis, at an angle to each.
//Field Sweeps
//This initial run step ensures that the system has enough time to relax into a stable state after getting hit with a large change of field
B_ext = vector(-Bmax, -Bmax/50, 0)
run(6e-9)
for B := -Bmax; B <= Bmax; B += Bstep {
B_ext = vector(B, B/50, 0)
run(1e-9)
tablesave()
save(m)
}
for B := Bmax; B >= -Bmax; B -= Bstep {
B_ext = vector(B, B/50, 0)
run(1e-9)
tablesave()
save(m)
}
//This run step ensures that the system has enough time to relax into a stable state after getting hit with a large change of field
B_ext = vector(-Bmax/50, -Bmax, 0)
run(6e-9)
for B := -Bmax; B <= Bmax; B += Bstep {
B_ext = vector(B/50, B, 0)
run(1e-9)
tablesave()
save(m)
}
for B := Bmax; B >= -Bmax; B -= Bstep {
B_ext = vector(B/50, B, 0)
run(1e-9)
tablesave()
save(m)
}
The purpose of this git repo is to track our simulations in a coherent, human readable way. To that end I’ve outlined guidelines for creating your own simulation files, and saving the results.
- Start a new branch for your simulation and give it a name
-
The name of your branch should be concise and informative. A good example
would be to briefly summarise the changes you plan to make to the template,
the purpose of this simulation, and/or basic parameters that you are changing
like dimensions, material parameters, angle and magnitude of field sweep. An
example might be:
250x5nm_50deg_75G
- Make the changes you want and commit those changes to your branch
-
I suggest copying/moving
MUMAX_TEMPLATE.mx3
to a new file likesimulation.mx3
, then making the edits you want in a text editor. - Run mumax3 on your file
- the output folder should appear in the base folder
of the git repository where your
.mx3
file is. - Perform whatever operations you want on your output
- This likely includes
converting the
.ovf
files into.png
, doing analysis with Mathematica, or making a plot with gnuplot. - Commit
- As with writing a branch name, make your commit messages short but descriptive. This gist gives some guidelines for good commit messages. Here’s an example of the format, taken from there.
Short (72 chars or less) summary More detailed explanatory text. Wrap it to 72 characters. The blank line separating the summary from the body is critical (unless you omit the body entirely). Write your commit message in the imperative: "Fix bug" and not "Fixed bug" or "Fixes bug." This convention matches up with commit messages generated by commands like git merge and git revert. Further paragraphs come after blank lines. - Bullet points are okay, too. - Typically a hyphen or asterisk is used for the bullet, followed by a single space. Use a hanging indent.
The gist contains more tips on writing good messages. It’s a very short read, so I urge you to atleast skim it.
You will need to define your:
x
,y
, andz
lengthsSetGridsize
SetCellsize
- Magnetic saturation field magnitude (
Msat
) - Exchange energy (
Aex
) - Torque/rotational damping coefficient (
alpha
) - and magnetic moment matrix (
m
)
Then relax()
your system. Define the temperature, time step,
maximum magnetic field, magnetic field step, (what’s minimizerstop?), and
add columns to your table output (TableAdd(B_ext), TableAdd(Temp). Now make
for loops that sweep the magnetic field in the direction of your vector
(B_ext), minimize() or run() to find the new magnetization configuration,
save the data to your table, and save(m).
randomMag()
and relax()
between your x-axis and y-axis sweeps. This way no
remnant magnetization from the first sweep will affect the second sweep.
Use ThermSeed()
to create thermal noise. Put in a random number in the argument
of the function; don’t make it too long, otherwise the simulation will
take forever to run.
Attention: Unless you have a lot of experience, please start any field sweep
simulations by renaming and editing the MUMAX_TEMPLATE.mx3
file located
in the C:/Mumax folder on the mumax computer. This will ensure that our
data processing code will work properly with your output.
- Write the code in a text editor (I have been using notepad) and save the file as a .mx3 file.
- This file needs to be in the folder MUMAX/mumaxolder for you to run it
- Sometimes
panic: CURAND_STATUS_LENGTH_NOT_MULTIPLE
error comes up when you use run(). Try running a simulation for side length that’s an even number. Apparently, the program has a random number generator that only takes even inputs. - The minimize() function compiles significantly faster than the relax() function. Run(time) runs the simulation for a given time in seconds, using sensible error settings. High-energy states are best minimized by relax(), and small changes best minimized by minimize(). For example, use relax() to minimize energy prior to sweeps, and use minimize() or run() every field step. 0K sweeps can be minimized with minimize(), but non-zero temperature sweeps appear to require the use of the run() function. We found run(1e-9) to be more useful than any smaller time step (smaller time breaks down about halfway through and gives random magnetizations), although it does take a while to run.
- From mumax3 function overview:
- Relax() tries to evolve the magnetization as closely as possible to the minimum energy state. This function assumes all excitations have been turned off (temperature, electrical current, time-dependent magnetic fields). During relax precession is disabled and the time t does not increase. There is no need to set high damping.
In general it is difficult to be sure the minimum energy state has been truly reached. Hence, relax may occasionally return after the energy has reached a local minimum, a saddle point, or a rather flat valley in the energy landscape.
- Minimize() is like Relax, but uses the conjugate gradient method to
find the energy minimum. It is usually much faster than Relax, but is a bit less robust against divergence. E.g., a random starting configuration can be Relaxed, but may fail with Minimize. Minimize is very well suited for hysteresis calculations, where we are never far away from the ground state.
http://mumax.github.io/api.html
Must be in the same directory as mumax3.exe -> C:\Mumax
- Change simulation file from .txt to .mx3
- This is most easily done with the command:* rename filename.txt filename.mx3*
- The file explorer rename option does not change the file type to mx3 only the name!
- Run simulation with the command: mumax3 filename.mx3
- Task manager will not display cuda gpu usage by default!–change any of the gpu graphs to cuda with the little arrow dropdown.
- Cuda usage should be ~90%
- While the simulation is running, you can monitor it using the GUI
interface by navigating to in a browser (this web address is also printed out in the command line when you run mumax3)
- Mumax will output the simulation data to a folder named filename.out
- Within the folder, it will generate a table of all the quantities that are input to the TableAdd() function in the .mx3 file. The components of local moments at each time step that save(m) is called will be saved as mXXXXXX.ovf, where XXXXXX is a 6-digit number that ascends from 0 as more ovfs are generated.
- You can save a visual representation of the magnetization at a
specific time by typing save(m). Alternatively, if you use the run(time) command, you can use autosave (m, time) for the code to save at regular intervals
- The files are saved as .ovf format, and are named something like
filename000000.ovf.
- In the folder where the .ovf files are stored, run the command
mumax3-convert -png m000001.ovf to convert, for example, file m000001.ovf to a .png image
- You can use the wildcard * to convert multiple files at once. For
example, to convert all the .ovf files in the folder to images, run
mumax3-convert -png ***.ovf
If you only want to convert a subset of
.ovf files, for example those that being with “m” you can run for
example mumax3-convert -png m.ovf*.
- To really streamline things, simply copy the batch file called
mumax_convert.bat into the directory where all the .ovf files are stored, and then run the batch file from that location
You may want to quickly look through the png files to check if they make sense. Here is a key to reading them:
Color scheme of .png mumax3 output:
- Red: right
- Turquoise: left
- Dark Purple: down
- Light Green: up
- You can also view magnetization configurations online by directly
uploading .ovf files to https://mumax.ugent.be/mumax-view/index.html. This is useful for seeing an animation of how the magnetic configuration evolves over time
Mathematica programs use the .csv files. Thus, you will need to use the above conversion method to convert your ovf files into csvs.
- Open a Mathematica notebook called xy hysteresis amr_BC_v3.nb
- Execute all the lines under “Needed Functions”to ensure that the functions are in memory
- If you want to just run the program for a single simulation, follow the instructions/example under “Actual running of the code”
- If you want to run the program sequentially for multiple simulations, follow the instructions under “Analyzing multiple files in succession”
- The MMA notebook should output a labeled image of the AMR sweeps, along with a csv file with the raw AMR vs H data.
- Running the Vector Show Animate Export notebook will generate a gif of the field sweep in the simulation’s folder. You will need to input the simulation’s .out folder.
Run the vectorShow v2.5.nb notebook (for MMA 12; for MMA 11 use vectorShow v2.6_MMA11.nb) to plot the magnetization direction arrows on the dot at a chosen instant. SetDirectory to where your simulation output files are, input the filename for the step you would like to plot (e.g. m000001.csv), play with ListVectorPlot to change how your output picture looks (for example, VectorPoints changes how many arrows are shown per side, and VectorScale changes arrow size; consult Wolfram Documentation for the function for more options)
- Run Compressor.bat
- This will make a zip of all .out folders not on the google drive and put them in the Simulation Archive Folder
- Write a .txt file that contains the code you want mumax to run (likely starting from the _MUMAX_TEMPLATE.mx3 file or another file that started with that file)
- Save (or rename) the file with the .mx3 extension (not strictly necessary)
- From the command prompt, navigate to where filename is stored, then input mumax3 filename.mx3 to run the simulation
- This generates all the ovf files and the table.txt file, which contain all the relevant info
- Run the *mumax_convert.bat *batch file in the directory containing the ovf files to generate csv files and images of your data.
- Run the MMA file to scrape through the csv files and generate AMR vs field data
- Run the MMA file to make insets with magnetization directions
- Run Compressor.bat to backup simulations
We are running a windows10 machine with an NVIDIA GeForce RTX 3080
We are running a Jenkins server for automating simulations. The admin account
for the Jenkins server is labadmin
, with the normal password, and the email is
[email protected]
.
This is .org file, for use in Emacs org-mode. This was chosen as the format
because the original author of this file uses Emacs and wanted to leverage the
power and flexibility afforded by org-mode. One of the functions is that the
MUMAX_TEMPLATE.mx3
file is generated from the code snippets in this document
using org-babel. The keystrokes to do so once you have this document open in
emacs is C-c C-v t or you could type in M-x org-babel-tangle RET. Where M-x is
the x key with the “Meta” key held down (usually the Alt key on PC), and RET is
the enter key. C-c corresponds to Control+C.
Another benefit of using org-mode is that this document can be easily exported to several other formats using the keystrokes C-c C-e. Most notably HTML, but also Markdown. If you cannot see the option to export to Markdown, you may have to start the package by typing M-S-: (require ‘ox-md) RET. Now you should be able to export to markdown. There exists lots of other exporters available for install if you want. For example if you issue M-x package-install RET ox-gfm RET you will install the exporter package for Github Flavored Markdown, which you’d need to start in the same way you started ox-md before.
Ultimately, if you have trouble with these steps but you want to transition this documentation to another format I reccomend using the pandoc software which is built to convert documents between many different formats.
Also, there is discussion in this page (namely around the minimize() function) that reads as a close paraphrase/copying of a comment made on the google group. This language should be removed or a citation should be added.
and whether to keep it in the template, this might be something we could delegate to seperate git branch.
would be cool for doing demos or making literature.
consider changing procedure or at the very least refactoring it. Specifically, it seems like the procedure ends up taking out only half-cell portions. An effort should be made to verify if this is the case. This section is also something that might be better suited to a seperate git branch.
It seems like in the template file we do not use the minimize() function and instead use relax. Why is it being set currently? Maybe this is something that can be mentioned or commented out but it doesn’t do anything in the current template.
Additionally, the analogous parameter relaxTorqueThreshold
is not being set.
In the future we should do some quick tests as to which method is faster and if the methods agree. This should involve changing the parameters to get a feel for their effect.
We seem to claim that ThermSeed()
with a large value will make the simulation
take a long time. That seems very dubious.
Why do we specify grid dimensions that are 7-smooth?
It’s because the main function that mumax performs is dealing with magnetostatics since it’s so long-range. Under the hood mumax is computing a magnetostatic kernel, then convolving it with the simulation to compute magnetostatics. The convolution theorem tells us that a convolution in signal space is equal to a multiplication in frequency space, so a common method of dealing with convolution is applying the FFT, multiplying, then applying the inverse FFT. This is what mumax does, but it uses the Cooley-Tukey algorithm (originally discovered by Gauss) which allows you to break up your DFT into smaller ones corresponding to the prime factors, and there exist good algorithms for computing DFTs of size up to 7.