def force_dw(Plist):
    """
    Method to return the force on a particle in a Gravitational
    potential given by: -(G*m1m2)/R**3)*vector_R
    where R is separation between two bodies and vector_R is a vector from pi to pj

    :param particlei: Particle3D instance
    :param particlej: Particle3D instance
    :param G: constant parameter
    :param vector_R: parameter vector_R from potential
    :param R: parameter R from potential
    :return: force acting on body as a Numpy array
    """
    no_parts = len(Plist)
    #pos_list = [o.position for o in Plist]
    force_dw = np.zeros((no_parts, no_parts, 3))
    
    for i,pi in enumerate(Plist):
        for j,pj in enumerate(Plist):
            vector_R = Particle3D.Vector_Separation(pi, pj)
            #vector_R = pos_list[i] - pos_list[j]
            R = np.linalg.norm(vector_R)
            m1m2 = Particle3D.mass(pi)*Particle3D.mass(pj)
            #m1m2 = Plist[pi].mass*Plist[pj].mass
            #if pi != pj:
            if R != 0:
                force_dw[i, j, :] = (((-1.48818E-34)*m1m2)/R**3)*vector_R
                #G is defined as the Gravitational constant and = -1.48818E-34 au^3/day^2/kg

            else:
                force_dw[i, j, :] = np.zeros(3)

    return force_dw
def pot_energy_dw(Plist):
    """
    Method to return potential energy of a body in
    a Gravitational potential which is given by:
    -(G*m1m2)/R)

    :param particlei: Particle3D instance
    :param particlej: Particle3D instance
    :param G: constant parameter
    :param vector_R: parameter vector_R from potential
    :param R: parameter R from potential
    :return: potential energy of body as a float
    """

    no_parts = len(Plist)
    #pos_list = [o.position for o in Plist]
    pot_energy_dw = np.zeros((no_parts, no_parts))
    
    for i,pi in enumerate(Plist):
        for j,pj in enumerate(Plist):
            vector_R = Particle3D.Vector_Separation(pi, pj)
            #vector_R = pos_list[i] - pos_list[j]
            R = np.linalg.norm(vector_R)
            m1m2 = Particle3D.mass(pi)*Particle3D.mass(pj)
            #m1m2 = Plist[pi].mass*Plist[pj].mass
            #if pi != pj:
            if R != 0:
                pot_energy_dw[i, j] = ((-(1.48818E-34)*m1m2)/R)

            else:
                pot_energy_dw[i, j] = 0

    return pot_energy_dw
示例#3
0
def force_dw(Plist):
    """
    Method to return the force on a particle in a Morse
    potential given by: -2aD_e(1-exp[-a*(R - r_e)])exp[-a*(R - re)]vector_R/R
    where R is separation between two atoms and vector_R is a vector from p1 to p2

    :param particle1: Particle3D instance
    :param particle2: Particle3D instance
    :param D_e: parameter D_e from potential
    :param r_e: parameter r_e from potential
    :param alpha: parameter alpha from potential
    :return: force acting on particle as a Numpy array
    """
    no_parts = len(Plist)
    #pos_list = [o.position for o in Plist]
    force_dw = np.zeros((no_parts, no_parts, 3))
    
    for i,pi in enumerate(Plist):
        for j,pj in enumerate(Plist):
            vector_R = Particle3D.Vector_Separation(pi, pj)
            #vector_R = pos_list[i] - pos_list[j]
            R = np.linalg.norm(vector_R)
            m1m2 = Particle3D.mass(pi)*Particle3D.mass(pj)
            #m1m2 = Plist[pi].mass*Plist[pj].mass
            #if pi != pj:
            if R != 0:
                force_dw[i, j, :] = (((-1.48818E-34)*m1m2)/R**3)*vector_R

            else:
                force_dw[i, j, :] = np.zeros(3)

    return force_dw
