Skip to content

Commit c5eb798

Browse files
committed
Add 4th Order UniaxialAnisotropy
1 parent cf3865f commit c5eb798

File tree

6 files changed

+125
-5
lines changed

6 files changed

+125
-5
lines changed

examples/micromagnetic/skyrmion/Ku_H/main.py

Lines changed: 4 additions & 4 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, DMI, UniaxialAnisotropy
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, DMI, UniaxialAnisotropy
9+
from fidimag.micro import Zeeman, TimeZeeman
1010
from fidimag.common.fileio import DataReader
1111

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

fidimag/micro/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
from .exchange import UniformExchange
44
from .exchange_rkky import ExchangeRKKY
55
from .zeeman import Zeeman, TimeZeeman
6-
from .anisotropy import UniaxialAnisotropy
6+
from .anisotropy import UniaxialAnisotropy, UniaxialAnisotropy4
77
from .dmi import DMI
88
from .baryakhtar import LLBar, LLBarFull
99
from .simple_demag import SimpleDemag

fidimag/micro/anisotropy.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,47 @@ def compute_field(self, t=0, spin=None):
3838
self.ny,
3939
self.nz)
4040
return self.field
41+
42+
43+
class UniaxialAnisotropy4(Energy):
44+
45+
"""
46+
4th Order Uniaxial Anisotropy
47+
"""
48+
49+
def __init__(self, K1, K2, axis=(1, 0, 0), name='UAnisotropy4'):
50+
self.K1 = K1
51+
self.K2 = K2
52+
self.name = name
53+
self.jac = True
54+
self.axis = axis
55+
56+
def setup(self, mesh, spin, Ms, Ms_inv):
57+
super(UniaxialAnisotropy4, self).setup(mesh, spin, Ms, Ms_inv)
58+
59+
self._K1 = helper.init_scalar(self.K1, self.mesh)
60+
self._K2 = helper.init_scalar(self.K2, self.mesh)
61+
self._axis = helper.init_vector(self.axis, self.mesh, 3, norm=True)
62+
63+
def compute_field(self, t=0, spin=None):
64+
if spin is not None:
65+
m = spin
66+
else:
67+
m = self.spin
68+
micro_clib.compute_anisotropy4_micro(m,
69+
self.field,
70+
self.energy,
71+
self.Ms_inv,
72+
self._K1,
73+
self._K2,
74+
self._axis,
75+
self.nx,
76+
self.ny,
77+
self.nz)
78+
79+
80+
81+
82+
83+
return self.field
84+

fidimag/micro/lib/anis.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,52 @@ void compute_uniaxial_anis(double *restrict m, double *restrict field, double *r
3030

3131
}
3232

