def force_morse(particle1, particle2, re, de, a): """ Gives the Morse force between particles interacting via the Morse potential :param re: equilibrium bond distance :param de: parameter controlling depth of the potential minimum :param a: parameter controlling curvature of the potential minimum (small a -> wide well) """ r12 = np.linalg.norm(Particle3D.separation(particle1, particle2)) exp = math.exp(-a * (r12 - re)) unit_r = np.true_divide(Particle3D.separation(particle1, particle2), r12) force = 2 * a * de * (1 - exp) * exp * unit_r return force
def check_observables(particle_list, max_arr, min_arr, wrt_arr, time, orbit_complete_flags, period_arr): """ Computes the observables for the planets Inputs: list particle_list: list of particles array max_arr: array of current maximum orbit disances (float) array min_arr: array of current maximum orbit disances (float) wrt_arr: array of integers corresponding to the index of the particle that the particle of the index of the element is orbiting time: current time in simulation (float) orbit_complete_flags: boolean array that is true when the particle with that index has traversed 2pi radians period_arr: array containing the period of the particle with that index Return: 4 tuple containing adjusted max_arr, min_arr, orbit_complete_flags, period_arr """ #apoapsis/periapsis for i in range(len(particle_list)): sep = Particle3D.separation(particle_list[i], particle_list[wrt_arr[i]]) if norm(sep) > max_arr[i]: max_arr[i] = norm(sep) elif norm(sep) < min_arr[i]: min_arr[i] = norm(sep) #period for i in range(len(particle_list)): if not orbit_complete_flags[i]: if orbit_complete(particle_list[i], particle_list[wrt_arr[i]]): orbit_complete_flags[i] = True period_arr[i] = time return (max_arr, min_arr, orbit_complete_flags, period_arr)
def pairwiseforces(particle1, particle2, re, De, alpha): """ Method to return pairwise forces of 2 particles interacting via the morse potential. :param particle1: 1st Particle3D instance :param particle2: 2nd Particle3D instance :param re: paramater re :param De: parameter De :param alpha: parameter alpha :return: potential energy of pairwise particles """ #find separation using Particle3D separation sep = Particle3D.separation(particle1, particle2) #magnitude of separation vector r12 = np.linalg.norm(sep) #normalized separation vector rnorm = sep / r12 #find constant out front L = -alpha * (r12 - re) const = 2 * alpha * De * (1 - np.exp(L)) * np.exp(L) #const = 2*alpha*De*((1-(np.exp(-alpha*(r12-re))))*(np.exp(-alpha*(r12-re)))) #find force on particle 1 f1 = np.multiply(const, rnorm) #unsure if return both f1 or just one and inverse in main code return f1
def pe_lj(particle1,particle2,sigma): """ LJ params for Argon epsilon = 119.8 k_B sigma = 3.405e-10 m = 0.03994 kg/mol """ r = np.linalg.norm(Particle3D.separation(particle1,particle2))/sigma pe = 4*((r)*10^(-12) - (r)*10^(-6)) return pe
def pe_morse(particle1, particle2, re, de, a): """ Gives the Morse potential energy between particles interacting via the Morse potential :param re: equilibrium bond distance :param de: parameter controlling depth of the potential minimum :param a: parameter controlling curvature of the potential minimum (small a -> wide well) """ r12 = np.linalg.norm(Particle3D.separation(particle1, particle2)) exp = math.exp(-a * (r12 - re)) pe = de * (((1 - exp)**2) - 1) return pe
def force_morse(p1, p2, D, alpha, r_e): """ Method to return the force on a particle in a morse potential. Force is given by F(p1,p2) = (-2*alpha*D*(1-m.exp(-alpha*(r_12-r_e)))*(m.exp(-alpha*(r_12-r_e)))*Particle3D.separation(p1,p2))/r_12 :param p1: Particle3D instance 1 :param p2: Particle3D instance 2 :param D: parameter D from morse potential :param alpha: parameter alpha from morse potential :param r_e: parameter r_e from morse potential :return: force acting on particle p1 due to p2 as Numpy array """ #the magnitude of the particles' separation r_12 = np.linalg.norm(Particle3D.separation(p1, p2)) #the force on p1 due to p2 force = (-2 * alpha * D * (1 - math.exp(-alpha * (r_12 - r_e))) * (math.exp(-alpha * (r_12 - r_e)))) * (1 / r_12) * (Particle3D.separation( p1, p2)) return force
def grav_pot(p1, p2, G): """ Expression for energy potential of two particles due to gravity Inputs: Particle3D p1: particle 1 Particle3d p2: particle 2 float G: simulation specific parameters return float: energy potentialx """ G = float(G) if p1 == p2: return 0 sep = Particle3D.separation(p1, p2) energy = -1 * G * p1.mass * p2.mass / norm(sep) return energy
def morse_energy(r1, r2, D_e, r_e, alpha): """ Expression for energy potential of two particles due to morse potential Inputs: Particle3D r1: particle 1 Particle3d r2: particle 2 float D_e, r_e, alpha: simulation specific parameters return float: energy potential """ D_e, r_e, alpha = float(D_e), float(r_e), float(alpha) if r1 == r2: return 0 sep = Particle3D.separation(r1, r2) energy = D_e * ((1 - math.exp(-1 * alpha*(norm(sep) - r_e))) ** 2 - 1) return energy
def morse_force(r1, r2, D_e, r_e, alpha): """ Calculates the force due to the morse potential on particle 1 due to particle 2 Inputs: Particle3D r1: particle 1 Particle3d r2: particle 2 float D_e, r_e, alpha: simulation specific parameters return numpy array: force """ if r1 == r2: return np.array([0,0,0]) D_e, r_e, alpha = float(D_e), float(r_e), float(alpha) sep = Particle3D.separation(r1, r2) #Split expression for force into smaller parts for easier digestion force_part_one = -2 * alpha * D_e * (1 - math.exp(-1 * alpha * (norm(sep) - r_e))) force_part_two = math.exp(-1 * alpha * (norm(sep) - r_e)) return force_part_one * force_part_two * (sep/norm(sep))
def grav_force(p1, p2, G): """ Calculates the force due to gravity on particle 1 due to particle 2 Inputs: Particle3D p1: particle 1 Particle3d p2: particle 2 float G: simulation specific parameters return numpy array: force """ if p1 == p2: return np.array([0, 0, 0]) G = float(G) sep = Particle3D.separation(p1, p2) #Split expression for force into smaller parts for easier digestion force_part_one = G * p1.mass * p2.mass force_part_two = norm(sep)**3 return -1 * (force_part_one / force_part_two) * (sep)
def potenergy(particle1, particle2, re, De, alpha): """ Method to return potential energy of 2 particles interacting via the morse potential. :param particle1: 1st Particle3D instance :param particle2: 2nd Particle3D instance :param re: paramater re :param De: parameter De :param alpha: parameter alpha :return: potential energy of pairwise particles """ #find separation using Particle3D separation sep = Particle3D.separation(particle1, particle2) #find potential by finding magnitude of separation and using given eqn potential = De * ((1 - np.exp(-alpha * (np.linalg.norm(sep) - re)))**2 - 1) return potential
def v_verlet(p1, p2, dt, D, alpha, r_e): force = force_morse(p1, p2, D, alpha, r_e) p1.leap_pos2nd(dt, force) p2.leap_pos2nd(dt, -force) new_force = force_morse(p1, p2, D, alpha, r_e) p1.leap_velocity(dt, 0.5 * (force + new_force)) p2.leap_velocity(dt, 0.5 * (-force - new_force)) separ = np.linalg.norm(Particle3D.separation(p1, p2)) tot_ener = pot_energy_morse( separ, D, alpha, r_e) + p1.kinetic_energy() + p2.kinetic_energy() return [separ, tot_ener]
def main(): # Read name of output file from command line, 3 arguments; #python code, positiontext, and potential values if len(sys.argv) != 3: print("Wrong number of arguments.") print("Usage: " + sys.argv[0] + " <output file>") quit() else: #input files for initial position & potential constants inputfile1 = sys.argv[1] inputfile2 = sys.argv[2] # Open output files separation & total energy sep_outfile = open("separationfile.txt", "w") u_outfile = open("totalenergyfile.txt", "w") # Set up simulation parameters dt = float(input("Please determine timestep: ")) tfinal = 12 t = 0.0 tstep = int(tfinal / dt) #Open position file file_handle = open(inputfile1, "r") #Open potential constants file file_pot = open(inputfile2, "r") #read line of file line = file_pot.readline() #split file into components at "," within file, should have 4 elements components = line.split(" ") #convert to floats and separate vals = [float(i) for i in components] #separate for readability into constants De = vals[0] re = vals[1] alpha = vals[2] #NOTE mass is included in the initial positions file, not in here #Create particles from initial position files p1 = Particle3D.from_file(file_handle) p2 = Particle3D.from_file(file_handle) # Write out initial conditions, separation & energy separ = np.linalg.norm(Particle3D.separation(p1, p2)) energy = p1.kinetic_energy() + p2.kinetic_energy() + mp.potenergy( p1, p2, re, De, alpha) u_outfile.write("{},{}\n".format(t, energy)) sep_outfile.write("{},{}\n".format(t, separ)) #u_outfile.write("{0:f} {1:f} {2:12.8f}\n".format(time,p1.position,energy)) # Initialise data lists for plotting later, first points time_list = [t] sep_list = [separ] energy_list = [energy] #Print out of important variables print(p1) print(p2) print(separ) # Start the time integration loop, with steps being total time over step size for i in range(tstep): # Update particle positions p1.leap_pos1st(dt) p2.leap_pos1st(dt) # Calculate pairwiseforces pairwisef1 = mp.pairwiseforces(p1, p2, re, De, alpha) pairwisef2 = -pairwisef1 # Update particle velocities p1.leap_velocity(dt, pairwisef1) p2.leap_velocity(dt, pairwisef2) # Increase time t += dt # Output particle information #energy energy = p1.kinetic_energy() + p2.kinetic_energy() + mp.potenergy( p1, p2, re, De, alpha) u_outfile.write("{},{}\n".format(t, energy)) #separation separ = np.linalg.norm(Particle3D.separation(p1, p2)) sep_outfile.write("{}{}\n".format(t, separ)) # Append information to data lists time_list.append(t) sep_list.append(separ) energy_list.append(energy) # Post-simulation: # Close output file sep_outfile.close() u_outfile.close() # Plot particle trajectory to screen pyplot.title('Symplectic Euler: Separation vs time') pyplot.xlabel('Time (10.18fs)') pyplot.ylabel('Separation (Angstroms)') pyplot.plot(time_list, sep_list) pyplot.legend(['Total Separation of the two particles'], loc=2) pyplot.show() # Plot particle energy to screen pyplot.title('Symplectic Euler: total energy vs time') pyplot.xlabel('Time (10.18fs)') pyplot.ylabel('Energy (eV)') pyplot.plot(time_list, energy_list) pyplot.legend(['Total energy of the two particles'], loc=2) pyplot.show()
def main(): #have the user enter which particle type they want to simulate particle_prompt = input( "Which particle are you looking to simulate? Type O or N ") if particle_prompt == "O": p1 = Particle3D.from_file("oxygen1.txt") p2 = Particle3D.from_file("oxygen2.txt") numstep, time, alpha, r_e, D_e = from_file_system( "oxygen_parameters.txt") elif particle_prompt == "N": p1 = Particle3D.from_file("nitrogen1.txt") p2 = Particle3D.from_file("nitrogen2.txt") numstep, time, alpha, r_e, D_e = from_file_system( "nitrogen_parameters.txt") else: print("that doesn't look right!") exit() # have user specify timestep dt = input("Enter your preferred timestep: ") dt = float(dt) pos1 = p1.position pos2 = p2.position initial_dist12 = Particle3D.separation(p1, p2) # finds the initial energy value energy = p1.kinetic_energy() + p2.kinetic_energy() + potential( initial_dist12, r_e, D_e, alpha) # calculate initial force value force = force_dw(initial_dist12, r_e, D_e, alpha) print(force) #initialise data lists for plotting later initial_dist12 = np.linalg.norm(initial_dist12) time_list = [time * 10.8E-15] pos_list = [np.linalg.norm(initial_dist12)] energy_list = [energy] #start time integration loop for i in range(numstep): # update time, position and energy values time += dt # time - appended later new_pos1 = p1.update_position2(dt, force) new_pos2 = p2.update_position2(dt, -force) new_dist = np.subtract(new_pos1, new_pos2) new_dist_norm = np.linalg.norm(new_dist) energy = p1.kinetic_energy() + p2.kinetic_energy() + potential( new_dist, r_e, D_e, alpha) # append energy and time data values to lists energy_list.append(energy) time_list.append(time * 10.8E-15) pos_list.append(new_dist_norm) # assign current velocity to variables vel1 = p1.velocity vel2 = p2.velocity old_force = -force force = force_dw(new_dist, r_e, D_e, alpha) # update velocity values p1.velocity = p1.update_velocity2(dt, old_force, force) p2.velocity = p2.update_velocity2(dt, old_force, -force) # creates text files to contain energy and relative separation outfile_energy = open("VerletEnergy.txt", "w") outfile_separation = open("VerletSeparation.txt", "w") # for loop writing individual values of energy to file as strings for number in energy_list: outfile_energy.write(str(number)) outfile_energy.close() # for loop writing individual values of position to file as strings for number in pos_list: outfile_separation.write(str(number)) outfile_separation.close() frequency(pos_list, time_list) energy_vals(energy_list) # create two subplots fig, axs = plt.subplots(2, 1, constrained_layout=True) # plot trajectory to first subplot axs[0].plot(time_list, pos_list, '-') axs[0].set_title('Time vs. relative position') axs[0].set_xlabel('Time') axs[0].set_ylabel('Relative Position') fig.suptitle('Verlet data', fontsize=16) # plot time and energy to second subplot axs[1].plot(time_list, energy_list, '-') axs[1].set_xlabel('Time') axs[1].set_title('Time vs. energy') axs[1].set_ylabel('Total Energy') plt.show()
def main(): # Read name of input and output files from command line if len(sys.argv) != 4: print("Wrong number of arguments.") print("Usage: " + sys.argv[0] + " <input file> " + "<separation output file> " + "<energy output file>") quit() else: datafile_name = sys.argv[1] outfile_separation_name = sys.argv[2] outfile_energy_name = sys.argv[3] # Open files outfile_separation = open(outfile_separation_name, "w") outfile_energy = open(outfile_energy_name, "w") """ data file should be formated x1 y1 z1 Vx1 Vy1 Vz1 mass1 label1 x2 y2 z2 Vx2 Vy2 Vz2 mass2 label2 dt time numstep re de a """ datafile = open(datafile_name, "r") # Set up particles and simulation parameters particle1 = Particle3D.from_file(datafile) particle2 = Particle3D.from_file(datafile) line = datafile.readline() param_data = line.split() dt = float(param_data[0]) time = float(param_data[1]) numstep = int(param_data[2]) re = float(param_data[3]) de = float(param_data[4]) a = float(param_data[5]) # Write initial conditions separation = np.linalg.norm(Particle3D.separation(particle1, particle2)) energy = particle1.kinetic_energy() + particle2.kinetic_energy( ) + pe_morse(particle1, particle2, re, de, a) """ ::::::FIX FORMAT FOR VMD USE::::::: outfile_separation.write("{0:f} , {1:4.4f}\n".format(time,separation)) outfile_energy.write("{0:f} , {1:4.4f}\n".format(time,energy)) """ #Initial force (use '-force' for force on particle2) force = force_morse(particle1, particle2, re, de, a) # Initialise data lists for plotting time_list = [time] sep_list = [separation] energy_list = [energy] # Time integration loop for i in range(numstep): print('ITERATION ' + str(i + 1) + ':') print(str(particle1) + ' ' + str(particle2)) # Update positions particle1.leap_pos2nd(dt, force) particle2.leap_pos2nd(dt, -force) # Calculate separation separation = np.linalg.norm(Particle3D.separation( particle1, particle2)) # Calculate new force force_new = force_morse(particle1, particle2, re, de, a) # Update velocities with an average of current and new forces avg_force = 0.5 * (force + force_new) particle1.leap_velocity(dt, avg_force) particle2.leap_velocity(dt, -avg_force) # Update force value force = force_new # Update energy energy = particle1.kinetic_energy() + particle2.kinetic_energy( ) + pe_morse(particle1, particle2, re, de, a) # Update time time += dt * 10.1805057107594 # Output information :::::::CLEAN THIS UP::::::::: outfile_separation.write( str(2) + "\n" + "Point = " + str(i + 1) + "\n" + "s1 " + str(particle1.position[0]) + " " + str(particle1.position[1]) + " " + str(particle1.position[2]) + "\n" + "s2 " + str(particle2.position[0]) + str(particle2.position[1]) + str(particle2.position[2]) + "\n") outfile_energy.write("{0:f} , {1:4.4f}\n".format(time, energy)) # Append information to data lists time_list.append(time) sep_list.append(separation) energy_list.append(energy) # Close output files outfile_separation.close() outfile_energy.close() # Find the error in the energy energy_error = abs((max(energy_list) - min(energy_list)) / energy_list[0]) print('Error in energy = ' + str(energy_error * 100) + ' %') # Find separation peaks and calculate period, frequency and wavenumber peak_locations = [] for i in range((len(sep_list) - 1)): if sep_list[i] > sep_list[i + 1] and sep_list[i] > sep_list[i - 1]: peak_locations.append(time_list[i]) else: None if len(peak_locations) >= 2: period = (peak_locations[len(peak_locations) - 1] - peak_locations[0]) / (len(peak_locations) - 1) frequency = 1 / (period * 1.0e-15) wavenumber = 1 / ((period * 1.0e-15) * 29979245800) print('Period = ' + str(period) + 'fs | Frequency = ' + str(frequency) + ' Hz | Wavenumber = ' + str(wavenumber) + 'cm^-1') else: print( 'INSUFFICIENT TIME PERIOD. Use a smaller timestep or a larger number of steps' ) # Plots pyplot.title('Velocity Verlet: separation vs time') pyplot.xlabel('Time /fs') pyplot.ylabel('Separation /Å') pyplot.grid(which='both', axis='both') pyplot.plot(time_list, sep_list, color='purple') pyplot.show() pyplot.title('Velocity Verlet: energy vs time') pyplot.xlabel('Time /fs') pyplot.ylabel('Energy /eV') pyplot.grid(which='both', axis='both') pyplot.plot(time_list, energy_list, color='g') pyplot.show()
def force_lj(particle1,particle2,sigma): r = np.linalg.norm(Particle3D.separation(particle1,particle2))/sigma force = 48*(r*10^(-14) - 0.5*r*10^(-8))* Particle3D.separation(particle1,particle2)/sigma return force
def main(): if len(sys.argv) != 3: raise ValueError( "Incorrect number of parameters!\n usage: {0} <input_file> <output_file>" .format(sys.argv[0])) in_args = get_input_vars(str(sys.argv[1])) out_file_name = str(sys.argv[2]) out_file = open(out_file_name, 'w') particles_list = in_args[2] sim_params_list = in_args[0] part_params_list = in_args[1] numstep = int(sim_params_list[0]) time = float(sim_params_list[1]) dt = float(sim_params_list[2]) D_e = part_params_list[0] r_e = part_params_list[1] alpha = part_params_list[2] tVals = [float(time)] sepVals = [ norm(Particle3D.separation(particles_list[0], particles_list[1])) ] energVals = [total_energy(D_e, r_e, alpha, particles_list)] initEnergy = total_energy(D_e, r_e, alpha, particles_list) relEnergyError = [0] out_file.write("{0:f} {1:f}\n".format( time, norm(Particle3D.separation(particles_list[0], particles_list[1])))) #create initial forces for i in particles_list: i.prev_force = np.array([0, 0, 0]) for j in particles_list: if i != j: i.prev_force = i.prev_force + morse_force( i, j, D_e, r_e, alpha) for i in range(numstep): step_time(particles_list, part_params_list, dt) time = time + dt tVals.append(time) out_file.write("{0:f} {1:f}\n".format( time, norm(Particle3D.separation(particles_list[0], particles_list[1])))) sepVals.append( norm(Particle3D.separation(particles_list[0], particles_list[1]))) energVals.append(total_energy(D_e, r_e, alpha, particles_list)) relEnergyError.append( energy_error_step(total_energy(D_e, r_e, alpha, particles_list), initEnergy)) out_file.close() #1 in time is 10.18 fs or 1.018x10^-14s timescale = 1.018e-14 tVals = [timescale * t for t in tVals] f, axarr = plot.subplots(2) axarr[0].plot(tVals, sepVals) axarr[0].set_title("Particle Separation") #axarr[1].plot(tVals, energVals) #axarr[1].set_title("System Energy") axarr[1].plot(tVals, relEnergyError) axarr[1].set_title("Relative Energy Error") #plot.plot(tVals, sepVals) #plot.title("Particle Separation Against Time") #plot.xlabel("Time (s)") #plot.ylabel("Separation (m^-10)") plot.show()
def main(): #have the user enter which particle type they wish to simulate particle_prompt = input( "Which particle are you looking to simulate? Type O or N ") if particle_prompt == "O": p1 = Particle3D.from_file("oxygen1.txt") p2 = Particle3D.from_file("oxygen2.txt") # set system parameters numstep, time, alpha, r_e, D_e = from_file_system( "oxygen_parameters.txt") elif particle_prompt == "N": p1 = Particle3D.from_file("nitrogen1.txt") p2 = Particle3D.from_file("nitrogen2.txt") # set system parameters numstep, time, alpha, r_e, D_e = from_file_system( "nitrogen_parameters.txt") else: print("that doesn't look right!") exit() # have user specify timestep dt = input("Enter your preferred timestep: ") dt = float(dt) # finds the initial relative distance of the two particles pos1 = p1.position pos2 = p2.position initial_dist12 = Particle3D.separation(p1, p2) # finds the initial energy value energy = p1.kinetic_energy() + p2.kinetic_energy() + potential( initial_dist12, r_e, D_e, alpha) # calculate initial force value force = force_dw(initial_dist12, r_e, D_e, alpha) #initialise data lists for plotting later initial_dist12 = np.linalg.norm(initial_dist12) time_list = [time * 10.8E-15] pos_list = [initial_dist12] energy_list = [energy] #start time integration loop for i in range(numstep): # update everything we're planning to append to a list time += dt # time - appended later new_pos1 = p1.update_position1(dt) new_pos2 = p2.update_position1(dt) new_dist = np.subtract(new_pos1, new_pos2) new_dist_norm = np.linalg.norm(new_dist) energy = p1.kinetic_energy() + p2.kinetic_energy() + potential( new_dist_norm, r_e, D_e, alpha) # append energy and time data values to lists energy_list.append(energy) time_list.append(time * 10.8E-15) pos_list.append(new_dist_norm) velocity2 = p2.velocity # defining old velocity for incrementing force # update force and velocity values force = force_dw(new_dist, r_e, D_e, alpha) p1.velocity = p1.update_velocity(dt, force) p2.velocity = p2.update_velocity(dt, -force) # outwriting energy and time data to external file outfile_energy = open("symplecticEnergy.txt", "w") outfile_separation = open("symplecticSeparation.txt", "w") for number in energy_list: outfile_energy.write(str(number)) outfile_energy.close() for number in pos_list: outfile_separation.write(str(number)) outfile_separation.close() # find frequency of both measurements frequency(pos_list, time_list) energy_vals(energy_list) # set up axes # assign relative position to first subplot fig, axs = plt.subplots(2, 1, constrained_layout=True) axs[0].plot(time_list, pos_list, '-') axs[0].set_title('Symplectic: time vs. relative position') axs[0].set_xlabel('time') axs[0].set_ylabel('Relative Position') fig.suptitle('Symplectic data', fontsize=16) # assign energy to first subplot axs[1].plot(time_list, energy_list, '-') axs[1].set_xlabel('time[10.8*10^{-2}s]') axs[1].set_title('Symplectic: time vs. energy') axs[1].set_ylabel('Total Energy') plt.show()
def main(): # Read name of output file from command line if len(sys.argv) != 3: print("Wrong number of arguments.") print("Usage: " + sys.argv[0] + " <output file>") quit() else: #input files for initial position & potential constants inputfile1 = sys.argv[1] inputfile2 = sys.argv[2] # Open output files separation & total energy sep_outfile = open("separationfile.txt", "w") u_outfile = open("totalenergyfile.txt", "w") # Set up simulation parameters dt = float(input("Please determine timestep: ")) tfinal = 10 t = 0.0 tstep = int(tfinal / dt) #open position file file_handle = open(inputfile1, "r") #Open potential constants file file_pot = open(inputfile2, "r") #read line of file line = file_pot.readline() #split file into components at "," within file, should have 4 elements components = line.split(" ") #convert to floats and separate vals = [float(i) for i in components] #separate for readability into constants De = vals[0] re = vals[1] alpha = vals[2] #NOTE mass is included in the initial positions file, not in here #Create particles from initial position files p1 = Particle3D.from_file(file_handle) p2 = Particle3D.from_file(file_handle) # Write out initial conditions, separation & energy separ = np.linalg.norm(Particle3D.separation(p1, p2)) energy = p1.kinetic_energy() + p2.kinetic_energy() + mp.potenergy( p1, p2, re, De, alpha) u_outfile.write("{},{}\n".format(t, energy)) sep_outfile.write("{},{}\n".format(t, separ)) #Find pairwiseforces pairwisef1 = mp.pairwiseforces(p1, p2, re, De, alpha) pairwisef2 = -pairwisef1 # Initialise data lists for plotting later, first points time_list = [t] sep_list = [separ] energy_list = [energy] #Print out of important variables print(p1) print(p2) print(separ) # Start the time integration loop for i in range(tstep): # Update particle position p1.leap_pos2nd(dt, pairwisef1) p2.leap_pos2nd(dt, pairwisef2) #new forces prwsf1 = mp.pairwiseforces(p1, p2, re, De, alpha) prwsf2 = -prwsf1 # Update particle velocity by averaging # current and new forces p1.leap_velocity(dt, 0.5 * (pairwisef1 + prwsf1)) p2.leap_velocity(dt, 0.5 * (pairwisef2 + prwsf2)) # Re-define force value pairwisef1 = prwsf1 pairwisef2 = prwsf2 # Increase time t += dt # Output particle information #energy energy = p1.kinetic_energy() + p2.kinetic_energy() + mp.potenergy( p1, p2, re, De, alpha) u_outfile.write("{},{}\n".format(t, energy)) #separation separ = np.linalg.norm(Particle3D.separation(p1, p2)) sep_outfile.write("{}{}\n".format(t, separ)) # Append information to data lists time_list.append(t) sep_list.append(separ) energy_list.append(energy) # Post-simulation: # Close output file sep_outfile.close() u_outfile.close() # Plot particle trajectory to screen pyplot.title('Velocity Verlet: Separation vs time') pyplot.xlabel('Time') pyplot.ylabel('Separtion') pyplot.plot(time_list, sep_list) pyplot.show() # Plot particle energy to screen pyplot.title('Velocity Verlet: total energy vs time') pyplot.xlabel('Time') pyplot.ylabel('Energy') pyplot.plot(time_list, energy_list) pyplot.show()