Files
pipeline/disk_postprocess.py
T
2020-12-14 16:25:22 +01:00

1297 lines
37 KiB
Python

# coding: utf-8
import sys
import os
import pymses
import numpy as np
import matplotlib as mpl
if os.environ.get("DISPLAY", "") == "":
print("No display found. Using non-interactive Agg backend")
mpl.use("Agg")
import pylab as P
import glob as glob
try:
import cPickle as pickle
except:
print("cPickle not found, using pickle")
import pickle
import tables
from pymses.sources.ramses import output
from pymses.analysis import Camera, raytracing, slicing, splatting
from pymses.filters import CellsToPoints
from pymses.analysis import ScalarOperator, FractionOperator, MaxLevelOperator
# extension for out files
out_ext = ".jpeg"
P.rcParams["image.cmap"] = "plasma"
P.rcParams["savefig.dpi"] = 400
def make_image_disk(
path,
num,
path_out=None,
order="<",
save_data=True,
force=False,
tag="",
vel_red=20,
map_size=512,
put_title=True,
cpu=False,
level=False,
pos_star=np.array([1.0, 1.0, 1.0]),
interactive=False,
fft=False,
):
"""
Make several useful image of an output of a simulation
Parameters
----------
path path of the Ramses output
num Ramses output number
path_out path of the pipeline outputb
order '<' or '>' order used by pymses for reading ramses output
force if set, erase any existing pipeline output files
tag string to add to the output name
vel_red number of point where velocity should be plot in the slices
map_size size of the map
cpuamr plot also levels and cpus at each step
"""
ro = pymses.RamsesOutput(path, num, order=order)
amr = ro.amr_source(["rho", "vel", "P"])
rad = 0.5
center = [0.5, 0.5, 0.5]
return make_image_aux(
amr,
ro,
center,
rad,
num,
path,
force=force,
path_out=path_out,
save_data=save_data,
map_size=map_size,
vel_red=vel_red,
tag=tag,
cpu=cpu,
level=level,
put_title=put_title,
pos_star=pos_star,
interactive=interactive,
fft=fft,
)
def make_image_aux(
amr,
ro,
center,
radius,
num,
path,
force=False,
path_out=None,
save_data=True,
map_size=512,
vel_red=20,
tag="",
cpu=False,
level=False,
pos_star=np.array([1.0, 1.0, 1.0]),
put_title=True,
interactive=False,
fft=False,
):
"""
Make several useful image of an output of a simulation, auxillary function
Parameters
----------
amr
ro pymses.RamsesOutput object
center 3D array for coordinates center
num output number
path_out path of the pipeline output
force if set, erase any existing pipeline output files
tag string to add to the output name
vel_red number of point where velocity should be plot in the slices
map_size size of the map
"""
lbox = ro.info["boxlen"] # boxlen in codeunits
G = 1.0 # Gravitational constant
# Plotting parameters
ntick = 6
title_ax = {"x": "x (code)", "y": "y (code)", "z": "z (code)"}
im_extent = [
(-radius + center[0]) * lbox,
(radius + center[0]) * lbox,
(-radius + center[1]) * lbox,
(radius + center[1]) * lbox,
]
time = ro.info["time"] # time in codeunits
title = "t=" + str(time)[0:5] + " (code)"
# Determining outpout directory
if path_out is not None:
directory = path_out
else:
directory = path
# Checking for existing files
name = directory + "/coldens_z" + "_" + tag + "_" + format(num, "05") + out_ext
if len(glob.glob(name)) == 1 and not force:
return
# Prepare saving data
if save_data:
maps_disk = {"time": time, "im_extent": im_extent}
rho_op = ScalarOperator(lambda dset: dset["rho"], ro.info["unit_density"])
rt = None
if fft:
rt = splatting.SplatterProcessor(amr, ro.info, rho_op)
else:
rt = raytracing.RayTracer(amr, ro.info, rho_op)
axes_los = ["x", "y", "z"] # Line of sight axes
axes_h = ["y", "x", "x"] # Horizontal axes
axes_v = ["z", "z", "y"] # Vertical axes
ax_nb = {"x": 0, "y": 1, "z": 2}
for i, ax_los in enumerate(axes_los):
ax_h = axes_h[i]
ax_v = axes_v[i]
cam = Camera(
center=center,
line_of_sight_axis=ax_los,
region_size=[2.0 * radius, 2.0 * radius],
distance=radius,
far_cut_depth=radius,
up_vector=ax_v,
map_max_size=map_size,
)
if interactive:
P.figure()
else:
P.close()
# Levels
if level:
amr.set_read_levelmax(20)
level_op = MaxLevelOperator()
rt_level = raytracing.RayTracer(amr, ro.info, level_op)
datamap = rt_level.process(cam, surf_qty=True)
map_level = datamap.map.T
# if save_data:
# maps_disk['levels_' + ax_los] = map_level
levels_ar = np.arange(ro.info["levelmin"], ro.info["levelmax"] + 1)
# Computing linewidths
lw = np.ones(levels_ar.size) * 2
lvl_th = 8 # Level threeshold for reducing linewidths
lw[levels_ar >= lvl_th] = lw[levels_ar >= lvl_th] ** (
lvl_th - levels_ar[levels_ar >= lvl_th]
)
lw[levels_ar < lvl_th] = 1.0
cont = P.contour(
map_level,
extent=im_extent,
origin="lower",
colors="k",
linewidths=lw,
levels=levels_ar,
)
cont.levels = cont.levels + 1
P.clabel(
cont,
levels_ar[levels_ar < lvl_th + 2][1::2],
inline=1,
fontsize=8.0,
fmt="%1d",
)
# Column density
datamap = rt.process(cam, surf_qty=True)
dmap_col = datamap.map.T * lbox
map_col = np.log10(dmap_col)
if save_data:
maps_disk["coldens_" + ax_los] = dmap_col
im = P.imshow(map_col, extent=im_extent, origin="lower")
P.locator_params(axis=ax_h, nbins=ntick)
P.locator_params(axis=ax_v, nbins=ntick)
if put_title:
P.title(title)
P.xlabel(title_ax[ax_h])
P.ylabel(title_ax[ax_v])
cbar = P.colorbar(im)
cbar.set_label(r"$log(N)$ (code)")
name = directory + "/coldens_" + ax_los + "_" + tag + "_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
# Rho slice
datamap_rho = slicing.SliceMap(amr, cam, rho_op, z=0.0)
dmap_rho = (datamap_rho.map).T
map_rho = np.log10(dmap_rho)
vh_op = ScalarOperator(
lambda dset: dset["vel"][:, ax_nb[ax_h]], ro.info["unit_velocity"]
)
dmap_vh = slicing.SliceMap(amr, cam, vh_op, z=0.0)
map_vh_red = dmap_vh.map[
::vel_red, ::vel_red
] # take only a subset of velocities
map_vh_red = map_vh_red.T
vv_op = ScalarOperator(
lambda dset: dset["vel"][:, ax_nb[ax_v]], ro.info["unit_velocity"]
)
dmap_vv = slicing.SliceMap(amr, cam, vv_op, z=0.0)
map_vv_red = dmap_vv.map[::vel_red, ::vel_red]
map_vv_red = map_vv_red.T
# if save_data:
# maps_disk['rho_' + ax_los] = dmap_rho
# maps_disk['v' + ax_h + '_' + ax_los] = (dmap_vh.map).T
# maps_disk['v' + ax_v + '_' + ax_los] = (dmap_vv.map).T
im = P.imshow(map_rho, extent=im_extent, origin="lower")
P.locator_params(axis=ax_h, nbins=ntick)
P.locator_params(axis=ax_v, nbins=ntick)
nh = map_vh_red.shape[0]
nv = map_vv_red.shape[1]
vec_h = (
np.arange(nh) * 2.0 / nh * radius - radius + center[0] + radius / nh
) * lbox
vec_v = (
np.arange(nv) * 2.0 / nv * radius - radius + center[1] + radius / nv
) * lbox
hh, vv = np.meshgrid(vec_h, vec_v)
max_v = np.max(np.sqrt(map_vh_red ** 2 + map_vv_red ** 2))
Q = P.quiver(hh, vv, map_vh_red, map_vv_red, units="width")
P.quiverkey(
Q,
0.7,
0.95,
max_v,
r"$" + str(max_v)[0:4] + "$ (code)",
labelpos="E",
coordinates="figure",
)
if put_title:
P.title(title)
P.xlabel(title_ax[ax_h])
P.ylabel(title_ax[ax_v])
cbar = P.colorbar(im)
cbar.set_label(r"$log(n)$ (code)")
name = directory + "/rho_" + ax_los + "_" + tag + "_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
P_op = ScalarOperator(lambda dset: dset["P"], ro.info["unit_pressure"])
dmap_P = (slicing.SliceMap(amr, cam, P_op, z=0.0)).map.T
dmap_T = dmap_P / dmap_rho
map_T = np.log10(dmap_T)
# if save_data:
# maps_disk['T_' + ax_los] = dmap_T
im = P.imshow(map_T, extent=im_extent, origin="lower")
P.locator_params(axis="x", nbins=ntick)
P.locator_params(axis="y", nbins=ntick)
if put_title:
P.title(title)
P.xlabel(title_ax[ax_h])
P.ylabel(title_ax[ax_v])
cbar = P.colorbar(im)
cbar.set_label(r"$log(T) \, (K)$")
name = directory + "/T_" + ax_los + "_" + tag + "_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
# Toomre parameter
if ax_los == "z":
def omega_rho_func(dset):
pos = dset.get_cell_centers()
pos = pos - (pos_star / lbox)
xx = pos[:, :, 0]
yy = pos[:, :, 1]
rc = np.sqrt(xx ** 2 + yy ** 2) # cylindrical radius
vx = dset["vel"][:, :, 0]
vy = dset["vel"][:, :, 1]
omega_rho = 1.0 / rc ** 2
omega_rho = omega_rho * dset["rho"]
vyx = vy * xx
vxy = vx * yy
omega_rho = omega_rho * (vyx - vxy)
return omega_rho
omega_op = FractionOperator(
omega_rho_func, lambda dset: dset["rho"], 1.0 / ro.info["unit_time"]
)
cs_op = FractionOperator(
lambda dset: dset["P"],
lambda dset: dset["rho"],
ro.info["unit_velocity"],
)
rt_omega = raytracing.RayTracer(amr, ro.info, omega_op)
if fft:
rt_cs = splatting.SplatterProcessor(amr, ro.info, cs_op, surf_qty=False)
else:
rt_cs = raytracing.RayTracer(amr, ro.info, cs_op)
dmap_omega = rt_omega.process(cam)
dmap_cs = rt_cs.process(cam)
map_Q = (lbox * dmap_cs.map.T) * dmap_omega.map.T / (np.pi * G * dmap_col)
# if save_data:
# maps_disk['Q_' + ax_los] = map_Q
im = P.imshow(
map_Q, extent=im_extent, origin="lower", norm=mpl.colors.LogNorm()
)
P.locator_params(axis="x", nbins=ntick)
P.locator_params(axis="y", nbins=ntick)
if put_title:
P.title(title)
P.xlabel(title_ax[ax_h])
P.ylabel(title_ax[ax_v])
cbar = P.colorbar(im)
cbar.set_label(r"$Q$")
name = directory + "/Q_" + ax_los + "_" + tag + "_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
if cpu:
cpu_op = ScalarOperator(
lambda dset: dset.icpu * (np.ones(dset["P"].shape)),
ro.info["unit_pressure"],
)
rt_cpu = raytracing.RayTracer(amr, ro.info, cpu_op)
datamap = rt_cpu.process(cam, surf_qty=True)
map_cpu = datamap.map.T
# if save_data:
# maps_disk['cpu_' + ax_los] = map_cpu
im = P.imshow(map_cpu, extent=im_extent, origin="lower")
P.locator_params(axis="x", nbins=ntick)
P.locator_params(axis="y", nbins=ntick)
if put_title:
P.title(title)
P.xlabel(title_ax[ax_h])
P.ylabel(title_ax[ax_v])
cbar = P.colorbar(im)
cbar.set_label(r"cpu")
name = directory + "/cpu_" + ax_los + "_" + tag + "_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
if save_data:
name_save = (
directory + "/maps_disk" + "_" + tag + "_" + format(num, "05") + ".save"
)
f = open(name_save, "w")
pickle.dump(maps_disk, f)
f.close()
return maps_disk
def disk_prop(
path_in,
num,
path_out=None,
force=False,
nb_bin=20,
rad_ext=1.0,
mass_star=1.0,
pos_star=np.array([1.0, 1.0, 1.0]),
binning="log",
):
"""
Compute properties of a disk in the plane (0,x,y)
with a protostar at the center of the box
The region of the disk is defined by its scale height
Parameters
----------
path_in path of the input data files (output of ramses)
num id of the output
path_out optional path to the output files
force if set, redo ouptut even if already done
nb_bin Number of radial bins
rad_ext Outer radius of the disk
pos_star position of the central protostar
mass_star mass of the central protostar
"""
# Set th output directory
if path_out is not None:
directory_out = path_out
else:
directory_out = path_in
# Check if the output file exists, and exit if it is the case
name_save = directory_out + "/prop_disk_" + str(num).zfill(5) + ".save"
if not force and len(glob.glob(name_save)) != 0:
return
# Compute the bins array
if binning == "log":
lrad = np.log10(rad_ext)
rad = np.logspace(lrad - 2.0, lrad, num=nb_bin)
elif binning == "lin":
rad = np.linspace(0.0, rad_ext, num=nb_bin)
else:
raise ValueError(
"Incorrect binning specification, binnning should be 'lin' or 'log'"
)
# Get Ramses data
ro = pymses.RamsesOutput(path_in, num)
lbox = ro.info["boxlen"] # boxlen in codeunits (=>pc)
time = ro.info["time"] # time in codeunits
# Get array of cell positions
amr = ro.amr_source(["rho", "vel", "Br", "Bl", "P", "g", "phi"])
cell_source = CellsToPoints(amr)
cells = cell_source.flatten()
dx = cells.get_sizes() * lbox
pos = cells.points * lbox
# Get positions in the frame of the protostar
pos = pos - pos_star
# Get cylindrical radius
rc = np.sqrt(pos[:, 0] ** 2 + pos[:, 1] ** 2)
# Get velocities
vel = cells["vel"]
# Get radial component of velocity
norm_pos = rc
norm_pos[rc == 0] = 1.0e-10 # Avoid division per 0
v_rad = (pos[:, 0] * vel[:, 0] + pos[:, 1] * vel[:, 1]) / norm_pos
# Get azimuthal component of velocity
v_az = (pos[:, 0] * vel[:, 1] - pos[:, 1] * vel[:, 0]) / norm_pos
# Gravitational field
g = cells["g"]
g_rad = (pos[:, 0] * g[:, 0] + pos[:, 1] * g[:, 1]) / norm_pos
g_az = (pos[:, 0] * g[:, 1] - pos[:, 1] * g[:, 0]) / norm_pos
# Select cells that are actually in the disk, ie within the scale height
G = 1.0
cs = np.sqrt(cells["P"] / cells["rho"]) # sound velocity
height = cs * np.sqrt(rc ** 3 / (G * mass_star))
mask_pos = np.abs(pos[:, 2]) < height # condition on position
mask_dens = cells["rho"] > 1.0e6 # condition on density
mask = mask_pos # & mask_dens
print("Number of selected cells ", np.sum(mask))
pos_disk = pos[mask]
rc_disk = rc[mask]
vel_disk = vel[mask]
rho_disk = cells["rho"][mask] # density
press_disk = cells["P"][mask] # pressure
dx_disk = dx[mask]
dvol_disk = dx_disk ** 3
v_rad_disk = v_rad[mask]
v_az_disk = v_az[mask]
v_kepl = np.sqrt(mass_star * G / rc_disk)
height_disk = height[mask]
g_rad_disk = g_rad[mask]
g_az_disk = g_az[mask]
total_mass_disk = np.sum(rho_disk * dvol_disk)
total_mass = np.sum(cells["rho"] * dx ** 3)
print("Mass disk", total_mass_disk)
print("Mass box", total_mass)
# Initialize binned quantities
cs_rad = np.zeros(nb_bin - 1)
temp_rad = np.zeros(nb_bin - 1)
press_rad = np.zeros(nb_bin - 1)
rho_rad = np.zeros(nb_bin - 1)
coldens_rad = np.zeros(nb_bin - 1)
v_az_rad = np.zeros(nb_bin - 1)
v_kepl_rad = np.zeros(nb_bin - 1)
v_rad_rad = np.zeros(nb_bin - 1)
alpha_rey_rad = np.zeros(nb_bin - 1)
alpha_rey_rad_bis = np.zeros(nb_bin - 1)
alpha_grav_rad = np.zeros(nb_bin - 1)
Q_kepl_rad = np.zeros(nb_bin - 1)
height_rad = np.zeros(nb_bin - 1)
vol_rad = np.zeros(nb_bin - 1) # Volume of a bin
surf_rad = np.zeros(nb_bin - 1) # Surface of a bin
mass_rad = np.zeros(nb_bin - 1) # Mass of a bin
for i in range(nb_bin - 1):
mask_bin = (rc_disk > rad[i]) & (rc_disk < rad[i + 1])
# print("Bin #{} : {} cells between {} and {}".format(i, np.sum(mask_bin), rad[i], rad[i + 1]))
vol_rad[i] = np.sum(dvol_disk[mask_bin])
mass_rad[i] = np.sum(rho_disk[mask_bin] * dvol_disk[mask_bin])
press_rad[i] = np.sum(press_disk[mask_bin] * dvol_disk[mask_bin]) / vol_rad[i]
rho_rad[i] = np.sum(rho_disk[mask_bin] * dvol_disk[mask_bin]) / vol_rad[i]
temp_rad[i] = np.sum(press_disk[mask_bin] * dvol_disk[mask_bin]) / mass_rad[i]
# Surface of a bin : S = dr * 2 * pi * r with
# dr = rad[i + 1] - rad[i] and r = (rad[i + 1] + rad[i]) / 2.
surf_rad[i] = (rad[i + 1] - rad[i]) * (rad[i + 1] + rad[i]) * np.pi
coldens_rad[i] = mass_rad[i] / surf_rad[i]
v_az_rad[i] = (
np.sum(v_az_disk[mask_bin] * rho_disk[mask_bin] * dvol_disk[mask_bin])
/ mass_rad[i]
)
v_rad_rad[i] = (
np.sum(v_rad_disk[mask_bin] * rho_disk[mask_bin] * dvol_disk[mask_bin])
/ mass_rad[i]
)
height_rad[i] = (
np.sum(height_disk[mask_bin] * rho_disk[mask_bin] * dvol_disk[mask_bin])
/ mass_rad[i]
)
alpha_rey_rad[i] = (2.0 / 3) * (
(
np.sum(
v_az_disk[mask_bin]
* v_rad_disk[mask_bin]
* rho_disk[mask_bin]
* dvol_disk[mask_bin]
)
/ np.sum(dvol_disk[mask_bin] * press_disk[mask_bin])
- v_az_rad[i] * v_rad_rad[i] * rho_rad[i] / press_rad[i]
)
* v_az_rad[i]
/ abs(v_az_rad[i])
)
alpha_grav_rad[i] = (2.0 / 3) * (
np.sum(
g_az_disk[mask_bin]
* g_rad_disk[mask_bin]
* rho_disk[mask_bin]
* dvol_disk[mask_bin]
)
/ (4 * np.pi * G)
/ np.sum(dvol_disk[mask_bin] * press_disk[mask_bin])
* coldens_rad[i]
)
v_kepl_rad[i] = (
np.sum(v_kepl[mask_bin] * rho_disk[mask_bin] * dvol_disk[mask_bin])
/ mass_rad[i]
)
# Derived quantities
cs_rad = np.sqrt(temp_rad)
Q_kepl_rad = cs_rad * v_az_rad / (np.pi * G * coldens_rad * rad[0 : nb_bin - 1])
# Means
mask_mean = (0.1 < rad[0 : nb_bin - 1]) & (rad[0 : nb_bin - 1] < 0.2)
mass_mean = np.sum(mass_rad[mask_mean])
alpha_rey_mean = np.sum(alpha_rey_rad[mask_mean] * mass_rad[mask_mean]) / mass_mean
alpha_grav_mean = (
np.sum(alpha_grav_rad[mask_mean] * mass_rad[mask_mean]) / mass_mean
)
Q_mean = np.sum(Q_kepl_rad[mask_mean] * mass_rad[mask_mean]) / mass_mean
Q_min = np.nanmin(Q_kepl_rad)
# store the results
prop_disk = {
"time": time,
"mass_disk": total_mass_disk,
"mass_box": total_mass,
"rad": rad[0 : nb_bin - 1],
"center": pos_star,
"alpha_rey": alpha_rey_rad,
"alpha_rey_mean": alpha_rey_mean,
"alpha_grav": alpha_grav_rad,
"alpha_grav_mean": alpha_grav_mean,
"v_rad": v_rad_rad,
"v_az": v_az_rad,
"v_kepl": v_kepl_rad,
"coldens": coldens_rad,
"rho": rho_rad,
"press": press_rad,
"temp": temp_rad,
"cs": cs_rad,
"Q_kepl": Q_kepl_rad,
"Q_mean": Q_mean,
"Q_min": Q_min,
"height": height_rad,
}
f = open(name_save, "w")
pickle.dump(prop_disk, f)
f.close()
def plot_disk_prop(path, num, force=False, tag="", interactive=False):
"""
Plot properties of a disk
num id of the ramses output
path path to the properties file
force if set, redo plots even if already done
"""
# Load property file
name_save = path + "/prop_disk_" + str(num).zfill(5) + ".save"
# Check if the properties file exists
if len(glob.glob(name_save)) == 0:
raise ("no pickle file for disk properties. Run disk_prop() first")
f = open(name_save, "r")
prop_disk = pickle.load(f)
f.close()
# Check if the output file exists, and exit if it is the case
name_save = path + "/rho_disk_r_" + str(num).zfill(5) + out_ext
if not force and len(glob.glob(name_save)) != 0:
return
time = prop_disk["time"]
mass = prop_disk["mass_disk"]
title = "t=" + str(time)[0:5] + " (code)"
rad = prop_disk["rad"]
if interactive:
P.figure()
else:
P.close()
P.xscale("log")
P.yscale("log")
P.grid()
P.plot(rad, prop_disk["rho"], color="k", linewidth=2)
P.ylabel(r"$n \, (code)$")
P.xlabel("disk radius")
P.title(title)
if interactive:
P.figure()
else:
P.savefig(path + "/rho_disk_r_" + str(num).zfill(5) + out_ext)
P.close()
P.xscale("log")
P.yscale("log")
P.grid()
P.plot(rad, prop_disk["temp"], color="k", linewidth=2)
P.ylabel(r"$T \, (K)$")
P.xlabel("disk radius")
P.title(title)
if interactive:
P.figure()
else:
P.savefig(path + "/T_disk_r_" + str(num).zfill(5) + out_ext)
P.close()
P.xscale("log")
P.yscale("symlog", linthreshy=0.01)
P.plot(rad, prop_disk["v_rad"], color="k", linewidth=2)
P.plot(rad, prop_disk["v_kepl"], color="b", linewidth=2)
P.plot(rad, abs(prop_disk["v_az"]), color="r", linewidth=2)
P.plot(rad, prop_disk["cs"], color="c", linewidth=2)
P.grid()
P.legend((r"$v_r$", r"$v_{kepl}$", r"$v_\phi$", r"$c_s$"), loc="upper right")
P.ylabel(r"$V \, (km s^{-1})$")
P.xlabel("disk radius")
if interactive:
P.figure()
else:
P.savefig(path + "/V_disk_r_" + str(num).zfill(5) + out_ext)
P.close()
P.xscale("log")
P.yscale("log")
P.grid()
P.plot(rad, prop_disk["coldens"], color="k", linewidth=2)
P.ylabel(r"$N\, (cm^{-2})$")
P.xlabel("disk radius ")
P.title(title)
if interactive:
P.figure()
else:
P.savefig(path + "/coldens_disk_r_" + str(num).zfill(5) + out_ext)
P.close()
# Alpha
alpha_rey_mean, alpha_grav_mean = (
prop_disk["alpha_rey_mean"],
prop_disk["alpha_grav_mean"],
)
# P.xscale('log')
P.xlim([1e-2, 0.25])
P.yscale("log")
P.ylim([1e-7, 1.0])
P.grid()
P.plot(
rad, abs(prop_disk["alpha_rey"]), "b", linewidth=2, label=r"$\alpha_{Reynolds}$"
)
P.plot(rad, abs(alpha_rey_mean * np.ones(len(rad))), "b:", linewidth=1)
P.plot(
rad, abs(prop_disk["alpha_grav"]), "r", linewidth=2, label=r"$\alpha_{grav}$"
)
P.plot(rad, abs(alpha_grav_mean * np.ones(len(rad))), "r:", linewidth=1)
P.plot(
rad,
abs(prop_disk["alpha_rey"]) + abs(prop_disk["alpha_grav"]),
"g--",
linewidth=2,
label=r"$\alpha_{tot}$",
)
P.title(
title
+ r", $\bar{\alpha}_{Reynolds} = %.1e, \bar{\alpha}_{grav} = %.1e$"
% (alpha_rey_mean, alpha_grav_mean)
)
P.legend()
P.ylabel(r"$\alpha$")
P.xlabel("disk radius ")
if interactive:
P.figure()
else:
P.savefig(path + "/alpha_disk_r_" + str(num).zfill(5) + out_ext)
P.close()
# Q
P.ylim([0, 10.0])
P.xlim([0, 0.5])
P.yticks(np.arange(0.0, 11, 1.0))
P.grid()
P.plot(rad, abs(prop_disk["Q_kepl"]), color="b", linewidth=2)
P.plot(rad, abs(prop_disk["Q_mean"]) * np.ones(len(rad)), "b:", linewidth=1)
P.ylabel(r"$Q$")
P.xlabel("disk radius ")
P.title(title + ", mass of disk = {} (code)".format(mass))
if interactive:
pass
else:
P.savefig(path + "/Q_r_" + str(num).zfill(5) + out_ext)
P.close()
# height ratio
P.grid()
P.plot(rad, abs(prop_disk["height"] / rad), color="b", linewidth=2)
P.ylabel(r"H ratio")
P.xlabel("disk radius ")
P.title(title + ", mass of box = {} (code)".format(prop_disk["mass_box"]))
if interactive:
pass
else:
P.savefig(path + "/H_r_" + str(num).zfill(5) + out_ext)
P.close()
def disk_pdf(
path,
num,
maps_disk,
pos_star=[1.0, 1.0],
force=False,
interactive=False,
nb_bin_hist=50,
tag="",
rad_min=0.1,
):
# Load property file
name_prop = path + "/prop_disk_" + str(num).zfill(5) + ".save"
# Check if the properties file exists
if len(glob.glob(name_prop)) == 0:
raise IOError("no pickle file for disk properties. Run disk_prop() first")
f = open(name_prop, "r")
prop_disk = pickle.load(f)
f.close()
# Load maps file
print("load maps file")
name_maps = path + "/maps_disk" + "_" + tag + "_" + format(num, "05") + ".save"
# Check if the maps file exists
if maps_disk is None:
if len(glob.glob(name_maps)) == 0:
raise IOError("no pickle file for disk maps. Run make_image_disk() first")
f = open(name_maps, "r")
maps_disk = pickle.load(f)
f.close()
print("maps file loaded")
time = prop_disk["time"]
title = "t=" + str(time)[0:5] + " (code)"
coldens_map = maps_disk["coldens_z"]
im_extent = maps_disk["im_extent"]
rad_bins = prop_disk["rad"]
coldens_rad = prop_disk["coldens"]
x = np.linspace(im_extent[0], im_extent[1], coldens_map.shape[0])
y = np.linspace(im_extent[2], im_extent[3], coldens_map.shape[1])
xx, yy = np.meshgrid(x, y)
rr = np.sqrt((xx - pos_star[0]) ** 2 + (yy - pos_star[1]) ** 2)
# Find appropriate bin for each coordinate set
bins = np.zeros(rr.shape, dtype=int)
for r in rad_bins[1:]:
bins = bins + (rr >= r).astype(int)
coldens_mean = coldens_rad[bins.flatten()]
coldens_mean_map = np.reshape(coldens_mean, coldens_map.shape)
# Kill fluctuations for r < rad_min
coldens_map[rr < rad_min] = coldens_mean_map[rr < rad_min]
# Histogramm : density fluctuation distribution function
dcoldens = np.log10(coldens_map.flatten() / coldens_mean)
P.grid()
P.yscale("log")
P.xlabel(r"$\log(N / \bar{N})$")
P.ylabel("Probability density")
P.title(title)
P.hist(dcoldens, nb_bin_hist, range=(-1, 2))
if interactive:
pass
else:
P.savefig(path + "/dcol_hist_" + str(num).zfill(5) + out_ext)
P.close()
# Fluctuation map
dcoldens_map = np.reshape(dcoldens, coldens_map.shape)
# cont = P.contour(coldens_mean_map,
# extent=im_extent,
# origin='lower',
# colors='k',
# linewidths=0.1)
im = P.imshow(dcoldens_map, extent=im_extent, origin="lower", cmap="viridis")
P.title(title)
P.xlabel(r"$x$")
P.ylabel(r"$y$")
cbar = P.colorbar(im)
cbar.set_label(r"$log(N/\bar{N})$ (code)")
name = path + "/dcoldensmap_" + format(num, "05")
name_im = name + out_ext
if interactive:
P.figure()
else:
P.savefig(name_im)
P.close()
def compare(path, runs, num, force=False, interactive=False):
"""
Compare properties of a disk in several simulations
num id of the ramses output
runs list of runs to consider
path path to the properties file
force if set, redo plots even if already done
interactive interactive mode, to use in a %pylab ipython shell
"""
# Initialize arrays
time = np.zeros(len(runs))
alpha_rey = np.zeros(len(runs))
alpha_grav = np.zeros(len(runs))
Q = np.zeros(len(runs))
Q0 = np.zeros(len(runs))
for i, run in enumerate(runs):
path_run = path + "/" + run
# Load property file
name_save = path_run + "/prop_disk_" + str(num).zfill(5) + ".save"
# Check if the properties file exists
if len(glob.glob(name_save)) == 0:
raise ("no pickle file for disk properties. Run disk_prop() first")
f = open(name_save, "r")
prop_disk = pickle.load(f)
f.close()
time[i] = prop_disk["time"]
alpha_rey[i] = prop_disk["alpha_rey_mean"]
alpha_grav[i] = prop_disk["alpha_grav_mean"]
Q[i] = prop_disk["Q_min"]
Q0[i] = float(run.split("_")[2][1:])
# Check if the output file exists, and exit if it is the case
name_save = path + "/alphaQ_" + str(num).zfill(5) + out_ext
if not force and len(glob.glob(name_save)) != 0:
return
title = "t=" + str(time[0]) + " (code)"
# alpha = f(Qmin)
P.yscale("log")
P.ylim([1e-7, 1.0])
P.grid()
P.plot(Q, abs(alpha_rey), "o--", label=r"$\bar{\alpha}_{Reynolds}$")
P.plot(Q, abs(alpha_grav), "*--", label=r"$\bar{\alpha}_{grav}$")
P.legend()
P.ylabel(r"$\bar{\alpha}$")
P.xlabel(r"$Q_{min}$")
if interactive:
P.figure()
else:
P.savefig(path + "/alphaQ_" + str(num).zfill(5) + out_ext)
P.close()
# alpha = f(Q0)
P.yscale("log")
P.ylim([1e-7, 1.0])
P.grid()
P.plot(Q0, abs(alpha_rey), "o-.", label=r"$\bar{\alpha}_{Reynolds}$")
P.plot(Q0, abs(alpha_grav), "*--", label=r"$\bar{\alpha}_{grav}$")
P.legend()
P.ylabel(r"$\bar{\alpha}$")
P.xlabel(r"$Q_{0}$")
if interactive:
P.figure()
else:
P.savefig(path + "/alphaQ0_" + str(num).zfill(5) + out_ext)
P.close()
def evolution(path, nums, force=False, interactive=False):
"""
Plot properties over time
path path to the properties file
nums list of id of the ramses output
force if set, redo plots even if already done
interactive interactive mode, to use in a %pylab ipython shell
"""
# Initialize arrays
time = np.zeros(len(nums))
alpha_rey = np.zeros(len(nums))
alpha_grav = np.zeros(len(nums))
Qmin = np.zeros(len(nums))
Qmean = np.zeros(len(nums))
mass_disk = np.zeros(len(nums))
mass_box = np.zeros(len(nums))
for i, num in enumerate(nums):
# Load property file
name_prop = path + "/prop_disk_" + str(num).zfill(5) + ".save"
# Check if the properties file exists
if len(glob.glob(name_prop)) == 0:
raise ("no pickle file for disk properties. Run disk_prop() first")
f = open(name_prop, "r")
prop_disk = pickle.load(f)
f.close()
time[i] = prop_disk["time"]
alpha_rey[i] = prop_disk["alpha_rey_mean"]
alpha_grav[i] = prop_disk["alpha_grav_mean"]
Qmin[i] = prop_disk["Q_min"]
Qmean[i] = prop_disk["Q_mean"]
mass_disk[i] = prop_disk["mass_disk"]
mass_box[i] = prop_disk["mass_box"]
# Check if the output file exists, and exit if it is the case
name_save = path + "/alpha_time" + out_ext
if not force and len(glob.glob(name_save)) != 0:
return
# Alpha
P.yscale("log")
P.ylim([1e-7, 1.0])
P.grid()
P.plot(time, abs(alpha_rey), "o-.", label=r"$\bar{\alpha}_{Reynolds}$")
P.plot(time, abs(alpha_grav), "*--", label=r"$\bar{\alpha}_{grav}$")
P.legend()
P.ylabel(r"$\bar{\alpha}$")
P.xlabel(r"time (code)")
if interactive:
P.figure()
else:
P.savefig(path + "/alpha_time" + out_ext)
P.close()
# Q
P.grid()
P.plot(time, Qmin, "o-.", label=r"$Q_{min}$")
P.plot(time, Qmean, "*--", label=r"$\bar{Q}$")
P.legend()
P.ylabel(r"$Q$")
P.xlabel(r"time (code)")
if interactive:
P.figure()
else:
P.savefig(path + "/Q_time" + out_ext)
P.close()
# M
P.grid()
P.plot(time, mass_disk, "o-.", label=r"$M_{disk}$")
P.plot(time, mass_box, "*--", label=r"$M_{box}$")
P.legend()
P.ylabel(r"$M / M_{*}$")
P.xlabel(r"time (code)")
if interactive:
P.figure()
else:
P.savefig(path + "/mass_time" + out_ext)
P.close()
def make_clump_hop(
path_in,
num,
name,
thres_dens,
thres_level,
pos_zoom,
size_zoom,
path_out=None,
path_hop="",
force=False,
gcomp=True,
):
"""
This routine use the HOP algorithm to extract clumps defined from their peaks
as an output it provides a list of cell position ordered by the group to which they belong
Parameters
----------
path_in is the path where the data tobe read are located
path_out is the path of teh directory where resulting files must be written
num output number
name a string which is used to write the names of the various files
thres_dens density threshold above which cells are considered
thres_level level threshold above which cells are considered
pos_zoom the center of the zoom coordinates
size_zoom the 3 zoom extension (x, y and z)
"""
if path_out is not None:
directory_out = path_out
else:
directory_out = path_in
name_txt = name + ".txt"
# check whether hop entry files have been created (not test is done on .txt only
if len(glob.glob(name_txt)) == 0 or force:
ro = pymses.RamsesOutput(path_in, num)
amr = ro.amr_source(["rho"], grav_compat=gcomp) # density only is used
center = np.asarray(pos_zoom)
radius = size_zoom
min_coords = np.zeros(3)
max_coords = np.zeros(3)
min_coords[:] = center[:] - radius / 2.0
max_coords[:] = center[:] + radius / 2.0
region = Box((min_coords, max_coords))
# region = Sphere(center,radius)
filt_amr = RegionFilter(region, amr)
cell_source = CellsToPoints(
filt_amr,
)
# selection of the cells of interest
def cell_selec_func(dset):
mask1 = dset["rho"] >= thres_dens
dx = dset.get_sizes()
mask2 = dx <= 0.5 ** thres_level
return mask1 * mask2
# begin cell_selec
cells_selec = PointFunctionFilter(cell_selec_func, cell_source).flatten()
dx = cells_selec.get_sizes()
ncells = cells_selec.npoints
# fill the matrice with ID, x,y,z and masses of particles
val_mat = np.zeros((ncells, 5))
val_mat[:, 0] = np.arange(ncells)
val_mat[:, 1:4] = cells_selec.points[:, 0:3]
val_mat[:, 4] = cells_selec["rho"] * (dx ** 3)
# write name.txt
head = str(ncells)
np.savetxt(
name_txt,
val_mat,
fmt="%10d %.10e %.10e %.10e %.10e",
header=head,
delimiter=" ",
comments=" ",
)
# end of creation name.txt
# creation name.den
f = open(name + ".den", "wb")
f.write(pack("I", ncells))
cells_selec["rho"].astype("f").tofile(f)
f.close()
print(name + ".den created")
# end of creation name.den
# HOP Algorithm
print("creation of .hop and .gbound du to hop")
fname = path_hop + name + ".txt"
print("look for hop in ", fname)
h = HOP(fname, path_hop)
h.process_hop()
print("hop grouping is finished")
# end of HOP Algorithm
idpart = val_mat[:, 0]
X = val_mat[:, 1]
Y = val_mat[:, 2]
Z = val_mat[:, 3]
mass = val_mat[:, 4]
# read the gbound file to get list of particle numbers within groups
f = open(name + ".gbound", "r")
aline = f.readline()
ngroups = int(aline)
npart_v = np.zeros(ngroups, dtype=int)
for i in range(10):
aline = f.readline()
for i in range(ngroups):
aline = f.readline()
vec = aline.split()
igroup = int(vec[0])
npart_v[igroup] = int(vec[1])
f.close()
# get the igroup array
group_ids = h.get_group_ids()
# sort it and apply the sorting to the coordinates
# this means that the particules of group 1 are written first then of group 2 etc...
ind_sort = np.argsort(group_ids)
xx_v = X[ind_sort]
yy_v = Y[ind_sort]
zz_v = Z[ind_sort]
vect_id_group = group_ids[ind_sort] # not so useful
# write the sorted cells
name_save_clump = directory_out + name + ".save"
np.savez(
name_save_clump,
ngroups=ngroups,
npart_v=npart_v,
xx_v=xx_v,
yy_v=yy_v,
zz_v=zz_v,
vect_id_group=vect_id_group,
num=num,
name=name,
thres_dens=thres_dens,
thres_level=thres_level,
pos_zoom=pos_zoom,
size_zoom=size_zoom,
)
return name_save_clump