21#include "pism/stressbalance/ssa/SSAFD_SNES.hh"
22#include "pism/stressbalance/StressBalance.hh"
23#include "pism/util/petscwrappers/Vec.hh"
24#include "pism/util/Logger.hh"
27namespace stressbalance {
30 PetscReal f, SNESConvergedReason *reason,
void *ctx) {
36 ierr = SNESConvergedDefault(snes, it, xnorm, gnorm, f, reason, ctx); CHKERRQ(ierr);
37 if (*reason >= 0 and tolerance > 0) {
40 ierr = SNESGetFunction(snes, &residual, NULL, NULL);
44 ierr = VecNorm(residual, NORM_INFINITY, &norm);
47 if (norm <= tolerance) {
48 *reason = SNES_CONVERGED_FNORM_ABS;
56 return m_config->get_number(
"stress_balance.ssa.fd.absolute_tolerance");
60 :
SSAFDBase(grid, regional_mode), m_residual(grid,
"_ssa_residual") {
78 ierr = DMDASNESSetFunctionLocal(*
m_DA, INSERT_VALUES,
79#
if PETSC_VERSION_LT(3,21,0)
85 PISM_CHK(ierr,
"DMDASNESSetFunctionLocal");
87 ierr = DMDASNESSetJacobianLocal(*
m_DA,
88#
if PETSC_VERSION_LT(3,21,0)
94 PISM_CHK(ierr,
"DMDASNESSetJacobianLocal");
100 PISM_CHK(ierr,
"DMSetApplicationContext");
102 ierr = SNESSetOptionsPrefix(
m_snes,
"ssafd_");
103 PISM_CHK(ierr,
"SNESSetOptionsPrefix");
109 PISM_CHK(ierr,
"SNESSetConvergenceTest");
111 ierr = SNESSetTolerances(
m_snes, 0.0, 0.0, 0.0, 500, -1);
112 PISM_CHK(ierr,
"SNESSetTolerances");
114 ierr = SNESSetFromOptions(
m_snes);
115 PISM_CHK(ierr,
"SNESSetFromOptions");
130 SNESConvergedReason reason;
131 ierr = SNESGetConvergedReason(
m_snes, &reason);
132 PISM_CHK(ierr,
"SNESGetConvergedReason");
135 "SSAFD_SNES solve failed to converge (SNES reason %s)",
136 SNESConvergedReasons[reason]);
139 PetscInt snes_iterations = 0;
140 ierr = SNESGetIterationNumber(
m_snes, &snes_iterations);
141 PISM_CHK(ierr,
"SNESGetIterationNumber");
143 PetscInt ksp_iterations = 0;
144 ierr = SNESGetLinearSolveIterations(
m_snes, &ksp_iterations);
145 PISM_CHK(ierr,
"SNESGetLinearSolveIterations");
147 m_log->message(1,
"SSA: %d*%d its, %s\n", (
int)snes_iterations,
148 (
int)(ksp_iterations / std::max((
int)snes_iterations, 1)),
149 SNESConvergedReasons[reason]);
166 MPI_Comm com = MPI_COMM_SELF;
167 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)data->
da, &com);
170 SETERRQ(com, 1,
"A PISM callback failed");
182 Vector2d const *
const *
const velocity, Mat ,
187 MPI_Comm com = MPI_COMM_SELF;
188 PetscErrorCode ierr = PetscObjectGetComm((PetscObject)data->
da, &com);
191 SETERRQ(com, 1,
"A PISM callback failed");
209 m_vars[0].long_name(
"magnitude of the SSAFD solver's residual").units(
"Pa");
214 auto result = allocate<array::Scalar>(
"ssa_residual_mag");
215 result->metadata(0) =
m_vars[0];
217 compute_magnitude(
model->residual(), *result);
std::shared_ptr< const Config > m_config
configuration database used by this component
const std::shared_ptr< const Grid > m_grid
grid used by this component
std::shared_ptr< const Logger > m_log
logger (for easy access)
A template derived from Diagnostic, adding a "Model".
std::vector< VariableMetadata > m_vars
metadata corresponding to NetCDF variables
static Ptr wrap(const T &input)
const units::System::Ptr m_sys
the unit system
std::shared_ptr< Diagnostic > Ptr
std::shared_ptr< const Grid > m_grid
the grid
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
void compute_residual(const Inputs &inputs, const array::Vector2 &velocity, array::Vector &result)
DiagnosticList spatial_diagnostics_impl() const
CallbackData m_callback_data
const array::Vector & residual() const
void solve(const Inputs &inputs)
std::shared_ptr< petsc::DM > m_DA
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)
DiagnosticList spatial_diagnostics_impl() const
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)