Пример #1
0
    def test1(self):
        convert = nbody_system.nbody_to_si(1.e5 | units.MSun, 1.0 | units.parsec)
        eps=2.e-4 | nbody_system.length

        test_class=PhiGRAPE
        number_of_particles = 50
        stars = new_king_model(number_of_particles, W0=7, convert_nbody=convert)
        stars.radius = 0.0 | units.RSun

        cluster=test_class(convert)
        cluster.parameters.epsilon_squared = eps**2 
        cluster.particles.add_particles(stars)
        cluster.synchronize_model()

        Ep1=convert.to_nbody(cluster.potential_energy).number
        Ek1=convert.to_nbody(cluster.kinetic_energy).number

        parts=cluster.particles.copy()
        parts1=parts.select_array(lambda x: (x > 0 | units.m), ['x'] )
        parts2=parts.select_array(lambda x: (x < 0 | units.m), ['x'] )
        cluster1=sys_from_parts(test_class, parts1, convert, eps)
        cluster2=sys_from_parts(test_class, parts2, convert, eps)

        cluster1.synchronize_model()
        cluster2.synchronize_model()

        bridgesys=bridge()
        bridgesys.add_system(cluster1, (cluster2,) )
        bridgesys.add_system(cluster2, (cluster1,) )

        Ep2=convert.to_nbody(bridgesys.potential_energy).number
        Ek2=convert.to_nbody(bridgesys.kinetic_energy).number
        self.assertAlmostEqual(Ek1,Ek2,12)
        self.assertAlmostEqual(Ep1,Ep2,12)
Пример #2
0
def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R):

    galaxy_code = MilkyWay_galaxy()

    converter = nbody_system.nbody_to_si(M, R)
    cluster_code = drift_without_gravity(convert_nbody=converter)
    bodies = new_king_model(N, W0, convert_nbody=converter)
    cluster_code.particles.add_particles(bodies)
    
    stars = cluster_code.particles.copy()    
    stars.x += Rinit
    stars.vy = 0.8*galaxy_code.circular_velocity(Rinit)
    channel = stars.new_channel_to(cluster_code.particles)
    channel.copy_attributes(["x","y","z","vx","vy","vz"])

    system = bridge(verbose=False)
    system.add_system(cluster_code, (galaxy_code,))

    times = quantities.arange(0|units.Myr, tend, 100*timestep)
    for i,t in enumerate(times):
        print "Time=", t.in_(units.Myr)
        system.evolve_model(t, timestep=timestep)
          
    x = system.particles.x.value_in(units.kpc)
    y = system.particles.y.value_in(units.kpc)
    cluster_code.stop()
    return x, y
Пример #3
0
def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R):

    galaxy_code = MilkyWay_galaxy()

    converter = nbody_system.nbody_to_si(M, R)
    cluster_code = drift_without_gravity(convert_nbody=converter)
    bodies = new_king_model(N, W0, convert_nbody=converter)
    cluster_code.particles.add_particles(bodies)

    stars = cluster_code.particles.copy()
    stars.x += Rinit
    stars.vy = 0.8 * galaxy_code.circular_velocity(Rinit)
    channel = stars.new_channel_to(cluster_code.particles)
    channel.copy_attributes(["x", "y", "z", "vx", "vy", "vz"])

    system = bridge(verbose=False)
    system.add_system(cluster_code, (galaxy_code, ))

    times = quantities.arange(0 | units.Myr, tend, 100 * timestep)
    for i, t in enumerate(times):
        print("Time=", t.in_(units.Myr))
        system.evolve_model(t, timestep=timestep)

    x = system.particles.x.value_in(units.kpc)
    y = system.particles.y.value_in(units.kpc)
    cluster_code.stop()
    return x, y
Пример #4
0
 def test1(self):
     print "First test: making a King model."
     number_of_particles = 10
     particles = new_king_model(number_of_particles, 6.0)
     self.assertAlmostEqual(particles.mass.sum(), 1 | nbody_system.mass)
     self.assertAlmostEqual(particles[0].mass , 0.1 | nbody_system.mass)
     print particles
     self.assertFalse(particles[0].mass.is_vector())
Пример #5
0
 def test1(self):
     print "First test: making a King model."
     number_of_particles = 10
     particles = new_king_model(number_of_particles, 6.0)
     self.assertAlmostEqual(particles.mass.sum(), 1 | nbody_system.mass)
     self.assertAlmostEqual(particles[0].mass, 0.1 | nbody_system.mass)
     print particles
     self.assertFalse(particles[0].mass.is_vector())
Пример #6
0
 def test2(self):
     print "Testing kinetic and potential energy of a King model realisation."
     convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU)
     number_of_particles = 500
     particles = new_king_model(number_of_particles, 6.0, convert_nbody, do_scale = True)
     self.assertEquals(len(particles), number_of_particles)
     self.assertAlmostEqual(particles[0].mass, (1.0|units.MSun)/number_of_particles, 3, in_units=units.MSun)
     self.assertAlmostEqual(convert_nbody.to_nbody(particles.kinetic_energy()), 0.25 | nbody_system.energy)
     self.assertAlmostEqual(convert_nbody.to_nbody(particles.potential_energy()), -0.5 | nbody_system.energy)
Пример #7
0
 def test2(self):
     print("Testing kinetic and potential energy of a King model realisation.")
     convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU)
     number_of_particles = 500
     particles = new_king_model(number_of_particles, 6.0, convert_nbody, do_scale = True)
     self.assertEqual(len(particles), number_of_particles)
     self.assertAlmostEqual(particles[0].mass, (1.0|units.MSun)/number_of_particles, 3, in_units=units.MSun)
     self.assertAlmostEqual(convert_nbody.to_nbody(particles.kinetic_energy()), 0.25 | nbody_system.energy)
     self.assertAlmostEqual(convert_nbody.to_nbody(particles.potential_energy()), -0.5 | nbody_system.energy)
Пример #8
0
def king_cluster(num_stars, filename_cluster, w0=2.5, IBF=0.5, rand_seed=0):
    ''' Creates an open cluster according to the King Model & Kroupa IMF
        num_stars: The total number of stellar systems.
        seed: The random seed used for cluster generation.
        filename_cluster: The filename used when saving the cluster.
        w0: The King density parameter.	
        IBF: The Initial Binary Fraction.
    '''
