This page presents a straightforward method for tracking the
motion of a skyrmion across a thin plate, as illustrated in this video
based on the OOMMF tutorial session 3
homework problem:
The key point of the method is the observation that the spins inside the skyrmion bubble point out of the plane of the film (mz>0) while the rest of the spins point into the plane (mz<0). Since the skyrmion is circular, we can estimate the center of the skyrmion by averaging the locations of all spins with mz>0.
The second simulation writes the magnetization spin configuration to disk at simulation time intervals of 50 ps, with file names
tclsh oommf.tcl avf2odt -average space \
-index t ns '$i*0.05' \
-valfunc xpos nm '$vz>0.5 ? $x*1e9 : 0' \
-valfunc ypos nm '$vz>0.5 ? $y*1e9 : 0' \
-valfunc wgt '' '$vz>0.5 ? 1 : 0' \
-defaultvals 0 -headers collapse -truncate 1 -onefile foo-a.odt \
skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-*omf
I've broken the command across several lines for readability, using
the unix backslash end-of-line continuation character
‘\
’. On Windows either merge all the lines
together onto one line, or else replace the backslash characters with
the Windows continuation character ‘^
’. On
Windows you will also need to replace the single quotes with double
quotes throughout. I give now a brief overview of the avf2odt options
used above; see the avf2odt documentation for additional details.
The back end of the command lists all the files we want to
process, namely all of the files output from the simulation.
Each file will correspond to one row in the output table, processed in
the order given on the command line. Glob string matches
(*
and ?
) will be sorted in alphabetical
order. By default avf2odt will print to stderr the name of each file
as it is processed. (This logging can be suppressed with
the ‑v 0
option.)
Moving to the front of the options list, we see
the ‑average
specification. avf2odt condenses data in a
vector field file by computing averages across a sequence of
regions. For example, you can request averages across lines or planes
parallel or perpendicular to coordinate axes to create line profiles
and cross-sectional averages. In this instance we want to average
spins across the 3D volume, so we specify ‑average
space
.
Next we specify what output we want. We want a time index for each
snapshot, so we use ‑index t ns '$i*0.05'
,
where ‑index
indicates values determined by the
sequential processing order of the files. The first two
subfields, t
and ns
, specify the column title
and units (here “t” for time and “ns” for
nanoseconds). The third subfield is a Tcl expr expression for the values
to put into the column, where $i
is the 0-based index of
the file being processed. Our output files are spaced 50 ps apart,
so the expression '$i*0.05'
will convert the file index
number into a time index in nanoseconds. A side note: On unix it is
critical to enclose the expr expression in single quotes, as otherwise
the unix shell will try to perform variable interpolation and wildcard
expansion at the $
and *
characters,
respectively.
The ‑valfunc
items are the key bits in the skyrmion
identification. As in the ‑index
option, the first
two subfields specify the column name and units in the output table, and
the third subfield is a Tcl expr expression for the column values. The
primary variables available in this expression
are $x
, $y
, $z
and
$vx
, $vy
, $vz
representing the
three location coordinates and three field coordinate values at each
point in the file. The Tcl expr expression is evaluated once for each
point in the file, and the average value is output to the table row
corresponding to the file.
The expression '$vz>0.5 ? $x*1e9 : 0'
uses the ternary
operator to check a condition ($vz>0.5
), and if true
returns the the x-coordinate of the point multiplied by 109
(a convenience, to convert from meters to nanometers), and if false
returns 0. In this way we average the x-coordinates of only points
inside the skyrmion, as indicated by having z-component of spin (in
this context mz is $vz
) larger than
0.5.
Two important notes: First, if the skyrmion center were pointing into
the plane instead of out, then the test should
be $vz<-0.5
instead of $vz>0.5
. Second,
if we were processing a magnetization file instead of a spin file, we
would want to compare $vz
to say half the saturation
magnetization instead of 0.5. In particular, if your simulations have
regions where Ms = 0, then you should work with
::Magnetization files instead of ::Spin files because the latter will
have randomly oriented spins in the Ms = 0 regions
which may be difficult to exclude from the averaging process.
There is a similar expression in the next line of the command to
collect the average y-coordinate of points inside the skyrmion,
followed by
‑valfunc wgt '' '$vz>0.5 ? 1 : 0'
. This expr
expression simply tallies the number of points we are counting
inside the skyrmion, so we can properly normalize the results in the
next step.
The remaining options merely request no data table columns other than
the ones we've expressly requested (‑defaultvals
0
), collect all the data together into a single file named
foo‑a.odt (‑headers collapse ‑onefile
foo‑a.odt
), and overwrite foo‑a.odt if it already
exists (‑truncate 1
).
The output produced by this command, stored in the file foo‑a.odt, has this form:
# ODT 1.0 ## Desc: Data from 81 vector field files: skyrmion_example‑init.omf, ... # Columns:\ # t xpos ypos wgt # Units:\ # ns nm nm {} 0.00000000000000 0.603560000000000 0.603560000000000 0.0105200000000000 0.0500000000000000 0.644760000000000 0.603000000000000 0.0104400000000000 0.100000000000000 0.718200000000000 0.627400000000000 0.0107600000000000 0.150000000000000 0.774960000000000 0.639680000000000 0.0108000000000000 ... 3.90000000000000 4.72972000000000 1.13836000000000 0.0109200000000000 3.95000000000000 4.73040000000000 1.13400000000000 0.0108000000000000 4.00000000000000 4.78200000000000 1.14344000000000 0.0108000000000000 # Table EndWe are now almost done. The first column contains the time index for each file, in nanoseconds. But the second and third columns, xpos and ypos, are not the skyrmion center, but rather some normalized sum of the locations of the spins inside the skyrmion. To get the skyrmion center coordinates we need to divide the xpos and ypos values in each row by the corresponding value in the last column. If you wish you can import this file into your favorite spreadsheet and implement the conversion there. An alternative is to use the OOMMF command line tool odtcalc. We will use this in conjunction with the OOMMF command line tool odtcols to get our final results:
tclsh oommf.tcl odtcalc x '$xpos/$wgt' nm y '$ypos/$wgt' nm < foo-a.odt > foo-b.odt
tclsh oommf.tcl odtcols t x y -f '%10.3f' < foo-b.odt > skyrmion-position.odt
The odtcalc
command takes parameter triples similar in format to
the ‑index
and ‑valfunc
options
to avf2odt
, except that the triplet order is column name,
Tcl expr expression, value units. The available variable names
come directly from the input data table column names. The output from
odtcalc repeats all the columns from the input, supplemented with an
additional column for each command line parameter triple. We only care
about the time and normalized skyrmion center locations
(columns t, x, and y, respectively), so we use odtcols
to extract just those three columns and write the result to the output
file skyrmion‑position.odt. The final result is
# ODT 1.0 ## Desc: Data from 81 vector field files: skyrmion_example‑init.omf, ... # Columns: \ # t x y # Units: \ # ns nm nm 0.000 57.373 57.373 0.050 61.759 57.759 0.100 66.747 58.309 0.150 71.756 59.230 ... 3.900 433.125 104.245 3.950 438.000 105.000 4.000 442.778 105.874 # Table EndSee the
odtcols
documentation if you want the last file
in CSV format, or as bare data with no headers.
The three commands avf2odt
, odtcalc
,
odtcols
, can be piped together as a single command. A
slightly more sophisticated, single command version of the above is
tclsh oommf.tcl avf2odt -average space \
-region 12e-9 12e-9 - 488e-9 188e-9 - \
-index t ns '$i*0.05' \
-valfunc xpos nm '$vz>0.5 ? $x*1e9*$vz : 0' \
-valfunc ypos nm '$vz>0.5 ? $y*1e9*$vz : 0' \
-valfunc wgt '' '$vz>0.5 ? $vz : 0' \
-defaultvals 0 -headers collapse -v 0 -onefile - \
skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-*omf \
| tclsh oommf.tcl odtcalc x '$xpos/$wgt' nm y '$ypos/$wgt' nm \
| tclsh oommf.tcl odtcols t x y -f '%10.3f' > skyrmion-position.odt
The Windows version is
tclsh oommf.tcl avf2odt -average space ^
-region 12e-9 12e-9 - 488e-9 188e-9 - ^
-index t ns "$i*0.05" ^
-valfunc xpos nm "$vz>0.5 ? $x*1e9*$vz : 0" ^
-valfunc ypos nm "$vz>0.5 ? $y*1e9*$vz : 0" ^
-valfunc wgt "" "$vz>0.5 ? $vz : 0" ^
-defaultvals 0 -headers collapse -v 0 -onefile - ^
skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-*omf ^
| tclsh oommf.tcl odtcalc x "$xpos/$wgt" nm y "$ypos/$wgt" nm ^
| tclsh oommf.tcl odtcols t x y -f "%10.3f" > skyrmion-position.odt
In this avf2odt
command we use the
‑region
option to ignore a 12 nm margin around
the outside of the simulation, in case any spins on the edge of the
simulation happen to have positive z-component and adversely impact
our skyrmion selection criterion. (Note that the region dimensions are
in meters!) The ‑valfunc
expressions are also
tweaked to weight locations inside the skyrmion by the strength of the
spin z-component. If you want to try this procedure yourself, you can
compare against the full output
file that was used to produce this graph:
-average plane -axis x
option
to avf2odt
to average magnetization component values
across planes perpendicular to the x-axis. We run this on a
single file (say the 2 ns snapshot) to create a 1D collection of
averages indexed by the x offset:
tclsh oommf.tcl avf2odt -average plane -axis x \
skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-*omf
We use the default output only. Since we don't
specify -onefile
, there will be one data table file
written for each input file (in this case, one file), named by
replacing the .omf
extension on the input file name
with .odt
. The output file has the form
# ODT 1.0 ## Desc: Data from vector field file skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-0006557.omf ... # Columns:\ # x m_x m_y m_z # Units:\ # m {} {} {} 1.30000000000000e-08 -0.0666609440209170 0.0105579739019117 -0.997642757515594 1.50000000000000e-08 -0.0466110757564310 0.00826372276950369 -0.998798356293519 1.70000000000000e-08 -0.0325609940391627 0.00640636195278553 -0.999365093481769 ... 4.83000000000000e-07 0.0319426902806790 0.00631023003805997 -0.999385449234615 4.85000000000000e-07 0.0457997980175227 0.00815129360001863 -0.998836608058228 4.87000000000000e-07 0.0656066145663459 0.0104285928185419 -0.997713831845614 # Table Endwhich yields this graph:
-average point
option
to avf2odt
to extract raw, non-averaged data from the
.omf
file. The command
tclsh oommf.tcl avf2odt -average point \
-region - 80e-9 - - 82e-9 - -opatsub -linegraph.odt \
skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-*omf
collects data along the line y = 81 nm:
# ODT 1.0 ## Desc: Data from vector field file skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-0006557.omf ## Active volume: (0,8e-08,0) x (5e-07,8.2e-08,6e-10) ## Cell size: 2e-09 x 2e-09 x 6e-10 ## Cells in active volume: 250 # # Table Start # Title: Points in specified volume # Columns:\ # x y z m_x m_y m_z # Units:\ # m m m {} {} {} 1.00000000000000e-09 8.10000000000000e-08 3.00000000000000e-10 -0.525758122122242 0.0309270756741152 -0.850071710511967 3.00000000000000e-09 8.10000000000000e-08 3.00000000000000e-10 -0.383855427027902 0.0282436687337109 -0.922961161868520 5.00000000000000e-09 8.10000000000000e-08 3.00000000000000e-10 -0.274898635848724 0.0244118972955306 -0.961163253188002 ... 4.95000000000000e-07 8.10000000000000e-08 3.00000000000000e-10 0.272353405599773 0.0242234134112282 -0.961892326978916 4.97000000000000e-07 8.10000000000000e-08 3.00000000000000e-10 0.381001948797025 0.0280470578610357 -0.924148731297192 4.99000000000000e-07 8.10000000000000e-08 3.00000000000000e-10 0.522878350430820 0.0307238099376666 -0.851853437014642 # Table EndCompare the resulting graph to the previous one of cross-sectional averages:
avf2ovf -info
command can be used to
extract general information, such as extents and lattice parameters, from an OVF file:
$ tclsh oommf.tcl avf2ovf -info skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-0006557.omf File: skyrmion_example-alpha0.100-Oxs_TimeDriver-Spin-40-0006557.omf File size: 600889 bytes Mesh title: Oxs_TimeDriver::Spin Mesh desc--- : Oxs vector field output : MIF source file: skyrmion_example.mif : Iteration: 6557, State id: 45741 : Stage: 40, Stage iteration: 159 : Stage simulation time: 5e-11 s : Total simulation time: 2.05e-09 s Rectangular mesh Mesh size: 25000 Dimensions: 250 100 1 Value magnitude span: 0.99999999999999978 [(1.54259e-05,-4.50696e-05,-1) at (4.41e-07,5.3e-08,3e-10)] to 1.0000000000000002 [(-6.58496e-11,0.525491,-0.850799) at (3.79e-07,1.99e-07,3e-10)] (in ) Data range: (1e-09,1e-09,3e-10) x (4.99e-07,1.99e-07,3e-10) (in m) Mesh range: (0,0,0) x (5e-07,2e-07,6e-10) (in m) Mesh base/step: (1e-09,1e-09,3e-10)/(2e-09,2e-09,6e-10) (in m)This can be useful for range selection when constructing
avf2odt
commands.
Back to OOMMF Tutorial
Date created: February 9, 2021 | Last updated: February 14, 2021 Contact: Webmaster