def test_exchange_frequence_as_deviation_angle(self): deviation_angles = np.array(list(range(30, 45, 5))) * np.pi / 180 for idx, d_angle in enumerate(deviation_angles): # Start by setting the initial position of the spins r, theta1, phi1 = to_sph([np.cos(d_angle), np.sin(d_angle), 0]) r, theta2, phi2 = to_sph([-np.cos(d_angle), np.sin(d_angle), 0]) self.sim.particles.atoms[0].set_position(theta1, phi1) self.sim.particles.atoms[1].set_position(theta2, phi2) # Next run the simulation self.sim.run_simulation(2**24) # Run the transformation self.sim.run_transformations(np.array([0, 0, 0])) # max_value_xx = max(self.sim.transformtables['[0 0 0]'].cols.I_xx) # max_value_yy = max(self.sim.transformtables['[0 0 0]'].cols.I_yy) # max_value_zz = max(self.sim.transformtables['[0 0 0]'].cols.I_zz) # # for row in self.sim.transformtables['[0 0 0]'].where('I_xx == {}'.format(max_value_xx)): # print('I_xx', max_value_xx, ', d_theta =', d_angle, ', E = ', row['energy']) # # for row in self.sim.transformtables['[0 0 0]'].where('I_yy == {}'.format(max_value_yy)): # print('I_yy', max_value_yy, ', d_theta =', d_angle, ', E = ', row['energy']) # # for row in self.sim.transformtables['[0 0 0]'].where('I_zz == {}'.format(max_value_zz)): # print('I_zz', max_value_yy, ', d_theta =', d_angle, ', E = ', row['energy']) self.sim.plot_energies('data/two_spins_test/t_two_spin_E_{}_' + str(d_angle) + '.png') plt.show() # self.sim.plot_spins_xyz('data/two_spins_test/two_spins_xyz_{}.png'.format(d_angle)) # Reset the simulation for the next angle plt.close('all') self.sim.close() self.sim.datafile = None self.sim.transformfile = None self.sim.transformtables = {} rmtree(self.tmpdir) # If were not just debugging we want to delete the datafile if not self.sim.options['debug']: rmtree(self.tmpdir) # Plot the expected along with the actual energies if self.sim.options['debug']: plt.figure(figsize=(6, 4), tight_layout=True) plt.plot(deviation_angles, expected_energies, label='Expected') plt.plot(deviation_angles, top_energies_z1, '.', label='Numerical') plt.xlabel('Angle [Degrees]', fontsize=10) plt.ylabel('Resonance energy [meV]', fontsize=10) plt.yticks(fontsize=9) plt.xticks(fontsize=9) plt.legend(prop={'size': 10}) plt.savefig('resonance_of_angle_two_spins.png', dpi=300) plt.show()
def setUp(self): # Create temporary folder for data files self.tmpdir = mkdtemp() self.tmpdir = 'data/three_spins_test' dt, n = calculate_dt_and_n(0.01, 10) n = int(n) J = - 172 print(dt, n) # Initialize a simulation self.sim = BaseSimulation() # Configure the simulation self.sim.options['simulation_name'] = 'TestThreeSpins' self.sim.options['input_file'] = 'tests/molecules/three_spins_triangle.pdb' self.sim.options['spin'] = 7 / 2 self.sim.options['l'] = l = 5e-4 self.sim.options['dt'] = dt = 1e-14 self.sim.options['J'] = J * self.sim.constants['k_b'] self.sim.options['T'] = T = .05 self.sim.options['B'] = [0., 0., 0.] self.sim.options['debug'] = True self.sim.options['data_file'] = self.tmpdir + f'/data_ad_bs_ks5_B0.1_dt{dt}_T{T}_l{l}_J{J}_60_deg.h5' self.sim.options['data_file'] = self.tmpdir + f'/data_dt4.1356673300000004e-16_T0.05_l5e-05_n999999.95_J-710.h5' self.sim.options['data_file'] = self.tmpdir + f'/data_dt1e-15_T0.05.h5' self.sim.options['transform_file'] = self.tmpdir + f'/transforms_final2.h5' self.sim.options['integrator'] = 'ad_bs' self.sim.load_particles() # Start by setting the initial position of the spins d_angle = 12 * np.pi / 180 r, theta1, phi1 = to_sph([np.sin(d_angle), np.cos(d_angle), np.cos(d_angle)]) r, theta2, phi2 = to_sph([np.sin(-d_angle), np.cos(d_angle), np.cos(d_angle)]) r, theta3, phi3 = to_sph([np.sin(d_angle), np.cos(-d_angle), np.cos(-d_angle)]) self.sim.particles.atoms[0].set_position(theta1, phi1) self.sim.particles.atoms[1].set_position(theta2, phi2) self.sim.particles.atoms[2].set_position(theta3, phi3) print([-np.sin(d_angle), np.cos(d_angle), np.cos(d_angle)]) print([np.sin(-d_angle), -np.cos(d_angle), -np.cos(d_angle)]) print([np.sin(d_angle), np.cos(-d_angle), np.cos(-d_angle)]) # Get the data loaded self.sim.run_simulation(1) # restore to last position for p in range(0, 3): r, theta, phi = to_sph([ self.sim.datatables[f'p{p}'].cols.pos_x[-1], self.sim.datatables[f'p{p}'].cols.pos_y[-1], self.sim.datatables[f'p{p}'].cols.pos_z[-1] ]) self.sim.particles.atoms[p].set_position(theta, phi) # self.sim.run_anneal(2**18) self.sim.run_simulation(2**22)
def __init__(self, id, atom, N, neighbours, options, constants): self.id = id self.N = N self.B_eff = np.array([0.0, 0.0, 0.0], dtype='float') self.B_eff_sph = 0., 0., 0. self.options = options self.constants = constants self.neighbours = neighbours self.lattice_position = atom.position r, theta, phi = to_sph(self.lattice_position) # Find initial position (just start with the lattice position) # Set r = 1 as we work with a unit vector representing the spin self.r = 1 self.theta = theta self.phi = phi # We use cartesian when calculating the effective B-field self.pos = to_cart([self.r, self.theta, self.phi]) # We calculate a constant once, so we don't have to do it for each iteration self.b_eff_p = -2 * options['J'] * options['spin'] / ( constants['g'] * constants['mu_b']) # We set the previous steps for use with Adams Bashforth integration self.sphi4, self.sphi3, self.sphi2, self.sphi1 = None, None, None, None self.stheta4, self.stheta3, self.stheta2, self.stheta1 = None, None, None, None
def map_function(params): sim = BaseSimulation() sim.options = params["sim"].options # Calculate positions of atoms positions = [] for i in range(params['n']): positions.append([params['d'] + i * params['d'], 0.0001, 0.0001]) # Create the atoms and load them into the simulation chain = Atoms('Gd' + str(params['n']), positions=positions) sim.load_particles(chain) # Grab parameters from the dictionary q_m = params['q_m'] c, o = params['c'], params['o'] # Calculate the scattering vector q = q_m * 2 * np.pi / params['n'] q_vec = np.array([q, 0., 0.]) # Calculate dt and N from expected energy max_expected_energy = 4. * params['J'] * k_b_meV * o['spin'] dt, N = calculate_dt_and_n(max_expected_energy * 0.01, max_expected_energy) print(max_expected_energy, dt, N) # Set relevant parameters on the sim params["N"] = N = N sim.options['dt'] = dt = dt sim.options['data_file'] = params[ "tmpdir"] + f'/datam_q{q}_n{params["n"]}_J{params["J"]}_T{params["T"]}_dt{dt}_S{params["S"]}_dt{dt}_d{params["d"]}_BZ{o["B"][2]}.h5' sim.options['transform_file'] = params[ "tmpdir"] + f'/transformsm_q{q}_n{params["n"]}_J{params["J"]}_T{params["T"]}_N{N}_dt{dt}_S{params["S"]}_dt{dt}_d{params["d"]}_BZ{o["B"][2]}.h5' # Set the initial positions of the spin to mirror a spin wave state for i in range(params["n"]): r, theta, phi = to_sph([np.cos(q * i), np.sin(q * i), 0.8]) sim.particles.atoms[i].set_position(theta, phi) # Run the sim and transforms sim.run_simulation(N) sim.run_transformations(q_vec) # Close everything down so we can open it in the main thread. sim.close() # Return the options and q_vector used return sim.options, q_vec, q_m
def setUp(self): # Create temporary folder for data files self.tmpdir = mkdtemp() self.tmpdir = 'data/ten_spins_test' # Initialize a simulation self.sim = BaseSimulation() # Some parameters n = 22 # Number of atoms d = 0.9 # One Aangstroem between each atom J = -126.0 T = 0.0 S = 7/2 self.q = q = 2 * np.pi / (n * d) # Calculate dt and N from expected energy expected_energy = np.abs(8 * S * J * k_b_meV) dt, N = calculate_dt_and_n(expected_energy * 0.5, expected_energy * 2) print(expected_energy) self.N = N = int(N / 8) dt = 68 * dt # N = 2000 BZ = 0. # Configure the simulation self.sim.options['simulation_name'] = 'TestSpinChain' self.sim.options['l'] = 0 self.sim.options['dt'] = dt self.sim.options['J'] = J * self.sim.constants['k_b'] self.sim.options['T'] = T self.sim.options['B'] = [0., 0., BZ] self.sim.options['spin'] = S self.sim.options['pbc'] = (True, False, False) self.sim.options['debug'] = True self.sim.options['data_file'] = self.tmpdir + f'/data_n{n}_J{J}_T{T}_N{N}_S{S}_dt{dt}_d{d}_B{BZ}.h5' self.sim.options['transform_file'] = self.tmpdir + f'/transforms_n{n}_J{J}_T{T}_N{N}_S{S}_dt{dt}_d{d}.h5' print(self.sim.options['data_file']) # Calculate positions of atoms positions = [] for i in range(n): positions.append([d + i * d, 0.0001, 0.0001]) # Create the atoms and load them into the simulation chain = Atoms('Gd' + str(n), positions = positions) self.sim.load_particles(chain) # Set the initial positions of the spin to mirror a spin wave state for q_m in range(1, 14): q = q_m * np.pi / 22 realspace = [] for i in range(n): x, y, z = np.cos(q * i), np.sin(q * i), 0.1 # Perturb the system if i == 100 and False: x += 0.1 y += 0.1 r, theta, phi = to_sph([x, y, z]) self.sim.particles.atoms[i].set_position(theta, phi) realspace.append([x, y, z]) self.sim.run_simulation((q_m) * N)
def test_dampening(self): # Set initial conditions d_angle_degrees = 45 d_angle = d_angle_degrees * np.pi / 180 r, theta1, phi1 = np.round( to_sph([np.sin(d_angle), np.cos(d_angle), np.cos(d_angle)]), 3) r, theta2, phi2 = np.round( to_sph([np.sin(d_angle), -np.cos(d_angle), -np.cos(d_angle)]), 3) self.sim.particles.atoms[0].set_position(theta1, phi1) self.sim.particles.atoms[1].set_position(theta2, phi2) # Figure out what the effective B-field is self.sim.particles.combine_neighbours() B_eff = self.sim.particles.atoms[0].B_eff # Figure out what our expected energy is expected_energy = ( (self.sim.constants['Hz_to_meV'] / (2 * np.pi)) * self.sim.constants['gamma'] * (B_eff[0] * np.cos(d_angle) - B_eff[2] * np.sin(d_angle)) / np.cos(d_angle)) # calculate and set dt and N dt, N = calculate_dt_and_n(expected_energy * 0.5, expected_energy * 2) N = 4 * int(np.ceil(N)) self.sim.options['dt'] = 2 * dt # Next run the simulation self.sim.options[ 'data_file'] = self.tmpdir + '/data_without_dampening.h5' self.sim.run_simulation(np.ceil(N)) # Setup the baseline comparison x = self.sim.datatables['p0'].cols.pos_x y = self.sim.datatables['p0'].cols.pos_y z = self.sim.datatables['p0'].cols.pos_z t = np.asarray(range(len(x))) * self.sim.options['dt'] fig, axs = plt.subplots(nrows=2, ncols=2, constrained_layout=True) ax = axs.flat[0] ax.plot(t, x, label='x') ax.plot(t, y, label='y') ax.plot(t, z, label='z') ax.set_title('a', fontsize=10) ax.set_xlabel('t [s]', fontsize=10) ax.set_ylabel('s(t) [A.U.]', fontsize=10) ax.legend(prop={'size': 10}) ax = axs.flat[1] ax.plot(t[-2000:], x[-2000:], label='x') ax.plot(t[-2000:], y[-2000:], label='y') ax.plot(t[-2000:], z[-2000:], label='z') ax.set_title('b', fontsize=10) ax.set_xlabel('t [s]', fontsize=10) ax.set_ylabel('s(t) [A.U.]', fontsize=10) ax.legend(prop={'size': 10}) # plt.figure(figsize=(6, 4), tight_layout=True) # # plt.plot(t, x, label='x') # plt.plot(t, y, label='y') # plt.plot(t, z, label='z') # # plt.xlabel('t [s]', fontsize=10) # plt.ylabel('s(t) [A.U.]', fontsize=10) # plt.legend(prop={'size': 10}) # # plt.yticks(fontsize=9) # plt.xticks(fontsize=9) # plt.show() # Reset the simulation so we can compare with dampening enabled self.sim.close() self.sim.datafile = None self.sim.transformfile = None self.sim.transformtables = {} # Set dampening self.sim.options['l'] = 1e-3 # Run the second simulation self.sim.options['data_file'] = self.tmpdir + '/data_with_dampening.h5' self.sim.run_simulation(np.ceil(N)) # And plot again so we can compare x = self.sim.datatables['p0'].cols.pos_x y = self.sim.datatables['p0'].cols.pos_y z = self.sim.datatables['p0'].cols.pos_z t = np.asarray(range(len(x))) * self.sim.options['dt'] # plt.figure(figsize=(6, 4), tight_layout=True) ax = axs.flat[2] ax.plot(t, x, label='x') ax.plot(t, y, label='y') ax.plot(t, z, label='z') ax.set_title('c', fontsize=10) ax.set_xlabel('t [s]', fontsize=10) ax.set_ylabel('s(t) [A.U.]', fontsize=10) ax.legend(prop={'size': 10}) ax = axs.flat[3] ax.plot(t[-2000:], x[-2000:], label='x') ax.plot(t[-2000:], y[-2000:], label='y') ax.plot(t[-2000:], z[-2000:], label='z') ax.set_title('d', fontsize=10) ax.set_xlabel('t [s]', fontsize=10) ax.set_ylabel('s(t) [A.U.]', fontsize=10) ax.legend(prop={'size': 10}) plt.show()