Skip to content

Commit bd8f0b3

Browse files
author
Weiwei Wang
committed
add cubic anisotropy for atomistic model
1 parent 2dc1e9f commit bd8f0b3

File tree

8 files changed

+97
-15
lines changed

8 files changed

+97
-15
lines changed

doc/core_eqs.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,21 @@ corresponding field is
110110
.. math::
111111
\vec{H}_{i,\text{an}} = \frac{2 \mathcal{K}_{u}}{\mu_s} \left(\vec{S}_{i}\cdot\hat{u}\right)\hat{u}
112112
113-
|
113+
The Hamiltonian for the cubic anisotropy is given by
114+
115+
.. math::
116+
\mathcal{H}_{\text{an}}^c = \mathcal{K}_{c} \sum_i (S_x^4+S_y^4+S_z^4)
117+
118+
which is equivalent to the popular form
119+
120+
.. math::
121+
\mathcal{H}_{\text{an}}^c = -2 \mathcal{K}_{c} \sum_i (S_x^2 S_y^2 + S_y^2 S_z^2 + S_z^2 S_x^2)
122+
123+
The effective fields thus can be computed as
124+
125+
.. math::
126+
\vec{H}_{i,\text{an}}^c = -\frac{4 \mathcal{K}_{c}}{\mu_s} \left ( S_x^3 \hat{x} + S_y^3 \hat{y} + S_z^3 \hat{z} \right)
127+
114128
115129
In micromagnetics, the uniaxial anisotropy energy of the system is defined as
116130

fidimag/atomistic/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from .sim import Sim
22
from .exchange import UniformExchange, Exchange
3-
from .anisotropy import Anisotropy
3+
from .anisotropy import Anisotropy, CubicAnisotropy
44
from .zeeman import Zeeman, TimeZeeman
55
from .demag import Demag
66
from .demag_hexagonal import DemagHexagonal

fidimag/atomistic/anisotropy.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,3 +72,33 @@ def compute_field(self, t=0, spin=None):
7272
)
7373

7474
return self.field * self.mu_s_inv
75+
76+
77+
class CubicAnisotropy(Energy):
78+
"""
79+
Compute the Cubic Anisotropy, see documentation for detailed equations.
80+
"""
81+
82+
def __init__(self, Kc, name='CubicAnisotropy'):
83+
self.Kc = Kc
84+
self.name = name
85+
self.jac = True
86+
87+
88+
def setup(self, mesh, spin, mu_s):
89+
super(CubicAnisotropy, self).setup(mesh, spin, mu_s)
90+
self._Kc = helper.init_scalar(self.Kc, self.mesh)
91+
92+
def compute_field(self, t=0, spin=None):
93+
if spin is not None:
94+
m = spin
95+
else:
96+
m = self.spin
97+
98+
clib.compute_anisotropy_cubic(m,
99+
self.field,
100+
self.energy,
101+
self._Kc,
102+
self.n)
103+
104+
return self.field * self.mu_s_inv

fidimag/atomistic/lib/anis.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33

44
void compute_anis(double *spin, double *field, double *energy,
55
double *Ku, double *axis, int n) {
6-
7-
/* Remember that the magnetisation order is
6+
7+
/* Remember that the magnetisation order is
88
* mx1, my1, mz1, mx2, my2, mz2, mx3,...
99
* so we get the corresponding components multiplying
1010
* by 3 in every iteration. The anisotropy *axis* has the
@@ -20,8 +20,8 @@ void compute_anis(double *spin, double *field, double *energy,
2020
double m_u = (spin[3 * i] * axis[3 * i] +
2121
spin[3 * i + 1] * axis[3 * i + 1] +
2222
spin[3 * i + 2] * axis[3 * i + 2]);
23-
24-
23+
24+
2525
field[3 * i] = 2 * Ku[i] * m_u * axis[3 * i] ;
2626
field[3 * i + 1] = 2 * Ku[i] * m_u * axis[3 * i + 1];
2727
field[3 * i + 2] = 2 * Ku[i] * m_u * axis[3 * i + 2];
@@ -31,3 +31,26 @@ void compute_anis(double *spin, double *field, double *energy,
3131
}
3232

3333
}
34+
35+
36+
void compute_anis_cubic(double *spin, double *field, double *energy,
37+
double *Kc, int n) {
38+
39+
/* Remember that the magnetisation order is
40+
* mx1, my1, mz1, mx2, my2, mz2, mx3,...
41+
* so we get the corresponding components multiplying
42+
* by 3 in every iteration.
43+
*
44+
*/
45+
#pragma omp parallel for
46+
for (int i = 0; i < n; i++) {
47+
int j = 3*i;
48+
field[j] = - 4*Kc[i]*spin[j]*spin[j]*spin[j];
49+
field[j+1] = - 4*Kc[i]*spin[j+1]*spin[j+1]*spin[j+1];
50+
field[j+2] = - 4*Kc[i]*spin[j+2]*spin[j+2]*spin[j+2];
51+
52+
energy[i] = -0.25*(field[j]*spin[j]+field[j+1]*spin[j+1]+field[j+2]*spin[j+2]) ;
53+
54+
}
55+
56+
}

