Exemplo n.º 1
0
def _new_galactics_model(halo_number_of_particles,
                         unit_system_converter=None,
                         do_scale=False,
                         verbose=False,
                         **keyword_arguments):

    code = keyword_arguments.pop("code")
    instance = code(unit_converter=unit_system_converter)
    instance.parameters.halo_number_of_particles = halo_number_of_particles
    for (key, value) in keyword_arguments.iteritems():
        setattr(instance.parameters, key, value)

    if verbose:
        print "adopted galaxy model parameters:"
        print instance.parameters

    instance.generate_particles()
    result = instance.particles.copy()

    if hasattr(instance, "gas_particles") and len(instance.gas_particles) > 0:
        resultgas = instance.gas_particles.copy()
    else:
        resultgas = Particles()

    instance.stop()

    if len(resultgas) > 0:
        allpart = ParticlesSuperset([result, resultgas])
    else:
        allpart = result
    allpart.move_to_center()

    # do_scale *is* possible for case with unit converter
    # note that in case of scaling the output galaxy parameters may be very different from the model
    # parameters input
    if do_scale:
        print "Warning: do_scale for a large galactics model may be very slow"
        if verbose:
            print "Warning: do_scale typically changes the galaxy scale parameters quite a lot from the input parameters"
        if len(resultgas) > 0:
            # this is fixable
            raise Exception(
                "scaling of galaxy models with gas currently not possible")
        allpart.scale_to_standard(convert_nbody=unit_system_converter)

    if not unit_system_converter is None:
        result = ParticlesWithUnitsConverted(
            result, unit_system_converter.as_converter_from_si_to_generic())
        result = result.copy()
        if len(resultgas) > 0:
            resultgas = ParticlesWithUnitsConverted(
                resultgas,
                unit_system_converter.as_converter_from_si_to_generic())
            resultgas = resultgas.copy()

    if len(resultgas) > 0:
        # resultincludes the gas particles (but not under the same keys)
        return resultgas, result
    else:
        return result
Exemplo 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
Exemplo n.º 3
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.º 4
0
def _new_galactics_model(halo_number_of_particles, unit_system_converter=None, do_scale=False, verbose=False, **keyword_arguments):

    code=keyword_arguments.pop("code")
    instance = code(unit_converter=unit_system_converter, redirection="none" if verbose else "null")
    instance.parameters.halo_number_of_particles = halo_number_of_particles
    for (key, value) in keyword_arguments.iteritems():
        setattr(instance.parameters, key, value)
    
    if verbose:
        print "adopted galaxy model parameters:"
        print instance.parameters
    
    instance.generate_particles()
    result = instance.particles.copy()
    
    if hasattr(instance,"gas_particles") and len(instance.gas_particles)>0:
        resultgas=instance.gas_particles.copy()
    else:
        resultgas=Particles()
    
    instance.stop()

    if len(resultgas)>0:
        allpart=ParticlesSuperset([result, resultgas])
    else:
        allpart=result
    allpart.move_to_center()

    # do_scale *is* possible for case with unit converter
    # note that in case of scaling the output galaxy parameters may be very different from the model 
    # parameters input
    if do_scale:
        print "Warning: do_scale for a large galactics model may be very slow"
        if verbose:
            print "Warning: do_scale typically changes the galaxy scale parameters quite a lot from the input parameters"
        if len(resultgas)>0:
            # this is fixable
            raise Exception("scaling of galaxy models with gas currently not possible")        
        allpart.scale_to_standard(convert_nbody=unit_system_converter)

    if not unit_system_converter is None:
        result = ParticlesWithUnitsConverted(result, unit_system_converter.as_converter_from_si_to_generic())
        result = result.copy()
        if len(resultgas)>0:
            resultgas = ParticlesWithUnitsConverted(resultgas, unit_system_converter.as_converter_from_si_to_generic())
            resultgas = resultgas.copy()

    if len(resultgas)>0:
      # resultincludes the gas particles (but not under the same keys)
      return resultgas, result
    else:
      return result
Exemplo n.º 5
0
 def test2(self):
     colliders = Particles(2)
     colliders.mass = [5, 5] | units.kg
     colliders.position = [[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]] | units.m
     colliders.velocity = [[0.0, 0.0, 0.0], [2.0, 2.0, 2.0]] | units.m / units.s
     
     merged = StickySpheres(mass_loss=0.2).handle_collision(colliders[0], colliders[1])
     self.assertTrue(isinstance(merged, Particles))
     self.assertEqual(merged.mass, 8 | units.kg)
     self.assertAlmostEqual(merged.position, [0.5, 0.5, 0.5] | units.m)
     self.assertAlmostEqual(merged.velocity, [1.0, 1.0, 1.0] | units.m / units.s)
     copy = colliders.copy()
     copy.move_to_center()
     self.assertAlmostEqual(colliders.kinetic_energy(), merged.as_set().kinetic_energy() / 0.8 + copy.kinetic_energy())
