Beispiel #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
Beispiel #2
0
def scale_to_standard(particles,
                      convert_nbody=None,
                      smoothing_length_squared=zero,
                      virial_ratio=0.5):
    """
    Scale the particles to a standard NBODY model with G=1,
    total_mass=1, and virial_radius=1 (or potential_energy=-0.5). 
    In virial equilibrium (virial_ratio=0.5, default) the 
    kinetic_energy=0.25 and the velocity_dispersion=1/sqrt(2).

    :argument convert_nbody: the scaling is in nbody units,
        when the particles are in si units a convert_nbody is needed
    :argument smoothing_length_squared: needed for calculating
        the potential energy correctly.
    :argument virial_ratio: scale velocities to Q=K/|U|, (kinetic/potential energy); 
        Q = virial_ratio > 0.5: supervirial, will expand
        Q = virial_ratio < 0.5: subvirial, will collapse
    """
    if not convert_nbody is None:
        particles = ParticlesWithUnitsConverted(
            particles, convert_nbody.as_converter_from_generic_to_si())
        if not smoothing_length_squared is zero:
            smoothing_length_squared = convert_nbody.to_nbody(
                smoothing_length_squared)

    # Proper order is to scale mass, then length, then velocities.
    # Simple length scaling for the potential works only in the
    # unsoftened case.  In general, it may not be possible to force
    # the potential to -0.5, so perhaps best to stop after the simple
    # scaling.  We can always scale the velocities to get the correct
    # virial ratio (and hence virial equilibrium).

    total_mass = particles.mass.sum()
    scale_factor = ((1 | total_mass.unit) / total_mass)
    particles.mass *= scale_factor

    potential_energy \
        = particles.potential_energy(G=nbody_system.G,
                         smoothing_length_squared = smoothing_length_squared)
    target_energy = -0.5 | nbody_system.energy
    scale_factor = (potential_energy / target_energy)  # unsoftened only...
    particles.position *= scale_factor
    if smoothing_length_squared == zero:
        potential_energy = target_energy
    else:
        potential_energy = particles.potential_energy(
            G=nbody_system.G,
            smoothing_length_squared=smoothing_length_squared)

    if virial_ratio == 0:
        scale_factor = 0
    else:
        scale_factor = numpy.sqrt(
            abs(virial_ratio * potential_energy) / particles.kinetic_energy())
    particles.velocity *= scale_factor
Beispiel #3
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
def scale_to_standard(particles, convert_nbody = None,
                      smoothing_length_squared = zero,
                      virial_ratio = 0.5):
    """
    Scale the particles to a standard NBODY model with G=1,
    total_mass=1, and virial_radius=1 (or potential_energy=-0.5). 
    In virial equilibrium (virial_ratio=0.5, default) the 
    kinetic_energy=0.25 and the velocity_dispersion=1/sqrt(2).

    :argument convert_nbody: the scaling is in nbody units,
        when the particles are in si units a convert_nbody is needed
    :argument smoothing_length_squared: needed for calculating
        the potential energy correctly.
    :argument virial_ratio: scale velocities to Q=K/|U|, (kinetic/potential energy); 
        Q = virial_ratio > 0.5: supervirial, will expand
        Q = virial_ratio < 0.5: subvirial, will collapse
    """
    if not convert_nbody is None:
        particles = ParticlesWithUnitsConverted(particles, convert_nbody.as_converter_from_generic_to_si())
        if not smoothing_length_squared is zero:
            smoothing_length_squared = convert_nbody.to_nbody(smoothing_length_squared)

    # Proper order is to scale mass, then length, then velocities.
    # Simple length scaling for the potential works only in the
    # unsoftened case.  In general, it may not be possible to force
    # the potential to -0.5, so perhaps best to stop after the simple
    # scaling.  We can always scale the velocities to get the correct
    # virial ratio (and hence virial equilibrium).

    total_mass = particles.mass.sum()
    scale_factor = ((1 | total_mass.unit) / total_mass)
    particles.mass *= scale_factor

    potential_energy \
        = particles.potential_energy(G=nbody_system.G,
                         smoothing_length_squared = smoothing_length_squared)
    target_energy = -0.5 | nbody_system.energy
    scale_factor = (potential_energy / target_energy)	# unsoftened only...
    particles.position *= scale_factor
    if smoothing_length_squared == zero:
        potential_energy = target_energy
    else:
        potential_energy = particles.potential_energy(G=nbody_system.G,
            smoothing_length_squared = smoothing_length_squared)
    
    if virial_ratio == 0:
        scale_factor = 0
    else:
        scale_factor = numpy.sqrt(abs(virial_ratio*potential_energy) / particles.kinetic_energy())
    particles.velocity *= scale_factor