fidimag/atomistic/lib/clib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ double compute_exch_energy(double *spin, double Jx, double Jy, double Jz,
3636

3737
void compute_anis(double *spin, double *field, double *energy, double *Ku,
3838
double *axis, int n);
39+
void compute_anis_cubic(double *spin, double *field, double *energy,
40+
double *Kc, int n);
3941

4042
void dmi_field_bulk(double *spin, double *field, double *energy, double *D,
4143
int *ngbs, int n);

fidimag/atomistic/lib/clib.pyx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ cdef extern from "clib.h":
6464
void compute_anis(double *spin, double *field, double *energy,
6565
double *Ku, double *axis, int n)
6666

67+
void compute_anis_cubic(double *spin, double *field, double *energy, double *Kc, int n)
68+
6769
void llg_rhs(double * dm_dt, double * spin,
6870
double *h, double *alpha, int *pins,
6971
double gamma, int n, int do_precession, double default_c)
@@ -159,14 +161,11 @@ def compute_exchange_energy(np.ndarray[double, ndim=1, mode="c"] spin,
159161
xperiodic, yperiodic)
160162

161163

162-
def compute_anisotropy(np.ndarray[double, ndim=1, mode="c"] spin,
163-
np.ndarray[double, ndim=1, mode="c"] field,
164-
np.ndarray[double, ndim=1, mode="c"] energy,
165-
np.ndarray[double, ndim=1, mode="c"] Ku,
166-
np.ndarray[double, ndim=1, mode="c"] axis,
167-
n):
168-
compute_anis(&spin[0], &field[0], &energy[0], &Ku[0],
169-
&axis[0], n)
164+
def compute_anisotropy(double [:] spin, double [:] field, double [:] energy, double [:] Ku, double [:] axis, n):
165+
compute_anis(&spin[0], &field[0], &energy[0], &Ku[0], &axis[0], n)
166+
167+
def compute_anisotropy_cubic(double [:] spin, double [:] field, double [:] energy, double [:] Kc, n):
168+
compute_anis_cubic(&spin[0], &field[0], &energy[0], &Kc[0], n)
170169

171170

172171
def compute_dmi_field(np.ndarray[double, ndim=1, mode="c"] spin,

fidimag/common/vtk.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ def __init__(self, mesh, header="", directory=".", filename="unnamed"):
2121
# for keyword argument dimensions: if the mesh is made up of
2222
# nx * ny * nz cells, it has (nx + 1) * (ny + 1) * (nz + 1)
2323
# vertices.
24+
print(mesh.grid)
2425
structure = pyvtk.RectilinearGrid(* mesh.grid)
2526
else:
2627
raise NotImplementedError(

tests/test_anis.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from fidimag.atomistic import Anisotropy
1+
from fidimag.atomistic import Anisotropy, CubicAnisotropy
22
from fidimag.common import CuboidMesh
33
from fidimag.atomistic import Sim
44
import numpy as np
@@ -17,6 +17,19 @@ def test_anis():
1717
field = anis.compute_field()
1818
assert field[0] == 2 * 99
1919

20+
def test_anis_cubic():
21+
mesh = CuboidMesh(nx=1, ny=1, nz=1)
22+
spin = np.array([0.6,0.8,0])
23+
anis = CubicAnisotropy(Kc=1.23)
24+
mu_s = np.ones(3)
25+
anis.setup(mesh, spin, mu_s)
26+
field = anis.compute_field()
27+
print field
28+
assert np.max(field-np.array([-1.06272,-2.51904, -0.]))<1e-6
29+
energy = anis.compute_energy()
30+
assert abs(energy-0.663216)<1e-5
31+
2032

2133
if __name__ == '__main__':
2234
test_anis()
35+
test_anis_cubic()

0 commit comments

Comments
 (0)