Skip to content

Commit

Permalink
update doc for neb
Browse files Browse the repository at this point in the history
  • Loading branch information
ww1g11 committed Jun 20, 2024
1 parent 9d955b8 commit f93238f
Show file tree
Hide file tree
Showing 6 changed files with 120 additions and 115 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "MicroMagnetic"
uuid = "cef16ca0-16a8-11ef-389e-9fbcf1974e83"
authors = ["Weiwei Wang <[email protected]>", "Boyao Lv <[email protected]>"]
version = "0.3.3"
version = "0.3.4"

[deps]
KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c"
Expand Down
1 change: 1 addition & 0 deletions docs/src/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ set_backend
set_precision
Sim
create_sim
NEB
run_sim
set_Ms
set_driver
Expand Down
4 changes: 2 additions & 2 deletions docs/src/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ In [Julia](http://julialang.org), packages can be easily installed with the Juli
From the Julia REPL, type ] to enter the Pkg REPL mode and run:

```julia
pkg> add https://github.com/ww1g11/MicroMagnetic.jl
pkg> add MicroMagnetic
```

Or, equivalently:

```julia
julia> using Pkg;
julia> Pkg.add("https://github.com/ww1g11/MicroMagnetic.jl")
julia> Pkg.add("MicroMagnetic.jl")
```

To enable GPU support, one has to install one of the following packages:
Expand Down
174 changes: 67 additions & 107 deletions docs/tutorials/neb/neb_skx.jl
Original file line number Diff line number Diff line change
@@ -1,157 +1,117 @@
# ---
# title: Skyrmion collapse using NEB
# author: Weiwei Wang
# date: 2022-12-14
# date: 2024-06-20
# description: an example to demostrate how to use NEB
# tag: tutorial; neb
# ---

using Printf
using NPZ
using CairoMakie
using DelimitedFiles
using CubicSplines

using MicroMagnetic
#MicroMagnetic.cuda_using_double(true);

# In this example, we will compute the energy barrier of a skyrmion collapse into the ferromagnetic state using the NEB method.
# Firstly, we create a create_sim method to describe the studied system. For example, the system is a thin film (120x120x2 nm^3)
# Firstly, we use create_sim method to describe the studied system. For example, the system is a thin film (120x120x2 nm^3)
# with periodic boundary conditions, and three energies are considered.
function create_sim(init_m_fun=(0,0,1))
mesh = FDMesh(nx=60, ny=60, nz=1, dx=2e-9, dy=2e-9, dz=2e-9, pbc="xy")
sim = Sim(mesh, name="neb", driver="SD")
set_Ms(sim, 3.84e5)

init_m0(sim, init_m_fun)

add_exch(sim, 3.25e-12)
add_dmi(sim, 5.83e-4)
add_zeeman(sim, (0, 0, 120*mT))
mesh = FDMesh(nx=60, ny=60, nz=1, dx=2e-9, dy=2e-9, dz=2e-9, pbc="xy")
params = Dict(
:Ms => 3.84e5,
:A => 3.25e-12,
:D => 5.83e-4,
:H => (0, 0, 120 * mT)
)

return sim
end
# Using NEB can be divided into two stages. The first stage is to prepare the initial state and the final state. We assume that
# the initial state is a magnetic skyrmion and the final state is ferromagnetic state.

# In this method, we will obtain a magnetic skyrmion. The skyrmion state is save as 'skx.npy'.
# In this method, we will obtain a magnetic skyrmion. The skyrmion state is saved as 'skx.vts'.
function relax_skx()
function m0_fun_skx(i,j,k, dx, dy, dz)
r2 = (i-30)^2 + (j-30)^2
function m0_fun_skx(i, j, k, dx, dy, dz)
r2 = (i - 30)^2 + (j - 30)^2
if r2 < 10^2
return (0.01, 0, -1)
return (0.01, 0, -1)
end
return (0,0,1)
return (0, 0, 1)
end

sim = create_sim(m0_fun_skx)
relax(sim, maxsteps=2000, stopping_dmdt=0.01)
npzwrite("skx.npy", Array(sim.spin))

sim = create_sim(mesh; m0=m0_fun_skx, params...)
relax(sim; maxsteps=2000, stopping_dmdt=0.01)
save_vtk(sim, "skx")
end

# We will use this method the plot the magnetization.
function plot_spatial_m(m; nx=60, ny=60, filename="")

points = [Point3f(i, j, 0) for i in 1:2:nx for j in 1:2:ny]

