Skip to content

Commit

Permalink
Add rad_shock test to CI
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Mullen committed Jan 30, 2025
1 parent 5bca683 commit 0601078
Show file tree
Hide file tree
Showing 6 changed files with 239 additions and 66 deletions.
2 changes: 1 addition & 1 deletion external/singularity-opac
Submodule singularity-opac updated 28 files
+102 −13 README.md
+1 −1 cmake/SetupOptions.cmake
+38 −33 singularity-opac/constants/constants.hpp
+5 −0 singularity-opac/neutrinos/brt_neutrinos.hpp
+5 −0 singularity-opac/neutrinos/gray_opacity_neutrinos.hpp
+1 −5 singularity-opac/neutrinos/mean_neutrino_variant.hpp
+14 −3 singularity-opac/neutrinos/mean_opacity_neutrinos.hpp
+1 −5 singularity-opac/neutrinos/neutrino_variant.hpp
+14 −0 singularity-opac/neutrinos/non_cgs_neutrinos.hpp
+177 −17 singularity-opac/neutrinos/spiner_opac_neutrinos.hpp
+2 −2 singularity-opac/neutrinos/thermal_distributions_neutrinos.hpp
+7 −2 singularity-opac/neutrinos/tophat_emissivity_neutrinos.hpp
+7 −2 singularity-opac/photons/epbremsstrahlung_opacity_photons.hpp
+19 −0 singularity-opac/photons/example_ascii/kap_plaw.txt
+103 −0 singularity-opac/photons/example_ascii/preproc_ascii_opac.py
+7 −4 singularity-opac/photons/gray_opacity_photons.hpp
+167 −33 singularity-opac/photons/mean_opacity_photons.hpp
+31 −0 singularity-opac/photons/mean_photon_types.hpp
+23 −5 singularity-opac/photons/mean_photon_variant.hpp
+32 −5 singularity-opac/photons/non_cgs_photons.hpp
+1 −5 singularity-opac/photons/photon_variant.hpp
+7 −4 singularity-opac/photons/powerlaw_opacity_photons.hpp
+2 −2 singularity-opac/photons/thermal_distributions_photons.hpp
+5 −0 test/CMakeLists.txt
+64 −0 test/test_gray_opacities.cpp
+162 −6 test/test_mean_opacities.cpp
+5 −1 utils/fast-math/logs.hpp
+1 −1 utils/spiner
76 changes: 39 additions & 37 deletions inputs/radiation/rad_shock.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,13 @@

<artemis>
problem = shock # name of the pgen
physical_units = cgs
unit_conversion = base
coordinates = cartesian # coordinate system
physical_units = cgs # not scale-free
unit_conversion = base # [L/T/M/Temp] = 1
time = 1.0e-10 # time unit
length = 0.01575 # length unit
mass = 3.906984375e-6 # mass unit (implying dunit=1.0)
temperature = 2.18e6 # temperature unit

<parthenon/job>
problem_id = shock # problem ID: basename of output filenames
Expand All @@ -25,74 +29,72 @@ variables = gas.prim.density, &
gas.prim.velocity, &
gas.prim.sie, &
field.jaybenne.energy_tally
file_type = hdf5 # HDF5 data dump
dt = 1e-10 # time increment between outputs
file_type = hdf5 # HDF5 data dump
dt = 1.0 # time increment between outputs

<parthenon/time>
nlim = -1 # cycle limit
tlim = 9e-10 # time limit
integrator = rk2 # time integration algorithm
nlim = -1 # cycle limit
tlim = 6.0 # time limit
integrator = rk2 # time integration algorithm

<parthenon/mesh>
nx1 = 512 # Number of zones in X1-direction
nx1 = 128 # Number of zones in X1-direction
x1min = 0.0 # minimum value of X1
x1max = 0.01575 # maximum value of X1
x1max = 1.0 # maximum value of X1
ix1_bc = ic # inner-X1 boundary flag
ox1_bc = ic # outer-X1 boundary flag

nx2 = 1 # Number of zones in X2-direction
x2min = 0.0 # minimum value of X2
x2max = 0.01575 # maximum value of X2
x2max = 1.0 # maximum value of X2
ix2_bc = periodic # inner-X2 boundary flag
ox2_bc = periodic # outer-X2 boundary flag

nx3 = 1 # Number of zones in X3-direction
x3min = 0.0 # minimum value of X3
x3max = 0.01575 # maximum value of X3
x3max = 1.0 # maximum value of X3
ix3_bc = periodic # inner-X3 boundary flag
ox3_bc = periodic # outer-X3 boundary flag