Exemplo n.º 6
0
 def test2(self):
     colliders = Particles(2)
     colliders.mass = [5, 5] | units.kg
     colliders.position = [[0.0, 0.0, 0.0], [1.0, 1.0, 1.0]] | units.m
     colliders.velocity = [[0.0, 0.0, 0.0], [2.0, 2.0, 2.0]] | units.m / units.s
     
     merged = StickySpheres(mass_loss=0.2).handle_collision(colliders[0], colliders[1])
     self.assertTrue(isinstance(merged, Particles))
     self.assertEqual(merged.mass, 8 | units.kg)
     self.assertAlmostEqual(merged.position, [0.5, 0.5, 0.5] | units.m)
     self.assertAlmostEqual(merged.velocity, [1.0, 1.0, 1.0] | units.m / units.s)
     copy = colliders.copy()
     copy.move_to_center()
     self.assertAlmostEqual(colliders.kinetic_energy(), merged.as_set().kinetic_energy() / 0.8 + copy.kinetic_energy())
Exemplo n.º 7
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.º 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 result(self):
     masses, x,y,z, vx,vy,vz, internal_energies = self.new_model()
     result = Particles(self.actualN)
     result.mass = nbody_system.mass.new_quantity(masses)
     result.x = nbody_system.length.new_quantity(x)
     result.y = nbody_system.length.new_quantity(y)
     result.z = nbody_system.length.new_quantity(z)
     result.vx = nbody_system.speed.new_quantity(vx)
     result.vy = nbody_system.speed.new_quantity(vy)
     result.vz = nbody_system.speed.new_quantity(vz)
     result.u = nbody_system.specific_energy.new_quantity(internal_energies)
             
     if not self.convert_nbody is None:
         result = ParticlesWithUnitsConverted(result, self.convert_nbody.as_converter_from_si_to_generic())
         result = result.copy()
         
     return result
Exemplo n.º 10
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
Exemplo 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
Exemplo n.º 12
0
def rgb_frame(
    stars,
    dryrun=False,
    vmax=None,
    percentile=0.9995,
    multi_psf=False,
    sourcebands="ubvri",
    image_width=12. | units.parsec,
    image_size=[1024, 1024],
    mapper_factory=None,
    gas=None,
    mapper_code=None,
    zoom_factor=1.0,
    psf_type="hubble",
    psf_sigma=1.0,
    verbose=True,
):

    if gas is None:
        gas = Particles()

    if verbose:
        print("luminosities..")

    for band in sourcebands:
        setattr(
            stars,
            band + "_band",
            4 * numpy.pi * stars.radius**2 * filter_band_flux(
                "bess-" + band + ".pass",
                lambda x: B_lambda(x, stars.temperature),
            ),
        )
    if verbose:
        print("..raw images..")

    if mapper_code != "gridify":
        # Use mapper to make raw (pre-convolved) images
        mapper = mapper_factory()
        stars_in_mapper = mapper.particles.add_particles(stars)
        gas_in_mapper = mapper.particles.add_particles(gas)

        mapper.parameters.projection_direction = [0, 0, 1]
        mapper.parameters.upvector = [0, -1, 0]

        raw_images = dict()
        for band in sourcebands:
            assign_weights_and_opacities(
                band,
                stars_in_mapper,
                gas_in_mapper,
                stars,
                gas,
                Nstar=500,
            )
            # mapper.particles.weight = getattr(
            #         stars,
            #         band+"_band"
            #         ).value_in(units.LSun)
            im = mapper.image.pixel_value
            raw_images[band] = numpy.fliplr(im)

        mapper.stop()
    else:
        # Use simpler python mapping script
        from .gridify import map_to_grid
        stars_in_mapper = stars.copy()
        gas_in_mapper = gas.copy()
        raw_images = dict()

        for band in sourcebands:
            assign_weights_and_opacities(
                band,
                stars_in_mapper,
                gas_in_mapper,
                stars,
                gas,
                Nstar=500,
            )
            allparticles = Particles()
            allparticles.add_particles(stars_in_mapper)
            allparticles.add_particles(gas_in_mapper)
            im = map_to_grid(
                allparticles.x,
                allparticles.y,
                weights=allparticles.weight,
                image_size=image_size,
                image_width=image_width,
            )
            raw_images[band] = im

    convolved_images = dict()

    if verbose:
        print("..convolving..")

    if psf_type == "hubble":
        psf = get_psf(zoom_factor=zoom_factor)
        if multi_psf:
            a = numpy.arange(image_size[0]) / float(image_size[0] - 1)
            b = numpy.arange(image_size[1]) / float(image_size[1] - 1)
            w1 = numpy.outer(a, b)
            w2 = numpy.outer(1. - a, b)
            w3 = numpy.outer(a, 1. - b)
            w4 = numpy.outer(1. - a, 1. - b)
            for key, val in list(raw_images.items()):
                im1 = Convolve(val, psf[key + '0'])
                im2 = Convolve(val, psf[key + '1'])
                im3 = Convolve(val, psf[key + '2'])
                im4 = Convolve(val, psf[key + '3'])
                convolved_images[key] = (w1 * im1 + w2 * im2 + w3 * im3 +
                                         w4 * im4)
        else:
            for key, val in list(raw_images.items()):
                im1 = Convolve(val, psf[key + '0'])
                convolved_images[key] = im1
    elif psf_type == "gaussian":
        for key, val in list(raw_images.items()):
            im1 = gaussian_filter(val, sigma=psf_sigma, order=0)
            convolved_images[key] = im1

    if verbose:
        print("..conversion to rgb")
    filter_data = get_filter_data()
    source = [filter_data['bess-' + x + '.pass'] for x in sourcebands]

    target = [xyz_data['x'], xyz_data['y'], xyz_data['z']]

    conv = ColorConverter(source, target)

    ubv = numpy.array([convolved_images[x] for x in sourcebands])

    xyz = numpy.tensordot(conv.conversion_matrix, ubv, axes=(1, 0))

    conv_xyz_to_lin = XYZ_to_sRGB_linear()

    srgb_l = numpy.tensordot(
        conv_xyz_to_lin.conversion_matrix,
        xyz,
        axes=(1, 0),
    )

    if dryrun or vmax is None:
        flat_sorted = numpy.sort(srgb_l.flatten())
        n = len(flat_sorted)
        vmax = flat_sorted[int(1. - 3 * (1. - percentile) * n)]
        print(("vmax:", vmax))
    if dryrun:
        return vmax

    conv_lin_to_sRGB = sRGB_linear_to_sRGB()

    srgb = conv_lin_to_sRGB.convert(srgb_l / vmax)

    # r = numpy.fliplr(srgb[0, :, :])
    # g = numpy.fliplr(srgb[1, :, :])
    # b = numpy.fliplr(srgb[2, :, :])

    rgb = numpy.zeros(image_size[0] * image_size[1] * 3)
    rgb = rgb.reshape(image_size[0], image_size[1], 3)
    rgb[:, :, 0] = srgb[0, :, :].T
    rgb[:, :, 1] = srgb[1, :, :].T
    rgb[:, :, 2] = srgb[2, :, :].T

    image = dict(
        pixels=rgb,
        size=rgb.size,
    )

    return vmax, image
