Spectral Deferred Corrections
Introduction
Spectral deferred correction (SDC) methods strongly couple reactions and hydrodynamics, eliminating the splitting error that arises with Strang (operator) splitting. Microphysics supports two different SDC formulations.
We want to solve the coupled equations:
where \(\Uc\) is the conserved state vector, \(\Uc = (\rho, (\rho X_k), (\rho \Ub), (\rho E))^\intercal\). Here, \(\rho\) is the density, \(X_k\) are the mass fractions constrained via \(\sum_k X_k = 1\), \(\Ub\) is the velocity vector, and \(E\) is the specific total energy, related to the specific internal energy, \(e\), via
The quantity \(\Advs{\Uc}\) represents the advective source term (including any hydrodynamical sources),
and \(\Rb(\Uc)\) is the reaction source term.
Note
Application codes can set the make variables USE_TRUE_SDC
or
USE_SIMPLIFIED_SDC
. But in Microphysics, both SDC formulations
are supported by the same integrators, and both of these options
will set the SDC
preprocessor flag.
“True” SDC
The true SDC implementation is described in [ZingaleKatzBell+19]. It divides the timestep into temporal nodes and uses low-order approximations to update from one temporal node to the next. Iteration is used to increase the order of accuracy.
The update from one temporal node, \(m\), to the next, \(m\), for iteration \(k+1\) appears as:
Solving this requires a nonlinear solve of:
where the right-hand side is constructed only from known states, and we define \({\bf C}\) for convenience as:
This can be cast as an ODE system as:
Simplified SDC
The Simplified-SDC method uses the ideas of the SDC method above, but instead of dividing time into discrete temporary notes, it uses a piecewise-constant-in-time approximation to the advection update over the timestep (for instance, computed by the CTU PPM method) and solves the ODE system:
and uses iteration to improve the advective term based on the reactions. The full details of the algorithm are presented in [ZKNR22].
Common ground
Both SDC formulations result in an ODE system of the form:
where \(\Uc^\prime\) is only
since those are the only components with reactive sources.
The SDC
burner includes storage for the advective terms.
Interface and Data Structures
For concreteness, we use the simplified-SDC formulation in the description below, but the true-SDC version is directly analogous.
burn_t
To accommodate the increased information required to evolve the
coupled system, the burn_t
used for Strang integration is extended
to include the conserved state and the advective sources. This is
used to pass information to/from the integration routine from the
hydrodynamics code.
ODE system
The reactions don’t modify the total density, \(\rho\), or momentum, \(\rho \Ub\), so our ODE system is just:
Here the advective terms are piecewise-constant (in time) approximations to the change in the state due to the hydrodynamics, computed with the during the hydro step.
However, to define the temperature, we need the density at any intermediate time, \(t\). We construct these as needed from the time-advanced momenta:
Interfaces
actual_integrator
The main driver, actual_integrator
, is nearly identical to the Strang counterpart. The
main difference is that it interprets the absolute tolerances in terms of \((\rho X_k)\)
instead of \(X_k\).
The flow of this main routine is:
Convert from the
burn_t
type to the integrator’s internal representation usingburn_to_int()
.This copies the state variables into the integration type and stores the initial density.
Call the main integration routine to advance the inputs state through the desired time interval, producing the new, output state.
Convert back from the internal representation to the
burn_t
by callingint_to_burn()
.
Righthand side wrapper
The manipulation of the righthand side is a little more complex now. Each network only provides the change in molar fractions and internal energy, but we need to convert these to the conservative system we are integrating, including the advective terms.
Note
Presently only the VODE
and BackwardEuler
integrators supports SDC evolution.
Get the current density by calling
update_density_in_time()
Call
clean_state
to ensure that the mass fractions are validConvert the integrator-specific data structures to a
burn_t
viaint_to_burn()
.Update the density (this may be redundant).
Fill the
burn_t
’sxn[]
, auxiliary data, internal energy, and call the EOS to get the temperature.
Call the
actual_rhs()
routine to get just the reaction sources to the update. In particular, this returns the change in molar fractions, \(\dot{Y}_k\) and the nuclear energy release, \(\dot{S}\).Convert back to the integrator’s internal representation via
rhs_to_int
This converts theydot
to mass fractions and adds the advective terms toydot
.
Jacobian
The Jacobian of this system is \({\bf J} = \partial \Rb / \partial \Uc\), since \(\Advs{\Uc}\) is held constant during the integration. We follow the approach of [ZKNR22] and factor the Jacobian as:
where \({\bf w} = (X_k, T)^\intercal\) are the more natural variables for a reaction network.
Note
In the original “true SDC” paper [ZingaleKatzBell+19], the matrix system was more complicated, and we included density in \({\bf w}\). This is not needed, and we use the Jacobian defined in [ZKNR22] instead.