m = reshape(m, 3, nx, ny)
mf = [Vec3f(m[1, i, j], m[2, i,j], m[3, i,j]) for i in 1:2:nx for j in 1:2:ny]
mz = [m[3, i, j] for i in 1:2:nx for j in 1:2:ny]

fig = Figure(resolution = (800, 800))
ax = Axis(fig[1, 1], backgroundcolor = "white")

arrows!(ax, points, mf, fxaa=true, # turn on anti-aliasing
color = vec(mz), linewidth = 0.5, arrowsize = 1, lengthscale = 1,
align = :center
)

if length(filename)>0
save(filename*".png", fig)
end

return fig

return plot_m(sim)
end

# We will invoke the relax_skx method to obtain a magnetic skyrmion state.
# We will invoke the relax_skx method to obtain a magnetic skyrmion state and plot the magnetization.
relax_skx()

# We plot the skyrmion using 3D arrows.
plot_spatial_m(npzread("skx.npy"))
# The following is the second stage.


# To use the NEB, we use the create_sim method to create a Sim instance.
sim = create_sim()

# We need to define the initial and final state, which is stored in the init_images list.
# We need to define the initial and final state, which is stored in the init\_images list.
# Note that any acceptable object, such as a function, a tuple, or an array, can be used.
# Moreover, the init_images list could contain the intermediate state if you have one.
init_images = [npzread("skx.npy"), (0, 0, 1)]
# Moreover, the init\_images list could contain the intermediate state if you have one.
init_images = [read_vtk("skx.vts"), (0, 0, 1)];

# We need an interpolation array to specify how many images will be used in the NEB simulation.
# Note the length of the interpolation array is the length of init_images minus one.
interpolation = [6]
# Note the length of the interpolation array is the length of init\_images minus one. For example,
# if init\_images = [read_vtk("skx.vts"), read_vtk("skx2.vts"), (0, 0, 1)], the length of interpolation should be 2,
# i.e., something like interpolation = [5,5].
interpolation = [6];

# We create the NEB instance and set the spring_constant.
# neb = NEB_GPU(sim, init_images, interpolation; name="skx_fm", driver="LLG")
# To use the NEB, we use the create_sim method to create a Sim instance.
sim = create_sim(mesh; params...);

# We create the NEB instance and set the spring_constant, the driver could be "SD" or "LLG"
neb = NEB(sim, init_images, interpolation; name="skx_fm", driver="SD");
# neb.spring_constant = 1e7

# Relax the whole system, uncomment the line 102
if !isfile("skx_fm_energy.txt")
#relax(neb, stopping_dmdt=0.1, save_vtk_every=1000, maxsteps=5000)
end
# Relax the whole system
relax(neb; stopping_dmdt=0.1, save_vtk_every=1000, maxsteps=5000)


# After running the simulation, the energy text file ('skx_fm_energy.txt') and the corresponding
# distance text file ('skx_fm_distance.txt') are generated.

# We define a function to extract the data for plotting.
function extract_data(;id=1)
energy = readdlm("assets/skx_fm_energy.txt", skipstart=2)
dms = readdlm("assets/skx_fm_distance.txt", skipstart=2)
xs = zeros(length(dms[1, 1:end]))
for i=2:length(xs)
xs[i] = sum(dms[id, 2:i])
end

et = energy[id, 2:end]
e0 = minimum(et)
energy_eV = (et .- e0) / meV

spline = CubicSpline(xs, energy_eV)

xs2 = range(xs[1], xs[end], 100)
energy2 = spline[xs2]

return xs, energy_eV, xs2, energy2
end
function extract_data(; id=1)
energy = readdlm("assets/skx_fm_energy.txt"; skipstart=2)
dms = readdlm("assets/skx_fm_distance.txt"; skipstart=2)
xs = zeros(length(dms[1, 1:end]))
for i in 2:length(xs)
xs[i] = sum(dms[id, 2:i])
end

et = energy[id, 2:end]
e0 = minimum(et)
energy_eV = (et .- e0) / meV

spline = CubicSpline(xs, energy_eV)

function plot_m()

fig = Figure(resolution = (800, 480))
ax = Axis(fig[1, 1],
xlabel = "Distance (a.u.)",
ylabel = "Energy (meV)"
)
xs2 = range(xs[1], xs[end], 100)
energy2 = spline[xs2]

return xs, energy_eV, xs2, energy2
end

xs, energy, xs2, energy2 = extract_data(id=1)
scatter!(ax, xs, energy, markersize = 6, label="Initial energy path")
lines!(ax, xs2, energy2)
function plot_energy()
fig = Figure(; resolution=(800, 480))
ax = Axis(fig[1, 1]; xlabel="Distance (a.u.)", ylabel="Energy (meV)")

