def bb79_cloud_evolve(N=50000,
                      Mcloud=1. | units.MSun,
                      Rcloud=3.2e16 | units.cm,
                      omega=1.56e-12 | units.rad / units.s,
                      density_perturb=0.5,
                      t_total=8.3e11 | units.s):

    # mean density of the cloud
    rho_uni = Mcloud / (4. / 3. * numpy.pi * Rcloud**3)
    print(" ** mean density = ", rho_uni.in_(units.g / units.cm**3))
    # free fall time of the cloud
    t_ff = numpy.sqrt(3. * numpy.pi / (32. * units.constants.G * rho_uni))
    print(" ** free-fall time = ", t_ff.in_(units.yr))

    conv = nbody_system.nbody_to_si(Mcloud, Rcloud)
    sph = Fi(conv)

    # the initial conditions of BB79
    parts_bb79 = bb79_cloud(targetN=N, omega=omega, rho_perturb=0.5,
                            ethep_ratio=0.25, convert_nbody=conv,
                            base_grid=body_centered_grid_unit_cube).result

    sph.gas_particles.add_particles(parts_bb79)

    sph.parameters.use_hydro_flag = True
    sph.parameters.isothermal_flag = True
    sph.parameters.integrate_entropy_flag = False
    sph.parameters.gamma = 1
    sph.parameters.verbosity = 0
    sph.parameters.timestep = 0.1 * t_ff

    print(
        "**evolving to time: (end time = ~ {0:.3f} t_ff)".format(t_total / t_ff))

    # setting snapshots to be plotted
    nplot = 10
    if nplot > 1:
        plot_timestep = t_total / (nplot - 1)
    else:
        plot_timestep = t_total

    # evolution of the cloud
    for i in range(nplot):
        ttarget = i * plot_timestep
        t_tff = ttarget / t_ff

        sph.evolve_model(ttarget)

        plot_i = "bb79_rho_{0:03d}.png".format(i)
        tt_tff = "{0:.3f}".format(t_tff)
        title_i = "$%s\,t_{\mathrm{ff}}$" % (tt_tff)

        print("\t {0:.3f} t_ff -> {1}".format(t_tff, plot_i))

        plot_sph_rho(sph, N=300, grid_size=0.025 | units.parsec,
                     plot_name=plot_i, plot_title=title_i)

    sph.stop()