# TODO: Have rand_seed actually do something ...

# Creates a List of Masses (in SI Units) Drawn from the Kroupa IMF
    masses_SI = new_kroupa_mass_distribution(num_stars)
# Creates the SI-NBody Converter
    converter = nbody_system.nbody_to_si(masses_SI.sum(), 1 | units.parsec)
# Creates a AMUS Particle Set Consisting of Positions (King) and Masses (Kroupa)
    stars_SI = new_king_model(num_stars, w0, convert_nbody=converter)
    stars_SI.mass = masses_SI
    print stars_SI.mass.as_quantity_in(units.MSun)
# Assigning IDs to the Stars
    stars_SI.id = np.arange(num_stars) + 1
    stars_SI.type = "star"
# Moving Stars to Virial Equilibrium
    stars_SI.move_to_center()
    if num_stars == 1:
        pass
    else:
        stars_SI.scale_to_standard(convert_nbody=converter)
    if int(IBF) != 0:
# Creating a Temporary Particle Set to Store Binaries
        binaries=Particles()
# Selects the Indices of Stars that will be converted to Binaries
        num_binaries = int(IBF*num_stars)
        select_stars_indices_for_binaries = rp.sample(xrange(0, num_stars), num_binaries)
        select_stars_indices_for_binaries.sort()
        delete_star_indices = []
# Creates a decending list of Star Indicies to make deletion easier.
        for y in xrange(0, num_binaries):
            delete_star_indices.append(select_stars_indices_for_binaries[(num_binaries-1)-y])
# Creates the Binaries and assigns IDs
        for j in xrange(0, num_binaries):
            q = select_stars_indices_for_binaries[j]
            binaries.add_particles(binary_system(stars_SI[q], converter))
        binaries.id = np.arange(num_binaries*2) + 2000000
# Deletes the Stars that were converted to Binaries
        for k in xrange(0, num_binaries):
            b = delete_star_indices[k]
            stars_SI.remove_particle(stars_SI[b])
# Merges the Binaries into to the Master Particle set
        stars_SI.add_particle(binaries)
# Assigning SOI Estimate for Interaction Radius
    if num_stars == 1:
        stars_SI.radius = 1000 | units.AU
    else:
        stars_SI.radius = util.calc_SOI(stars_SI.mass, np.var(stars_SI.velocity), G=units.constants.G)
# Returns the Cluster & Converter
    return stars_SI, converter
Пример #9
0
    def __init__(self, options_reader):

        options_reader.set_options(self)
        # self.N, self.W0, self.Mcluster, self.Rcluster, self.ncpu
        # self.gpu_enabled, self.ngpu, self.softening

        if self.use_kroupa is True:
            m = new_kroupa_mass_distribution(self.N,
                                             self.kroupa_max | units.MSun)
            tot_m = np.sum(m.value_in(units.MSun))
            self.converter = \
                nbody_system.nbody_to_si(tot_m | units.MSun,
                                         self.Rcluster | units.parsec)

            self.bodies = new_king_model(self.N,
                                         self.W0,
                                         convert_nbody=self.converter)
            self.bodies.mass = m
            self.bodies.scale_to_standard(convert_nbody=self.converter)
            self.bodies.move_to_center()
        else:
            self.converter = \
                nbody_system.nbody_to_si(self.Mcluster | units.MSun,
                                         self.Rcluster | units.parsec)

            self.bodies = new_king_model(self.N,
                                         self.W0,
                                         convert_nbody=self.converter)

        if self.gpu_enabled:
            self.code = self.nbodycode(self.converter,
                                       number_of_workers=self.ngpu,
                                       mode='gpu')
        else:
            self.code = self.nbodycode(self.converter,
                                       number_of_workers=self.ncpu)

        parameters = {'epsilon_squared': (self.softening | units.parsec)**2}

        for name, value in parameters.items():
            setattr(self.code.parameters, name, value)
        self.code.particles.add_particles(self.bodies)
Пример #10
0
def make_king_model_cluster(nbodycode, N, W0, Mcluster,
                            Rcluster, parameters = []):

    converter=nbody_system.nbody_to_si(Mcluster,Rcluster)
    bodies=new_king_model(N,W0,convert_nbody=converter)

    code=nbodycode(converter)
    for name,value in parameters:
        setattr(code.parameters, name, value)
    code.particles.add_particles(bodies)
    return code
Пример #11
0
def make_king_model_cluster(nbodycode, N, W0, Mcluster,
                            Rcluster, parameters = []):

    converter=nbody_system.nbody_to_si(Mcluster,Rcluster)
    bodies=new_king_model(N,W0,convert_nbody=converter)

    code=nbodycode(converter)
    for name,value in parameters:
        setattr(code.parameters, name, value)
    code.particles.add_particles(bodies)
    return code
Пример #12
0
 def test5(self):
     print("Testing a specific King model realisation.")
     numpy.random.seed(345672)
     convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU)
     particles = new_king_model(500, 6.0, convert_nbody)
     self.assertEqual(len(particles), 500)
     self.assertAlmostEqual(particles.total_mass(), 1.0 | units.MSun)
     self.assertAlmostEqual(particles.mass, 1.0 / 500 | units.MSun)
     self.assertAlmostEqual(particles.center_of_mass(),          [0,0,0] | units.AU)
     self.assertAlmostEqual(particles.center_of_mass_velocity(), [0,0,0] | units.km / units.s)
     self.assertAlmostEqual(particles[:3].position, [[-0.23147381,-0.19421449,-0.01165137],
         [-0.09283025,-0.06444658,-0.07922396], [-0.44189946,0.23786357,0.39115629]] | units.AU)
Пример #13
0
 def test5(self):
     print "Testing a specific King model realisation."
     numpy.random.seed(345672)
     convert_nbody = nbody_system.nbody_to_si(1.0 | units.MSun, 1.0 | units.AU)
     particles = new_king_model(500, 6.0, convert_nbody)
     self.assertEquals(len(particles), 500)
     self.assertAlmostEqual(particles.total_mass(), 1.0 | units.MSun)
     self.assertAlmostEqual(particles.mass, 1.0 / 500 | units.MSun)
     self.assertAlmostEqual(particles.center_of_mass(),          [0,0,0] | units.AU)
     self.assertAlmostEqual(particles.center_of_mass_velocity(), [0,0,0] | units.km / units.s)
     self.assertAlmostEqual(particles[:3].position, [[-0.23147381,-0.19421449,-0.01165137],
         [-0.09283025,-0.06444658,-0.07922396], [-0.44189946,0.23786357,0.39115629]] | units.AU)
