Skip to content

Commit 3ff439d

Browse files
authored
Merge pull request #70 from computationalmodelling/nebm_spherical
Nebm spherical
2 parents c9aaba8 + e281e56 commit 3ff439d

File tree

3 files changed

+72
-30
lines changed

3 files changed

+72
-30
lines changed

fidimag/common/neb_spherical.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -365,12 +365,11 @@ def init_m(pos):
365365
self.coords = np.zeros(2 * self.n * self.total_image_num)
366366
self.last_m = np.zeros(self.coords.shape)
367367

368-
# For the effective field we use the extremes (to fit the energies
369-
# array length). We could save some memory if we don't consider them
370-
# (CHECK this in the future)
371-
self.Heff = np.zeros(self.coords.shape)
368+
# For the effective field we do not consider the extremes
369+
# since they are fixed
370+
self.Heff = np.zeros(2 * self.n * self.image_num)
372371
# self.Heff = np.zeros(2 * self.n * self.total_image_num)
373-
self.Heff.shape = (self.total_image_num, -1)
372+
self.Heff.shape = (self.image_num, -1)
374373

375374
# Tangent components in spherical coordinates
376375
self.tangents = np.zeros(2 * self.n * self.image_num)
@@ -548,8 +547,22 @@ def save_vtks(self):
548547

549548
self.coords.shape = (self.total_image_num, -1)
550549

550+
# We use Ms from the simulation assuming that all the
551+
# images are the same
551552
for i in range(self.total_image_num):
552-
self.vtk.save_vtk(spherical2cartesian(self.coords[i]), step=i, vtkname='m')
553+
# We will try to save for the micromagnetic simulation (Ms)
554+
# or an atomistic simulation (mu_s)
555+
# TODO: maybe this can be done with an: isinstance
556+
try:
557+
self.vtk.save_vtk(spherical2cartesian(self.coords[i]).reshape(-1, 3),
558+
self.sim.Ms,
559+
step=i,
560+
vtkname='m')
561+
except:
562+
self.vtk.save_vtk(spherical2cartesian(self.coords[i]).reshape(-1, 3),
563+
self.sim._mu_s,
564+
step=i,
565+
vtkname='m')
553566

554567
self.coords.shape = (-1, )
555568

@@ -606,7 +619,7 @@ def compute_effective_field(self, y):
606619

607620
# Set the simulation magnetisation to the (i+1)-th image
608621
# spin components
609-
self.sim.spin = spherical2cartesian(y[i + 1])
622+
self.sim.spin[:] = spherical2cartesian(y[i + 1])
610623

611624
# Compute the effective field using Fidimag's methods.
612625
# (we use the time=0 since we are only using the simulation
@@ -618,7 +631,7 @@ def compute_effective_field(self, y):
618631
h = self.sim.field
619632
# Save the field components of the (i + 1)-th image
620633
# to the effective field array which is in spherical coords
621-
self.Heff[i + 1, :] = cartesian2spherical_field(h, y[i + 1])
634+
self.Heff[i, :] = cartesian2spherical_field(h, y[i + 1])
622635
# Compute and save the total energy for this image
623636
self.energy[i + 1] = self.sim.compute_energy()
624637

@@ -674,7 +687,7 @@ def sundials_rhs(self, time, y, ydot):
674687
# D_climb = -nabla E + 2 * [nabla E * t] t
675688
for i in range(self.image_num):
676689
# The eff field has (i + 1) since it considers the extreme images
677-
h = self.Heff[i + 1]
690+
h = self.Heff[i]
678691
# Tangents and springs has length: total images -2 (no extremes)
679692
t = self.tangents[i]
680693
sf = self.springs[i]

fidimag/common/vtk.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ def init_VtkData(self, structure, header):
5151
def reset_data(self):
5252
self.vtk_data = pyvtk.VtkData(self.structure, self.header)
5353

54+
@ignore_stderr
5455
def save_scalar(self, s, name="my_field", step=0):
5556
self.vtk_data.cell_data.append(pyvtk.Scalars(s, name))
5657

tests/test_two_particles.py renamed to tests/test_two_particles_nebm.py

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44
# FIDIMAG:
55
from fidimag.micro import Sim
66
from fidimag.common import CuboidMesh
7-
from fidimag.micro import UniformExchange, UniaxialAnisotropy, Demag
7+
from fidimag.micro import UniformExchange, UniaxialAnisotropy
88
from fidimag.common.neb_cartesian import NEB_Sundials
9+
from fidimag.common.neb_spherical import NEB_Sundials as NEB_Sundials_spherical
910
import numpy as np
1011

