Skip to content

Refactor PETSc preconditioner for CVODE#3382

Open
bendudson wants to merge 15 commits into
nextfrom
refactor-petsc-precon
Open

Refactor PETSc preconditioner for CVODE#3382
bendudson wants to merge 15 commits into
nextfrom
refactor-petsc-precon

Conversation

@bendudson
Copy link
Copy Markdown
Contributor

@bendudson bendudson commented May 29, 2026

Refactors the Jacobian coloring preconditioner and makes it available as a CVODE preconditioner.

test2 from scratch. 10 steps of size 1.

No preconditioning:

CVODE: nsteps 803, nfevals 967, nniters 966, npevals 0, nliters 4132
    -> Newton iterations per step: 1.202989e+00
    -> Linear iterations per Newton iteration: 4.277433e+00
    -> Preconditioner evaluations per Newton: 0.000000e+00
    -> Last step size: 2.046315e-02, order: 2
    -> Local error fails: 0, nonlinear convergence fails: 64
    -> Stability limit order reductions: 0
1.000e+01        292       1.22e+01     3.8    0.0   32.9    0.7   62.6
Run time : 3 m 38 s

User preconditioning:

CVODE: nsteps 237, nfevals 280, nniters 279, npevals 913, nliters 669
    -> Newton iterations per step: 1.177215e+00
    -> Linear iterations per Newton iteration: 2.397849e+00
    -> Preconditioner evaluations per Newton: 3.272401e+00
    -> Last step size: 1.171224e-01, order: 3
    -> Local error fails: 0, nonlinear convergence fails: 2
    -> Stability limit order reductions: 0
1.000e+01         69       5.32e+00   -10.9    0.0   31.0    2.4   77.5
Run time : 1 m 14 s

petsc preconditioning (ksp_type=preonly, pc_type=hypre):

CVODE: nsteps 282, nfevals 326, nniters 325, npevals 787, nliters 479
    -> Newton iterations per step: 1.152482e+00
    -> Linear iterations per Newton iteration: 1.473846e+00
    -> Preconditioner evaluations per Newton: 2.421538e+00
    -> Last step size: 1.976899e-01, order: 4
    -> Local error fails: 0, nonlinear convergence fails: 6
    -> Stability limit order reductions: 0
1.000e+01         16       1.36e+00     2.0    0.0   13.8    7.7   76.6
Run time : 2 m 55 s

With PETSc preconditioning the number of linear iterations per Newton step is small, and the timesteps seem to be bigger than other methods. When using STRUMPACK rather than hypre there is an error on the first iteration but it continues and accelerates after:

[9]PETSC ERROR: STRUMPACK error: factorization failed
[9]PETSC ERROR: #1 MatLUFactorNumeric_STRUMPACK() at /Users/dudson2/code/petsc/src/mat/impls/aij/mpi/strumpack/strumpack.c:986
[9]PETSC ERROR: #2 MatLUFactorNumeric() at /Users/dudson2/code/petsc/src/mat/interface/matrix.c:3312
[9]PETSC ERROR: #3 PCSetUp_LU() at /Users/dudson2/code/petsc/src/ksp/pc/impls/factor/lu/lu.c:121
[9]PETSC ERROR: #4 PCSetUp() at /Users/dudson2/code/petsc/src/ksp/pc/interface/precon.c:1086
[9]PETSC ERROR: #5 KSPSetUp() at /Users/dudson2/code/petsc/src/ksp/ksp/interface/itfunc.c:427

It runs fine with STRUMPACK after the first step, but this factorization failure makes me a bit suspicious.

bendudson added 4 commits May 29, 2026 13:20
Use the same coloring, preconditioning code in CVODE, PETSc and SNES
time-integration solvers.

Major refactoring by Codex. Much more testing needed.
Setting `cvode_precon_method` to `none` disables preconditioning.
The default `auto` uses the user-supplied preconditioner if present,
then PETSc if available, then SUNDIALS' BBD preconditioner.
cvode_lsetup_frequency and cvode_jac_eval_frequency modify
how often the Jacobian and preconditioner are recalculated.
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/solver/impls/cvode/cvode.cxx Outdated
Comment thread src/solver/impls/cvode/cvode.cxx
Comment thread src/solver/impls/cvode/cvode.cxx Outdated
Comment thread src/solver/impls/cvode/cvode.cxx
PetscCall(VecGetArray(f, &fdata));

try {
s->rhs(s->petsc_t, const_cast<BoutReal*>(xdata), s->petsc_rhs_tmp.data(), true);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

warning: do not use const_cast to remove const qualifier [cppcoreguidelines-pro-type-const-cast]

{
                         ^

Comment thread src/solver/impls/snes/snes.cxx Outdated
Comment thread src/solver/petsc_preconditioner.cxx
Comment thread src/solver/petsc_preconditioner.cxx
Comment thread src/solver/petsc_preconditioner.cxx Outdated
Comment thread src/solver/petsc_preconditioner.cxx
`CVodeSetLSetupFrequency` and `CVodeSetJacEvalFrequency` are not
available in Sundials version 4.1.0 on CI.
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/solver/impls/cvode/cvode.cxx Outdated
bendudson added 2 commits May 30, 2026 09:49
test-delp2 answer changes slightly (~1e-6) if preconditioning
is enabled.
Hermes-3 braginskii_conduction creates a "type" subsection
in every section of options. PetscLib throws an exception when
the "petsc" section contains a subsection.
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/solver/impls/cvode/cvode.cxx
Comment thread src/solver/impls/cvode/cvode.cxx Outdated
Comment thread src/solver/petsc_preconditioner.cxx
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clang-tidy made some suggestions

Comment thread src/solver/impls/cvode/cvode.cxx Outdated
Comment on lines +168 to +172
if ((*options)["use_precon"].isSet()) {
output_warn << "WARNING: solver:use_precon is deprecated for CVODE and is now "
"ignored. Use solver:cvode_precon_method=none to disable "
"preconditioning.\n";
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be an error?
We throw also errors for unused options, so I think we should also force the users here to update.

Comment on lines +176 to +177
// around a bug in Hermes-3 braginskii_conduction that creates a
// "petsc:type" subsection.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How hard would it be to fix it in hermes?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fairly straightforward to fix (I've fixed it in a branch) so hopefully this is a short-lived patch.

const int band_width_default = std::accumulate(
begin(f3d), end(f3d), 0, [](int a, const VarStr<Field3D>& fvar) {
const Mesh* localmesh = fvar.var->getMesh();
return a + localmesh->xend - localmesh->xstart + 3;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That means the ddx must only use one guard cell, and higher order stencils will perform poorly, do to wrong preconditioning?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The whole BBD preconditioner is of quite dubious benefit really. It doesn't know anything about spatial stencils so only preconditions coupling between variables that appear next to each other in the 1D state vector. In practice I think that means it's only good for preconditioning coupling between variables in the same cell. I've not yet seen a case where BBD preconditioning improved performance, so it's really here in case someone wants to try it as a last resort.

Comment thread src/solver/impls/petsc/petsc.cxx Outdated
output_progress.write("Creating Jacobian coloring\n");
updateColoring();

#if 0
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems to be the code that has been moved to petsc_preconditioner.cxx, thus I deleted it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants