Exemplo n.º 1
0
    def test5(self):
        print("Testing SinkParticles accrete, one particle within two sinks' radii")
        particles = Particles(10)
        particles.radius = 42.0 | units.RSun
        particles.mass = list(range(1,11)) | units.MSun
        particles.position = [[i, 2*i, 3*i] for i in range(10)] | units.parsec
        particles.velocity = [[i, 0, -i] for i in range(10)] | units.km/units.s
        particles.age = list(range(10)) | units.Myr
        copy = particles.copy()

        sinks = SinkParticles(particles[[3, 7]], sink_radius=[4,12]|units.parsec,looping_over=self.looping_over)
        self.assertEqual(sinks.sink_radius, [4.0, 12.0] | units.parsec)
        self.assertEqual(sinks.mass, [4.0, 8.0] | units.MSun)
        self.assertEqual(sinks.position, [[3, 6, 9], [7, 14, 21]] | units.parsec)

        sinks.accrete(particles)
        self.assertEqual(len(particles), 4) # 6 particles were accreted
        self.assertEqual(sinks.mass, [12.0, 40.0] | units.MSun) # mass of sinks increased
        self.assertEqual(sinks.get_intersecting_subset_in(particles).mass,
            [12.0, 40.0] | units.MSun) # original particles' masses match
        self.assertEqual(particles.total_mass(), copy.total_mass()) # total mass is conserved
        self.assertEqual(particles.center_of_mass(), copy.center_of_mass()) # center of mass is conserved
        self.assertEqual(particles.center_of_mass_velocity(), copy.center_of_mass_velocity()) # center of mass velocity is conserved
        self.assertEqual(particles.total_momentum(), copy.total_momentum()) # momentum is conserved
        self.assertEqual(particles.total_angular_momentum()+sinks.angular_momentum.sum(axis=0), copy.total_angular_momentum()) # angular_momentum is conserved
Exemplo n.º 2
0
    class comsystem(baseclass):
        def __init__(self, *args, **kwargs):
            self.particles_accessed = True
            self._particles = Particles(0)
            baseclass.__init__(self, *args, **kwargs)

        def evolve_model(self, *args, **kwargs):
            if self.particles_accessed:
                self.com_position = self._particles.center_of_mass()
                self.com_velocity = self._particles.center_of_mass_velocity()
                com_time = self.model_time
                self._particles.synchronize_to(self.overridden().particles)
                self._particles.new_channel_to(
                    self.overridden().particles).copy_attributes(
                        ["mass", "radius"])
                self.overridden(
                ).particles.position = self._particles.position - self.com_position
                self.overridden(
                ).particles.velocity = self._particles.velocity - self.com_velocity
            self.overridden().evolve_model(*args, **kwargs)
            self.com_position += self.com_velocity * (self.model_time -
                                                      com_time)
            self.particles_accessed = False

        @property
        def particles(self):
            if not self.particles_accessed:
                self._particles = self.overridden().particles.copy()
                self._particles.position += self.com_position
                self._particles.velocity += self.com_velocity
                self.particles_accessed = True
            return self._particles
Exemplo n.º 3
0
 class comsystem(baseclass):
    def __init__(self,*args,**kwargs):
      self.particles_accessed=True
      self._particles=Particles(0)
      baseclass.__init__(self,*args,**kwargs)
    
    def evolve_model(self,*args,**kwargs):
      if self.particles_accessed:         
        self.com_position=self._particles.center_of_mass()
        self.com_velocity=self._particles.center_of_mass_velocity()
        com_time=self.model_time
        self._particles.synchronize_to(self.overridden().particles)
        self._particles.new_channel_to(self.overridden().particles).copy_attributes(["mass","radius"])
        self.overridden().particles.position=self._particles.position-self.com_position
        self.overridden().particles.velocity=self._particles.velocity-self.com_velocity
      self.overridden().evolve_model(*args,**kwargs)
      self.com_position+=self.com_velocity*(self.model_time-com_time)        
      self.particles_accessed=False
      
    @property
    def particles(self):
      if not self.particles_accessed:
        self._particles=self.overridden().particles.copy()
        self._particles.position+=self.com_position
        self._particles.velocity+=self.com_velocity
        self.particles_accessed=True
      return self._particles