<parthenon/swarm>
ix1_bc = jaybenne_reflecting
ox1_bc = jaybenne_reflecting
ix2_bc = periodic
ox2_bc = periodic
ix3_bc = periodic
ox3_bc = periodic
ix1_bc = jaybenne_reflecting # inner-X1 boundary flag for swarms
ox1_bc = jaybenne_reflecting # outer-X1 boundary flag for swarms
ix2_bc = periodic # inner-X2 boundary flag for swarms
ox2_bc = periodic # outer-X2 boundary flag for swarms
ix3_bc = periodic # inner-X3 boundary flag for swarms
ox3_bc = periodic # outer-X3 boundary flag for swarms

<parthenon/meshblock>
nx1 = 256 # Number of cells in each MeshBlock, X1-dir
nx1 = 128 # Number of cells in each MeshBlock, X1-dir
nx2 = 1 # Number of cells in each MeshBlock, X2-dir
nx3 = 1 # Number of cells in each MeshBlock, X3-dir

<physics>
gas = true
radiation = true
gas = true # enable gas hydrodynamics
radiation = true # enable IMC radiation

<gas>
gamma = 1.666666 # adiabatic index
mu = 1.008
cfl = 0.8
reconstruct = plm
riemann = hllc
dfloor = 1.0e-10
siefloor = 1.0e-10
gamma = 1.666666 # adiabatic index
mu = 1.008 # mean molecular weight
cfl = 0.8 # CFL number
reconstruct = plm # reconstruction algorithm
riemann = hllc # Riemann solver

<gas/opacity/absorption>
opacity_model = powerlaw # absorption opacity model
coef_kappa_a = 577. # kappa_a,0 constant
coef_kappa_a = 577.0 # kappa_a,0 constant (must be passed in cgs)
rho_exp = -1.0 # dens exponent for opacity powerlaw
temp_exp = 0.0 # temp exponent for opacity powerlaw

<jaybenne>
num_particles = 1000000
use_ddmc = false
num_particles = 100000 # particle resolution
use_ddmc = false # use DDMC?

