Skip to content

Commit 48fff3f

Browse files
Merge branch 'nebm-kf' of github.com:computationalmodelling/fidimag into nebm-kf
2 parents dce6cd3 + aee3da0 commit 48fff3f

File tree

8 files changed

+129
-69
lines changed

8 files changed

+129
-69
lines changed

.readthedocs.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
version: 2
2+
3+
build:
4+
os: "ubuntu-20.04"
5+
tools:
6+
python: "mambaforge-22.9"
7+
8+
conda:
9+
environment: doc/environment.yml
10+
11+
sphinx:
12+
# Path to your Sphinx configuration file.
13+
configuration: doc/conf.py

doc/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@
7878

7979
html_theme_options = {
8080
"github_url": "https://github.com/computationalmodelling/fidimag",
81-
"use_edit_page_button": True,
81+
# "use_edit_page_button": True,
8282
"show_toc_level": 1,
8383
# "navbar_align": "right", # For testing that the navbar items align properly
8484
}

fidimag/common/chain_method_base.py

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -199,10 +199,7 @@ def __init__(self, sim,
199199
self.n_dofs_image_material = np.sum(self._material)
200200

201201
# VTK saver for the magnetisation/spin field --------------------------
202-
self.VTK = VTK(self.mesh,
203-
directory='vtks'.format(self.name),
204-
filename='image'
205-
)
202+
self.VTK = VTK(self.mesh, directory='vtks', filename='image')
206203

207204
# Functions to convert the energy band coordinates to Cartesian
208205
# coordinates when saving VTK and NPY files We assume Cartesian
@@ -303,6 +300,9 @@ def __init__(self, sim,
303300

304301
self.G_log = []
305302

303+
# Make sure the sim object does not have a driver: (see sim_base.py -> set_m)
304+
sim.driver = None
305+
306306
# TODO: Move this property to the NEBM classes because they are only
307307
# relevant to the NEBM and not the string method
308308
@property
@@ -403,21 +403,17 @@ def save_npys(self, coordinates_function=None):
403403
np.save(name, self.band[i])
404404
self.band.shape = (-1)
405405

406-
def initialise_integrator(self,
407-
integrator='sundials',
408-
rtol=1e-6, atol=1e-6):
406+
def initialise_integrator(self, integrator='sundials', rtol=1e-6, atol=1e-6):
409407
self.t = 0
410408
self.iterations = 0
411409
self.ode_count = 1
412410

413411
if integrator == 'sundials':
414412
if not self.openmp:
415-
self.integrator = cvode.CvodeSolver(self.band,
416-
self.Sundials_RHS)
413+
self.integrator = cvode.CvodeSolver(self.band, self.Sundials_RHS)
417414
self.integrator.set_options(rtol, atol)
418415
else:
419-
self.integrator = cvode.CvodeSolver_OpenMP(self.band,
420-
self.Sundials_RHS)
416+
self.integrator = cvode.CvodeSolver_OpenMP(self.band, self.Sundials_RHS)
421417
self.integrator.set_options(rtol, atol)
422418
# elif integrator == 'scipy':
423419
# self.integrator = ScipyIntegrator(self.band, self.step_RHS)
@@ -440,8 +436,7 @@ def initialise_integrator(self,
440436
# In Verlet algorithm we only use the total force G and not YxYxG:
441437
self._llg_evolve = False
442438
else:
443-
raise Exception('No valid integrator specified. Available: '
444-
'"sundials", "scipy"')
439+
raise Exception('No valid integrator specified. Available: "sundials", "scipy"')
445440

446441
def create_tablewriter(self):
447442
entities_energy = {
@@ -763,11 +758,15 @@ def compute_polynomial_factors(self, compute_fields=True):
763758
self.compute_tangents(self.band)
764759
self.compute_distances()
765760

761+
self.gradientE.shape = (self.n_images, -1)
762+
self.tangents.shape = (self.n_images, -1)
763+
766764
deltas = np.zeros(self.n_images)
767765
for i in range(self.n_images):
768-
deltas[i] = np.dot(self.scale * (self.gradientE).reshape(self.n_images, -1)[i],
769-
self.tangents.reshape(self.n_images, -1)[i]
770-
)
766+
deltas[i] = np.dot(self.scale * self.gradientE[i], self.tangents[i])
767+
768+
self.gradientE.shape = (-1)
769+
self.tangents.shape = (-1)
771770

772771
ds = self.path_distances
773772
E = self.energies

fidimag/common/chain_method_integrators.py

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ def __init__(self, ChainObj,
160160
# band, forces, distances, rhs_fun, action_fun,
161161
# n_images, n_dofs_image,
162162
maxSteps=1000,
163-
maxCreep=6, actionTol=1e-2, forcesTol=1e-6,
164-
etaScale=1e-6, dEta=4., minEta=1e-6,
163+
maxCreep=4, actionTol=1e-2, forcesTol=1e-8,
164+
etaScale=1e4, dEta=4., minEta=1e-6,
165165
# perturbSeed=42, perturbFactor=0.1,
166166
nTrail=13, resetMax=20
167167
):
@@ -188,13 +188,17 @@ def __init__(self, ChainObj,
188188
self.n_dofs_image = self.ChainObj.n_dofs_image
189189
# self.forces_prev = np.zeros_like(band).reshape(n_images, -1)
190190
# self.G :
191-
self.forces = self.ChainObj.G
191+
self.forces = -self.ChainObj.G
192192
self.distances = self.ChainObj.distances
193193
self.forces_old = np.zeros_like(self.ChainObj.G)
194194

195195
# self.band should be just a reference to the band in the ChainObj
196-
self.band = self.ChainObj.band
197-
self.band_old = np.copy(self.band)
196+
# self.band = self.ChainObj.band
197+
self.band_old = np.copy(self.ChainObj.band)
198+
199+
# CHECK
200+
self.ChainObj.k[:] = 0.0
201+
self.ChainObj.spring_force[:] = 0.0
198202

199203
def run_for(self, n_steps):
200204

@@ -218,43 +222,67 @@ def run_for(self, n_steps):
218222
self.ChainObj.tablewriter_dm.save()
219223

220224
np.save(self.ChainObj.name + '_init.npy', self.ChainObj.band)
225+
self.action_old = 0.0
221226

222227
while not exitFlag:
223228

224229
if totalRestart:
225230
if self.i_step > 0:
226231
print('Restarting')
227-
self.band[:] = self.band_old
232+
self.ChainObj.band[:] = self.band_old
228233

229234
# Compute from self.band. Do not update the step at this stage:
230235
# This step updates the forces and distances in the G array of the nebm module,
231236
# using the current band state self.y
232237
# TODO: make a specific function to update G??
233238
print('Computing forces')
234-
self.ChainObj.nebm_step(self.band, ensure_zero_extrema=True)
239+
self.ChainObj.nebm_step(self.ChainObj.band, ensure_zero_extrema=True)
235240
self.action = self.ChainObj.compute_action()
236241

237242
# self.step += 1
238-
self.forces_old[:] = self.forces # Scale field??
243+
self.forces_old[:] = self.ChainObj.G # Scale field??
239244
# self.gradE_last[~_material] = 0.0
240245
# self.gradE[:] = self.gradE_last
241246
self.action_old = self.action
242247
self.trailAction[nStart] = self.action
243248
nStart = next(trailPool)
244249
eta = 1.0
245250
totalRestart = False
246-
247251
creepCount = 0
248252

253+
249254
# Creep stage: minimise with a fixed eta
250255
while creepCount < self.maxCreep:
251256
# Update spin. Avoid pinned or zero-Ms sites
252-
self.band[:] = self.band_old - eta * self.etaScale * self.forces_old
253-
normalise_spins(self.band)
257+
self.ChainObj.band[:] = self.band_old - eta * self.etaScale * self.forces_old
258+
normalise_spins(self.ChainObj.band)
259+
260+
# self.refine_path(self.ChainObj.path_distances, self.ChainObj.band) # Resets the path to equidistant structures (smoothing kinks?)
261+
# normalise_spins(self.ChainObj.band)
262+
263+
self.trailAction[nStart] = self.action
264+
nStart = next(trailPool)
254265

255-
self.trailAction
266+
self.ChainObj.nebm_step(self.ChainObj.band, ensure_zero_extrema=True)
267+
268+
# gradE = self.ChainObj.gradientE.reshape(self.n_images, -1)
269+
# band = self.ChainObj.band.reshape(self.n_images, -1)
270+
# tgts = self.ChainObj.tangents.reshape(self.n_images, -1)
271+
# forces = self.ChainObj.G.reshape(self.n_images, -1)
272+
# for im_idx in range(gradE.shape[0]):
273+
# gradE_dot_tgt = np.sum(forces[im_idx] * tgts[im_idx])
274+
# print(f'Im {im_idx}', forces[im_idx], tgts[im_idx], gradE_dot_tgt)
275+
# print('-----', np.linalg.norm(tgts[im_idx]))
276+
# gradE = self.ChainObj.gradientE.reshape(self.n_images, -1)
277+
# band = self.ChainObj.band.reshape(self.n_images, -1)
278+
# tgts = self.ChainObj.tangents.reshape(self.n_images, -1)
279+
# forces = self.ChainObj.G.reshape(self.n_images, -1)
280+
281+
# for im_idx in range(gradE.shape[0]):
282+
# gradE_dot_tgt = np.sum(forces[im_idx] * tgts[im_idx])
283+
# print(np.linalg.norm(tgts[im_idx]), gradE_dot_tgt)
284+
# print('--')
256285

257-
self.ChainObj.nebm_step(self.band, ensure_zero_extrema=True)
258286
self.action = self.ChainObj.compute_action()
259287

260288
self.trailAction[nStart] = self.action
@@ -269,9 +297,9 @@ def run_for(self, n_steps):
269297
# Getting averages of forces from the INNER images in the band (no extrema)
270298
# (forces are given by vector G in the chain method code)
271299
# TODO: we might use all band images, not only inner ones, although G is zero at the extrema
272-
Gnorms2 = np.sum(self.forces[INNER_DOFS].reshape(-1, 3)**2, axis=1)
300+
Gnorms2 = np.sum(self.ChainObj.G.reshape(-1, 3)**2, axis=1)
273301
# Compute the root mean square per image
274-
rms_G_norms_per_image = np.sum(Gnorms2.reshape(self.n_images - 2, -1), axis=1) / self.ChainObj.n_spins
302+
rms_G_norms_per_image = np.sum(Gnorms2.reshape(self.n_images, -1), axis=1) / self.ChainObj.n_images
275303
rms_G_norms_per_image = np.sqrt(rms_G_norms_per_image)
276304
mean_rms_G_norms_per_image = np.mean(rms_G_norms_per_image)
277305

@@ -314,7 +342,7 @@ def run_for(self, n_steps):
314342
resetCount += 1
315343
# bestAction = self.action_old
316344
print('Refining path')
317-
self.refine_path(self.ChainObj.path_distances, self.band) # Resets the path to equidistant structures (smoothing kinks?)
345+
self.refine_path(self.ChainObj.path_distances, self.ChainObj.band) # Resets the path to equidistant structures (smoothing kinks?)
318346
# PathChanged[:] = True
319347

320348
if resetCount > self.resetMax:
@@ -328,14 +356,14 @@ def run_for(self, n_steps):
328356
# Otherwise, just start again with smaller alpha
329357
else:
330358
print('Decreasing alpha')
331-
self.band[:] = self.band_old
332-
self.forces[:] = self.forces_old
359+
self.ChainObj.band[:] = self.band_old
360+
self.ChainObj.G[:] = self.forces_old
333361
# If action decreases, move to next creep step
334362
else:
335363
creepCount += 1
336364
self.action_old = self.action
337-
self.band_old[:] = self.band
338-
self.forces_old[:] = self.forces
365+
self.band_old[:] = self.ChainObj.band
366+
self.forces_old[:] = self.ChainObj.G
339367

340368
if (mean_rms_G_norms_per_image < self.forcesTol):
341369
print('Change of mean of the force RMSquares negligible')

fidimag/common/nebm_FS.py

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,8 @@ def __init__(self, sim,
126126
openmp=openmp
127127
)
128128

129+
# The gradient = - H_eff
130+
self.gradientE = np.zeros_like(self.band)
129131
# We need the gradient norm to calculate the action
130132
self.gradientENorm = np.zeros(self.n_images)
131133

@@ -243,7 +245,7 @@ def compute_effective_field_and_energy(self, y):
243245
# Do not update the extreme images
244246
for i in range(1, len(y) - 1):
245247

246-
self.sim.set_m(y[i])
248+
self.sim.spin[:] = y[i]
247249
# elif self.coordinates == 'Cartesian':
248250
# self.sim.set_m(self.band[i])
249251

@@ -263,9 +265,9 @@ def compute_tangents(self, y):
263265
nebm_clib.project_images(self.tangents, y,
264266
self.n_images, self.n_dofs_image
265267
)
266-
# nebm_clib.normalise_images(self.tangents,
267-
# self.n_images, self.n_dofs_image
268-
# )
268+
nebm_clib.normalise_images(self.tangents,
269+
self.n_images, self.n_dofs_image
270+
)
269271

270272
def compute_spring_force(self, y):
271273
"""
@@ -321,13 +323,18 @@ def compute_action(self):
321323
# )
322324

323325
# NOTE: Gradient here is projected in the S2^N tangent space
326+
# nebm_clib.project_images(self.gradientE, self.band, self.n_images, self.n_dofs_image)
324327
self.gradientE.shape = (self.n_images, -1)
325-
# NOTE: HEre we have to divide by the number of spins per image,not n_images:
328+
# # NOTE: HEre we have to divide by the number of spins per image,not n_images:
326329
Gnorms2 = np.sum(self.gradientE**2, axis=1) / self.n_spins
330+
# self.G.shape = (self.n_images, -1)
331+
# Gnorms2 = np.sum(self.G**2, axis=1) / self.n_spins
327332

328333
# Compute the root mean square per image
329-
self.gradientENorm[:] = np.sqrt(Gnorms2)
334+
# self.gradientENorm[:] = np.sqrt(Gnorms2)
335+
self.gradientENorm[:] = np.linalg.norm(self.gradientE, axis=1) / self.n_spins
330336
self.gradientE.shape = (-1)
337+
# self.G.shape = (-1)
331338

332339
# DEBUG:
333340
# print('gradEnorm', self.gradientENorm)
@@ -374,8 +381,11 @@ def nebm_step(self, y, ensure_zero_extrema=False):
374381

375382
self.compute_effective_field_and_energy(y)
376383
nebm_clib.project_images(self.gradientE, y, self.n_images, self.n_dofs_image)
377-
self.compute_tangents(y)
378-
nebm_clib.normalise_spins(self.tangents, self.n_images, self.n_dofs_image)
384+
# print('GRADE', self.gradientE)
385+
self.compute_tangents(y) # In the function: tangents -> project -> normalise
386+
# self.tangents.shape = (self.n_images, -1)
387+
# print(f'tangent norms', np.linalg.norm(self.tangents, axis=1))
388+
# self.tangents.shape = (-1)
379389
self.compute_spring_force(y)
380390

381391
nebm_clib.compute_effective_force(self.G,
@@ -386,6 +396,27 @@ def nebm_step(self, y, ensure_zero_extrema=False):
386396
self.n_images,
387397
self.n_dofs_image
388398
)
399+
# self.G.shape = (self.n_images, -1, 3)
400+
# self.tangents.shape = (self.n_images, -1, 3)
401+
# self.gradientE.shape = (self.n_images, -1, 3)
402+
# for im_idx in range(self.G.shape[0]):
403+
# for s_idx in range(self.G.shape[1]):
404+
# gradE_dot_t = np.dot(self.gradientE[im_idx, s_idx, :], self.tangents[im_idx, s_idx, :])
405+
# self.G[im_idx, s_idx, :] = -self.gradientE[im_idx, s_idx, :] + gradE_dot_t * self.tangents[im_idx, s_idx, :]
406+
# self.G.shape = (-1)
407+
# self.tangents.shape = (-1)
408+
# self.gradientE.shape = (-1)
409+
410+
411+
# tgts = self.tangents.reshape(self.n_images, -1)
412+
# forces = self.G.reshape(self.n_images, -1)
413+
# for im_idx in range(forces.shape[0]):
414+
# gradE_dot_tgt = np.sum(forces[im_idx] * tgts[im_idx])
415+
# print(f'Im {im_idx}', forces[im_idx], tgts[im_idx], gradE_dot_tgt)
416+
# print('-----', np.linalg.norm(tgts[im_idx]))
417+
# print(self.spring_force.reshape(self.n_images, -1)[im_idx])
418+
# tgts = self.tangents.reshape(self.n_images, -1)
419+
# forces = self.G.reshape(self.n_images, -1)
389420

390421
# The effective force at the extreme images should already be zero, but
391422
# we will manually remove any value

0 commit comments

Comments
 (0)