Exemplo n.º 1
0
        def resolve_sinks(self):
            print "processing high dens particles...",
            highdens=self.gas_particles.select_array(lambda rho:rho>self.density_threshold,["rho"])
            print "N=", len(highdens)
            candidate_stars=highdens.copy()
            self.gas_particles.remove_particles(highdens)
            self.gas_particles.synchronize_to(self.code.gas_particles)

            print "new sinks..."
            if len(candidate_stars)>0: # had to make some changes to prevent double adding particles
                print "Adding stars, N=", len(candidate_stars)
                newstars_in_code = self.code.dm_particles.add_particles(candidate_stars)
                newstars = Particles()
                for nsi in newstars_in_code:
                    if nsi not in self.star_particles:
                        newstars.add_particle(nsi)
                    else:
                        print "this star should not exicst"
                newstars.name = "Star" 
                newstars.birth_age = self.code.model_time
                newstars.Lx = 0 | (units.g * units.m**2)/units.s
                newstars.Ly = 0 | (units.g * units.m**2)/units.s
                newstars.Lz = 0 | (units.g * units.m**2)/units.s
                        
                print "pre N=", len(self.star_particles), len(newstars), len(self.code.dm_particles)
                #self.star_particles.add_sinks(newstars)
                self.star_particles.add_particles(newstars)
                print "post N=", len(self.star_particles), len(newstars), len(self.code.dm_particles)
            else:
                print "N candidates:", len(candidate_stars)
Exemplo n.º 2
0
def make_secondaries(center_of_masses, Nbin):

    resulting_binaries = Particles()
    singles_in_binaries = Particles()
    binaries = center_of_masses.random_sample(Nbin)
    mmin = center_of_masses.mass.min()
    for bi in binaries:
        mp = bi.mass
        ms = numpy.random.uniform(mmin.value_in(units.MSun),
                                  mp.value_in(units.MSun)) | units.MSun
        a = random_semimajor_axis_PPE(mp, ms)
        e = numpy.sqrt(numpy.random.random())

        nb = new_binary_orbit(mp, ms, a, e)
        nb.position += bi.position
        nb.velocity += bi.velocity
        nb = singles_in_binaries.add_particles(nb)
        nb.radius = 0.01 * a

        bi.radius = 3*a
        binary_particle = bi.copy()
        binary_particle.child1 = nb[0]
        binary_particle.child2 = nb[1]
        binary_particle.semi_major_axis = a
        binary_particle.eccentricity = e
        resulting_binaries.add_particle(binary_particle)

    single_stars = center_of_masses-binaries
    return single_stars, resulting_binaries, singles_in_binaries
Exemplo n.º 3
0
 def merge_sinks(self):
     print "Let gravity take care of merging sinks" 
     if True:
        if self.merge_radius<=quantities.zero:
            return
        print "identify groups.." 
        ccs=self.sink_particles.copy().connected_components(threshold=self.merge_radius)
        if len(ccs):
            print "merging sink sets... "
        nmerge=0
        newsinks=Particles()
        for cc in ccs:
            if len(cc) >1:
                nmerge+=1
            if len(cc) > 3: 
                print "warning: large merge(than 3) ", len(cc)
            cc=cc.copy()
            self.sink_particles.remove_particles(cc)
            self.sink_particles.synchronize_to(self.code.dm_particles)
            new = self.merge_stars(cc)
            newsinks.add_particle(new)
        if len(newsinks)>0:
            #new_in_code = self.dm_particles.add_particles(newsinks)
            #self.sink_particles.add_sinks(new_in_code,angular_momentum=newsinks.angular_momentum)
            newsinks_in_code = newsinks
            self.sink_particles.add_sinks(SinkParticles(newsinks_in_code,
                                                        looping_over="sources"))
            self.sink_particles.synchronize_to(self.code.dm_particles)
            
        if nmerge>0:
            print "nmerg found: ",nmerge,
        print "...done"
Exemplo n.º 4
0
def sink_particles(sinks,sources,Raccretion=0.1 | units.AU):
  closest=numpy.array([-1]*len(sources))
  mind2=(numpy.array([Raccretion.number]*len(sources)) | Raccretion.unit)**2
  for i,s in enumerate(sinks):
     xs,ys,zs=s.x,s.y,s.z
     d2=(sources.x-xs)**2+(sources.y-ys)**2+(sources.z-zs)**2
     select=numpy.where( d2<mind2 )[0]
     mind2[select]=d2[select]
     closest[select]=i

  to_remove=Particles(0)
  for i,s in enumerate(sinks):
     insink=numpy.where(closest == i)[0]
     if len(insink) > 0:
       cm=s.position*s.mass
       p=s.velocity*s.mass
       insinkp=Particles(0)
       for ip in insink:
         insinkp.add_particle(sources[ip])
       s.mass+=insinkp.total_mass()
       s.position=(cm+insinkp.center_of_mass()*insinkp.total_mass())/s.mass
       s.velocity=(p+insinkp.total_momentum())/s.mass
# we lose angular momentum !    
       to_remove.add_particles(insinkp)   
       print len(insinkp),"particles accrete on star", i
  if len(to_remove)>0:
    sources.remove_particles(to_remove)
Exemplo n.º 5
0
 def merge_sinks(self):
     print "Let gravity take care of merging sinks" 
     if True:
        if self.merge_radius<=quantities.zero:
            return
        print "identify groups.." 
        ccs=self.sink_particles.copy().connected_components(threshold=self.merge_radius)
        if len(ccs):
            print "merging sink sets... "
        nmerge=0
        newsinks=Particles()
        for cc in ccs:
            if len(cc) >1:
                nmerge+=1
            if len(cc) > 3: 
                print "warning: large merge(than 3) ", len(cc)
            cc=cc.copy()
            self.sink_particles.remove_particles(cc)
            new = self.merge_stars(cc)
            newsinks.add_particle(new)
        if len(newsinks)>0:
            #new_in_code = self.dm_particles.add_particles(newsinks)
            #self.sink_particles.add_sinks(new_in_code,angular_momentum=newsinks.angular_momentum)
            newsinks_in_code = newsinks
            self.sink_particles.add_sinks(SinkParticles(newsinks_in_code,
                                                        looping_over="sources"))
        if nmerge>0:
            print "nmerg found: ",nmerge,
        print "...done"
Exemplo n.º 6
0
    def drift_codes(self, tend, corr_time):
        code = self.parent_code
        stopping_condition = code.stopping_conditions.collision_detection
        stopping_condition.enable()
        while code.model_time < tend * (1 - 1.e-12):
            code.evolve_model(tend)
            if stopping_condition.is_set():
                coll_time = code.model_time
                #print("coll_time, t_end:", coll_time.in_(units.Myr), tend.in_(units.Myr))
                coll_sets = self.find_coll_sets(
                    stopping_condition.particles(0),
                    stopping_condition.particles(1))
                #print("collsets:",len(coll_sets))
                newparents = Particles()
                for cs in coll_sets:
                    newparents.add_particle(
                        self.handle_collision(coll_time, corr_time, cs))
                #print("len, corr-coll in Myr:",len(newparents),(corr_time-coll_time).in_(units.Myr))
                self.correction_kicks(self.particles, newparents,
                                      corr_time - coll_time)
                self.particles.recenter_subsystems()

        threads = []
        for x in self.subcodes.values():
            threads.append(
                threading.Thread(target=x.evolve_model, args=(tend, )))
        if self.use_threading:
            for x in threads:
                x.start()
            for x in threads:
                x.join()
        else:
            for x in threads:
                x.run()
Exemplo n.º 7
0
class Position_In_Potential(Abstract_Potential):
    """
        Wrapper around any other potential that has a test particle.
        Any call to get_potential_at_point will shift the coordinates to
        put the center on the location of that test particle.
        The particle is put in a Particles set to allow channels to be used,
        however, only a single particle is allowed at a time.
    """
    def __init__(self, potential, particle=None):
        self.potential = potential

        if particle is None:
            particle = Particle()
            particle.position = [0., 0., 0.] | units.parsec
            particle.velocity = [0., 0., 0.] | units.kms

        self.particles = Particles()
        self.particles.add_particle(particle)

    @property
    def particle(self):
        return self.particles[0]

    @particle.setter
    def particle(self, particle):
        self.particles.remove_particles(self.particles)
        self.particles.add_particle(particle)

    def get_potential_at_point(self, eps, x, y, z):
        px, py, pz = self.particle.position
        return self.potential.get_potential_at_point(eps, x+px, y+py, z+pz)
Exemplo n.º 8
0
def solar_system_in_time(time_JD=2457099.5|units.day):
  """
  Initial conditions of Solar system --
  particle set with the sun + eight planets,
  at the center-of-mass reference frame.

  Defined attributes: 
  name, mass, radius, x, y, z, vx, vy, vz
  """
  time_0 = 2457099.5 | units.day
  delta_JD = time_JD-time_0
  sun, planets = get_sun_and_planets(delta_JD=delta_JD)
  
  solar_system = Particles()
  solar_system.add_particle(sun)
  solar_system.add_particles(planets)
  solar_system.move_to_center()
  
  ### to compare with JPL, relative positions and velocities need to be corrected for the
  # Sun's vectors with respect to the barycenter
  #r_s = (3.123390770608490E-03, -4.370830943817017E-04, -1.443425433116342E-04) | units.AU
  #v_s = (3.421633816761503E-06,  5.767414405893875E-06, -8.878039607570240E-08) | (units.AU / units.day)
  #print sun
  #print planets.position.in_(units.AU) + r_s
  #print planets.velocity.in_(units.AU/units.day) + v_s
  
  return solar_system
def initialize_circumbinary_system(star_elements, planet_elements, star_masses):
  """
  set up two_stars and one planet orbiting both
  from given orbital parameters
  """
  
  se = star_elements
  
  pe = planet_elements
  
  se_true_anom = orbit.true_anomaly_from_mean_anomaly(se.M, se.e)
  
  stars = orbit.kepler_binary_from_orbital_elements(star_masses[0], star_masses[1], 
                    se.a, se.e, se_true_anom, se.i, se.node, se.argw)
                    
  pe_true_anom = orbit.true_anomaly_from_mean_anomaly(pe.M, pe.e)
                        
  binary_mass = star_masses[0] + star_masses[1] # Is this incorrect??????
  
  planet = orbit.planet_from_orbital_elements(binary_mass,
                       pe.a, pe.e, pe_true_anom, pe.i, pe.node, pe.argw)
                       
  system = Particles(0)
  system.add_particle(stars[0])
  system.add_particle(stars[1])
  system.add_particle(planet)
                        
  return system
Exemplo n.º 10
0
class Position_In_Potential(Abstract_Potential):
    """
        Wrapper around any other potential that has a test particle.
        Any call to get_potential_at_point will shift the coordinates to
        put the center on the location of that test particle.
        The particle is put in a Particles set to allow channels to be used,
        however, only a single particle is allowed at a time.
    """
    def __init__(self, potential, particle=None):
        self.potential = potential

        if particle is None:
            particle = Particle()
            particle.position = [0., 0., 0.] | units.parsec
            particle.velocity = [0., 0., 0.] | units.kms

        self.particles = Particles()
        self.particles.add_particle(particle)

    @property
    def particle(self):
        return self.particles[0]

    @particle.setter
    def particle(self, particle):
        self.particles.remove_particles(self.particles)
        self.particles.add_particle(particle)

    def get_potential_at_point(self, eps, x, y, z):
        px, py, pz = self.particle.position
        return self.potential.get_potential_at_point(eps, x+px, y+py, z+pz)
Exemplo n.º 11
0
 def all(self):
     parts = Particles()
     for parent in self:
         if parent.subsystem is None:
             parts.add_particle(parent)
         else:
             subsys = parts.add_particles(parent.subsystem)
             subsys.position += parent.position
             subsys.velocity += parent.velocity
     return parts
Exemplo n.º 12
0
def merge_two_stars(primary, secondary):
    "Merge two colliding stars into one new one"
    colliders = Particles()
    colliders.add_particle(primary)
    colliders.add_particle(secondary)
    new_particle = Particle()
    new_particle.mass = colliders.mass.sum()
    new_particle.position = colliders.center_of_mass()
    new_particle.velocity = colliders.center_of_mass_velocity()

    return new_particle