xs, energy, xs2, energy2 = extract_data(id=500)
scatter!(ax, xs, energy, markersize = 6, label="Minimal energy path")
lines!(ax, xs2, energy2)
#linescatter!(ax, data[:,2]*1e9, data[:,5], markersize = 6)
#linescatter!(ax, data[:,2]*1e9, data[:,6], markersize = 6)
xs, energy, xs2, energy2 = extract_data(; id=1)
scatter!(ax, xs, energy; markersize=6, label="Initial energy path")
lines!(ax, xs2, energy2)

axislegend()
xs, energy, xs2, energy2 = extract_data(; id=500)
scatter!(ax, xs, energy; markersize=6, label="Minimal energy path")
lines!(ax, xs2, energy2)
#linescatter!(ax, data[:,2]*1e9, data[:,5], markersize = 6)
#linescatter!(ax, data[:,2]*1e9, data[:,6], markersize = 6)

save("energy.png", fig)
axislegend()

return fig
save("energy.png", fig)

return fig
end

plot_m()
plot_energy()
52 changes: 48 additions & 4 deletions src/neb/neb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,57 @@ end

"""
NEB(sim::AbstractSim, init_images::TupleOrArray, frames_between_images::TupleOrArray;
name="NEB", spring_constant=1.0e5, driver="LLG")
name="NEB", spring_constant=1.0e5, driver="LLG", clib_image=-1)
Create a NEB instance.
args:
sim: Sim instance that include the interactions.
init_images::TupleOrArray:
# Arguments
- `sim::AbstractSim`: Simulation instance that includes the interactions.
- `init_images::TupleOrArray`: Tuple or array of initial and final state images. Intermediate state images can also be included.
- `frames_between_images::TupleOrArray`: Tuple or array specifying the number of frames between each pair of images.
- `name::String="NEB"`: Name for the NEB instance.
- `spring_constant::Float64=1.0e5`: Spring constant used in the NEB simulation.
- `driver::String="LLG"`: Driver for the NEB simulation. Options are `"SD"` or `"LLG"`.
- `clib_image::Int=-1`: Optional parameter for specifying a particular image in the library (default is -1).
# Returns
A NEB instance configured with the provided parameters.
# Example
```julia
# define mesh and the corresponding parameters
mesh = FDMesh(nx=60, ny=60, nz=1, dx=2e-9, dy=2e-9, dz=2e-9, pbc="xy")
params = Dict(
:Ms => 3.84e5,
:A => 3.25e-12,
:D => 5.83e-4,
:H => (0, 0, 120 * mT)
)
# Define the initial and final state, stored in the init_images list.
# Any acceptable object, such as a function, a tuple, or an array, can be used.
# The init_images list can also contain the intermediate state if you have one.
init_images = [read_vtk("skx.vts"), (0, 0, 1)]
# Define the interpolation array to specify the number of images used in the NEB simulation.
# The length of the interpolation array should be the length of init_images minus one.
# For example, if init_images = [read_vtk("skx.vts"), read_vtk("skx2.vts"), (0, 0, 1)],
# the length of interpolation should be 2, i.e., something like interpolation = [5,5].
interpolation = [6]
# Use the create_sim method to create a Sim instance.
sim = create_sim(mesh; params...)
# Create the NEB instance and set the spring_constant. The driver can be "SD" or "LLG".
neb = NEB(sim, init_images, interpolation; name="skx_fm", driver="SD")
# neb.spring_constant = 1e7
# Relax the entire system.
relax(neb; stopping_dmdt=0.1, save_vtk_every=1000, maxsteps=5000)
```
"""
function NEB(sim::AbstractSim, given_images::TupleOrArray,
frames_between_images::TupleOrArray; name="NEB", spring_constant=1.0e5,
Expand Down
2 changes: 1 addition & 1 deletion src/vtk.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ using WriteVTK
using ReadVTK
using Printf

export save_vtk, ovf2vtk
export save_vtk, ovf2vtk, read_vtk

#TODO: tidy up save_vtk

Expand Down

2 comments on commit f93238f

@ww1g11
Copy link
Member Author

@ww1g11 ww1g11 commented on f93238f Jun 20, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

  • fixed NEB

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/109408

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.3.4 -m "<description of version>" f93238f6ef52c584b170dd3a494a04a5c53ef6e6
git push origin v0.3.4

Please sign in to comment.