示例#4
0
def pot_energy_dw(Plist):
    """
    Method to return potential energy of a particle in
    a Morse potential which is given by:
    V(r1,r2) = D_e * ((1-exp[-a*(R12 - re)])**2 - 1)

    :param particle1: Particle3D instance
    :param particle2: Particle3D instance
    :param D_e: parameter D_e from potential
    :param r_e: parameter r_e from potential
    :param alpha: parameter alpha from potential
    :return: potential energy of particle as float
    """

    no_parts = len(Plist)
    #pos_list = [o.position for o in Plist]
    pot_energy_dw = np.zeros((no_parts, no_parts))
    
    for i,pi in enumerate(Plist):
        for j,pj in enumerate(Plist):
            vector_R = Particle3D.Vector_Separation(pi, pj)
            #vector_R = pos_list[i] - pos_list[j]
            R = np.linalg.norm(vector_R)
            m1m2 = Particle3D.mass(pi)*Particle3D.mass(pj)
            #m1m2 = Plist[pi].mass*Plist[pj].mass
            #if pi != pj:
            if R != 0:
                pot_energy_dw[i, j] = ((-(1.48818E-34)*m1m2)/R)

            else:
                pot_energy_dw[i, j] = 0

    return pot_energy_dw
def add_to_pos_lists(lst,d,p):

    """
    Method to update lists in d and p at different points of time in the simulation, 
    where d stores within it the list of distances between each body in lst(except the sun) and its parent body,
    and p stores within it the list of positions as numpy arrays of each body in lst.
    Note that these lists being updated are the second element of pairs in the lists of pairs, d and p, where the first is the label of the body that the information is relevant to.
    Ie d and p are lists of 2-tuples of a string and a list of floating point numbers.

    :param lst: list of the bodies as Particle3D instances
    :param d: list of pairs, in which the first pair element is the body label as a string, and the second is a list of all the scalar distances of the body from the body it is orbitting
    :param p: list of pairs, in which the first pair element is the body label as a string and the second is a list of positions of the body as a numpy array
    """   

    # find the two bodies that are being orbitted and assign them to Sun and Earth
    # done in seperate loop so that the order of particles in the input file doesn't matter

    for l in lst:
        if l.label == 'Sun': 
            Sun = l
        if l.label == 'Earth':
            Earth = l

    for l in lst:

        p[lst.index(l)][1].append(l.position) # appends position of particle l to corresponding list of its positions in p
        
        if l.label == 'Sun': # sun is not orbitting anything so can ignore distances from anything else in this case
            pass
        elif l.label == 'Moon': # ensure distance from moon to earth is appended to the correct list in d  
            d[lst.index(l)][1].append(np.linalg.norm(Particle3D.particle_separation(l,Earth)))

        else: # everything else is orbitting sun so the distance between sun and that body is appended do the correct list in d
            d[lst.index(l)][1].append(np.linalg.norm(Particle3D.particle_separation(l,Sun)))
示例#6
0
def main():

    if len(sys.argv) != 4:
        print("Wrong number of arguments.")
        print("Usage: " + sys.argv[0] + "<input file>" + " <output file>" +
              "method of time integration:either 'euler' or 'verlet'")
        quit()
    else:
        outfile_name = sys.argv[2]
        infile_name = sys.argv[1]

    # Open output file
    outfile = open(outfile_name, "w")

    #read in input file
    infile = open(infile_name, "r")

    #Get the specific constants for the particle from the input file
    #read in first line from input file
    constants = infile.readline()
    #split first line up
    tokens = constants.split(",")

    #set up initial parameters for particles
    D = tokens[0]
    alpha = tokens[2]
    r_e = tokens[1]

    dt = 0.01
    numstep = 20
    time = 0.0

    #set up the initial state of the particles

    p1 = Particle3D.file_read(infile)
    p2 = Particle3D.file_read(infile)

    #create a list of particles p1,p2
    particles = [p1, p2]

    sep_vector = p1.separation(p2)

    #calculate the magnitude of the separation between p1 and p2
    distance = np.linalg.norm(sep_vector)

    #get the total initial energy of the system
    energy = Particle3D.kinetic_energy(p1) + Particle3D.kinetic_energy(
        p2) + pot_energy_morse(distance, D, alpha, r_e)

    #write the initial time, initial separation and initial total energy to the output file
    outfile.write("{0:f} {1:f} {2:12.8f}\n".format(time, distance, energy))

    # Initialise data lists for plotting later
    time_list = []
    distance_list = []
    energy_list = []
