@@ -48,25 +48,25 @@ class DMI(Energy):
48
48
known as anti-skyrmions are stabilised with this
49
49
DMI type
50
50
51
+ custom :: Pass n number of DMI constants as the main argument and
52
+ specify a dmi_vector array of length 18 * n. This array
53
+ has the dmi vector components for every NN in the order
54
+
55
+ [D1x(-x) D1y(-x) D1z(-x) D1x(+x) D1y(+x) ... D1z(+z)
56
+ D2x(-x) D2y(-x) ... D2z(+z)
57
+ ...
58
+ ]
59
+
51
60
ARGUMENTS: ----------------------------------------------------------------
52
61
53
62
D :: DMI vector norm which can be specified as an int, float, (X * n)
54
- array (X=6 for bulk DMI and X=4 for interfacial DMI), (n) array
55
63
or spatially dependent scalar field function. The units are
56
64
Joules / ( meter **2 ).
57
65
58
66
int, float: D will have the same magnitude for every NN of the
59
67
spins at every mesh node, given by this magnitude
60
68
61
- (n) array: D will have the same magnitude for every NN on every
62
- mesh node but will vary according to the values of the array,
63
- i.e. the value of D for the 6 NNs at the i-th mesh site will be
64
- given by the i-th value of the array
65
-
66
- (X * n) array: Manually specify the DMI vector norm for every NN
67
- at every mesh node. The bulk DMI considers the 6 NNs from every
68
- node and interfacial and D_2d DMI are 2D so they only consider 4
69
- NNs from the xy plane.
69
+ (n) array or list: D for every DMI constant
70
70
71
71
OPTIONAL ARGUMENTS: -------------------------------------------------------
72
72
@@ -75,18 +75,19 @@ class DMI(Energy):
75
75
76
76
"""
77
77
78
- def __init__ (self , D , name = 'DMI' , dmi_type = 'bulk' , D2 = None ):
78
+ def __init__ (self , D , name = 'DMI' , dmi_type = 'bulk' , dmi_vector = None ):
79
79
"""
80
80
"""
81
81
self .D = D
82
82
self .name = name
83
83
self .jac = True
84
84
self .dmi_type = dmi_type
85
+ self .dmi_vector = dmi_vector
85
86
86
87
# Number of NNs for the calculation of the corresponding DMI
87
88
# Interfacial or D_2d are 2D so we use 4 ngbs
88
- types = ['bulk' , 'interfacial' , 'D_n' , 'C_n' , 'D_2d' ]
89
- if self .dmi_type not in [ 'bulk' , 'interfacial' , 'D_n' , 'C_n' , 'D_2d' ] :
89
+ types = ['bulk' , 'interfacial' , 'D_n' , 'C_n' , 'D_2d' , 'custom' ]
90
+ if self .dmi_type not in types :
90
91
raise Exception (
91
92
"Unsupported DMI type: {}, " +
92
93
"available options:\n {}" .format (self .dmi_type , * types )
@@ -98,142 +99,159 @@ def __init__(self, D, name='DMI', dmi_type='bulk', D2=None):
98
99
# raise Exception("For C_n and D_n symmetry, you must also pass a D2 value"
99
100
# " as this material class has multiple DMI constants")
100
101
101
-
102
102
def setup (self , mesh , spin , Ms , Ms_inv ):
103
103
super (DMI , self ).setup (mesh , spin , Ms , Ms_inv )
104
104
105
105
if self .dmi_type == 'bulk' :
106
106
self .dmi_vector = np .array ([- 1. , 0 , 0 ,
107
- 1. , 0 , 0 ,
108
- 0 , - 1. , 0 ,
109
- 0 , 1. , 0 ,
110
- 0 , 0 , - 1. ,
111
- 0 , 0 , 1.
112
- ])
107
+ 1. , 0 , 0 ,
108
+ 0 , - 1. , 0 ,
109
+ 0 , 1. , 0 ,
110
+ 0 , 0 , - 1. ,
111
+ 0 , 0 , 1.
112
+ ])
113
113
114
114
elif self .dmi_type == 'interfacial' :
115
115
self .dmi_vector = np .array ([0 , - 1. , 0 , # -x
116
- 0 , 1. , 0 , # +x
117
- 1. , 0 , 0 , # -y
118
- - 1. , 0 , 0 , # +y
119
- 0 , 0 , 0 , # -z
120
- 0 , 0 , 0 # +z
121
- ])
116
+ 0 , 1. , 0 , # +x
117
+ 1. , 0 , 0 , # -y
118
+ - 1. , 0 , 0 , # +y
119
+ 0 , 0 , 0 , # -z
120
+ 0 , 0 , 0 # +z
121
+ ])
122
122
123
123
elif self .dmi_type == 'D_2d' :
124
124
self .dmi_vector = np .array ([1. , 0 , 0 , # -x
125
- - 1. , 0 , 0 , # +x
126
- 0 , - 1. , 0 , # -y
127
- 0 , 1. , 0 , # +y
128
- 0 , 0 , 0 , # -z
129
- 0 , 0 , 0 # +z
130
- ])
125
+ - 1. , 0 , 0 , # +x
126
+ 0 , - 1. , 0 , # -y
127
+ 0 , 1. , 0 , # +y
128
+ 0 , 0 , 0 , # -z
129
+ 0 , 0 , 0 # +z
130
+ ])
131
131
132
132
elif self .dmi_type == 'D_n' :
133
- self .dmi_vector = np .array ([1.0 , 0 , 0 , # D1 components
134
- - 1 , 0 , 0 ,
135
- 0 , - 1 , 0 ,
136
- 0 , 1 , 0 ,
137
- 0 , 0 , 0 ,
138
- 0 , 0 , 0 ,
139
- 0 , 0 , 0 , # D2 components
140
- 0 , 0 , 0 ,
141
- 0 , 0 , 0 ,
142
- 0 , 0 , 0 ,
143
- 0 , 0 , 1 ,
144
- 0 , 0 , - 1 ,
145
- ])
133
+ self .dmi_vector = np .array ([1.0 , 0 , 0 , # D1 components
134
+ - 1 , 0 , 0 ,
135
+ 0 , - 1 , 0 ,
136
+ 0 , 1 , 0 ,
137
+ 0 , 0 , 0 ,
138
+ 0 , 0 , 0 ,
139
+ 0 , 0 , 0 , # D2 components
140
+ 0 , 0 , 0 ,
141
+ 0 , 0 , 0 ,
142
+ 0 , 0 , 0 ,
143
+ 0 , 0 , 1 ,
144
+ 0 , 0 , - 1 ,
145
+ ])
146
146
147
147
elif self .dmi_type == 'C_n' :
148
- self .dmi_vector = np .array ([0 , - 1. , 0 , # -x
149
- 0 , 1. , 0 , # +x
150
- 1. , 0 , 0 , # -y
151
- - 1. , 0 , 0 , # +y
152
- 0 , 0 , 0 , # -z
153
- 0 , 0 , 0 , # +z
154
- 1 , 0 , 0 , # D2 components
155
- - 1 , 0 , 0 ,
156
- 0 , - 1 , 0 ,
157
- 0 , 1 , 0 ,
158
- 0 , 0 , 0 ,
159
- 0 , 0 , 0 ,
160
- ])
148
+ self .dmi_vector = np .array ([0 , - 1. , 0 , # -x
149
+ 0 , 1. , 0 , # +x
150
+ 1. , 0 , 0 , # -y
151
+ - 1. , 0 , 0 , # +y
152
+ 0 , 0 , 0 , # -z
153
+ 0 , 0 , 0 , # +z
154
+ 1 , 0 , 0 , # D2 components
155
+ - 1 , 0 , 0 ,
156
+ 0 , - 1 , 0 ,
157
+ 0 , 1 , 0 ,
158
+ 0 , 0 , 0 ,
159
+ 0 , 0 , 0 ,
160
+ ])
161
+ elif self .dmi_type == 'custom' :
162
+ self .dmi_vector = np .array (self .dmi_vector )
163
+ # Example:
164
+ # self.DMI_vector = [ 0, 0, D1, # DMI 1
165
+ # 0, 0, -D1,
166
+ # 0, 0, 0,
167
+ # 0, 0, 0,
168
+ # 0, 0, 0,
169
+ # 0, 0, 0,
170
+ # 0, 0, 0, # DMI 2
171
+ # 0, 0, 0,
172
+ # 0, D2, 0,
173
+ # 0, -D2, 0,
174
+ # 0, 0, 0,
175
+ # 0, 0, 0,
176
+ # ]
177
+ n_Ds = len (self .dmi_vector ) // 18
178
+
179
+ if len (self .dmi_vector ) % 18 != 0 :
180
+ raise Exception ('The DMI vector length must be a mult of 18: '
181
+ ' N of DMIs times 3 * number of ngbs = 18' )
182
+
183
+ if n_Ds > 1 :
184
+ self .Ds = helper .init_vector (self .D , self .mesh , dim = n_Ds )
185
+ else :
186
+ self .Ds = helper .init_scalar (self .D , self .mesh )
187
+
188
+ self .n_dmis = n_Ds
189
+
161
190
if self .dmi_type == 'C_n' or self .dmi_type == 'D_n' :
162
191
self .Ds = helper .init_vector (self .D , self .mesh , dim = 2 )
163
- D0 = self .Ds [::2 ]
164
- D1 = self .Ds [1 ::2 ]
165
- self .Ds [:] = np .hstack ([D0 , D1 ])
192
+ self .n_dmis = 2
166
193
else :
167
194
self .Ds = helper .init_scalar (self .D , self .mesh )
168
-
195
+ self . n_dmis = 1
169
196
170
197
def compute_field (self , t = 0 , spin = None ):
171
198
if spin is not None :
172
199
m = spin
173
200
else :
174
201
m = self .spin
175
202
176
-
177
-
178
- if self .dmi_type == 'D_n' or self .dmi_type == 'C_n' :
179
- # Now have two vaues for D,
180
- # so what we can do is intersperse the D values, i.e.
181
- # [D^1_0, D^2_0, D^1_1, D^2_1, ... D^1_n, D^2_n]
182
- # So to address cell i's values, you can use
183
- # D1 = 2*i
184
- # D2 = 2*i + 1
185
-
186
- micro_clib .compute_dmi_field (m ,
187
- self .field ,
188
- self .energy ,
189
- self .Ms_inv ,
190
- self .Ds [:self .n ],
191
- self .dmi_vector [:18 ],
192
- self .dx ,
193
- self .dy ,
194
- self .dz ,
195
- self .n ,
196
- self .neighbours
197
- )
198
-
199
- field0 = np .zeros_like (self .field )
200
- micro_clib .compute_dmi_field (m ,
201
- field0 ,
202
- self .energy ,
203
- self .Ms_inv ,
204
- self .Ds [self .n :],
205
- self .dmi_vector [18 :],
206
- self .dx ,
207
- self .dy ,
208
- self .dz ,
209
- self .n ,
210
- self .neighbours
211
- )
212
- # print('field0 minmax = ', np.min(field0), np.max(field0))
213
- # print('D0 minmax = ', np.min(self.Ds[:self.n]), np.max(self.Ds[:self.n]))
214
- # print('D1 minmax = ', np.min(self.Ds[self.n:]), np.max(self.Ds[self.n:]))
215
- self .field += field0
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
- else :
226
- micro_clib .compute_dmi_field (m ,
227
- self .field ,
228
- self .energy ,
229
- self .Ms_inv ,
230
- self .Ds ,
231
- self .dmi_vector ,
232
- self .dx ,
233
- self .dy ,
234
- self .dz ,
235
- self .n ,
236
- self .neighbours
237
- )
203
+ # if self.dmi_type == 'D_n' or self.dmi_type == 'C_n':
204
+ # # Now have two vaues for D,
205
+ # # so what we can do is intersperse the D values, i.e.
206
+ # # [D^1_0, D^2_0, D^1_1, D^2_1, ... D^1_n, D^2_n]
207
+ # # So to address cell i's values, you can use
208
+ # # D1 = 2*i
209
+ # # D2 = 2*i + 1
210
+
211
+ # micro_clib.compute_dmi_field(m,
212
+ # self.field,
213
+ # self.energy,
214
+ # self.Ms_inv,
215
+ # self.Ds[:self.n],
216
+ # self.dmi_vector[:18],
217
+ # self.dx,
218
+ # self.dy,
219
+ # self.dz,
220
+ # self.n,
221
+ # self.neighbours
222
+ # )
223
+
224
+ # field0 = np.zeros_like(self.field)
225
+ # micro_clib.compute_dmi_field(m,
226
+ # field0,
227
+ # self.energy,
228
+ # self.Ms_inv,
229
+ # self.Ds[self.n:],
230
+ # self.dmi_vector[18:],
231
+ # self.dx,
232
+ # self.dy,
233
+ # self.dz,
234
+ # self.n,
235
+ # self.neighbours
236
+ # )
237
+ # # print('field0 minmax = ', np.min(field0), np.max(field0))
238
+ # # print('D0 minmax = ', np.min(self.Ds[:self.n]), np.max(self.Ds[:self.n]))
239
+ # # print('D1 minmax = ', np.min(self.Ds[self.n:]), np.max(self.Ds[self.n:]))
240
+ # self.field += field0
241
+
242
+ # else:
243
+ micro_clib .compute_dmi_field (m ,
244
+ self .field ,
245
+ self .energy ,
246
+ self .Ms_inv ,
247
+ self .Ds ,
248
+ self .n_dmis ,
249
+ self .dmi_vector ,
250
+ self .dx ,
251
+ self .dy ,
252
+ self .dz ,
253
+ self .n ,
254
+ self .neighbours
255
+ )
238
256
239
257
return self .field
0 commit comments