[galaxy] add a file with external routine useful for galaxies
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
# coding: utf-8
|
||||
|
||||
import numpy as np
|
||||
from plotter import U
|
||||
|
||||
|
||||
def get_dispersion(dset, name):
|
||||
"""
|
||||
Compute dispersion from dset["name"]
|
||||
"""
|
||||
vel = dset[name]
|
||||
mass = dset["mass_kg"]
|
||||
mass_tot = np.sum(mass)
|
||||
mean = np.sum(mass * vel) / mass_tot
|
||||
return np.sqrt(np.sum(mass * (vel - mean) ** 2) / mass_tot)
|
||||
|
||||
|
||||
def get_polar_sigma(dset):
|
||||
"""
|
||||
Get speed dispersion in polar coordinates
|
||||
"""
|
||||
return {
|
||||
velname: get_dispersion(dset, velname) for velname in ["velphi", "velr", "velz"]
|
||||
}
|
||||
|
||||
|
||||
def get_gas_dm_stars(pp):
|
||||
# Load arrays
|
||||
pp.load_parts()
|
||||
pp.load_cells()
|
||||
cells = pp.cells
|
||||
parts = pp.parts
|
||||
|
||||
# Compute extra fields and convert units
|
||||
for dset in (cells, parts):
|
||||
dset["pos_kpc"] = dset["pos"] - np.array([0.5, 0.5, 0.5])
|
||||
dset["pos_kpc"] *= pp.info["unit_length"].express(U.kpc)
|
||||
dset["r"] = np.sqrt(np.sum(dset["pos_kpc"][:, :2] ** 2, axis=1))
|
||||
dset["phi"] = np.angle(dset["pos_kpc"][:, 0] + dset["pos_kpc"][:, 1] * 1j)
|
||||
dset["velphi"] = pp.getter_vect_phi(dset, "vel") * pp.info[
|
||||
"unit_velocity"
|
||||
].express(U.km_s)
|
||||
dset["velr"] = pp.getter_vect_r(dset, "vel") * pp.info["unit_velocity"].express(
|
||||
U.km_s
|
||||
)
|
||||
dset["velz"] = dset["vel"][:, 2] * pp.info["unit_velocity"].express(U.km_s)
|
||||
|
||||
cells["mass_kg"] = (
|
||||
cells["rho"]
|
||||
* cells["dx"] ** 3
|
||||
* (pp.info["unit_density"] * pp.info["unit_length"] ** 3).express(U.kg)
|
||||
)
|
||||
|
||||
parts["mass_kg"] = parts["mass"] * pp.info["unit_mass"].express(U.kg)
|
||||
|
||||
for dset in (cells, parts):
|
||||
dset["ek"] = dset["mass_kg"] * np.sum(dset["vel"] ** 2, axis=1)
|
||||
dset["ek"] *= (U.kg * pp.info["unit_velocity"] ** 2).express(U.J)
|
||||
|
||||
# Separate DM from stars
|
||||
mass_dm = np.max(parts["mass_kg"])
|
||||
mask_dm = parts["mass_kg"] == mass_dm
|
||||
mask_star = parts["mass_kg"] < mass_dm
|
||||
|
||||
# Create separated arrays
|
||||
gas = cells
|
||||
dm = {key: parts[key][mask_dm] for key in parts}
|
||||
stars = {key: parts[key][mask_star] for key in parts}
|
||||
|
||||
# Store arrays and return them
|
||||
pp.gas = gas
|
||||
pp.dm = dm
|
||||
pp.stars = stars
|
||||
return gas, dm, stars
|
||||
|
||||
|
||||
def extract_polar_region(dset, r=4, dr=0.5, phi=0, dphi=0.125, z=0, dz=0.5):
|
||||
"""
|
||||
Returns a mask for dset of the polar volume within polar coordinates
|
||||
[r - dr, r + dr] x [phi - dphi, phi + dphi] x [z -dz, z + dz]
|
||||
"""
|
||||
mask_box = (
|
||||
(np.abs(dset["r"] - r) < dr)
|
||||
& (np.abs(dset["phi"] - phi) < dphi)
|
||||
& (np.abs(dset["pos"][:, 2] - z) < dz)
|
||||
)
|
||||
return {key: dset[key][mask_box] for key in dset}
|
||||
|
||||
|
||||
def sector_analysis(pp, r=4, dr=0.5, phi=0, dphi=0.125, z=0, dz=0.5):
|
||||
"""
|
||||
Analyze box at given coordinates
|
||||
"""
|
||||
gds = [pp.gas, pp.dm, pp.stars]
|
||||
gds_box = [extract_polar_region(dset, r, dr, phi, dphi, z, dz) for dset in gds]
|
||||
result = {}
|
||||
result["ek"] = np.array([np.sum(dset["ek"]) for dset in gds_box]) # J
|
||||
result["mass"] = np.array([np.sum(dset["mass_kg"]) for dset in gds_box]) # kg
|
||||
result["ek_spe"] = result["ek"] / result["mass"] # J.kg^-1
|
||||
for dset in gds_box:
|
||||
sigma = get_polar_sigma(dset)
|
||||
for key in sigma:
|
||||
keyres = "sigma_" + key
|
||||
if keyres in result:
|
||||
result[keyres].append(sigma[key])
|
||||
else:
|
||||
result[keyres] = [sigma[key]]
|
||||
return result
|
||||
|
||||
|
||||
def ring_analysis(pp, r=4, dr=0.5, dphi=0.125, z=0, dz=0.5, do_mean=True):
|
||||
"""
|
||||
Compute the average at a given of quantities computed in polar sectors.
|
||||
"""
|
||||
|
||||
phi_sectors = np.arange(-np.pi + dphi, np.pi - dphi, 2 * dphi)
|
||||
data_sec = [sector_analysis(pp, r, dr, phi, dphi, z, dz) for phi in phi_sectors]
|
||||
|
||||
data = {}
|
||||
mwavg = {}
|
||||
tot_mass = [np.sum([d["mass"][i] for d in data_sec]) for i in range(3)]
|
||||
for key in data_sec[0]:
|
||||
mwavg[key] = []
|
||||
for i in range(3):
|
||||
mwavg[key].append(
|
||||
np.sum([d["mass"][i] * d[key][i] for d in data_sec]) / tot_mass[i]
|
||||
)
|
||||
|
||||
data[key] = np.array([d[key] for d in data_sec])
|
||||
|
||||
return mwavg, phi_sectors, data
|
||||
Reference in New Issue
Block a user