Skip to content

(optionally) add T/e correction term to Strang Jacobians #1595

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: development
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
a397a43
add a runtime parameter to disable the T/e correction term in Jacobians
zingale Jun 26, 2024
626d852
add the corrections to Strang
zingale Jun 26, 2024
5dc7409
fix compilation
zingale Jun 26, 2024
da31904
fix the fix
zingale Jun 26, 2024
09aa7b8
update jacobian docs
zingale Jun 28, 2024
5683362
more fixes
zingale Jun 28, 2024
ae358b6
Merge branch 'development' into jacobian_correction
zingale Jun 28, 2024
c7675ea
Merge branch 'development' into jacobian_correction
zingale Jun 28, 2024
9f219ab
Merge branch 'development' into jacobian_correction
zingale Jul 8, 2024
882287e
Merge branch 'development' into jacobian_correction
zingale Jul 8, 2024
2738b96
Merge branch 'development' into jacobian_correction
zingale Jul 8, 2024
74d9f07
Merge branch 'development' into jacobian_correction
zingale Jul 11, 2024
0de4ffc
Merge branch 'development' into jacobian_correction
zingale Jul 11, 2024
dc6341c
Merge branch 'development' into jacobian_correction
zingale Jul 12, 2024
36cb234
Merge branch 'development' into jacobian_correction
zingale Jul 14, 2024
49640b6
Merge branch 'development' into jacobian_correction
zingale Jul 15, 2024
cde76f9
Merge branch 'development' into jacobian_correction
zingale Jul 17, 2024
b937188
Merge branch 'development' into jacobian_correction
zingale Jul 17, 2024
eecaccd
Merge branch 'development' into jacobian_correction
zingale Jul 18, 2024
d31cb0f
Merge branch 'development' into jacobian_correction
zingale Jul 23, 2024
993ec72
Merge branch 'development' into jacobian_correction
zingale Jul 26, 2024
d878650
Merge branch 'development' into jacobian_correction
zingale Jul 31, 2024
4ee9302
sync
zingale Jul 31, 2024
39756e3
Merge branch 'development' into jacobian_correction
zingale Aug 26, 2024
bf77ccf
Merge branch 'development' into jacobian_correction
zingale Sep 3, 2024
1ace2c9
Merge branch 'development' into jacobian_correction
zingale Oct 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/burn_cell.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
- name: Run burn_cell (VODE, ignition_chamulak)
run: |
cd unit_test/burn_cell
./main3d.gnu.ex inputs_ignition_chamulak amrex.fpe_trap_{invalid,zero,overflow}=1 > test.out
./main3d.gnu.ex inputs_ignition_chamulak integrator.correct_jacobian_for_const_e=0 amrex.fpe_trap_{invalid,zero,overflow}=1> test.out

- name: Compare to stored output (VODE, ignition_chamulak)
run: |
Expand Down
5 changes: 5 additions & 0 deletions integration/_parameters
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,8 @@ nse_include_enu_weak bool 1

# for the linear algebra, do we allow pivoting?
linalg_do_pivoting bool 1

# when converting the Jacobian from (rho, Y, T) to (rho, X, e), do
# we add a correction to the species terms reflecting that
# dT/dX at constant e is not zero?
correct_jacobian_for_const_e bool 1
49 changes: 27 additions & 22 deletions integration/integrator_rhs_sdc.H
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,17 @@ void jac (const amrex::Real time, BurnT& state, T& int_state, MatrixType& pd)

// The Jacobian from the nets is in terms of dYdot/dY, but we want
// it was dXdot/dX, so convert here.