Exemplo n.º 4
0
 def test10(self):
     particles = Particles(2)
     particles.position = [[1, 0, 0], [2,0,0]] | units.m
     particles.velocity = [[3, 0, 0], [4,0,0]] | units.m / units.s
     particles.mass = 1 | units.kg
     
     self.assertEquals(particles.total_mass(), 2 | units.kg)
     self.assertEquals(particles.total_momentum(), [7, 0, 0] | units.kg * units.m / units.s)
     self.assertEquals(particles.total_momentum(), particles.total_mass() * particles.center_of_mass_velocity())
     self.assertEquals(particles.total_radius(), 0.5 | units.m)
     
     convert_nbody = nbody_system.nbody_to_si(1000 | units.kg, 1e-6 | units.m)
     numpy.random.seed(123)
     field = new_plummer_sphere(10000, convert_nbody) # small clump of particles, can be regarded as point mass
     self.assertAlmostRelativeEquals(particles.potential_energy_in_field(field), -constants.G * (1500 | units.kg**2 / units.m), 5)
     self.assertAlmostEquals(particles.potential_energy_in_field(field), -1.001142 | 1e-7 * units.kg * units.m**2 / units.s**2, 5)
     
     field.position *= ((5 | units.m) / field.position.lengths()).reshape((-1, 1)) # spherical shell around particles
     potential_energy = particles.potential_energy_in_field(field)
     particles.position += [0, 1, 2] | units.m # as long as particles remain inside the shell, the potential doesn't change
     self.assertAlmostEquals(particles.potential_energy_in_field(field), potential_energy, 5)
     
     particles.mass = [1, 2] | units.kg
     self.assertAlmostRelativeEquals(particles.potential(), -constants.G * ([2, 1] | units.kg / units.m))
     self.assertAlmostRelativeEquals(particles.potential()[0], particles[0].potential())
     self.assertAlmostRelativeEquals(particles.potential()[1], particles[1].potential())
Exemplo n.º 5
0
    def test5(self):
        print "Testing SinkParticles accrete, one particle within two sinks' radii"
        particles = Particles(10)
        particles.radius = 42.0 | units.RSun
        particles.mass = range(1,11) | units.MSun
        particles.position = [[i, 2*i, 3*i] for i in range(10)] | units.parsec
        particles.velocity = [[i, 0, -i] for i in range(10)] | units.km/units.s
        particles.age = range(10) | units.Myr
        copy = particles.copy()

        sinks = SinkParticles(particles[[3, 7]], sink_radius=[4,12]|units.parsec,looping_over=self.looping_over)
        self.assertEqual(sinks.sink_radius, [4.0, 12.0] | units.parsec)
        self.assertEqual(sinks.mass, [4.0, 8.0] | units.MSun)
        self.assertEqual(sinks.position, [[3, 6, 9], [7, 14, 21]] | units.parsec)

        sinks.accrete(particles)
        self.assertEqual(len(particles), 4) # 6 particles were accreted
        self.assertEqual(sinks.mass, [12.0, 40.0] | units.MSun) # mass of sinks increased
        self.assertEqual(sinks.get_intersecting_subset_in(particles).mass,
            [12.0, 40.0] | units.MSun) # original particles' masses match
        self.assertEqual(particles.total_mass(), copy.total_mass()) # total mass is conserved
        self.assertEqual(particles.center_of_mass(), copy.center_of_mass()) # center of mass is conserved
        self.assertEqual(particles.center_of_mass_velocity(), copy.center_of_mass_velocity()) # center of mass velocity is conserved
        self.assertEqual(particles.total_momentum(), copy.total_momentum()) # momentum is conserved
        self.assertEqual(particles.total_angular_momentum()+sinks.angular_momentum.sum(axis=0), copy.total_angular_momentum()) # angular_momentum is conserved