Exemplo n.º 13
0
def get_orbital_elements_of_triple(stars):
    inner_binary = stars[0]+stars[1]
    outer_binary = Particles(1)
    outer_binary[0].mass = inner_binary.mass.sum()
    outer_binary[0].position = inner_binary.center_of_mass()
    outer_binary[0].velocity = inner_binary.center_of_mass_velocity()
    outer_binary.add_particle(stars[2])
    M1, M2, ain, ein, ta_in, inc_in, lan_in, aop_in \
        = orbital_elements_from_binary(inner_binary, G=constants.G)
    M12, M3, aout, eout, ta_out, outc_out, lan_out, aop_out \
        = orbital_elements_from_binary(outer_binary, G=constants.G)
    return ain, ein, aout, eout
Exemplo n.º 14
0
def get_orbital_elements_of_triple(stars):
    inner_binary = stars[0]+stars[1]
    outer_binary = Particles(1)
    outer_binary[0].mass = inner_binary.mass.sum()
    outer_binary[0].position = inner_binary.center_of_mass()
    outer_binary[0].velocity = inner_binary.center_of_mass_velocity()
    outer_binary.add_particle(stars[2])
    M1, M2, ain, ein, ta_in, inc_in, lan_in, aop_in \
        = orbital_elements_from_binary(inner_binary, G=constants.G)
    M12, M3, aout, eout, ta_out, outc_out, lan_out, aop_out \
        = orbital_elements_from_binary(outer_binary, G=constants.G)
    return ain, ein, aout, eout
Exemplo n.º 15
0
def unstructured_square_domain(L=1000 | units.km,N=10):
    x,y,triangles,edges=square_domain(N=N)
    nodes=UnstructuredGrid(len(x))
    elements=UnstructuredGrid(len(triangles))
    nodes.x=x*L
    nodes.y=y*L
    for i in range(len(triangles)):
        elements[i].nodes=nodes[triangles[i,:]]
    boundaries=Particles()
    for e in edges:
      boundary=Particle(nodes=nodes[e])
      boundaries.add_particle(boundary)
    return nodes,elements,boundaries
Exemplo n.º 16
0
def get_orbital_elements_from_binary(binary, G=nbody_system.G):
    """
    Function that computes orbital elements from given two-particle set.
    Elements are computed for the second particle in this set and the
    return values are: mass1, mass2, semimajor axis, eccentricity,
    cosine of true anomaly, cosine of inclination, cosine of the
    longitude of the ascending node and the cosine of the argument of
    pericenter. In case of a perfectly circular orbit the true anomaly
    and argument of pericenter cannot be determined; in this case the
    return values are 1.0 for both cosines.
    """
    primaries = Particles()
    secondaries = Particles()
    if len(binary) > 2:
        raise Exception("expects binary or single part")
    elif len(binary) == 2:
        primaries.add_particle(binary[0])
        secondaries.add_particle(binary[1])
    else:
        # FIXME: in case of one particle, what do we calculate the orbit of?
        # The method below is what was default before.
        primaries.add_particle(binary[0])
        primaries[0].position *= 0
        primaries[0].velocity *= 0
        secondaries.add_particle(Particle())
        secondaries[0].mass = 0 * primaries[0].mass
        secondaries[0].position = binary.position
        secondaries[0].velocity = binary.velocity

    (mass1, mass2, semimajor_axis, eccentricity, true_anomaly, inclination,
     long_asc_node, arg_per) = get_orbital_elements_from_binaries(primaries,
                                                                  secondaries,
                                                                  G=G)
    return (mass1[0], mass2[0], semimajor_axis[0], eccentricity[0],
            true_anomaly[0], inclination[0], long_asc_node[0], arg_per[0])
Exemplo n.º 17
0
def new_binary_from_orbital_elements(
        mass1,
        mass2,
        semimajor_axis,
        eccentricity=0,
        true_anomaly=0 | units.deg,
        inclination=0 | units.deg,
        longitude_of_the_ascending_node=0 | units.deg,
        argument_of_periapsis=0 | units.deg,
        G=nbody_system.G
        ):
    """
    returns a two-particle Particle set, with the second particle's position
    and velocities computed from the input orbital elements.
    inclination is given between 0 and 180 deg.
    angles are assumed to be in deg if no unit is given.
    """
    def angle_with_unit(angle, default_unit=units.deg):
        try:
            default_unit = angle.unit
        except:
            angle = angle | default_unit
        return angle

    # If no unit is given for angles, assume they are in degrees
    true_anomaly = angle_with_unit(true_anomaly, default_unit=units.deg)
    inclination = angle_with_unit(inclination, default_unit=units.deg)
    argument_of_periapsis = angle_with_unit(
            argument_of_periapsis,
            default_unit=units.deg
            )
    longitude_of_the_ascending_node = angle_with_unit(
            longitude_of_the_ascending_node,
            default_unit=units.deg
            )
    primary, secondary = generate_binaries(
            mass1, mass2, semimajor_axis,
            eccentricity=eccentricity,
            true_anomaly=true_anomaly,
            inclination=inclination,
            longitude_of_the_ascending_node=longitude_of_the_ascending_node,
            argument_of_periapsis=argument_of_periapsis,
            G=G
            )

    result = Particles()
    result.add_particle(primary[0])
    result.add_particle(secondary[0])
    return result
Exemplo n.º 18
0
def get_bodies_in_orbit(m0, m_ffp, m_bp, a_bp, e_bp, phi_bp, lan_bp, b_ffp, r_inf):

    #Bodies
    bodies = Particles()

    ##Get BP in orbit
    #Binary
    star_planet = new_binary_from_orbital_elements(m0, m_bp, a_bp, e_bp, true_anomaly=phi_bp, inclination = 28, longitude_of_the_ascending_node = lan_bp)
    #Planet attributes
    star_planet.eccentricity = e_bp
    star_planet.semimajoraxis = a_bp
    #Center on the star
    star_planet.position -= star_planet[0].position
    star_planet.velocity -= star_planet[0].velocity
    cm_p = star_planet.center_of_mass()
    cm_v = star_planet.center_of_mass_velocity()

    ##Get FFP in orbit
    #Particle set
    m0_ffp = Particles(2)
    #Zeros and parabolic velocity
    zero_p = 0.0 | nbody_system.length
    zero_v = 0.0 | nbody_system.speed
    parabolic_velocity = get_parabolic_velocity(m0, m_ffp, b_ffp, r_inf, m_bp, a_bp, phi_bp)
    #Central star
    m0_ffp[0].mass = m0
    m0_ffp[0].position = (zero_p,zero_p,zero_p)
    m0_ffp[0].velocity = (zero_v,zero_v,zero_v)
    #Free-floating planet
    m0_ffp[1].mass = m_ffp
    m0_ffp[1].position = (-r_inf-cm_p[0],-b_ffp-cm_p[1],zero_p)
    m0_ffp[1].velocity = (parabolic_velocity,zero_v,zero_v)
    #Orbital Elements
    star_planet_as_one = Particles(1)
    star_planet_as_one.mass = m0 + m_bp
    star_planet_as_one.position = cm_p
    star_planet_as_one.velocity = cm_v
    binary = [star_planet_as_one[0], m0_ffp[1]]
    m1, m2, sma, e = my_orbital_elements_from_binary(binary)
    #For the star it sets the initial values of semimajoraxis and eccentricity of the ffp around star+bp
    m0_ffp.eccentricity = e
    m0_ffp.semimajoraxis = sma

    #Order: star, ffp, bp
    bodies.add_particle(m0_ffp[0])
    bodies.add_particle(m0_ffp[1])
    bodies.add_particle(star_planet[1])

    return bodies
def new_system(star_mass=1 | units.MSun,
               star_radius=1 | units.RSun,
               disk_minimum_radius=0.05 | units.AU,
               disk_maximum_radius=10 | units.AU,
               disk_mass=20 | MEarth,
               accurancy=0.0001,
               planet_density=3 | units.g / units.cm**3,
               rng=None,
               kepler=None):

    central_particle = Particle()
    central_particle.mass = star_mass
    central_particle.position = (0, 0, 0) | units.AU
    central_particle.velocity = (0, 0, 0) | units.kms
    central_particle.radius = star_radius
    central_particle.name = "star"
    central_particle.type = "star"
    central_particle.id = 0

    if rng is None:
        rng = numpy.random

    converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)

    if kepler is None:
        kepler = Kepler(converter)
        kepler.initialize_code()

    m, r, f = new_planet_distribution(disk_minimum_radius, disk_maximum_radius,
                                      disk_mass, accurancy)

    planets = make_planets(central_particle,
                           m,
                           r,
                           density=planet_density,
                           phi=0,
                           theta=None,
                           kepler=kepler,
                           rng=rng)
    planets.name = "planet"
    planets.type = "planet"
    for i in range(len(planets)):
        planets[i].id = i

    central_particle.planets = planets
    kepler.stop()
    p = Particles()
    p.add_particle(central_particle)
    return p
def get_moons_for_planet(planet, delta_JD=0. | units.day):
    """
  The Earth's moon
  as for JD = 2457099.500000000 = A.D. 2015-Mar-18 00:00:00.0000 (CT)
  https://ssd.jpl.nasa.gov/?sat_elem
  """

    data = numpy.array([tuple(entry) for entry in _lunar_data],
                       dtype=[('planet_name', 'S10'), ('name', 'S10'),
                              ('mass', '<f8'), ('radius', '<f8'),
                              ('semimajor_axis', '<f8'),
                              ('eccentricity', '<f8'),
                              ('argument_of_peri', '<f8'),
                              ('mean_anomaly', '<f8'), ('inclination', '<f8'),
                              ('longitude_oan', '<f8')])
    moon_data = data[data['planet_name'] == planet.name.encode('UTF-8')]
    print("Planet=", planet.name, "moon=", moon_data["name"])
    moons = Particles()
    if len(moon_data["name"]):
        print(len(moon_data["name"]))
        for moon in moon_data:
            #Ignore the moon for now, because it's complicated
            if planet.name == "EarthMoon":
                planet.mass -= moon["mass"] * 1.e+16 | units.kg
                planet.name = "Earth"
            #print moon
            r, v = get_position(planet.mass,
                                moon["mass"] * 1.e+16 | units.kg,
                                moon["eccentricity"],
                                moon["semimajor_axis"] | units.km,
                                numpy.deg2rad(moon["mean_anomaly"]),
                                numpy.deg2rad(moon["inclination"]),
                                numpy.deg2rad(moon["longitude_oan"]),
                                numpy.deg2rad(moon["argument_of_peri"]),
                                delta_t=delta_JD)
            single_moon = Particle()
            single_moon.type = "moon"
            single_moon.name = moon["name"]
            single_moon.mass = moon["mass"] * 1.e+16 | units.kg
            single_moon.hostname = moon["planet_name"]
            single_moon.radius = moon["radius"] | units.km
            single_moon.position = r
            single_moon.position += planet.position
            single_moon.velocity = v
            single_moon.velocity += planet.velocity
            moons.add_particle(single_moon)

    return moons
Exemplo n.º 21
0
        def evolve_model(self, model_time):
            
            start_time = time.time()

            density_limit_detection = self.code.stopping_conditions.density_limit_detection
            density_limit_detection.enable()

            model_time_old=self.code.model_time
            dt=model_time - model_time_old
            print "Evolve Hydrodynamics:", dt.in_(units.yr)
            print "Cool gas for dt=", (dt/2).in_(units.Myr)
            self.cooling.evolve_for(dt/2)
                #print "...done."
            self.code.evolve_model(model_time)
            #print "gas evolved."
            while density_limit_detection.is_set():
                print "processing high dens particles...",
                highdens=self.gas_particles.select_array(lambda rho:rho>self.density_threshold,["rho"])
                print "N=", len(highdens)
                candidate_sinks=highdens.copy()
                self.gas_particles.remove_particles(highdens)
                if len(self.sink_particles)>0:
                    print "new sinks..."
                    if len(candidate_sinks)>0: # had to make some changes to prevent double adding particles
                        newsinks_in_code = self.code.dm_particles.add_particles(candidate_sinks)
                        newsinks = Particles()
                        for nsi in newsinks_in_code:
                            if nsi not in self.sink_particles:
                                newsinks.add_particle(nsi) 
                        self.sink_particles.add_sinks(newsinks)
                else:
                    print "Create new sinks: N=", len(candidate_sinks)
                    #print "Code is very slow after this..."
                    newsinks_in_code = self.code.dm_particles.add_particles(candidate_sinks)
                    sink_particles_tmp = newsinks_in_code.copy()
                    #print "creating new sinks..."
                    self.sink_particles=SinkParticles(sink_particles_tmp, 
                                                      looping_over="sources")
                    #print "New sink particle:", sink_particles_tmp
                    print "New sinks created: ", len(sink_particles_tmp)

                print "..done"
                ##if len(self.sink_particles)>1: self.merge_sinks()
                self.code.evolve_model(model_time)
            print "Cool gas for another dt=", (dt/2).in_(units.Myr)
            self.cooling.evolve_for(dt/2)
                #print "...done."
            self.channel_to_framework.copy()
