Ejemplo n.º 1
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
Ejemplo n.º 2
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
Ejemplo 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
Ejemplo n.º 4
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
Ejemplo n.º 5
0
def sink_particles(sinks,sources,Raccretion=0.1 | units.AU):
  closest=numpy.array([-1]*len(sources))
  mind2=(numpy.array([Raccretion.number]*len(sources)) | Raccretion.unit)**2
  for i,s in enumerate(sinks):
     xs,ys,zs=s.x,s.y,s.z
     d2=(sources.x-xs)**2+(sources.y-ys)**2+(sources.z-zs)**2
     select=numpy.where( d2<mind2 )[0]
     mind2[select]=d2[select]
     closest[select]=i

  to_remove=Particles(0)
  for i,s in enumerate(sinks):
     insink=numpy.where(closest == i)[0]
     if len(insink) > 0:
       cm=s.position*s.mass
       p=s.velocity*s.mass
       insinkp=Particles(0)
       for ip in insink:
         insinkp.add_particle(sources[ip])
       s.mass+=insinkp.total_mass()
       s.position=(cm+insinkp.center_of_mass()*insinkp.total_mass())/s.mass
       s.velocity=(p+insinkp.total_momentum())/s.mass
# we lose angular momentum !    
       to_remove.add_particles(insinkp)   
       print len(insinkp),"particles accrete on star", i
  if len(to_remove)>0:
    sources.remove_particles(to_remove)
Ejemplo n.º 6
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
Ejemplo n.º 7
0
 def test2(self):
     particles = Particles(4)
     particles.mass = [1, 2, 3, 6] | kg
     particles.position = [[0, 0, 0], [3, 0, 0], [0, 4, 0], [3, 4, 0]] | m
     self.assertEqual(particles.center_of_mass(), [2, 3, 0] | m)
     pickled_particles = pickle.dumps(particles)
     unpickled_particles = pickle.loads(pickled_particles)
     self.assertAlmostRelativeEquals(unpickled_particles.mass, [1, 2, 3, 6] | kg)
     self.assertEqual(unpickled_particles.center_of_mass(), [2, 3, 0] | m)
Ejemplo n.º 8
0
 def test2(self):
     particles = Particles(4)
     particles.mass = [1, 2, 3, 6] | kg
     particles.position = [[0, 0, 0], [3, 0, 0], [0, 4, 0], [3, 4, 0]] | m
     self.assertEqual(particles.center_of_mass(), [2, 3, 0] | m)
     pickled_particles = pickle.dumps(particles)
     unpickled_particles = pickle.loads(pickled_particles)
     self.assertAlmostRelativeEquals(unpickled_particles.mass, [1, 2, 3, 6] | kg)
     self.assertEqual(unpickled_particles.center_of_mass(), [2, 3, 0] | m)
Ejemplo n.º 9
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
Ejemplo n.º 10
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
Ejemplo n.º 11
0
 def result(self):
     masses, positions, velocities, internal_energies = self.new_model()
     result = Particles(self.actual_number_of_particles)
     result.mass = nbody_system.mass.new_quantity(masses)
     result.position = nbody_system.length.new_quantity(positions)
     result.velocity = nbody_system.speed.new_quantity(velocities)
     result.u = nbody_system.specific_energy.new_quantity(internal_energies)
     
     result.position -= result.center_of_mass()
     if self.do_scale:
         scale_factor = (result.potential_energy(G=nbody_system.G)) / (-0.5 | nbody_system.energy)
         result.position *= scale_factor
     
     if not self.convert_nbody is None:
         result = ParticlesWithUnitsConverted(result, self.convert_nbody.as_converter_from_si_to_generic())
         result = result.copy()
         
     return result
