Skip to content

Commit 199d790

Browse files
author
Weiwei Wang
committed
change stt slightly (enable current in z-direction)
1 parent 2012f6f commit 199d790

File tree

7 files changed

+94
-52
lines changed

7 files changed

+94
-52
lines changed

fidimag/atomistic/lib/clib.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@ void llg_s_rhs(double * dm_dt, double * spin, double * h, double *alpha,
6060
double *chi, double gamma, int n);
6161

6262

63-
void compute_stt_field_c(double *spin, double *field, double *jx, double *jy,
64-
double dx, double dy, int *ngbs, int n);
63+
void compute_stt_field_c(double *spin, double *field, double *jx, double *jy, double *jz,
64+
double dx, double dy, double dz, int *ngbs, int n);
6565

6666
void llg_stt_rhs(double *dm_dt, double *m, double *h,
6767
double *h_stt, double *alpha,

fidimag/atomistic/lib/clib.pyx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@ cdef extern from "clib.h":
7878
void normalise(double *m, int *pins, int n)
7979

8080
void compute_stt_field_c(double *spin, double *field,
81-
double *jx, double *jy,
82-
double dx, double dy, int *ngbs, int n)
81+
double *jx, double *jy, double *jz,
82+
double dx, double dy, double dz, int *ngbs, int n)
8383

8484
void llg_stt_rhs(double *dm_dt, double *m, double *h, double *h_stt,
8585
double *alpha,double beta, double u0, double gamma, int n)
@@ -241,12 +241,13 @@ def compute_stt_field(np.ndarray[double, ndim=1, mode="c"] spin,
241241
np.ndarray[double, ndim=1, mode="c"] field,
242242
np.ndarray[double, ndim=1, mode="c"] jx,
243243
np.ndarray[double, ndim=1, mode="c"] jy,
244-
dx, dy,
244+
np.ndarray[double, ndim=1, mode="c"] jz,
245+
dx, dy, dz,
245246
np.ndarray[int, ndim=2, mode="c"] ngbs,
246247
n
247248
):
248-
compute_stt_field_c(&spin[0], &field[0], &jx[0], &jy[0],
249-
dx, dy, &ngbs[0, 0], n)
249+
compute_stt_field_c(&spin[0], &field[0], &jx[0], &jy[0],&jz[0],
250+
dx, dy, dz, &ngbs[0, 0], n)
250251