Exemplo n.º 6
0
def make_planets(central_particle,
                 masses,
                 radii,
                 density=3 | units.g / units.cm**3,
                 phi=None,
                 theta=None,
                 eccentricity=0.0,
                 kepler=None,
                 rng=None):
    volumes = masses / density
    planet_radii = (3.0 * volumes / (4.0 * numpy.pi))**(1.0 / 3.0)
    n = len(masses)
    planet_particles = Particles(n)
    planet_particles.semimajor_axis = radii
    if eccentricity is None:
        eccentricity = numpy.abs(rng.normal(-0.00001, 0.00001, n))
    planet_particles.eccentricity = eccentricity
    planet_particles.mass = masses
    planet_particles.radius = planet_radii

    if phi is None:
        phi = numpy.radians(rng.uniform(0.0, 90.0, 1)[0])  #rotate under x
    if theta is None:
        theta0 = numpy.radians((rng.normal(-90.0, 90.0,
                                           1)[0]))  #rotate under y
        theta0 = 0
        theta_inclination = numpy.radians(rng.normal(0, 1.0, n))
        theta_inclination[0] = 0
        theta = theta0 + theta_inclination

    #psi = numpy.radians(rng.uniform(0, 180, 1))[0] #0 # numpy.radians(90) # numpy.radians(rng.uniform(0, 180, 1))[0]
    psi = numpy.radians(rng.uniform(0.0, 180.0, 1))[
        0]  #0 # numpy.radians(90) # numpy.radians(rng.uniform(0, 180, 1))[0]
    com_particle = central_particle.copy()
    for x, t in zip(iter(planet_particles), theta):
        pos, vel = posvel_from_orbital_elements(com_particle.mass + x.mass,
                                                x.semimajor_axis,
                                                x.eccentricity, kepler, rng)
        pos, vel = rotate(pos, vel, 0, 0, psi)  # theta and phi in radians
        pos, vel = rotate(pos, vel, 0, t, 0)  # theta and phi in radians
        pos, vel = rotate(pos, vel, phi, 0, 0)  # theta and phi in radians
        x.position = pos + com_particle.position
        x.velocity = vel + com_particle.velocity
        if False:
            two_body = Particles(particles=[com_particle, x])
            print "dp:", (com_particle.position -
                          two_body.center_of_mass()).as_quantity_in(units.AU)
            com_particle.mass = two_body.mass.sum()
            com_particle.position = two_body.center_of_mass()
            com_particle.velocity = two_body.center_of_mass_velocity()

    #planet_particles.position += central_particle.position
    #planet_particles.velocity += central_particle.velocity

    return planet_particles
Exemplo n.º 7
0
def merge_two_stars(primary, secondary):
    "Merge two colliding stars into one new one"
    colliders = Particles()
    colliders.add_particle(primary)
    colliders.add_particle(secondary)
    new_particle = Particle()
    new_particle.mass = colliders.mass.sum()
    new_particle.position = colliders.center_of_mass()
    new_particle.velocity = colliders.center_of_mass_velocity()

    return new_particle
Exemplo n.º 8
0
 def test1(self):
     colliders = Particles(2)
     colliders.mass = [5, 2] | units.kg
     colliders.position = [[0.0, 0.0, 0.0], [0.7, 1.4, -0.35]] | units.m
     colliders.velocity = [[0.4, -0.6, 0.0], [0.0, 0.0, -3.0]] | units.m / units.s
     self.assertAlmostEqual(colliders.center_of_mass_velocity().length(), 1.0 | units.m / units.s)
     
     merged = StickySpheres().handle_collision(colliders[0], colliders[1])
     self.assertTrue(isinstance(merged, Particles))
     self.assertEqual(merged.mass, 7 | units.kg)
     self.assertAlmostEqual(merged.position, [0.2, 0.4, -0.1] | units.m)
     self.assertAlmostEqual(merged.velocity, ([2.0, -3.0, -6.0] | units.m / units.s) / 7.0)
     self.assertAlmostEqual(merged.velocity.length(), 1.0 | units.m / units.s)
     copy = colliders.copy()
     copy.move_to_center()
     self.assertAlmostEqual(colliders.kinetic_energy(), merged.as_set().kinetic_energy() + copy.kinetic_energy())
Exemplo n.º 9
0
 def test1(self):
     colliders = Particles(2)
     colliders.mass = [5, 2] | units.kg
     colliders.position = [[0.0, 0.0, 0.0], [0.7, 1.4, -0.35]] | units.m
     colliders.velocity = [[0.4, -0.6, 0.0], [0.0, 0.0, -3.0]] | units.m / units.s
     self.assertAlmostEqual(colliders.center_of_mass_velocity().length(), 1.0 | units.m / units.s)
     
     merged = StickySpheres().handle_collision(colliders[0], colliders[1])
     self.assertTrue(isinstance(merged, Particles))
     self.assertEqual(merged.mass, 7 | units.kg)
     self.assertAlmostEqual(merged.position, [0.2, 0.4, -0.1] | units.m)
     self.assertAlmostEqual(merged.velocity, ([2.0, -3.0, -6.0] | units.m / units.s) / 7.0)
     self.assertAlmostEqual(merged.velocity.length(), 1.0 | units.m / units.s)
     copy = colliders.copy()
     copy.move_to_center()
     self.assertAlmostEqual(colliders.kinetic_energy(), merged.as_set().kinetic_energy() + copy.kinetic_energy())