1112
# Material Parameters
@@ -25,7 +26,7 @@
2526

2627
def two_part(pos):
2728

28-
x, y = pos[0], pos[1]
29+
x = pos[0]
2930

3031
if x > 6 or x < 3:
3132
return Ms
@@ -34,15 +35,16 @@ def two_part(pos):
3435

3536
# Finite differences mesh
3637
mesh = CuboidMesh(nx=3,
37-
ny=1,
38-
nz=1,
39-
dx=3, dy=3, dz=3,
40-
unit_length=1e-9
41-
)
38+
ny=1,
39+
nz=1,
40+
dx=3, dy=3, dz=3,
41+
unit_length=1e-9
42+
)
4243

4344

4445
# Simulation Function
45-
def relax_neb(k, maxst, simname, init_im, interp, save_every=10000):
46+
def relax_neb(k, maxst, simname, init_im, interp, save_every=10000,
47+
coordinates='Cartesian'):
4648
"""
4749
Execute a simulation with the NEB function of the FIDIMAG code, for an
4850
elongated particle (long cylinder)
@@ -78,28 +80,36 @@ def relax_neb(k, maxst, simname, init_im, interp, save_every=10000):
7880
# equal to 'the number of initial states specified', minus one.
7981
interpolations = interp
8082

81-
neb = NEB_Sundials(sim,
82-
init_images,
83-
interpolations=interpolations,
84-
spring=k,
85-
name=simname)
83+
if coordinates == 'Cartesian':
84+
neb = NEB_Sundials(sim,
85+
init_images,
86+
interpolations=interpolations,
87+
spring=k,
88+
name=simname)
89+
elif coordinates == 'Spherical':
90+
neb = NEB_Sundials_spherical(sim,
91+
init_images,
92+
interpolations=interpolations,
93+
spring=k,
94+
name=simname)
8695

8796
neb.relax(max_steps=maxst,
8897
save_vtk_steps=save_every,
8998
save_npy_steps=save_every,
9099
stopping_dmdt=1e-2)
91100

92101

102+
def mid_m(pos):
103+
if pos[0] > 4:
104+
return (0.5, 0, 0.2)
105+
else:
106+
return (-0.5, 0, 0.2)
107+
108+
93109
# this test runs for over a minute
94110
@pytest.mark.slow
95111
def test_energy_barrier_2particles():
96112
# Initial images: we set here a rotation interpolating
97-
def mid_m(pos):
98-
if pos[0] > 4:
99-
return (0.5, 0, 0.2)
100-
else:
101-
return (-0.5, 0, 0.2)
102-
103113
init_im = [(-1, 0, 0), mid_m, (1, 0, 0)]
104114
interp = [6, 6]
105115

@@ -114,12 +124,27 @@ def mid_m(pos):
114124
interp,
115125
save_every=5000)
116126

127+
# Relax the same system using spherical coordinates
128+
relax_neb(float(k), 2000,
129+
'neb_2particles_k{}_10-10int_spherical'.format(k),
130+
init_im,
131+
interp,
132+
save_every=5000,
133+
coordinates='Spherical'
134+
)
135+
117136
# Get the energies from the last state
118137
data = np.loadtxt('neb_2particles_k1e8_10-10int_energy.ndt')[-1][1:]
138+
data_spherical = np.loadtxt(
139+
'neb_2particles_k1e8_10-10int_spherical_energy.ndt')[-1][1:]
119140

120141
ebarrier = np.abs(np.max(data) - np.min(data)) / (1.602e-19)
121142
print(ebarrier)
122143

144+
ebarrier_spherical = np.abs(np.max(data_spherical) -
145+
np.min(data_spherical)) / (1.602e-19)
146+
print(ebarrier_spherical)
147+
123148
# Analitically, the energy when a single particle rotates is:
124149
# K V cos^2 theta
125150
# where theta is the angle of the direction of one particle with respect
@@ -133,6 +158,9 @@ def mid_m(pos):
133158
assert ebarrier < 0.017
134159
assert ebarrier > 0.005
135160

161+
assert ebarrier_spherical < 0.017
162+
assert ebarrier_spherical > 0.005
163+
136164

137-
if __name__=='__main__':
138-
test_energy_barrier_2particles()
165+
if __name__ == '__main__':
166+
test_energy_barrier_2particles()

0 commit comments

Comments
 (0)