Пример #14
0
def sys_from_king(base_class,
                  N,
                  W,
                  converter,
                  eps=None,
                  timestep=None,
                  usegl=False,
                  mode=None):
    parts = new_king_model(N, W0=W, convert_nbody=converter)
    parts.radius = 0. | nbody_system.length
    return sys_from_parts(base_class, parts, converter, eps, timestep, usegl,
                          mode)
Пример #15
0
def evolve_cluster_in_galaxy(N, W0, Rinit, tend, timestep, M, R):

    R_galaxy=0.1 | units.kpc
    M_galaxy=1.6e10 | units.MSun
    converter=nbody_system.nbody_to_si(M_galaxy, R_galaxy)
    galaxy=new_plummer_model(10000,convert_nbody=converter)

    print "com:", galaxy.center_of_mass().in_(units.kpc)
    print "comv:", galaxy.center_of_mass_velocity().in_(units.kms)
   
    print len(galaxy)
    galaxy_code = BHTree(converter, number_of_workers=2)
    galaxy_code.parameters.epsilon_squared = (0.01 | units.kpc)**2
    channe_to_galaxy = galaxy_code.particles.new_channel_to(galaxy)
    channe_to_galaxy.copy()
    galaxy_code.particles.add_particles(galaxy)
    inner_stars = galaxy.select(lambda r: r.length()<Rinit,["position"])
    Minner = inner_stars.mass.sum()
    print "Minner=", Minner.in_(units.MSun)
    print "Ninner=", len(inner_stars)
    vc_inner = (constants.G*Minner/Rinit).sqrt()

    converter=nbody_system.nbody_to_si(Mcluster,Rcluster)
    stars=new_king_model(N,W0,convert_nbody=converter)
    masses = new_powerlaw_mass_distribution(N, 0.1|units.MSun, 100|units.MSun, -2.35)
    stars.mass = masses
    stars.scale_to_standard(converter)
    
    stars.x += Rinit
    stars.vy += 0.8*vc_inner
    cluster_code=ph4(converter, number_of_workers=2)
    cluster_code.particles.add_particles(stars)
    channel_to_stars=cluster_code.particles.new_channel_to(stars)

    system=bridge(verbose=False)
    system.add_system(cluster_code, (galaxy_code,))
    system.add_system(galaxy_code, (cluster_code,))
    system.timestep = 0.1*timestep

    times = quantities.arange(0|units.Myr, tend, timestep)
    for i,t in enumerate(times):
        print "Time=", t.in_(units.Myr)
        channe_to_galaxy.copy()
        channel_to_stars.copy()

        inner_stars =  galaxy.select(lambda r: r.length()<Rinit,["position"])
        print "Minner=", inner_stars.mass.sum().in_(units.MSun)

        system.evolve_model(t,timestep=timestep)
    plot_galaxy_and_stars(galaxy, stars)
    galaxy_code.stop()
    cluster_code.stop()
Пример #16
0
def king_model_cluster(interface,N=1024,W0=3, Mcluster=4.e4 | units.MSun,
                                 Rcluster= .7 | units.parsec,parameters=[]):

    converter=nbody_system.nbody_to_si(Mcluster,Rcluster)

    parts=new_king_model(N,W0,convert_nbody=converter)
    parts.radius=0.0| units.parsec

    nb=interface(converter)
    for name,value in parameters:
      setattr(nb.parameters, name, value)

    nb.particles.add_particles(parts)

    return nb
Пример #17
0
def generate_cluster():
    m = new_kroupa_mass_distribution(N, kroupa_max)
    tot_m = np.sum(m)
    converter = nbody_system.nbody_to_si(tot_m, Rcluster)
    bodies = new_king_model(N, W0, convert_nbody=converter)
    bodies.mass = m
    bodies.scale_to_standard(convert_nbody=converter)
    bodies.move_to_center()
    code = ph4(converter, mode='gpu')
    parameters = {'epsilon_squared': (softening)**2}

    for name, value in parameters.items():
        setattr(code.parameters, name, value)

    code.particles.add_particles(bodies)
    return code
Пример #18
0
def king_model_cluster(interface, N=1024, W0=3, Mcluster=4.e4 | units.MSun,
                       Rcluster=.7 | units.parsec, parameters=[]):
    """
    helper function to setup an nbody king model cluster (returns code with
    particles)
    """
    converter = nbody_system.nbody_to_si(Mcluster, Rcluster)

    parts = new_king_model(N, W0, convert_nbody=converter)
    parts.radius = 0.0 | units.parsec

    nb = interface(converter)
    for name, value in parameters:
        setattr(nb.parameters, name, value)

    nb.particles.add_particles(parts)

    return nb
Пример #19
0
    def __init__(self,
                 name,
                 Mtot=(1e15 | units.MSun),
                 Rvir=(500 | units.kpc),
                 Ndm=1e2,
                 Ngas=1e3):
        self.name = name
        self.converter = nbody_system.nbody_to_si(Mtot, Rvir)
        self.Mtot = Mtot
        self.Rvir = Rvir
        self.Ndm = int(Ndm)
        self.Ngas = int(Ngas)

        # Set up numerical smoothing fractions.
        self.dm_smoothing_fraction = 0.001
        self.gas_smoothing_fraction = 0.05
        self.dm_epsilon = self.dm_smoothing_fraction * self.Rvir
        self.gas_epsilon = self.gas_smoothing_fraction * self.Rvir

        # Set up gas and dark matter fractions and gas/dm mass.
        self.gas_fraction = 0.1
        self.dm_fraction = 1.0 - self.gas_fraction
        self.dm_mass = self.dm_fraction * self.Mtot
        self.gas_mass = self.gas_fraction * self.Mtot

        # Set up King Sphere for the gas
        # Second parameter W0: Dimension-less depth of the King potential
        W0 = 3
        self.gas = new_king_model(self.Ngas, W0, convert_nbody=self.converter)
        self.gas.h_smooth = self.gas_epsilon
        self.gas.mass = (1.0 / self.Ngas) * self.gas_mass
        self.gas.move_to_center()

        # Set up NFW profile for the Dark Matter (TODO: now plummer sphere!)
        self.dm = new_plummer_model(self.Ndm, convert_nbody=self.converter)
        self.dm.radius = self.dm_epsilon
        self.dm.mass = (1.0 / self.Ndm) * self.dm_mass
        self.dm.move_to_center()

        print "Succesfuly created a Sub Cluster with the following properties"
        print self

        print self.gas
