|
| 1 | +from __future__ import print_function |
| 2 | +import pytest |
| 3 | + |
| 4 | +import numpy as np |
| 5 | + |
| 6 | +# FIDIMAG libraries |
| 7 | +from fidimag.common import CuboidMesh as Mesh |
| 8 | +from fidimag.atomistic import Sim, UniformExchange, Anisotropy |
| 9 | +import fidimag.common.constant as const |
| 10 | + |
| 11 | +mu0 = 4 * np.pi * 1e-7 |
| 12 | + |
| 13 | +def load_mz_npy(npy_file): |
| 14 | + |
| 15 | + m0_z = np.load(npy_file) |
| 16 | + m_magnitude = m0_z[0] ** 2 + m0_z[1] ** 2 + m0_z[2] ** 2 |
| 17 | + |
| 18 | + if np.abs(m_magnitude - 1) < 1e-6: |
| 19 | + m0_z = m0_z.reshape(-1, 3)[:, 2] |
| 20 | + else: |
| 21 | + m0_z = m0_z.reshape(3, -1)[2] |
| 22 | + |
| 23 | + return m0_z |
| 24 | + |
| 25 | + |
| 26 | +# Initial State, a rough DW in a 1D chain |
| 27 | +def init_m(pos): |
| 28 | + |
| 29 | + x = pos[0] |
| 30 | + |
| 31 | + if x < 450: |
| 32 | + return (1, 0, 0) |
| 33 | + elif 450 <= x < 550: |
| 34 | + return (0, 1, 1) |
| 35 | + else: |
| 36 | + return (-1, 0, 0) |
| 37 | + |
| 38 | + |
| 39 | +def relax_system(mesh): |
| 40 | + |
| 41 | + # Only relaxation |
| 42 | + sim = Sim(mesh, name='relax') |
| 43 | + |
| 44 | + # Simulation parameters |
| 45 | + sim.set_tols(rtol=1e-8, atol=1e-10) |
| 46 | + sim.alpha = 0.5 |
| 47 | + sim.gamma = 2.211e5/mu0 |
| 48 | + sim.mu_s = 1e-27/mu0 |
| 49 | + sim.do_precession = False |
| 50 | + |
| 51 | + # The initial state passed as a function |
| 52 | + sim.set_m(init_m) |
| 53 | + # sim.set_m(np.load('m0.npy')) |
| 54 | + |
| 55 | + # Energies |
| 56 | + exch = UniformExchange(J=2e-20) |
| 57 | + sim.add(exch) |
| 58 | + |
| 59 | + anis = Anisotropy(0.01*2e-20, axis=(1,0,0)) |
| 60 | + sim.add(anis) |
| 61 | + |
| 62 | + # dmi = DMI(D=8e-4) |
| 63 | + # sim.add(dmi) |
| 64 | + |
| 65 | + # Start relaxation and save the state in m0.npy |
| 66 | + sim.relax(dt=1e-14, stopping_dmdt=1e3, max_steps=5000, |
| 67 | + save_m_steps=None, save_vtk_steps=None) |
| 68 | + |
| 69 | + np.save('m0.npy', sim.spin) |
| 70 | + #sim.save_vtk() |
| 71 | + |
| 72 | + |
| 73 | +# This function excites the system with a |
| 74 | +# current in the x-direction using Spin Transfer Torque |
| 75 | +# formalism |
| 76 | +def excite_system(mesh, time=0.1, snaps=11): |
| 77 | + |
| 78 | + # Specify the stt dynamics in the simulation |
| 79 | + sim = Sim(mesh, name='dyn', driver='llg_stt') |
| 80 | + |
| 81 | + # Set the simulation parameters |
| 82 | + sim.set_tols(rtol=1e-12, atol=1e-12) |
| 83 | + sim.gamma = 2.211e5/mu0 |
| 84 | + sim.mu_s = 1e-27/mu0 |
| 85 | + sim.alpha = 0.05 |
| 86 | + |
| 87 | + sim.set_m(np.load('m0.npy')) |
| 88 | + |
| 89 | + # Energies |
| 90 | + exch = UniformExchange(J=2e-20) |
| 91 | + sim.add(exch) |
| 92 | + |
| 93 | + anis = Anisotropy(0.01*2e-20, axis=(1,0,0)) |
| 94 | + sim.add(anis) |
| 95 | + # dmi = DMI(D=8e-4) |
| 96 | + # sim.add(dmi) |
| 97 | + |
| 98 | + # Set the current in the x direction, in A / m |
| 99 | + # beta is the parameter in the STT torque |
| 100 | + sim.jx = -1e12 |
| 101 | + sim.beta = 0.1 |
| 102 | + |
| 103 | + # The simulation will run for x ns and save |
| 104 | + # 'snaps' snapshots of the system in the process |
| 105 | + ts = np.linspace(0, time * 1e-9, snaps) |
| 106 | + |
| 107 | + |
| 108 | + for t in ts: |
| 109 | + print('time', t) |
| 110 | + sim.run_until(t) |
| 111 | + #sim.save_vtk() |
| 112 | + np.save('m1.npy', sim.spin) |
| 113 | + |
| 114 | + |
| 115 | +def test_stt_dw_atomistic(): |
| 116 | + mesh = Mesh(nx=1000, ny=1, nz=1, |
| 117 | + dx=1.0, dy=1.0, dz=1.0, |
| 118 | + unit_length=1e-9) |
| 119 | + |
| 120 | + # Relax the initial state. It will save the last state |
| 121 | + # to the m0.npy file |
| 122 | + relax_system(mesh) |
| 123 | + |
| 124 | + m0 = np.load('m0.npy') |
| 125 | + m0.shape=(-1,3) |
| 126 | + mx0 = np.average(m0[:,0]) |
| 127 | + |
| 128 | + excite_system(mesh) |
| 129 | + |
| 130 | + m1 = np.load('m1.npy') |
| 131 | + m1.shape=(-1,3) |
| 132 | + mx1 = np.average(m1[:,0]) |
| 133 | + |
| 134 | + mu_s = (1e-27/mu0) |
| 135 | + v = 1e-27 |
| 136 | + p = 0.5 |
| 137 | + jx = 1e12 |
| 138 | + alpha = 0.05 |
| 139 | + beta = 0.1 |
| 140 | + time = 0.1 |
| 141 | + |
| 142 | + u = const.g_e * const.mu_B / (2 * const.c_e) * v/ mu_s * p * jx |
| 143 | + distance = (1+alpha*beta)/(1+alpha*alpha)*u*time |
| 144 | + dmx = distance/1000*2 |
| 145 | + |
| 146 | + print(mx0, mx1, dmx, abs(mx1-mx0-dmx)) |
| 147 | + assert(mx1-mx0>0) |
| 148 | + assert(abs(mx1-mx0-dmx)<5e-5) |
| 149 | + |
| 150 | +if __name__ == '__main__': |
| 151 | + test_stt_dw_atomistic() |
0 commit comments