33+
34+
void compute_uniaxial4_anis(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
35+
double *restrict K1, double *restrict K2, double *restrict axis, int nx, int ny, int nz) {
36+
37+
int n = nx * ny * nz;
38+
39+
// Follows calculation of OOMMF extension by Hans and Richard Boardman
40+
// http://www.soton.ac.uk/~fangohr/software/oxs_uniaxial4/download/uniaxialanisotropy4.cc
41+
42+
#pragma omp parallel for
43+
for (int i = 0; i < n; i++) {
44+
int j = 3 * i;
45+
46+
if (Ms_inv[i] == 0.0) {
47+
field[j] = 0;
48+
field[j + 1] = 0;
49+
field[j + 2] = 0;
50+
energy[i] = 0;
51+
continue;
52+
}
53+
54+
double k1 = K1[i];
55+
double k2 = K2[i];
56+
57+
double field_mult1 = MU0_INV * 2.0 * k1 * Ms_inv[i];
58+
double field_mult2 = MU0_INV * 4.0 * k2 * Ms_inv[i];
59+
double m_dot_u = m[j] * axis[j] + m[j + 1] * axis[j + 1] + m[j + 2] * axis[j + 2];
60+
61+
if (k1 <= 0) {
62+
field[j + 0] = (field_mult1*m_dot_u) * axis[j + 0] + (field_mult2 * m_dot_u*m_dot_u*m_dot_u) * axis[j + 0];
63+
field[j + 1] = (field_mult1*m_dot_u) * axis[j + 1] + (field_mult2 * m_dot_u*m_dot_u*m_dot_u) * axis[j + 1];
64+
field[j + 2] = (field_mult1*m_dot_u) * axis[j + 2] + (field_mult2 * m_dot_u*m_dot_u*m_dot_u) * axis[j + 2];
65+
energy[i] = -k1*m_dot_u*m_dot_u - k2*m_dot_u*m_dot_u*m_dot_u*m_dot_u;
66+
}
67+
68+
else {
69+
double u_x_m[3];
70+
u_x_m[0] = cross_x(axis[j], axis[j+1], axis[j+2], m[j], m[j+1], m[j+2]);
71+
u_x_m[1] = cross_y(axis[j], axis[j+1], axis[j+2], m[j], m[j+1], m[j+2]);
72+
u_x_m[2] = cross_z(axis[j], axis[j+1], axis[j+2], m[j], m[j+1], m[j+2]);
73+
double u_x_m_mag2 = u_x_m[1]*u_x_m[1] + u_x_m[1]*u_x_m[1] + u_x_m[2]*u_x_m[2];
74+
field[j + 0] = (field_mult1*m_dot_u) * axis[j + 0] + (field_mult2*m_dot_u*m_dot_u*m_dot_u) * axis[j + 0];
75+
field[j + 1] = (field_mult1*m_dot_u) * axis[j + 1] + (field_mult2*m_dot_u*m_dot_u*m_dot_u) * axis[j + 1];
76+
field[j + 2] = (field_mult1*m_dot_u) * axis[j + 2] + (field_mult2*m_dot_u*m_dot_u*m_dot_u) * axis[j + 2];
77+
energy[i] = (k1 + 2*k2)*u_x_m_mag2 - k2*u_x_m_mag2*u_x_m_mag2;
78+
}
79+
}
80+
81+
}

fidimag/micro/lib/micro_clib.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,8 @@ void compute_exch_field_rkky_micro(double *m, double *field, double *energy, dou
2828
void compute_uniaxial_anis(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
2929
double *restrict Ku, double *restrict axis, int nx, int ny, int nz);
3030

31+
void compute_uniaxial4_anis(double *restrict m, double *restrict field, double *restrict energy, double *restrict Ms_inv,
32+
double *restrict K1, double *restrict K2, double *restrict axis, int nx, int ny, int nz);
33+
3134
double skyrmion_number(double *restrict spin, double *restrict charge,
3235
int nx, int ny, int nz, int *restrict ngbs);

fidimag/micro/lib/micro_clib.pyx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,20 @@ cdef extern from "micro_clib.h":
2121
double *Ku, double *axis,
2222
int nx, int ny, int nz)
2323

24+
25+
void compute_uniaxial4_anis(double *m, double *field,
26+
double *energy, double *Ms_inv,
27+
double *K1, double *K2,
28+
double *axis,
29+
int nx, int ny, int nz)
30+
31+
2432
double skyrmion_number(double *m, double *charge,
2533
int nx, int ny, int nz, int *ngbs)
2634

2735

36+
37+
2838
def compute_exchange_field_micro(double [:] m,
2939
double [:] field,
3040
double [:] energy,
@@ -74,6 +84,20 @@ def compute_anisotropy_micro(double [:] m,
7484
compute_uniaxial_anis(&m[0], &field[0], &energy[0], &Ms_inv[0],
7585
&Ku[0], &axis[0], nx, ny, nz)
7686

87+
88+
def compute_anisotropy4_micro(double [:] m,
89+
double [:] field,
90+
double [:] energy,
91+
double [:] Ms_inv,
92+
double [:] K1,
93+
double [:] K2,
94+
double [:] axis,
95+
nx, ny, nz):
96+
97+
compute_uniaxial4_anis(&m[0], &field[0], &energy[0], &Ms_inv[0],
98+
&K1[0], &K2[0], &axis[0], nx, ny, nz)
99+
100+
77101
def compute_skyrmion_number(double [:] m,
78102
double [:] charge,
79103
nx, ny, nz,

0 commit comments

Comments
 (0)