Пример #20
0
    def test1(self):
        convert = nbody_system.nbody_to_si(1.e5 | units.MSun,
                                           1.0 | units.parsec)
        eps = 2.e-4 | nbody_system.length

        test_class = PhiGRAPE
        number_of_particles = 50
        stars = new_king_model(number_of_particles,
                               W0=7,
                               convert_nbody=convert)
        stars.radius = 0.0 | units.RSun

        cluster = test_class(convert)
        cluster.parameters.epsilon_squared = eps**2
        cluster.particles.add_particles(stars)
        cluster.synchronize_model()

        Ep1 = convert.to_nbody(cluster.potential_energy).number
        Ek1 = convert.to_nbody(cluster.kinetic_energy).number

        parts = cluster.particles.copy()
        parts1 = parts.select_array(lambda x: (x > 0 | units.m), ['x'])
        parts2 = parts.select_array(lambda x: (x < 0 | units.m), ['x'])
        cluster1 = sys_from_parts(test_class, parts1, convert, eps)
        cluster2 = sys_from_parts(test_class, parts2, convert, eps)

        cluster1.synchronize_model()
        cluster2.synchronize_model()

        bridgesys = bridge()
        bridgesys.add_system(cluster1, (cluster2, ))
        bridgesys.add_system(cluster2, (cluster1, ))

        Ep2 = convert.to_nbody(bridgesys.potential_energy).number
        Ek2 = convert.to_nbody(bridgesys.kinetic_energy).number
        self.assertAlmostEqual(Ek1, Ek2, 12)
        self.assertAlmostEqual(Ep1, Ep2, 12)
Пример #21
0
 def slowtest3(self):
     print "King models with varying King dimensionless depth W0."
     number_of_particles = 10
     for w_0 in [1.0, 6.0, 11.0, 16.0]:
         particles = new_king_model(number_of_particles, W0=w_0)
         self.assertEquals(len(particles), number_of_particles)
from matplotlib import pyplot
from amuse.ic.kingmodel import new_king_model

if __name__ in ('__main__', '__plot__'):

    # set up parameters:
    N = 100
    W0 = 3
    Rinit = 50. | units.parsec
    timestep = 0.01 | units.Myr
    Mcluster = 4.e4 | units.MSun
    Rcluster = 0.7 | units.parsec
    converter = nbody_system.nbody_to_si(Mcluster,Rcluster)

    # create a globular cluster model
    particles = new_king_model(N, W0, convert_nbody=converter)
    particles.radius = 0.0| units.parsec
    cluster = PhiGRAPE(converter, parameters=[("epsilon_squared", (0.01 | units.parsec)**2)])

    # create the external potential of the Galaxy
    galaxy = Agama(converter, type="Dehnen", gamma=1.8, \
        rscale=1000.| units.parsec, mass=1.6e10 | units.MSun, channel_type='sockets')

    # shift the cluster to an orbit around Galactic center
    acc,_,_ = galaxy.get_gravity_at_point(0|units.kpc, Rinit, 0|units.kpc, 0|units.kpc)
    vcirc = (-acc * Rinit)**0.5
    print "Vcirc=", vcirc.value_in(units.kms), "km/s"
    particles.x  += Rinit
    particles.vy += vcirc
    cluster.particles.add_particles(particles)
Пример #23
0
def new_cluster(number_of_particles, W0, converter):
    particles = new_king_model(N, W0, convert_nbody=converter)
    particles.radius = 0.0 | units.parsec
    return particles
Пример #24
0
def sys_from_king(base_class, N, W, converter, eps=None,
                  timestep=None, usegl=False, mode=None):
    parts = new_king_model(N, W0=W, convert_nbody=converter)
    parts.radius = 0. | nbody_system.length
    return sys_from_parts(
            base_class, parts, converter, eps, timestep, usegl, mode)
Пример #25
0
 def slowtest3(self):
     print "King models with varying King dimensionless depth W0."
     number_of_particles = 10
     for w_0 in [1.0, 6.0, 11.0, 16.0]:
         particles = new_king_model(number_of_particles, W0 = w_0)
         self.assertEquals(len(particles), number_of_particles)
Пример #26
0
def new_cluster(number_of_particles, W0, converter):

    particles = new_king_model(N, W0, convert_nbody=converter)
    particles.radius = 0.0 | units.parsec
    return particles
Пример #27
0
def king_cluster_v2(num_stars, **kwargs):
    ''' Creates an open cluster according to the King Model & Kroupa IMF
        num_stars: The total number of stellar systems.
        w0: The King density parameter.
        vradius: The virial radius of the cluster.
        seed: The random seed used for cluster generation.
        do_binaries: Turn on/off binary creation.
        binary_recursions: The number of times a star is tested to be a binary.
        split_binaries: Turn on/off splitting Binary CoM into individual Companions.
    '''
    # Check Keyword Arguments
    w0 = kwargs.get("w0", 2.5)
    virial_radius = kwargs.get("vradius", 2 | units.parsec)
    rand_seed = kwargs.get("seed", 7)
    do_binaries = kwargs.get("do_binaries", True)
    binary_recursions = kwargs.get("binary_recursions", 1)
    split_binaries = kwargs.get("split_binaries", True)

    # Check if rand_seed is a integer or not. Convert it if it isn't.
    if not type(rand_seed) == type(1):
        rand_seed = util.new_seed_from_string(rand_seed)