Ejemplo n.º 12
0
 def result(self):
     masses, positions, velocities, internal_energies = self.new_model()
     result = Particles(self.actual_number_of_particles)
     result.mass = nbody_system.mass.new_quantity(masses)
     result.position = nbody_system.length.new_quantity(positions)
     result.velocity = nbody_system.speed.new_quantity(velocities)
     result.u = nbody_system.specific_energy.new_quantity(internal_energies)
     
     result.position -= result.center_of_mass()
     if self.do_scale:
         scale_factor = (result.potential_energy(G=nbody_system.G)) / (-0.5 | nbody_system.energy)
         result.position *= scale_factor
     
     if not self.convert_nbody is None:
         result = ParticlesWithUnitsConverted(result, self.convert_nbody.as_converter_from_si_to_generic())
         result = result.copy()
         
     return result
Ejemplo n.º 13
0
def main():
    numpy.random.seed(42)
    evo_headstart = 0.0 | units.Myr
    dt_base = 0.001 | units.Myr
    dt = dt_base
    time = 0 | units.Myr
    time_end = 8 | units.Myr
    Tmin = 22 | units.K

    gas_density = 5e3 | units.amu * units.cm**-3

    increase_vol = 2

    Ngas = increase_vol**3 * 10000
    Mgas = increase_vol**3 * 1000 | units.MSun  # Mgas = Ngas | units.MSun
    volume = Mgas / gas_density  # 4/3 * pi * r**3
    radius = (volume / (pi * 4/3))**(1/3)
    radius = increase_vol * radius  # 15 | units.parsec

    gasconverter = nbody_system.nbody_to_si(Mgas, radius)
    # gasconverter = nbody_system.nbody_to_si(1 | units.pc, 1 | units.MSun)
    # gasconverter = nbody_system.nbody_to_si(1e10 | units.cm, 1e10 | units.g)

    # NOTE: make stars first - so that it remains the same random
    # initialisation even when we change the number of gas particles
    if len(sys.argv) > 1:
        gas = read_set_from_file(sys.argv[1], "amuse")
        stars = read_set_from_file(sys.argv[2], "amuse")
        stars.position = stars.position * 3
    else:
        # stars = new_star_cluster(
        #     stellar_mass=1000 | units.MSun, effective_radius=3 | units.parsec
        # )
        # stars.velocity = stars.velocity * 2.0
        from amuse.datamodel import Particles
        Nstars = 100
        stars = Particles(Nstars)
        stars.position = [0, 0, 0] | units.pc
        stars.velocity = [0, 0, 0] | units.kms
        stars.mass = new_kroupa_mass_distribution(Nstars, mass_min=1 | units.MSun).reshape(Nstars)
        #  25 | units.MSun
        gas = molecular_cloud(targetN=Ngas, convert_nbody=gasconverter).result
        # gas.velocity = gas.velocity * 0.5
        gas.u = temperature_to_u(100 | units.K)
    # gas.x = gas.x
    # gas.y = gas.y
    # gas.z = gas.z
    # gas.h_smooth = (gas.mass / gas_density / (4/3) / pi)**(1/3)
    # print(gas.h_smooth.mean())
    # gas = read_set_from_file("gas_initial.hdf5", "amuse")
    # gas.density = gas_density
    # print(gas.h_smooth.mean())
    # exit()
    u_now = gas.u
    #print(gasconverter.to_nbody(gas[0].u))
    #print(constants.kB.value_in(units.erg * units.K**-1))
    #print((constants.kB * 6.02215076e23).value_in(units.erg * units.K**-1))

    #print(gasconverter.to_nbody(temperature_to_u(10 | units.K)))
    #tempiso = 2.d0/3.d0*ui/(Rg/gmwvar/uergg)
    # print(nbody_system.length**2 / nbody_system.time**2)
    # print(gasconverter.to_si(1 | nbody_system.length**2 / nbody_system.time**2).value_in(units.kms**2))
    # print(gasconverter.to_nbody(temperature_to_u(Tmin)))
    # Rg = (constants.kB * 6.02214076e23).value_in(units.erg * units.K**-1)
    # gmwvar = 1.2727272727
    # uergg = nbody_system.length**2 * nbody_system.time**-2
    # uergg = 6.6720409999999996E-8
    # print(Rg)
    # print(
    #     2.0/3.0*gasconverter.to_nbody(temperature_to_u(Tmin))/(Rg/gmwvar/uergg)
    # )
    # #tempiso, ui, Rg, gmwvar, uergg, udist, utime   1.7552962911187030E-018   2.5778500859241771E-003   83140000.000000000        1.2727272727272725        6.6720409999999996E-008   1.0000000000000000        3871.4231866737564
    # u = 3./2. * Tmin.value_in(units.K) * (Rg/gmwvar/uergg)
    # print(u)
    # print(
    #     2.0/3.0*u/(Rg/gmwvar/uergg)
    # )
    # print(u, Rg, gmwvar, uergg)
    # print(temperature_to_u(10 | units.K).value_in(units.kms**2))
    u = temperature_to_u(20 | units.K)
    #print(gasconverter.to_nbody(u))
    #print(u_to_temperature(u).value_in(units.K))
    # exit()
    # gas.u = u | units.kms**2
    # exit()
    
    # print(gasconverter.to_nbody(gas.u.mean()))
    # print(gasconverter.to_si(gas.u.mean()).value_in(units.kms**2))
    # exit()
    gas.du_dt = (u_now - u_now) / dt  # zero, but in the correct units

    # stars = read_set_from_file("stars.amuse", "amuse")
    # write_set_to_file(stars, 'stars.amuse', 'amuse', append_to_file=False)
    # stars.velocity *= 3
    # stars.vx += 0 | units.kms
    # stars.vy += 0 | units.kms

    M = stars.total_mass() + Mgas
    R = stars.position.lengths().mean()
    converter = nbody_system.nbody_to_si(M, R)
    # exit()
    # gas = new_plummer_gas_model(Ngas, gasconverter)
    # gas = molecular_cloud(targetN=Ngas, convert_nbody=gasconverter).result
    # gas.u = temperature_to_u(Tmin)
    # gas = read_set_from_file("gas.amuse", "amuse")
    # print(stars.mass == stars.mass.max())
    print(len(stars.mass))
    print(len(stars.mass == stars.mass.max()))
    print(stars[0])
    print(stars[stars.mass == stars.mass.max()])
    mms = stars[stars.mass == stars.mass.max()]
    print("Most massive star: %s" % mms.mass)
    print("Gas particle mass: %s" % gas[0].mass)

    evo = SeBa()
    # sph = Fi(converter, mode="openmp")
    phantomconverter = nbody_system.nbody_to_si(
        default_settings.gas_rscale,
        default_settings.gas_mscale,
    )
    sph = Phantom(phantomconverter, redirection="none")
    sph.parameters.ieos = 2
    sph.parameters.icooling = 1
    sph.parameters.alpha = 0.1
    sph.parameters.gamma = 5/3
    sph.parameters.rho_crit = 1e17 | units.amu * units.cm**-3
    sph.parameters.h_soft_sinkgas = 0.1 | units.parsec
    sph.parameters.h_soft_sinksink = 0.1 | units.parsec
    sph.parameters.h_acc = 0.1 | units.parsec
    # print(sph.parameters)

    stars_in_evo = evo.particles.add_particles(stars)
    channel_stars_evo_from_code = stars_in_evo.new_channel_to(
        stars,
        attributes=[
            "age", "radius", "mass", "luminosity", "temperature",
            "stellar_type",
        ],
    )
    channel_stars_evo_from_code.copy()

    # try:
    #     sph.parameters.timestep = dt
    # except:
    #     print("SPH code doesn't support setting the timestep")
    sph.parameters.stopping_condition_maximum_density = \
        5e-16 | units.g * units.cm**-3
    # sph.parameters.beta = 1.
    # sph.parameters.C_cour = sph.parameters.C_cour / 4
    # sph.parameters.C_force = sph.parameters.C_force / 4
    print(sph.parameters)
    stars_in_sph = stars.copy()  # sph.sink_particles.add_particles(stars)
    # stars_in_sph = sph.sink_particles.add_particles(stars)
    channel_stars_grav_to_code = stars.new_channel_to(
        # sph.sink_particles,
        # sph.dm_particles,
        stars_in_sph,
        attributes=["mass"]
    )
    channel_stars_grav_from_code = stars_in_sph.new_channel_to(
        stars,
        attributes=["x", "y", "z", "vx", "vy", "vz"],
    )
    # We don't want to accrete gas onto the stars/sinks
    stars_in_sph.radius = 0 | units.RSun
    # stars_in_sph = sph.dm_particles.add_particles(stars)
    # try:
    #     sph.parameters.isothermal_flag = True
    #     sph.parameters.integrate_entropy_flag = False
    #     sph.parameters.gamma = 1
    # except:
    #     print("SPH code doesn't support setting isothermal flag")
    gas_in_code = sph.gas_particles.add_particles(gas)
    # print(gasconverter.to_nbody(gas_in_code[0].u).value_in(nbody_system.specific_energy))
    # ui = temperature_to_u(10 | units.K)
    # Rg = constants.kB * 6.02214179e+23
    # gmwvar = (1.4/1.1) | units.g
    # uergg = 1.# | nbody_system.specific_energy
    # print("gmwvar = %s"%gasconverter.to_si(gmwvar))
    # print("Rg = %s"% gasconverter.to_si(Rg))
    # print("ui = %s"% gasconverter.to_si(ui))
    # #print("uergg = %s"% gasconverter.to_nbody(uergg))
    # print("uergg = %s" % gasconverter.to_si(1 | nbody_system.specific_energy).in_(units.cm**2 * units.s**-2))
    # print("****** %s" % ((2.0/3.0)*ui/(Rg/gmwvar/uergg)) + "*****")
    # print(gasconverter.to_nbody(Rg))
    # print((ui).in_(units.cm**2*units.s**-2))
    # #exit()
    
    # sph.evolve_model(1 | units.day)
    # write_set_to_file(sph.gas_particles, "gas_initial.hdf5", "amuse")
    # exit()

    channel_gas_to_code = gas.new_channel_to(
        gas_in_code,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "u",
        ]
    )
    # mass is never updated, and if sph is in isothermal mode u is not reliable
    channel_gas_from_code = gas_in_code.new_channel_to(
        gas,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "density", "pressure", "rho",
            "u", "h_smooth",
        ],
    )
    channel_gas_from_code.copy()  # Initialise values for density etc

    sph_particle_mass = gas[0].mass  # 0.1 | units.MSun
    r_max = 0.1 | units.parsec

    wind = stellar_wind.new_stellar_wind(
        sph_particle_mass,
        mode="heating",
        r_max=r_max,
        derive_from_evolution=True,
        tag_gas_source=True,
        # target_gas=gas,
        # timestep=dt,
    )
    stars_in_wind = wind.particles.add_particles(stars)
    channel_stars_wind_to_code = stars.new_channel_to(
        stars_in_wind,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "age", "radius", "mass",
            "luminosity", "temperature", "stellar_type",
        ],
    )
    channel_stars_wind_to_code.copy()


    # reference_mu = 2.2 | units.amu
    gasvolume = (4./3.) * numpy.pi * (
        gas.position - gas.center_of_mass()
    ).lengths().mean()**3
    rho0 = gas.total_mass() / gasvolume
    print(rho0.value_in(units.g * units.cm**-3))
    # exit()
    # cooling_flag = "thermal_model"
    # cooling = Cooling(
    cooling = SimplifiedThermalModelEvolver(
        # gas_in_code,
        gas,
        Tmin=Tmin,
        # T0=30 | units.K,
        # n0=rho0/reference_mu
    )
    cooling.model_time = sph.model_time
    # cooling_to_code = cooling.particles.new_channel_to(gas

    start_mass = (
        stars.mass.sum()
        + (gas.mass.sum() if not gas.is_empty() else 0 | units.MSun)
    )
    step = 0
    plotnr = 0
    com = stars_in_sph.center_of_mass()
    plot_hydro_and_stars(
        time,
        sph,
        stars=stars,
        sinks=None,
        L=20,
        # N=100,
        filename="phantom-coolthermalwindtestplot-%04i.png" % step,
        title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
        gasproperties=["density", "temperature"],
        # colorbar=True,
        starscale=1,
        offset_x=com[0].value_in(units.parsec),
        offset_y=com[1].value_in(units.parsec),
        thickness=5 | units.parsec,
    )

    dt = dt_base
    sph.parameters.time_step = dt
    delta_t = phantomconverter.to_si(2**(-16) | nbody_system.time)
    print("delta_t: %s" % delta_t.in_(units.day))
    # small_step = True
    small_step = False
    plot_every = 100
    subplot_factor = 10
    subplot_enabled = False
    subplot = 0
    while time < time_end:
        time += dt
        print("Gas mean u: %s" % (gas.u.mean().in_(units.erg/units.MSun)))
        print("Evolving to t=%s (%s)" % (time, gasconverter.to_nbody(time)))
        step += 1
        evo.evolve_model(evo_headstart+time)

        print(evo.particles.stellar_type.max())
        channel_stars_evo_from_code.copy()
        channel_stars_grav_to_code.copy()

        if COOLING:
            channel_gas_from_code.copy()
            cooling.evolve_for(dt/2)
            channel_gas_to_code.copy()
        print(
            "min/max temp in gas: %s %s" % (
                u_to_temperature(gas_in_code.u.min()).in_(units.K),
                u_to_temperature(gas_in_code.u.max()).in_(units.K),
            )
        )
        if small_step:
            # Take small steps until a full timestep is done.
            # Each substep is 2* as long as the last until dt is reached
            print("Doing small steps")
            # print(u_to_temperature(sph.gas_particles[0].u))
            # print(sph.gas_particles[0].u)
            old_dt = dt_base
            substeps = 2**8
            dt = old_dt / substeps
            dt_done = 0 * old_dt
            sph.parameters.time_step = dt
            print("adjusted dt to %s, base dt is %s" % (
                dt.in_(units.Myr),
                dt_base.in_(units.Myr),
                )
            )
            sph.evolve_model(sph.model_time + dt)
            dt_done += dt
            while dt_done < old_dt:
                sph.parameters.time_step = dt
                print("adjusted dt to %s, base dt is %s" % (
                    dt.in_(units.Myr),
                    dt_base.in_(units.Myr),
                    )
                )
                sph.evolve_model(sph.model_time + dt)
                dt_done += dt
                dt = min(2*dt, old_dt-dt_done)
                dt = max(dt, old_dt/substeps)
            dt = dt_base
            sph.parameters.time_step = dt
            print(
                "adjusted dt to %s" % sph.parameters.time_step.in_(units.Myr)
            )
            small_step = False
            print("Finished small steps")
            # print(u_to_temperature(sph.gas_particles[0].u))
            # print(sph.gas_particles[0].u)
            # exit()
        else:
            sph.evolve_model(time)
        channel_gas_from_code.copy()
        channel_stars_grav_from_code.copy()
        u_previous = u_now
        u_now = gas.u
        gas.du_dt = (u_now - u_previous) / dt

        channel_stars_wind_to_code.copy()
        wind.evolve_model(time)
        # channel_stars_wind_from_code.copy()
        if COOLING:
            channel_gas_from_code.copy()
            cooling.evolve_for(dt/2)
            channel_gas_to_code.copy()

        if wind.has_new_wind_particles():
            subplot_enabled = True
            wind_p = wind.create_wind_particles()
            # nearest = gas.find_closest_particle_to(wind_p.x, wind_p.y, wind_p.z)
            # wind_p.h_smooth = nearest.h_smooth
            wind_p.h_smooth = 100 | units.au
            print("u: %s / T: %s" % (wind_p.u.mean(), u_to_temperature(wind_p.u.mean())))
            # max_e = (1e44 | units.erg) / wind_p[0].mass
            # max_e = 10 * gas.u.mean()
            # max_e = (1.e48 | units.erg) / wind_p[0].mass
            # wind_p[wind_p.u > max_e].u = max_e
            # wind_p[wind_p.u > max_e].h_smooth = 0.1 | units.parsec
            # print(wind_p.position)
            print(
                "time: %s, wind energy: %s"
                % (time, (wind_p.u * wind_p.mass).sum())
            )
            print(
                "wind temperature: %s"
                % (u_to_temperature(wind_p.u))
            )
            print(
                "gas particles: %i (total mass %s)"
                % (len(wind_p), wind_p.total_mass())
            )
            # for windje in wind_p:
            #     # print(windje)
            #     source = stars[stars.key == windje.source][0]
            #     windje.position += source.position
            #     windje.velocity += source.velocity
            #     # print(source)
            #     # print(windje)
            # # exit()
            gas.add_particles(wind_p)
            gas_in_code.add_particles(wind_p)
            # for wp in wind_p:
            #     print(wp)
            print("Wind particles added")
            if True:  # wind_p.u.max() > gas_in_code.u.max():
                print("Setting dt to very short")
                small_step = True  # dt = 0.1 | units.yr
                h_min = gas.h_smooth.min()
                # delta_t = determine_short_timestep(sph, wind_p, h_min=h_min)
                # print("delta_t is set to %s" % delta_t.in_(units.yr))
        # else:
        #     small_step = True
        print(
            "time: %s sph: %s dM: %s" % (
                time.in_(units.Myr),
                sph.model_time.in_(units.Myr),
                (
                    stars.total_mass()
                    + (
                        gas.total_mass()
                        if not gas.is_empty()
                        else (0 | units.MSun)
                    )
                    - start_mass
                )
            )
        )
        # com = sph.sink_particles.center_of_mass()
        # com = sph.dm_particles.center_of_mass()
        com = stars.center_of_mass()
        print("STEP: %i step%%plot_every: %i" % (step, step % plot_every))
        if step % plot_every == 0:
            plotnr = plotnr + 1
            plot_hydro_and_stars(
                time,
                sph,
                # stars=sph.sink_particles,
                # stars=sph.dm_particles,
                stars=stars,
                sinks=None,
                L=20,
                # N=100,
                # image_size_scale=10,
                filename="phantom-coolthermalwindtestplot-%04i.png" % plotnr,  # int(step/plot_every),
                title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
                gasproperties=["density", "temperature"],
                # colorbar=True,
                starscale=1,
                offset_x=com[0].value_in(units.parsec),
                offset_y=com[1].value_in(units.parsec),
                thickness=5 | units.parsec,
            )
            # write_set_to_file(gas, "gas.amuse", "amuse", append_to_file=False)
            # write_set_to_file(stars, "stars.amuse", "amuse", append_to_file=False)
        elif (
                subplot_enabled
                and ((step % (plot_every/subplot_factor)) == 0)
        ):
            plotnr = plotnr + 1
            subplot += 1
            plot_hydro_and_stars(
                time,
                sph,
                # stars=sph.sink_particles,
                # stars=sph.dm_particles,
                stars=stars,
                sinks=None,
                L=20,
                # N=100,
                # image_size_scale=10,
                filename="phantom-coolthermalwindtestplot-%04i.png" % plotnr,  # int(step/plot_every),
                title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
                gasproperties=["density", "temperature"],
                # colorbar=True,
                starscale=1,
                offset_x=com[0].value_in(units.parsec),
                offset_y=com[1].value_in(units.parsec),
                thickness=5 | units.parsec,
            )
            if subplot % subplot_factor == 0:
                subplot_enabled = False
        print(
            "Average temperature of gas: %s" % (
                u_to_temperature(gas.u).mean().in_(units.K)
            )
        )
    return