Exemplo n.º 13
0
class SimpleXSplitSet(SimpleX):
    
    def __init__(self,**options):
        SimpleX.__init__(self,**options)
        self.gas_particles=Particles()
        self.src_particles=Particles()

    def commit_particles(self):
        
        sites=self.gas_particles.copy()
        sites.flux=0. | units.s**-1

        for p in self.src_particles:
          nearest=sites.find_closest_particle_to(p.x,p.y,p.z)
          nearest.flux+=p.luminosity

        self.particles.add_particles(sites)
        
        self.simplex_to_gas_channel=self.particles.new_channel_to(self.gas_particles)

        self.overridden().commit_particles()
        
        if hasattr(sites,"du_dt"):
          attributes=["du_dt"]
          channel=sites.new_channel_to(self.particles)
          channel.copy_attributes(attributes)

        del sites
              
    def recommit_particles(self):  

        sites=self.gas_particles.copy()
        sites.flux=0. | units.s**-1

        for p in self.src_particles:
          nearest=sites.find_closest_particle_to(p.x,p.y,p.z)
          nearest.flux+=p.luminosity

#        sites.synchronize_to(self.particles)
        add_set=sites.difference(self.particles)
        remove_set=self.particles.difference(sites)

        if len(remove_set)>0: self.particles.remove_particles(remove_set)
        if len(add_set)>0: self.particles.add_particles(add_set)
        self.overridden().recommit_particles() 

        channel=sites.new_channel_to(self.particles)
        attributes=["x","y","z","rho","xion","u","flux"]
        if hasattr(sites,"metallicity"):
           attributes.append("metallicity") 
        if hasattr(sites,"du_dt"):
           attributes.append("du_dt") 
        channel.copy_attributes(attributes)
        del sites

        self.overridden().recommit_particles()

    def evolve_model(self,tend):
        self.overridden().evolve_model(tend)
        self.simplex_to_gas_channel.copy_attributes(["xion","u","metallicity"])
        
    def define_state(self, object):
        CommonCode.define_state(self, object)
        
        object.add_transition('INITIALIZED','EDIT','commit_parameters')
        object.add_transition('RUN','CHANGE_PARAMETERS_RUN','before_set_parameter', False)
        object.add_transition('EDIT','CHANGE_PARAMETERS_EDIT','before_set_parameter', False)
        object.add_transition('UPDATE','CHANGE_PARAMETERS_UPDATE','before_set_parameter', False)
        object.add_transition('CHANGE_PARAMETERS_RUN','RUN','recommit_parameters')
        object.add_transition('CHANGE_PARAMETERS_EDIT','EDIT','recommit_parameters')
        object.add_transition('CHANGE_PARAMETERS_UPDATE','UPDATE','recommit_parameters')
        
        object.add_method('CHANGE_PARAMETERS_RUN', 'before_set_parameter')
        object.add_method('CHANGE_PARAMETERS_EDIT', 'before_set_parameter')
        object.add_method('CHANGE_PARAMETERS_UPDATE','before_set_parameter')
        
        object.add_method('CHANGE_PARAMETERS_RUN', 'before_get_parameter')
        object.add_method('CHANGE_PARAMETERS_EDIT', 'before_get_parameter')
        object.add_method('CHANGE_PARAMETERS_UPDATE','before_get_parameter')
        object.add_method('RUN', 'before_get_parameter')
        object.add_method('EDIT', 'before_get_parameter')
        object.add_method('UPDATE','before_get_parameter')
        object.add_method('EVOLVED','before_get_parameter')
        object.add_method('RUNCOMMIT','before_get_parameter')
        
        
        
        object.add_method('EDIT', 'new_particle')
        object.add_method('EDIT', 'delete_particle')
        object.add_transition('EDIT', 'RUNCOMMIT', 'commit_particles')
        object.add_transition('RUN', 'UPDATE', 'new_particle', False)
        object.add_transition('RUN', 'UPDATE', 'delete_particle', False)
        object.add_transition('UPDATE', 'RUN', 'recommit_particles')
        object.add_transition('RUN','RUNCOMMIT', 'recommit_particles')
        object.add_transition('RUNCOMMIT','RUN', 'auto_go_to_run')
        object.add_transition('RUNCOMMIT', 'EVOLVED', 'evolve_model', False)
