Exemplo n.º 1
0
 class comsystem(baseclass):
    def __init__(self,*args,**kwargs):
      self.particles_accessed=True
      self._particles=Particles(0)
      baseclass.__init__(self,*args,**kwargs)
    
    def evolve_model(self,*args,**kwargs):
      if self.particles_accessed:         
        self.com_position=self._particles.center_of_mass()
        self.com_velocity=self._particles.center_of_mass_velocity()
        com_time=self.model_time
        self._particles.synchronize_to(self.overridden().particles)
        self._particles.new_channel_to(self.overridden().particles).copy_attributes(["mass","radius"])
        self.overridden().particles.position=self._particles.position-self.com_position
        self.overridden().particles.velocity=self._particles.velocity-self.com_velocity
      self.overridden().evolve_model(*args,**kwargs)
      self.com_position+=self.com_velocity*(self.model_time-com_time)        
      self.particles_accessed=False
      
    @property
    def particles(self):
      if not self.particles_accessed:
        self._particles=self.overridden().particles.copy()
        self._particles.position+=self.com_position
        self._particles.velocity+=self.com_velocity
        self.particles_accessed=True
      return self._particles
Exemplo n.º 2
0
    class comsystem(baseclass):
        def __init__(self, *args, **kwargs):
            self.particles_accessed = True
            self._particles = Particles(0)
            baseclass.__init__(self, *args, **kwargs)

        def evolve_model(self, *args, **kwargs):
            if self.particles_accessed:
                self.com_position = self._particles.center_of_mass()
                self.com_velocity = self._particles.center_of_mass_velocity()
                com_time = self.model_time
                self._particles.synchronize_to(self.overridden().particles)
                self._particles.new_channel_to(
                    self.overridden().particles).copy_attributes(
                        ["mass", "radius"])
                self.overridden(
                ).particles.position = self._particles.position - self.com_position
                self.overridden(
                ).particles.velocity = self._particles.velocity - self.com_velocity
            self.overridden().evolve_model(*args, **kwargs)
            self.com_position += self.com_velocity * (self.model_time -
                                                      com_time)
            self.particles_accessed = False

        @property
        def particles(self):
            if not self.particles_accessed:
                self._particles = self.overridden().particles.copy()
                self._particles.position += self.com_position
                self._particles.velocity += self.com_velocity
                self.particles_accessed = True
            return self._particles
    def setup_particles_in_nbodycode(self):
        staggered_grid_shape = numpy.asarray(self.gridcode.grid.shape) + 2
        corner0 = self.gridcode.grid[0][0][0].position
        corner1 = self.gridcode.grid[-1][-1][-1].position

        delta = self.gridcode.grid[1][1][1].position - corner0
        print delta.prod()
        self.volume = delta.prod()
        staggered_corner0 = corner0 - delta
        staggered_corner1 = corner1
        self.staggered_grid = Grid.create(
            staggered_grid_shape,
            staggered_corner1 - staggered_corner0 + delta)
        #self.staggered_grid.x += staggered_corner0.x
        #self.staggered_grid.y += staggered_corner0.x
        #self.staggered_grid.z += staggered_corner0.x

        #self.staggered_grid.p000 = 0.0 | mass
        #self.staggered_grid.p100 = 0.0 | mass
        #self.staggered_grid.p010 = 0.0 | mass
        #self.staggered_grid.p110 = 0.0 | mass
        #self.staggered_grid.p000 = 0.0 | mass
        #self.staggered_grid.p100 = 0.0 | mass
        #self.staggered_grid.p011 = 0.0 | mass
        #self.staggered_grid.p111 = 0.0 | mass
        #self.staggered_grid.p001 = 0.0 | mass
        #self.staggered_grid.p101 = 0.0 | mass

        self.normal_grid = Grid.create(self.gridcode.grid.shape,
                                       corner1 - corner0 + delta)
        particles = Particles(self.normal_grid.size)
        particles.mass = 0.0 | mass
        particles.x = self.grid.x.flatten()
        particles.y = self.grid.y.flatten()
        particles.z = self.grid.z.flatten()
        particles.vx = 0.0 | speed
        particles.vy = 0.0 | speed
        particles.vz = 0.0 | speed
        particles.radius = 0.0 | length

        self.nbodycode.particles.add_particles(particles)
        self.from_model_to_nbody = particles.new_channel_to(
            self.nbodycode.particles)
        self.nbodycode.commit_particles()
        self.particles = particles
    def setup_particles_in_nbodycode(self):
        staggered_grid_shape = numpy.asarray(self.gridcode.grid.shape) + 2
        corner0 = self.gridcode.grid[0][0][0].position
        corner1 = self.gridcode.grid[-1][-1][-1].position

        delta = self.gridcode.grid[1][1][1].position - corner0
        print delta.prod()
        self.volume = delta.prod()
        staggered_corner0 = corner0 - delta
        staggered_corner1 = corner1
        self.staggered_grid = Grid.create(
            staggered_grid_shape,
            staggered_corner1 - staggered_corner0 + delta)
        # self.staggered_grid.x += staggered_corner0.x
        # self.staggered_grid.y += staggered_corner0.x
        # self.staggered_grid.z += staggered_corner0.x

        # self.staggered_grid.p000 = 0.0 | mass
        # self.staggered_grid.p100 = 0.0 | mass
        # self.staggered_grid.p010 = 0.0 | mass
        # self.staggered_grid.p110 = 0.0 | mass
        # self.staggered_grid.p000 = 0.0 | mass
        # self.staggered_grid.p100 = 0.0 | mass
        # self.staggered_grid.p011 = 0.0 | mass
        # self.staggered_grid.p111 = 0.0 | mass
        # self.staggered_grid.p001 = 0.0 | mass
        # self.staggered_grid.p101 = 0.0 | mass

        self.normal_grid = Grid.create(
            self.gridcode.grid.shape, corner1 - corner0 + delta)
        particles = Particles(self.normal_grid.size)
        particles.mass = 0.0 | mass
        particles.x = self.grid.x.flatten()
        particles.y = self.grid.y.flatten()
        particles.z = self.grid.z.flatten()
        particles.vx = 0.0 | speed
        particles.vy = 0.0 | speed
        particles.vz = 0.0 | speed
        particles.radius = 0.0 | length

        self.nbodycode.particles.add_particles(particles)
        self.from_model_to_nbody = particles.new_channel_to(
            self.nbodycode.particles)
        self.nbodycode.commit_particles()
        self.particles = particles