Beispiel #5
0
def _new_galactics_model(halo_number_of_particles, unit_system_converter=None, do_scale=False, **keyword_arguments):
    instance = GalactICs(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)
    
    instance.generate_particles()
    result = instance.particles.copy()
    instance.stop()
    
    result.move_to_center()
    if do_scale:
        result.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()
    return result
Beispiel #6
0
def new_halogen_model(number_of_particles,
                      convert_nbody=None,
                      do_scale=False,
                      redirection='null',
                      **keyword_arguments):
    """
    Create an alpha-beta-gamma-model using Halogen with the given number of 
    particles. Returns a set of equal-mass particles self-consistently sampled 
    from the spherically symmetric density distribution defined by the alpha, 
    beta, and gamma parameters. The model is centered around the origin. 
    Positions and velocities are optionally scaled such that the kinetic and 
    potential energies are 0.25 and -0.5 in nbody-units, respectively.
    
    The alpha, beta, and gamma parameters are (of course) required, but all 
    other Halogen parameters can be used too, e.g. 
    new_halogen_model(..., black_hole_mass = 1.0e6 | units.MSun)
    will set halogen.parameters.black_hole_mass to this value. See 
    help(Halogen().parameters) for an overview of the Halogen parameters.

    :argument number_of_particles: Number of particles to generate in the model
    :argument convert_nbody:  When given will convert the resulting set to SI units
    :argument do_scale: scale the result to exact nbody units (M=1, K=0.25, U=-0.5)
    :argument alpha: alpha parameter in density profile (see amuse/community/halogen/src/doc for details)
    :argument beta:  beta parameter in density profile (see amuse/community/halogen/src/doc for details)
    :argument gamma: gamma parameter in density profile (see amuse/community/halogen/src/doc for details)
    """
    instance = Halogen(unit_converter=convert_nbody, redirection=redirection)
    instance.parameters.number_of_particles = number_of_particles
    for (key, value) in keyword_arguments.items():
        setattr(instance.parameters, key, value)

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

    result.move_to_center()
    if do_scale:
        result.scale_to_standard()

    if not convert_nbody is None:
        result = ParticlesWithUnitsConverted(
            result, convert_nbody.as_converter_from_si_to_generic())
        result = result.copy()
    return result
Beispiel #7
0
def new_limepy_model(*args, **kwargs):
    conv = kwargs.pop("converter", None)

    l = Limepy(*args, **kwargs)
    p = l.result

    if conv is not None:
        p = ParticlesWithUnitsConverted(p,
                                        conv.as_converter_from_si_to_generic())

    return p
Beispiel #8
0
def new_halogen_model(number_of_particles, convert_nbody = None, do_scale = False, 
        redirection = 'null', **keyword_arguments):
    """
    Create an alpha-beta-gamma-model using Halogen with the given number of 
    particles. Returns a set of equal-mass particles self-consistently sampled 
    from the spherically symmetric density distribution defined by the alpha, 
    beta, and gamma parameters. The model is centered around the origin. 
    Positions and velocities are optionally scaled such that the kinetic and 
    potential energies are 0.25 and -0.5 in nbody-units, respectively.
    
    The alpha, beta, and gamma parameters are (of course) required, but all 
    other Halogen parameters can be used too, e.g. 
    new_halogen_model(..., black_hole_mass = 1.0e6 | units.MSun)
    will set halogen.parameters.black_hole_mass to this value. See 
    help(Halogen().parameters) for an overview of the Halogen parameters.

    :argument number_of_particles: Number of particles to generate in the model
    :argument convert_nbody:  When given will convert the resulting set to SI units
    :argument do_scale: scale the result to exact nbody units (M=1, K=0.25, U=-0.5)
    :argument alpha: alpha parameter in density profile (see amuse/community/halogen/src/doc for details)
    :argument beta:  beta parameter in density profile (see amuse/community/halogen/src/doc for details)
    :argument gamma: gamma parameter in density profile (see amuse/community/halogen/src/doc for details)
    """
    instance = Halogen(unit_converter=convert_nbody, redirection=redirection)
    instance.parameters.number_of_particles = number_of_particles
    for (key, value) in keyword_arguments.iteritems():
        setattr(instance.parameters, key, value)
    
    instance.generate_particles()
    result = instance.particles.copy()
    instance.stop()
    
    result.move_to_center()
    if do_scale:
        result.scale_to_standard()
    
    if not convert_nbody is None:
        result = ParticlesWithUnitsConverted(result, convert_nbody.as_converter_from_si_to_generic())
        result = result.copy()
    return result