def evolve(cluster,cloud, converter_grav,converter_sph, t_end, dt_sph, dt_diag,\
           sink=True, merge=False):

    with open(printout_file, 'a') as pf:
        pf.write('Setting up the gravity code and the hydro code...\n')
    '''# Initialising the direct N-body integrator
    gravity = ph4(converter_grav)
    gravity.particles.add_particles(cluster)'''

    # Initialising the hydro code
    sph = Fi(converter_sph, mode="openmp")
    sph.gas_particles.add_particles(cloud)
    sph.dm_particles.add_particles(cluster)

    sph.parameters.radiation_flag = False
    #sph.parameters.isothermal_flag = True
    #sph.parameters.integrate_entropy_flag = False  #should we consider isothermal process or adiabatic one?
    sph.parameters.timestep = dt_sph
    #sph.parameters.eps_is_h_flag = False    # h_smooth is constant
    #eps = 0.1 | units.parsec
    #sph.parameters.gas_epsilon = eps
    #sph.parameters.sph_h_const = eps
    #cloud.h_smooth= eps
    '''# Building a bridge between hydro and grav
    with open(printout_file, 'a') as pf:
        pf.write('Bridging...\n')
    grav_sph = bridge.Bridge(use_threading=False)
    grav_sph.add_system(gravity, (sph,))
    grav_sph.add_system(sph, (gravity,))
    grav_sph.timestep = dt_bridge'''

    # Setting up channels from code to cloud and cluster
    #channel_from_grav_to_cluster = gravity.particles.new_channel_to(cluster)
    channel_from_sph_to_cloud = sph.gas_particles.new_channel_to(cloud)
    channel_from_sph_to_cluster = sph.dm_particles.new_channel_to(cluster)

    # consider star formation
    if sink == True:
        with open(printout_file, 'a') as pf:
            pf.write('[Star formation is considered.]\n')
        stars = Particles(0)
        sph.dm_particles.add_particles(stars)

        density_threshold = Jeans_density(M=sph.gas_particles.mass.max())
        sph.parameters.stopping_condition_maximum_density = density_threshold
        density_limit_detection = sph.stopping_conditions.density_limit_detection
        density_limit_detection.enable()

    if merge == True:
        merge_radius = 1e-4 | units.parsec  # 1 pc = 206265 AU
        with open(printout_file, 'a') as pf:
            pf.write('[Star merging is considered.]\n')

    # Initialize data lists (Lagrangian radii and relative total energy)
    lr_cloud_list = [Lagrange_radii(cloud, converter_sph)]
    lr_cluster_list = [Lagrange_radii(cluster, converter_grav)]

    E0_cloud = get_energy(cloud)
    Etot0_cloud = E0_cloud[-1]
    E_cloud_list = [E0_cloud / Etot0_cloud]

    E0_cluster = get_energy(cluster)
    Etot0_cluster = E0_cluster[-1]
    E_cluster_list = [E0_cluster / Etot0_cluster]

    n_formed_star = [0]

    # Start Evolving!
    # unify the unit of times
    unit_time = units.Myr
    t_end = t_end.in_(unit_time)
    dt_diag = dt_diag.in_(unit_time)
    dt_sph = dt_sph.in_(unit_time)
    times = quantities.arange(0. | unit_time, t_end + dt_diag, dt_diag)

    with open(printout_file, 'a') as pf:
        pf.write('\nStart evolving the molecular cloud...\n')
        pf.write(
            f'End time = {t_end}; Diagnostic timestep = {dt_diag}; sph code timestep = {dt_sph}.\n'
        )

    for i, t in enumerate(times):
        with open(printout_file, 'a') as pf:
            pf.write(f'---------- Time = {t.in_(units.Myr)} ----------\n')

        # calculate the dynamical(dyn), half-mass relaxation(rh), and free-fall(ff) timescales
        # of both the cloud and the cluster systems
        t_dyn_cloud, t_rh_cloud, t_ff_cloud = timescale(cloud, unit_time)
        t_dyn_cluster, t_rh_cluster, t_ff_cluster = timescale(
            cluster, unit_time)
        all_timescales = [
            t_dyn_cloud, t_rh_cloud, t_ff_cloud, t_dyn_cluster, t_rh_cluster,
            t_ff_cluster
        ] | unit_time
        # check if the bridge timestep should be reduced
        if all_timescales.amax() < 10 * dt_sph:
            dt_sph_old = dt_sph
            dt_sph = all_timescales.amax() / 10.
            with open(printout_file, 'a') as pf:
                pf.write(
                    f'Change the bridge timestep from {dt_sph_old} to {dt_sph}.\n'
                )

        if sink == True:
            # make sure at this time, elements in 'stars' and 'sph.gas_particles' are the same
            resolve_sinks(sph, stars, cloud, density_threshold, t)

        # evolve for one diagnostic timestep
        #grav_sph.evolve_model(t, timestep=dt_bridge)
        sph.evolve_model(t, timestep=dt_sph)

        #channel_from_grav_to_cluster.copy()
        channel_from_sph_to_cloud.copy()
        channel_from_sph_to_cluster.copy()
        if len(stars) > 0:
            newstars = cluster.select_array(
                lambda birth_age: birth_age >= 0. | unit_time, ["birth_age"])
            cluster.remove_particles(newstars)

        # merge two stars if they are too close to each other (distance < merge_radius)
        # typically we don't consider merging event since it is very rare given a reasonable merge radius
        if merge == True:
            merge_stars(sph, stars, merge_radius)

        with open(printout_file, 'a') as pf:
            pf.write('Number of stars in `cluster`= %d; in `stars` = %d; in `sph.dm_particles`= %d.\n'\
                     %(len(cluster), len(stars), len(sph.dm_particles)))

        # make snapshots
        plot_cloud_cluster(cluster, sph, stars, title='{0}'.format(float(t.value_in(units.Myr))),\
                           vrange=[-5,3])

        # save data (energy will be added afterwards)
        lr_cloud = Lagrange_radii(cloud, converter_sph)
        lr_cloud_list.append(lr_cloud)
        lr_cluster = Lagrange_radii(cluster, converter_grav)
        lr_cluster_list.append(lr_cluster)

        E_cloud = get_energy(cloud, norm=Etot0_cloud)
        E_cloud_list.append(E_cloud)
        E_cluster = get_energy(cluster, norm=Etot0_cluster)
        E_cluster_list.append(E_cluster)

        n_formed_star.append(len(stars))

        # save data instantaneously
        lr_data = np.concatenate(
            ([t.value_in(unit_time)], lr_cloud, lr_cluster))
        E_data = np.concatenate(([t.value_in(unit_time)], E_cloud, E_cluster))
        with open('lr_data.txt', 'a') as f_lr_data:
            f_lr_data.write(','.join(str(x) for x in lr_data) + '\n')
        with open('E_data.txt', 'a') as f_E_data:
            f_E_data.write(','.join(str(x) for x in E_data) + '\n')
        with open('formed_star_data.txt', 'a') as f_fs_data:
            f_fs_data.write('%f,%d\n' % (t.value_in(unit_time), len(stars)))

        with open(printout_file, 'a') as pf:
            pf.write(f'Finished.\n')

    #gravity.stop()
    sph.stop()

    return times.value_in(
        unit_time
    ), n_formed_star, lr_cloud_list, lr_cluster_list, E_cloud_list, E_cluster_list