#        object.add_method('EVOLVED', 'evolve_model')
        object.define_state('RUNCOMMIT')
        object.add_transition('EVOLVED','RUN', 'synchronize_model')
        object.add_method('RUN', 'synchronize_model')
        object.add_method('RUN', 'get_state')
        object.add_method('RUN', 'get_density')
        object.add_method('RUN', 'get_position')
        object.add_method('RUN', 'get_flux')
        object.add_method('RUN', 'get_ionisation')
        object.add_method('RUN', 'get_internal_energy')
        object.add_method('RUN', 'set_dinternal_energy_dt')
        object.add_method('RUN', 'get_dinternal_energy_dt')
        object.add_method('UPDATE', 'set_dinternal_energy_dt')
        object.add_method('UPDATE', 'get_dinternal_energy_dt')

        object.add_method('INITIALIZED', 'set_hilbert_order')
        object.add_method('INITIALIZED', 'set_box_size')
        object.add_method('INITIALIZED', 'set_timestep')
        object.add_method('INITIALIZED', 'set_source_Teff')
        object.add_method('INITIALIZED', 'set_number_frequency_bins')
        object.add_method('INITIALIZED', 'set_thermal_evolution')
        object.add_method('INITIALIZED', 'set_blackbody_spectrum')
        object.add_method('INITIALIZED', 'set_metal_cooling')
        object.add_method('INITIALIZED', 'set_recombination_radiation')
        object.add_method('INITIALIZED', 'set_collisional_ionization')
Exemplo n.º 14
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
Exemplo n.º 15
0
class SimpleXSplitSet(SimpleX):
    def __init__(self, **options):
        SimpleX.__init__(self, **options)
        self.gas_particles = Particles()
        self.src_particles = Particles()

    def commit_particles(self):

        sites = self.gas_particles.copy()
        sites.flux = 0. | units.s**-1

        for p in self.src_particles:
            nearest = sites.find_closest_particle_to(p.x, p.y, p.z)
            nearest.flux += p.luminosity

        self.particles.add_particles(sites)

        self.simplex_to_gas_channel = self.particles.new_channel_to(
            self.gas_particles)

        self.overridden().commit_particles()

        if hasattr(sites, "du_dt"):
            attributes = ["du_dt"]
            channel = sites.new_channel_to(self.particles)
            channel.copy_attributes(attributes)

        del sites

    def recommit_particles(self):

        sites = self.gas_particles.copy()
        sites.flux = 0. | units.s**-1

        for p in self.src_particles:
            nearest = sites.find_closest_particle_to(p.x, p.y, p.z)
            nearest.flux += p.luminosity

