Skip to content

For tracking mumax3 simulations in Barry Costanzi's Lab.

Notifications You must be signed in to change notification settings

ruppec/BarrysLabSimulations

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Basics of mumax3

Helpful Links

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 $1$ nanometer $=$ $1*10-9$ meters.

// 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 $128 × 128 × 2$ cells, and compute the appropriate size of the cells to fit our desired geometry.

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 $\leq$ the exchange length. Ideally they would be less than half. The exchange length for permalloy is $5.3 \mathrm{nm}$.

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 $7$-smooth numbers), but the smaller the better. For our example we use $128=2^7$. If you’re wondering why this occurs read Appendix A.

//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 $1/2$.

//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:

  1. Stops simulation time t
  2. Turns off thermal excitation
  3. Computes the gradient of the total energy and performs a steepest descent algorithm to step toward an energy minimum
  4. We stop iterating once the maximum of the magnitudes of magnetization change dm of the past $n$ steps is less than MinimizerStop (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)

  1. Stops simulation time t
  2. Turns off thermal excitation
  3. Minimizes the energy (somehow?) using the LLG equation without the precession term, stopping when it hits a noise floor.
  4. 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)
}

How to run your own simulation using Git

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 like simulation.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.

Basics of coding in mumax3

You will need to define your:

  • x, y, and z lengths
  • SetGridsize
  • 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

How to run a Mumax3 file

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.

Convert .ovf files to .png and .csv

  • 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

Looking through .png files

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:

./vortex.png

  • 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

Making Mathematica plots

Mathematica programs use the .csv files. Thus, you will need to use the above conversion method to convert your ovf files into csvs.

  1. Open a Mathematica notebook called xy hysteresis amr_BC_v3.nb
  2. Execute all the lines under “Needed Functions”to ensure that the functions are in memory
  3. If you want to just run the program for a single simulation, follow the instructions/example under “Actual running of the code”
  4. If you want to run the program sequentially for multiple simulations, follow the instructions under “Analyzing multiple files in succession”
  5. The MMA notebook should output a labeled image of the AMR sweeps, along with a csv file with the raw AMR vs H data.
  6. 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.

Making Mathematica insets

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)

Backing up to Google Drive

  1. Run Compressor.bat
  2. This will make a zip of all .out folders not on the google drive and put them in the Simulation Archive Folder

Overview: General Workflow

  1. 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)
  2. Save (or rename) the file with the .mx3 extension (not strictly necessary)
  3. From the command prompt, navigate to where filename is stored, then input mumax3 filename.mx3 to run the simulation
  4. This generates all the ovf files and the table.txt file, which contain all the relevant info
  5. Run the *mumax_convert.bat *batch file in the directory containing the ovf files to generate csv files and images of your data.
  6. Run the MMA file to scrape through the csv files and generate AMR vs field data
  7. Run the MMA file to make insets with magnetization directions
  8. Run Compressor.bat to backup simulations

Our Tech Stack

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].

What is this document?

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.

Tasks

TODO Find the original source and make this into a clear citation

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.

TODO Talk to Barry about the corner-cutting code

and whether to keep it in the template, this might be something we could delegate to seperate git branch.

TODO Get code highlighting for html or latex output working?

would be cool for doing demos or making literature.

TODO Review edge roughness procedure

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.

TODO Why are we setting minimizerStop?

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.

TODO Test out relax() and minimize()

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.

TODO Consult code of mumax to determine exactly what relax() and minimize() are doing.

TODO Come up with a naming scheme for branches in this repository.

TODO Automate mumax running and then committing to a branch.

TODO Change initial state from vortex to uniform slightly diagonal

TODO Change the way that Jenkins communicates with Github to not use my credentials

TODO Investigate Claim about ThermSeed().

We seem to claim that ThermSeed() with a large value will make the simulation take a long time. That seems very dubious.

TODO Investigate claim about dimensions being odd giving CURAND error

Appendix A

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.

TODO Turn this appendix into a footnote?

About

For tracking mumax3 simulations in Barry Costanzi's Lab.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published