Exemplo n.º 22
0
    def handle_collision(self, coll_time, corr_time, coll_set):
        print("collision:", len(coll_set))

        subsystems = self.particles.compound_particles()
        collsubset = self.particles[0:0]
        collsubsystems = Particles()
        for p in coll_set:
            p = p.as_particle_in_set(self.particles)
            collsubset += p
            if self.subcodes.has_key(p):
                code = self.subcodes[p]
                code.evolve_model(coll_time)
                print(coll_time - code.model_time) / self.timestep
            if p.subsystem is not None:
                collsubsystems.add_particle(p)

        print("corr", coll_time.in_(units.yr),
              (coll_time - corr_time) / self.timestep)
        self.correction_kicks(collsubset, collsubsystems,
                              coll_time - corr_time)

        newparts = HierarchicalParticles(Particles())
        to_remove = Particles()
        for p in coll_set:
            p = p.as_particle_in_set(self.particles)
            if self.subcodes.has_key(p):
                code = self.subcodes.pop(p)
                parts = code.particles.copy()
                parts.position += p.position
                parts.velocity += p.velocity
                newparts.add_particles(parts)
                del code
            else:
                np = newparts.add_particle(p)
                np.radius = p.sub_worker_radius
            to_remove.add_particle(p)
        self.particles.remove_particles(to_remove)
        newcode = self.subcode_factory(newparts)
        newcode.parameters.begin_time = coll_time
        newcode.particles.add_particles(newparts)
        newparent = self.particles.add_subsystem(newcode.particles)
        self.set_parent_particle_radius(newparent)
        newparent.sub_worker_radius = 0. * newparent.radius
        print("radius:", newparent.radius.in_(units.parsec),
              newparent.sub_worker_radius.in_(units.parsec))
        self.subcodes[newparent] = newcode
        return newparent
Exemplo n.º 23
0
def new_system(
        star_mass = 1|units.MSun, 
        star_radius = 1|units.RSun, 
        disk_minumum_radius = 0.05 | units.AU,
        disk_maximum_radius = 10 | units.AU,
        disk_mass = 20 | MEarth,
        accurancy = 0.0001, 
        planet_density =  3 | units.g/units.cm**3,
        rng = None,
        kepler = None):
            
    central_particle = Particle()
    central_particle.mass =  star_mass
    central_particle.position = (0,0,0) | units.AU
    central_particle.velocity = (0,0,0) | units.kms
    central_particle.radius = star_radius
    
    if rng is None:
        rng = numpy.random
        
    converter = nbody_system.nbody_to_si(1|units.MSun, 1 | units.AU)
    
    if kepler is None:
        kepler = Kepler(converter)
        kepler.initialize_code()
        
    m, r, f = new_planet_distribution(
        disk_minumum_radius, disk_maximum_radius, 
        disk_mass,
        accurancy
    )
    
    planets = make_planets(
        central_particle, 
        m, r, 
        density = planet_density, 
        phi = 0, theta = None, 
        kepler = kepler, 
        rng = rng
    )
    
    central_particle.planets = planets
    kepler.stop()
    p = Particles()
    p.add_particle(central_particle)
    return p
Exemplo n.º 24
0
 def test3(self):
     particles = Particles(2)
     particles.add_attribute_domain('a')
     particles.add_attribute_domain('b')
     particles.a.foo = 1 | units.m
     particles.b.foo = 2 | units.kg
     particles.foo = 3 | units.s
     particles.a.add_particle(Particle(foo = 2 | units.m))
     
     self.assertAlmostRelativeEqual(particles.a.foo,  [1,1,2] | units.m)
     self.assertAlmostRelativeEqual(particles.b.foo,  [2,2,0] | units.kg)
     self.assertAlmostRelativeEqual(particles.foo,  [3,3,0] | units.s)
     
     particles.add_particle(Particle(foo = 2 | units.s))
     self.assertAlmostRelativeEqual(particles.a.foo,  [1,1,2,0] | units.m)
     self.assertAlmostRelativeEqual(particles.b.foo,  [2,2,0,0] | units.kg)
     self.assertAlmostRelativeEqual(particles.foo,  [3,3,0,2] | units.s)
Exemplo n.º 25
0
def new_binary_from_orbital_elements(mass1,
                                     mass2,
                                     semimajor_axis,
                                     eccentricity=0,
                                     true_anomaly=0 | units.deg,
                                     inclination=0 | units.deg,
                                     longitude_of_the_ascending_node=0
                                     | units.deg,
                                     argument_of_periapsis=0 | units.deg,
                                     G=nbody_system.G):
    """
    returns a two-particle Particle set, with the second particle's position
    and velocities computed from the input orbital elements.
    inclination is given between 0 and 180 deg.
    angles are assumed to be in deg if no unit is given.
    """
    def angle_with_unit(angle, default_unit=units.deg):
        try:
            default_unit = angle.unit
        except:
            angle = angle | default_unit
        return angle

    # If no unit is given for angles, assume they are in degrees
    true_anomaly = angle_with_unit(true_anomaly, default_unit=units.deg)
    inclination = angle_with_unit(inclination, default_unit=units.deg)
    argument_of_periapsis = angle_with_unit(argument_of_periapsis,
                                            default_unit=units.deg)
    longitude_of_the_ascending_node = angle_with_unit(
        longitude_of_the_ascending_node, default_unit=units.deg)
    primary, secondary = generate_binaries(
        mass1,
        mass2,
        semimajor_axis,
        eccentricity=eccentricity,
        true_anomaly=true_anomaly,
        inclination=inclination,
        longitude_of_the_ascending_node=longitude_of_the_ascending_node,
        argument_of_periapsis=argument_of_periapsis,
        G=G)

    result = Particles()
    result.add_particle(primary[0])
    result.add_particle(secondary[0])
    return result
Exemplo n.º 26
0
    def test3(self):
        particles = Particles(2)
        particles.add_attribute_domain('a')
        particles.add_attribute_domain('b')
        particles.a.foo = 1 | units.m
        particles.b.foo = 2 | units.kg
        particles.foo = 3 | units.s
        particles.a.add_particle(Particle(foo=2 | units.m))

        self.assertAlmostRelativeEqual(particles.a.foo, [1, 1, 2] | units.m)
        self.assertAlmostRelativeEqual(particles.b.foo, [2, 2, 0] | units.kg)
        self.assertAlmostRelativeEqual(particles.foo, [3, 3, 0] | units.s)

        particles.add_particle(Particle(foo=2 | units.s))
        self.assertAlmostRelativeEqual(particles.a.foo, [1, 1, 2, 0] | units.m)
        self.assertAlmostRelativeEqual(particles.b.foo,
                                       [2, 2, 0, 0] | units.kg)
        self.assertAlmostRelativeEqual(particles.foo, [3, 3, 0, 2] | units.s)
Exemplo n.º 27
0
def get_planets(m0, a_planets, m_planets, e_planets, phi=0.):

    #Particle set with all planets
    planets = Particles()

    #Initialize star-planet orbit
    for i,a_i in enumerate(a_planets):
        #Binary
        star_planet = new_binary_from_orbital_elements(m0, m_planets[i], a_planets[i], e_planets[i], true_anomaly=phi)
        #Planets attributes
        star_planet.eccentricity = e_planets[i]
        star_planet.semimajoraxis = a_planets[i]
        #Center on the star
        star_planet.position -= star_planet[0].position
        star_planet.velocity -= star_planet[0].velocity
        planets.add_particle(star_planet[1])

    return planets
def planet_from_orbital_elements(mass, sma, ecc, true_anom, inc, long_asc_node, arg_peri):
    """
    returns one particle (a planet) w/ coordinates in 'Center of Mass' frame of the binary
    This is not what you would expect from the typical binary_from_... function.
    """
    
    two_bodies = kepler_binary_from_orbital_elements(mass, 0.0 * mass, 
                        sma, ecc, true_anom, inc, long_asc_node, arg_peri)
                       
    # Move to 'Binary' Frame 
    two_bodies.position -= two_bodies[0].position
    two_bodies.velocity -= two_bodies[0].velocity
    
    planet = Particles(0)
    planet.add_particle(two_bodies[1])
    
    
    return planet
def planet_from_orbital_elements(mass, sma, ecc, true_anom, inc, long_asc_node,
                                 arg_peri):
    """
    returns one particle (a planet) w/ coordinates in 'Center of Mass' frame of the binary
    This is not what you would expect from the typical binary_from_... function.
    """

    two_bodies = kepler_binary_from_orbital_elements(mass, 0.0 * mass, sma,
                                                     ecc, true_anom, inc,
                                                     long_asc_node, arg_peri)

    # Move to 'Binary' Frame
    two_bodies.position -= two_bodies[0].position
    two_bodies.velocity -= two_bodies[0].velocity

    planet = Particles(0)
    planet.add_particle(two_bodies[1])

    return planet
Exemplo n.º 30
0
def old_new_solar_system():
    """
    Create initial conditions describing the solar system. Returns a single 
    particle set containing the sun, planets and Pluto. The model is centered at 
    the origin (center-of-mass(-velocity) coordinates).
    
    Defined attributes: 
    name, mass, radius, x, y, z, vx, vy, vz
    """
    sun = Particle()
    sun.name = 'SUN'
    sun.mass = 1.0 | units.MSun
    sun.radius = 1.0 | units.RSun
    planets = _planets_only()
    
    particles = Particles()
    particles.add_particle(sun)
    particles.add_particles(planets)
    particles.move_to_center()
    return particles
Exemplo n.º 31
0
def get_moons_for_planet(planet, delta_JD=0.|units.day):
  """
  The Earth's moon
  as for JD = 2457099.500000000 = A.D. 2015-Mar-18 00:00:00.0000 (CT)
  https://ssd.jpl.nasa.gov/?sat_elem
  """

  data = numpy.array([tuple(entry) for entry in _lunar_data],
        dtype=[('planet_name','S10'), ('name','S10'), 
        ('mass','<f8'), ('radius','<f8'), ('semimajor_axis','<f8'), 
        ('eccentricity','<f8'), ('argument_of_peri','<f8'),
        ('mean_anomaly','<f8'), ('inclination','<f8'), ('longitude_oan','<f8')])
  moon_data = data[data['planet_name']==planet.name]
  print "Planet=", planet.name, "moon=", moon_data["name"]
  moons = Particles()
  if len(moon_data["name"]):
      print len(moon_data["name"])
      for moon in moon_data:
          #print moon
          r, v = get_position(planet.mass,
                              moon["mass"] * 1.e+16 | units.kg,
                              moon["eccentricity"],
                              moon["semimajor_axis"]|units.km,
                              numpy.deg2rad(moon["mean_anomaly"]),
                              numpy.deg2rad(moon["inclination"]),
                              numpy.deg2rad(moon["longitude_oan"]),
                              numpy.deg2rad(moon["argument_of_peri"]),
                              delta_t=delta_JD)
          single_moon = Particle()
          single_moon.type = "moon"
          single_moon.name = moon["name"]
          single_moon.mass = moon["mass"] * 1.e+16 | units.kg
          single_moon.hostname = moon["planet_name"]
          single_moon.radius = moon["radius"] | units.km
          single_moon.position = r
          single_moon.position += planet.position
          single_moon.velocity = v
          single_moon.velocity += planet.velocity
          moons.add_particle(single_moon)
    
  return moons
