Exemple #1
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
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