示例#7
0
    def totalEnergy(G):
        totalEnergy=0.0
        # Cycle through every Celestial object that has been called into existence in the program so far
        for obj in Celestial.objReg:
            # Add the kinetic energy of all the bodies to the total energy
            totalEnergy = totalEnergy + P3D.kineticEnergy(obj.P3D)

            # Now go through all the pair potentials and add their contribution to the total energy
            # Note the sum below is one of the type SIGMA_{j<i} ie. there is no double counting
            for obj2 in Celestial.objReg[:Celestial.objReg.index(obj)]:
                totalEnergy = totalEnergy + P3D.potential_energy(obj.P3D, obj2.P3D, G)
        return totalEnergy
示例#8
0
    def apsis(self):
        """
        Appends the distances of each astronomical body from the Sun
        except the Moon (appends its distance from the Earth) to the corresponding list
        in the distances class variable, using the Particle3D v_sub_mag method.
        """

        for i in range(1, self.N - 1):
            self.distances[i - 1].append(
                Particle3D.v_sub_mag(self.particlelist[0],
                                     self.particlelist[i]))
        self.distances[self.N - 2].append(
            Particle3D.v_sub_mag(self.particlelist[3],
                                 self.particlelist[self.N - 1]))
示例#9
0
    def list_creator(self):
        """
        Method that fills the particlelist with the Particle3D objects created.
        Fills the labels list with the corresponding names.
        Creates the acceleration_list using the acceleration method.
        Corrects for centre of mass velocity using the com_velocity method.
        """

        for i in range(self.N):
            self.particlelist.append(Particle3D(self.file_handle))
            self.labels.append(Particle3D.label(self.particlelist[i]))

        self.acceleration_list = self.acceleration()
        self.com_velocity()
示例#10
0
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
示例#11
0
def apoperi(particle, apo, peri):
    """
    Method to update the apo and periapsis of each particle
    with respect to the sun for all particles except the moon
    which is with respect to Earth

    :param particle: Particle list
    :param apo: Existing apoapses list
    :param peri: Existing periapses list
    :return: Lists of all particles' updated apo- and periapses
    """
    #Loop for all planets except sun
    for f in range(1, len(particle) - 2):
        #All separations excluding the moon, since moon is placed innthe last positionin the poskms file
        if f != 4:
            #Calculate separation
            sep = np.linalg.norm(
                Particle3D.seperation(particle[0].position,
                                      particle[f].position))
            #Determine if new apoapsis
            if apo[f] == None:
                apo[f] = sep
            elif (sep > apo[f]):
                apo[f] = sep

            #Determine if new periapsis
            #If no periapsis exists
            if peri[f] == None:
                peri[f] = sep
            elif (sep < peri[f]):
                peri[f] = sep
        #For the moon, relative to the Earth
        else:
            #Calculate separation, assuming Earth is particle 3
            sep = np.linalg.norm(
                Particle3D.seperation(particle[3].position,
                                      particle[f].position))
            #Determine if new apoapsis
            if apo[f] == None:
                apo[f] = sep
            elif (sep > apo[f]):
                apo[f] = sep

            #Determine if new periapsis
            if peri[f] == None:
                peri[f] = sep
            elif (sep < peri[f]):
                peri[f] = sep
    return apo, peri
示例#12
0
def cm_velocity(Plist):

    cm_velocity = np.zeros((len(Plist), 3))
    for i in range(len(Plist)):
        for j in range(i+1, len(Plist)):

            v1 = Particle3D.velocity(Plist[i])
            v2 = Particle3D.velcoity(Plist[j])
            m1 = Particle3D.mass(Plist[i])
            m2 = Particle3D.mass(Plist[j])

            cm_velocity[i] += (v1*m1 + v2*m2)/(m1 + m2)
            cm_velocity[j] -= (v1 * m1 + v2 * m2) / (m1 + m2)

    return cm_velocity