def orbital_parameter_sorted_sets(planetesimals, two_stars):
    """
    Returns four sets of particles, sorted by their 'bounds' to each of the two stars
    """
    unbound = Particles(0)
    one = Particles(0)
    two = Particles(0)
    both = Particles(0)

    # two_stars can't be three stars or one star (hence the name)
    if len(two_stars) != 2:
        print "This is not really a Type Error, but whatever..."
        raise TypeError  # Replace with error message or something

    coor = []

    copy0 = planetesimals.copy_to_memory()
    copy1 = planetesimals.copy_to_memory()
    coor.append(copy0)
    coor.append(copy1)

    coor[0].position -= two_stars[0].position
    coor[1].position -= two_stars[1].position

    coor[0].velocity -= two_stars[0].velocity
    coor[1].velocity -= two_stars[1].velocity

    for pl, pl_0, pl_1 in zip(planetesimals, coor[0], coor[1]):
        rel_pos = []
        rel_pos.append(pl_0.position - two_stars[0].position)  # 505, 507 fix
        rel_pos.append(pl_1.position - two_stars[0].position)

        rel_vel = []
        rel_vel.append(pl_0.velocity - two_stars[0].velocity)
        rel_vel.append(pl_1.velocity - two_stars[0].velocity)

        a_a, ecc_a, T_a = orbital_parameters(rel_pos[0], rel_vel[0],
                                             two_stars[0].mass)
        a_b, ecc_b, T_b = orbital_parameters(rel_pos[1], rel_vel[1],
                                             two_stars[1].mass)

        if (0 <= ecc_a < 1 and 0 <= ecc_b < 1):
            both.add_particle(pl)
        elif (0 <= ecc_a < 1):
            one.add_particle(pl)
        elif (0 <= ecc_b < 1):
            two.add_particle(pl)
        else:
            unbound.add_particle(pl)

    return unbound, one, two, both
Exemplo n.º 33
0
        def resolve_sinks(self):
            print "processing high dens particles...",
            highdens=self.gas_particles.select_array(lambda rho:rho>self.density_threshold,["rho"])
            print "N=", len(highdens)
            candidate_sinks=highdens.copy()
            self.gas_particles.remove_particles(highdens)
            self.gas_particles.synchronize_to(self.code.gas_particles)
            #self.gas_particles.synchronize_to(self.cooling.gas_particles)
            if len(self.sink_particles)>0:
                print "new sinks..."
                if len(candidate_sinks)>0: # had to make some changes to prevent double adding particles
                    print "Adding sinks, N=", len(candidate_sinks)
                    newsinks_in_code = self.code.dm_particles.add_particles(candidate_sinks)
                    newsinks = Particles()
                    for nsi in newsinks_in_code:
                        if nsi not in self.sink_particles:
                            newsinks.add_particle(nsi)
                        else:
                            print "this sink should not exicst"
                        newsinks.sink_radius=self.sink_particles.sink_radius.max()
                    print "pre N=", len(self.sink_particles), len(newsinks), len(self.code.dm_particles)
                    self.sink_particles.add_sinks(newsinks)
                    print "post N=", len(self.sink_particles), len(newsinks), len(self.code.dm_particles)
                    print "Why can I not prim the sinks=", self.sink_particles
                else:
                    print "N candidates:", len(candidate_sinks)
            else:
                print "Create new sinks: N=", len(candidate_sinks)
                if len(candidate_sinks)>0:
                    newsinks_in_code = self.code.dm_particles.add_particles(candidate_sinks)
                    sink_particles_tmp = newsinks_in_code.copy()
                    print "creating new sinks..."
                    self.sink_particles=SinkParticles(sink_particles_tmp, 
                                                      looping_over="sources")
#                    self.channel_to_sinks = self.code.dm_particles.new_channel_to(self.sink_particles)

                    
                    print "New sinks created: ", len(sink_particles_tmp)
                else:
                    print "No sinks created."
Exemplo n.º 34
0
 def test2(self):
   m_star = 0.666|units.MSun
   a_min=666.|units.AU
   a_max=6666.|units.AU
   q_min=6.|units.AU
   cloud = new_isotropic_cloud(66,
                               m_star=m_star,
                               a_min=a_min,
                               a_max=a_max,
                               q_min=q_min)
   binary = Particles(1)
   binary[0].mass = m_star
   binary[0].position = (0.,0.,0.) | units.AU
   binary[0].velocity = (0.,0.,0.) | units.kms
   for comet in cloud:
     binary.add_particle(comet)
     mass1, mass2, semimajor_axis, eccentricity, true_anomaly, inclination, long_asc_node, arg_per = \
       orbital_elements_from_binary(binary, G=constants.G)
     print mass1, mass2, semimajor_axis, eccentricity, true_anomaly, inclination, long_asc_node, arg_per
     self.assertTrue( a_min < semimajor_axis < a_max )
     self.assertTrue( q_min < semimajor_axis*(1.-eccentricity) )
     binary.remove_particle(comet)
def orbital_parameter_sorted_sets(planetesimals, two_stars):
    """
    Returns four sets of particles, sorted by their 'bounds' to each of the two stars
    """
    unbound = Particles(0)
    one = Particles(0)
    two = Particles(0)
    both = Particles(0)

    # two_stars can't be three stars or one star (hence the name)
    if len(two_stars) != 2:
        print "This is not really a Type Error, but whatever..."
        raise TypeError  # Replace with error message or something

    coor = []
    
    copy0 = planetesimals.copy_to_memory()
    copy1 = planetesimals.copy_to_memory()
    coor.append(copy0)
    coor.append(copy1)

    coor[0].position -= two_stars[0].position
    coor[1].position -= two_stars[1].position

    coor[0].velocity -= two_stars[0].velocity
    coor[1].velocity -= two_stars[1].velocity

    for pl, pl_0, pl_1 in zip(planetesimals, coor[0], coor[1]):
        rel_pos = []
        rel_pos.append(pl_0.position - two_stars[0].position) # 505, 507 fix
        rel_pos.append(pl_1.position - two_stars[0].position)

        rel_vel = []
        rel_vel.append(pl_0.velocity - two_stars[0].velocity)
        rel_vel.append(pl_1.velocity - two_stars[0].velocity)

        a_a, ecc_a, T_a = orbital_parameters(rel_pos[0], rel_vel[0], two_stars[0].mass)
        a_b, ecc_b, T_b = orbital_parameters(rel_pos[1], rel_vel[1], two_stars[1].mass)

        if (0 <= ecc_a < 1 and 0 <= ecc_b < 1):
             both.add_particle(pl)
        elif (0 <= ecc_a < 1):
             one.add_particle(pl)
        elif (0 <= ecc_b < 1):
             two.add_particle(pl)
        else:
             unbound.add_particle(pl)

    return unbound, one, two, both
Exemplo n.º 36
0
 def test2(self):
     m_star = 0.666 | units.MSun
     a_min = 666. | units.AU
     a_max = 6666. | units.AU
     q_min = 6. | units.AU
     cloud = new_isotropic_cloud(66,
                                 m_star=m_star,
                                 a_min=a_min,
                                 a_max=a_max,
                                 q_min=q_min)
     binary = Particles(1)
     binary[0].mass = m_star
     binary[0].position = (0., 0., 0.) | units.AU
     binary[0].velocity = (0., 0., 0.) | units.kms
     for comet in cloud:
         binary.add_particle(comet)
         mass1, mass2, semimajor_axis, eccentricity, true_anomaly, inclination, long_asc_node, arg_per = \
           orbital_elements_from_binary(binary, G=constants.G)
         print mass1, mass2, semimajor_axis, eccentricity, true_anomaly, inclination, long_asc_node, arg_per
         self.assertTrue(a_min < semimajor_axis < a_max)
         self.assertTrue(q_min < semimajor_axis * (1. - eccentricity))
         binary.remove_particle(comet)
Exemplo n.º 37
0
    def split_subcodes(self):
        subsystems = self.particles.compound_particles()
        to_remove = Particles()
        sys_to_add = []
        for parent in subsystems:
            subsys = parent.subsystem
            radius = parent.radius
            components = subsys.connected_components(threshold=self.threshold,
                                                     distfunc=self.distfunc)
            if len(components) > 1:
                print("splitting:", len(components))
                parentposition = parent.position
                parentvelocity = parent.velocity
                to_remove.add_particle(parent)
                for c in components:
                    sys = c.copy()
                    sys.position += parentposition
                    sys.velocity += parentvelocity
                    sys_to_add.append(sys)
                code = self.subcodes.pop(parent)
                del code

        if len(to_remove) > 0:
            self.particles.remove_particles(to_remove)

            for sys in sys_to_add:
                if len(sys) > 1:
                    newcode = self.subcode_factory(sys)
                    newcode.parameters.begin_time = self.model_time
                    newcode.particles.add_particles(sys)
                    newparent = self.particles.add_subsystem(newcode.particles)
                    newparent.sub_worker_radius = 0. * newparent.radius
                    self.subcodes[newparent] = newcode
                else:
                    newparent = self.particles.add_subsystem(sys)
                    newparent.sub_worker_radius = sys[0].radius
                self.set_parent_particle_radius(newparent)
                print("radius:", newparent.radius.in_(units.parsec),
                      newparent.sub_worker_radius.in_(units.parsec))
Exemplo n.º 38
0
def evolve_bridged_orbit_in_potential(potential, cluster, code, timestep,
                                      current_age):
    orbit = static_potentials.Position_In_Potential(potential, cluster)

    bridge, gravity, gravity_to_orbit = setup_bridge(potential, cluster,
                                                     current_age, timestep,
                                                     orbit, code)

    print(current_age, "->", orbit.particle.position)
    # Evolving backward
    gravity.particles.velocity *= -1
    while bridge.model_time < current_age - (timestep / 2.):
        # print bridge.model_time, "-", gravity.particles.position[0]
        bridge.evolve_model(bridge.model_time + timestep)
        gravity_to_orbit.copy()
    gravity.particles.velocity *= -1

    gravity.model_time = 0 | units.Myr
    bridge.time = 0 | units.Myr
    cluster = gravity.particles[0]
    orbit.particle = cluster

    bridge, gravity, gravity_to_orbit = setup_bridge(potential, cluster,
                                                     current_age, timestep,
                                                     orbit, code)

    print(bridge.model_time, "->", orbit.particle.position)

    # Evolving forward
    full_orbit = Particles()
    while bridge.model_time < current_age - (timestep / 2.):
        full_orbit.add_particle(orbit.particle.copy())
        bridge.evolve_model(bridge.model_time + timestep)
        gravity_to_orbit.copy()
    full_orbit.add_particle(orbit.particle.copy())
    print(bridge.model_time, "->", orbit.particle.position)

    full_orbit.position -= coordinate_correction
    return full_orbit
Exemplo n.º 39
0
def evolve_bridged_orbit_in_potential(potential, cluster, code, timestep,
                                      current_age):
    orbit = static_potentials.Position_In_Potential(potential, cluster)

    bridge, gravity, gravity_to_orbit = setup_bridge(
        potential, cluster, current_age, timestep, orbit, code)

    print(current_age, "->", orbit.particle.position)
    # Evolving backward
    gravity.particles.velocity *= -1
    while bridge.model_time < current_age-(timestep/2.):
        # print bridge.model_time, "-", gravity.particles.position[0]
        bridge.evolve_model(bridge.model_time + timestep)
        gravity_to_orbit.copy()
    gravity.particles.velocity *= -1

    gravity.model_time = 0 | units.Myr
    bridge.time = 0 | units.Myr
    cluster = gravity.particles[0]
    orbit.particle = cluster

    bridge, gravity, gravity_to_orbit = setup_bridge(
        potential, cluster, current_age, timestep, orbit, code)

    print(bridge.model_time, "->", orbit.particle.position)

    # Evolving forward
    full_orbit = Particles()
    while bridge.model_time < current_age-(timestep/2.):
        full_orbit.add_particle(orbit.particle.copy())
        bridge.evolve_model(bridge.model_time + timestep)
        gravity_to_orbit.copy()
    full_orbit.add_particle(orbit.particle.copy())
    print(bridge.model_time, "->", orbit.particle.position)

    full_orbit.position -= coordinate_correction
    return full_orbit
Exemplo n.º 40
0
    def resolve_sinks(self):
        print("processing high dens particles...", end=' ')
        highdens = self.gas_particles.select_array(
            lambda rho: rho > self.density_threshold, ["rho"])
        print("N=", len(highdens))
        candidate_stars = highdens.copy()
        self.gas_particles.remove_particles(highdens)
        self.gas_particles.synchronize_to(self.code.gas_particles)

        print("new sinks...")
        if len(
                candidate_stars
        ) > 0:  # had to make some changes to prevent double adding particles
            print("Adding stars, N=", len(candidate_stars))
            newstars_in_code = self.code.dm_particles.add_particles(
                candidate_stars)
            newstars = Particles()
            for nsi in newstars_in_code:
                if nsi not in self.star_particles:
                    newstars.add_particle(nsi)
                else:
                    print("this star should not exicst")
            newstars.name = "Star"
            newstars.birth_age = self.code.model_time
            newstars.Lx = 0 | (units.g * units.m**2) / units.s
            newstars.Ly = 0 | (units.g * units.m**2) / units.s
            newstars.Lz = 0 | (units.g * units.m**2) / units.s

            print("pre N=", len(self.star_particles), len(newstars),
                  len(self.code.dm_particles))
            # self.star_particles.add_sinks(newstars)
            self.star_particles.add_particles(newstars)
            print("post N=", len(self.star_particles), len(newstars),
                  len(self.code.dm_particles))
        else:
            print("N candidates:", len(candidate_stars))