Beispiel #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
Beispiel #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
Beispiel #11
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:]
    def test6(self):
        print "Test all particle attributes using Hop - each different function creates its own instance of Hop"
        numpy.random.seed(123)
        nbody_plummer = new_plummer_sphere(100)
        nbody_plummer.mass = new_salpeter_mass_distribution_nbody(100)

        # Each different function creates its own instance of Hop
        result = nbody_plummer.new_particle_from_cluster_core(reuse_hop=True)
        result = nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=True)
        result = nbody_plummer.mass_segregation_Gini_coefficient(
            reuse_hop=True)
        result = nbody_plummer.LagrangianRadii(reuse_hop=True)
        result = nbody_plummer.densitycentre_coreradius_coredens(
            reuse_hop=True)

        converter = nbody_system.nbody_to_si(1.0 | units.MSun,
                                             1.0 | units.parsec)
        si_plummer = ParticlesWithUnitsConverted(
            nbody_plummer, converter.as_converter_from_si_to_nbody())
        functions_using_hop = [
            si_plummer.new_particle_from_cluster_core, si_plummer.bound_subset,
            si_plummer.mass_segregation_Gini_coefficient,
            si_plummer.LagrangianRadii,
            si_plummer.densitycentre_coreradius_coredens
        ]

        # Each fails since the Hop instance it tries to reuse has a different unit_converter
        for function_using_hop in functions_using_hop:
            self.assertRaises(
                ConvertArgumentsException,
                function_using_hop,
                unit_converter=converter,
                expected_message=
                "error while converting parameter 'mass', error: Cannot express kg in mass, the units do not have the same bases"
            )

        # Close all Hop instances:
        nbody_results = []
        nbody_results.append(
            nbody_plummer.new_particle_from_cluster_core(reuse_hop=False))
        nbody_results.append(
            nbody_plummer.bound_subset(G=nbody_system.G, reuse_hop=False))
        nbody_results.append(
            nbody_plummer.mass_segregation_Gini_coefficient(reuse_hop=False))
        nbody_results.append(nbody_plummer.LagrangianRadii(reuse_hop=False))
        nbody_results.append(
            nbody_plummer.densitycentre_coreradius_coredens(reuse_hop=False))

        # Now it works, because the Hop instances were closed, and new ones will be instantiated
        si_results = []
        for function_using_hop in functions_using_hop:
            si_results.append(function_using_hop(unit_converter=converter))

        convert = converter.as_converter_from_si_to_nbody()
        self.assertAlmostRelativeEqual(
            si_results[0].position,
            ParticlesWithUnitsConverted(nbody_results[0].as_set(),
                                        convert)[0].position)
        self.assertAlmostRelativeEqual(
            si_results[1].position,
            ParticlesWithUnitsConverted(nbody_results[1], convert).position)
        self.assertAlmostRelativeEqual(si_results[2],
                                       nbody_results[2],
                                       places=10)
        self.assertAlmostRelativeEqual(si_results[3][0],
                                       convert.from_target_to_source(
                                           nbody_results[3][0]),
                                       places=10)
        for in_si, in_nbody in zip(si_results[4], nbody_results[4]):
            self.assertAlmostRelativeEqual(
                in_si, convert.from_target_to_source(in_nbody), places=10)