251252
def compute_llg_stt_rhs(np.ndarray[double, ndim=1, mode="c"] dm_dt,
252253
np.ndarray[double, ndim=1, mode="c"] spin,

fidimag/atomistic/lib/stt.c

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* is
55
* ( \vec{j}_s \cdot \nabla ) \vec{m}
66
*
7-
* where j_s is the current vector in 2D
7+
* where j_s is the current vector in 3D
88
* For this computation we use the neighbours matrix to make easier the
99
* derivative calculation at the boundaries.
1010
* ** For now this only works with the CUBOID mesh
@@ -17,6 +17,7 @@
1717
* the derivatives are simply:
1818
* f(x + 1, y, z) - f(x - 1, y, z) / 2 dx
1919
* f(x, y + 1, z) - f(x, y - 1, z) / 2 dy
20+
* f(x, y, z + 1) - f(x, y, z - 1) / 2 dz
2021
*
2122
* where x+-1 is the neighbour to the left or right.
2223
*
@@ -31,7 +32,7 @@
3132
* i-th site and nn_x2 for the NN to the right. These variables are simply
3233
* the i-th index (in the corresponding cases) when there is a single NN
3334
*
34-
* Similar for y
35+
* Similar for y and z
3536
*
3637
* n is the number of spins or lattice sites in the system
3738
*
@@ -50,25 +51,24 @@
5051
* Neighbouring sites where there is no material, has index -1
5152
*
5253
*/
53-
void compute_stt_field_c(double *spin, double *field, double *jx, double *jy,
54-
double dx, double dy, int *ngbs, int n) {
54+
void compute_stt_field_c(double *spin, double *field, double *jx, double *jy, double *jz,
55+
double dx, double dy, double dz, int *ngbs, int n) {
5556

56-
int i, j;
57-
float factor_x, factor_y;
58-
int nn_i;
59-
int nn_x1, nn_x2, nn_y1, nn_y2;
60-
61-
for (i = 0; i < 3 * n; i++) {
57+
//#pragma omp parallel for
58+
for (int i = 0; i < 3 * n; i++) {
6259
field[i] = 0;
6360
}
64-
61+
62+
#pragma omp parallel for
6563
/* Iterate through every lattice site */
66-
for (i = 0; i < n; i++){
64+
for (int i = 0; i < n; i++){
6765

6866
/* Starting index for the NNs of the i-th site
6967
* i+0, i+1, i+2, i+3 ... --> -x, +x, -y, +y ...
7068
*/
71-
nn_i = 6 * i;
69+
int nn_i = 6 * i;
70+
double factor_x, factor_y, factor_z;
71+
int nn_x1, nn_x2, nn_y1, nn_y2, nn_z1, nn_z2;
7272

7373
/* Here we distinguish if there are 2 NNs, no NN in the
7474
* -x direction, or no NN in the +x direction,
@@ -100,7 +100,7 @@ void compute_stt_field_c(double *spin, double *field, double *jx, double *jy,
100100
* This calculation is: jx[i] * d m[i] / dx
101101
* */
102102
if (factor_x){
103-
for(j = 0; j < 3; j++){
103+
for(int j = 0; j < 3; j++){
104104
field[3 * i + j] += jx[i] * (spin[3 * nn_x2 + j]
105105
- spin[3 * nn_x1 + j]) / (factor_x * dx);
106106
}
@@ -124,11 +124,37 @@ void compute_stt_field_c(double *spin, double *field, double *jx, double *jy,
124124
}
125125

126126
if (factor_y){
127-
for(j = 0; j < 3; j++){
127+
for(int j = 0; j < 3; j++){
128128
field[3 * i + j] += jy[i] * (spin[3 * nn_y2 + j]
129129
- spin[3 * nn_y1 + j]) / (factor_y * dy);
130130
}
131131
}
132+
133+
134+
// We do the same along the z direction
135+
if(ngbs[nn_i + 4] != -1 && ngbs[nn_i + 5] != -1) {
136+
factor_z = 2;
137+
nn_z1 = ngbs[nn_i + 4];
138+
nn_z2 = ngbs[nn_i + 5];
139+
} else if(ngbs[nn_i + 4] == -1 && ngbs[nn_i + 5] != -1){
140+
factor_z = 1;
141+
nn_z1 = ngbs[nn_i + 4];
142+
nn_z2 = i;
143+
} else if(ngbs[nn_i + 4] == -1 && ngbs[nn_i + 5] != -1){
144+
factor_z = 1;
145+
nn_z1 = i;
146+
nn_z2 = ngbs[nn_i + 5];
147+
} else {
148+
factor_z = 0;
149+
}
150+
151+
if (factor_z){
152+
for(int j = 0; j < 3; j++){
153+
field[3 * i + j] += jz[i] * (spin[3 * nn_z2 + j]
154+
- spin[3 * nn_z1 + j]) / (factor_z * dz);
155+
}
156+
}
157+
132158
}
133159
}
134160

fidimag/atomistic/llg_stt.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self, mesh, name='unnamed'):
2424

2525
self._jx = np.zeros(self.n, dtype=np.float)
2626
self._jy = np.zeros(self.n, dtype=np.float)
27+
self._jz = np.zeros(self.n, dtype=np.float)
2728

2829
self.p = 0.5
2930
self.beta = 0
@@ -49,6 +50,14 @@ def set_jy(self, value):
4950

5051
jy = property(get_jy, set_jy)
5152

53+
def get_jz(self):
54+
return self._jz
55+
56+
def set_jz(self, value):
57+
self._jz[:] = helper.init_scalar(value, self.mesh)
58+
59+
jz = property(get_jz, set_jz)
60+
5261
def sundials_rhs(self, t, y, ydot):
5362

5463
self.t = t
@@ -63,8 +72,10 @@ def sundials_rhs(self, t, y, ydot):
6372
self.field_stt,
6473
self._jx * self.update_j_fun(t),
6574
self._jy * self.update_j_fun(t),
75+
self._jz * self.update_j_fun(t),
6676
self.mesh.dx * self.mesh.unit_length,
6777
self.mesh.dy * self.mesh.unit_length,
78+
self.mesh.dz * self.mesh.unit_length,
6879
self.mesh.neighbours,
6980
self.n
7081
)
@@ -73,8 +84,10 @@ def sundials_rhs(self, t, y, ydot):
7384
self.field_stt,
7485
self._jx,
7586
self._jy,
87+
self._jz,
7688
self.mesh.dx * self.mesh.unit_length,
7789
self.mesh.dy * self.mesh.unit_length,
90+
self.mesh.dz * self.mesh.unit_length,
7891
self.mesh.neighbours,
7992
self.n
8093
)

fidimag/micro/llg_stt.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ def __init__(self, mesh, name='unnamed'):
2424

2525
self._jx = np.zeros(self.n, dtype=np.float)
2626
self._jy = np.zeros(self.n, dtype=np.float)
27+
self._jz = np.zeros(self.n, dtype=np.float)
2728

2829
self.p = 0.5
2930
self.beta = 0
@@ -48,6 +49,14 @@ def set_jy(self, value):
4849

4950
jy = property(get_jy, set_jy)
5051

52+
def get_jz(self):
53+
return self._jz
54+
55+
def set_jz(self, value):
56+
self._jz[:] = helper.init_scalar(value, self.mesh)
57+
58+
jz = property(get_jz, set_jz)
59+
5160
def sundials_rhs(self, t, y, ydot):
5261

5362
self.t = t
@@ -62,8 +71,10 @@ def sundials_rhs(self, t, y, ydot):
6271
self.field_stt,
6372
self._jx * self.update_j_fun(t),
6473
self._jy * self.update_j_fun(t),
74+
self._jz * self.update_j_fun(t),
6575
self.mesh.dx * self.mesh.unit_length,
6676
self.mesh.dy * self.mesh.unit_length,
77+
self.mesh.dz * self.mesh.unit_length,
6778
self.mesh.neighbours,
6879
self.n
6980
)
@@ -72,8 +83,10 @@ def sundials_rhs(self, t, y, ydot):
7283
self.field_stt,
7384
self._jx,
7485
self._jy,
86+
self._jz,
7587
self.mesh.dx * self.mesh.unit_length,
7688
self.mesh.dy * self.mesh.unit_length,
89+
self.mesh.dz * self.mesh.unit_length,
7790
self.mesh.neighbours,
7891
self.n
7992
)

tests/test_stt.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ def test_sst_field_1d():
5353
# The system is 1d with 4 spins.
5454
nx, ny, nz = 4, 1, 1
5555
n = nx * ny * nz
56-
dx, dy = 1, 1
56+
dx, dy, dz = 1, 1, 1
5757

5858
# NO PBCs -----------------------------------------------------------------
5959
# We can manually construct the neighbours matrix,
@@ -81,6 +81,7 @@ def test_sst_field_1d():
8181
field = np.zeros(nxyz)
8282
jx = np.zeros(nxyz)
8383
jy = np.zeros(nxyz)
84+
jz = np.zeros(nxyz)
8485
jx[:] = 1
8586
jy[:] = 2
8687

@@ -94,8 +95,8 @@ def test_sst_field_1d():
9495

9596
clib.compute_stt_field(spin,
9697
field,
97-
jx, jy,
98-
dx, dy,
98+
jx, jy, jz,
99+
dx, dy, dz,
99100
ngbs,
100101
n
101102
)
@@ -118,8 +119,8 @@ def test_sst_field_1d():
118119

119120
clib.compute_stt_field(spin,
120121
field,
121-
jx, jy,
122-
dx, dy,
122+
jx, jy, jz,
123+
dx, dy, dz,
123124
ngbs,
124125
n
125126
)

tests/test_stt_dw_atomistic.py

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,18 @@
1010

1111
mu0 = 4 * np.pi * 1e-7
1212

13-
def load_mz_npy(npy_file):
14-
15-
m0_z = np.load(npy_file)
16-
m_magnitude = m0_z[0] ** 2 + m0_z[1] ** 2 + m0_z[2] ** 2
17-
18-
if np.abs(m_magnitude - 1) < 1e-6:
19-
m0_z = m0_z.reshape(-1, 3)[:, 2]
20-
else:
21-
m0_z = m0_z.reshape(3, -1)[2]
22-
23-
return m0_z
24-
2513

2614
# Initial State, a rough DW in a 1D chain
2715
def init_m(pos):
2816

29-
x = pos[0]
17+
z = pos[2]
3018

31-
if x < 450:
32-
return (1, 0, 0)
33-
elif 450 <= x < 550:
34-
return (0, 1, 1)
19+
if z < 450:
20+
return (0, 0, 1)
21+
elif 450 <= z < 550:
22+
return (1, 1, 0)
3523
else:
36-
return (-1, 0, 0)
24+
return (0, 0, -1)
3725

3826

3927
def relax_system(mesh):
@@ -56,14 +44,14 @@ def relax_system(mesh):
5644
exch = UniformExchange(J=2e-20)
5745
sim.add(exch)
5846

59-
anis = Anisotropy(0.01*2e-20, axis=(1,0,0))
47+
anis = Anisotropy(0.01*2e-20, axis=(0,0,1))
6048
sim.add(anis)
6149

6250
# dmi = DMI(D=8e-4)
6351
# sim.add(dmi)
6452

6553
# Start relaxation and save the state in m0.npy
66-
sim.relax(dt=1e-14, stopping_dmdt=1e3, max_steps=5000,
54+
sim.relax(dt=1e-14, stopping_dmdt=1e4, max_steps=5000,
6755
save_m_steps=None, save_vtk_steps=None)
6856

6957
np.save('m0.npy', sim.spin)
@@ -90,14 +78,14 @@ def excite_system(mesh, time=0.1, snaps=11):
9078
exch = UniformExchange(J=2e-20)
9179
sim.add(exch)
9280

93-
anis = Anisotropy(0.01*2e-20, axis=(1,0,0))
81+
anis = Anisotropy(0.01*2e-20, axis=(0,0,1))
9482
sim.add(anis)
9583
# dmi = DMI(D=8e-4)
9684
# sim.add(dmi)
9785

9886
# Set the current in the x direction, in A / m
9987
# beta is the parameter in the STT torque
100-
sim.jx = -1e12
88+
sim.jz = -1e12
10189
sim.beta = 0.1
10290

10391
# The simulation will run for x ns and save
@@ -113,7 +101,7 @@ def excite_system(mesh, time=0.1, snaps=11):
113101

114102

115103
def test_stt_dw_atomistic():
116-
mesh = Mesh(nx=1000, ny=1, nz=1,
104+
mesh = Mesh(nx=1, ny=1, nz=1000,
117105
dx=1.0, dy=1.0, dz=1.0,
118106
unit_length=1e-9)
119107

@@ -123,13 +111,13 @@ def test_stt_dw_atomistic():
123111

124112
m0 = np.load('m0.npy')
125113
m0.shape=(-1,3)
126-
mx0 = np.average(m0[:,0])
114+
mx0 = np.average(m0[:,2])
127115

128116
excite_system(mesh)
129117

130118
m1 = np.load('m1.npy')
131119
m1.shape=(-1,3)
132-
mx1 = np.average(m1[:,0])
120+
mx1 = np.average(m1[:,2])
133121

134122
mu_s = (1e-27/mu0)
135123
v = 1e-27

0 commit comments

Comments
 (0)