示例#13
0
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)
示例#14
0
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
示例#15
0
文件: Box.py 项目: ckourris/LJ-nbody
    def get_forces(self):
        """Returns [N,3]-dim narray of forces on all particles."""

        N = len(self.particles)
        particle_forces = np.zeros((N, 3))  # Initialises force output array.

        # Use C++ version if cppenabled
        if (self.cppenabled):
            accelerate_lib.c_getforces(self.get_positions(), particle_forces,
                                       self.boxdim, self.LJ_cutoff)
            return particle_forces

        # Python calculation if cppenabled = False:
        # Iterate over all i<j, then calculate
        # force for each i, j combination
        for i in range(N):
            for j in range(i):
                # Get force of particle i on j, respecting pbc and mic.
                sep = Particle3D.pbc_sep(self.particles[i], self.particles[j],
                                         self.boxdim)
                force = LJ_Force(sep, self.LJ_cutoff)
                particle_forces[j] += force
                particle_forces[i] += -force  # Using Newtons 3rd law

        return particle_forces
示例#16
0
def rdf(particles, rho, bins, box_size):
    bins_list = np.zeros(bins)
    dist_list = []
    N = len(particles)
    for i in range(N):
        for j in range(i + 1, N):
            sep = Particle3D.sep(particles[i], particles[j])
            distances = LA.norm(mic(sep, box_size)) / (N * rho)
            dist_list.append(distances)
    #compute the size of each bin
    bin_size = (max(dist_list) - min(dist_list)) / bins
    # Compare the value of dist_list against the range of each bin
    dist_N = len(dist_list)
    for i in range(dist_N):
        for j in range(bins):
            if dist_list[i] >= j * bin_size and dist_list[i] <= (j +
                                                                 1) * bin_size:
                bins_list[j] = bins_list[j] + 1
    # normalise each of the bins
    for n in range(bins):
        r = (n * bin_size + (n + 1) * bin_size) / 2
        bins_list[n] = bins_list[n] / (4 * bin_size * math.pi * rho * (r**2))

    dist_list2 = []
    for i in range(bins):
        r = (i * bin_size + (i + 1) * bin_size) / 2
        dist_list2.append(r)

    return bins_list, dist_list2
