def relax_system(mesh, Dx=0.005, Dp=0.01): mat = UnitMaterial() sim = Sim(mesh, name='test_energy') print('Created sim') sim.driver.set_tols(rtol=1e-10, atol=1e-12) sim.alpha = mat.alpha sim.driver.gamma = mat.gamma sim.pins = pin_fun exch = UniformExchange(mat.J) sim.add(exch) print('Added UniformExchange') anis = Anisotropy(Dx, axis=[1, 0, 0], name='Dx') sim.add(anis) print('Added Anisotropy') anis2 = Anisotropy([0, 0, -Dp], name='Dp') sim.add(anis2) print('Added Anisotropy 2') sim.set_m((1, 1, 1)) T = 100 ts = np.linspace(0, T, 201) for t in ts: # sim.save_vtk() sim.driver.run_until(t) print(('Running -', t)) # sim.save_vtk() np.save('m0.npy', sim.spin)
def test_dynamic(): mesh = CuboidMesh(nx=1, ny=1, nz=1) sim = Sim(mesh, name='dyn_spin', driver='llg_stt_cpp') # sim.set_options(rtol=1e-10,atol=1e-14) sim.driver.gamma = 1.0 sim.mu_s = 1.0 sim.set_m((0.8, 0, -1)) Kx = Anisotropy(Ku=-0.05, axis=(0, 0, 1), name='Kz') sim.add(Kx) sim.p = (0, 0, 1) sim.a_J = 0.0052 sim.alpha = 0.1 ts = np.linspace(0, 1200, 401) for t in ts: sim.driver.run_until(t) mz = sim.spin[2] alpha, K, u = 0.1, 0.05, 0.0052 print(mz, u / (2 * alpha * K)) ######################################################### # The system used in this test can be solved analytically, which gives that mz = u/(2*alpha*K), # where K represents the easy-plane anisotropy. ### assert abs(mz - u / (2 * alpha * K)) / mz < 5e-4
def dynamic(mesh): sim = Sim(mesh, name='dyn', driver='slonczewski') # sim.set_options(rtol=1e-10,atol=1e-14) 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) Kx = Anisotropy(Ku=0.005, axis=(1, 0, 0), name='Kx') sim.add(Kx) sim.p = (0, 0, 1) sim.u0 = 0.03 sim.driver.alpha = 0.1 ts = np.linspace(0, 1e3, 101) for t in ts: sim.run_until(t) sim.save_vtk() print t
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) Kx = Anisotropy(Ku=0.005, axis=(1, 0, 0), name='Kx') sim.add(Kx) 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 relax_system(mesh): # Only relaxation sim = Sim(mesh, name='relax') # Simulation parameters sim.driver.set_tols(rtol=1e-8, atol=1e-10) sim.alpha = 0.5 sim.driver.gamma = 2.211e5 / mu0 sim.mu_s = 1e-27 / mu0 sim.driver.do_precession = False # The initial state passed as a function sim.set_m(init_m) # sim.set_m(np.load('m0.npy')) # Energies exch = UniformExchange(J=2e-20) sim.add(exch) anis = Anisotropy(0.01 * 2e-20, axis=(0, 0, 1)) sim.add(anis) # dmi = DMI(D=8e-4) # sim.add(dmi) # Start relaxation and save the state in m0.npy sim.relax(dt=1e-14, stopping_dmdt=1e4, max_steps=5000, save_m_steps=None, save_vtk_steps=None) np.save('m0.npy', sim.spin)
def relax_neb(k, maxst, simname, init_im, interp, save_every=10000): """ Execute a simulation with the NEB function of the FIDIMAG code The simulations are made for a specific spring constant 'k' (a float), number of images 'init_im', interpolations between images 'interp' (an array) and a maximum of 'maxst' steps. 'simname' is the name of the simulation, to distinguish the output files. --> vtks and npys are saved in files starting with the 'simname' string """ # Prepare simulation sim = Sim(mesh, name=simname) sim.driver.gamma = const.gamma # magnetisation in units of Bohr's magneton sim.mu_s = 2. * const.mu_B # Exchange constant in Joules: E = Sum J_{ij} S_i S_j J = 12. * const.meV exch = UniformExchange(J) sim.add(exch) # DMI constant in Joules: E = Sum D_{ij} S_i x S_j D = 2. * const.meV dmi = DMI(D, dmi_type='interfacial') sim.add(dmi) # Anisotropy along +z axis ku = Anisotropy(Ku=0.5 * const.meV, axis=[0, 0, 1], name='ku') sim.add(ku) # Initial images init_images = init_im # Number of images between each state specified before (here we need only # two, one for the states between the initial and intermediate state # and another one for the images between the intermediate and final # states). Thus, the number of interpolations must always be # equal to 'the number of initial states specified', minus one. interpolations = interp neb = NEB_Sundials(sim, init_images, interpolations=interpolations, spring=k, name=simname) neb.relax(max_steps=maxst, save_vtk_steps=save_every, save_npy_steps=save_every, stopping_dmdt=1e-2)
def test_sim_pin(): mesh = CuboidMesh(nx=3, ny=2, nz=1) sim = Sim(mesh) sim.set_m((0, 0.8, 0.6)) sim.alpha = 0.1 sim.gamma = 1.0 sim.pins = pin_fun anis = Anisotropy(Ku=1.0, axis=[0, 0, 1], name='Dx') sim.add(anis) sim.run_until(1.0) assert sim.spin[0] == 0 assert sim.spin[2] != 0
def relax_system(): # 1D chain of 50 spins with a lattice constant of 0.27 A mesh = CuboidMesh( nx=nx, dx=dx, unit_length=1e-9, # pbc='1d' ) # Initiate the simulation sim = Sim(mesh, name=sim_name) sim.gamma = const.gamma # magnetisation in units of Bohr's magneton sim.mu_s = 2 * const.mu_B # sim.set_options(gamma=const.gamma, k_B=const.k_B) # Initial magnetisation profile sim.set_m(init_m) # Exchange constant in Joules: E = Sum J_{ij} S_i S_j J = 12. * const.meV exch = UniformExchange(J) sim.add(exch) # DMI constant in Joules: E = Sum D_{ij} S_i x S_j D = 2. * const.meV dmi = DMI(D, dmi_type='interfacial') sim.add(dmi) # Anisotropy along +z axis ku = Anisotropy(Ku=0.5 * const.meV, axis=[0, 0, 1], name='ku') sim.add(ku) # Faster convergence sim.alpha = 0.5 sim.do_precession = False sim.relax(dt=1e-13, stopping_dmdt=0.05, max_steps=700, save_m_steps=1000, save_vtk_steps=1000) # Save the last relaxed state np.save(sim_name + '.npy', sim.spin)
def test_dw_dmi_atomistic(do_plot=False): mesh = CuboidMesh(nx=300, ny=1, nz=1) sim = Sim(mesh, name='relax') sim.set_default_options(gamma=const.gamma) sim.alpha = 0.5 sim.mu_s = const.mu_s_1 sim.do_precession = False sim.set_m(m_init_dw) J = 50.0 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.01 * J dmi = DMI(D) sim.add(dmi) K = 0.005 * J anis = Anisotropy(K, axis=[1, 0, 0]) sim.add(anis) 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) xs = np.array([p[0] for p in mesh.coordinates]) - 150 mx, my, mz = analytical(xs, A=J / 2.0, D=-D, K=K) mxyz = sim.spin.copy() mxyz = mxyz.reshape(-1, 3).T assert max(abs(mxyz[0, :] - mx)) < 0.001 assert max(abs(mxyz[1, :] - my)) < 0.001 assert max(abs(mxyz[2, :] - mz)) < 0.0006 if do_plot: save_plot(xs, mxyz, mx, my, mz)
def test_anis(): mesh = CuboidMesh(nx=5, ny=3, nz=2) spin = np.zeros(90) anis = Anisotropy(Ku=1, axis=[1, 0, 0]) mu_s = np.ones(90) anis.setup(mesh, spin, mu_s) field = anis.compute_field() assert len(mesh.coordinates) == 5 * 3 * 2 assert np.max(field) == 0 spin[0] = 99 field = anis.compute_field() assert field[0] == 2 * 99
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 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.do_procession = False sim.set_m(m_init_dw) J = 50.0 * const.k_B exch = UniformExchange(J) sim.add(exch) D = 0.1 * J dmi = DMI(D, dmi_type='interfacial') sim.add(dmi) K = 0.02 * J anis = Anisotropy(K, axis=[0, 0, 1]) sim.add(anis) 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) xs = np.array([p[0] for p in mesh.pos]) - 150 mx, my, mz = analytical(xs, A=J / 2.0, D=-D, K=K) mxyz = sim.spin.copy() mxyz.shape = (3, -1) save_plot(xs, mxyz, mx, my, mz)
def dynamic(mesh): sim = Sim(mesh, name='dyn_spin', driver='slonczewski') # sim.set_options(rtol=1e-10,atol=1e-14) sim.gamma = 1.0 sim.mu_s = 1.0 sim.set_m((0.8, 0, -1)) Kx = Anisotropy(Ku=-0.05, axis=(0, 0, 1), name='Kz') sim.add(Kx) sim.p = (0, 0, 1) sim.u0 = 0.005 sim.alpha = 0.1 ts = np.linspace(0, 1200, 401) for t in ts: sim.run_until(t) #sim.save_vtk() print t
def excite_system(mesh, time=0.1, snaps=11): # Specify the stt dynamics in the simulation sim = Sim(mesh, name='dyn', driver='llg_stt') # Set the simulation parameters sim.driver.set_tols(rtol=1e-12, atol=1e-12) sim.driver.gamma = 2.211e5 / mu0 sim.mu_s = 1e-27 / mu0 sim.alpha = 0.05 sim.set_m(np.load('m0.npy')) # Energies exch = UniformExchange(J=2e-20) sim.add(exch) anis = Anisotropy(0.01 * 2e-20, axis=(0, 0, 1)) sim.add(anis) # dmi = DMI(D=8e-4) # sim.add(dmi) # Set the current in the x direction, in A / m # beta is the parameter in the STT torque sim.driver.jz = -1e12 sim.driver.beta = 0.1 # The simulation will run for x ns and save # 'snaps' snapshots of the system in the process ts = np.linspace(0, time * 1e-9, snaps) for t in ts: print('time', t) sim.driver.run_until(t) #sim.save_vtk() np.save('m1.npy', sim.spin) print(np.load('m1.npy')[:100])
def single_spin(alpha=0.01): mat = Material() mesh = CuboidMesh(nx=1, ny=1, nz=1) sim = Sim(mesh, driver='sllg') sim.alpha = alpha sim.gamma = mat.gamma sim.mu_s = mat.mu_s sim.T = 10000 sim.set_m((1, 1, 1)) #sim.add(Zeeman(1,(0, 0, 1))) anis = Anisotropy(mat.K, direction=(0, 0, 1)) sim.add(anis) dt = 0.5e-12 ts = np.linspace(0, 1000 * dt, 1001) sx = [] sy = [] for t in ts: sim.run_until(t) sx.append(sim.spin[0]) sy.append(sim.spin[1]) print(t) plt.plot(sx, sy) plt.xlabel("$S_x$") plt.ylabel("$S_y$") plt.grid() plt.axis((-0.9, 0.9, -0.9, 0.9)) plt.axes().set_aspect('equal') plt.savefig("macrospin.pdf")
def create_sim(): mesh = CuboidMesh(nx=121, ny=121, nz=1) sim = Sim(mesh, name='relax') sim.alpha = 1.0 sim.gamma = 0.5 sim.mu_s = mu_s sim.set_m(init_m) J = 1.0 exch = UniformExchange(J) sim.add(exch) D = 0.08 dmi = DMI(D) sim.add(dmi) K = 4e-3 anis = Anisotropy(K, direction=(0, 0, 1), name='Ku') sim.add(anis) return sim
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()
# Data ------------------------------------------------------------------------ mesh = HexagonalMesh(0.125, 320, 185, unit_length=1e-9, alignment='square') # Generate the linear interpolations of the NEBM band from every DMI value from # the arguments for D in args.D_list: sim = Sim(mesh) sim.set_mu_s(0.846 * const.mu_B) sim.add(DemagHexagonal()) sim.add(UniformExchange(J=27.026 * const.meV)) sim.add(DMI(DMIc[D] * const.meV, dmi_type='interfacial')) sim.add(Anisotropy(0.0676 * const.meV, axis=[0, 0, 1])) images = [ np.load(os.path.join(methods(args.method, D), _file)) for _file in sorted(os.listdir(methods(args.method, D)), key=lambda f: int(re.search('\d+', f).group(0))) ] nebm = NEBM_Geodesic(sim, images, spring_constant=1e4) l, E = nebm.compute_polynomial_approximation(500) # Distances for every image from the first image (0th image) ll = [0] for i in range(len(nebm.distances)): ll.append(np.sum(nebm.distances[:i + 1])) ll = np.array(ll)
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)) print('DMI constant: {} meV'.format(args.D)) if args.k_u: print('Anisotropy constant: {} meV'.format(args.k_u)) if args.B: print('Zeeman field: (0, 0, {}) T'.format(args.B / mu0))
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
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))