Exemplo n.º 41
0
def get_orbital_elements_from_binary(binary, G=nbody_system.G):
    """
    Function that computes orbital elements from given two-particle set.
    Elements are computed for the second particle in this set and the
    return values are: mass1, mass2, semimajor axis, eccentricity,
    cosine of true anomaly, cosine of inclination, cosine of the
    longitude of the ascending node and the cosine of the argument of
    pericenter. In case of a perfectly circular orbit the true anomaly
    and argument of pericenter cannot be determined; in this case the
    return values are 1.0 for both cosines.
    """
    primaries = Particles()
    secondaries = Particles()
    if len(binary) > 2:
        raise Exception("expects binary or single part")
    elif len(binary) == 2:
        primaries.add_particle(binary[0])
        secondaries.add_particle(binary[1])
    else:
        # FIXME: in case of one particle, what do we calculate the orbit of?
        # The method below is what was default before.
        primaries.add_particle(binary[0])
        primaries[0].position *= 0
        primaries[0].velocity *= 0
        secondaries.add_particle(Particle())
        secondaries[0].mass = 0 * primaries[0].mass
        secondaries[0].position = binary.position
        secondaries[0].velocity = binary.velocity

    (
            mass1, mass2, semimajor_axis, eccentricity, true_anomaly,
            inclination, long_asc_node, arg_per
            ) = get_orbital_elements_from_binaries(primaries, secondaries, G=G)
    return (
            mass1[0], mass2[0], semimajor_axis[0], eccentricity[0],
            true_anomaly[0], inclination[0], long_asc_node[0], arg_per[0])
Exemplo n.º 42
0
 def local_copy_of_particles(self, primary, secondary):
     particles = Particles(0)
     particles.add_particle(primary)
     particles.add_particle(secondary)
     return particles
Exemplo n.º 43
0
 def local_copy_of_particles(self, primary, secondary):
     particles = Particles(0)
     particles.add_particle(primary)
     particles.add_particle(secondary)
     return particles
Exemplo n.º 44
0
def main():
    import sys
    from amuse.io import read_set_from_file, write_set_to_file
    from amuse.support.console import set_preferred_units

    set_preferred_units(units.parsec, units.MSun, units.kms)

    converter = nbody_system.nbody_to_si(
        100 | units.MSun,
        1 | units.parsec,
    )

    # TODO: set a fixed density for Hop across snapshots

    # snapshot_numbers = []
    # snapshot_clusters = []
    cluster_cores = Particles()
    start_cluster_counter = 0
    for i, snapshot in enumerate(sys.argv[1:]):
        print("Reading snapshot %s" % snapshot)
        stars = read_set_from_file(snapshot, 'amuse', close_file=True)
        time = stars.get_timestamp()
        snapnum = snapshot.split('.')[0].split('-')[1]
        # snapshot_numbers.append(snapnum)
        # clusters = find_clusters(stars, mean_density=100000 | units.MSun * units.parsec**-3)
        clusters = find_clusters(stars, mean_density=None)
        print("Found %i clusters" % len(clusters))
        for j, cluster in enumerate(clusters):
            core = cluster.new_particle_from_cluster_core(converter)
            core.time = time
            lagrangian = cluster.LagrangianRadii(converter)
            core.lr100 = lagrangian[0][-1]
            core.lr90 = lagrangian[0][-2]
            core.lr75 = lagrangian[0][-3]
            core.lr50 = lagrangian[0][-4]
            core.lr20 = lagrangian[0][-5]
            core.lr10 = lagrangian[0][-6]
            core.lr05 = lagrangian[0][-7]
            core.lr02 = lagrangian[0][-8]
            core.lr01 = lagrangian[0][-9]
            core.mass = cluster.mass.sum()
            core.clusternumber = j
            core.snapshotnumber = snapnum
            cluster_cores.add_particle(core)
            cluster.core_id = len(cluster_cores) - 1
            # print("Cluster core id: %i" % cluster[0].core_id)
        if i > 0:
            match_clusters(
                clusters,
                clusters_to_match,
                cluster_cores,
                time=time,
                time_to_match=time_to_match,
            )
        clusters_to_match = clusters
        stars_to_match = stars
        i_to_match = i
        time_to_match = time
        start_cluster_counter += len(clusters)
    write_set_to_file(cluster_cores,
                      "cluster_cores_strong.amuse",
                      "amuse",
                      append_to_file=False)
    exit()

    print("Found %i clusters:" % len(clusters))
    for i, cluster in enumerate(clusters):
        snap = sys.argv[1].split('.')[0].split('-')[1]
        print(
            "fresco.py -s %s -o cluster-%03i -a 0 -w %f --xo %f --yo %f --zo %f"
            % (
                sys.argv[1],
                i,
                5.0,
                cluster.center_of_mass().x.value_in(units.parsec),
                cluster.center_of_mass().y.value_in(units.parsec),
                cluster.center_of_mass().z.value_in(units.parsec),
            ))

    for i, cluster in enumerate(clusters):
        snap = sys.argv[1].split('.')[0].split('-')[1]
        print(
            "python plotting_class.py -g gas-%s.hdf5 -s stars-%s.hdf5 -x %f -y %f -w 50 -n 100 -o zoom-%03i"
            % (
                snap,
                snap,
                cluster.center_of_mass().x.value_in(units.parsec),
                cluster.center_of_mass().y.value_in(units.parsec),
                i,
            ))
    return
Exemplo n.º 45
0
def get_bodies_in_orbit(m0, m_ffp, m_bp, a_bp, e_bp, phi_bp, inc_bp, lan_bp, b_ffp, r_inf):

    #Bodies
    bodies = Particles()

    ##Get BP in orbit
    #Binary
    star_planet = new_binary_from_orbital_elements(m0, m_bp, a_bp, e_bp, true_anomaly=phi_bp, inclination = inc_bp, longitude_of_the_ascending_node = lan_bp)
    #Planet attributes
    star_planet.eccentricity = e_bp
    star_planet.semimajoraxis = a_bp
    #Center on the star
    star_planet.position -= star_planet[0].position
    star_planet.velocity -= star_planet[0].velocity
    cm_p = star_planet.center_of_mass()
    cm_v = star_planet.center_of_mass_velocity()

    ##Get FFP in orbit
    #Particle set
    m0_ffp = Particles(2)
    #Zeros and parabolic velocity
    zero_p = 0.0 | nbody_system.length
    zero_v = 0.0 | nbody_system.speed
    parabolic_velocity = get_parabolic_velocity(m0, m_bp, b_ffp, r_inf)
    #Central star
    m0_ffp[0].mass = m0
    m0_ffp[0].position = (zero_p,zero_p,zero_p)
    m0_ffp[0].velocity = (zero_v,zero_v,zero_v)
    #Free-floating planet
    m0_ffp[1].mass = m_ffp
    m0_ffp[1].position = (-r_inf+cm_p[0], b_ffp+cm_p[1], cm_p[2])
    m0_ffp[1].velocity = (parabolic_velocity+cm_v[0], cm_v[1], cm_v[2])

    #To find the orbital period of the BP
    G = (1.0 | nbody_system.length**3 * nbody_system.time**-2 * nbody_system.mass**-1)
    orbital_period_bp = 2*math.pi*((a_bp**3)/(G*m0)).sqrt()

    #To find the distance and time to periastron
    kep = Kepler()
    kep.initialize_code()

    star_planet_as_one = Particles(1)
    star_planet_as_one.mass = m0 + m_bp
    star_planet_as_one.position = cm_p
    star_planet_as_one.velocity = cm_v

    kepler_bodies = Particles()
    kepler_bodies.add_particle(star_planet_as_one[0])
    kepler_bodies.add_particle(m0_ffp[1])

    kep.initialize_from_particles(kepler_bodies)

    kep.advance_to_periastron()
    time_pericenter = kep.get_time()
    
    kep.stop()

    binary = [star_planet_as_one[0], m0_ffp[1]]
    sma, e, inclination, long_asc_node, arg_per = my_orbital_elements_from_binary(binary)
    m0_ffp.eccentricity = e
    m0_ffp.semimajoraxis = sma

    #Adding bodies. Order: star, ffp, bp
    bodies.add_particle(m0_ffp[0])
    bodies.add_particle(m0_ffp[1])
    bodies.add_particle(star_planet[1])

    return bodies, time_pericenter, orbital_period_bp
Exemplo n.º 46
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, dtse_fac):

    import random
    from amuse.ext.solarsystem import get_position

    print "Initial masses:", M1, M2, M3
    t_stellar = 4.0|units.Myr
    triple = Particles(3)
    triple[0].mass = M1
    triple[1].mass = M2
    triple[2].mass = M3
    stellar = SeBa()
    stellar.particles.add_particles(triple)
    channel_from_stellar = stellar.particles.new_channel_to(triple)
    stellar.evolve_model(t_stellar)
    channel_from_stellar.copy_attributes(["mass"])
    M1 = triple[0].mass
    M2 = triple[1].mass
    M3 = triple[2].mass
    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Masses at time T:", M1, M2, M3
    
    # Inner binary
    
    tmp_stars = Particles(2)
    tmp_stars[0].mass = M1
    tmp_stars[1].mass = M2

    if Pora == 1:
        ain_0 = semimajor_axis(Pin_0, M1+M2)
    else:
        Pin_0 = orbital_period(ain_0, M1+M2)
        
    print 'ain_0 =', ain_0
    print 'M1+M2 =', M1+M2
    print 'Pin_0 =', Pin_0.value_in(units.day), '[day]'
    #print 'semi:', semimajor_axis(Pin_0, M1+M2).value_in(units.AU), 'AU'
    #print 'period:', orbital_period(ain_0, M1+M2).value_in(units.day), '[day]'
    
    dt = 0.1*Pin_0
    ma = 180
    inc = 30
    aop = 180
    lon = 0
    r, v = get_position(M1, M2, ein_0, ain_0, ma, inc, aop, lon, dt)
    tmp_stars[1].position = r
    tmp_stars[1].velocity = v
    tmp_stars.move_to_center()

    # Outer binary
    
    r, v = get_position(M1+M2, M3, eout_0, aout_0, 0, 0, 0, 0, dt)
    tertiary = Particle()
    tertiary.mass = M3
    tertiary.position = r
    tertiary.velocity = v
    tmp_stars.add_particle(tertiary)
    tmp_stars.move_to_center()

    triple.position = tmp_stars.position
    triple.velocity = tmp_stars.velocity

    Mtriple = triple.mass.sum()
    Pout = orbital_period(aout_0, Mtriple)

    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Pout=", Pout.in_(units.Myr)

    converter = nbody_system.nbody_to_si(triple.mass.sum(), aout_0)
    gravity = Hermite(converter)
    gravity.particles.add_particles(triple)

    channel_from_framework_to_gd = triple.new_channel_to(gravity.particles)
    channel_from_gd_to_framework = gravity.particles.new_channel_to(triple)
    
    Etot_init = gravity.kinetic_energy + gravity.potential_energy
    Etot_prev = Etot_init

    gravity.particles.move_to_center()

    time = 0.0 | t_end.unit
    ts = t_stellar + time

    ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
    print "Triple elements t=",  time,  \
        "inner:", triple[0].mass, triple[1].mass, ain, ein, \
        "outer:", triple[2].mass, aout, eout

    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag

    t = [time.value_in(units.Myr)] 
    smai = [ain/ain_0] 
    ecci = [ein/ein_0]
    smao = [aout/aout_0] 
    ecco = [eout/eout_0]
    ain = ain_0

    def advance_stellar(ts, dt):
        E0 = gravity.kinetic_energy + gravity.potential_energy
        ts += dt
        stellar.evolve_model(ts)
        channel_from_stellar.copy_attributes(["mass"])
        channel_from_framework_to_gd.copy_attributes(["mass"])
        return ts, gravity.kinetic_energy + gravity.potential_energy - E0

    def advance_gravity(tg, dt):
        tg += dt
        gravity.evolve_model(tg)
        channel_from_gd_to_framework.copy()
        return tg

    while time < t_end:

        Pin = orbital_period(ain, triple[0].mass+triple[1].mass)
        dt = dtse_fac*Pin
        dt *= random.random()

        if scheme == 1:
            
            ts, dE_se = advance_stellar(ts, dt)
            time = advance_gravity(time, dt)
            
        elif scheme == 2:
            
            time = advance_gravity(time, dt)
            ts, dE_se = advance_stellar(ts, dt)
            
        else:

            dE_se = zero
            #ts, dE_se = advance_stellar(ts, dt/2)
            time = advance_gravity(time, dt)
            #ts, dE = advance_stellar(ts, dt/2)
            #dE_se += dE

        if time >= t_diag:
            
            t_diag = time + dt_diag

            Ekin = gravity.kinetic_energy 
            Epot = gravity.potential_energy
            Etot = Ekin + Epot
            dE = Etot_prev - Etot
            Mtot = triple.mass.sum()
            print "T=", time, 
            print "M=", Mtot, "(dM[SE]=", Mtot/Mtriple, ")",
            print "E= ", Etot, "Q= ", Ekin/Epot,
            print "dE=", (Etot_init-Etot)/Etot, "ddE=", (Etot_prev-Etot)/Etot, 
            print "(dE[SE]=", dE_se/Etot, ")"
            Etot_init -= dE
            Etot_prev = Etot
            ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
            print "Triple elements t=",  (4|units.Myr) + time,  \
                "inner:", triple[0].mass, triple[1].mass, ain, ein, \
                "outer:", triple[2].mass, aout, eout

            t.append(time.value_in(units.Myr))
            smai.append(ain/ain_0)
            ecci.append(ein/ein_0)
            smao.append(aout/aout_0)
            ecco.append(eout/eout_0)

            if eout > 1.0 or aout <= zero:
                print "Binary ionized or merged"
                break

    gravity.stop()
    stellar.stop()

    return t, smai, ecci, smao, ecco
