2
2
import warnings
3
3
from .integrators import BaseIntegrator
4
4
from .integrators import euler_step , runge_kutta_step
5
+ from itertools import cycle
5
6
6
7
import fidimag .extensions .nebm_clib as nebm_clib
7
8
@@ -149,7 +150,7 @@ def _step(self, t, y, h, f):
149
150
class FSIntegrator (BaseIntegrator ):
150
151
"""A step integrator considering the action of the band
151
152
"""
152
- def __init__ (self , band , forces , action , rhs_fun , n_images , n_dofs_image ,
153
+ def __init__ (self , band , forces , action , rhs_fun , action_fun , n_images , n_dofs_image ,
153
154
max_steps = 1000 ,
154
155
maxCreep = 5 , eta_scale = 1.0 , stopping_dE = 1e-6 , dEta = 2 ,
155
156
etaMin = 0.001 ,
@@ -158,6 +159,8 @@ def __init__(self, band, forces, action, rhs_fun, n_images, n_dofs_image,
158
159
):
159
160
super (FSIntegrator , self ).__init__ (band , rhs_fun )
160
161
162
+ self .action_fun = action_fun
163
+
161
164
self .i_step = 0
162
165
self .n_images = n_images
163
166
self .n_dofs_image = n_dofs_image
@@ -175,15 +178,18 @@ def run_until(self, t):
175
178
176
179
def run_for (self , n_steps ):
177
180
181
+ t = 0.0
178
182
nStart = 0
179
183
exitFlag = False
180
184
totalRestart = True
181
185
resetCount = 0
182
186
creepCount = 0
183
- self .trailE = np .zeros (nTrail )
187
+ self .trailAction = np .zeros (nTrail )
184
188
trailPool = cycle (range (nTrail )) # cycle through 0,1,...,(nTrail-1),0,1,...
185
189
eta = 1.0
186
190
191
+ INNER_DOFS = slice (self .n_dofs_image , - self .n_dofs_image )
192
+
187
193
while not exitFlag :
188
194
189
195
if totalRestart :
@@ -194,15 +200,17 @@ def run_for(self, n_steps):
194
200
# Compute from self.band. Do not update the step at this stage:
195
201
# This step updates the forces in the G array of the nebm module,
196
202
# using the current band state self.y
203
+ # TODO: remove time from chain method rhs
204
+ # make a specific function to update G??
197
205
self .rhs (t , self .y )
198
-
206
+ self . action = self . action_fun ()
199
207
200
208
# self.step += 1
201
- self .gradE_last [:] = - self .field # Scale field??
202
- self .gradE_last [~ _material ] = 0.0
203
- self .gradE [:] = self .gradE_last
204
- self .totalE_last = self .totalE
205
- self .trailE [nStart ] = self .totalE
209
+ self .forces_last [:] = self .forces # Scale field??
210
+ # self.gradE_last[~_material] = 0.0
211
+ # self.gradE[:] = self.gradE_last
212
+ self .action_last = self .action
213
+ self .trailAction [nStart ] = self .action
206
214
nStart = next (trailPool )
207
215
eta = 1.0
208
216
totalRestart = False
@@ -212,10 +220,28 @@ def run_for(self, n_steps):
212
220
# Creep stage: minimise with a fixed eta
213
221
while creepCount < maxCreep :
214
222
# Update spin. Avoid pinned or zero-Ms sites
215
- self .y [:] = self .y_last - eta * eta_scale * self .forces_images
223
+ self .y [:] = self .y_last + eta * eta_scale * self .forces
224
+ normalise_spins (self .y )
225
+
226
+ self .trailAction
227
+
228
+ self .rhs (t , self .y )
229
+ self .action = self .action_fun ()
230
+
231
+ self .trailAction [nStart ] = self .action
232
+ nStart = next (trailPool )
216
233
234
+ bandNormSquared = 0.0
235
+ # Getting averages of forces from the INNER images in the band (no extrema)
236
+ # (forces are given by vector G in the chain method code)
237
+ G_norms = np .linalg .norm (self .forces [INNER_DOFS ].reshape (- 1 , 3 ), axis = 1 )
238
+ # Compute the root mean square per image
239
+ rms_G_norms_per_image = np .sqrt (np .mean (G_norms .reshape (self .n_images - 2 , - 1 ), axis = 1 ))
240
+ mean_rms_G_norms_per_image = np .mean (rms_G_norms_per_image )
217
241
218
242
243
+ # 10 seems like a magic number; we set here a minimum number of evaulations
244
+ if (nStart > nTrail * 10 ) and :
219
245
220
246
221
247
0 commit comments