Skip to content

SNES timestep control changes#3273

Merged
ZedThree merged 13 commits into
nextfrom
next-snes-controller
Feb 16, 2026
Merged

SNES timestep control changes#3273
ZedThree merged 13 commits into
nextfrom
next-snes-controller

Conversation

@bendudson
Copy link
Copy Markdown
Contributor

  • New enum setting timestep_control replaces pid_controller boolean. Choices are:
    • pid_nonlinear_its that uses a PID controller and the nonlinear iteration count. This is now the default.
    • residual_ratio that uses the ratio of the global residual (Root-Mean-Square of the time derivatives, averaged over all fields and cells). The algorithm is taken from PETSc TSPSEUDO: https://petsc.org/release/manualpages/TS/TSPSEUDO/ .
    • threshold_nonlinear_its is the previous default, that increases and decreases timestep based on thresholds in the number of nonlinear iterations
    • fixed is for testing; no timestep control
  • New enum setting output_trigger changes when outputs are written:
    • fixed_time_interval is the default, outputting at regular time intervals.
    • residual_ratio outputs when the global residual has reduced below a given factor (output_residual_ratio option, default 0.5) times the residual at the previous output. This is a useful measure of progress towards steady state.

bendudson and others added 10 commits February 11, 2026 10:49
Allows the target to be set to push timestep rather than
stall once reaching a set number of iterations.
Calculates a moving average of recent SNES failures.
Enables timestep controllers to be more cautious when SNES
is repeatedly failing.
Separate out the global timestep control into a function
Now always calculates local and global residuals.
If pseudo timestepping is used then another loop over variables
is used to update per-cell timesteps and set `dt_vec`.

When `diagnose=true`, the local residual will be saved as
`snes_local_residual`, and the global residual will be printed
after each internal timestep.
Selects the trigger for writing an output.
The default is `fixed_time_interval` that outputs at regular time
intervals. Other choice is `residual_ratio` that outputs when the
global residual falls by a factor `output_residual_ratio`.
Describe new settings `timestep_control` and `output_trigger` that
select different strategies to adjust global timesteps and
output simulation state.
Save the global residual diagnostic
Uses setting `pid_controller` rather than `pid_nonlinear_its`.
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

int loop_count = 0;
recent_failure_rate = 0.0;

BoutReal start_global_residual = global_residual;
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: variable 'start_global_residual' of type 'BoutReal' (aka 'double') can be declared 'const' [misc-const-correctness]

Suggested change
BoutReal start_global_residual = global_residual;
BoutReal const start_global_residual = global_residual;

Comment thread src/solver/impls/snes/snes.cxx
break;
}
return timestep; // No change
}
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: no header providing "copy" is directly included [misc-include-cleaner]

d
                          ^

}
return timestep; // No change
}

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: no header providing "copy" is directly included [misc-include-cleaner]

;
                             ^

PetscCall(rhs_function(x, snes_f, false));

// Reading the residual vectors
const BoutReal* current_residual = nullptr;
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: pointee of variable 'mesh' of type 'Mesh *' can be declared 'const' [misc-const-correctness]

Suggested change
const BoutReal* current_residual = nullptr;
n const

}
}
}

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: no header providing "mean" is directly included [misc-include-cleaner]

)
                                ^

Comment thread src/solver/impls/snes/snes.hxx
Comment thread src/solver/impls/snes/snes.hxx
bendudson and others added 3 commits February 12, 2026 10:59
False by default. If true, re-uses the Jacobian and preconditioner
across SNES calls.
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/snes/snes.cxx
int loop_count = 0;
recent_failure_rate = 0.0;

BoutReal start_global_residual = global_residual;
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: avoid do-while loops [cppcoreguidelines-avoid-do-while]

    do {
    ^


PetscErrorCode SNESSolver::updateResiduals(Vec x) {
// Push residuals to previous residuals
// Copying so that data is not shared
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: no header providing "copy" is directly included [misc-include-cleaner]

d
                          ^

PetscErrorCode SNESSolver::updateResiduals(Vec x) {
// Push residuals to previous residuals
// Copying so that data is not shared
local_residual_prev = copy(local_residual);
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: no header providing "copy" is directly included [misc-include-cleaner]

;
                             ^

PetscCall(VecGetArrayRead(snes_f, &current_residual));

// Note: The ordering of quantities in the PETSc vectors
// depends on the Solver::loop_vars function
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: pointee of variable 'mesh' of type 'Mesh *' can be declared 'const' [misc-const-correctness]

Suggested change
// depends on the Solver::loop_vars function
n const

// Restore Vec data arrays
PetscCall(VecRestoreArrayRead(snes_f, &current_residual));

// Global residual metric (RMS)
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: no header providing "mean" is directly included [misc-include-cleaner]

)
                                ^

@ZedThree ZedThree merged commit f51d9f1 into next Feb 16, 2026
1 check passed
@ZedThree ZedThree deleted the next-snes-controller branch February 16, 2026 10:54
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