# Apply the Seed for the Cluster
    rs = RandomState(MT19937(SeedSequence(rand_seed)))
    np.random.seed(rand_seed)
    random.seed(rand_seed)

    min_stellar_mass = 100 | units.MJupiter
    max_stellar_mass = 10 | units.MSun
    # Creates a List of Primary Masses (in SI Units) Drawn from the Kroupa IMF
    Masses_SI = util.new_truncated_kroupa(num_stars)

    # If Primordial Binaries are Desired, Start the Conversion Process
    if do_binaries:
        # Find Sutable CoM Objects to Turn into Binaries, Update the System
        # Mass, and record the CoM's Index to Remove it Later.
        Masses_SI, ids_to_become_binaries = find_possible_binaries_v2(
            Masses_SI, binary_recursions=binary_recursions)

# Creates the SI-to-NBody Converter
    converter = nbody_system.nbody_to_si(Masses_SI.sum(), virial_radius)

    # Creates a AMUS Particle Set Consisting of Positions (King) and Masses (Kroupa)
    stars_SI = new_king_model(num_stars, w0, convert_nbody=converter)
    stars_SI.mass = Masses_SI

    # Assigning Type of System ('star' or 'primordial binary')
    stars_SI.type = "star"
    if do_binaries:
        for com_index in ids_to_become_binaries:
            stars_SI[com_index].type = "primordial binary"

# Shifts Cluster's CoM to the Origin Before Scaling to Virial Equilibrium
    stars_SI.move_to_center()
    if num_stars == 1:
        pass
    else:
        stars_SI.scale_to_standard(convert_nbody=converter)

# Assigning SOI Estimate for Interaction Radius
    if num_stars == 1:
        stars_SI.radius = 2000 * stars_SI.mass / (1.0 | units.MSun) | units.AU
    else:
        # Temporary Solution
        stars_SI.radius = 2000 * stars_SI.mass / (1.0 | units.MSun) | units.AU
        # Need to think of a better way to calculate the SOI
        # stars_SI.radius = 100*util.calc_SOI(stars_SI.mass, np.var(stars_SI.velocity), G=units.constants.G)

# If Requested, Split Binary Systems into Seperate Particles
    if do_binaries:
        # Define the Binary Set
        binaries = Particles()
        singles_in_binaries = Particles()
        com_to_remove = Particles()

        # Create a Kepler Worker to Ensure the Binaries are Approaching
        BinaryConverter = nbody_system.nbody_to_si(
            2 * np.mean(stars_SI.mass), 2 * np.mean(stars_SI.radius))
        kep = Kepler(unit_converter=BinaryConverter, redirection='none')
        # Split the Binary into its Companions & Store in Seperate Sets
        for com_index in ids_to_become_binaries:
            stars_SI[com_index].id = com_index
            binary_particle, singles_in_binary = binary_system_v2(
                stars_SI[com_index], stars_SI, kepler_worker=kep)
            binaries.add_particle(binary_particle)
            singles_in_binaries.add_particle(singles_in_binary)
            com_to_remove.add_particle(stars_SI[com_index])

        # If Desired, Remove the CoM and Replace it with the Single Companions.
        # Note: Default is to do this until we get multiples.py and encounters.py
        #       to match functionality exactly plus Kira.py features.
        if split_binaries:
            stars_SI.remove_particles(com_to_remove)
            stars_SI.add_particles(singles_in_binaries)

# Set Particle Ids for Easy Referencing
    stars_SI.id = np.arange(len(stars_SI)) + 1

    # Final Radius Setting (Ensuring that the Interaction Distance is not Small)
    min_stellar_radius = 1000 | units.AU
    for star in stars_SI:
        if star.radius < min_stellar_radius:
            star.radius = min_stellar_radius


# Return the Desired Particle Sets and Required Converter
    if do_binaries:
        kep.stop()
        return stars_SI, converter, binaries, singles_in_binaries
    else:
        return stars_SI, converter
Пример #28
0
def king_cluster(num_stars, **kwargs):
    ''' Creates an open cluster according to the King Model & Kroupa IMF
        num_stars: The total number of stellar systems.
        w0: The King density parameter.
        seed: The random seed used for cluster generation.
        num_binaries: The number of binary systems desired.
    '''
# Check Keyword Arguments
    w0 = kwargs.get("w0", 2.5)
    #rand_seed = int(str(kwargs.get("seed", 7)).encode('hex'), 32)
    rand_seed = util.new_seed_from_string(kwargs.get("seed", 7))
    num_binaries = kwargs.get("num_binaries", int(num_stars*0.25))

# Apply the Seed for the Cluster
    np.random.seed(rand_seed)
    #rp.seed(rand_seed)
# Creates a List of Primary Masses (in SI Units) Drawn from the Kroupa IMF
    SMasses_SI = new_kroupa_mass_distribution(num_stars, mass_max = 10 | units.MSun)
# Creates a List of Binary Companion Masses (in SI_Units) Drawn from the Kroupa IMF
    BMasses_SI = new_kroupa_mass_distribution(num_binaries, mass_max = 10 | units.MSun)
# Creates the SI-NBody Converter
    converter = nbody_system.nbody_to_si(SMasses_SI.sum()+BMasses_SI.sum(), 1 | units.parsec)
# Creates a AMUS Particle Set Consisting of Positions (King) and Masses (Kroupa)
    stars_SI = new_king_model(num_stars, w0, convert_nbody=converter)
    stars_SI.mass = SMasses_SI
    #print stars_SI.mass.as_quantity_in(units.MSun)
# Assigning IDs to the Stars
    stars_SI.id = np.arange(num_stars) + 1
    stars_SI.type = "star"

# If Requested, Search for Possible Binary Systems
    if int(num_binaries) != 0:
    # Search for all Stars Able to Become Binary Systems & Update stars_SI Masses for Correct Scaling
        stars_SI, stars_to_become_binaries = find_possible_binaries(stars_SI, num_binaries, BMasses_SI)
    # Update the Number of Binaries (Safety Check)
        num_binaries = len(stars_to_become_binaries)

# Moving Stars to Virial Equilibrium
    stars_SI.move_to_center()
    if num_stars == 1:
        pass
    else:
        stars_SI.scale_to_standard(convert_nbody=converter)

# Assigning SOI Estimate for Interaction Radius
    if num_stars == 1:
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU
    else:
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU # Temporary Solution
        # Need to think of a better way to calculate the SOI
        # stars_SI.radius = 100*util.calc_SOI(stars_SI.mass, np.var(stars_SI.velocity), G=units.constants.G)