#        sites.synchronize_to(self.particles)
        add_set = sites.difference(self.particles)
        remove_set = self.particles.difference(sites)

        if len(remove_set) > 0: self.particles.remove_particles(remove_set)
        if len(add_set) > 0: self.particles.add_particles(add_set)
        self.overridden().recommit_particles()

        channel = sites.new_channel_to(self.particles)
        attributes = ["x", "y", "z", "rho", "xion", "u", "flux"]
        if hasattr(sites, "metallicity"):
            attributes.append("metallicity")
        if hasattr(sites, "du_dt"):
            attributes.append("du_dt")
        channel.copy_attributes(attributes)
        del sites

        self.overridden().recommit_particles()

    def evolve_model(self, tend):
        self.overridden().evolve_model(tend)
        self.simplex_to_gas_channel.copy_attributes(
            ["xion", "u", "metallicity"])

    def define_state(self, handler):
        CommonCode.define_state(self, handler)

        handler.add_transition('INITIALIZED', 'EDIT', 'commit_parameters')
        handler.add_transition('RUN', 'CHANGE_PARAMETERS_RUN',
                               'before_set_parameter', False)
        handler.add_transition('EDIT', 'CHANGE_PARAMETERS_EDIT',
                               'before_set_parameter', False)
        handler.add_transition('UPDATE', 'CHANGE_PARAMETERS_UPDATE',
                               'before_set_parameter', False)
        handler.add_transition('CHANGE_PARAMETERS_RUN', 'RUN',
                               'recommit_parameters')
        handler.add_transition('CHANGE_PARAMETERS_EDIT', 'EDIT',
                               'recommit_parameters')
        handler.add_transition('CHANGE_PARAMETERS_UPDATE', 'UPDATE',
                               'recommit_parameters')

        handler.add_method('CHANGE_PARAMETERS_RUN', 'before_set_parameter')
        handler.add_method('CHANGE_PARAMETERS_EDIT', 'before_set_parameter')
        handler.add_method('CHANGE_PARAMETERS_UPDATE', 'before_set_parameter')

        handler.add_method('CHANGE_PARAMETERS_RUN', 'before_get_parameter')
        handler.add_method('CHANGE_PARAMETERS_EDIT', 'before_get_parameter')
        handler.add_method('CHANGE_PARAMETERS_UPDATE', 'before_get_parameter')
        handler.add_method('RUN', 'before_get_parameter')
        handler.add_method('EDIT', 'before_get_parameter')
        handler.add_method('UPDATE', 'before_get_parameter')
        handler.add_method('EVOLVED', 'before_get_parameter')
        handler.add_method('RUNCOMMIT', 'before_get_parameter')

        handler.add_method('EDIT', 'new_particle')
        handler.add_method('EDIT', 'delete_particle')
        handler.add_transition('EDIT', 'RUNCOMMIT', 'commit_particles')
        handler.add_transition('RUN', 'UPDATE', 'new_particle', False)
        handler.add_transition('RUN', 'UPDATE', 'delete_particle', False)
        handler.add_transition('UPDATE', 'RUN', 'recommit_particles')
        handler.add_transition('RUN', 'RUNCOMMIT', 'recommit_particles')
        handler.add_transition('RUNCOMMIT', 'RUN', 'auto_go_to_run')
        handler.add_transition('RUNCOMMIT', 'EVOLVED', 'evolve_model', False)
        #        handler.add_method('EVOLVED', 'evolve_model')
        handler.define_state('RUNCOMMIT')
        handler.add_transition('EVOLVED', 'RUN', 'synchronize_model')
        handler.add_method('RUN', 'synchronize_model')
        handler.add_method('RUN', 'get_state')
        handler.add_method('RUN', 'get_density')
        handler.add_method('RUN', 'get_position')
        handler.add_method('RUN', 'get_flux')
        handler.add_method('RUN', 'get_ionisation')
        handler.add_method('RUN', 'get_internal_energy')
        handler.add_method('RUN', 'set_dinternal_energy_dt')
        handler.add_method('RUN', 'get_dinternal_energy_dt')
        handler.add_method('UPDATE', 'set_dinternal_energy_dt')
        handler.add_method('UPDATE', 'get_dinternal_energy_dt')

        handler.add_method('INITIALIZED', 'set_hilbert_order')
        handler.add_method('INITIALIZED', 'set_box_size')
        handler.add_method('INITIALIZED', 'set_timestep')
        handler.add_method('INITIALIZED', 'set_source_Teff')
        handler.add_method('INITIALIZED', 'set_number_frequency_bins')
        handler.add_method('INITIALIZED', 'set_thermal_evolution')
        handler.add_method('INITIALIZED', 'set_blackbody_spectrum')
        handler.add_method('INITIALIZED', 'set_metal_cooling')
        handler.add_method('INITIALIZED', 'set_recombination_radiation')
        handler.add_method('INITIALIZED', 'set_collisional_ionization')