Exemplo n.º 47
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0, ein_0,
                            eout_0, t_end, nsteps, scheme, dtse_fac):

    import random
    from amuse.ext.solarsystem import get_position

    time_framework = 0

    print "Initial masses:", M1, M2, M3
    t_stellar = 4.0 | units.Myr
    triple = Particles(3)
    triple[0].mass = M1
    triple[1].mass = M2
    triple[2].mass = M3
    stellar = SeBa()
    stellar.particles.add_particles(triple)
    channel_from_stellar = stellar.particles.new_channel_to(triple)
    t0 = ctime.time()
    stellar.evolve_model(t_stellar)
    delta_t = ctime.time() - t0
    time_framework += delta_t
    channel_from_stellar.copy_attributes(["mass"])
    M1 = triple[0].mass
    M2 = triple[1].mass
    M3 = triple[2].mass
    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Masses at time T:", M1, M2, M3

    # Inner binary

    tmp_stars = Particles(2)
    tmp_stars[0].mass = M1
    tmp_stars[1].mass = M2

    if Pora == 1:
        ain_0 = semimajor_axis(Pin_0, M1 + M2)
    else:
        Pin_0 = orbital_period(ain_0, M1 + M2)

    print 'ain_0 =', ain_0
    print 'M1+M2 =', M1 + M2
    print 'Pin_0 =', Pin_0.value_in(units.day), '[day]'
    #print 'semi:', semimajor_axis(Pin_0, M1+M2).value_in(units.AU), 'AU'
    #print 'period:', orbital_period(ain_0, M1+M2).value_in(units.day), '[day]'

    dt = 0.1 * Pin_0
    ma = 180
    inc = 30
    aop = 180
    lon = 0
    r, v = get_position(M1, M2, ein_0, ain_0, ma, inc, aop, lon, dt)
    tmp_stars[1].position = r
    tmp_stars[1].velocity = v
    tmp_stars.move_to_center()

    # Outer binary

    r, v = get_position(M1 + M2, M3, eout_0, aout_0, 0, 0, 0, 0, dt)
    tertiary = Particle()
    tertiary.mass = M3
    tertiary.position = r
    tertiary.velocity = v
    tmp_stars.add_particle(tertiary)
    tmp_stars.move_to_center()

    triple.position = tmp_stars.position
    triple.velocity = tmp_stars.velocity

    Mtriple = triple.mass.sum()
    Pout = orbital_period(aout_0, Mtriple)

    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Pout=", Pout.in_(units.Myr)

    converter = nbody_system.nbody_to_si(triple.mass.sum(), aout_0)
    gravity = Huayno(converter)
    gravity.particles.add_particles(triple)

    channel_from_framework_to_gd = triple.new_channel_to(gravity.particles)
    channel_from_gd_to_framework = gravity.particles.new_channel_to(triple)

    Etot_init = gravity.kinetic_energy + gravity.potential_energy
    Etot_prev = Etot_init

    gravity.particles.move_to_center()

    time = 0.0 | t_end.unit
    ts = t_stellar + time  # begin when stars have formed after 4.0 Myr years

    ain, ein, aout, eout, iin, iout = get_orbital_elements_of_triple(triple)
    print "Triple elements t=",  time,  \
        "inner:", triple[0].mass, triple[1].mass, ain, ein, iin, \
        "outer:", triple[2].mass, aout, eout, iout

    dt_diag = t_end / float(
        nsteps)  # how often we want to save the generated data
    t_diag = dt_diag

    t = [time.value_in(units.Myr)]
    smai = [ain / ain_0]
    ecci = [ein / ein_0]
    smao = [aout / aout_0]
    ecco = [eout / eout_0]
    inci = [iin]
    inco = [iout]
    ain = ain_0

    def advance_stellar(ts, dt):
        E0 = gravity.kinetic_energy + gravity.potential_energy
        ts += dt
        stellar.evolve_model(ts)
        channel_from_stellar.copy_attributes(["mass"])
        channel_from_framework_to_gd.copy_attributes(["mass"])
        return ts, gravity.kinetic_energy + gravity.potential_energy - E0

    def advance_stellar_with_massloss(
        ts,
        time_framework,
        dt_massloss=15e-9 | units.Myr,
        max_massloss=3e-4
        | units.MSun):  # Scheme 3: dt 8*10^-7, dm = 2*10^-5 (

        max_massloss = 0.0 | units.MSun  # massloss over full gravtiational time step  massloss0
        #max_massloss= 3e-6 | units.MSun # massloss over full gravtiational time step massloss1
        #max_massloss= 1e-6 | units.MSun # massloss over full gravtiational time step massloss2

        E0 = gravity.kinetic_energy + gravity.potential_energy
        massloss = -1 | units.MSun
        mass_0 = numpy.sum(stellar.particles.mass)
        dt_stellar = 0 | units.Myr
        niter = 0
        while massloss < max_massloss:
            ts += dt_massloss
            dt_stellar += dt_massloss  # counter for full time
            niter += 1
            t0 = ctime.time()
            stellar.evolve_model(ts)
            delta_t = ctime.time() - t0
            time_framework += delta_t
            massloss = 2. * (
                mass_0 - numpy.sum(stellar.particles.mass)
            )  # massloss over full gravtiational time step is x2

        channel_from_stellar.copy_attributes(["mass"])
        channel_from_framework_to_gd.copy_attributes(["mass"])

        print 'Tstellar:', dt_stellar, ', Total Mloss:', massloss, ' Niter:', niter

        return ts, time_framework, gravity.kinetic_energy + gravity.potential_energy - E0, dt_stellar

    def advance_gravity(tg, dt):
        tg += dt
        gravity.evolve_model(tg)
        channel_from_gd_to_framework.copy()
        return tg

    global_time = []
    global_massloss = []
    global_dmdt = []
    while time < t_end:

        Pin = orbital_period(ain, triple[0].mass + triple[1].mass)
        dt = dtse_fac * Pin
        dt *= random.random(
        )  # time step is chosen random between 0 and 50*Pin

        if scheme == 1:

            ts, dE_se = advance_stellar(ts, dt)
            time = advance_gravity(time, dt)

        elif scheme == 2:

            time = advance_gravity(time, dt)
            ts, dE_se = advance_stellar(ts, dt)

        elif scheme == 3:

            # inital mass
            mass_init = stellar.particles.mass.sum()

            # perform step
            ts, dE_se = advance_stellar(ts, dt / 2)
            time = advance_gravity(time, dt)
            ts, dE = advance_stellar(ts, dt / 2)
            dE_se += dE

            # add right vlaues
            global_time = numpy.append(global_time, time.value_in(units.Myr))
            global_massloss = numpy.append(
                global_massloss,
                mass_init.value_in(units.MSun) -
                numpy.sum(stellar.particles.mass).value_in(units.MSun))

        else:  # our scheme is 4

            # inital mass
            mass_init = stellar.particles.mass.sum()
            time_init = time.value_in(units.Myr) | units.Myr

            # get optimal dt to perform a time step without losing too much mass
            ts, time_framework, dE_se, dt_stellar = advance_stellar_with_massloss(
                ts, time_framework)

            # perform time step dt
            t0 = ctime.time()
            time = advance_gravity(time, dt_stellar * 2)
            ts, dE = advance_stellar(ts, dt_stellar)
            delta_t = ctime.time() - t0
            time_framework += delta_t
            dE_se += dE

            # save everything
            global_time = numpy.append(global_time, time.value_in(units.Myr))
            global_massloss = numpy.append(
                global_massloss,
                mass_init.value_in(units.MSun) -
                numpy.sum(stellar.particles.mass).value_in(units.MSun))
            global_dmdt = numpy.append(
                global_dmdt,
                (mass_init.value_in(units.MSun) -
                 numpy.sum(stellar.particles.mass).value_in(units.MSun)) /
                (time.value_in(units.Myr) - time_init.value_in(units.Myr)))

        if time >= t_diag:

            t_diag = time + dt_diag

            Ekin = gravity.kinetic_energy
            Epot = gravity.potential_energy
            Etot = Ekin + Epot
            dE = Etot_prev - Etot
            Mtot = triple.mass.sum()
            print "T=", time  #,
            #print "M=", Mtot, "(dM[SE]=", Mtot/Mtriple, ")",
            #print "E= ", Etot, "Q= ", Ekin/Epot,
            #print "dE=", (Etot_init-Etot)/Etot, "ddE=", (Etot_prev-Etot)/Etot,
            #print "(dE[SE]=", dE_se/Etot, ")"
            Etot_init -= dE
            Etot_prev = Etot
            ain, ein, aout, eout, iin, iout = get_orbital_elements_of_triple(
                triple)
            #print "Triple elements t=",  (4|units.Myr) + time,  \
            #    "inner:", triple[0].mass, triple[1].mass, ain, ein, \
            #    "outer:", triple[2].mass, aout, eout

            t.append(time.value_in(units.Myr))
            smai.append(ain / ain_0)
            ecci.append(ein / ein_0)
            smao.append(aout / aout_0)
            ecco.append(eout / eout_0)
            inci.append(iin)
            inco.append(iout)

            if eout > 1.0 or aout <= zero:
                print "Binary ionized or merged"
                break

    pyplot.close()

    data = numpy.array(zip(global_time, global_massloss, global_dmdt))
    numpy.save('massloss0', data)

    return t, smai, ecci, smao, ecco, inci, inco, time_framework
