20#include "pism/stressbalance/ssa/SSAFD_SNES.hh"
21#include "pism/stressbalance/StressBalance.hh"
22#include "pism/util/petscwrappers/Vec.hh"
26namespace stressbalance {
29 PetscReal f, SNESConvergedReason *reason,
void *ctx) {
35 ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx); CHKERRQ(ierr);
36 if (*reason >= 0 and tolerance > 0) {
39 ierr = SNESGetFunction(snes, &residual, NULL, NULL);
43 ierr = VecNorm(residual, NORM_INFINITY, &norm);
46 if (norm <= tolerance) {
47 *reason = SNES_CONVERGED_FNORM_ABS;
55 return m_config->get_number(
"stress_balance.ssa.fd.absolute_tolerance");
59 :
SSAFDBase(grid, regional_mode), m_residual(grid,
"_ssa_residual") {
77 ierr = DMDASNESSetFunctionLocal(*
m_DA, INSERT_VALUES,
78#
if PETSC_VERSION_LT(3,21,0)
84 PISM_CHK(ierr,
"DMDASNESSetFunctionLocal");
86 ierr = DMDASNESSetJacobianLocal(*
m_DA,
87#
if PETSC_VERSION_LT(3,21,0)
93 PISM_CHK(ierr,
"DMDASNESSetJacobianLocal");
99 PISM_CHK(ierr,
"DMSetApplicationContext");
101 ierr = SNESSetOptionsPrefix(
m_snes,
"ssafd_");
102 PISM_CHK(ierr,
"SNESSetOptionsPrefix");
108 PISM_CHK(ierr,
"SNESSetConvergenceTest");
110 ierr = SNESSetTolerances(
m_snes, 0.0, 0.0, 0.0, 500, -1);
111 PISM_CHK(ierr,
"SNESSetTolerances");
113 ierr = SNESSetFromOptions(
m_snes);
114 PISM_CHK(ierr,
"SNESSetFromOptions");
129 SNESConvergedReason reason;
130 ierr = SNESGetConvergedReason(
m_snes, &reason);
131 PISM_CHK(ierr,
"SNESGetConvergedReason");
134 "SSAFD_SNES solve failed to converge (SNES reason %s)",
135 SNESConvergedReasons[reason]);
138 PetscInt snes_iterations = 0;
139 ierr = SNESGetIterationNumber(
m_snes, &snes_iterations);
140 PISM_CHK(ierr,
"SNESGetIterationNumber");
142 PetscInt ksp_iterations = 0;
143 ierr = SNESGetLinearSolveIterations(
m_snes, &ksp_iterations);
144 PISM_CHK(ierr,
"SNESGetLinearSolveIterations");
146 m_log->message(1,
"SSA: %d*%d its, %s\n", (
int)snes_iterations,
147 (
int)(ksp_iterations / std::max((
int)snes_iterations, 1)),
148 SNESConvergedReasons[reason]);
165 MPI_Comm com = MPI_COMM_SELF;
166 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)data->
da, &com);
169 SETERRQ(com, 1,
"A PISM callback failed");
181 Vector2d const *
const *
const velocity, Mat ,
186 MPI_Comm com = MPI_COMM_SELF;
187 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)data->
da, &com);
190 SETERRQ(com, 1,
"A PISM callback failed");
208 m_vars[0].long_name(
"magnitude of the SSAFD solver's residual").units(
"Pa");
213 auto result = allocate<array::Scalar>(
"ssa_residual_mag");
214 result->metadata(0) =
m_vars[0];
216 compute_magnitude(
model->residual(), *result);
const Config::ConstPtr m_config
configuration database used by this component
const Logger::ConstPtr m_log
logger (for easy access)
const std::shared_ptr< const Grid > m_grid
grid used by this component
A template derived from Diagnostic, adding a "Model".
static Ptr wrap(const T &input)
const units::System::Ptr m_sys
the unit system
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
std::shared_ptr< Diagnostic > Ptr
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
void copy_from(const Array2D< T > &source)
void fd_operator(const Geometry &geometry, const array::Scalar *bc_mask, double bc_scaling, const array::Scalar &basal_yield_stress, IceBasalResistancePlasticLaw *basal_sliding_law, const pism::Vector2d *const *velocity, const array::Staggered1 &nuH, const array::CellType1 &cell_type, Mat *A, Vector2d **Ax) const
Assemble the left-hand side matrix for the KSP-based, Picard iteration, and finite difference impleme...
void initialize_iterations(const Inputs &inputs)
array::Staggered1 m_nuH
viscosity times thickness
array::CellType2 m_cell_type
const double m_bc_scaling
scaling used for diagonal matrix elements at Dirichlet BC locations
DiagnosticList diagnostics_impl() const
void compute_residual(const Inputs &inputs, const array::Vector2 &velocity, array::Vector &result)
CallbackData m_callback_data
const array::Vector & residual() const
DiagnosticList diagnostics_impl() const
void solve(const Inputs &inputs)
SSAFD_SNES(std::shared_ptr< const Grid > grid, bool regional_mode)
static PetscErrorCode jacobian_callback(DMDALocalInfo *info, Vector2d const *const *velocity, Mat A, Mat J, CallbackData *data)
static PetscErrorCode function_callback(DMDALocalInfo *info, Vector2d const *const *velocity, Vector2d **result, CallbackData *)
void compute_jacobian(const Inputs &inputs, Vector2d const *const *velocity, Mat J)
array::Vector m_residual
residual (diagnostic)
SSAFD_residual_mag(const SSAFD_SNES *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes the magnitude of the driving shear stress at the base of ice (diagnostically).
array::Vector m_velocity_global
const array::Vector1 & velocity() const
Get the thickness-advective 2D velocity.
IceBasalResistancePlasticLaw * m_basal_sliding_law
array::Vector2 m_velocity
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
PetscErrorCode SSAFDSNESConvergenceTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal gnorm, PetscReal f, SNESConvergedReason *reason, void *ctx)
std::map< std::string, Diagnostic::Ptr > DiagnosticList
void handle_fatal_errors(MPI_Comm com)