# If Requested, Creates Binary Systems
    if int(num_binaries) != 0:
    # Loop the Creation of Binary Systems
        binaries=Particles()
        for j in xrange(0, num_binaries):
            binaries.add_particles(binary_system(stars_to_become_binaries[j]))
    # Adjust the ID for each Binary Component Particle
        binaries.id = np.arange(num_binaries*2) + num_stars + 1
    # Remove Old Place-Holder Particles
        stars_SI.remove_particles(stars_to_become_binaries)
    # Merge the Two Sets
        stars_SI.add_particles(binaries)
    # Fix the ID Problem
        stars_SI.id = np.arange(len(stars_SI.id)) + 1

# Final Radius Setting (Ensuring that the Interaction Distance is not Small)
    min_stellar_radius = 1000 | units.AU
    for star in stars_SI:
        if star.radius < min_stellar_radius:
            star.radius = min_stellar_radius

# Returns the Cluster & Converter
    return stars_SI, converter
Пример #29
0
def king_cluster_v2(num_stars, **kwargs):
    ''' Creates an open cluster according to the King Model & Kroupa IMF
        num_stars: The total number of stellar systems.
        w0: The King density parameter.
        vradius: The virial radius of the cluster.
        seed: The random seed used for cluster generation.
        do_binaries: Turn on/off binary creation.
        binary_recursions: The number of times a star is tested to be a binary.
        split_binaries: Turn on/off splitting Binary CoM into individual Companions.
    '''
# Check Keyword Arguments
    w0 = kwargs.get("w0", 2.5)
    virial_radius = kwargs.get("vradius", 2 | units.parsec)
    rand_seed = util.new_seed_from_string(kwargs.get("seed", 7))
    do_binaries = kwargs.get("do_binaries", True)
    binary_recursions = kwargs.get("binary_recursions", 1)
    split_binaries = kwargs.get("split_binaries", True)

# Apply the Seed for the Cluster
    np.random.seed(rand_seed)

    min_stellar_mass = 100 | units.MJupiter
    max_stellar_mass = 10 | units.MSun
# Creates a List of Primary Masses (in SI Units) Drawn from the Kroupa IMF
    Masses_SI = util.new_truncated_kroupa(num_stars)

# If Primordial Binaries are Desired, Start the Conversion Process
    if do_binaries:
        # Find Sutable CoM Objects to Turn into Binaries, Update the System
        # Mass, and record the CoM's Index to Remove it Later.
        Masses_SI, ids_to_become_binaries = find_possible_binaries_v2(Masses_SI,
                                                binary_recursions = binary_recursions)

# Creates the SI-to-NBody Converter
    converter = nbody_system.nbody_to_si(Masses_SI.sum(), virial_radius)

# Creates a AMUS Particle Set Consisting of Positions (King) and Masses (Kroupa)
    stars_SI = new_king_model(num_stars, w0, convert_nbody=converter)
    stars_SI.mass = Masses_SI

# Assigning Type of System ('star' or 'primordial binary')
    stars_SI.type = "star"
    if do_binaries:
        for com_index in ids_to_become_binaries:
            stars_SI[com_index].type = "primordial binary"

# Shifts Cluster's CoM to the Origin Before Scaling to Virial Equilibrium
    stars_SI.move_to_center()
    if num_stars == 1:
        pass
    else:
        stars_SI.scale_to_standard(convert_nbody=converter)

# Assigning SOI Estimate for Interaction Radius
    if num_stars == 1:
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU
    else:
        # Temporary Solution
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU
        # Need to think of a better way to calculate the SOI
        # stars_SI.radius = 100*util.calc_SOI(stars_SI.mass, np.var(stars_SI.velocity), G=units.constants.G)

# If Requested, Split Binary Systems into Seperate Particles
    if do_binaries:
        # Define the Binary Set
        binaries = Particles()
        singles_in_binaries = Particles()
        com_to_remove = Particles()

        # Split the Binary into its Companions & Store in Seperate Sets
        for com_index in ids_to_become_binaries:
            stars_SI[com_index].id = com_index
            binary_particle, singles_in_binary = binary_system_v2(stars_SI[com_index])
            binaries.add_particle(binary_particle)
            singles_in_binaries.add_particle(singles_in_binary)
            com_to_remove.add_particle(stars_SI[com_index])

        # If Desired, Remove the CoM and Replace it with the Single Companions.
        # Note: Default is to do this until we get multiples.py and encounters.py
        #       to match functionality exactly plus Kira.py features.
        if split_binaries:
            stars_SI.remove_particles(com_to_remove)
            stars_SI.add_particles(singles_in_binaries)

# Set Particle Ids for Easy Referencing
    stars_SI.id = np.arange(len(stars_SI)) + 1

# Final Radius Setting (Ensuring that the Interaction Distance is not Small)
    min_stellar_radius = 1000 | units.AU
    for star in stars_SI:
        if star.radius < min_stellar_radius:
            star.radius = min_stellar_radius

# Return the Desired Particle Sets and Required Converter
    if do_binaries:
        return stars_SI, converter, binaries, singles_in_binaries
    else:
        return stars_SI, converter
Пример #30
0
def king_cluster(num_stars, **kwargs):
    ''' Creates an open cluster according to the King Model & Kroupa IMF
        num_stars: The total number of stellar systems.
        w0: The King density parameter.
        seed: The random seed used for cluster generation.
        num_binaries: The number of binary systems desired.
    '''
# Check Keyword Arguments
    w0 = kwargs.get("w0", 2.5)
    #rand_seed = int(str(kwargs.get("seed", 7)).encode('hex'), 32)
    rand_seed = util.new_seed_from_string(kwargs.get("seed", 7))
    num_binaries = kwargs.get("num_binaries", int(num_stars*0.25))

# Apply the Seed for the Cluster
    np.random.seed(rand_seed)
    #rp.seed(rand_seed)
# Creates a List of Primary Masses (in SI Units) Drawn from the Kroupa IMF
    SMasses_SI = new_kroupa_mass_distribution(num_stars, mass_max = 10 | units.MSun)
