def test6(self): print "Test with different masses" # Particles on a cubic grid with masses according to a gaussian density profile grid = numpy.mgrid[-1:1:21j, -1:1:21j, -1:1:21j] | units.m particles = Particles(9261, x=grid[0], y=grid[1], z=grid[2]) peak_positions = [[0.2, -0.4, 0.3], [-0.6, 0.2, 0.7]] | units.m particles.mass = 2*numpy.exp(-(particles.position-peak_positions[0]).lengths_squared() / (0.1|units.m**2)) | units.kg particles.mass += numpy.exp(-(particles.position-peak_positions[1]).lengths_squared() / (0.1|units.m**2)) | units.kg self.assertAlmostEquals(particles.position[particles.mass.argmax()], peak_positions[0]) self.assertAlmostEquals(particles[:4000].position[particles[:4000].mass.argmax()], peak_positions[1]) hop = Hop(unit_converter=nbody_system.nbody_to_si(particles.mass.sum(), 1.0 | units.m))#, redirection="none") hop.parameters.density_method = 2 hop.parameters.number_of_neighbors_for_local_density = 50 hop.parameters.relative_saddle_density_threshold = True hop.commit_parameters() hop.particles.add_particles(particles) hop.calculate_densities() self.assertAlmostEquals(hop.particles.position[hop.particles.density.argmax()], peak_positions[0]) self.assertAlmostEquals(hop.particles[:4000].position[hop.particles[:4000].density.argmax()], peak_positions[1]) hop.do_hop() groups = list(hop.groups()) self.assertEquals(len(groups), 2) for group, peak_position in zip(groups, peak_positions): self.assertAlmostEquals(group.center_of_mass(), peak_position, 1) hop.stop()
def test6(self): print("Test with different masses") # Particles on a cubic grid with masses according to a gaussian density profile grid = numpy.mgrid[-1:1:21j, -1:1:21j, -1:1:21j] | units.m particles = Particles(9261, x=grid[0].flatten(), y=grid[1].flatten(), z=grid[2].flatten()) peak_positions = [[0.2, -0.4, 0.3], [-0.6, 0.2, 0.7]] | units.m particles.mass = 2*numpy.exp(-(particles.position-peak_positions[0]).lengths_squared() / (0.1|units.m**2)) | units.kg particles.mass += numpy.exp(-(particles.position-peak_positions[1]).lengths_squared() / (0.1|units.m**2)) | units.kg self.assertAlmostEqual(particles.position[particles.mass.argmax()], peak_positions[0]) self.assertAlmostEqual(particles[:4000].position[particles[:4000].mass.argmax()], peak_positions[1]) hop = Hop(unit_converter=nbody_system.nbody_to_si(particles.mass.sum(), 1.0 | units.m))#, redirection="none") hop.parameters.density_method = 2 hop.parameters.number_of_neighbors_for_local_density = 50 hop.parameters.relative_saddle_density_threshold = True hop.commit_parameters() hop.particles.add_particles(particles) hop.calculate_densities() self.assertAlmostEqual(hop.particles.position[hop.particles.density.argmax()], peak_positions[0]) self.assertAlmostEqual(hop.particles[:4000].position[hop.particles[:4000].density.argmax()], peak_positions[1]) hop.do_hop() groups = list(hop.groups()) self.assertEqual(len(groups), 2) for group, peak_position in zip(groups, peak_positions): self.assertAlmostEqual(group.center_of_mass(), peak_position, 1) hop.stop()
def create_star(self, N=1): star = Particles(N) star.mass = 2 | units.MSun star.radius = 2 | units.RSun star.temperature = 5000 | units.K star.position = [1, 1, 1] | units.parsec star.velocity = [-1000, 0, 1000] | units.ms star.wind_mass_loss_rate = 1e-6 | units.MSun / units.yr star.initial_wind_velocity = 50 | units.ms star.terminal_wind_velocity = 500 | units.ms return star
def new_cluster(number_of_stars = 1000): masses = new_salpeter_mass_distribution( number_of_stars, mass_min = 0.1 | units.MSun, mass_max = 125.0 | units.MSun, alpha = -2.35 ) particles = Particles(number_of_stars) particles.mass = masses particles.x = units.parsec(random.gamma(2.0, 1.0, number_of_stars)) particles.y = units.parsec(random.gamma(1.0, 1.0, number_of_stars)) particles.z = units.parsec(random.random(number_of_stars)) return particles
def test1(self): print "First test: adding particles, setting and getting." hop = Hop() particles = Particles(6) particles.mass = 1.0 | nbody_system.mass particles.x = [i*i for i in range(6)] | nbody_system.length particles.y = 0.0 | nbody_system.length particles.z = 0.0 | nbody_system.length hop.particles.add_particles(particles) positions = hop.particles.position for i in range(6): x, y, z = positions[i] self.assertEquals(x, i*i | nbody_system.length) self.assertEquals(y, 0 | nbody_system.length) self.assertEquals(z, 0 | nbody_system.length) hop.stop()
def nbodies(centralmass, *orbiting): """ Parameters ---------- centralmass: mass of the central body orbiting: dictionary with args/kwargs to create binary from elements """ bodies = Particles() centralbody = Particle(mass = centralmass) bodies.add_particle(centralbody) for body in orbiting: mass = body['mass'] elements = body['elements'] twobody = new_binary_from_elements(centralmass, mass, **elements) bodies.add_particle(twobody[1]) return bodies
def twobodies_circular(mass1, mass2, sma): """ Sets up a two-body system with zero eccentricity. mass1 : mass of central body mass2 : mass of orbiting body sma : semi-major-axis of the orbit, so here it's just the radius of the circular orbit. Returns ------- Particles instance """ bodies = Particles(2) totalmass = mass1 + mass2 period0 = numpy.sqrt(4.0 * numpy.pi**2 * sma**3 / (constants.G * (totalmass))) angular_frequency = 2.0 * numpy.pi / period0 velocity = angular_frequency * sma position_orbiting_body = [sma.value_in(sma.unit), 0, 0] | sma.unit velocity_orbiting_body = [0, velocity.value_in(velocity.unit), 0 ] | velocity.unit central = bodies[0] central.mass = mass1 central.position = (0.0, 0.0, 0.0) | units.AU central.velocity = (0.0, 0.0, 0.0) | (units.AU / units.s) orbitingbody = bodies[1] orbitingbody.mass = mass2 orbitingbody.position = position_orbiting_body orbitingbody.velocity = velocity_orbiting_body bodies.period0 = period0 bodies.sma0 = sma return bodies
def veras_multiplanet(): """ Initial conditions for multi-planet system as described in: Veras D, MNRAS 431, 1686-1708 (2013), paragraph 2.2 """ endtime = 5e5 | units.yr mdot = 1.244e-5 | (units.MSun / units.yr) mass1 = 7.659 | units.MSun mass2 = 0.001 | units.MSun assert mdot * endtime < mass1 threebody = Particles() twobody1 = new_binary_from_elements(mass1, mass2, 10 | units.AU) twobody2 = new_binary_from_elements(mass1, mass2, 30 | units.AU, eccentricity=0.5) threebody.add_particles(twobody1) threebody.add_particle(twobody2[1]) threebody[0].radius = 363.777818568 | units.RSun threebody[1].radius = 6000 | units.km threebody[2].radius = 6000 | units.km return threebody
def setup_supernova(self): numpy.random.seed(123456789) stars = Particles(2) stars.mass = [9, 10] | units.MSun stars[0].position = [1, 1, 1] | units.parsec stars[1].position = [-1, -1, -1] | units.parsec stars[0].velocity = [-1000, 0, 1000] | units.ms stars[1].velocity = [0, 0, 0] | units.ms stev = SeBa() stars = stev.particles.add_particles(stars) r_max = .1 | units.parsec star_wind = stellar_wind.new_stellar_wind(3e-5 | units.MSun, mode="heating", r_max=r_max, derive_from_evolution=True, tag_gas_source=True) star_wind.particles.add_particles(stars) return stev, star_wind, stars
def test_target_gas(self): star = self.create_star() gas = Particles() star_wind = stellar_wind.new_stellar_wind(1e-8 | units.MSun, target_gas=gas, timestep=1 | units.day) star_wind.particles.add_particles(star) star_wind.evolve_model(1 | units.yr) self.assertEqual(len(gas), 99) star_wind.evolve_model(1.5 | units.yr) self.assertEqual(len(gas), 149)
def twobodies_circular(mass1, mass2, sma): """ Sets up a two-body system with zero eccentricity. mass1 : mass of central body mass2 : mass of orbiting body sma : semi-major-axis of the orbit, so here it's just the radius of the circular orbit. Returns ------- Particles instance """ bodies = Particles(2) totalmass = mass1+mass2 period0 = numpy.sqrt(4.0*numpy.pi**2*sma**3/(constants.G*(totalmass))) angular_frequency = 2.0*numpy.pi / period0 velocity = angular_frequency * sma position_orbiting_body = [sma.value_in(sma.unit), 0, 0] | sma.unit velocity_orbiting_body = [0, velocity.value_in(velocity.unit), 0] | velocity.unit central = bodies[0] central.mass = mass1 central.position = (0.0, 0.0, 0.0) | units.AU central.velocity = (0.0, 0.0, 0.0) | (units.AU / units.s) orbitingbody = bodies[1] orbitingbody.mass = mass2 orbitingbody.position = position_orbiting_body orbitingbody.velocity = velocity_orbiting_body bodies.period0 = period0 bodies.sma0 = sma return bodies
def veras_multiplanet(): """ Initial conditions for multi-planet system as described in: Veras D, MNRAS 431, 1686-1708 (2013), paragraph 2.2 """ endtime = 5e5 |units.yr mdot = 1.244e-5 |(units.MSun/units.yr) mass1 = 7.659 |units.MSun mass2 = 0.001 |units.MSun assert mdot * endtime < mass1 threebody = Particles() twobody1 = new_binary_from_elements(mass1, mass2, 10|units.AU) twobody2 = new_binary_from_elements(mass1, mass2, 30|units.AU, eccentricity=0.5) threebody.add_particles(twobody1) threebody.add_particle(twobody2[1]) threebody[0].radius = 363.777818568 |units.RSun threebody[1].radius = 6000 |units.km threebody[2].radius = 6000 |units.km return threebody
def create_stars_without_wind_attributes(self): stars = Particles(2) stars.mass = 2 | units.MSun stars.radius = 2 | units.RSun stars.temperature = 5000 | units.K stars.luminosity = 2 | units.LSun stars.age = 0 | units.Myr stars[0].position = [1, 1, 1] | units.parsec stars[1].position = [-1, -1, -1] | units.parsec stars[0].velocity = [-1000, 0, 1000] | units.ms stars[1].velocity = [0, 0, 0] | units.ms return stars
def setup_supernova(self): numpy.random.seed(123456789) stars = Particles(2) stars.mass = [9, 10] | units.MSun stars[0].position = [1, 1, 1] | units.parsec stars[1].position = [-1, -1, -1] | units.parsec stars[0].velocity = [-1000, 0, 1000] | units.ms stars[1].velocity = [0, 0, 0] | units.ms stev = SeBa() stars = stev.particles.add_particles(stars) r_max = .1 | units.parsec star_wind = stellar_wind.new_stellar_wind( 3e-5 | units.MSun, mode="heating", r_max=r_max, derive_from_evolution=True, tag_gas_source=True ) star_wind.particles.add_particles(stars) return stev, star_wind, stars
def new_cluster(number_of_stars=1000): masses = new_salpeter_mass_distribution(number_of_stars, mass_min=0.1 | units.MSun, mass_max=125.0 | units.MSun, alpha=-2.35) particles = Particles(number_of_stars) particles.mass = masses particles.x = units.parsec(random.gamma(2.0, 1.0, number_of_stars)) particles.y = units.parsec(random.gamma(1.0, 1.0, number_of_stars)) particles.z = units.parsec(random.random(number_of_stars)) return particles
def test_later_star_add(self): star1 = self.create_star() gas = Particles() star_wind = stellar_wind.new_stellar_wind(1e-8 | units.MSun, target_gas=gas, timestep=1 | units.day) star_wind.particles.add_particles(star1) star_wind.evolve_model(1 | units.yr) self.assertEqual(len(gas), 99) star2 = self.create_star()[0] star2.x = 50 | units.parsec star_wind.particles.add_particle(star2) star_wind.evolve_model(1.5 | units.yr) self.assertEqual(len(gas), 198) star1_gas = gas[gas.x < 25 | units.parsec] star2_gas = gas - star1_gas self.assertEqual(len(star1_gas), 149) self.assertEqual(len(star2_gas), 49)
def sun_and_earth(): """ Sets up a two-body system representing the sun and earth. Returns ------- Particles instance representing the sun and earth. """ bodies = Particles(2) sun = bodies[0] sun.mass = 1.0 | units.MSun sun.position = (0.0, 0.0, 0.0) | units.m sun.velocity = (0.0, 0.0, 0.0) | (units.m / units.s) sun.radius = 1.0 | units.RSun earth = bodies[1] earth.mass = 5.9736e24 | units.kg earth.position = (149.5e6, 0.0, 0.0) | units.km earth.velocity = (0.0, 29800, 0.0) | (units.m / units.s) earth.radius = 6371.0 | units.km return bodies
def test1(self): print "First test: adding particles, setting and getting." hop = Hop() particles = Particles(6) particles.mass = 1.0 | nbody_system.mass particles.x = [i * i for i in range(6)] | nbody_system.length particles.y = 0.0 | nbody_system.length particles.z = 0.0 | nbody_system.length hop.particles.add_particles(particles) positions = hop.particles.position for i in range(6): x, y, z = positions[i] self.assertEquals(x, i * i | nbody_system.length) self.assertEquals(y, 0 | nbody_system.length) self.assertEquals(z, 0 | nbody_system.length) hop.stop()
def nbodies(centralmass, *orbiting): """ Parameters ---------- centralmass: mass of the central body orbiting: dictionary with args/kwargs to create binary from elements """ bodies = Particles() centralbody = Particle(mass=centralmass) bodies.add_particle(centralbody) for body in orbiting: mass = body['mass'] elements = body['elements'] twobody = new_binary_from_elements(centralmass, mass, **elements) bodies.add_particle(twobody[1]) return bodies
def __init__(self, *args, **kwargs): self.particles = Particles() self.model_time = 0 | units.Myr self.mass_loss_rate = 1e-11 | units.MSun / units.yr
def new_stars_from_sink(origin, upper_mass_limit=125 | units.MSun, lower_mass_limit=0.1 | units.MSun, default_radius=0.25 | units.pc, velocity_dispersion=1 | units.kms, logger=None, initial_mass_function="kroupa", distribution="random", randomseed=None, **keyword_arguments): """ Form stars from an origin particle that keeps track of the properties of this region. """ logger = logger or logging.getLogger(__name__) if randomseed is not None: logger.info("setting random seed to %i", randomseed) numpy.random.seed(randomseed) try: initialised = origin.initialised except AttributeError: initialised = False if not initialised: logger.debug("Initialising origin particle %i for star formation", origin.key) next_mass = new_star_cluster( initial_mass_function=initial_mass_function, upper_mass_limit=upper_mass_limit, lower_mass_limit=lower_mass_limit, number_of_stars=1, **keyword_arguments) origin.next_primary_mass = next_mass[0].mass origin.initialised = True if origin.mass < origin.next_primary_mass: logger.debug( "Not enough in star forming region %i to form the next star", origin.key) return Particles() mass_reservoir = origin.mass - origin.next_primary_mass stellar_masses = new_star_cluster( stellar_mass=mass_reservoir, upper_mass_limit=upper_mass_limit, lower_mass_limit=lower_mass_limit, imf=initial_mass_function, ).mass number_of_stars = len(stellar_masses) new_stars = Particles(number_of_stars) new_stars.age = 0 | units.yr new_stars[0].mass = origin.next_primary_mass new_stars[1:].mass = stellar_masses[:-1] origin.next_primary_mass = stellar_masses[-1] new_stars.position = origin.position new_stars.velocity = origin.velocity try: radius = origin.radius except AttributeError: radius = default_radius rho = numpy.random.random(number_of_stars) * radius theta = (numpy.random.random(number_of_stars) * (2 * numpy.pi | units.rad)) phi = (numpy.random.random(number_of_stars) * numpy.pi | units.rad) x = rho * sin(phi) * cos(theta) y = rho * sin(phi) * sin(theta) z = rho * cos(phi) new_stars.x += x new_stars.y += y new_stars.z += z velocity_magnitude = numpy.random.normal( scale=velocity_dispersion.value_in(units.kms), size=number_of_stars, ) | units.kms velocity_theta = (numpy.random.random(number_of_stars) * (2 * numpy.pi | units.rad)) velocity_phi = (numpy.random.random(number_of_stars) * (numpy.pi | units.rad)) vx = velocity_magnitude * sin(velocity_phi) * cos(velocity_theta) vy = velocity_magnitude * sin(velocity_phi) * sin(velocity_theta) vz = velocity_magnitude * cos(velocity_phi) new_stars.vx += vx new_stars.vy += vy new_stars.vz += vz new_stars.origin = origin.key origin.mass -= new_stars.total_mass() return new_stars