def test_full_exch_hex_3_shells_lattice_pos(): """ Test the x component of the exchange field when using 3 shells of neighbours in a 9 x 9 hexagonal lattice with square arrangement We set the s_x and s_y spin components as the (i, j) index of the lattice positions: """ a = 1 shells = 3 mesh = HexagonalMesh(a * 0.5, nx=9, ny=9, shells=shells, alignment='square') sim = Sim(mesh) # Set the indexes (i, j) as their s_x, s_y position sim.set_m(lambda r: init_m(r, a), normalise=False) Js = np.ones(shells) exch = Exchange(Js) sim.add(exch) field = exch.compute_field() assert field[3 * 0] == (1 + 1 + 0) + (2 + 0) + (2 + 1) # f_x 1st spin assert field[3 * 11] == ((3 + 1 + 2 + 1 + 1 + 2) + (3 + 0 + 2 + 0 + 0 + 3) + (4 + 0 + 3 + 0 + 1 + 0))
def test_exch_1d(): """ Test the x component of the exchange field in a 1D mesh, with the spin ordering: 0 1 2 3 4 5 """ mesh = CuboidMesh(nx=5, ny=1, nz=1) sim = Sim(mesh) exch = Exchange(1.0) sim.add(exch) sim.set_m(init_m, normalise=False) field = exch.compute_field() assert field[0] == 1 assert field[1 * 3] == 2 assert field[2 * 3] == 4 assert field[3 * 3] == 6 assert field[4 * 3] == 3 assert np.max(field[2::3]) == 0 assert np.max(field[1::3]) == 0
def test_full_exch_hex_2_shells(): """ Test the x component of the exchange field when using 2 shells of neighbours, comparing the field manually. This is similar than the *test_full_exch_hex_9_shells* function but here we do not assume that the neighbours indexes are correct We set J=1 for NN and J=2 for NNN """ a = 1 shells = 2 mesh = HexagonalMesh(a * 0.5, nx=9, ny=9, shells=shells, alignment='square') sim = Sim(mesh) sim.spin.reshape(-1, 3)[:, 0] = np.arange(len(sim.spin.reshape(-1, 3)[:, 0])) Js = np.array([1., 2.]) exch = Exchange(Js) sim.add(exch) field = exch.compute_field() assert field[3 * 0] == 1. * (1 + 10 + 9) + 2. * (11 + 18) assert field[3 * 11] == (12 + 10 + 20 + 1 + 19 + 2) + 2. * (21 + 29 + 18 + 3)
def test_full_exch_hex_9_shells_J_rings(): """ Test the x component of the exchange field when using 9 shells of neighbours in a 11 X 11 hexagonal lattice with square and diagonal arrangement We set J=1,2,3,.. for every shell and set the s_x component of the spins as the lattice site number: [0, 1, 2, 3, ... 120] Since we set the s_x components as the lattice position indexes, the x component of the field is the sum of the indexes of the neighbours (assuming the neighbours indexing is correct) multiplied by J[i] where i is the shell (1, 2, ...9), i.e. the 1st shell of ngbs is multiplied by 1, the 2nd shell by 2, the 3rd shell by 3, and so on """ for arrang in ['square', 'diagonal']: a = 1 shells = 9 mesh = HexagonalMesh(a * 0.5, nx=11, ny=11, shells=shells, alignment=arrang) sim = Sim(mesh) # Set s_x as the lattice site number sim.spin.reshape(-1, 3)[:, 0] = np.arange(len(sim.spin.reshape(-1, 3)[:, 0])) # Exchange constants according to the shell Js = np.arange(1, 10) exch = Exchange(Js) sim.add(exch) field = exch.compute_field() # We only test for the 60th lattice site ngbs_60 = mesh.neighbours[60] sum_ngbs = mesh._sum_ngbs_shell # For every shell, find the ngb indexes in that shell and multiply the # sum by the corresponding J=1, 2, 3, ... sum_rings = 0 for i in range(1, shells + 1): ngbs_range = slice(sum_ngbs[i - 1], sum_ngbs[i]) print('J = ', Js[i - 1], ' ngbs indexes: ', ngbs_60[ngbs_range]) sum_rings += Js[i - 1] * np.sum(ngbs_60[ngbs_range]) assert field[3 * 60] == sum_rings
def test_full_exch_hex_9_shells(): """ Test the x component of the exchange field when using 9 shells of neighbours in a 9 X 9 hexagonal lattice with square and diagonal arrangement We set J=1 for every shell and set the s_x component of the spins as the lattice site number: [0, 1, 2, 3, ... 80] Since we set the s_x components as the lattice position indexes, the x component of the field is just the sum of the indexes of the neighbours (assuming the neighbours indexing is correct) because we set the exchange constants as 1 """ for arrang in ['square', 'diagonal']: a = 1 shells = 9 mesh = HexagonalMesh(a * 0.5, nx=9, ny=9, shells=shells, alignment=arrang) sim = Sim(mesh) # Set s_x as the lattice site number sim.spin.reshape(-1, 3)[:, 0] = np.arange(len(sim.spin.reshape(-1, 3)[:, 0])) Js = np.ones(shells) exch = Exchange(Js) sim.add(exch) field = exch.compute_field() # Test the x component for every lattice site, summing the neighbours # index and removing the -1 elements (their contribution is zero) for i in range(sim.mesh.n): assert field[3 * i] == np.sum( remove_negatives(sim.mesh.neighbours[i]))
def test_exch_1d_spatial(): """ Test the x component of the exchange field in a 1D mesh, with the spin ordering: 0 1 2 3 4 5 """ mesh = CuboidMesh(nx=12, ny=1, nz=1) sim = Sim(mesh) exch = Exchange(spatial_J) sim.add(exch) sim.set_m(init_m, normalise=False) field = exch.compute_field() assert exch._J[3, 3] == -1.0 assert exch._J[5, 1] == 0.3 assert exch._J[6, 0] == 0.3 assert exch._J[8, 5] == 1.0
def test_exch_1d_spatial(): """ Test the x component of the exchange field in a 1D mesh, with the spin ordering: 0 1 2 3 4 5 """ mesh = CuboidMesh(nx=12, ny=1, nz=1) sim = Sim(mesh) exch = Exchange(spatial_J) sim.add(exch) sim.set_m(init_m, normalise=False) field = exch.compute_field() assert exch._J[3,3] == -1.0 assert exch._J[5,1] == 0.3 assert exch._J[6,0] == 0.3 assert exch._J[8,5] == 1.0
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))
# Fidimag simulation options ------------------------------------------------ # sim.set_tols(rtol=1e-10, atol=1e-14) sim.driver.alpha = args.alpha # sim.driver.gamma = 1.76e11 if args.no_precession: sim.driver.do_precession = False # Material parameters ------------------------------------------------------- if args.hexagonal_mesh: sim.mu_s = float(args.mu_s) * const.mu_B if shells == 1: exch = Exchange(args.J[0] * const.meV) else: exch = Exchange(np.array(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]))
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)) 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))
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))