Exemple #3
0
N_particles = 1000  # Number of SPH particles
disk = ProtoPlanetaryDisk(N_particles,
                          convert_nbody=converter,
                          densitypower=1.5,
                          Rmin=0.5,
                          Rmax=100,
                          q_out=1.)  # Rmin and Rmax in AU

disk_particles = disk.result  # Disk particles
disk_particles.h_smooth = 0.06 | units.au  # Smoothing length

# Rotate the disk 90 degrees around x axis
disk = rotate(disk_particles, 90, 0, 0)

# Start SPH code and add particles
sph = Fi(converter)
sph.gas_particles.add_particles(
    disk_particles)  # Disk particles are added as gas particles
sph.dm_particles.add_particles(
    stars[0])  # Star is added as dark matter particle

# Evolve code in time steps
t_end = 100 | units.yr
dt = 1 | units.yr
t = 0 | units.yr

while t < t_end:
    t += dt
    print t
    sph.evolve_model(t)
Exemple #4
0
def run_molecular_cloud(N=100,
                        Mcloud=100. | units.MSun,
                        Rcloud=1. | units.parsec):

    conv = nbody_system.nbody_to_si(Mcloud, Rcloud)

    rho_cloud = 3. * Mcloud / (4. * numpy.pi * Rcloud**3)
    print rho_cloud
    tff = 0.5427 / numpy.sqrt(constants.G * rho_cloud)
    print "t_ff=", tff.value_in(units.Myr), 'Myr'

    dt = 5.e-2 | units.Myr
    tend = 1.0 | units.Myr
    #    tend=2.0 | units.Myr

    parts = molecular_cloud(targetN=N,
                            convert_nbody=conv,
                            base_grid=body_centered_grid_unit_cube,
                            seed=100).result

    sph = Fi(conv, number_of_workers=3)
    sph.parameters.use_hydro_flag = True
    sph.parameters.radiation_flag = False
    sph.parameters.gamma = 1
    sph.parameters.isothermal_flag = True
    sph.parameters.integrate_entropy_flag = False
    sph.parameters.timestep = dt
    sph.parameters.verbosity = 0
    sph.parameters.eps_is_h_flag = False  # h_smooth is constant
    eps = 0.1 | units.parsec
    sph.parameters.gas_epsilon = eps
    sph.parameters.sph_h_const = eps
    parts.h_smooth = eps

    print 'eps-h flag', sph.get_eps_is_h(), sph.get_consthsm()

    expected_dt = 0.2 * numpy.pi * numpy.power(eps, 1.5) / numpy.sqrt(
        constants.G * Mcloud / N)

    print "dt_exp=", expected_dt.value_in(units.Myr)
    print "dt=", dt
    print "eps=", sph.parameters.gas_epsilon.in_(units.parsec)

    sph.gas_particles.add_particles(parts)

    #grav=copycat(Fi, sph, conv)
    #sys=bridge(verbose=False)
    #sys.add_system(sph,(grav,),False)
    channel_from_sph_to_parts = sph.gas_particles.new_channel_to(parts)
    channel_from_parts_to_sph = parts.new_channel_to(sph.gas_particles)

    i = 0
    L = 6
    E0 = 0.0
    ttarget = 0.0 | units.Myr

    plot_hydro(ttarget, sph, i, L)

    while ttarget < tend:
        ttarget = float(i) * dt
        print ttarget
        sph.evolve_model(ttarget, timestep=dt)
        E = sph.gas_particles.kinetic_energy(
        ) + sph.gas_particles.potential_energy(
        ) + sph.gas_particles.thermal_energy()
        E_th = sph.gas_particles.thermal_energy()
        if i == 0:
            E0 = E
        Eerr = (E - E0) / E0
        print 'energy=', E, 'energy_error=', Eerr, 'e_th=', E_th
        channel_from_sph_to_parts.copy()
        """
        filename = 'm400k_r10pc_e01_'+ str(i).zfill(2) + '.dat'
        print filename
        parts_sorted = parts.sorted_by_attribute('rho')
        write_output(filename, parts_sorted, conv)        
        """
        plot_hydro(ttarget, sph, i, L)
        i = i + 1

    plot_hydro_and_stars(ttarget, sph, L)

    sph.stop()
    return parts