Exemplo n.º 10
0
    def test10(self):
        particles = Particles(2)
        particles.position = [[1, 0, 0], [2, 0, 0]] | units.m
        particles.velocity = [[3, 0, 0], [4, 0, 0]] | units.m / units.s
        particles.mass = 1 | units.kg

        self.assertEquals(particles.total_mass(), 2 | units.kg)
        self.assertEquals(particles.total_momentum(),
                          [7, 0, 0] | units.kg * units.m / units.s)
        self.assertEquals(
            particles.total_momentum(),
            particles.total_mass() * particles.center_of_mass_velocity())
        self.assertEquals(particles.total_radius(), 0.5 | units.m)

        convert_nbody = nbody_system.nbody_to_si(1000 | units.kg,
                                                 1e-6 | units.m)
        numpy.random.seed(123)
        field = new_plummer_sphere(
            10000, convert_nbody
        )  # small clump of particles, can be regarded as point mass
        self.assertAlmostRelativeEquals(
            particles.potential_energy_in_field(field),
            -constants.G * (1500 | units.kg**2 / units.m), 5)
        self.assertAlmostEquals(
            particles.potential_energy_in_field(field),
            -1.001142 | 1e-7 * units.kg * units.m**2 / units.s**2, 5)

        field.position *= ((5 | units.m) / field.position.lengths()).reshape(
            (-1, 1))  # spherical shell around particles
        potential_energy = particles.potential_energy_in_field(field)
        particles.position += [
            0, 1, 2
        ] | units.m  # as long as particles remain inside the shell, the potential doesn't change
        self.assertAlmostEquals(particles.potential_energy_in_field(field),
                                potential_energy, 5)

        particles.mass = [1, 2] | units.kg
        self.assertAlmostRelativeEquals(
            particles.potential(),
            -constants.G * ([2, 1] | units.kg / units.m))
        self.assertAlmostRelativeEquals(particles.potential()[0],
                                        particles[0].potential())
        self.assertAlmostRelativeEquals(particles.potential()[1],
                                        particles[1].potential())
Exemplo n.º 11
0
def make_planets(central_particle, masses, radii, density = 3 | units.g/units.cm**3, phi=None, theta=None, eccentricity = 0.0, kepler = None, rng = None):
    volumes = masses / density
    planet_radii = (3.0 * volumes /  (4.0 * numpy.pi))**(1.0/3.0)
    n = len(masses)
    planet_particles = Particles(n)
    planet_particles.semimajor_axis = radii
    if eccentricity is None:
        eccentricity = numpy.abs(rng.normal(-0.00001,0.00001,n))
    planet_particles.eccentricity = eccentricity
    planet_particles.mass = masses
    planet_particles.radius = planet_radii


    if phi is None:
        phi = numpy.radians(rng.uniform(0.0, 90.0, 1)[0])#rotate under x
    if theta is None:
        theta0 = numpy.radians((rng.normal(-90.0,90.0,1)[0]))#rotate under y
        theta0 = 0
        theta_inclination = numpy.radians(rng.normal(0, 1.0, n )) 
        theta_inclination[0] = 0
        theta = theta0 + theta_inclination

    #psi = numpy.radians(rng.uniform(0, 180, 1))[0] #0 # numpy.radians(90) # numpy.radians(rng.uniform(0, 180, 1))[0]
    psi = numpy.radians(rng.uniform(0.0, 180.0, 1))[0] #0 # numpy.radians(90) # numpy.radians(rng.uniform(0, 180, 1))[0]
    com_particle = central_particle.copy()
    for x, t in zip(iter(planet_particles), theta):
        pos,vel = posvel_from_orbital_elements(com_particle.mass + x.mass, x.semimajor_axis, x.eccentricity, kepler, rng)
        pos,vel = rotate(pos, vel, 0, 0, psi) # theta and phi in radians            
        pos,vel = rotate(pos, vel, 0, t, 0) # theta and phi in radians            
        pos,vel = rotate(pos, vel, phi, 0, 0) # theta and phi in radians            
        x.position = pos + com_particle.position
        x.velocity = vel + com_particle.velocity
        if False:
            two_body = Particles(particles=[com_particle, x])
            print "dp:", (com_particle.position - two_body.center_of_mass()).as_quantity_in(units.AU)
            com_particle.mass = two_body.mass.sum()
            com_particle.position = two_body.center_of_mass()
            com_particle.velocity = two_body.center_of_mass_velocity()

    #planet_particles.position += central_particle.position
    #planet_particles.velocity += central_particle.velocity

    return planet_particles