Exemplo n.º 48
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, integrator,
                            t_stellar, dt_se, dtse_fac, interp):

    import random
    from amuse.ext.solarsystem import get_position

    numpy.random.seed(42)

    print "Initial masses:", M1, M2, M3
    triple = Particles(3)
    triple[0].mass = M1
    triple[1].mass = M2
    triple[2].mass = M3
    stellar = SeBa()
    stellar.particles.add_particles(triple)
    channel_from_stellar = stellar.particles.new_channel_to(triple)

    # Evolve to t_stellar.
    
    stellar.evolve_model(t_stellar)
    channel_from_stellar.copy_attributes(["mass"])
    M1 = triple[0].mass
    M2 = triple[1].mass
    M3 = triple[2].mass
    print "t=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "R=", stellar.particles.radius.in_(units.RSun)
    print "L=", stellar.particles.luminosity.in_(units.LSun)
    print "T=", stellar.particles.temperature.in_(units.K)
    print "Mdot=", \
        -stellar.particles.wind_mass_loss_rate.in_(units.MSun/units.yr)

    # Start the dynamics.
    # Inner binary:
    
    tmp_stars = Particles(2)
    tmp_stars[0].mass = M1
    tmp_stars[1].mass = M2

    if Pora == 1:
        ain_0 = semimajor_axis(Pin_0, M1+M2)
    else:
        Pin_0 = orbital_period(ain_0, M1+M2)
    print 'Pin =', Pin_0
        
    print 'ain_0 =', ain_0
    print 'M1+M2 =', M1+M2
    print 'Pin_0 =', Pin_0.value_in(units.day), '[day]'
    #print 'semi:', semimajor_axis(Pin_0, M1+M2).value_in(units.AU), 'AU'
    #print 'period:', orbital_period(ain_0, M1+M2).value_in(units.day), '[day]'
    
    dt_init = 0.01*Pin_0
    ma = 180
    inc = 60
    aop = 180
    lon = 0
    r,v = get_position(M1, M2, ein_0, ain_0, ma, inc, aop, lon, dt_init)
    tmp_stars[1].position = r
    tmp_stars[1].velocity = v
    tmp_stars.move_to_center()

    # Outer binary:
    
    r,v = get_position(M1+M2, M3, eout_0, aout_0, 0, 0, 0, 0, dt_init)
    tertiary = Particle()
    tertiary.mass = M3
    tertiary.position = r
    tertiary.velocity = v
    tmp_stars.add_particle(tertiary)
    tmp_stars.move_to_center()

    triple.position = tmp_stars.position
    triple.velocity = tmp_stars.velocity

    Mtriple = triple.mass.sum()
    Pout = orbital_period(aout_0, Mtriple)

    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Pout=", Pout.in_(units.Myr)
    print 'tK =', ((M1+M2)/M3)*Pout**2*(1-eout_0**2)**1.5/Pin_0

    converter = nbody_system.nbody_to_si(triple.mass.sum(), aout_0)

    if integrator == 0:
        gravity = Hermite(converter)
        gravity.parameters.timestep_parameter = 0.01
    elif integrator == 1:
        gravity = SmallN(converter)
        gravity.parameters.timestep_parameter = 0.01
        gravity.parameters.full_unperturbed = 0
    elif integrator == 2:
        gravity = Huayno(converter)
        gravity.parameters.inttype_parameter = 20
        gravity.parameters.timestep = (1./256)*Pin_0
    else:
        gravity = symple(converter)
        gravity.parameters.integrator = 10
        #gravity.parameters.timestep_parameter = 0.
        gravity.parameters.timestep = (1./128)*Pin_0

    print gravity.parameters

    gravity.particles.add_particles(triple)
    channel_from_framework_to_gd = triple.new_channel_to(gravity.particles)
    channel_from_gd_to_framework = gravity.particles.new_channel_to(triple)
    
    Etot_init = gravity.kinetic_energy + gravity.potential_energy
    Etot_prev = Etot_init

    gravity.particles.move_to_center()

    # Note: time = t_diag = 0 at the start of the dynamical integration.
    
    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag
    time = 0.0 | t_end.unit
    t_se = t_stellar + time

    print 't_end =', t_end
    print 'dt_diag =', dt_diag

    ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
    print "Triple elements t=",  time,  \
        "inner:", triple[0].mass, triple[1].mass, ain, ein, \
        "outer:", triple[2].mass, aout, eout

    t = [time.value_in(units.Myr)]
    Mtot = triple.mass.sum()
    mtot = [Mtot.value_in(units.MSun)]
    smai = [ain/ain_0] 
    ecci = [ein/ein_0]
    smao = [aout/aout_0] 
    ecco = [eout/eout_0]

    if interp:
        
        # Create arrays of stellar times and masses for interpolation.

        times = [time]
        masses = [triple.mass.copy()]
        while time < t_end:
            time += dt_se
            stellar.evolve_model(t_stellar+time)
            channel_from_stellar.copy_attributes(["mass"])
            times.append(time)
            masses.append(triple.mass.copy())

        time = 0.0 | t_end.unit
        print '\ntimes:', times, '\n'

    # Evolve the system.
    
    def advance_stellar(t_se, dt):
        E0 = gravity.kinetic_energy + gravity.potential_energy
        t_se += dt

        if interp:
            t = t_se-t_stellar
            i = int(t/dt_se)
            mass = masses[i] + (t-times[i])*(masses[i+1]-masses[i])/dt_se
            triple.mass = mass
            #print 't_se =', t_se, 'masses =', mass
        else:
            stellar.evolve_model(t_se)
            channel_from_stellar.copy_attributes(["mass"])

        channel_from_framework_to_gd.copy_attributes(["mass"])
        return t_se, gravity.kinetic_energy + gravity.potential_energy - E0

    def advance_gravity(tg, dt):
        tg += dt
        gravity.evolve_model(tg)
        channel_from_gd_to_framework.copy()
        return tg

    while time < t_end:

        if scheme == 1:

            # Advance to the next diagnostic time.
            
            dE_se = zero
            dt = t_diag - time

            if dt > 0|dt.unit:
                time = advance_gravity(time, dt)

        elif scheme == 2:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                t_se, dE_se = advance_stellar(t_se, dt)
                time = advance_gravity(time, dt)
            
        elif scheme == 3:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                time = advance_gravity(time, dt)
                t_se, dE_se = advance_stellar(t_se, dt)
            
        elif scheme == 4:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                t_se, dE_se = advance_stellar(t_se, 0.5*dt)
                time = advance_gravity(time, dt)
                t_se, dE_se2 = advance_stellar(t_se, 0.5*dt)
                dE_se += dE_se2
            
        elif scheme == 5:

            # Use the specified dt_se.
            
            dE_se = zero
            dt = dt_se
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:

                # For use with symple only: set up average mass loss.
    
                channel_from_stellar.copy_attributes(["mass"])
                m0 = triple.mass.copy()
                stellar.evolve_model(t_se+dt)
                channel_from_stellar.copy_attributes(["mass"])
                t_se = stellar.model_time
                m1 = triple.mass
                dmdt = (m1-m0)/dt
                for i in range(len(dmdt)):
                    gravity.set_dmdt(i, dmdt[i])

                time = advance_gravity(time, dt)

        else:

            print 'unknown option'
            sys.exit(0)

        if time >= t_diag:
            
            t_diag = time + dt_diag

            Ekin = gravity.kinetic_energy 
            Epot = gravity.potential_energy
            Etot = Ekin + Epot
            dE = Etot_prev - Etot
            Mtot = triple.mass.sum()
            print "T=", time, 
            print "M=", Mtot, "(dM[SE]=", Mtot/Mtriple, ")",
            print "E= ", Etot, "Q= ", Ekin/Epot,
            print "dE=", (Etot_init-Etot)/Etot, "ddE=", (Etot_prev-Etot)/Etot, 
            print "(dE[SE]=", dE_se/Etot, ")"
            Etot_init -= dE
            Etot_prev = Etot
            ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
            print "Triple elements t=",  t_stellar + time,  \
                "inner:", triple[0].mass, triple[1].mass, ain, ein, \
                "outer:", triple[2].mass, aout, eout

            t.append(time.value_in(units.yr))
            mtot.append(Mtot.value_in(units.MSun))
            smai.append(ain/ain_0)
            ecci.append(ein/ein_0)
            smao.append(aout/aout_0)
            ecco.append(eout/eout_0)

            if eout > 1 or aout <= zero:
                print "Binary ionized or merged"
                break

    gravity.stop()
    stellar.stop()

    return t, mtot, smai, ecci, smao, ecco
Exemplo n.º 49
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, integrator,
                            t_stellar, dt_se, dtse_fac, interp):

    import random
    from amuse.ext.solarsystem import get_position

    numpy.random.seed(42)

    print("Initial masses:", M1, M2, M3)
    triple = Particles(3)
    triple[0].mass = M1
    triple[1].mass = M2
    triple[2].mass = M3
    stellar = SeBa()
    stellar.particles.add_particles(triple)
    channel_from_stellar = stellar.particles.new_channel_to(triple)

    # Evolve to t_stellar.
    
    stellar.evolve_model(t_stellar)
    channel_from_stellar.copy_attributes(["mass"])
    M1 = triple[0].mass
    M2 = triple[1].mass
    M3 = triple[2].mass
    print("t=", stellar.model_time.in_(units.Myr))
    print("M=", stellar.particles.mass.in_(units.MSun))
    print("R=", stellar.particles.radius.in_(units.RSun))
    print("L=", stellar.particles.luminosity.in_(units.LSun))
    print("T=", stellar.particles.temperature.in_(units.K))
    print("Mdot=", \
        -stellar.particles.wind_mass_loss_rate.in_(units.MSun/units.yr))

    # Start the dynamics.
    # Inner binary:
    
    tmp_stars = Particles(2)
    tmp_stars[0].mass = M1
    tmp_stars[1].mass = M2

    if Pora == 1:
        ain_0 = semimajor_axis(Pin_0, M1+M2)
    else:
        Pin_0 = orbital_period(ain_0, M1+M2)
    print('Pin =', Pin_0)
        
    print('ain_0 =', ain_0)
    print('M1+M2 =', M1+M2)
    print('Pin_0 =', Pin_0.value_in(units.day), '[day]')
    #print 'semi:', semimajor_axis(Pin_0, M1+M2).value_in(units.AU), 'AU'
    #print 'period:', orbital_period(ain_0, M1+M2).value_in(units.day), '[day]'
    
    dt_init = 0.01*Pin_0
    ma = 180
    inc = 60
    aop = 180
    lon = 0
    r,v = get_position(M1, M2, ein_0, ain_0, ma, inc, aop, lon, dt_init)
    tmp_stars[1].position = r
    tmp_stars[1].velocity = v
    tmp_stars.move_to_center()

    # Outer binary:
    
    r,v = get_position(M1+M2, M3, eout_0, aout_0, 0, 0, 0, 0, dt_init)
    tertiary = Particle()
    tertiary.mass = M3
    tertiary.position = r
    tertiary.velocity = v
    tmp_stars.add_particle(tertiary)
    tmp_stars.move_to_center()

    triple.position = tmp_stars.position
    triple.velocity = tmp_stars.velocity

    Mtriple = triple.mass.sum()
    Pout = orbital_period(aout_0, Mtriple)

    print("T=", stellar.model_time.in_(units.Myr))
    print("M=", stellar.particles.mass.in_(units.MSun))
    print("Pout=", Pout.in_(units.Myr))
    print('tK =', ((M1+M2)/M3)*Pout**2*(1-eout_0**2)**1.5/Pin_0)

    converter = nbody_system.nbody_to_si(triple.mass.sum(), aout_0)

    if integrator == 0:
        gravity = Hermite(converter)
        gravity.parameters.timestep_parameter = 0.01
    elif integrator == 1:
        gravity = SmallN(converter)
        gravity.parameters.timestep_parameter = 0.01
        gravity.parameters.full_unperturbed = 0
    elif integrator == 2:
        gravity = Huayno(converter)
        gravity.parameters.inttype_parameter = 20
        gravity.parameters.timestep = (1./256)*Pin_0
    else:
        gravity = symple(converter)
        gravity.parameters.integrator = 10
        #gravity.parameters.timestep_parameter = 0.
        gravity.parameters.timestep = (1./128)*Pin_0

    print(gravity.parameters)

    gravity.particles.add_particles(triple)
    channel_from_framework_to_gd = triple.new_channel_to(gravity.particles)
    channel_from_gd_to_framework = gravity.particles.new_channel_to(triple)
    
    Etot_init = gravity.kinetic_energy + gravity.potential_energy
    Etot_prev = Etot_init

    gravity.particles.move_to_center()

    # Note: time = t_diag = 0 at the start of the dynamical integration.
    
    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag
    time = 0.0 | t_end.unit
    t_se = t_stellar + time

    print('t_end =', t_end)
    print('dt_diag =', dt_diag)

    ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
    print("Triple elements t=",  time,  \
        "inner:", triple[0].mass, triple[1].mass, ain, ein, \
        "outer:", triple[2].mass, aout, eout)

    t = [time.value_in(units.Myr)]
    Mtot = triple.mass.sum()
    mtot = [Mtot.value_in(units.MSun)]
    smai = [ain/ain_0] 
    ecci = [ein/ein_0]
    smao = [aout/aout_0] 
    ecco = [eout/eout_0]

    if interp:
        
        # Create arrays of stellar times and masses for interpolation.

        times = [time]
        masses = [triple.mass.copy()]
        while time < t_end:
            time += dt_se
            stellar.evolve_model(t_stellar+time)
            channel_from_stellar.copy_attributes(["mass"])
            times.append(time)
            masses.append(triple.mass.copy())

        time = 0.0 | t_end.unit
        print('\ntimes:', times, '\n')

    # Evolve the system.
    
    def advance_stellar(t_se, dt):
        E0 = gravity.kinetic_energy + gravity.potential_energy
        t_se += dt

        if interp:
            t = t_se-t_stellar
            i = int(t/dt_se)
            mass = masses[i] + (t-times[i])*(masses[i+1]-masses[i])/dt_se
            triple.mass = mass
            #print 't_se =', t_se, 'masses =', mass
        else:
            stellar.evolve_model(t_se)
            channel_from_stellar.copy_attributes(["mass"])

        channel_from_framework_to_gd.copy_attributes(["mass"])
        return t_se, gravity.kinetic_energy + gravity.potential_energy - E0

    def advance_gravity(tg, dt):
        tg += dt
        gravity.evolve_model(tg)
        channel_from_gd_to_framework.copy()
        return tg

    while time < t_end:

        if scheme == 1:

            # Advance to the next diagnostic time.
            
            dE_se = zero
            dt = t_diag - time

            if dt > 0|dt.unit:
                time = advance_gravity(time, dt)

        elif scheme == 2:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                t_se, dE_se = advance_stellar(t_se, dt)
                time = advance_gravity(time, dt)
            
        elif scheme == 3:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                time = advance_gravity(time, dt)
                t_se, dE_se = advance_stellar(t_se, dt)
            
        elif scheme == 4:
            
            # Derive dt from Pin using dtse_fac.
            
            dt = dtse_fac*Pin_0
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:
                t_se, dE_se = advance_stellar(t_se, 0.5*dt)
                time = advance_gravity(time, dt)
                t_se, dE_se2 = advance_stellar(t_se, 0.5*dt)
                dE_se += dE_se2
            
        elif scheme == 5:

            # Use the specified dt_se.
            
            dE_se = zero
            dt = dt_se
            if time + dt > t_diag: dt = t_diag - time

            if dt > 0|dt.unit:

                # For use with symple only: set up average mass loss.
    
                channel_from_stellar.copy_attributes(["mass"])
                m0 = triple.mass.copy()
                stellar.evolve_model(t_se+dt)
                channel_from_stellar.copy_attributes(["mass"])
                t_se = stellar.model_time
                m1 = triple.mass
                dmdt = (m1-m0)/dt
                for i in range(len(dmdt)):
                    gravity.set_dmdt(i, dmdt[i])

                time = advance_gravity(time, dt)

        else:

            print('unknown option')
            sys.exit(0)

        if time >= t_diag:
            
            t_diag = time + dt_diag

            Ekin = gravity.kinetic_energy 
            Epot = gravity.potential_energy
            Etot = Ekin + Epot
            dE = Etot_prev - Etot
            Mtot = triple.mass.sum()
            print("T=", time, end=' ') 
            print("M=", Mtot, "(dM[SE]=", Mtot/Mtriple, ")", end=' ')
            print("E= ", Etot, "Q= ", Ekin/Epot, end=' ')
            print("dE=", (Etot_init-Etot)/Etot, "ddE=", (Etot_prev-Etot)/Etot, end=' ') 
            print("(dE[SE]=", dE_se/Etot, ")")
            Etot_init -= dE
            Etot_prev = Etot
            ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
            print("Triple elements t=",  t_stellar + time,  \
                "inner:", triple[0].mass, triple[1].mass, ain, ein, \
                "outer:", triple[2].mass, aout, eout)

            t.append(time.value_in(units.yr))
            mtot.append(Mtot.value_in(units.MSun))
            smai.append(ain/ain_0)
            ecci.append(ein/ein_0)
            smao.append(aout/aout_0)
            ecco.append(eout/eout_0)

            if eout > 1 or aout <= zero:
                print("Binary ionized or merged")
                break

    gravity.stop()
    stellar.stop()

    return t, mtot, smai, ecci, smao, ecco
