Commit c4b75e9f authored by Josh Borrow's avatar Josh Borrow Committed by Matthieu Schaller
Browse files

Feedback Energy Injection Changes

parent 0cb55120
...@@ -30,6 +30,7 @@ examples/fof_mpi ...@@ -30,6 +30,7 @@ examples/fof_mpi
examples/*/*/*.xmf examples/*/*/*.xmf
examples/*/*/*.dat examples/*/*/*.dat
examples/*/*/*.png examples/*/*/*.png
examples/*/*/*.pdf
examples/*/*/*.mp4 examples/*/*/*.mp4
examples/*/*/*.txt examples/*/*/*.txt
examples/*/*/*.rst examples/*/*/*.rst
......
...@@ -16,4 +16,12 @@ This test emulates what the EAGLE model does to particles for feedback, i.e. ...@@ -16,4 +16,12 @@ This test emulates what the EAGLE model does to particles for feedback, i.e.
+ Heats a single particle to 10^7.5 K + Heats a single particle to 10^7.5 K
+ Does _not_ switch off cooling + Does _not_ switch off cooling
+ Runs to completion. + Runs to completion.
\ No newline at end of file
Running Multiple Tests
----------------------
If you would like to run a suite of tests, try the runs.sh script. You'll
need to set the directories in the parameter file to be one higher, i.e.
../coolingtables rather than ./coolingtables.
...@@ -9,20 +9,20 @@ InternalUnitSystem: ...@@ -9,20 +9,20 @@ InternalUnitSystem:
# Parameters governing the time integration # Parameters governing the time integration
TimeIntegration: TimeIntegration:
time_begin: 0. # The starting time of the simulation (in internal units). time_begin: 0. # The starting time of the simulation (in internal units).
time_end: 1e-3 # The end time of the simulation (in internal units). time_end: 1e-4 # The end time of the simulation (in internal units).
dt_min: 1e-9 # The minimal time-step size of the simulation (in internal units). dt_min: 1e-9 # The minimal time-step size of the simulation (in internal units).
dt_max: 1e-3 # The maximal time-step size of the simulation (in internal units). dt_max: 1e-4 # The maximal time-step size of the simulation (in internal units).
# Parameters governing the snapshots # Parameters governing the snapshots
Snapshots: Snapshots:
basename: feedback # Common part of the name of output files basename: feedback # Common part of the name of output files
time_first: 0. # Time of the first output (in internal units) time_first: 0. # Time of the first output (in internal units)
delta_time: 1e-4 # Time difference between consecutive outputs (in internal units) delta_time: 1e-5 # Time difference between consecutive outputs (in internal units)
compression: 1 compression: 1
# Parameters governing the conserved quantities statistics # Parameters governing the conserved quantities statistics
Statistics: Statistics:
delta_time: 1e-3 # Time between statistics output delta_time: 1e-6 # Time between statistics output
# Parameters for the hydrodynamics scheme # Parameters for the hydrodynamics scheme
SPH: SPH:
...@@ -75,4 +75,16 @@ EAGLECooling: ...@@ -75,4 +75,16 @@ EAGLECooling:
H_reion_eV_p_H: 2.0 H_reion_eV_p_H: 2.0
He_reion_z_centre: 3.5 He_reion_z_centre: 3.5
He_reion_z_sigma: 0.5 He_reion_z_sigma: 0.5
He_reion_eV_p_H: 2.0 He_reion_eV_p_H: 2.0
\ No newline at end of file
# Parameters for the EAGLE "equation of state"
EAGLEEntropyFloor:
Jeans_density_threshold_H_p_cm3: 0.1 # Physical density above which the EAGLE Jeans limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3.
Jeans_over_density_threshold: 10. # Overdensity above which the EAGLE Jeans limiter entropy floor can kick in.
Jeans_temperature_norm_K: 8000 # Temperature of the EAGLE Jeans limiter entropy floor at the density threshold expressed in Kelvin.
Jeans_gamma_effective: 1.3333333 # Slope the of the EAGLE Jeans limiter entropy floor
Cool_density_threshold_H_p_cm3: 1e-5 # Physical density above which the EAGLE Cool limiter entropy floor kicks in expressed in Hydrogen atoms per cm^3.
Cool_over_density_threshold: 10. # Overdensity above which the EAGLE Cool limiter entropy floor can kick in.
Cool_temperature_norm_K: 8000 # Temperature of the EAGLE Cool limiter entropy floor at the density threshold expressed in Kelvin.
Cool_gamma_effective: 1. # Slope the of the EAGLE Cool limiter entropy floor
...@@ -30,43 +30,44 @@ import numpy as np ...@@ -30,43 +30,44 @@ import numpy as np
# Parameters # Parameters
gamma = 5.0 / 3.0 gamma = 5.0 / 3.0
initial_density = 0.1 * mh / (cm ** 3) initial_density = 0.1 * mh / (cm ** 3)
initial_temperature = 1e4 * K initial_temperature = 2550 * (5/4) * K # Equilibrium temperature at solar abundance
inject_temperature = 10 ** (7.5) * K inject_temperature = 10 ** (7.5) * K
mu = 0.5 mu = 0.5
particle_mass = 1e6 * msun particle_mass = 1e6 * msun
unit_system = cosmo_units if __name__ == "__main__":
file_name = "feedback.hdf5" unit_system = cosmo_units
file_name = "feedback.hdf5"
# Read in glass file # Read in glass file
with h5py.File("glassCube_32.hdf5", "r") as handle: with h5py.File("glassCube_32.hdf5", "r") as handle:
positions = handle["/PartType0/Coordinates"][:] positions = handle["/PartType0/Coordinates"][:]
h = handle["PartType0/SmoothingLength"][:] * 0.3 h = handle["PartType0/SmoothingLength"][:] * 0.3
number_of_particles = len(h) number_of_particles = len(h)
side_length = (number_of_particles * particle_mass / initial_density) ** (1 / 3) side_length = (number_of_particles * particle_mass / initial_density) ** (1 / 3)
side_length.convert_to_base(unit_system) side_length.convert_to_base(unit_system)
print(f"Your box has a side length of {side_length}") print(f"Your box has a side length of {side_length}")
# Find the central particle # Find the central particle
central_particle = np.sum((positions - 0.5) ** 2, axis=1).argmin() central_particle = np.sum((positions - 0.5) ** 2, axis=1).argmin()
# Inject the feedback into that central particle # Inject the feedback into that central particle
background_internal_energy = ( background_internal_energy = (
(1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * initial_temperature (1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * initial_temperature
) )
heated_internal_energy = (1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * inject_temperature heated_internal_energy = (1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * inject_temperature
internal_energy = np.ones_like(h) * background_internal_energy internal_energy = np.ones_like(h) * background_internal_energy
internal_energy[central_particle] = heated_internal_energy internal_energy[central_particle] = heated_internal_energy
# Now we have all the information we need to set up the initial conditions! # Now we have all the information we need to set up the initial conditions!
output = Writer(unit_system=unit_system, box_size=side_length) output = Writer(unit_system=unit_system, box_size=side_length)
output.gas.coordinates = positions * side_length output.gas.coordinates = positions * side_length
output.gas.velocities = np.zeros_like(positions) * cm / s output.gas.velocities = np.zeros_like(positions) * cm / s
output.gas.smoothing_length = h * side_length output.gas.smoothing_length = h * side_length
output.gas.internal_energy = internal_energy output.gas.internal_energy = internal_energy
output.gas.masses = np.ones_like(h) * particle_mass output.gas.masses = np.ones_like(h) * particle_mass
output.write(file_name) output.write(file_name)
"""
Plots the energy from the energy.txt file for this simulation.
"""
import matplotlib.pyplot as plt
import numpy as np
from swiftsimio import load
from unyt import Gyr, erg, mh, kb
from makeIC import gamma, initial_density, initial_temperature, inject_temperature, mu, particle_mass
try:
plt.style.use("mnras_durham")
except:
pass
# Snapshot for grabbing the units.
snapshot = load("feedback_0000.hdf5")
units = snapshot.metadata.units
energy_units = units.mass * units.length ** 2 / (units.time ** 2)
data = np.loadtxt("energy.txt").T
# Assign correct units to each
time = data[0] * units.time
mass = data[1] * units.mass
total_energy = data[2] * energy_units
kinetic_energy = data[3] * energy_units
thermal_energy = data[4] * energy_units
radiative_cool = data[8] * energy_units
# Now we have to figure out how much energy we actually 'injected'
background_internal_energy = (
(1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * initial_temperature
)
heated_internal_energy = (1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * inject_temperature
injected_energy = (heated_internal_energy - background_internal_energy) * particle_mass
# Also want to remove the 'background' energy
n_parts = snapshot.metadata.n_gas
total_background_energy = background_internal_energy * n_parts * particle_mass
# Now we can plot
fig, ax = plt.subplots()
ax.plot(
time.to(Gyr),
(kinetic_energy).to(erg),
label="Kinetic"
)
ax.plot(
time.to(Gyr),
(thermal_energy - total_background_energy).to(erg),
label="Thermal"
)
ax.plot(
time.to(Gyr),
(radiative_cool ).to(erg),
label="Lost to cooling"
)
ax.set_xlim(0, 0.05 * Gyr)
ax.set_xlabel("Time [Gyr]")
ax.set_ylabel("Energy [erg]")
ax.legend()
fig.tight_layout()
fig.savefig("Energy.pdf")
\ No newline at end of file
"""
Plots the energy from the energy.txt file for this simulation.
"""
import matplotlib.pyplot as plt
import numpy as np
from swiftsimio import load
from unyt import Gyr, erg, mh, kb, Myr
from scipy.interpolate import interp1d
from makeIC import gamma, initial_density, initial_temperature, inject_temperature, mu, particle_mass
try:
plt.style.use("mnras_durham")
except:
pass
time_to_plot = 25 * Myr
diffusion_parameters = [0.1 * x for x in range(11)]
plot_directory_name = "default_diffmax"
kinetic_energy_at_time = []
thermal_energy_at_time = []
radiative_energy_at_time = []
for diffusion in diffusion_parameters:
directory_name = f"{plot_directory_name}_{diffusion:1.1f}"
# Snapshot for grabbing the units.
snapshot = load(f"{directory_name}/feedback_0000.hdf5")
units = snapshot.metadata.units
energy_units = units.mass * units.length ** 2 / (units.time ** 2)
data = np.loadtxt(f"{directory_name}/energy.txt").T
# Assign correct units to each
time = data[0] * units.time
mass = data[1] * units.mass
total_energy = data[2] * energy_units
kinetic_energy = data[3] * energy_units
thermal_energy = data[4] * energy_units
radiative_cool = data[8] * energy_units
# Now we have to figure out how much energy we actually 'injected'
background_internal_energy = (
(1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * initial_temperature
)
heated_internal_energy = (1.0 / (mu * mh)) * (kb / (gamma - 1.0)) * inject_temperature
injected_energy = (heated_internal_energy - background_internal_energy) * particle_mass
# Also want to remove the 'background' energy
n_parts = snapshot.metadata.n_gas
total_background_energy = background_internal_energy * n_parts * particle_mass
kinetic_energy_interpolated = interp1d(
time.to(Myr),
kinetic_energy.to(erg)
)
thermal_energy_interpolated = interp1d(
time.to(Myr),
(thermal_energy - total_background_energy).to(erg)
)
radiative_cool_interpolated = interp1d(
time.to(Myr),
radiative_cool.to(erg)
)
kinetic_energy_at_time.append(kinetic_energy_interpolated(time_to_plot.to(Myr)))
thermal_energy_at_time.append(thermal_energy_interpolated(time_to_plot.to(Myr)))
radiative_energy_at_time.append(radiative_cool_interpolated(time_to_plot.to(Myr)))
# Now we can plot
fig, ax = plt.subplots()
ax.plot(
diffusion_parameters,
kinetic_energy_at_time,
label="Kinetic"
)
ax.plot(
diffusion_parameters,
thermal_energy_at_time,
label="Thermal"
)
ax.plot(
diffusion_parameters,
radiative_energy_at_time,
label="Lost to cooling"
)
ax.set_xlim(0, 1.0)
ax.set_xlabel(r"Diffusion $\alpha_{\rm max}$")
ax.set_ylabel(f"Energy in component at $t=${time_to_plot} [erg]")
ax.legend()
fig.tight_layout()
fig.savefig("EnergyFuncDiff.pdf")
...@@ -29,6 +29,7 @@ from scipy import stats ...@@ -29,6 +29,7 @@ from scipy import stats
from unyt import cm, s, km, kpc, Pa, msun, K, keV, mh from unyt import cm, s, km, kpc, Pa, msun, K, keV, mh
kPa = 1000 * Pa kPa = 1000 * Pa
plot_radius = 7 * kpc
from swiftsimio import load from swiftsimio import load
...@@ -155,7 +156,7 @@ log = dict( ...@@ -155,7 +156,7 @@ log = dict(
v_r=False, v_phi=False, u=False, S=False, P=False, rho=False, visc=False, diff=False v_r=False, v_phi=False, u=False, S=False, P=False, rho=False, visc=False, diff=False
) )
ylim = dict( ylim = dict(
v_r=[-8, 5], u=[3500, 5500], rho=[0.02, 0.15], visc=[0, 2.0], diff=[0, 0.25], v_r=[-4, 25], u=[4750, 6000], rho=[0.09, 0.16], visc=[0, 2.0], diff=[0, 0.25],
P=[3e-18, 10e-18], S=[-0.5e60, 4e60] P=[3e-18, 10e-18], S=[-0.5e60, 4e60]
) )
...@@ -198,7 +199,7 @@ for key, label in plot.items(): ...@@ -198,7 +199,7 @@ for key, label in plot.items():
axis.set_xlabel("Radius ($r$) [kpc]", labelpad=0) axis.set_xlabel("Radius ($r$) [kpc]", labelpad=0)
axis.set_ylabel(label, labelpad=0) axis.set_ylabel(label, labelpad=0)
axis.set_xlim(0.0, 0.7 * boxSize.to(kpc).value) axis.set_xlim(0.0, plot_radius.to(kpc))
try: try:
axis.set_ylim(*ylim[key]) axis.set_ylim(*ylim[key])
......
...@@ -5,3 +5,4 @@ ...@@ -5,3 +5,4 @@
# Plot the solution # Plot the solution
python plotSolution.py 5 python plotSolution.py 5
python plotEnergy.py
#!/bin/bash -l
#SBATCH -J SWIFTDiffusionCalibration
#SBATCH -N 1
#SBATCH -o swift_diffusion.out
#SBATCH -e swift_diffusion.err
#SBATCH -p cosma
#SBATCH -A durham
#SBATCH --exclusive
#SBATCH -t 1:00:00
for diffusion_alpha_max in 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0;
do
mkdir default_diffmax_$diffusion_alpha_max
cd default_diffmax_$diffusion_alpha_max
../../../swift --hydro --cooling --limiter --threads=16 --param="SPH:diffusion_alpha_max:${diffusion_alpha_max}" ../feedback.yml 2>&1 | tee output.log
cd ..
mkdir nocool_diffmax_$diffusion_alpha_max
cd nocool_diffmax_$diffusion_alpha_max
../../../swift --hydro --temperature --limiter --threads=16 --param="SPH:diffusion_alpha_max:${diffusion_alpha_max}" ../feedback.yml 2>&1 | tee output.log
cd ..
done
"""
Makes a movie of the output of the blob test.
Josh Borrow (joshua.borrow@durham.ac.uk) 2019
LGPLv3
"""
from swiftsimio import load
from swiftsimio.visualisation import slice
from p_tqdm import p_map
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.colors import LogNorm
from matplotlib.animation import FuncAnimation
info_frames = 15
start_frame = 0
end_frame = 101
resolution = 1024
snapshot_name = "blob"
cmap = "Spectral_r"
text_args = dict(color="black")
# plot = "pressure"
# name = "Pressure $P$"
plot = "density"
name = "Fluid Density $\\rho$"
def get_image(n):
"""
Gets the image for snapshot n, and also returns the associated
SWIFT metadata object.
"""
filename = f"{snapshot_name}_{n:04d}.hdf5"
data = load(filename)
boxsize = data.metadata.boxsize[0].value
output = np.zeros((resolution, resolution * 4), dtype=float)
x, y, z = data.gas.coordinates.value.T
# This is an oblong box but we can only make squares!
for box, box_edges in enumerate([[0.0, 1.1], [0.9, 2.1], [1.9, 3.1], [2.9, 4.0]]):
mask = np.logical_and(x >= box_edges[0], x <= box_edges[1])
masked_x = x[mask] - np.float64(box)
masked_y = y[mask]
masked_z = z[mask]
hsml = data.gas.smoothing_length.value[mask]
if plot == "density":
mass = data.gas.masses.value[mask]
image = slice(
x=masked_y,
y=masked_x,
z=masked_z,
m=mass,
h=hsml,
z_slice=0.5,
res=resolution,
)
else:
quantity = getattr(data.gas, plot).value[mask]
# Need to divide out the particle density for non-projected density quantities
image = scatter(
x=masked_y,
y=masked_x,
z=masked_z,
m=quantity,
h=hsml,
z_slice=0.5,
res=resolution,
) / scatter(
x=masked_y,
y=masked_x,
z=masked_z,
m=np.ones_like(quantity),
h=hsml,
z_slice=0.5,
res=resolution,
)
output[:, box * resolution : (box + 1) * resolution] = image
return output, data.metadata
def get_data_dump(metadata):
"""
Gets a big data dump from the SWIFT metadata
"""
try:
viscosity = metadata.viscosity_info
except:
viscosity = "No info"
try:
diffusion = metadata.diffusion_info
except:
diffusion = "No info"
output = (
"$\\bf{Blob}$ $\\bf{Test}$\n\n"
"$\\bf{SWIFT}$\n"
+ metadata.code_info
+ "\n\n"
+ "$\\bf{Compiler}$\n"
+ metadata.compiler_info
+ "\n\n"
+ "$\\bf{Hydrodynamics}$\n"
+ metadata.hydro_info
+ "\n\n"
+ "$\\bf{Viscosity}$\n"
+ viscosity
+ "\n\n"
+ "$\\bf{Diffusion}$\n"
+ diffusion
)
return output
def time_formatter(metadata):
return f"$t = {metadata.t:2.2f}$"
# Generate the frames and unpack our variables
images, metadata = zip(*p_map(get_image, list(range(start_frame, end_frame))))
# The edges are funny because of the non-periodicity.
central_region = images[0][
resolution // 10 : resolution - resolution // 10,
resolution // 10 : resolution - resolution // 10,
]
norm = LogNorm(vmin=np.min(central_region), vmax=np.max(central_region), clip="black")
fig, ax = plt.subplots(figsize=(8 * 4, 8), dpi=resolution // 8)
fig.subplots_adjust(0, 0, 1, 1)
ax.axis("off")
# Set up the initial state
image = ax.imshow(np.zeros_like(images[0]), norm=norm, cmap=cmap, origin="lower")
description_text = ax.text(
0.5,
0.5,