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 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_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
os.makedirs(txt_dir) if args.save_energy: energies_dir = 'energies/' if not os.path.exists(energies_dir): os.makedirs(energies_dir) E = sim.compute_energy() np.savetxt(energies_dir + args.sim_name + '_E.txt', np.array([E])) if args.save_Q: Q_dir = 'top_charges/' if not os.path.exists(Q_dir): os.makedirs(Q_dir) Q = sim.skyrmion_number(method='BergLuscher') np.savetxt(Q_dir + args.sim_name + '_Q.txt', np.array([Q])) # files = [_f for _f in os.listdir('.') # if (os.path.isdir(_f) and _f.startswith(args.sim_name))] # Fidimag vtk and npy files are saved in the sim_name_vtks or sim_name_npys # folders respectively. We will move them to the vtks/ and npys/ directories # Remove the vtk folder if it already exists inside the vtks/ folder if os.path.exists(vtk_dir + args.sim_name + '_vtks/'): shutil.rmtree(vtk_dir + args.sim_name + '_vtks/') try: shutil.move(args.sim_name + '_vtks/', vtk_dir) except IOError: pass
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