Exemplo n.º 50
0
def testhuayno(N=100, fd=1.6, seed=1234567):

    parts = new_fractal_cluster_model(N=N,
                                      fractal_dimension=fd,
                                      random_seed=seed)

    #  parts.z*=0
    #  parts.vz*=0

    def distfunc(p, q):
        return timestep(p, q, _G=nbody_system.G)

    f = pyplot.figure(figsize=(8, 8))
    pyplot.plot(parts.x.number, parts.y.number, 'r.')
    pyplot.xlim(-1, 1)
    pyplot.ylim(-1, 1)
    pyplot.savefig("fractal-%3.1f.png" % fd)

    i = 0
    cc = []
    newparts = parts
    while len(cc) < len(parts):
        tcurrent = 1. / 2**i | nbody_system.time
        #    lcurrent=1./2**i |  nbody_system.length
        parts = newparts
        graph, cc = connected_components(parts,
                                         treshold=tcurrent,
                                         distfunc=distfunc)
        #    graph,cc=connected_components(parts,treshold=lcurrent)

        print i, tcurrent, len(cc), len(parts)

        if len(cc) > 1:
            f = pyplot.figure(figsize=(8, 8))
            alledges = graph.all_edges()
            for e in alledges:
                pyplot.plot([e[2].x.number, e[1].x.number],
                            [e[2].y.number, e[1].y.number],
                            'grey',
                            linewidth=0.5)
            for ip, iparts in enumerate(cc):
                for p in iparts:
                    pyplot.plot(p.x.number,
                                p.y.number,
                                'k.',
                                markersize=8.,
                                mew=.5)
            pyplot.xlim(-1.2, 1.2)
            pyplot.ylim(-1.2, 1.2)

            single = 0
            for s in cc:
                if len(s) == 1:
                    single += 1

            binary = 0
            for s in cc:
                if len(s) == 2:
                    binary += 1

            pyplot.text(0.6, -.85, "level: %2i" % i, fontsize=16)
            pyplot.text(0.6, -.95, "#cc: %i" % len(cc), fontsize=16)
            pyplot.text(0.6,
                        -1.05,
                        "#s,b: %i,%i" % (single, binary),
                        fontsize=16)
            pyplot.text(0.6, -1.15, "#parts: %i" % len(parts), fontsize=16)

            pyplot.savefig("cc-%3.1f-%3.3i.png" % (fd, i))

            newparts = Particles()
            for s in cc:
                if len(s) > 2:
                    for p in s:
                        newparts.add_particle(p)

        i += 1
    print len(cc), len(parts)
Exemplo n.º 51
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, dtse_fac):

    import random
    from amuse.ext.solarsystem import get_position

    print "Initial masses:", M1, M2, M3
    t_stellar = 4.0|units.Myr
    triple = Particles(3)
    triple[0].mass = M1
    triple[1].mass = M2
    triple[2].mass = M3
    stellar = SeBa()
    stellar.particles.add_particles(triple)
    channel_from_stellar = stellar.particles.new_channel_to(triple)
    stellar.evolve_model(t_stellar)
    channel_from_stellar.copy_attributes(["mass"])
    M1 = triple[0].mass
    M2 = triple[1].mass
    M3 = triple[2].mass
    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Masses at time T:", M1, M2, M3
    
    # Inner binary
    
    tmp_stars = Particles(2)
    tmp_stars[0].mass = M1
    tmp_stars[1].mass = M2

    if Pora == 1:
        ain_0 = semimajor_axis(Pin_0, M1+M2)
    else:
        Pin_0 = orbital_period(ain_0, M1+M2)
        
    print 'ain_0 =', ain_0
    print 'M1+M2 =', M1+M2
    print 'Pin_0 =', Pin_0.value_in(units.day), '[day]'
    #print 'semi:', semimajor_axis(Pin_0, M1+M2).value_in(units.AU), 'AU'
    #print 'period:', orbital_period(ain_0, M1+M2).value_in(units.day), '[day]'
    
    dt = 0.1*Pin_0
    ma = 180
    inc = 30
    aop = 180
    lon = 0
    r, v = get_position(M1, M2, ein_0, ain_0, ma, inc, aop, lon, dt)
    tmp_stars[1].position = r
    tmp_stars[1].velocity = v
    tmp_stars.move_to_center()

    # Outer binary
    
    r, v = get_position(M1+M2, M3, eout_0, aout_0, 0, 0, 0, 0, dt)
    tertiary = Particle()
    tertiary.mass = M3
    tertiary.position = r
    tertiary.velocity = v
    tmp_stars.add_particle(tertiary)
    tmp_stars.move_to_center()

    triple.position = tmp_stars.position
    triple.velocity = tmp_stars.velocity

    Mtriple = triple.mass.sum()
    Pout = orbital_period(aout_0, Mtriple)

    print "T=", stellar.model_time.in_(units.Myr)
    print "M=", stellar.particles.mass.in_(units.MSun)
    print "Pout=", Pout.in_(units.Myr)

    converter = nbody_system.nbody_to_si(triple.mass.sum(), aout_0)
    gravity = Hermite(converter)
    gravity.particles.add_particles(triple)

    channel_from_framework_to_gd = triple.new_channel_to(gravity.particles)
    channel_from_gd_to_framework = gravity.particles.new_channel_to(triple)
    
    Etot_init = gravity.kinetic_energy + gravity.potential_energy
    Etot_prev = Etot_init

    gravity.particles.move_to_center()

    time = 0.0 | t_end.unit
    ts = t_stellar + time

    ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
    print "Triple elements t=",  time,  \
        "inner:", triple[0].mass, triple[1].mass, ain, ein, \
        "outer:", triple[2].mass, aout, eout

    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag

    t = [time.value_in(units.Myr)] 
    smai = [ain/ain_0] 
    ecci = [ein/ein_0]
    smao = [aout/aout_0] 
    ecco = [eout/eout_0]
    ain = ain_0

    def advance_stellar(ts, dt):
        E0 = gravity.kinetic_energy + gravity.potential_energy
        ts += dt
        stellar.evolve_model(ts)
        channel_from_stellar.copy_attributes(["mass"])
        channel_from_framework_to_gd.copy_attributes(["mass"])
        return ts, gravity.kinetic_energy + gravity.potential_energy - E0

    def advance_gravity(tg, dt):
        tg += dt
        gravity.evolve_model(tg)
        channel_from_gd_to_framework.copy()
        return tg

    while time < t_end:

        Pin = orbital_period(ain, triple[0].mass+triple[1].mass)
        dt = dtse_fac*Pin
        dt *= random.random()

        if scheme == 1:
            
            ts, dE_se = advance_stellar(ts, dt)
            time = advance_gravity(time, dt)
            
        elif scheme == 2:
            
            time = advance_gravity(time, dt)
            ts, dE_se = advance_stellar(ts, dt)
            
        else:

            dE_se = zero
            #ts, dE_se = advance_stellar(ts, dt/2)
            time = advance_gravity(time, dt)
            #ts, dE = advance_stellar(ts, dt/2)
            #dE_se += dE

        if time >= t_diag:
            
            t_diag = time + dt_diag

            Ekin = gravity.kinetic_energy 
            Epot = gravity.potential_energy
            Etot = Ekin + Epot
            dE = Etot_prev - Etot
            Mtot = triple.mass.sum()
            print "T=", time, 
            print "M=", Mtot, "(dM[SE]=", Mtot/Mtriple, ")",
            print "E= ", Etot, "Q= ", Ekin/Epot,
            print "dE=", (Etot_init-Etot)/Etot, "ddE=", (Etot_prev-Etot)/Etot, 
            print "(dE[SE]=", dE_se/Etot, ")"
            Etot_init -= dE
            Etot_prev = Etot
            ain, ein, aout, eout = get_orbital_elements_of_triple(triple)
            print "Triple elements t=",  (4|units.Myr) + time,  \
                "inner:", triple[0].mass, triple[1].mass, ain, ein, \
                "outer:", triple[2].mass, aout, eout

            t.append(time.value_in(units.Myr))
            smai.append(ain/ain_0)
            ecci.append(ein/ein_0)
            smao.append(aout/aout_0)
            ecco.append(eout/eout_0)

            if eout > 1.0 or aout <= zero:
                print "Binary ionized or merged"
                break

    gravity.stop()
    stellar.stop()

    return t, smai, ecci, smao, ecco