History Output#

Athelas writes a scalar history file for time-series quantities such as total mass, total energy, boundary fluxes, and optional diagnostic trackers. History output is intended for inexpensive quantities that can be represented by one value per output time.

The history file is a plain text table. The first line is a header beginning with #. Each column is described by an integer index followed by the column name:

# 0 Time [s] 1 Total Mass [g] 2 Total Energy [erg] ...

All subsequent rows contain floating-point values in the same order. The first column is always simulation time.

Input Deck#

History output is configured under config.output.history:

config.output = {
  dt_hdf5 = 1.0e-2,
  history = {
    fn = "model.hst",
    dt = 1.0e-3,
  },
}

The relevant controls are:

  • history.fn – history filename. The default is based on the problem name.

  • history.dt – history output cadence. If omitted, it defaults to a fraction of the HDF5 output cadence.

The output directory is controlled by the normal command-line -o option or the corresponding parsed output.dir parameter.

Built-In Quantities#

The driver registers a standard set of global conservation and boundary quantities, including:

  • Total Mass [g]

  • Total Energy [erg]

  • Total Fluid Energy [erg]

  • Total Fluid Momentum [g cm / s]

  • Total Internal Energy [erg]

  • Total Kinetic Energy [erg]

  • Total Momentum [g cm / s]

  • Fluid Boundary Energy Rate [erg / s]

Additional columns are registered when their physics packages are enabled. For example, radiation runs add radiation energy, radiation momentum, and radiation boundary energy rate columns. Nickel heating runs add total isotope masses.

Gravity runs add, among others:

  • Total Gravitational Energy [erg] – the discrete potential energy \(W_h = \sum_q H_q \varphi_q\), which is the quantity the weak gravity energy source is constructed to conserve against.

  • Cumulative Limiter Mesh Work [erg] – gravitational potential energy moved by the limiters relocating interior nodes, rather than by any physical source. A measure of limiter dissipation.

  • Cumulative Limiter Energy Correction [erg] and Cumulative Limiter Energy Clamp Residual [erg] – when the limiter energy correction is enabled, the energy it returned to the fluid and the shortfall the EOS floor prevented returning. Both zero when the correction is off.

See Gravity for what these diagnose and how to interpret a nonzero value.

Diagnostics can also add history columns. For example, enabling the shock tracker adds:

  • Shock Radius [cm]

  • Shock Cell Index

  • Shock Compression [1 / s]

See Diagnostics for the available tracker quantities and their meanings.

Developer Notes#

History quantities are registered with HistoryOutput during driver initialization. The simple path is add_quantity, which registers one column from a callback:

history.add_quantity("Total Mass [g]", analysis::total_mass);

The callback has the signature:

double(const MeshState &, const Mesh &)

For related columns that share an expensive calculation, use add_quantities. It registers several adjacent columns from one callback:

history.add_quantities(
    {"Shock Radius [cm]", "Shock Cell Index", "Shock Compression [1 / s]"},
    [](const MeshState &state, const Mesh &mesh) {
      const auto shock = diagnostics::detect_shock(state, mesh);
      return std::vector<double>{shock.radius, shock.cell,
                                 shock.compression};
    });

This keeps HistoryOutput stateless across writes while avoiding duplicate work within a single row. The callback is evaluated once per history write and must return exactly one value for each registered column name.

Output-Time State#

Before a history row is written, the driver refreshes derived quantities and then runs output-only diagnostic preparation. For example, the optical-depth profile is filled at output cadence before the photosphere history tracker reads it. This keeps history callbacks simple: they should read the current MeshState and Mesh and return scalar values, but they should not advance the solution or mutate timestep state.