Exemplo n.º 16
0
    def make_model(self):
    
        call=[self._exec]+self.arguments()
        
        print(call)
        
        mameclot=Popen(call, stdout=PIPE,stderr=PIPE,executable=os.path.join(self._bin_path,self._exec))
        
        (out,err)=mameclot.communicate()
 
        print(err)
        
        outsplit=out.decode().strip().split("\n")
        errsplit=err.decode().strip().split("\n")
        
        if self.mass_ratio==0:
          nline=errsplit[6].split()
          mline=errsplit[7].split()
          rline=errsplit[8].split()
          N1=int(nline[2])
          N2=0
          mscale=(float(mline[4])/float(mline[2])) | units.MSun
          rscale=(float(rline[4])/float(mline[2])) | units.parsec
        else:
          nline=errsplit[8].split()
          n2line=errsplit[22].split()
          mline=errsplit[9].split()
          rline=errsplit[10].split()
          N1=int(nline[2])
          N2=int(n2line[2])
          mscale=(float(mline[4])/float(mline[2])) | units.MSun
          rscale=(float(rline[4])/float(mline[2])) | units.parsec
        print(N1,N2)
        
        N=len( outsplit)
        
        parts=Particles(N)
        
        masses=numpy.zeros((N,))
        energy=numpy.zeros((N,))
        
        position=numpy.zeros((N,3))
        velocity=numpy.zeros((N,3))
        
        for i,line in enumerate(outsplit):
            l=line.split()
            masses[i]=float(l[0])
            position[i,0:3]=[float(l[1]),float(l[2]),float(l[3])]
            velocity[i,0:3]=[float(l[4]),float(l[5]),float(l[6])]
            energy[i]=float(l[7])  
            
        parts.mass=masses | nbody_system.mass
        parts.position=position | nbody_system.length
        parts.velocity=velocity | nbody_system.speed
        parts.specific_energy=energy| nbody_system.specific_energy
  
        parts.move_to_center()
  
        if self.convert_to_physical:
            print("mass scale:", mscale)
            print("length scale:", rscale)  

            convert_nbody=nbody_system.nbody_to_si(mscale,rscale)
            parts = ParticlesWithUnitsConverted(parts, convert_nbody.as_converter_from_si_to_generic())
            parts = parts.copy()
  
        self._all=parts
        self._cluster1=parts[:N1]
        self._cluster2=parts[N1:]
Exemplo n.º 17
0
    def make_model(self):

        call = [self._exec] + self.arguments()

        print call

        mameclot = Popen(call, stdout=PIPE, stderr=PIPE, executable=os.path.join(self._bin_path, self._exec))

        (out, err) = mameclot.communicate()

        print err

        outsplit = out.strip().split("\n")
        errsplit = err.strip().split("\n")

        if self.mass_ratio == 0:
            nline = errsplit[6].split()
            mline = errsplit[7].split()
            rline = errsplit[8].split()
            N1 = int(nline[2])
            N2 = 0
            mscale = (float(mline[4]) / float(mline[2])) | units.MSun
            rscale = (float(rline[4]) / float(mline[2])) | units.parsec
        else:
            nline = errsplit[8].split()
            n2line = errsplit[22].split()
            mline = errsplit[9].split()
            rline = errsplit[10].split()
            N1 = int(nline[2])
            N2 = int(n2line[2])
            mscale = (float(mline[4]) / float(mline[2])) | units.MSun
            rscale = (float(rline[4]) / float(mline[2])) | units.parsec
        print N1, N2

        N = len(outsplit)

        parts = Particles(N)

        masses = numpy.zeros((N,))
        energy = numpy.zeros((N,))

        position = numpy.zeros((N, 3))
        velocity = numpy.zeros((N, 3))

        for i, line in enumerate(outsplit):
            l = line.split()
            masses[i] = float(l[0])
            position[i, 0:3] = [float(l[1]), float(l[2]), float(l[3])]
            velocity[i, 0:3] = [float(l[4]), float(l[5]), float(l[6])]
            energy[i] = float(l[7])

        parts.mass = masses | nbody_system.mass
        parts.position = position | nbody_system.length
        parts.velocity = velocity | nbody_system.speed
        parts.specific_energy = energy | nbody_system.specific_energy

        parts.move_to_center()

        if self.convert_to_physical:
            print "mass scale:", mscale
            print "length scale:", rscale

            convert_nbody = nbody_system.nbody_to_si(mscale, rscale)
            parts = ParticlesWithUnitsConverted(parts, convert_nbody.as_converter_from_si_to_generic())
            parts = parts.copy()

        self._all = parts
        self._cluster1 = parts[:N1]
        self._cluster2 = parts[N1:]