Exemplo n.º 5
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, integrator,
                            t_stellar, dt_se, dtse_fac, interp):

    import random
    from amuse.ext.solarsystem import get_position

    numpy.random.seed(42)

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

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

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

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

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

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

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

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

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

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

    print(gravity.parameters)

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

    gravity.particles.move_to_center()

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

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

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

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

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

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

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

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

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

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

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

    while time < t_end:

        if scheme == 1:

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

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

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

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

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

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

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

            if dt > 0|dt.unit:

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

                time = advance_gravity(time, dt)

        else:

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

        if time >= t_diag:
            
            t_diag = time + dt_diag

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

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

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

    gravity.stop()
    stellar.stop()

    return t, mtot, smai, ecci, smao, ecco
Exemplo n.º 6
0
def main():
    numpy.random.seed(42)
    evo_headstart = 0.0 | units.Myr
    dt_base = 0.001 | units.Myr
    dt = dt_base
    time = 0 | units.Myr
    time_end = 8 | units.Myr
    Tmin = 22 | units.K

    gas_density = 5e3 | units.amu * units.cm**-3

    increase_vol = 2

    Ngas = increase_vol**3 * 10000
    Mgas = increase_vol**3 * 1000 | units.MSun  # Mgas = Ngas | units.MSun
    volume = Mgas / gas_density  # 4/3 * pi * r**3
    radius = (volume / (pi * 4/3))**(1/3)
    radius = increase_vol * radius  # 15 | units.parsec

    gasconverter = nbody_system.nbody_to_si(Mgas, radius)
    # gasconverter = nbody_system.nbody_to_si(1 | units.pc, 1 | units.MSun)
    # gasconverter = nbody_system.nbody_to_si(1e10 | units.cm, 1e10 | units.g)

    # NOTE: make stars first - so that it remains the same random
    # initialisation even when we change the number of gas particles
    if len(sys.argv) > 1:
        gas = read_set_from_file(sys.argv[1], "amuse")
        stars = read_set_from_file(sys.argv[2], "amuse")
        stars.position = stars.position * 3
    else:
        # stars = new_star_cluster(
        #     stellar_mass=1000 | units.MSun, effective_radius=3 | units.parsec
        # )
        # stars.velocity = stars.velocity * 2.0
        from amuse.datamodel import Particles
        Nstars = 100
        stars = Particles(Nstars)
        stars.position = [0, 0, 0] | units.pc
        stars.velocity = [0, 0, 0] | units.kms
        stars.mass = new_kroupa_mass_distribution(Nstars, mass_min=1 | units.MSun).reshape(Nstars)
        #  25 | units.MSun
        gas = molecular_cloud(targetN=Ngas, convert_nbody=gasconverter).result
        # gas.velocity = gas.velocity * 0.5
        gas.u = temperature_to_u(100 | units.K)
    # gas.x = gas.x
    # gas.y = gas.y
    # gas.z = gas.z
    # gas.h_smooth = (gas.mass / gas_density / (4/3) / pi)**(1/3)
    # print(gas.h_smooth.mean())
    # gas = read_set_from_file("gas_initial.hdf5", "amuse")
    # gas.density = gas_density
    # print(gas.h_smooth.mean())
    # exit()
    u_now = gas.u
    #print(gasconverter.to_nbody(gas[0].u))
    #print(constants.kB.value_in(units.erg * units.K**-1))
    #print((constants.kB * 6.02215076e23).value_in(units.erg * units.K**-1))

    #print(gasconverter.to_nbody(temperature_to_u(10 | units.K)))
    #tempiso = 2.d0/3.d0*ui/(Rg/gmwvar/uergg)
    # print(nbody_system.length**2 / nbody_system.time**2)
    # print(gasconverter.to_si(1 | nbody_system.length**2 / nbody_system.time**2).value_in(units.kms**2))
    # print(gasconverter.to_nbody(temperature_to_u(Tmin)))
    # Rg = (constants.kB * 6.02214076e23).value_in(units.erg * units.K**-1)
    # gmwvar = 1.2727272727
    # uergg = nbody_system.length**2 * nbody_system.time**-2
    # uergg = 6.6720409999999996E-8
    # print(Rg)
    # print(
    #     2.0/3.0*gasconverter.to_nbody(temperature_to_u(Tmin))/(Rg/gmwvar/uergg)
    # )
    # #tempiso, ui, Rg, gmwvar, uergg, udist, utime   1.7552962911187030E-018   2.5778500859241771E-003   83140000.000000000        1.2727272727272725        6.6720409999999996E-008   1.0000000000000000        3871.4231866737564
    # u = 3./2. * Tmin.value_in(units.K) * (Rg/gmwvar/uergg)
    # print(u)
    # print(
    #     2.0/3.0*u/(Rg/gmwvar/uergg)
    # )
    # print(u, Rg, gmwvar, uergg)
    # print(temperature_to_u(10 | units.K).value_in(units.kms**2))
    u = temperature_to_u(20 | units.K)
    #print(gasconverter.to_nbody(u))
    #print(u_to_temperature(u).value_in(units.K))
    # exit()
    # gas.u = u | units.kms**2
    # exit()
    
    # print(gasconverter.to_nbody(gas.u.mean()))
    # print(gasconverter.to_si(gas.u.mean()).value_in(units.kms**2))
    # exit()
    gas.du_dt = (u_now - u_now) / dt  # zero, but in the correct units

    # stars = read_set_from_file("stars.amuse", "amuse")
    # write_set_to_file(stars, 'stars.amuse', 'amuse', append_to_file=False)
    # stars.velocity *= 3
    # stars.vx += 0 | units.kms
    # stars.vy += 0 | units.kms

    M = stars.total_mass() + Mgas
    R = stars.position.lengths().mean()
    converter = nbody_system.nbody_to_si(M, R)
    # exit()
    # gas = new_plummer_gas_model(Ngas, gasconverter)
    # gas = molecular_cloud(targetN=Ngas, convert_nbody=gasconverter).result
    # gas.u = temperature_to_u(Tmin)
    # gas = read_set_from_file("gas.amuse", "amuse")
    # print(stars.mass == stars.mass.max())
    print(len(stars.mass))
    print(len(stars.mass == stars.mass.max()))
    print(stars[0])
    print(stars[stars.mass == stars.mass.max()])
    mms = stars[stars.mass == stars.mass.max()]
    print("Most massive star: %s" % mms.mass)
    print("Gas particle mass: %s" % gas[0].mass)

    evo = SeBa()
    # sph = Fi(converter, mode="openmp")
    phantomconverter = nbody_system.nbody_to_si(
        default_settings.gas_rscale,
        default_settings.gas_mscale,
    )
    sph = Phantom(phantomconverter, redirection="none")
    sph.parameters.ieos = 2
    sph.parameters.icooling = 1
    sph.parameters.alpha = 0.1
    sph.parameters.gamma = 5/3
    sph.parameters.rho_crit = 1e17 | units.amu * units.cm**-3
    sph.parameters.h_soft_sinkgas = 0.1 | units.parsec
    sph.parameters.h_soft_sinksink = 0.1 | units.parsec
    sph.parameters.h_acc = 0.1 | units.parsec
    # print(sph.parameters)

    stars_in_evo = evo.particles.add_particles(stars)
    channel_stars_evo_from_code = stars_in_evo.new_channel_to(
        stars,
        attributes=[
            "age", "radius", "mass", "luminosity", "temperature",
            "stellar_type",
        ],
    )
    channel_stars_evo_from_code.copy()

    # try:
    #     sph.parameters.timestep = dt
    # except:
    #     print("SPH code doesn't support setting the timestep")
    sph.parameters.stopping_condition_maximum_density = \
        5e-16 | units.g * units.cm**-3
    # sph.parameters.beta = 1.
    # sph.parameters.C_cour = sph.parameters.C_cour / 4
    # sph.parameters.C_force = sph.parameters.C_force / 4
    print(sph.parameters)
    stars_in_sph = stars.copy()  # sph.sink_particles.add_particles(stars)
    # stars_in_sph = sph.sink_particles.add_particles(stars)
    channel_stars_grav_to_code = stars.new_channel_to(
        # sph.sink_particles,
        # sph.dm_particles,
        stars_in_sph,
        attributes=["mass"]
    )
    channel_stars_grav_from_code = stars_in_sph.new_channel_to(
        stars,
        attributes=["x", "y", "z", "vx", "vy", "vz"],
    )
    # We don't want to accrete gas onto the stars/sinks
    stars_in_sph.radius = 0 | units.RSun
    # stars_in_sph = sph.dm_particles.add_particles(stars)
    # try:
    #     sph.parameters.isothermal_flag = True
    #     sph.parameters.integrate_entropy_flag = False
    #     sph.parameters.gamma = 1
    # except:
    #     print("SPH code doesn't support setting isothermal flag")
    gas_in_code = sph.gas_particles.add_particles(gas)
    # print(gasconverter.to_nbody(gas_in_code[0].u).value_in(nbody_system.specific_energy))
    # ui = temperature_to_u(10 | units.K)
    # Rg = constants.kB * 6.02214179e+23
    # gmwvar = (1.4/1.1) | units.g
    # uergg = 1.# | nbody_system.specific_energy
    # print("gmwvar = %s"%gasconverter.to_si(gmwvar))
    # print("Rg = %s"% gasconverter.to_si(Rg))
    # print("ui = %s"% gasconverter.to_si(ui))
    # #print("uergg = %s"% gasconverter.to_nbody(uergg))
    # print("uergg = %s" % gasconverter.to_si(1 | nbody_system.specific_energy).in_(units.cm**2 * units.s**-2))
    # print("****** %s" % ((2.0/3.0)*ui/(Rg/gmwvar/uergg)) + "*****")
    # print(gasconverter.to_nbody(Rg))
    # print((ui).in_(units.cm**2*units.s**-2))
    # #exit()
    
    # sph.evolve_model(1 | units.day)
    # write_set_to_file(sph.gas_particles, "gas_initial.hdf5", "amuse")
    # exit()

    channel_gas_to_code = gas.new_channel_to(
        gas_in_code,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "u",
        ]
    )
    # mass is never updated, and if sph is in isothermal mode u is not reliable
    channel_gas_from_code = gas_in_code.new_channel_to(
        gas,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "density", "pressure", "rho",
            "u", "h_smooth",
        ],
    )
    channel_gas_from_code.copy()  # Initialise values for density etc

    sph_particle_mass = gas[0].mass  # 0.1 | units.MSun
    r_max = 0.1 | units.parsec

    wind = stellar_wind.new_stellar_wind(
        sph_particle_mass,
        mode="heating",
        r_max=r_max,
        derive_from_evolution=True,
        tag_gas_source=True,
        # target_gas=gas,
        # timestep=dt,
    )
    stars_in_wind = wind.particles.add_particles(stars)
    channel_stars_wind_to_code = stars.new_channel_to(
        stars_in_wind,
        attributes=[
            "x", "y", "z", "vx", "vy", "vz", "age", "radius", "mass",
            "luminosity", "temperature", "stellar_type",
        ],
    )
    channel_stars_wind_to_code.copy()


    # reference_mu = 2.2 | units.amu
    gasvolume = (4./3.) * numpy.pi * (
        gas.position - gas.center_of_mass()
    ).lengths().mean()**3
    rho0 = gas.total_mass() / gasvolume
    print(rho0.value_in(units.g * units.cm**-3))
    # exit()
    # cooling_flag = "thermal_model"
    # cooling = Cooling(
    cooling = SimplifiedThermalModelEvolver(
        # gas_in_code,
        gas,
        Tmin=Tmin,
        # T0=30 | units.K,
        # n0=rho0/reference_mu
    )
    cooling.model_time = sph.model_time
    # cooling_to_code = cooling.particles.new_channel_to(gas

    start_mass = (
        stars.mass.sum()
        + (gas.mass.sum() if not gas.is_empty() else 0 | units.MSun)
    )
    step = 0
    plotnr = 0
    com = stars_in_sph.center_of_mass()
    plot_hydro_and_stars(
        time,
        sph,
        stars=stars,
        sinks=None,
        L=20,
        # N=100,
        filename="phantom-coolthermalwindtestplot-%04i.png" % step,
        title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
        gasproperties=["density", "temperature"],
        # colorbar=True,
        starscale=1,
        offset_x=com[0].value_in(units.parsec),
        offset_y=com[1].value_in(units.parsec),
        thickness=5 | units.parsec,
    )

    dt = dt_base
    sph.parameters.time_step = dt
    delta_t = phantomconverter.to_si(2**(-16) | nbody_system.time)
    print("delta_t: %s" % delta_t.in_(units.day))
    # small_step = True
    small_step = False
    plot_every = 100
    subplot_factor = 10
    subplot_enabled = False
    subplot = 0
    while time < time_end:
        time += dt
        print("Gas mean u: %s" % (gas.u.mean().in_(units.erg/units.MSun)))
        print("Evolving to t=%s (%s)" % (time, gasconverter.to_nbody(time)))
        step += 1
        evo.evolve_model(evo_headstart+time)

        print(evo.particles.stellar_type.max())
        channel_stars_evo_from_code.copy()
        channel_stars_grav_to_code.copy()

        if COOLING:
            channel_gas_from_code.copy()
            cooling.evolve_for(dt/2)
            channel_gas_to_code.copy()
        print(
            "min/max temp in gas: %s %s" % (
                u_to_temperature(gas_in_code.u.min()).in_(units.K),
                u_to_temperature(gas_in_code.u.max()).in_(units.K),
            )
        )
        if small_step:
            # Take small steps until a full timestep is done.
            # Each substep is 2* as long as the last until dt is reached
            print("Doing small steps")
            # print(u_to_temperature(sph.gas_particles[0].u))
            # print(sph.gas_particles[0].u)
            old_dt = dt_base
            substeps = 2**8
            dt = old_dt / substeps
            dt_done = 0 * old_dt
            sph.parameters.time_step = dt
            print("adjusted dt to %s, base dt is %s" % (
                dt.in_(units.Myr),
                dt_base.in_(units.Myr),
                )
            )
            sph.evolve_model(sph.model_time + dt)
            dt_done += dt
            while dt_done < old_dt:
                sph.parameters.time_step = dt
                print("adjusted dt to %s, base dt is %s" % (
                    dt.in_(units.Myr),
                    dt_base.in_(units.Myr),
                    )
                )
                sph.evolve_model(sph.model_time + dt)
                dt_done += dt
                dt = min(2*dt, old_dt-dt_done)
                dt = max(dt, old_dt/substeps)
            dt = dt_base
            sph.parameters.time_step = dt
            print(
                "adjusted dt to %s" % sph.parameters.time_step.in_(units.Myr)
            )
            small_step = False
            print("Finished small steps")
            # print(u_to_temperature(sph.gas_particles[0].u))
            # print(sph.gas_particles[0].u)
            # exit()
        else:
            sph.evolve_model(time)
        channel_gas_from_code.copy()
        channel_stars_grav_from_code.copy()
        u_previous = u_now
        u_now = gas.u
        gas.du_dt = (u_now - u_previous) / dt

        channel_stars_wind_to_code.copy()
        wind.evolve_model(time)
        # channel_stars_wind_from_code.copy()
        if COOLING:
            channel_gas_from_code.copy()
            cooling.evolve_for(dt/2)
            channel_gas_to_code.copy()

        if wind.has_new_wind_particles():
            subplot_enabled = True
            wind_p = wind.create_wind_particles()
            # nearest = gas.find_closest_particle_to(wind_p.x, wind_p.y, wind_p.z)
            # wind_p.h_smooth = nearest.h_smooth
            wind_p.h_smooth = 100 | units.au
            print("u: %s / T: %s" % (wind_p.u.mean(), u_to_temperature(wind_p.u.mean())))
            # max_e = (1e44 | units.erg) / wind_p[0].mass
            # max_e = 10 * gas.u.mean()
            # max_e = (1.e48 | units.erg) / wind_p[0].mass
            # wind_p[wind_p.u > max_e].u = max_e
            # wind_p[wind_p.u > max_e].h_smooth = 0.1 | units.parsec
            # print(wind_p.position)
            print(
                "time: %s, wind energy: %s"
                % (time, (wind_p.u * wind_p.mass).sum())
            )
            print(
                "wind temperature: %s"
                % (u_to_temperature(wind_p.u))
            )
            print(
                "gas particles: %i (total mass %s)"
                % (len(wind_p), wind_p.total_mass())
            )
            # for windje in wind_p:
            #     # print(windje)
            #     source = stars[stars.key == windje.source][0]
            #     windje.position += source.position
            #     windje.velocity += source.velocity
            #     # print(source)
            #     # print(windje)
            # # exit()
            gas.add_particles(wind_p)
            gas_in_code.add_particles(wind_p)
            # for wp in wind_p:
            #     print(wp)
            print("Wind particles added")
            if True:  # wind_p.u.max() > gas_in_code.u.max():
                print("Setting dt to very short")
                small_step = True  # dt = 0.1 | units.yr
                h_min = gas.h_smooth.min()
                # delta_t = determine_short_timestep(sph, wind_p, h_min=h_min)
                # print("delta_t is set to %s" % delta_t.in_(units.yr))
        # else:
        #     small_step = True
        print(
            "time: %s sph: %s dM: %s" % (
                time.in_(units.Myr),
                sph.model_time.in_(units.Myr),
                (
                    stars.total_mass()
                    + (
                        gas.total_mass()
                        if not gas.is_empty()
                        else (0 | units.MSun)
                    )
                    - start_mass
                )
            )
        )
        # com = sph.sink_particles.center_of_mass()
        # com = sph.dm_particles.center_of_mass()
        com = stars.center_of_mass()
        print("STEP: %i step%%plot_every: %i" % (step, step % plot_every))
        if step % plot_every == 0:
            plotnr = plotnr + 1
            plot_hydro_and_stars(
                time,
                sph,
                # stars=sph.sink_particles,
                # stars=sph.dm_particles,
                stars=stars,
                sinks=None,
                L=20,
                # N=100,
                # image_size_scale=10,
                filename="phantom-coolthermalwindtestplot-%04i.png" % plotnr,  # int(step/plot_every),
                title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
                gasproperties=["density", "temperature"],
                # colorbar=True,
                starscale=1,
                offset_x=com[0].value_in(units.parsec),
                offset_y=com[1].value_in(units.parsec),
                thickness=5 | units.parsec,
            )
            # write_set_to_file(gas, "gas.amuse", "amuse", append_to_file=False)
            # write_set_to_file(stars, "stars.amuse", "amuse", append_to_file=False)
        elif (
                subplot_enabled
                and ((step % (plot_every/subplot_factor)) == 0)
        ):
            plotnr = plotnr + 1
            subplot += 1
            plot_hydro_and_stars(
                time,
                sph,
                # stars=sph.sink_particles,
                # stars=sph.dm_particles,
                stars=stars,
                sinks=None,
                L=20,
                # N=100,
                # image_size_scale=10,
                filename="phantom-coolthermalwindtestplot-%04i.png" % plotnr,  # int(step/plot_every),
                title="time = %06.2f %s" % (time.value_in(units.Myr), units.Myr),
                gasproperties=["density", "temperature"],
                # colorbar=True,
                starscale=1,
                offset_x=com[0].value_in(units.parsec),
                offset_y=com[1].value_in(units.parsec),
                thickness=5 | units.parsec,
            )
            if subplot % subplot_factor == 0:
                subplot_enabled = False
        print(
            "Average temperature of gas: %s" % (
                u_to_temperature(gas.u).mean().in_(units.K)
            )
        )
    return