# Creates a List of Binary Companion Masses (in SI_Units) Drawn from the Kroupa IMF
    BMasses_SI = new_kroupa_mass_distribution(num_binaries, mass_max = 10 | units.MSun)
# Creates the SI-NBody Converter
    converter = nbody_system.nbody_to_si(SMasses_SI.sum()+BMasses_SI.sum(), 1 | units.parsec)
# Creates a AMUS Particle Set Consisting of Positions (King) and Masses (Kroupa)
    stars_SI = new_king_model(num_stars, w0, convert_nbody=converter)
    stars_SI.mass = SMasses_SI
    #print stars_SI.mass.as_quantity_in(units.MSun)
# Assigning IDs to the Stars
    stars_SI.id = np.arange(num_stars) + 1
    stars_SI.type = "star"

# If Requested, Search for Possible Binary Systems
    if int(num_binaries) != 0:
    # Search for all Stars Able to Become Binary Systems & Update stars_SI Masses for Correct Scaling
        stars_SI, stars_to_become_binaries = find_possible_binaries(stars_SI, num_binaries, BMasses_SI)
    # Update the Number of Binaries (Safety Check)
        num_binaries = len(stars_to_become_binaries)

# Moving Stars to Virial Equilibrium
    stars_SI.move_to_center()
    if num_stars == 1:
        pass
    else:
        stars_SI.scale_to_standard(convert_nbody=converter)

# Assigning SOI Estimate for Interaction Radius
    if num_stars == 1:
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU
    else:
        stars_SI.radius = 2000*stars_SI.mass/(1.0 | units.MSun) | units.AU # Temporary Solution
        # Need to think of a better way to calculate the SOI
        # stars_SI.radius = 100*util.calc_SOI(stars_SI.mass, np.var(stars_SI.velocity), G=units.constants.G)

# If Requested, Creates Binary Systems
    if int(num_binaries) != 0:
    # Loop the Creation of Binary Systems
        binaries=Particles()
        for j in xrange(0, num_binaries):
            binaries.add_particles(binary_system(stars_to_become_binaries[j]))
    # Adjust the ID for each Binary Component Particle
        binaries.id = np.arange(num_binaries*2) + num_stars + 1
    # Remove Old Place-Holder Particles
        stars_SI.remove_particles(stars_to_become_binaries)
    # Merge the Two Sets
        stars_SI.add_particles(binaries)
    # Fix the ID Problem
        stars_SI.id = np.arange(len(stars_SI.id)) + 1

# Final Radius Setting (Ensuring that the Interaction Distance is not Small)
    min_stellar_radius = 1000 | units.AU
    for star in stars_SI:
        if star.radius < min_stellar_radius:
            star.radius = min_stellar_radius

# Returns the Cluster & Converter
    return stars_SI, converter
Пример #31
0
def make_king_model_cluster(r_init,
                            phi_init,
                            z_init,
                            vr_init,
                            vphi_init,
                            vz_init,
                            W0,
                            Mcluster,
                            star_masses,
                            radius,
                            Mgalaxy,
                            Rgalaxy,
                            code_name,
                            parameters=[]):
    '''
    sets up a cluster with mass M and radius R
    which nbodycode would you like to use?
    '''

    converter = nbody_system.nbody_to_si(star_masses.sum(),
                                         radius | units.parsec)
    bodies = new_king_model(len(star_masses), W0, convert_nbody=converter)
    bodies.mass = star_masses
    '''
    takes in R, Z value
    returns VR, Vphi, VZ values
    should get appropriate 6D initial phase space conditions
    '''

    #convert from galpy/cylindrical to AMUSE/Cartesian units
    x_init = r_init * np.cos(phi_init) | units.kpc
    y_init = r_init * np.sin(phi_init) | units.kpc
    z_init = z_init | units.kpc

    #vphi = R \dot{\phi}? assuming yes for now
    vx_init = (vr_init * np.cos(phi_init) -
               vphi_init * np.sin(phi_init)) | units.kms
    vy_init = (vr_init * np.sin(phi_init) +
               vphi_init * np.cos(phi_init)) | units.kms
    vz_init = vz_init | units.kms

    pos_vec, vel_vec = (x_init, y_init, z_init), (vx_init, vy_init, vz_init)

    #initializing phase space coordinates
    bodies.x += x_init
    bodies.y += y_init
    bodies.z += z_init
    bodies.vx += vx_init
    bodies.vy += vy_init
    bodies.vz += vz_init

    #sub_worker in Nemesis
    if code_name == 'Nbody':

        code = Hermite(converter)
        code.particles.add_particles(bodies)
        code.commit_particles()

    if code_name == 'tree':

        code = BHTree(converter)
        code.particles.add_particles(bodies)
        code.commit_particles()

    return bodies, code