Ejemplo n.º 14
0
def main():
    settings = ekster_settings.Settings()
    o = new_argument_parser(settings)
    gasfilename = o.gasfilename
    starsfilename = o.starsfilename
    sinksfilename = o.sinksfilename
    imagefilename = o.imagefilename
    bins = o.bins
    offset_x = o.x | units.pc
    offset_y = o.y | units.pc
    offset_z = o.z | units.pc
    w = o.w
    x_axis = o.x_axis
    y_axis = o.y_axis
    settings.plot_starscale = o.starscale
    settings.plot_width = w | units.pc
    settings.plot_image_size_scale = (
        settings.plot_image_size_scale *
        (settings.plot_bins / bins)) or settings.plot_image_size_scale

    stars = read_set_from_file(
        starsfilename,
        "amuse",
    ) if starsfilename != "" else Particles()
    sinks = read_set_from_file(
        sinksfilename,
        "amuse",
    ) if sinksfilename != "" else Particles()
    if gasfilename:
        gas = read_set_from_file(
            gasfilename,
            "amuse",
        )
        if hasattr(gas, "itype"):
            gas = gas[gas.itype == 1]
        # gas.h_smooth = gas.h
        default_temperature = 30 | units.K
        if not hasattr(gas, "u"):
            print("Setting temperature to %s" % default_temperature)
            gas.u = temperature_to_u(default_temperature)
        elif gas.u.unit is units.K:
            temp = gas.u
            del gas.u
            gas.u = temperature_to_u(temp)
    else:
        gas = Particles()

    mtot = gas.total_mass()
    com = mtot * gas.center_of_mass()
    if not sinks.is_empty():
        mtot += sinks.total_mass()
        com += sinks.total_mass() * sinks.center_of_mass()
    if not stars.is_empty():
        mtot += stars.total_mass()
        com += stars.total_mass() * stars.center_of_mass()
    com = com / mtot
    if o.use_com:
        offset_x = com[0]
        offset_y = com[1]
        offset_z = com[2]

    print(com.value_in(units.parsec))

    time = o.time | units.Myr
    if not o.timestamp_off:
        try:
            time = gas.get_timestamp()
        except AttributeError:
            print('Unable to get timestamp, set time to 0 Myr.')
            time = 0.0 | units.Myr
        if time is None:
            print('Time is None, set time to 0 Myr')
            time = 0.0 | units.Myr
    print(time.in_(units.Myr))

    converter = nbody_system.nbody_to_si(
        # 1 | units.pc, 1 | units.MSun,
        settings.gas_rscale,
        settings.gas_mscale,
    )

    gasproperties = ["density", "temperature"]
    # gasproperties = ["density"]
    for gasproperty in gasproperties:
        settings.plot_width = o.w | units.pc
        settings.plot_bins = o.bins
        figure, ax = plot_hydro_and_stars(
            time,
            stars=stars,
            sinks=sinks,
            gas=gas,
            filename=imagefilename + ".pdf",
            offset_x=offset_x,
            offset_y=offset_y,
            offset_z=offset_z,
            x_axis=x_axis,
            y_axis=y_axis,
            title="time = %06.2f %s" % (
                time.value_in(units.Myr),
                units.Myr,
            ),
            gasproperties=[gasproperty],
            # colorbar=True,  # causes weird interpolation
            # alpha_sfe=0.02,
            # stars_are_sinks=False,
            thickness=None,
            length_unit=units.parsec,
            return_figure=True,
            settings=settings,
        )
        plot_cluster_locations = False
        if plot_cluster_locations:
            from find_clusters import find_clusters
            clusters = find_clusters(
                stars,
                convert_nbody=converter,
            )
            for cluster in clusters:
                cluster_com = cluster.center_of_mass()
                cluster_x = cluster_com[0].value_in(units.parsec)
                cluster_y = cluster_com[1].value_in(units.parsec)
                lagrangian = cluster.LagrangianRadii(converter)
                lr90 = lagrangian[0][-2]
                s = lr90.value_in(units.parsec)
                # print("Circle with x, y, z: ", x, y, s)
                circle = pyplot.Circle(
                    (cluster_x, cluster_y),
                    s,
                    color='r',
                    fill=False,
                )
                ax.add_artist(circle)
        pyplot.savefig(
            gasproperty + "-" + imagefilename + ".png",
            dpi=settings.plot_dpi,
        )