Exemplo n.º 7
0
def evolve_triple_with_wind(M1, M2, M3, Pora, Pin_0, ain_0, aout_0,
                            ein_0, eout_0, t_end, nsteps, scheme, dtse_fac):

    import random
    from amuse.ext.solarsystem import get_position

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

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

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

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

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

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

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

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

    gravity.particles.move_to_center()

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

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

    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag

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

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

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

    while time < t_end:

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

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

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

        if time >= t_diag:
            
            t_diag = time + dt_diag

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

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

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

    gravity.stop()
    stellar.stop()

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

    import random
    from amuse.ext.solarsystem import get_position

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

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

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

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

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

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

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

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

    gravity.particles.move_to_center()

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

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

    dt_diag = t_end/float(nsteps)
    t_diag = dt_diag

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

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

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

    while time < t_end:

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

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

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

        if time >= t_diag:
            
            t_diag = time + dt_diag

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

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

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

    gravity.stop()
    stellar.stop()

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

    import random
    from amuse.ext.solarsystem import get_position

    numpy.random.seed(42)

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

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

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

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

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

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

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

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

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

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

    print gravity.parameters

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

    gravity.particles.move_to_center()

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

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

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

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

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

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

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

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

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

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

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

    while time < t_end:

        if scheme == 1:

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

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

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

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

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

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

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

            if dt > 0|dt.unit:

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

                time = advance_gravity(time, dt)

        else:

            print 'unknown option'
            sys.exit(0)

        if time >= t_diag:
            
            t_diag = time + dt_diag

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

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

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

    gravity.stop()
    stellar.stop()

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

    import random
    from amuse.ext.solarsystem import get_position

    time_framework = 0

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

    # Inner binary

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

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

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

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

    # Outer binary

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

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

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

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

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

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

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

    gravity.particles.move_to_center()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        if scheme == 1:

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

        elif scheme == 2:

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

        elif scheme == 3:

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

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

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

        else:  # our scheme is 4

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

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

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

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

        if time >= t_diag:

            t_diag = time + dt_diag

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

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

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

    pyplot.close()

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

    return t, smai, ecci, smao, ecco, inci, inco, time_framework