Skip to content

Commit b3a1c39

Browse files
author
Weiwei Wang
committed
add a rkky-style exchange for micro code
1 parent 02c060c commit b3a1c39

File tree

9 files changed

+279
-41
lines changed

9 files changed

+279
-41
lines changed

examples/micromagnetic/PRB_88_184422/fidimag/prb.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_prb88_184422():
3232

3333
sim.set_m((0, 0, 1))
3434

35-
sim.add(UniformExchange(A))
35+
sim.add(UniformExchange(A=A))
3636
sim.add(DMI(-D, type='interfacial'))
3737
sim.add(UniaxialAnisotropy(K, axis=(0, 0, 1)))
3838

examples/micromagnetic/dw_stt/main.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@
33
import matplotlib.pyplot as plt
44

55
import numpy as np
6-
from micro import Sim
7-
from common import CuboidMesh
6+
from fidimag.micro import Sim
7+
from fidimag.common import CuboidMesh
88

99
# The energies, we can use DMI in a future simulation
10-
from micro import UniformExchange
11-
from micro import UniaxialAnisotropy
10+
from fidimag.micro import UniformExchange
11+
from fidimag.micro import UniaxialAnisotropy
1212
# from micro import DMI
1313

1414
mu0 = 4 * np.pi * 1e-7
@@ -21,11 +21,11 @@ def init_m(pos):
2121
x = pos[0]
2222

2323
if x < 400:
24-
return (1, 0, 0)
24+
return (-1, 0, 0)
2525
elif 400 <= x < 500:
2626
return (0, 1, 1)
2727
else:
28-
return (-1, 0, 0)
28+
return (1, 0, 0)
2929

3030

3131
def relax_system(mesh):
@@ -38,7 +38,7 @@ def relax_system(mesh):
3838
sim.driver.alpha = 0.5
3939
sim.driver.gamma = 2.211e5
4040
sim.Ms = 8.6e5
41-
sim.do_precession = False
41+
sim.driver.do_precession = False
4242

4343
# The initial state passed as a function
4444
sim.set_m(init_m)
@@ -59,8 +59,8 @@ def relax_system(mesh):
5959
# ONE_DEGREE_PER_NS = 17453292.52
6060

6161
# Start relaxation and save the state in m0.npy
62-
sim.relax(dt=1e-14, stopping_dmdt=0.00001, max_steps=5000,
63-
save_m_steps=None, save_vtk_steps=None)
62+
sim.relax(dt=1e-14, stopping_dmdt=0.01, max_steps=5000,
63+
save_m_steps=None, save_vtk_steps=50)
6464

6565
np.save('m0.npy', sim.spin)
6666

@@ -106,8 +106,7 @@ def deal_plot(_list, output_file):
106106

107107