示例#17
0
def get_input_vars(param_file):
    """
    Reads in an arbitrary number of particles and the simulation parameters from a file
    input: str param_file: file containing appropriately formatted parameters and particles
    return: 3-tuple containing a list of sim params, particle params and the particles themselves
    """
    in_file = str(param_file)
    read_file = open(in_file, 'r')
    in_file_contents = read_file.read()
    file_list = in_file_contents.split('\n')
    non_comments = []
    for i in file_list:
        if i.startswith('#') == False and i != '': #filters out comment lines in file
            non_comments.append(i)
    sim_params_list = non_comments[0:3] #first 3 non comments are sim params (numstep, dt, init_time)
    part_params_list = non_comments[3:6] #second 3 non comments are particle params (D_e, r_e, alpha)
    particles_list = []
    for i in range((len(non_comments) - 3) // 4): #4 because each particle is specified by four lines
        start = 6 + 4*(i) 
        end = 6 + 4*(i+1)
        temp_l = non_comments[start:end]
        p_lab = str(temp_l[0])
        p_mass = float(temp_l[1])
        p_pos = temp_l[2].split(', ')
        for i in range(len(p_pos)):
            p_pos[i] = float(p_pos[i])
        p_pos = np.array(p_pos)
        p_vel = temp_l[3].split(', ')
        for i in range(len(p_vel)):
            p_vel[i] = float(p_vel[i])
        p_vel = np.array(p_vel)
        particle = Particle3D(p_lab, p_mass, p_pos, p_vel)
        particles_list.append(particle)
    read_file.close()
    return (sim_params_list, part_params_list, particles_list)
示例#18
0
 def totalKineticEnergy():
     totalKE = 0.0
     # Cycle through every Celestial object that has been called into existence in the program so far
     for obj in Celestial.objReg:
         # Add the kinetic energy of all the bodies to the total energy
         totalKE = totalKE + P3D.kineticEnergy(obj.P3D)
     return totalKE
示例#19
0
def rij(particleList, boxDim):
    pDistances = []
    for i, el in enumerate(particleList):
        for j, al in enumerate(particleList):
            if i < j:
                pDistances.append(Particle3D.scalarSeparation(el, al, boxDim))
    return pDistances
示例#20
0
def MeanSD(particleList, initialPosPart, boxDim):
    y = 0.
    for i in range(len(particleList)):
        x = Particle3D.scalarSeparation(particleList[i], initialPosPart[i],
                                        boxDim)**2
        y += x
    MSD = (1. / len(particleList)) * y
    return MSD
示例#21
0
 def totalPotentialEnergy(G):
     totalPE = 0.0
     for obj in Celestial.objReg:
         # Now go through all the pair potentials and add their contribution to the total energy
         # Note the sum below is one of the type SIGMA_{j<i} ie. there is no double counting
         for obj2 in Celestial.objReg[:Celestial.objReg.index(obj)]:
             totalPE = totalPE + P3D.potential_energy(obj.P3D, obj2.P3D, G)
     return totalPE
示例#22
0
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
示例#23
0
def pNamer(PNUMBER):
    particles = []
    for i in range(PNUMBER):
        position = 0
        velocity = 0
        mass = 1
        name = i + 1
        p = Particle3D(position, velocity, mass, name)
        particles.append(p)
    return particles
def mic(p1, p2, BOXSIZE):
    #checks if the distance between two particles is greater than half the boxsize for each dimension
    #and applies the minimum image convention if they arent
    for i in range(3):
        if abs(p1.position[i] - p2.position[i]) > 0.5 * BOXSIZE:
            if (p1.position[i] - p2.position[i]) > 0.5 * BOXSIZE:
                p2.position[i] = p2.position[i] + BOXSIZE
            elif (p1.position[i] - p2.position[i]) < 0.5 * BOXSIZE:
                p2.position[i] = p2.position[i] - BOXSIZE
    return p.Seperation(p1, p2)
示例#25
0
    def globalForceUpdate(G):
        for obj in Celestial.objReg:

            force = np.array([0.0,0.0,0.0])

            for obj2 in Celestial.objReg:
                if obj!=obj2:
                    force = force + P3D.force_vector(obj.P3D, obj2.P3D, G)

            # updated force vector is stacked at the bottom row of the force_History array.
            obj.force_History = np.vstack((obj.force_History, force))
示例#26
0
def kinetic_energy_dw(Plist):


    no_parts = len(Plist)
    kinetic_energy = np.zeros(no_parts)
    for i in range(no_parts):

        kinetic_energy[i] = Particle3D.kinetic_energy(Plist[i])


    return kinetic_energy
def force_dw(particle1, particle2):
    """
    Method to return the force on a particle in a Morse
    potential given by: -2aD_e(1-exp[-a*(R - r_e)])exp[-a*(R - re)]vector_R/R
    where R is separation between two atoms and vector_R is a vector from p1 to p2

    :param particle1: Particle3D instance
    :param particle2: Particle3D instance
    :param D_e: parameter D_e from potential
    :param r_e: parameter r_e from potential
    :param alpha: parameter alpha from potential
    :return: force acting on particle as a Numpy array
    """
    force_dw = []
    while i, j <= len(Plist) and i != j:
    vector_R = Particle3D.Vector_Separation(Plist[i],Plist[j])
    R = np.linalg.norm(vector_R)
    m1m2 = Particle3D.mass(Plist[i])*Particle3D.mass(Plist[j])
    force_dw[i] = sum((((1.48818E-34)*m1m2)/R**3)*vector_R)
    return force_dw
示例#28
0
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
示例#29
0
    def trajectory(self, i):
        """
        Method that writes the required output for VMD for every n'th (argument) timestep.
        n is taken from the parameters text file.
        Argument i is a dummy variable.
        """

        if i % self.ne == 0:
            self.outfile.write(str(self.N) + "\n")
            self.outfile.write("Point = " + str(i / self.ne + 1) + "\n")
            for j in range(self.N):
                self.outfile.write(
                    str(Particle3D.__str__(self.particlelist[j])) + "\n")
示例#30
0
    def globalForceUpdate_Initialization(G):
        # Each body will be treated in turn
        for obj in Celestial.objReg:
            # Initialize a force array
            force = np.array([0.0,0.0,0.0])

            # Consider all other bodies that are different from the body of interest
            for obj2 in Celestial.objReg:
                if obj!=obj2:
                    # Do a vector sum of the individual forces acting on the body of interest due to all other bodies
                    force = force + P3D.force_vector(obj.P3D, obj2.P3D, G)

            # Update the net force acting on the body of interest
            obj.force_History = force