def relax_system(mesh): sim = Sim(mesh, name='relax') sim.set_default_options(gamma=const.gamma) sim.alpha = 0.5 sim.mu_s = const.mu_s_1 sim.set_m(init_m) J = 50.0 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.5 * J dmi = DMI(D) sim.add(dmi) Hz = 0.2 * J / const.mu_s_1 zeeman = Zeeman([0, 0, Hz]) sim.add(zeeman) ONE_DEGREE_PER_NS = 17453292.52 sim.relax(dt=1e-13, stopping_dmdt=0.01 * ONE_DEGREE_PER_NS, max_steps=1000, save_m_steps=100, save_vtk_steps=50) np.save('m0.npy', sim.spin)
def relax_system(mesh): sim = Sim(mesh, name='relax') # sim.set_options(rtol=1e-10,atol=1e-14) sim.driver.alpha = 1.0 sim.driver.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(init_m) # sim.set_m(random_m) # sim.set_m(np.load('m_10000.npy')) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.09 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0, 3.75e-3]) sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-6, max_steps=1000, save_m_steps=100, save_vtk_steps=50) np.save('m0.npy', sim.spin)
def excite_system(mesh): sim = Sim(mesh, name='dyn', driver='sllg') sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B) sim.alpha = 0.1 sim.mu_s = const.mu_s_1 sim.T = temperature_gradient sim.set_m(np.load("m0.npy")) J = 50.0 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.5 * J dmi = DMI(D) sim.add(dmi) Hz = 0.2 * J / const.mu_s_1 zeeman = Zeeman([0, 0, Hz]) sim.add(zeeman) dt = 2e-14 * 50 # 1e-12 ts = np.linspace(0, 1000 * dt, 501) for t in ts: sim.run_until(t) sim.save_vtk() sim.save_m() print 'sim t=%g' % t
def relax_system(mesh): sim = Sim(mesh, name='relax') sim.set_options(rtol=1e-12, atol=1e-14) sim.do_procession = False sim.alpha = 0.5 sim.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(init_m) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.18 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0e-3, 2e-2], name='H') sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-8, max_steps=10000, save_m_steps=None, save_vtk_steps=100) np.save('m0.npy', sim.spin)
def relax_system(mesh, Hy=0): sim = Sim(mesh, name='relax') sim.driver.set_tols(rtol=1e-10, atol=1e-12) sim.driver.alpha = 0.5 sim.driver.gamma = 1.0 sim.mu_s = 1.0 sim.do_precession = False sim.set_m(init_m) #sim.set_m(random_m) #sim.set_m(np.load('m_10000.npy')) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.18 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, Hy, 2e-2], name='H') sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-7, max_steps=10000, save_m_steps=100, save_vtk_steps=50) np.save('m0.npy', sim.spin)
def excite_system(mesh, Hy=0): sim = Sim(mesh, name='dyn') sim.driver.set_tols(rtol=1e-10, atol=1e-12) sim.driver.alpha = 0.04 sim.driver.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(np.load('m0.npy')) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.18 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, Hy, 2e-2], name='H') sim.add(zeeman) hx = TimeZeeman([0, 0, 1e-5], sinc_fun, name='h') sim.add(hx, save_field=True) dt = 5 steps = 2001 for i in range(steps): sim.run_until(i * dt) sim.save_m() print("step {}/{}".format(i, steps))
def relax_system_stage2(): mesh = CuboidMesh(nx=140 , ny=140, nz=1) sim = Sim(mesh, name='dyn', driver='llg') sim.alpha = 0.1 sim.do_precession = True sim.gamma = const.gamma sim.mu_s = spatial_mu sim.set_m(np.load('skx.npy')) J = 50 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.27 * J dmi = DMI(D) sim.add(dmi) zeeman = Zeeman(spatial_H) sim.add(zeeman) ts = np.linspace(0, 2e-9, 201) for t in ts: sim.run_until(t) sim.save_vtk() sim.save_m() print(t)
def relax_system_stage1(): mesh = CuboidMesh(nx=140 , ny=140, nz=1) sim = Sim(mesh, name='relax', driver='llg') #sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B) sim.alpha = 0.5 sim.do_precession = False sim.gamma = const.gamma sim.mu_s = spatial_mu sim.set_m(init_m) J = 50 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.27 * J dmi = DMI(D) sim.add(dmi) zeeman = Zeeman(spatial_H) sim.add(zeeman) sim.relax(dt=1e-14, stopping_dmdt=1e10, max_steps=1000, save_m_steps=100, save_vtk_steps=10) np.save('skx.npy', sim.spin) plot_m(mesh, 'skx.npy', comp='z')
def test_skx_num(): mesh = CuboidMesh(nx=120, ny=120, nz=1, periodicity=(True, True, False)) sim = Sim(mesh, name='skx_num') sim.set_tols(rtol=1e-6, atol=1e-6) sim.alpha = 1.0 sim.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(init_m) sim.do_procession = False J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.09 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0, 5e-3]) sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-2, max_steps=1000, save_m_steps=None, save_vtk_steps=None) skn = sim.skyrmion_number() print 'skx_number', skn assert skn > -1 and skn < -0.99
def excite_system(mesh): sim = Sim(mesh, name='dyn') # sim.set_options(rtol=1e-10,atol=1e-14) sim.alpha = 0.04 sim.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(np.load('m0.npy')) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.09 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0, 3.75e-3], name='H') sim.add(zeeman) w0 = 0.02 def time_fun(t): return np.exp(-w0 * t) hx = TimeZeeman([0, 0, 1e-5], sinc_fun, name='h') sim.add(hx, save_field=True) ts = np.linspace(0, 20000, 5001) for t in ts: sim.run_until(t) print 'sim t=%g' % t
def excite_system(T=0.1, H=0.15): mesh = CuboidMesh(nx=28 * 3, ny=16 * 5, nz=1, pbc='2d') sim = Sim(mesh, name='dyn', driver='sllg') sim.set_options(dt=1e-14, gamma=const.gamma, k_B=const.k_B) sim.alpha = 0.1 sim.mu_s = const.mu_s_1 sim.set_m(random_m) J = 50 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.5 * J dmi = DMI(D) sim.add(dmi) Hz = H * J / const.mu_s_1 zeeman = Zeeman([0, 0, Hz]) sim.add(zeeman) sim.T = J / const.k_B * T ts = np.linspace(0, 5e-11, 51) for t in ts: sim.run_until(t) # sim.save_vtk() np.save('m.npy', sim.spin) plot_m(mesh, 'm.npy', comp='z')
def test_sim_spins(do_plot=False): mesh = CuboidMesh(nx=10, ny=5, nz=1) sim = Sim(mesh, name='10spin') alpha = 0.1 gamma = 2.21e5 sim.alpha = alpha sim.gamma = gamma sim.mu_s = 1.0 sim.set_m((1, 0, 0)) print(sim.spin) H0 = 1e5 sim.add(Zeeman((0, 0, H0))) ts = np.linspace(0, 1e-9, 101) mx = [] my = [] mz = [] real_ts = [] for t in ts: sim.run_until(t) real_ts.append(sim.t) #print sim.t, abs(sim.spin_length()[0] - 1) av = sim.compute_average() mx.append(av[0]) my.append(av[1]) mz.append(av[2]) #sim.save_vtk() mz = np.array(mz) # print mz a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts) print(sim.stat()) if do_plot: plot(real_ts, mx, my, mz, a_mx, a_my, a_mz, name='spins.pdf', title='integrating spins') print(("Max Deviation = {0}".format(np.max(np.abs(mz - a_mz))))) assert np.max(np.abs(mz - a_mz)) < 5e-7
def test_skx_num_atomistic(): """ Test the *finite spin chirality* or skyrmion number for a discrete spins simulation in a two dimensional lattice The expression is (PRL 108, 017601 (2012)) : Q = S_i \dot ( S_{i+1} X S_{j+1} ) + S_i \dot ( S_{i-1} X S_{j-1} ) which measures the chirality taking two triangles of spins per lattice site i: S_{i} , S_{i + x} , S_{i + y} and S_{i} , S_{i - x} , S_{i - y} The area of the two triangles cover a unit cell, thus the sum cover the whole area of the atomic lattice This test generate a skyrmion pointing down with unrealistic paremeters. """ mesh = CuboidMesh(nx=120, ny=120, nz=1, periodicity=(True, True, False)) sim = Sim(mesh, name='skx_num') sim.set_tols(rtol=1e-6, atol=1e-6) sim.alpha = 1.0 sim.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(lambda pos: init_m(pos, 60, 60, 20)) sim.do_precession = False J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.09 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0, 5e-3]) sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-2, max_steps=1000, save_m_steps=None, save_vtk_steps=None) skn = sim.skyrmion_number() print('skx_number', skn) assert skn > -1 and skn < -0.99
def test_zeeman(): """ Test the x and y component of the zeeman field for the 2nd spin 6 7 8 9 10 11 0 1 2 3 4 5 ^ """ mesh = CuboidMesh(nx=5, ny=2, nz=1) sim = Sim(mesh) sim.set_m((1, 0, 0)) zeeman = Zeeman(varying_field) sim.add(zeeman) field = zeeman.compute_field() assert field[2 * 3] == 1.2 * (2 + 0.5) assert field[2 * 3 + 1] == 2.3 * 0.5
def test_sim_single_spin_sllg(do_plot=False): mesh = CuboidMesh(nx=1, ny=1, nz=1) sim = Sim(mesh, name='spin', driver='sllg') alpha = 0.1 gamma = 2.21e5 sim.set_options(dt=5e-15, gamma=gamma) sim.alpha = alpha sim.mu_s = 1.0 sim.set_m((1, 0, 0)) H0 = 1e5 sim.add(Zeeman((0, 0, H0))) ts = np.linspace(0, 1e-10, 101) mx = [] my = [] mz = [] real_ts = [] for t in ts: sim.run_until(t) real_ts.append(sim.t) print(sim.t, abs(sim.spin_length()[0] - 1)) mx.append(sim.spin[0]) my.append(sim.spin[1]) mz.append(sim.spin[2]) mz = np.array(mz) a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts) if do_plot: plot(real_ts, mx, my, mz, a_mx, a_my, a_mz, name='spin_sllg.pdf', title='integrating a spin') print(("Max Deviation = {0}".format(np.max(np.abs(mz - a_mz))))) assert np.max(np.abs(mz - a_mz)) < 1e-8
def relax_system(rtol=1e-10, atol=1e-12): """numerical solution""" mesh = CuboidMesh(nx=1, ny=1, nz=1) sim = Sim(mesh, name='relax') sim.driver.set_tols(rtol=rtol, atol=atol) sim.driver.alpha = 0.5 sim.driver.gamma = 2.21e5 sim.mu_s = 1.0 sim.set_m((1.0, 0, 0)) sim.add(Zeeman((0, 0, 1e5))) ts = np.linspace(0, 1e-9, 1001) for t in ts: sim.driver.run_until(t)
def disable_test_sim_single_spin_llg_stt(do_plot=False): ni = Nickel() mesh = CuboidMesh(nx=1, ny=1, nz=1) mesh.set_material(ni) ni.alpha = 0.1 sim = Sim(mesh, driver='llg_stt') sim.set_m((1, 0, 0)) H0 = 1 sim.add(Zeeman((0, 0, H0))) dt = 1e-12 ts = np.linspace(0, 200 * dt, 101) precession = ni.gamma / (1 + ni.alpha**2) mz_ref = [] mxyz = [] real_ts = [] for t in ts: sim.run_until(t) real_ts.append(sim.t) print(sim.t, abs(sim.spin_length()[0] - 1), sim.spin) mz_ref.append(np.tanh(precession * ni.alpha * H0 * sim.t)) mxyz.append(np.copy(sim.spin)) mxyz = np.array(mxyz) if do_plot: ts_ns = np.array(real_ts) * 1e9 plt.plot(ts_ns, mxyz[:, 0], ".-", label="mx") plt.plot(ts_ns, mxyz[:, 1], ".-", label="my") plt.plot(ts_ns, mxyz[:, 2], ".-", label="mz") plt.plot(ts_ns, mz_ref, "-", label="analytical") plt.xlabel("time (ns)") plt.ylabel("mz") plt.title("integrating a macrospin") plt.legend() plt.savefig("test_llg_stt.png") print(("Deviation = {0}".format(np.max(np.abs(mxyz[:, 2] - mz_ref))))) assert np.max(np.abs(mxyz[:, 2] - mz_ref)) < 1e-9
def create_simulation(R, B): mu_s = 3 sim_hexagon = HexagonSim( R, # R 0.2715, # a mu_s, # mu_s name='unnamed') sim = sim_hexagon.sim # mask = (sim.mu_s / C.mu_B) > 1e-5 exch = UniformExchange(5.881 * C.meV) sim.add(exch) dmi = DMI(D=1.557 * C.meV, dmi_type='interfacial') sim.add(dmi) sim.add(Zeeman([0., 0., B])) sim.add(Anisotropy(0.406 * C.meV, axis=[0, 0, 1])) return sim
def test_sim_single_spin_vode(do_plot=False): mesh = CuboidMesh(nx=1, ny=1, nz=1) sim = Sim(mesh, name='spin') alpha = 0.1 gamma = 2.21e5 sim.driver.alpha = alpha sim.driver.gamma = gamma sim.mu_s = 1.0 sim.set_m((1, 0, 0)) H0 = 1e5 sim.add(Zeeman((0, 0, H0))) ts = np.linspace(0, 1e-9, 101) mx = [] my = [] mz = [] real_ts = [] for t in ts: sim.driver.run_until(t) real_ts.append(sim.driver.t) #print sim.driver.t, abs(sim.spin_length()[0] - 1) mx.append(sim.spin[0]) my.append(sim.spin[1]) mz.append(sim.spin[2]) mz = np.array(mz) a_mx, a_my, a_mz = single_spin(alpha, gamma, H0, ts) print(sim.driver.stat()) if do_plot: plot(real_ts, mx, my, mz, a_mx, a_my, a_mz) print(("Max Deviation = {0}".format( np.max(np.abs(mz - a_mz))))) assert np.max(np.abs(mz - a_mz)) < 5e-7
def test_skx_num_atomistic(): """ Test the *finite spin chirality* or skyrmion number for a discrete spins simulation in a two dimensional lattice The expression is (PRL 108, 017601 (2012)) : Q = S_i \dot ( S_{i+1} X S_{j+1} ) + S_i \dot ( S_{i-1} X S_{j-1} ) which measures the chirality taking two triangles of spins per lattice site i: S_{i} , S_{i + x} , S_{i + y} and S_{i} , S_{i - x} , S_{i - y} The area of the two triangles cover a unit cell, thus the sum cover the whole area of the atomic lattice We also test the Berg and Luscher definition for a topological charge (see the hexagonal mesh test for details) in a square lattice. This test generate a skyrmion pointing down with unrealistic paremeters. """ mesh = CuboidMesh(nx=120, ny=120, nz=1, periodicity=(True, True, False)) sim = Sim(mesh, name='skx_num') sim.driver.set_tols(rtol=1e-6, atol=1e-6) sim.driver.alpha = 1.0 sim.driver.gamma = 1.0 sim.mu_s = 1.0 sim.set_m(lambda pos: init_m(pos, 60, 60, 20)) sim.do_precession = False J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.09 dmi = DMI(D) sim.add(dmi) zeeman = Zeeman([0, 0, 5e-3]) sim.add(zeeman) sim.relax(dt=2.0, stopping_dmdt=1e-2, max_steps=1000, save_m_steps=None, save_vtk_steps=None) skn = sim.skyrmion_number() print('skx_number', skn) skn_BL = sim.skyrmion_number(method='BergLuscher') print('skx_number_BergLuscher', skn_BL) # Test the finite chirality method assert skn > -1 and skn < -0.99 # Test the Berg-Luscher method assert np.abs(skn_BL - (-1)) < 1e-4 and np.sign(skn_BL) < 0 # Test guiding center Rx, Ry = compute_RxRy(mesh, sim.spin) print('Rx=%g, Ry=%g' % (Rx, Ry)) assert Rx < 60 and Rx > 58 assert Ry < 60 and Ry > 58
def test_skx_num_atomistic_hexagonal(): """ Test the topological charge or skyrmion number for a discrete spins simulation in a two dimensional hexagonal lattice, using Berg and Luscher definition in [Nucl Phys B 190, 412 (1981)] and simplified in [PRB 93, 174403 (2016)], which maps a triangulated lattice (using triangles of neighbouring spins) area into a unit sphere. The areas of two triangles per lattice site cover a unit cell, thus the sum cover the whole area of the atomic lattice This test generates a skyrmion pointing down and two skyrmions pointing up in a PdFe sample using magnetic parameters from: PRL 114, 177203 (2015) """ mesh = HexagonalMesh(0.2715, 41, 41, periodicity=(True, True)) sim = Sim(mesh, name='skx_number_hexagonal') sim.driver.set_tols(rtol=1e-6, atol=1e-6) sim.driver.alpha = 1.0 sim.driver.gamma = 1.0 sim.mu_s = 3 * const.mu_B sim.set_m(lambda pos: init_m(pos, 16.1, 10, 2)) sim.driver.do_precession = False J = 5.881 * const.meV exch = UniformExchange(J) sim.add(exch) D = 1.557 * const.meV dmi = DMI(D, dmi_type='interfacial') sim.add(dmi) sim.add(Anisotropy(0.406 * const.meV, axis=[0, 0, 1])) zeeman = Zeeman([0, 0, 2.5]) sim.add(zeeman) sim.relax(dt=1e-13, stopping_dmdt=1e-2, max_steps=2000, save_m_steps=None, save_vtk_steps=100) skn_single = sim.skyrmion_number(method='BergLuscher') print('skx_number_hexagonal', skn_single) # Now we generate two skyrmions pointing up sim.driver.reset_integrator() sim.set_m( lambda pos: init_m_multiple_sks(pos, 1, sk_pos=[(9, 6), (18, 12)])) sim.get_interaction('Zeeman').update_field([0, 0, -2.5]) sim.relax(dt=1e-13, stopping_dmdt=1e-2, max_steps=2000, save_m_steps=None, save_vtk_steps=None) skn_two = sim.skyrmion_number(method='BergLuscher') print('skx_number_hexagonal_two', skn_two) # Check that we get a right sk number assert np.abs(skn_single - (-1)) < 1e-4 and np.sign(skn_single) < 0 assert np.abs(skn_two - (2)) < 1e-4 and np.sign(skn_two) > 0
from fidimag.atomistic import Sim from fidimag.common.cuboid_mesh import CuboidMesh from fidimag.atomistic import UniformExchange, Zeeman import fidimag.common.constant as const mesh = CuboidMesh(nx=1, ny=1, dx=1, dy=1) sim = Sim(mesh, name='relax_sk') sim.gamma = const.gamma sim.set_m((1, 0, 0)) sim.add(Zeeman((0, 0, 25.))) sim.run_until(1e-11) sim.set_tols(rtol=1e-10, atol=1e-12) sim.run_until(2e-11)
dy=dy, dz=dz, x0=-nx * 0.5, y0=-ny * 0.5, z0=-nz * 0.5, unit_length=1., periodicity=(True, True, False)) sim_name = 'sk_helix' sim = Sim(mesh, name=sim_name, integrator='sundials_openmp') sim.mu_s = 1 sim.add(Exchange(1)) sim.add(DMI(0.727, dmi_type='bulk')) bz_min = FIELD sim.add(Zeeman((0.0, 0.0, bz_min * 1e-3)), save_field=True) kc = -0.05 if np.abs(kc) > 0.0: sim.add(CubicAnisotropy(kc)) # ......................................................................... sim.driver.alpha = 0.9 sim.driver.do_precession = False # Zeeman_int = sim.get_interaction('Zeeman') # Zeeman_int.update_field((0.0, 0.0, B_sweep * 1e-3)) H_BG = np.load( f'../npys/helix-y_kc-5e-2_L10/m_helix-y_kc-5e-2_L10_Bz_{FIELD:06d}.npy' )
def generate_simulation(self, do_precession=False, gamma=1.76e11, load_mu_s=False): """ Generates a simulation according to the self.simulation option gamma :: Default is the free electron gyromagnetic ratio load_mu_s :: A file path to a NPY file with the mu_s information (only for the experimental_sample option) """ # Mesh ---------------------------------------------------------------- if self.simulation == 'experimental_sample': self.sim_from_image = sfi.sim_from_image(sfi.default_image) if not load_mu_s: self.sim_from_image.generate_magnetic_moments(mu_s=self.mu_s) else: self.sim_from_image.generate_magnetic_moments( load_file=load_mu_s) self.sim = self.sim_from_image.sim elif self.simulation == '2D_square': # A square sized hexagonal mesh mesh = HexagonalMesh( self.mesh_a * 0.5, self.mesh_nx, self.mesh_ny, # periodicity=(True, True), alignment='square', unit_length=1e-9) self.sim = Sim(mesh) # If we use polygon mesh tools, we can use a hexagon shaped mesh # self.sim.mu_s = self.mu_s_in_hexagon self.sim.mu_s = self.mu_s elif self.simulation == '1D_chain': # A 1D chain using a cuboid mesh mesh = CuboidMesh( dx=self.mesh_a, nx=self.mesh_nx, ny=1, nz=1, # periodicity=(True, True), unit_length=1e-9) self.sim = Sim(mesh) # If we use polygon mesh tools, we can use a hexagon shaped mesh # self.sim.mu_s = self.mu_s_in_hexagon self.sim.mu_s = self.mu_s self.sim.driver.do_precession = do_precession self.sim.driver.gamma = gamma # Interactions -------------------------------------------------------- exch = UniformExchange(self.J) self.sim.add(exch) dmi = DMI(D=(self.D), dmi_type='interfacial') self.sim.add(dmi) zeeman = Zeeman((self.B[0], self.B[1], self.B[2])) self.sim.add(zeeman, save_field=True) if self.ku: # Uniaxial anisotropy along + z-axis self.sim.add(Anisotropy(self.ku, axis=[0, 0, 1])) if self.Demag: print('Using Demag!') self.sim.add(DemagHexagonal()) # --------------------------------------------------------------------- self.hls = np.ones_like(self.sim.spin.reshape(-1, 3)) self.rgbs = np.ones((self.sim.spin.reshape(-1, 3).shape[0], 4))
def simulation(nx, ny, nz, dx, dy, dz, j, d, kc, mu_s, sim_name, bz_min, bz_max, bz_steps, bz_hysteresis=False, initial_state_one_bobber=None, initial_state_two_bobbers=None, initial_state_two_bobbers_asymm=None, initial_state_sk_tube=None, initial_state_one_dim_mod=None, initial_state_helix_angle_x=(None, None), stopping_dmdt=1e-5, max_steps=4000, save_initial_state=None): mesh = CuboidMesh(nx=nx, ny=ny, nz=nz, dx=dx, dy=dy, dz=dz, x0=-nx * 0.5, y0=-ny * 0.5, z0=-nz * 0.5, unit_length=1., periodicity=(True, True, False)) # J = 1. # D = 0.628 # L_D = 2 PI a J / D = 10 * a => D / J = 2 PI / 10. # Bz = 0.2 # B_z == (B_z mu_s / J) # mu_s = 1. sim = Sim(mesh, name=sim_name, integrator='sundials_openmp') sim.mu_s = mu_s sim.add(Exchange(j)) sim.add(DMI(d, dmi_type='bulk')) sim.add(Zeeman((0.0, 0.0, bz_min * 1e-3)), save_field=True) if np.abs(kc) > 0.0: sim.add(CubicAnisotropy(kc)) # ......................................................................... sim.driver.alpha = 0.9 sim.driver.do_precession = False if not os.path.exists('npys/{}'.format(sim_name)): os.makedirs('npys/{}'.format(sim_name)) if not os.path.exists('txts'): os.makedirs('txts') for i, B_sweep in enumerate(np.linspace(bz_min, bz_max, bz_steps)): print('Bz = {:.0f} mT '.format(B_sweep).ljust(80, '-')) Zeeman_int = sim.get_interaction('Zeeman') Zeeman_int.update_field((0.0, 0.0, B_sweep * 1e-3)) if (not bz_hysteresis) or (bz_hysteresis and i < 1): if initial_state_one_dim_mod: sim.set_m(lambda r: one_dim_mod(r, B_sweep * 1e-3, d)) elif initial_state_helix_angle_x[0]: angle = initial_state_helix_angle_x[0] * np.pi / 180. periodic = initial_state_helix_angle_x[1] sim.set_m(lambda r: helix_angle_x(r, angle, periodic)) elif initial_state_sk_tube: sk_rad = initial_state_sk_tube sim.set_m( lambda r: sk_tube(r, B_sweep * 1e-3, d, sk_rad=sk_rad)) elif initial_state_two_bobbers: bobber_length = initial_state_two_bobbers sim.set_m(lambda r: two_bobbers(r, B_sweep * 1e-3, d, mesh.Lz, bobber_rad=3., bobber_length=bobber_length)) elif initial_state_two_bobbers_asymm: bobber_length = initial_state_two_bobbers_asymm sim.set_m( lambda r: two_bobbers_asymm(r, B_sweep * 1e-3, d, mesh.Lz, bobber_rad=3., bobber_length=bobber_length)) elif initial_state_one_bobber: bobber_length = initial_state_one_bobber sim.set_m(lambda r: one_bobber(r, B_sweep * 1e-3, d, mesh.Lz, bobber_rad=3., bobber_length=bobber_length)) else: raise Exception('Not a valid initial state') if save_initial_state: save_vtk(sim, sim_name + '_INITIAL', field_mT=B_sweep) name = 'npys/{}/m_{}_INITIAL_Bz_{:06d}.npy'.format( sim.driver.name, sim_name, int(B_sweep)) np.save(name, sim.spin) # ..................................................................... sim.relax(stopping_dmdt=stopping_dmdt, max_steps=max_steps, save_m_steps=None, save_vtk_steps=None) # ..................................................................... save_vtk(sim, sim_name, field_mT=B_sweep) name = 'npys/{}/m_{}_Bz_{:06d}.npy'.format(sim.driver.name, sim_name, int(B_sweep)) np.save(name, sim.spin) sim.driver.reset_integrator() shutil.move(sim_name + '.txt', 'txts/{}.txt'.format(sim_name))
def simulation(nx, ny, nz, dx, dy, dz, j, d, kc, bz, mu_s, sim_name, add_image=None, add_interpolations=None, add_images_folder=None, spring_constant=None, stopping_dydt=None, max_steps=None, keep_sim_climbing_image_steps=None, save_m_every=None, climbing_image=None, keep_sim_climbing_image=None, keep_sim_climbing_image_again=None, integrator='sundials', integrator_stepsize=1e-3, interpolation_method='rotation', variable_spring_forces=None, interpolation_energy='polynomial'): if add_interpolations: if (len(add_image) - 1) != len(add_interpolations): raise Exception('(N interpolations) != (N images - 1)') mesh = CuboidMesh(nx=nx, ny=ny, nz=nz, dx=dx, dy=dy, dz=dz, x0=-nx * 0.5, y0=-ny * 0.5, z0=-nz * 0.5, unit_length=1., periodicity=(True, True, False)) # Simulation sim = Sim(mesh, name=sim_name) sim.mu_s = mu_s sim.add(Exchange(j)) sim.add(DMI(d, dmi_type='bulk')) sim.add(Zeeman((0.0, 0.0, bz * 1e-3))) if np.abs(kc) > 0.0: sim.add(CubicAnisotropy(kc)) # GNEBM simulation ........................................................ if add_interpolations: # Set the initial images from the list init_images = [np.load(image) for image in add_image] interpolations = [i for i in add_interpolations] elif add_images_folder: if add_images_folder.endswith('_LAST'): dir_list = glob.glob(add_images_folder[:-5] + '*') dir_list = sorted( dir_list, key=lambda f: int(re.search(r'(?<=_)[0-9]+$', f).group(0))) add_images_folder = dir_list[-1] flist = sorted(os.listdir(add_images_folder)) init_images = [ np.load(os.path.join(add_images_folder, image)) for image in flist ] interpolations = [] else: raise Exception('Specify an option to add images') if climbing_image: if climbing_image.isdigit(): climbing_image = int(climbing_image) else: try: energies = np.loadtxt(climbing_image)[-1][1:] energies = energies - energies[0] climbing_image = np.where(energies == np.max(energies))[0][0] except OSError: raise Exception('Err trying to compute climb image from file') print('Using climbing image: {}'.format(climbing_image)) # Start a NEB simulation passing the Simulation object and all the NEB # parameters neb = NEBM_Geodesic(sim, init_images, interpolations=interpolations, spring_constant=spring_constant, name=sim_name, openmp=True, climbing_image=climbing_image, integrator=integrator, interpolation_method=interpolation_method) if integrator == 'verlet': neb.integrator.mass = 1 neb.integrator.stepsize = integrator_stepsize dt = integrator_stepsize * 10 else: dt = integrator_stepsize # ......................................................................... for fdir in ['interpolations', 'ndts']: if not os.path.exists(fdir): os.makedirs(fdir) # Finally start the energy band relaxation neb.relax(max_iterations=max_steps, save_vtks_every=save_m_every, save_npys_every=save_m_every, stopping_dYdt=stopping_dydt, dt=dt) if variable_spring_forces: neb.variable_k = True neb.dk = spring_constant * 0.9 neb.relax(max_iterations=max_steps, save_vtks_every=save_m_every, save_npys_every=save_m_every, stopping_dYdt=stopping_dydt, dt=dt, save_initial_state=False) # Continue with climbing image if specified if keep_sim_climbing_image: if not keep_sim_climbing_image_steps: keep_sim_climbing_image_steps = max_steps # Find all local maxima largest_E_im_idx = [] for i in range(2, neb.n_images - 2): if (neb.energies[i] > neb.energies[i - 1] and neb.energies[i - 1] > neb.energies[i - 2] and neb.energies[i] > neb.energies[i + 1] and neb.energies[i + 1] > neb.energies[i + 2]): largest_E_im_idx.append(i) elif (neb.energies[i] < neb.energies[i - 1] and neb.energies[i - 1] < neb.energies[i - 2] and neb.energies[i] < neb.energies[i + 1] and neb.energies[i + 1] < neb.energies[i + 2]): largest_E_im_idx.append(-i) neb.climbing_image = largest_E_im_idx print('Continuing simulation with CI = {}'.format(largest_E_im_idx)) neb.name += '_CI' # Data will be appended to the initial NDT file, at least we create a # new one with the CI appended to the sim name: # neb.create_tablewriter() # last_step_relax = neb.iterations # Variable dk for better resolution around saddle points # neb.variable_k = True # neb.dk = spring_constant neb.relax(max_iterations=keep_sim_climbing_image_steps, save_vtks_every=save_m_every, save_npys_every=save_m_every, stopping_dYdt=keep_sim_climbing_image, dt=dt, save_initial_state=False) # Remove initial state (same as final state from the prev relaxation) # shutil.rmtree('vtks/{}_{}'.format(neb.name, last_step_relax)) # Continue with climbing image if specified if keep_sim_climbing_image_again: if not keep_sim_climbing_image_steps: keep_sim_climbing_image_steps = max_steps # Find all local maxima largest_E_im_idx = [] for i in range(2, neb.n_images - 2): if (neb.energies[i] > neb.energies[i - 1] and neb.energies[i - 1] > neb.energies[i - 2] and neb.energies[i] > neb.energies[i + 1] and neb.energies[i + 1] > neb.energies[i + 2]): largest_E_im_idx.append(i) elif (neb.energies[i] < neb.energies[i - 1] and neb.energies[i - 1] < neb.energies[i - 2] and neb.energies[i] < neb.energies[i + 1] and neb.energies[i + 1] < neb.energies[i + 2]): largest_E_im_idx.append(-i) neb.climbing_image = largest_E_im_idx print('Continuing simulation with CI = {}'.format(largest_E_im_idx)) neb.name += '_CI' neb.relax(max_iterations=keep_sim_climbing_image_steps, save_vtks_every=save_m_every, save_npys_every=save_m_every, stopping_dYdt=keep_sim_climbing_image_again, dt=dt, save_initial_state=False) # Produce a file with the data from a cubic interpolation for the band interp_data = np.zeros((200, 2)) if interpolation_energy == 'polynomial': neb.compute_polynomial_factors() (interp_data[:, 0], interp_data[:, 1]) = neb.compute_polynomial_approximation_energy(200) elif interpolation_energy == 'Bernstein': neb.compute_Bernstein_polynomials() (interp_data[:, 0], interp_data[:, 1]) = neb.compute_Bernstein_approximation_energy(200) else: raise Exception('No valid interpolation method') np.savetxt('interpolations/{}_interpolation.dat'.format(sim_name), interp_data) # Clean files shutil.move(sim_name + '_energy.ndt', 'ndts/{}_energy.ndt'.format(sim_name)) shutil.move(sim_name + '_dYs.ndt', 'ndts/{}_dYs.ndt'.format(sim_name))
if args.alpha: sim.driver.alpha = args.alpha # sim.gamma = 2.211e5 # Material parameters --------------------------------------------------------- sim.mu_s = args.mu_s * const.mu_B exch = UniformExchange(args.J * const.meV) sim.add(exch) dmi = DMI(D=(args.D * const.meV), dmi_type='interfacial') sim.add(dmi) if args.B: zeeman = Zeeman((0, 0, args.B)) sim.add(zeeman, save_field=True) if args.k_u: # Uniaxial anisotropy along + z-axis sim.add(Anisotropy(args.k_u * const.meV, axis=[0, 0, 1])) if args.Demag: sim.add(DemagHexagonal()) # ----------------------------------------------------------------------------- # Debug Information ----------------------------------------------------------- print('Saturation Magnetisation: {} mu_B'.format(args.mu_s)) print('Exchange constant: {} meV'.format(args.J))
def simulation(nx, ny, nz, dx, dy, dz, j, d, kc, bz, mu_s, sim_name, add_image=None, add_interpolations=None, add_images_folder=None, stopping_dydt=None, max_steps=None, save_m_every=None, integrator='sundials', integrator_stepsize=1e-3, interpolation_method='rotation', variable_spring_forces=None, interpolation_energy='polynomial'): if add_interpolations: if (len(add_image) - 1) != len(add_interpolations): raise Exception('(N interpolations) != (N images - 1)') mesh = CuboidMesh(nx=nx, ny=ny, nz=nz, dx=dx, dy=dy, dz=dz, x0=-nx * 0.5, y0=-ny * 0.5, z0=-nz * 0.5, unit_length=1., periodicity=(True, True, False)) # Simulation sim = Sim(mesh, name=sim_name) sim.mu_s = mu_s sim.add(Exchange(j)) sim.add(DMI(d, dmi_type='bulk')) sim.add(Zeeman((0.0, 0.0, bz * 1e-3))) if np.abs(kc) > 0.0: sim.add(CubicAnisotropy(kc)) # GNEBM simulation ........................................................ if add_interpolations: # Set the initial images from the list init_images = [np.load(image) for image in add_image] interpolations = [i for i in add_interpolations] elif add_images_folder: if add_images_folder.endswith('_LAST'): dir_list = glob.glob(add_images_folder[:-5] + '*') dir_list = sorted( dir_list, key=lambda f: int(re.search(r'(?<=_)[0-9]+$', f).group(0))) add_images_folder = dir_list[-1] flist = sorted(os.listdir(add_images_folder)) init_images = [ np.load(os.path.join(add_images_folder, image)) for image in flist ] interpolations = [] else: raise Exception('Specify an option to add images') # Start a NEB simulation passing the Simulation object and all the NEB # parameters string = StringMethod(sim, init_images, interpolations=interpolations, name=sim_name, openmp=True, integrator=integrator, interpolation_method=interpolation_method) if integrator == 'verlet': string.integrator.mass = 1 string.integrator.stepsize = integrator_stepsize dt = integrator_stepsize * 10 else: dt = integrator_stepsize # ......................................................................... for fdir in ['interpolations', 'ndts']: if not os.path.exists(fdir): os.makedirs(fdir) # Finally start the energy band relaxation string.relax(max_iterations=max_steps, save_vtks_every=save_m_every, save_npys_every=save_m_every, stopping_dYdt=stopping_dydt, dt=dt) # Produce a file with the data from a cubic interpolation for the band interp_data = np.zeros((200, 2)) if interpolation_energy == 'polynomial': string.compute_polynomial_factors() (interp_data[:, 0], interp_data[:, 1]) = string.compute_polynomial_approximation_energy(200) elif interpolation_energy == 'Bernstein': string.compute_Bernstein_polynomials() (interp_data[:, 0], interp_data[:, 1]) = string.compute_Bernstein_approximation_energy(200) else: raise Exception('No valid interpolation method') np.savetxt('interpolations/{}_interpolation.dat'.format(sim_name), interp_data) # Clean files shutil.move(sim_name + '_energy.ndt', 'ndts/{}_energy.ndt'.format(sim_name)) shutil.move(sim_name + '_dYs.ndt', 'ndts/{}_dYs.ndt'.format(sim_name))
def hysteresis_loop(config_file, D=1.56, J=5.88, k_u=0.41, mu_s=3, B=(0, 0, 0), Demag=None, ): """ The config file must have the following parameters: D J k_u mu_s :: Magnitude in Bohr magneton units. A file path can be specified to load a NPY file with the mu_s values, when using the mesh_from_image option Demag :: Set to True for Demag sim_name :: Simulation name initial_state :: A function or a npy file hysteresis_steps :: mesh_from_image :: [IMAGE_PATH, xmin, xmax, ymin, ymax] hexagonal_mesh :: [nx, ny, a] PBC_2D :: Set to True for Periodic boundaries pin_boundaries :: Set to True to pin the spins at the boundaries. Their orientations are already given from the initial_state NPY file llg_dt :: llg_stopping_dmdt :: llg_max_steps :: llg_do_precession :: False as default llg_alpha :: 0.01 as default """ # Parameters -------------------------------------------------------------- cf = {} # execfile(config_file, cf) # Python3: exec(open(config_file).read(), cf) D = cf["D"] * const.meV J = cf["J"] * const.meV k_u = cf["k_u"] * const.meV if isinstance(cf["mu_s"], int) or isinstance(cf["mu_s"], float): mu_s = cf["mu_s"] * const.mu_B if isinstance(cf["initial_state"], str): init_state = np.load(cf["initial_state"]) elif isinstance(cf["initial_state"], types.FunctionType): init_state = cf["initial_state"] # Set up default arguments default_args = {"mesh_alignment": 'diagonal', "mesh_unit_length": 1e-9, "llg_dt": 1e-11, "llg_stopping_dmdt": 1e-2, "llg_max_steps": 4000, "llg_do_precession": False, "llg_alpha": 0.01 } for key in default_args.keys(): if not cf.get(key): print(default_args[key]) cf[key] = default_args[key] # Simulation object ------------------------------------------------------- if cf.get("hexagonal_mesh"): if not cf["PBC_2D"]: mesh = HexagonalMesh(cf["hexagonal_mesh"][2] * 0.5, int(cf["hexagonal_mesh"][0]), int(cf["hexagonal_mesh"][1]), alignment=cf["mesh_alignment"], unit_length=cf["mesh_unit_length"] ) else: mesh = HexagonalMesh(cf["hexagonal_mesh"][2] * 0.5, int(cf["hexagonal_mesh"][0]), int(cf["hexagonal_mesh"][1]), periodicity=(True, True), alignment=cf["mesh_alignment"], unit_length=cf["mesh_unit_length"] ) sim = Sim(mesh, name=cf["sim_name"]) elif cf.get("mesh_from_image"): sim_from_image = sfi.sim_from_image( cf["mesh_from_image"][0], image_range=[float(cf["mesh_from_image"][1]), float(cf["mesh_from_image"][2]), float(cf["mesh_from_image"][3]), float(cf["mesh_from_image"][4]) ], sim_name=cf["sim_name"] ) if isinstance(cf["mu_s"], str): sim_from_image.generate_magnetic_moments(load_file=cf["mu_s"]) else: sim_from_image.generate_magnetic_moments(mu_s=(mu_s)) sim = sim_from_image.sim elif cf.get("truncated_triangle"): if len(cf["truncated_triangle"]) == 3: sim_triangle = TruncatedTriangleSim( cf["truncated_triangle"][0], # L cf["truncated_triangle"][1], # offset cf["truncated_triangle"][2], # a cf["mu_s"], # mu_s name=cf["sim_name"] ) elif len(cf["truncated_triangle"]) == 5: sim_triangle = TruncatedTriangleSim( cf["truncated_triangle"][0], # L [float(offs) for offs in cf["truncated_triangle"][1:4]], # offsets cf["truncated_triangle"][4], # a cf["mu_s"], # mu_s name=cf["sim_name"] ) sim = sim_triangle.sim elif cf.get("hexagon"): sim_hexagon = HexagonSim(cf["hexagon"][0], # R cf["hexagon"][1], # a cf["mu_s"], # mu_s name=cf["sim_name"] ) sim = sim_hexagon.sim # Initial state sim.set_m(init_state) sim.driver.do_precession = cf["llg_do_precession"] sim.driver.alpha = cf["llg_alpha"] # Material parameters ----------------------------------------------------- if cf.get("hexagonal_mesh"): sim.mu_s = mu_s exch = UniformExchange(J) sim.add(exch) dmi = DMI(D=(D), dmi_type='interfacial') sim.add(dmi) zeeman = Zeeman((0, 0, 0)) sim.add(zeeman, save_field=True) if k_u: # Uniaxial anisotropy along + z-axis sim.add(Anisotropy(k_u, axis=[0, 0, 1])) if cf.get("Demag"): print('Using Demag!') sim.add(DemagHexagonal()) # Pin boundaries ---------------------------------------------------------- # We will correct the spin directions according to the specified argument, # in case the spins at the boundaries are pinned if cf.get('pin_boundaries'): ngbs_filter = np.zeros(sim.pins.shape[0]) # Filter rows by checking if any of the elements is less than zero # This means that if any of the neighbours of the i-th lattice site is # -1, we pin the spin direction at that site ngbs_filter = np.any(sim.mesh.neighbours < 0, axis=1, out=ngbs_filter) sim.set_pins(ngbs_filter) # Hysteresis -------------------------------------------------------------- for ext in ['npys', 'vtks']: if not os.path.exists('{}/{}'.format(ext, cf["sim_name"])): os.makedirs('{}/{}'.format(ext, cf["sim_name"])) for ext in ['txts', 'dats']: if not os.path.exists('{}/'.format(ext)): os.makedirs('{}'.format(ext)) Brange = cf["hysteresis_steps"] print('Computing for Fields:', Brange) # We will save the hysteresis steps on this file with every row as: # step_number field_in_Tesla hystfile = '{}_hyst_steps.dat'.format(cf["sim_name"]) # If the file already exists, we will append the new steps, otherwise # we just create a new file (useful for restarting simulations) if not os.path.exists(hystfile): nsteps = 0 fstate = 'w' else: # Move old txt file from the previous simulation, appending an _r # everytime a simulation with the same name is started txtfile = [f for f in os.listdir('.') if f.endswith('txt')][0] txtfile = re.search(r'.*(?=\.txt)', txtfile).group(0) shutil.move(txtfile + '.txt', txtfile + '_r.txt') nsteps = len(np.loadtxt(hystfile)) fstate = 'a' f = open(hystfile, fstate) for i, B in enumerate(Brange): sim.get_interaction('Zeeman').update_field(B) sim.driver.relax(dt=cf["llg_dt"], stopping_dmdt=cf["llg_stopping_dmdt"], max_steps=cf["llg_max_steps"], save_m_steps=None, save_vtk_steps=None ) print('Saving NPY for B = {}'.format(B)) np.save('npys/{0}/step_{1}.npy'.format(cf["sim_name"], i + nsteps), sim.spin) sim.driver.save_vtk() shutil.move('{}_vtks/m_{}.vtk'.format(cf["sim_name"], str(sim.driver.step).zfill(6) ), 'vtks/{0}/step_{1}.vtk'.format(cf["sim_name"], i + nsteps) ) f.write('{} {} {} {}\n'.format(i + nsteps, B[0], B[1], B[2], ) ) f.flush() sim.driver.reset_integrator() os.rmdir('{}_vtks'.format(cf["sim_name"])) shutil.move('{}.txt'.format(cf["sim_name"]), 'txts/') shutil.move(hystfile, 'dats/') f.close()