for (int jcol = 1; jcol <= neqs; ++jcol) {
for (int irow = 1; irow <= NumSpec; irow++) {
pd(irow, jcol) = pd(irow, jcol) * aion[irow-1];
if (!integrator_rp::use_number_densities) {
for (int jcol = 1; jcol <= neqs; ++jcol) {
for (int irow = 1; irow <= NumSpec; irow++) {
pd(irow, jcol) = pd(irow, jcol) * aion[irow-1];
}
}
}

for (int jcol = 1; jcol <= NumSpec; ++jcol) {
for (int irow = 1; irow <= neqs; ++irow) {
pd(irow, jcol) = pd(irow, jcol) * aion_inv[jcol-1];
for (int jcol = 1; jcol <= NumSpec; ++jcol) {
for (int irow = 1; irow <= neqs; ++irow) {
pd(irow, jcol) = pd(irow, jcol) * aion_inv[jcol-1];
}
}
}

Expand All @@ -148,26 +149,30 @@ void jac (const amrex::Real time, BurnT& state, T& int_state, MatrixType& pd)
// now correct the species derivatives
// this constructs dy/dX_k |_e = dy/dX_k |_T - e_{X_k} |_T dy/dT / c_v

eos_re_extra_t eos_state;
eos_state.rho = state.rho;
eos_state.T = state.T;
eos_state.e = state.e;
for (int n = 0; n < NumSpec; n++) {
eos_state.xn[n] = state.xn[n];
}
if (integrator_rp::correct_jacobian_for_const_e) {

eos_re_extra_t eos_state;
eos_state.rho = state.rho;
eos_state.T = state.T;
eos_state.e = state.e;
for (int n = 0; n < NumSpec; n++) {
eos_state.xn[n] = state.xn[n];
}
#ifdef AUX_THERMO
// make the aux data consistent with the state X's
set_aux_comp_from_X(eos_state);
// make the aux data consistent with the state X's
set_aux_comp_from_X(eos_state);
#endif

eos(eos_input_re, eos_state);
eos(eos_input_re, eos_state);

eos_xderivs_t eos_xderivs = composition_derivatives(eos_state);
eos_xderivs_t eos_xderivs = composition_derivatives(eos_state);

for (int jcol = 1; jcol <= NumSpec;++jcol) {
for (int irow = 1; irow <= neqs; ++irow) {
pd(irow, jcol) -= eos_xderivs.dedX[jcol-1] * pd(irow, net_ienuc);
for (int jcol = 1; jcol <= NumSpec;++jcol) {
for (int irow = 1; irow <= neqs; ++irow) {
pd(irow, jcol) -= eos_xderivs.dedX[jcol-1] * pd(irow, net_ienuc);
}
}

}

// apply scale_system scaling (if needed)
Expand Down
41 changes: 41 additions & 0 deletions integration/integrator_rhs_strang.H
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,47 @@ void jac ([[maybe_unused]] const amrex::Real time, BurnT& state, T& int_state, M
}
}

// The system we integrate has the form (rho X_k, rho e)

// pd is now of the form:
//
// SFS / d(rho X1dot)/dX1 d(rho X1dit)/dX2 ... 1/cv d(rho X1dot)/dT \ //
// | d(rho X2dot)/dX1 d(rho X2dot)/dX2 ... 1/cv d(rho X2dot)/dT |
// SFS-1+nspec | ... |
// SEINT \ d(rho Edot)/dX1 d(rho Edot)/dX2 ... 1/cv d(rho Edot)/dT /
//
// SFS SEINT

// now correct the species derivatives
// this constructs dy/dX_k |_e = dy/dX_k |_T - e_{X_k} |_T dy/dT / c_v

if (integrator_rp::correct_jacobian_for_const_e) {

eos_re_extra_t eos_state;
eos_state.rho = state.rho;
eos_state.T = state.T;
eos_state.e = state.e;
for (int n = 0; n < NumSpec; n++) {
eos_state.xn[n] = state.xn[n];
}
#ifdef AUX_THERMO
// make the aux data consistent with the state X's
set_aux_comp_from_X(eos_state);
#endif

eos(eos_input_re, eos_state);

eos_xderivs_t eos_xderivs = composition_derivatives(eos_state);

for (int jcol = 1; jcol <= NumSpec;++jcol) {
for (int irow = 1; irow <= neqs; ++irow) {
pd(irow, jcol) -= eos_xderivs.dedX[jcol-1] * pd(irow, net_ienuc);
}
}

}


// scale the energy derivatives

if (integrator_rp::scale_system) {
Expand Down
111 changes: 98 additions & 13 deletions sphinx_docs/source/integrators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -197,12 +197,16 @@ fields to fill are:
* ``state.ydot(net_ienuc)`` : the change in the internal energy
from the net, :math:`de/dt`

The righthand side routine is assumed to return the change in *molar fractions*,
:math:`dY_k/dt`. These will be converted to the change in mass fractions, :math:`dX_k/dt`
by the wrappers that call the righthand side routine for the integrator.
If the network builds the RHS in terms of mass fractions directly, :math:`dX_k/dt`, then
these will need to be converted to molar fraction rates for storage, e.g.,
:math:`dY_k/dt = A_k^{-1} dX_k/dt`.
.. important::

The righthand side routine is assumed to return the change in
*molar fractions*, :math:`dY_k/dt`. These will be converted to the
change in mass fractions, :math:`dX_k/dt` by the wrappers that call
the righthand side routine for the integrator. If the network
builds the RHS in terms of mass fractions directly,
:math:`dX_k/dt`, then these will need to be converted to molar
fraction rates for storage, e.g., :math:`dY_k/dt = A_k^{-1}
dX_k/dt`.

Righthand side wrapper
^^^^^^^^^^^^^^^^^^^^^^
Expand Down Expand Up @@ -259,15 +263,42 @@ The Jacobian matrix elements are stored in ``jac`` as:
* ``jac(net_ienuc, net_ienuc)`` :
:math:`d(\dot{e})/de`

The form looks like:
.. important::

The Jacobian returned by the network is assumed to be in terms of molar fractions.
However, we do convert the temperature derivative to an energy derivative already
in the network by multiplying by $(1/c_v)$.

The form of the Jacobian return by the integrator looks like:

.. math::
\left (
\begin{matrix}
\ddots & \vdots & & \vdots \\
\cdots & \partial \dot{Y}_m/\partial Y_n & \cdots & \partial \dot{Y}_m/\partial e \\
& \vdots & \ddots & \vdots \\
\cdots & \partial \dot{e}/\partial Y_n & \cdots & \partial \dot{e}/\partial e \\
\dfrac{\partial \dot{Y}_1}{\partial Y_1} &
\dfrac{\partial \dot{Y}_1}{\partial Y_2} &
\cdots &
\dfrac{\partial \dot{Y}_1}{\partial Y_\mathrm{NumSpec}} &
\dfrac{1}{c_v} \dfrac{\partial \dot{Y}_1}{\partial T} \\
%
\dfrac{\partial \dot{Y}_2}{\partial Y_1} &
\dfrac{\partial \dot{Y}_2}{\partial Y_2} &
\cdots &
\dfrac{\partial \dot{Y}_2}{\partial Y_\mathrm{NumSpec}} &
\dfrac{1}{c_v} \dfrac{\partial \dot{Y}_2}{\partial T} \\
%
\vdots & \vdots & \ddots & \vdots & \vdots \\
%
\dfrac{\partial \dot{Y}_\mathrm{NumSpec}}{\partial Y_1} &
\dfrac{\partial \dot{Y}_\mathrm{NumSpec}}{\partial Y_2} &
\cdots &
\dfrac{\partial \dot{Y}_\mathrm{NumSpec}}{\partial Y_\mathrm{NumSpec}} &
\dfrac{1}{c_v} \dfrac{\partial \dot{Y}_\mathrm{NumSpec}}{\partial T} \\
%
\dfrac{\partial \dot{e}}{\partial Y_1} &
\dfrac{\partial \dot{e}}{\partial Y_2} &
\cdots &
\dfrac{\partial \dot{e}}{\partial Y_\mathrm{NumSpec}} &
\dfrac{1}{c_v} \dfrac{\partial \dot{e}}{\partial T}
\end{matrix}
\right )

Expand Down Expand Up @@ -296,16 +327,70 @@ flow is (for VODE):
wrapper above which did the ``clean_state`` and
``update_thermodynamics`` calls.

.. index:: integrator.react_boost
.. index:: integrator.react_boost, integrator.correct_jacobian_for_const_e

#. call ``integrator_to_burn()`` to update the ``burn_t``

#. call ``actual_jac()`` to have the network fill the Jacobian array

#. convert the derivative to be mass-fraction-based
#. convert the derivative to be mass-fraction-based.

Since $Y_k = X_k/A_k$, we have $\partial/\partial X_k = A_k^{-1} \partial/\partial Y_k$.

We transform by:

* multiplying all rows of the form $\partial Y_m / \partial \star$ by $A_m$ (where $\star$ is either a molar fraction or $T$/$e$).

* multiplying all columns of the form $\partial \star / \partial Y_n$ by $1/A_n$.

#. add correction
terms proportional to :math:`\partial e/\partial X_k |_{\rho, T, X_{j,j\ne k}}`
if ``integrator.correct_jacobian_for_const_e`` is ``1``.

The system we integrate is $(X_k, e)$, but the derivatives we took in the analytic Jacobian
were in terms of $T$ and not $e$. So we need to correct for the fact that for some quantity
$q$,

.. math::

\left . \frac{\partial q}{\partial X_k} \right |_e \ne \left . \frac{\partial q}{\partial X_k} \right |_T

If we write $q = q(\rho, T(\rho, X_k, e), X_k)$ then we find that:

.. math::

\left . \frac{\partial q}{\partial X_k} \right |_{\rho, e, X_{j,j\ne k}} =
\left . \frac{\partial q}{\partial X_k} \right |_{\rho, T, X_{j,j\ne k}} - \frac{e_{X_k}}{c_v} \left . \frac{\partial T}{\partial X_k} \right |_{\rho, e, X_{j,j\ne k}}

where :math:`e_{X_k} = \partial e / \partial X_k |_{\rho, T, X_{j,j\ne k}}`.

This correction term is described in :cite:`castro_simple_sdc`.

#. apply any boosting to the rates if ``integrator.react_boost`` > 0

The final form of the Jacobian is:

.. math::
\left (
\begin{matrix}
\dfrac{\partial \dot{X}_1}{\partial X_1} - \dfrac{e_{X_1}}{c_v} \dfrac{\partial \dot{X}_1}{\partial T} &
\dfrac{\partial \dot{X}_1}{\partial X_2} - \dfrac{e_{X_2}}{c_v} \dfrac{\partial \dot{X}_1}{\partial T} &
\cdots &
\dfrac{1}{c_v} \dfrac{\partial \dot{X}_1}{\partial T} \\
%
\dfrac{\partial \dot{X}_2}{\partial X_1} - \dfrac{e_{X_1}}{c_v} \dfrac{\partial \dot{X}_2}{\partial T} &
\dfrac{\partial \dot{X}_2}{\partial X_2} - \dfrac{e_{X_2}}{c_v} \dfrac{\partial \dot{X}_2}{\partial T} &
\cdots &
\dfrac{1}{c_v} \dfrac{\partial \dot{X}_2}{\partial T} \\
%
\vdots & \vdots & \ddots & \vdots \\
%
\dfrac{\partial \dot{e}}{\partial X_1} - \dfrac{e_{X_1}}{c_v} \dfrac{\partial \dot{e}}{\partial T} &
\dfrac{\partial \dot{e}}{\partial X_2} - \dfrac{e_{X_2}}{c_v} \dfrac{\partial \dot{e}}{\partial T} &
\cdots &
\dfrac{1}{c_v} \dfrac{\partial \dot{e}}{\partial T}
\end{matrix}
\right )



Expand Down
5 changes: 5 additions & 0 deletions sphinx_docs/source/sdc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,3 +239,8 @@ for a reaction network.
system was more complicated, and we included density in ${\bf w}$.
This is not needed, and we use the Jacobian defined in
:cite:`castro_simple_sdc` instead.

.. note::

The final form of the Jacobian is identical to the one used in
Strang integration.
Loading