Exemplo n.º 18
0
def form_stars_from_group_older_version(
        group_index,
        sink_particles,
        newly_removed_gas,
        lower_mass_limit=settings.stars_lower_mass_limit,
        upper_mass_limit=settings.stars_upper_mass_limit,
        local_sound_speed=0.2 | units.kms,
        minimum_sink_mass=0.01 | units.MSun,
        logger=None,
        randomseed=None,
        shrink_sinks=True,
        **keyword_arguments):
    """
    Form stars from specific group of sinks.

    NOTE: This is the older version where removed gas is
    considered as star-forming region. This is now being
    updated to the above latest version.
    """
    logger = logger or logging.getLogger(__name__)
    logger.info("Using form_stars_from_group on group %i", group_index)
    if randomseed is not None:
        logger.info("Setting random seed to %i", randomseed)
        numpy.random.seed(randomseed)

    # Sanity check: each sink particle must be in a group.
    ungrouped_sinks = sink_particles.select_array(lambda x: x <= 0,
                                                  ['in_group'])
    if not ungrouped_sinks.is_empty():
        logger.info(
            "WARNING: There exist ungrouped sinks. Something is wrong!")
        return None

    # Consider only group with input group index from here onwards.
    group = sink_particles[sink_particles.in_group == group_index]

    # Sanity check: group must have at least a sink
    if group.is_empty():
        logger.info(
            "WARNING: There is no sink in the group: Something is wrong!")
        return None

    number_of_sinks = len(group)
    logger.info("%i sinks found in group #%i: %s", number_of_sinks,
                group_index, group.key)
    group_mass = group.total_mass()
    logger.info("Group mass: %s", group_mass.in_(units.MSun))

    next_mass = generate_next_mass(
        initial_mass_function=initial_mass_function,
        lower_mass_limit=lower_mass_limit,
        upper_mass_limit=upper_mass_limit,
    )[0][0]
    try:
        # Within a group, group_next_primary_mass values are either
        # a mass, or 0 MSun. If all values are 0 MSun, this is a
        # new group. Else, only interested on the non-zero value. The
        # non-zero values are the same.
        logger.info('SANITY CHECK: group_next_primary_mass %s',
                    group.group_next_primary_mass)
        if group.group_next_primary_mass.max() == 0 | units.MSun:
            logger.info('Initiate group #%i for star formation', group_index)
            group.group_next_primary_mass = next_mass
        else:
            next_mass = group.group_next_primary_mass.max()
    # This happens for the first ever assignment of this attribute
    except AttributeError:
        logger.info(
            'AttributeError exception: Initiate group #%i for star formation',
            group_index)
        group.group_next_primary_mass = next_mass

    logger.info("Next mass is %s", next_mass)

    if group_mass < next_mass:
        logger.info("Group #%i is not massive enough for the next star",
                    group_index)
        return None

    # Form stars from the leftover group sink mass
    mass_left = group_mass - next_mass
    masses = new_masses(
        stellar_mass=mass_left,
        lower_mass_limit=lower_mass_limit,
        upper_mass_limit=upper_mass_limit,
        initial_mass_function=settings.stars_initial_mass_function,
    )
    number_of_stars = len(masses)

    logger.info("%i stars created in group #%i with %i sinks", number_of_stars,
                group_index, number_of_sinks)

    new_stars = Particles(number_of_stars)
    new_stars.age = 0 | units.Myr
    new_stars[0].mass = next_mass
    new_stars[1:].mass = masses[:-1]
    group.group_next_primary_mass = masses[-1]
    new_stars = new_stars.sorted_by_attribute("mass").reversed()

    logger.info("Group's next primary mass is %s",
                group.group_next_primary_mass[0])

    # Create placeholders for attributes of new_stars
    new_stars.position = [0, 0, 0] | units.pc
    new_stars.velocity = [0, 0, 0] | units.kms
    new_stars.origin_cloud = group[0].key
    new_stars.star_forming_radius = 0 | units.pc
    new_stars.star_forming_u = local_sound_speed**2

    # Find the newly removed gas in the group
    removed_gas = Particles()
    if not newly_removed_gas.is_empty():
        for s in group:
            removed_gas_by_this_sink = (
                newly_removed_gas[newly_removed_gas.accreted_by_sink == s.key])
            removed_gas.add_particles(removed_gas_by_this_sink)

    logger.info("%i removed gas found in this group", len(removed_gas))

    # Star forming regions that contain the removed gas and the group
    # of sinks
    if not removed_gas.is_empty():
        removed_gas.radius = removed_gas.h_smooth
    star_forming_regions = group.copy()
    star_forming_regions.density = (
        star_forming_regions.initial_density / 1000
    )  # /1000 to reduce likelihood of forming stars in sinks
    star_forming_regions.accreted_by_sink = star_forming_regions.key
    try:
        star_forming_regions.u = star_forming_regions.u
    except AttributeError:
        star_forming_regions.u = local_sound_speed**2
    star_forming_regions.add_particles(removed_gas.copy())
    star_forming_regions.sorted_by_attribute("density").reversed()

    # Generate a probability list of star forming region indices the
    # stars should associate to
    probabilities = (star_forming_regions.density /
                     star_forming_regions.density.sum())
    probabilities /= probabilities.sum()  # Ensure sum is exactly 1
    logger.info("Max & min probabilities: %s, %s", probabilities.max(),
                probabilities.min())

    logger.info("%i star forming regions", len(star_forming_regions))

    def delta_positions_and_velocities(new_stars, star_forming_regions,
                                       probabilities):
        """
        Assign positions and velocities of stars in the star forming regions
        according to the probability distribution
        """
        number_of_stars = len(new_stars)

        # Create an index list of removed gas from probability list
        sample = numpy.random.choice(len(star_forming_regions),
                                     number_of_stars,
                                     p=probabilities)

        # Assign the stars to the removed gas according to the sample
        star_forming_regions_sampled = star_forming_regions[sample]
        new_stars.position = star_forming_regions_sampled.position
        new_stars.velocity = star_forming_regions_sampled.velocity
        new_stars.origin_cloud = star_forming_regions_sampled.accreted_by_sink
        new_stars.star_forming_radius = star_forming_regions_sampled.radius
        try:
            new_stars.star_forming_u = star_forming_regions_sampled.u
        except AttributeError:
            new_stars.star_forming_u = local_sound_speed**2

        # Random position of stars within the sink radius they assigned to
        rho = (numpy.random.random(number_of_stars) *
               new_stars.star_forming_radius)
        theta = (numpy.random.random(number_of_stars) *
                 (2 * numpy.pi | units.rad))
        phi = (numpy.random.random(number_of_stars) * numpy.pi | units.rad)
        x = (rho * sin(phi) * cos(theta)).value_in(units.pc)
        y = (rho * sin(phi) * sin(theta)).value_in(units.pc)
        z = (rho * cos(phi)).value_in(units.pc)

        X = list(zip(*[x, y, z])) | units.pc

        # Random velocity, sample magnitude from gaussian with local sound
        # speed like Wall et al (2019)
        # temperature = 10 | units.K

        # or (gamma * local_pressure / density).sqrt()
        velocity_magnitude = numpy.random.normal(
            # loc=0.0,  # <- since we already added the velocity of the sink
            scale=new_stars.star_forming_u.sqrt().value_in(units.kms),
            size=number_of_stars,
        ) | units.kms
        velocity_theta = (numpy.random.random(number_of_stars) *
                          (2 * numpy.pi | units.rad))
        velocity_phi = (numpy.random.random(number_of_stars) *
                        (numpy.pi | units.rad))
        vx = (velocity_magnitude * sin(velocity_phi) *
              cos(velocity_theta)).value_in(units.kms)
        vy = (velocity_magnitude * sin(velocity_phi) *
              sin(velocity_theta)).value_in(units.kms)
        vz = (velocity_magnitude * cos(velocity_phi)).value_in(units.kms)

        V = list(zip(*[vx, vy, vz])) | units.kms

        return X, V

    dX, dV = delta_positions_and_velocities(new_stars, star_forming_regions,
                                            probabilities)
    logger.info("Updating new stars...")
    new_stars.position += dX
    new_stars.velocity += dV

    # For Pentacle, this is the PP radius
    new_stars.radius = 0.05 | units.parsec

    # mass_ratio = 1 - new_stars.total_mass()/group.total_mass()
    # group.mass *= mass_ratio

    excess_star_mass = 0 | units.MSun
    for s in group:
        logger.info('Sink mass before reduction: %s', s.mass.in_(units.MSun))
        total_star_mass_nearby = (
            new_stars[new_stars.origin_cloud == s.key]).total_mass()

        # To prevent sink mass becomes negative
        if s.mass > minimum_sink_mass:
            if (s.mass - total_star_mass_nearby) <= minimum_sink_mass:
                excess_star_mass += (total_star_mass_nearby - s.mass +
                                     minimum_sink_mass)
                logger.info('Sink mass goes below %s; excess mass is now %s',
                            minimum_sink_mass.in_(units.MSun),
                            excess_star_mass.in_(units.MSun))
                s.mass = minimum_sink_mass
            else:
                s.mass -= total_star_mass_nearby
        else:
            excess_star_mass += total_star_mass_nearby
            logger.info(
                'Sink mass is already <= minimum mass allowed; '
                'excess mass is now %s', excess_star_mass.in_(units.MSun))

        logger.info('Sink mass after reduction: %s', s.mass.in_(units.MSun))

    # Reduce all sinks in group equally with the excess star mass
    logger.info('Reducing all sink mass equally with excess star mass...')
    mass_ratio = 1 - excess_star_mass / group.total_mass()
    group.mass *= mass_ratio

    logger.info("Total sink mass in group: %s",
                group.total_mass().in_(units.MSun))

    if shrink_sinks:
        group.radius = ((group.mass / group.initial_density) /
                        (4 / 3 * numpy.pi))**(1 / 3)
        logger.info("New radii: %s", group.radius.in_(units.pc))

    return new_stars