<problem>
xdisc = 0.01305
vxl = 5.19e7
vxr = 1.73e7
tl = 2.18e6
tr = 7.98e6
rhol = 5.69
rhor = 17.1
rhol = 5.69 # density (left)
rhor = 17.1 # density (right)
vxl = 0.329524 # x-velocity (left)
vxr = 0.109841 # x-velocity (right)
tl = 1.0 # gas and radiation temp (left)
tr = 3.66055 # gas and radiation temp (right)
xdisc = 0.828571 # discontinuity position
3 changes: 1 addition & 2 deletions src/gas/gas.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin,
params.Add("mu", mu);
params.Add("cv", cv);
EOS eos_host = singularity::UnitSystem<singularity::IdealGas>(
singularity::IdealGas(gamma - 1., cv),
singularity::IdealGas(gamma - 1., cv * units.GetSpecificHeatCodeToPhysical()),
singularity::eos_units_init::LengthTimeUnitsInit(), units.GetTimeCodeToPhysical(),
units.GetMassCodeToPhysical(), units.GetLengthCodeToPhysical(),
units.GetTemperatureCodeToPhysical());
Expand Down Expand Up @@ -148,7 +148,6 @@ std::shared_ptr<StateDescriptor> Initialize(ParameterInput *pin,
pin->GetOrAddReal("gas/opacity/absorption", "coef_kappa_a", 0.0);
const Real rho_exp = pin->GetOrAddReal("gas/opacity/absorption", "rho_exp", 0.0);
const Real temp_exp = pin->GetOrAddReal("gas/opacity/absorption", "temp_exp", 0.0);

opacity = NonCGSUnits<PowerLaw>(PowerLaw(coef_kappa_a, rho_exp, temp_exp), time, mass,
length, temp);
} else {
Expand Down
27 changes: 1 addition & 26 deletions src/utils/opacity/opacity.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,36 +19,11 @@

namespace ArtemisUtils {

// Custom units/opacity model for ShocktubeA problem
// c=1732.05, arad=7.716e-4
struct BasePhysicalConstantsShocktubeA : singularity::BaseUnity {
static constexpr Real speed_of_light = 1732.05;
static constexpr Real planck = 0.0344;
};
using PhysicalConstantsShocktubeA =
singularity::PhysicalConstants<BasePhysicalConstantsShocktubeA,
singularity::UnitConversionDefault>;
using ShocktubeAOpacity =
singularity::photons::PowerLawOpacity<PhysicalConstantsShocktubeA>;

// Custom units/opacity model for Thermalization problem
// c=1.0, arad=1.0
struct BasePhysicalConstantsThermalization : singularity::BaseUnity {
static constexpr Real speed_of_light = 1.0;
static constexpr Real planck = 5.46490601180566;
};
using PhysicalConstantsThermalization =
singularity::PhysicalConstants<BasePhysicalConstantsThermalization,
singularity::UnitConversionDefault>;
using ThermalizationOpacity =
singularity::photons::GrayOpacity<PhysicalConstantsThermalization>;

// Reduced absorption variant for this codebase
using Opacity = singularity::photons::impl::Variant<
singularity::photons::NonCGSUnits<singularity::photons::Gray>,
singularity::photons::NonCGSUnits<singularity::photons::PowerLaw>,
singularity::photons::NonCGSUnits<singularity::photons::EPBremss>, ShocktubeAOpacity,
ThermalizationOpacity>;
singularity::photons::NonCGSUnits<singularity::photons::EPBremss>>;

// Reduced scattering variant for this codebase
using Scattering = singularity::photons::impl::S_Variant<
Expand Down
196 changes: 196 additions & 0 deletions tst/scripts/radiation/rad_shock.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# ========================================================================================
# (C) (or copyright) 2023-2025. Triad National Security, LLC. All rights reserved.
#
# This program was produced under U.S. Government contract 89233218CNA000001 for Los
# Alamos National Laboratory (LANL), which is operated by Triad National Security, LLC
# for the U.S. Department of Energy/National Nuclear Security Administration. All rights
# in the program are reserved by Triad National Security, LLC, and the U.S. Department
# of Energy/National Nuclear Security Administration. The Government is granted for
# itself and others acting on its behalf a nonexclusive, paid-up, irrevocable worldwide
# license in this material to reproduce, prepare derivative works, distribute copies to
# the public, perform publicly and display publicly, and to permit others to do so.
# ========================================================================================

# Regression test based on the Lowrie&Edwards, Mach=3 Steady Radiation Shock
# Exact solutions are generated via the open source, Quokka script here:
# https://github.com/quokka-astro/quokka/blob/development/extern/LowrieEdwards/radshock.py

# Modules
import logging
import numpy as np
import os
import scipy.interpolate
import scripts.utils.artemis as artemis
import sys

logger = logging.getLogger("artemis" + __name__[7:]) # set logger name
logging.getLogger("h5py").setLevel(logging.WARNING)
logging.getLogger("matplotlib").setLevel(logging.WARNING)
logging.getLogger("PIL").setLevel(logging.WARNING)
import matplotlib

matplotlib.use("Agg") # Use the Agg backend to avoid issues with DISPLAY not being set
import matplotlib.pyplot as plt

sys.path.insert(
0,
os.path.join(
artemis.get_artemis_dir(),
"external/parthenon/scripts/python/packages/parthenon_tools/parthenon_tools",
),
)
from phdf import phdf

# Plotting style
plt.rc("text", usetex=True)
plt.rc("font", family="serif", size=20)
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]

# Commands
_nranks = 1
_file_id = "shock"

# Constants
_kb = 1.3806488e-16
_ar = 7.5657308e-15
_c = 2.9979246e10
_amu = 1.6605389e-24

# Units
_time = 1.0e-10
_length = 0.01575
_temperature = 2.18e6
_density = 1.0
_mass = _density * _length**3.0
_velocity = _length / _time
_energy = _mass * _velocity**2.0

# Opacity
_ka0 = 577.0 # in CGS
_rho_exp = -1.0
_temp_exp = 0.0

# Constants
_tf = 6.0e-10 / _time
_gamma = 1.666666
_mu = 1.008

# L/R States
_rhol = 5.69 / _density
_rhor = 17.1 / _density
_vxl = 5.19e7 / _velocity
_vxr = 1.73e7 / _velocity
_tl = 2.18e6 / _temperature
_tr = 7.98e6 / _temperature
_xdisc = 0.01305 / _length

# Thresholds
# NOTE(@pdmullen): The particle count in this test is too low to get good statistics of
# the radiation energy density via a tally. Future extensions of this test may get at the
# radiation temperature via a different means so that we can lower the trad threshold...
_thr_gas = 0.05
_thr_rad = 0.11


# Run Artemis
def run(**kwargs):
logger.debug("Runnning test " + __name__)
arguments = [
"parthenon/job/problem_id=" + _file_id,
"artemis/coordinates=cartesian",
"artemis/physical_units=cgs",
"artemis/unit_conversion=base",
"artemis/time={:24.16e}".format(_time),
"artemis/length={:24.16e}".format(_length),
"artemis/mass={:24.16e}".format(_mass),
"artemis/temperature={:24.16e}".format(_temperature),
"gas/gamma={:24.16e}".format(_gamma),
"gas/mu={:24.16e}".format(_mu),
"gas/opacity/absorption/opacity_model=powerlaw",
"gas/opacity/absorption/coef_kappa_a={:24.16e}".format(_ka0),
"gas/opacity/absorption/rho_exp={:24.16e}".format(_rho_exp),
"gas/opacity/absorption/temp_exp={:24.16e}".format(_temp_exp),
"jaybenne/num_particles=100000",
"jaybenne/use_ddmc=false",
"problem/rhol={:24.16e}".format(_rhol),
"problem/rhor={:24.16e}".format(_rhor),
"problem/vxl={:24.16e}".format(_vxl),
"problem/vxr={:24.16e}".format(_vxr),
"problem/tl={:24.16e}".format(_tl),
"problem/tr={:24.16e}".format(_tr),
"problem/xdisc={:24.16e}".format(_xdisc),
]
artemis.run(_nranks, "radiation/rad_shock.in", arguments)


# Analyze outputs
def analyze():
# NOTE(@pdmullen): In the below, we check that the correct equilibrium temperature
# is obtained after reaching the final time. Future extensions of this test could
# test other jaybenne/dt to test how artemis fares for varying dt / (c rho kappa)^-1
logger.debug("Analyzing test " + __name__)
analyze_status = True

# Derived constants
gm1 = _gamma - 1.0
cv = _kb / (_mu * _amu * gm1)

# Grab Artemis datasets
data = phdf(os.path.join(artemis.get_data_dir(), "shock.out1.final.phdf"))
xc = 0.5 * (data.xng[0, 1:] + data.xng[0, :-1])
sie = data.Get("gas.prim.sie_0", False, False)[0, 0, 0]
erad = data.Get("field.jaybenne.energy_tally", False, False)[0, 0, 0]
xc *= _length
sie *= _energy / _mass
erad *= _energy / _length**3.0
tgas = np.array(sie / cv)
trad = np.array((erad / _ar) ** 0.25)

# Grab exact solution
exact = np.loadtxt(
os.path.join(artemis.get_artemis_dir(), "tst/scripts/radiation/rad_shock.dat"),
unpack=True,
)
int_tg = scipy.interpolate.interp1d(exact[0], exact[1], kind="linear")
int_tr = scipy.interpolate.interp1d(exact[0], exact[2], kind="linear")
tgas_exact = int_tg(xc)
trad_exact = int_tr(xc)

# Plot results
os.makedirs(artemis.get_fig_dir(), exist_ok=True)
fig = plt.figure(figsize=(12, 8))
ax1 = fig.add_subplot(1, 1, 1)
ax1.plot(xc, tgas, label="$T_\\mathrm{gas}$", lw=4, alpha=0.25, color=colors[0])
ax1.scatter(xc, trad, label="$T_\\mathrm{rad}$", lw=4, alpha=0.25, color=colors[1])
ax1.plot(xc, tgas_exact, label="$T_\\mathrm{gas}$", lw=2, color=colors[0])
ax1.plot(xc, trad_exact, label="$T_\\mathrm{rad}$", lw=2, color=colors[1])
ax1.set_xlabel("$x \\; (\\mathrm{cm})$")
ax1.set_ylabel("$T \\; (\\mathrm{K})$")
ax1.legend(loc="upper left")
ax1.grid(alpha=0.5)
ax1.xaxis.set_ticks_position("both")
ax1.yaxis.set_ticks_position("both")
ax1.tick_params(which="both", direction="in")
plt.minorticks_on()
plt.tight_layout()
fig.savefig(os.path.join(artemis.get_fig_dir(), "rad_shock.png"))

# Check if solution errors are above threshold. See notes above regarding thresholds.
dx = xc[1] - xc[0]
l1_tgas = dx * np.sum(np.abs(tgas - tgas_exact)) / _temperature / _length
l1_trad = dx * np.sum(np.abs(trad - trad_exact)) / _temperature / _length
print(l1_tgas, l1_trad)
if l1_tgas > _thr_gas:
logger.warning(
"Error in gas temperature solution is greater than threshold: "
"l1_tgas: {0} thr: {1}".format(l1_tgas, _thr_gas)
)
analyze_status = False
if l1_trad > _thr_rad:
logger.warning(
"Error in radiation temperature solution is greater than threshold: "
"l1_trad: {0} thr: {1} ".format(l1_trad, _thr_rad)
)
analyze_status = False

return analyze_status
1 change: 1 addition & 0 deletions tst/scripts/radiation/thermalization.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
)
from phdf import phdf

# Plotting style
plt.rc("text", usetex=True)
plt.rc("font", family="serif", size=20)
colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
Expand Down

0 comments on commit 0601078

Please sign in to comment.