Пример #32
0
def Create_King_Cluster(number_of_stars, number_of_binaries, w, write_file=True, cluster_name=None):
    """
    This is a function created to create a King's Model Cluster and write the HDF5 File if requested.
    The Function Returns: The Set of Stars, AMUSE Nbody Converter, Cluster Name, & King's Model W0 Value
    """
    # Creates a List of Masses Drawn from the Salpeter Mass Distribution & Prints the Total Mass
    salpeter_masses = new_salpeter_mass_distribution(number_of_stars, mass_max = (15 | units.MSun))
    total_mass = salpeter_masses.sum()
    print "Total Mass of the Cluster:", total_mass.value_in(units.MSun), "Solar Masses"

    # This converter is set so that [1 mass = Cluster's Total Mass] & [1 length = 1 parsec].
    converter = nbody_system.nbody_to_si(total_mass, 1 | units.parsec)

    # Creates a AMUSE Particle Set Consisting of Stars from the King Model & Sets Their Masses
    stars = new_king_model(number_of_stars, w)
    stars.mass = converter.to_nbody(salpeter_masses)
    #stars.radius = stars.mass.number | nbody_system.length
    stars.radius = converter.to_nbody(1000 | units.AU)
    stars.id = np.arange(number_of_stars) + 1

    # Moving Stars to Virial Equilibrium
    stars.move_to_center()
    if number_of_stars == 1:
        pass
    else:
        stars.scale_to_standard()
    
    # Creates the AMUSE Paricle set for the Binaries
    binaries = Particles()
	
	# Selects the Indices of Stars that will be converted to Binaries
    select_stars_indices_for_binaries = random.sample(xrange(0, number_of_stars), number_of_binaries)
    select_stars_indices_for_binaries.sort()
    delete_star_indices = []
	
	# Creates a decending list of Star Indicies to make deletion easier.
    for y in xrange(0, number_of_binaries):
		delete_star_indices.append(select_stars_indices_for_binaries[(number_of_binaries-1)-y])

	# Creates the Binaries and assigns IDs
    for j in xrange(0, number_of_binaries):
		q = select_stars_indices_for_binaries[j]
		binaries.add_particles(makeBinary(stars[q], converter))
    binaries.id = np.arange(number_of_binaries*2) + 2000000
    
    # Deletes the Stars that were converted to Binaries
    for k in xrange(0, number_of_binaries):
		b = delete_star_indices[k]
		stars.remove_particle(stars[b])
	
	# Adds in the Binaries to the Master Particle set
    stars.add_particle(binaries)
		
    # Assigns a Name to the Cluster if Not Provided
    if cluster_name == None:
        cluster_name = "OC"+tp.strftime("%y%m%d-%H%M%S", tp.gmtime())
    
    # Optionally Write the Cluster to a File
    if write_file:
        file_format = "hdf5"
        # Generates a File Name Given the Cluster Name
        file_name = "kingcluster_%s_w%.2f_N%i_M%.6f.%s" %(cluster_name, w, number_of_stars, total_mass.value_in(units.MSun), file_format)
        # Sets the File Path and Writes the Particle Set to a hdf5 File
        file_dir = os.getcwd()+"/Clusters"
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
        file_path = file_dir+"/"+file_name
        write_set_to_file(stars, file_path, format=file_format, close_file=True)
    else:
        pass
    
    # Return the Particle Set of Stars and the Unit Converter
    return stars, converter, cluster_name, w
Пример #33
0
def new_star_cluster(
        stellar_mass=False,
        initial_mass_function="salpeter",
        upper_mass_limit=125. | units.MSun,
        lower_mass_limit=0.1 | units.MSun,
        number_of_stars=1024,
        effective_radius=3.0 | units.parsec,
        star_distribution="plummer",
        star_distribution_w0=7.0,
        star_distribution_fd=2.0,
        star_metallicity=0.01,
        # initial_binary_fraction=0,
        **kwargs):
    """
    Create stars.
    When using an IMF, either the stellar mass is fixed (within
    stochastic error) or the number of stars is fixed. When using
    equal-mass stars, both are fixed.
    """

    imf_name = initial_mass_function.lower()
    if imf_name == "salpeter":
        from amuse.ic.salpeter import new_salpeter_mass_distribution
        initial_mass_function = new_salpeter_mass_distribution
    elif imf_name == "kroupa":
        from amuse.ic.brokenimf import new_kroupa_mass_distribution
        initial_mass_function = new_kroupa_mass_distribution
    elif imf_name == "flat":
        from amuse.ic.flatimf import new_flat_mass_distribution
        initial_mass_function = new_flat_mass_distribution
    elif imf_name == "fixed":
        from amuse.ic.flatimf import new_flat_mass_distribution

        def new_fixed_mass_distribution(number_of_particles, *list_arguments,
                                        **keyword_arguments):
            return new_flat_mass_distribution(
                number_of_particles,
                mass_min=stellar_mass / number_of_stars,
                mass_max=stellar_mass / number_of_stars,
            )

        initial_mass_function = new_fixed_mass_distribution

    if stellar_mass:
        # Add stars to cluster, until mass limit reached (inclusive!)
        mass = initial_mass_function(
            0,
            mass_min=lower_mass_limit,
            mass_max=upper_mass_limit,
        )
        while mass.sum() < stellar_mass:
            mass.append(
                initial_mass_function(
                    1,
                    mass_min=lower_mass_limit,
                    mass_max=upper_mass_limit,
                )[0])
        total_mass = mass.sum()
        number_of_stars = len(mass)
    else:
        # Give stars their mass
        mass = initial_mass_function(
            number_of_stars,
            mass_min=lower_mass_limit,
            mass_max=upper_mass_limit,
        )
        total_mass = mass.sum()

    converter = generic_unit_converter.ConvertBetweenGenericAndSiUnits(
        total_mass,
        1. | units.kms,
        effective_radius,
    )
    # Give stars a position and velocity, based on the distribution model.
    if star_distribution == "plummer":
        stars = new_plummer_sphere(
            number_of_stars,
            convert_nbody=converter,
        )
    elif star_distribution == "king":
        stars = new_king_model(
            number_of_stars,
            star_distribution_w0,
            convert_nbody=converter,
        )
    elif star_distribution == "fractal":
        stars = new_fractal_cluster_model(
            number_of_stars,
            fractal_dimension=star_distribution_fd,
            convert_nbody=converter,
        )
    else:
        return -1, "No stellar distribution"

    # set the stellar mass.
    stars.mass = mass

    # set other stellar parameters.
    stars.metallicity = star_metallicity

    # Virialize the star cluster if > 1 star
    if len(stars) > 1:
        stars.move_to_center()
        stars.scale_to_standard(
            convert_nbody=converter,
            # virial_ratio=virial_ratio,
            # smoothing_length_squared= ...,
        )

    # Record the cluster's initial parameters to the particle distribution
    stars.collection_attributes.initial_mass_function = imf_name
    stars.collection_attributes.upper_mass_limit = upper_mass_limit
    stars.collection_attributes.lower_mass_limit = lower_mass_limit
    stars.collection_attributes.number_of_stars = number_of_stars

    stars.collection_attributes.effective_radius = effective_radius

    stars.collection_attributes.star_distribution = star_distribution
    stars.collection_attributes.star_distribution_w0 = star_distribution_w0
    stars.collection_attributes.star_distribution_fd = star_distribution_fd

    stars.collection_attributes.star_metallicity = star_metallicity

    # Derived/legacy values
    stars.collection_attributes.converter_mass = \
        converter.to_si(1 | nbody_system.mass)
    stars.collection_attributes.converter_length =\
        converter.to_si(1 | nbody_system.length)
    stars.collection_attributes.converter_speed =\
        converter.to_si(1 | nbody_system.speed)

    return stars