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)
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
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"
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)
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"
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()
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)
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
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
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
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
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
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])
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
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
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()
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
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
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)
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
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)
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 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
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
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."
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 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 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))
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
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
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))
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])
def local_copy_of_particles(self, primary, secondary): particles = Particles(0) particles.add_particle(primary) particles.add_particle(secondary) return particles
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
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
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
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
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
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
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)