108108
# THIS NEEDS REVISION
109-
def deal_plot_dynamics(spin, m_component='mz',
110-
output_file):
109+
def deal_plot_dynamics(spin, m_component='mz', output_file='output.pdf'):
111110
"""
112111
The dynamics of the m_component of the i-th spin
113112
of the chain, from the magnetisation snapshot
@@ -140,10 +139,10 @@ def deal_plot_dynamics(spin, m_component='mz',
140139
def excite_system(mesh):
141140

142141
# Specify the stt dynamics in the simulation
143-
sim = Sim(mesh, name='dyn', driver='llg_stt')
142+
sim = Sim(mesh, name='dyn2', driver='llg_stt')
144143

145144
sim.driver.set_tols(rtol=1e-12, atol=1e-14)
146-
sim.driver.alpha = 0.05
145+
sim.driver.alpha = 0.2
147146
sim.driver.gamma = 2.211e5
148147
sim.Ms = 8.6e5
149148

@@ -163,16 +162,16 @@ def excite_system(mesh):
163162

164163
# Set the current in the x direction, in A / m
165164
# beta is the parameter in the STT torque
166-
sim.jx = -1e12
167-
sim.beta = 1
165+
sim.driver.jx = -1e12
166+
sim.driver.beta = 0.01
168167

169168
# The simulation will run for 5 ns and save
170169
# 500 snapshots of the system in the process
171170
ts = np.linspace(0, 5e-9, 501)
172171

173172
for t in ts:
174173
print 'time', t
175-
sim.run_until(t)
174+
sim.driver.run_until(t)
176175
sim.save_vtk()
177176
sim.save_m()
178177

examples/micromagnetic/vortex/main.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
import matplotlib.pyplot as plt
44

55
import numpy as np
6-
from micro import Sim
7-
from common import CuboidMesh
8-
from micro import UniformExchange, Demag
9-
from micro import Zeeman, TimeZeeman
6+
from fidimag.micro import Sim
7+
from fidimag.common import CuboidMesh
8+
from fidimag.micro import UniformExchange, Demag
9+
from fidimag.micro import Zeeman, TimeZeeman
1010
from fidimag.common.fileio import DataReader
1111

1212
mu0 = 4 * np.pi * 1e-7
@@ -46,7 +46,7 @@ def relax_system(mesh):
4646
sim.driver.alpha = 0.5
4747
sim.driver.gamma = 2.211e5
4848
sim.Ms = spatial_Ms
49-
sim.do_precession = False
49+
sim.driver.do_precession = False
5050

5151
sim.set_m(init_m)
5252
# sim.set_m(np.load('m0.npy'))
@@ -55,7 +55,7 @@ def relax_system(mesh):
5555
exch = UniformExchange(A=A)
5656
sim.add(exch)
5757

58-
demag = Demag()
58+
demag = Demag(pbc_2d=True)
5959
sim.add(demag)
6060

6161
mT = 795.7747154594767
@@ -84,7 +84,7 @@ def excite_system(mesh):
8484
exch = UniformExchange(A=A)
8585
sim.add(exch)
8686

87-
demag = Demag()
87+
demag = Demag(pbc_2d=True)
8888
sim.add(demag)
8989

9090
mT = 795.7747154594767
@@ -110,9 +110,9 @@ def gaussian_fun(t):
110110

111111
mesh = CuboidMesh(nx=80, ny=80, nz=2, dx=2.5, dy=2.5, dz=5.0, unit_length=1e-9)
112112

113-
# relax_system(mesh)
113+
relax_system(mesh)
114114

115-
excite_system(mesh)
115+
#excite_system(mesh)
116116

117117
# apply_field1(mesh)
118118
# deal_plot()

fidimag/micro/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
from .sim import Sim
22
from .demag import Demag
33
from .exchange import UniformExchange
4+
from .exchange_rkky import ExchangeRKKY
45
from .zeeman import Zeeman, TimeZeeman
56
from .anisotropy import UniaxialAnisotropy
67
from .dmi import DMI
78
from .baryakhtar import LLBar, LLBarFull
89
from .simple_demag import SimpleDemag
10+

fidimag/micro/exchange_rkky.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import fidimag.extensions.micro_clib as micro_clib
2+
from .energy import Energy
3+
#from constant import mu_0
4+
5+
6+
class ExchangeRKKY(Energy):
7+
8+
"""
9+
RKKYExchange(sigma, Delta, z_bottom=0, z_top = -1, name='RKKYExchange')
10+
11+
Compute the RKKY-style exchange interaction defined by
12+
13+
E = sigma/Delta *(1-m_t * m_b)
14+
15+
where E is the energy density, sigma is the surface exchange coefficient between the two surfaces,
16+
Delata is the space thickness. m_t and m_b are the unit vectors of the top and bottom layers, respectively.
17+
18+
Inputs:
19+
sigma: float
20+
sigma is the surface exchange stiffness constant.
21+
Delta: float
22+
Delta is the the space thickness in Meter.
23+
z_bottom: int
24+
z_bottom is the index of the bottom layer
25+
z_top: int
26+
z_top is the index of the top layer.
27+
28+
"""
29+
30+
def __init__(self, sigma, Delta=1e-9, z_bottom=0, z_top = -1, name='RKKYExchange'):
31+
self.sigma = sigma/Delta
32+
self.name = name
33+
self.z_bottom = z_bottom
34+
self.z_top = z_top
35+
self.jac = True
36+
37+
def setup(self, mesh, spin, Ms):
38+
super(ExchangeRKKY, self).setup(mesh, spin, Ms)
39+
if self.z_top<0:
40+
self.z_top+= self.nz
41+
42+
43+
def compute_field(self, t=0, spin=None):
44+
if spin is not None:
45+
m = spin
46+
else:
47+
m = self.spin
48+
49+
micro_clib.compute_exchange_field_micro_rkky(m,
50+
self.field,
51+
self.energy,
52+
self.Ms_inv,
53+
self.sigma,
54+
self.nx,
55+
self.ny,
56+
self.nz,
57+
self.z_bottom,
58+
self.z_top
59+
)
60+
61+
return self.field

fidimag/micro/lib/exch.c

Lines changed: 89 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,22 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
1010
*
1111
* Ms_inv :: Array with the (1 / Ms) values for every mesh node.
1212
* The values are zero for points with Ms = 0 (no material)
13-
*
13+
*
1414
* A :: Exchange constant
15-
*
15+
*
1616
* dx, dy, dz :: Mesh spacings in the corresponding directions
17-
*
17+
*
1818
* n :: Number of mesh nodes
1919
*
2020
* ngbs :: The array of neighbouring spins, which has (6 * n)
21-
* entries. Specifically, it contains the indexes of
21+
* entries. Specifically, it contains the indexes of
2222
* the neighbours of every mesh node, in the following order:
2323
* -x, +x, -y, +y, -z, +z
24-
*
24+
*
2525
* Thus, the array is like:
2626
* | 0-x, 0+x, 0-y, 0+y, 0-z, 0+z, 1-x, 1+x, 1-y, ... |
2727
* i=0 i=1 ...
28-
*
28+
*
2929
* where 0-y is the index of the neighbour of the 0th spin,
3030
* in the -y direction, for example. The index value for a
3131
* neighbour where Ms = 0, is evaluated as -1. The array
@@ -48,15 +48,15 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
4848
* since it is the left neighbour which is the PBC in x, etc..)
4949
*
5050
* For the exchange computation, the field is defined as:
51-
* H_ex = (2 * A / (mu0 * Ms)) * nabla^2 (mx, my, mz)
51+
* H_ex = (2 * A / (mu0 * Ms)) * nabla^2 (mx, my, mz)
5252
*
5353
* Therefore, for the i-th mesh node (spin), we approximate the
5454
* derivatives as:
55-
* nabla^2 mx = (1 / dx^2) * ( m[i-x] - 2 * m[i] + m[i+x] ) +
56-
* (1 / dy^2) * ( m[i-y] - 2 * m[i] + m[i+y] ) +
55+
* nabla^2 mx = (1 / dx^2) * ( m[i-x] - 2 * m[i] + m[i+x] ) +
56+
* (1 / dy^2) * ( m[i-y] - 2 * m[i] + m[i+y] ) +
5757
* (1 / dz^2) * ( m[i-z] - 2 * m[i] + m[i+z] )
58-
*
59-
* Where i-x is the neighbour in the -x direction. This is similar
58+
*
59+
* Where i-x is the neighbour in the -x direction. This is similar
6060
* for my and mz.
6161
* We can notice that the sum is the same if we do:
6262
* ( m[i-x] - m[i] ) + ( m[i+x] - m[i] )
@@ -101,7 +101,7 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
101101
field[3 * i + 2] = 0;
102102
continue;
103103
}
104-
104+
105105
/* Here we iterate through the neighbours */
106106
for (int j = 0; j < 6; j++) {
107107
/* Remember that index=-1 is for sites without material */
@@ -113,15 +113,15 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
113113
/* Check that the magnetisation of the neighbouring spin
114114
* is larger than zero */
115115
if (Ms_inv[ngbs[idn + j]] > 0){
116-
117-
/* Neighbours in the -x and +x directions
116+
117+
/* Neighbours in the -x and +x directions
118118
* giving: ( m[i-x] - m[i] ) + ( m[i+x] - m[i] )
119119
* when ngbs[idn + j] > 0 for j = 0 and j=1
120120
* If, for example, there is no
121121
* neighbour at -x (j=0) in the 0th node (no PBCs),
122122
* the second derivative would only be avaluated as:
123123
* (1 / dx * dx) * ( m[i+x] - m[i] )
124-
* which, according to
124+
* which, according to
125125
* [M.J. Donahue and D.G. Porter; Physica B, 343, 177-183 (2004)]
126126
* when performing the integration of the energy, we still
127127
* have error of the order O(dx^2)
@@ -160,3 +160,77 @@ void compute_exch_field_micro(double *m, double *field, double *energy,
160160
field[3 * i + 2] = fz * Ms_inv[i] * MU0_INV;
161161
}
162162
}
163+
164+
inline int get_index(int nx, int ny, int i, int j, int k){
165+
return k * nx*ny + j * nx + i;
166+
}
167+
168+
void compute_exch_field_rkky_micro(double *m, double *field, double *energy, double *Ms_inv,
169+
double sigma, int nx, double ny, double nz, int z_bottom, int z_top){
170+
171+
/* Compute the micromagnetic exchange field and energy using the
172+
* matrix of neighbouring spins and a second order approximation
173+
* for the derivative
174+
*
175+
* Ms_inv :: Array with the (1 / Ms) values for every mesh node.
176+
* The values are zero for points with Ms = 0 (no material)
177+
*
178+
* sigma :: Exchange constant
179+
*
180+
* nx, ny, nz :: Mesh dimensions.
181+
* The exchange field at the top (bottom) layer can be computed as:
182+
*
183+
* H_top = (sigma / (mu0 * Ms)) * m_bottom
184+
* H_bottom = (sigma / (mu0 * Ms)) * m_top
185+
*
186+
* The *m array contains the spins as:
187+
* [mx0, my0, mz0, mx1, my1, mz1, mx2, ...]
188+
* so if we want the starting position of the magnetisation for the
189+
* i-th spin, we only have to do (3 * i) for mx, (3 * i + 1) for my
190+
* and (3 * i + 2) for mz
191+
*
192+
*
193+
*
194+
*/
195+
196+
int n = nx*ny*nz;
197+
for (int i = 0; i < n; i++){
198+
energy[i] = 0;
199+
field[3*i]=0;
200+
field[3*i+1]=0;
201+
field[3*i+2]=0;
202+
}
203+
204+
#pragma omp parallel for
205+
for (int i = 0; i < nx; i++) {
206+
for (int j = 0; j < ny; j++){
207+
double mtx=0, mty=0, mtz=0;
208+
double mbx=0, mby=0, mbz=0;
209+
int id1 = get_index(nx,ny, i, j, z_bottom);
210+
int id2 = get_index(nx,ny, i, j, z_top);
211+
mtx = m[3*id2];
212+
mty = m[3*id2+1];
213+
mtz = m[3*id2+2];
214+
215+
mbx = m[3*id1];
216+
mby = m[3*id1+1];
217+
mbz = m[3*id1+2];
218+
219+
if (Ms_inv[id1] != 0.0){
220+
energy[id1] = sigma*(1-mtx*mbx-mty*mby-mtz*mbz);
221+
field[3*id1] = sigma * mtx * Ms_inv[id1] * MU0_INV;
222+
field[3*id1+1] = sigma * mty * Ms_inv[id1] * MU0_INV;
223+
field[3*id1+2] = sigma * mtz * Ms_inv[id1] * MU0_INV;
224+
}
225+
226+
if (Ms_inv[id2] != 0.0){
227+
energy[id2] = sigma*(1-mtx*mbx-mty*mby-mtz*mbz);
228+
field[3*id2] = sigma * mbx * Ms_inv[id2] * MU0_INV;
229+
field[3*id2+1] = sigma * mby * Ms_inv[id2] * MU0_INV;
230+
field[3*id2+2] = sigma * mbz * Ms_inv[id2] * MU0_INV;
231+
}
232+
}
233+
}
234+
235+
236+
}

fidimag/micro/lib/micro_clib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ inline double cross_z(double a0, double a1, double a2,
1616
void compute_exch_field_micro(double *m, double *field, double *energy, double *Ms_inv,
1717
double A, double dx, double dy, double dz, int n, int *ngbs);
1818

19+
void compute_exch_field_rkky_micro(double *m, double *field, double *energy, double *Ms_inv,
20+
double sigma, int nx, double ny, double nz, int z_bottom, int z_top);
21+
1922
void dmi_field(double *m, double *field, double *energy, double *Ms_inv,
2023
double *D, double dmi_vector[18], int n_dmi_ngbs,
2124
double dx, double dy, double dz,

0 commit comments

Comments
 (0)