Пример #1
0
    def test8(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for extreme cases
        """
        N = 3
        mass1 = (1.2 * numpy.ones(N)) | units.MSun
        mass2 = (0.1, 0.05, 0.003) | units.MSun
        semi_major_axis = (1., 2., 3.) | units.AU
        eccentricity = (0., 0.5, 0.6)
        true_anomaly = (0., 0., 66.)
        inclination = (12., 0., 180.)
        longitude_of_the_ascending_node = (
            0.,
            0.,
            0.,
        )
        argument_of_periapsis = (0., 23., 90.)
        mass12 = []
        rel_position = []
        rel_velocity = []
        for i, arg in enumerate(
                zip(mass1, mass2, semi_major_axis, eccentricity, true_anomaly,
                    inclination, longitude_of_the_ascending_node,
                    argument_of_periapsis)):
            sun_and_comet = new_binary_from_orbital_elements(*arg,
                                                             G=constants.G)
            mass12.append(sun_and_comet[0].mass + sun_and_comet[1].mass)
            rel_position.append(sun_and_comet[1].position -
                                sun_and_comet[0].position)
            rel_velocity.append(sun_and_comet[1].velocity -
                                sun_and_comet[0].velocity)

        # to convert lists to vector quantities
        rel_pos = numpy.array(
            [vec_i.value_in(units.AU) for vec_i in rel_position]) | units.AU
        rel_vel = numpy.array(
            [vec_i.value_in(units.kms) for vec_i in rel_velocity]) | units.kms
        mass_12 = numpy.array([m_i.value_in(units.MSun)
                               for m_i in mass12]) | units.MSun

        semi_major_axis_ext, eccentricity_ext, ta_ext, inclination_ext, \
        longitude_of_the_ascending_node_ext, argument_of_periapsis_ext = \
        orbital_elements_for_rel_posvel_arrays(rel_pos,
                                               rel_vel,
                                               mass_12,
                                               G=constants.G)
        rad_to_deg = 180. / numpy.pi
        for i in range(N):
            self.assertAlmostEqual(semi_major_axis[i].value_in(units.AU),
                                   semi_major_axis_ext[i].value_in(units.AU))
            self.assertAlmostEqual(eccentricity[i], eccentricity_ext[i])
            self.assertAlmostEqual(inclination[i],
                                   rad_to_deg * inclination_ext[i])
            self.assertAlmostEqual(
                longitude_of_the_ascending_node[i],
                rad_to_deg * longitude_of_the_ascending_node_ext[i])
            self.assertAlmostEqual(argument_of_periapsis[i],
                                   rad_to_deg * argument_of_periapsis_ext[i])
            self.assertAlmostEqual(true_anomaly[i], rad_to_deg * ta_ext[i])
Пример #2
0
    def test6(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for N particles 
        with random orbital elements
        """
        numpy.random.seed(666)
        N = 100

        mass_sun = 1. | units.MSun
        mass1 = numpy.ones(N) * mass_sun
        mass2 = numpy.zeros(N) | units.MSun
        semi_major_axis = (-numpy.log(random.random(N))) | units.AU
        eccentricity = random.random(N)
        true_anomaly = 360. * random.random(N) - 180.
        inclination = 180 * random.random(N)
        longitude_of_the_ascending_node = 360 * random.random(N) - 180
        argument_of_periapsis = 360 * random.random(N) - 180

        comets = datamodel.Particles(N)
        for i, arg in enumerate(
                zip(mass1, mass2, semi_major_axis, eccentricity, true_anomaly,
                    inclination, longitude_of_the_ascending_node,
                    argument_of_periapsis)):
            sun_and_comet = new_binary_from_orbital_elements(*arg,
                                                             G=constants.G)
            comets[i].mass = sun_and_comet[1].mass
            comets[i].position = sun_and_comet[1].position
            comets[i].velocity = sun_and_comet[1].velocity

        semi_major_axis_ext, eccentricity_ext, ta_ext, inclination_ext, \
        longitude_of_the_ascending_node_ext, argument_of_periapsis_ext = \
        orbital_elements_for_rel_posvel_arrays(comets.position,
                                               comets.velocity,
                                               comets.mass + mass_sun,
                                               G=constants.G)
        rad_to_deg = 180. / numpy.pi
        for i in range(N):
            self.assertAlmostEqual(semi_major_axis[i].value_in(units.AU),
                                   semi_major_axis_ext[i].value_in(units.AU))
            self.assertAlmostEqual(eccentricity[i], eccentricity_ext[i])
            self.assertAlmostEqual(inclination[i],
                                   rad_to_deg * inclination_ext[i])
            self.assertAlmostEqual(
                longitude_of_the_ascending_node[i],
                rad_to_deg * longitude_of_the_ascending_node_ext[i])
            self.assertAlmostEqual(argument_of_periapsis[i],
                                   rad_to_deg * argument_of_periapsis_ext[i])
            self.assertAlmostEqual(true_anomaly[i], rad_to_deg * ta_ext[i])
Пример #3
0
    def xtest10(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for N particles 
        with random orbital elements, unitless
        """
        numpy.random.seed(666)
        N = 100

        mass_sun = 1.
        mass1 = numpy.ones(N) * mass_sun
        mass2 = numpy.zeros(N)
        semi_major_axis = (-numpy.log(random.random(N)))
        eccentricity = random.random(N)
        true_anomaly = 360. * random.random(N) - 180.
        inclination = 180 * random.random(N)
        longitude_of_the_ascending_node = 360 * random.random(N) - 180
        argument_of_periapsis = 360 * random.random(N) - 180

        comets = datamodel.Particles(N)
        for i, arg in enumerate(
                zip(mass1, mass2, semi_major_axis, eccentricity, true_anomaly,
                    inclination, longitude_of_the_ascending_node,
                    argument_of_periapsis)):
            sun_and_comet = new_binary_from_orbital_elements(*arg, G=1)
            comets[i].mass = sun_and_comet[1].mass
            comets[i].position = sun_and_comet[1].position
            comets[i].velocity = sun_and_comet[1].velocity

        semi_major_axis_ext, eccentricity_ext, ta_ext, inclination_ext, \
        longitude_of_the_ascending_node_ext, argument_of_periapsis_ext = \
        orbital_elements_for_rel_posvel_arrays(comets.position,
                                               comets.velocity,
                                               comets.mass + mass_sun,
                                               G=1)

        self.assertAlmostEqual(semi_major_axis, semi_major_axis_ext)
        self.assertAlmostEqual(eccentricity, eccentricity_ext)
        self.assertAlmostEqual(inclination, inclination_ext)
        self.assertAlmostEqual(longitude_of_the_ascending_node,
                               longitude_of_the_ascending_node_ext)
        self.assertAlmostEqual(argument_of_periapsis,
                               argument_of_periapsis_ext)
        self.assertAlmostEqual(true_anomaly, ta_ext)
Пример #4
0
    def test7(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for the case of one particle
        """
        numpy.random.seed(999)

        mass1 = 0.5 | units.MSun
        mass2 = 0.8 | units.MSun
        sem = 12. | units.AU
        ecc = 0.05
        inc = 20.
        lon = 10.
        arg = 0.4
        ta = 360. * random.random() - 180.

        binary = new_binary_from_orbital_elements(mass1,
                                                  mass2,
                                                  sem,
                                                  ecc,
                                                  ta,
                                                  inc,
                                                  lon,
                                                  arg,
                                                  G=constants.G)

        rel_pos = binary[1].position - binary[0].position
        rel_vel = binary[1].velocity - binary[0].velocity
        mass_12 = binary[1].mass + binary[0].mass
        sem_ext, ecc_ext, ta_ext, inc_ext, lon_ext, arg_ext = \
        orbital_elements_for_rel_posvel_arrays(rel_pos, rel_vel, mass_12, G=constants.G)

        rad_to_deg = 180. / numpy.pi
        self.assertAlmostEqual(sem.value_in(units.AU),
                               sem_ext.value_in(units.AU))
        self.assertAlmostEqual(ecc, ecc_ext)
        self.assertAlmostEqual(inc, rad_to_deg * inc_ext)
        self.assertAlmostEqual(lon, rad_to_deg * lon_ext)
        self.assertAlmostEqual(arg, rad_to_deg * arg_ext)
        self.assertAlmostEqual(ta, rad_to_deg * ta_ext)
Пример #5
0
    def test11(self):
        """
        testing orbital_elements_for_rel_posvel_arrays for unbound orbits
        """

        from amuse.community.kepler.interface import Kepler

        numpy.random.seed(66)
        N = 10

        mass_sun = 1. | units.MSun
        mass1 = numpy.ones(N) * mass_sun
        mass2 = numpy.zeros(N) | units.MSun
        semi_major_axis = -1000. * (random.random(N)) | units.AU
        eccentricity = (1. + random.random(N)) * 10. - 9.
        inclination = numpy.pi * random.random(N)
        longitude_of_the_ascending_node = 2. * numpy.pi * random.random(
            N) - numpy.pi
        argument_of_periapsis = 2. * numpy.pi * random.random(N) - numpy.pi

        # kepler.initialize_from_elements initializes orbits with mean_anomaly=0 and true_anomaly=0
        true_anomaly = 0. * (360. * random.random(N) - 180.)

        comets = datamodel.Particles(N)

        converter = nbody_system.nbody_to_si(1 | units.MSun, 1 | units.AU)
        kepler = Kepler(converter)
        kepler.initialize_code()
        for i, arg in enumerate(
                zip(mass1, mass2, semi_major_axis, eccentricity, true_anomaly,
                    inclination, longitude_of_the_ascending_node,
                    argument_of_periapsis)):
            kepler.initialize_from_elements(mass=(mass1[i] + mass2[i]),
                                            semi=semi_major_axis[i],
                                            ecc=eccentricity[i])
            ri = kepler.get_separation_vector()
            vi = kepler.get_velocity_vector()

            om = longitude_of_the_ascending_node[i]
            w = argument_of_periapsis[i]
            incl = inclination[i]
            a1 = ([numpy.cos(om), -numpy.sin(om),
                   0.0], [numpy.sin(om), numpy.cos(om), 0.0], [0.0, 0.0, 1.0])
            a2 = ([1.0, 0.0, 0.0], [0.0,
                                    numpy.cos(incl), -numpy.sin(incl)],
                  [0.0, numpy.sin(incl), numpy.cos(incl)])
            a3 = ([numpy.cos(w), -numpy.sin(w),
                   0.0], [numpy.sin(w), numpy.cos(w), 0.0], [0.0, 0.0, 1.0])
            A = numpy.dot(numpy.dot(a1, a2), a3)

            r_vec = numpy.dot(A, numpy.reshape(ri, 3, 1))
            v_vec = numpy.dot(A, numpy.reshape(vi, 3, 1))

            r = (0.0, 0.0, 0.0) | units.AU
            v = (0.0, 0.0, 0.0) | (units.AU / units.day)
            r[0] = r_vec[0]
            r[1] = r_vec[1]
            r[2] = r_vec[2]
            v[0] = v_vec[0]
            v[1] = v_vec[1]
            v[2] = v_vec[2]

            comets[i].mass = mass2[i]
            comets[i].position = r_vec
            comets[i].velocity = v_vec

        kepler.stop()

        semi_major_axis_ext, eccentricity_ext, ta_ext, inclination_ext, \
        longitude_of_the_ascending_node_ext, argument_of_periapsis_ext = \
        orbital_elements_for_rel_posvel_arrays(comets.position,
                                               comets.velocity,
                                               comets.mass + mass_sun,
                                               G=constants.G)

        for i in range(N):
            self.assertAlmostEqual(semi_major_axis[i].value_in(units.AU),
                                   semi_major_axis_ext[i].value_in(units.AU))
            self.assertAlmostEqual(eccentricity[i], eccentricity_ext[i])
            self.assertAlmostEqual(inclination[i], inclination_ext[i])
            self.assertAlmostEqual(longitude_of_the_ascending_node[i],
                                   longitude_of_the_ascending_node_ext[i])
            self.assertAlmostEqual(argument_of_periapsis[i],
                                   argument_of_periapsis_ext[i])
            self.assertAlmostEqual(true_anomaly[i], ta_ext[i])
Пример #6
0
def main(options):
    starttime = clocktime.time()
    now = clocktime.strftime("%Y%m%d%H%M%S")

    # Read the initial conditions file provided. This uses "Giant Impact" units.

    mass_unit = options["unit_mass"]
    length_unit = options["unit_length"]
    converter = nbody_system.nbody_to_si(1 | mass_unit, 1 | length_unit)
    options["converter"] = converter

    time = options["time_start"]
    if options["verbose"] > 1:
        print "%d : Start reading particles" % (clocktime.time() - starttime)
    if len(sys.argv) >= 2:
        filename = sys.argv[1]
        ext = filename.split('.')[-1]
        if ext == "txt":
            data = open(filename, "r").readlines()

            time = converter.to_si(float(data[0]) | nbody_system.time)
            nparticles = int(data[1])
            particles = Particles(nparticles)
            for n in range(nparticles):
                line = data[2 + n].split()
                number = int(line[0])
                mass, radius, x, y, z, vx, vy, vz = map(float, line[1:])
                particles[n].number = number
                particles[n].mass = converter.to_si(mass | nbody_system.mass)
                particles[n].radius = converter.to_si(radius
                                                      | nbody_system.length)
                particles[n].position = converter.to_si(
                    VectorQuantity(unit=nbody_system.length, array=[x, y, z]))
                particles[n].velocity = converter.to_si(
                    VectorQuantity(unit=nbody_system.speed, array=[vx, vy,
                                                                   vz]))

            particles.position -= particles.center_of_mass()
            particles.velocity -= particles.center_of_mass_velocity()

            particles[0].type = "planet"
            particles[1:].type = "disc"
            rundir = "./runs/" + filename.split('/')[-1][:-4]
        elif ext == "hdf5":
            particles = read_set_from_file(filename, "amuse")
            rundir = "./runs/" + filename.split('/')[-1][:-5]
        else:
            print "Unknown filetype"
            exit()

    else:
        particles = initial_particles(10000)
        write_set_to_file(
            particles,
            "this_run.hdf5",
            "amuse",
        )
    if options["verbose"] > 1:
        print "%d : Read particles" % (clocktime.time() - starttime)

    rundir += "-%s-%s" % (
        now,
        options["gravity"],
    )
    if options["rubblepile"]:
        rundir += "-rubblepile"

    backupdir = rundir + "/backups"
    plotdir = rundir + "/plots"

    try:
        os.makedirs(rundir)
        os.makedirs(backupdir)
        os.makedirs(plotdir)
        shutil.copy(sys.argv[0], rundir)
    except:
        #FIXME make a new dir in this case, to prevent overwriting old files
        # use a datetime stamp
        print "#directories already present"
        exit()

    particles[0].colour = "blue"
    particles[1:].colour = "black"

    kepler_time = converter.to_si(
        2 * np.pi * ((1 | nbody_system.length)**3 /
                     ((1 | nbody_system.mass) * nbody_system.G))**0.5)

    converter_earthunits = nbody_system.nbody_to_si(1 | units.MEarth,
                                                    1 | units.REarth)

    timestep_k2000 = (kepler_time / (2 * np.pi)) * (2**-9)
    options["timestep"] = timestep_k2000

    if options["verbose"] > 1:
        print "%d : Starting gravity" % (clocktime.time() - starttime)
    # Start up gravity code
    if options["gravity"] == "Rebound":
        gravity = Rebound(converter, redirection="none")
        gravity.parameters.timestep = timestep_k2000
        gravity.parameters.integrator = options["integrator"]
        gravity.parameters.solver = "compensated"
        #gravity.parameters.solver           = "tree"
        #gravity.parameters.opening_angle2   = 0.25
        #gravity.parameters.boundary         = "open"
        #gravity.parameters.boundary_size    = 10|units.REarth
        if options["whfast_corrector"]:
            gravity.parameters.whfast_corrector = options["whfast_corrector"]
    elif options["gravity"] == "Bonsai":
        #gravity = Bonsai(converter,redirection="none")
        gravity = Bonsai(converter, )
        gravity.parameters.timestep = timestep_k2000
        gravity.parameters.opening_angle = 0.5
        #gravity.parameters.epsilon_squared  = (0.1 * particles[-1].radius)**2
        gravity.parameters.epsilon_squared = 0.0 | nbody_system.length**2
    elif options["gravity"] == "Pikachu":
        #gravity = Bonsai(converter,redirection="none")
        gravity = Pikachu(converter, )
        gravity.parameters.timestep = timestep_k2000
        gravity.parameters.opening_angle = 0.5
        #gravity.parameters.epsilon_squared  = (0.1 * particles[-1].radius)**2
        gravity.parameters.epsilon_squared = 0.0 | nbody_system.length**2
    elif options["gravity"] == "ph4":
        if options["use_gpu"]:
            gravity = ph4(converter, mode="gpu", redirection="none")
        else:
            gravity = ph4(converter, redirection="none")
    elif options["gravity"] == "phigrape":
        if options["use_gpu"]:
            gravity = PhiGRAPE(converter, mode="gpu")
        else:
            gravity = PhiGRAPE(converter)
    elif options["gravity"] == "Hermite":
        gravity = Hermite(converter, number_of_workers=6)
        gravity.parameters.dt_min = timestep_k2000
        gravity.parameters.dt_max = timestep_k2000
    else:
        print "Unknown gravity code"
        exit()
    print gravity.parameters

    planetary_disc = Planetary_Disc(options)
    planetary_disc.add_integrator(gravity)
    planetary_disc.add_particles(particles)

    t_start = time
    plot_time = time
    backup_time = time
    timestep = timestep_k2000  #options["timestep"]
    plot_timestep = options["timestep_plot"]
    backup_timestep = options["timestep_backup"]
    t_end = options["time_end"]

    backup = 0
    plot = 0

    log_time = VectorQuantity([], units.s)
    log_kinetic_energy = VectorQuantity([], units.erg)
    log_potential_energy = VectorQuantity([], units.erg)
    log_angular_momentum = VectorQuantity([], units.AU**2 * units.MEarth *
                                          units.yr**-1)

    log = open(rundir + "/log.txt", 'w')
    log.write("#1 time   = %s\n" %
              (converter_earthunits.to_si(1 | nbody_system.time)))
    log.write("#1 length = %s\n" %
              (converter_earthunits.to_si(1 | nbody_system.length)))
    log.write("#1 mass   = %s\n" %
              (converter_earthunits.to_si(1 | nbody_system.mass)))
    log.write("#1 energy = %s\n" %
              (converter_earthunits.to_si(1 | nbody_system.energy)))
    log.write(
        "#Time N E_kin E_pot l2 M_disc a_mean a_sigma e_mean e_sigma inc_mean inc_sigma\n"
    )
    log.write("#%s n %s %s %s %s %s %s\n" % (
        units.s,
        nbody_system.energy,  #s.erg,
        nbody_system.energy,  #s.erg,
        (units.REarth**2 * units.MEarth * units.day**-1)**2,
        units.MEarth,
        units.REarth,
        units.REarth,
    ))
    log.flush()

    time += timestep_k2000
    if options["verbose"] > 1:
        print "%d : Starting loop" % (clocktime.time() - starttime)
    while time < t_end:
        if time >= plot_time:
            if options["verbose"] > 1:
                print "%d : Making plot" % (clocktime.time() - starttime)
            plot_system(
                planetary_disc.particles,
                "%s/plot-%05i.png" % (plotdir, plot),
            )
            plot += 1
            plot_time += plot_timestep
        if time >= backup_time:
            if options["verbose"] > 1:
                print "%d : Making backup" % (clocktime.time() - starttime)
            planetary_disc.write_backup(filename="%s/savefile-%i.hdf5" %
                                        (backupdir, backup))
            backup += 1
            backup_time += backup_timestep
        if (time - planetary_disc.model_time) <= 0.5 * timestep:
            if options["verbose"] > 0:
                print "#Increasing timestep: %s - %s <= 0.5" % (
                    planetary_disc.model_time / planetary_disc.timestep,
                    time / planetary_disc.timestep,
                )
            time += timestep
            kinetic_energy = planetary_disc.kinetic_energy
            potential_energy = planetary_disc.potential_energy
            angular_momentum = planetary_disc.particles.total_angular_momentum(
            )
            semimajor_axis, eccentricity, true_anomaly, inc, long_asc_node, arg_per_mat = orbital_elements_for_rel_posvel_arrays(
                planetary_disc.disc.position - planetary_disc.planet.position,
                planetary_disc.disc.velocity - planetary_disc.planet.velocity,
                planetary_disc.planet.mass,  #total_masses, 
                G=constants.G,
            )
            #FIXME kinetic energy per particle
            #FIXME angular momentum per particle

            log.write("%s %i %s %s %s %s %s %s %s %s %s %s\n" % (
                planetary_disc.model_time.value_in(units.s),
                len(planetary_disc.particles),
                converter_earthunits.to_nbody(kinetic_energy).value_in(
                    nbody_system.energy),
                converter_earthunits.to_nbody(potential_energy).value_in(
                    nbody_system.energy),
                (angular_momentum[0]**2 + angular_momentum[1]**2 +
                 angular_momentum[2]**2).value_in(
                     units.REarth**4 * units.MEarth**2 * units.day**-2),
                planetary_disc.disc.mass.sum().value_in(units.MEarth),
                semimajor_axis.mean().value_in(units.REarth),
                semimajor_axis.std().value_in(units.REarth),
                eccentricity.mean(),
                eccentricity.std(),
                inc.mean(),
                inc.std(),
            ))
            log.flush()
        else:
            if options["verbose"] > 0:
                print "#Not increasing timestep: %s - %s > 0.5" % (
                    planetary_disc.model_time / planetary_disc.timestep,
                    time / planetary_disc.timestep,
                )
        planetary_disc.evolve_model(time)

    gravity.stop()
    log.close()