19#include "pism/inverse/IP_SSATaucTikhonovGNSolver.hh"
20#include "pism/util/TerminationReason.hh"
21#include "pism/util/pism_options.hh"
22#include "pism/util/Config.hh"
23#include "pism/util/Grid.hh"
24#include "pism/util/Context.hh"
25#include "pism/util/petscwrappers/Vec.hh"
26#include "pism/util/petscwrappers/DM.hh"
27#include "pism/util/Logger.hh"
36 : m_design_stencil_width(d0.stencil_width()),
37 m_state_stencil_width(u_obs.stencil_width()),
38 m_ssaforward(ssaforward),
40 m_tmp_D1Global(d0.grid(),
"work vector"),
41 m_tmp_D2Global(d0.grid(),
"work vector"),
42 m_tmp_D1Local(d0.grid(),
"work vector"),
43 m_tmp_D2Local(d0.grid(),
"work vector"),
44 m_tmp_S1Global(d0.grid(),
"work vector"),
45 m_tmp_S2Global(d0.grid(),
"work vector"),
46 m_tmp_S1Local(d0.grid(),
"work vector"),
47 m_tmp_S2Local(d0.grid(),
"work vector"),
48 m_GN_rhs(d0.grid(),
"GN_rhs"),
50 m_dGlobal(d0.grid(),
"d (sans ghosts)"),
51 m_d_diff(d0.grid(),
"d_diff"),
52 m_d_diff_lin(d0.grid(),
"d_diff linearized"),
54 m_hGlobal(d0.grid(),
"h (sans ghosts)"),
55 m_dalpha_rhs(d0.grid(),
"dalpha rhs"),
56 m_dh_dalpha(d0.grid(),
"dh_dalpha"),
57 m_dh_dalphaGlobal(d0.grid(),
"dh_dalpha"),
58 m_grad_design(d0.grid(),
"grad design"),
59 m_grad_state(d0.grid(),
"grad design"),
60 m_gradient(d0.grid(),
"grad design"),
62 m_u_diff(d0.grid(),
"du"),
64 m_designFunctional(designFunctional),
65 m_stateFunctional(stateFunctional),
69 std::shared_ptr<const Grid> grid =
m_d0.
grid();
72 m_d = std::make_shared<DesignVecGhosted>(grid,
"d");
77 ierr = KSPSetOptionsPrefix(
m_ksp,
"inv_gn_");
78 PISM_CHK(ierr,
"KSPSetOptionsPrefix");
80 double ksp_rtol = 1e-5;
81 ierr = KSPSetTolerances(
m_ksp, ksp_rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
84 ierr = KSPSetType(
m_ksp, KSPCG);
88 ierr = KSPGetPC(
m_ksp, &pc);
91 ierr = PCSetType(pc, PCNONE);
94 ierr = KSPSetFromOptions(
m_ksp);
97 int nLocalNodes = grid->xm()*grid->ym();
98 int nGlobalNodes = grid->Mx()*grid->My();
99 ierr = MatCreateShell(grid->com, nLocalNodes, nLocalNodes,
113 auto config = grid->ctx()->config();
141 ierr = DMGlobalToLocalBegin(*
m_x.
dm(), x, INSERT_VALUES,
m_x.
vec());
142 PISM_CHK(ierr,
"DMGlobalToLocalBegin");
144 ierr = DMGlobalToLocalEnd(*
m_x.
dm(), x, INSERT_VALUES,
m_x.
vec());
145 PISM_CHK(ierr,
"DMGlobalToLocalEnd");
158 ierr = VecCopy(GNx.
vec(), y);
PISM_CHK(ierr,
"VecCopy");
185 KSPConvergedReason ksp_reason;
186 ierr = KSPGetConvergedReason(
m_ksp ,&ksp_reason);
187 PISM_CHK(ierr,
"KSPGetConvergedReason");
209 *value =
m_alpha*dValue + sValue;
215 double designNorm, stateNorm, sumNorm;
216 double dWeight, sWeight;
223 designNorm *= dWeight;
224 stateNorm *= sWeight;
229 "----------------------------------------------------------\n");
231 "IP_SSATaucTikhonovGNSolver Iteration %d: misfit %g; functional %g \n",
236 double relsum = (sumNorm/std::max(designNorm,stateNorm));
238 "design norm %g stateNorm %g sum %g; relative difference %g\n",
239 designNorm, stateNorm, sumNorm, relsum);
268 if (reason->failed()) {
289 double valDesign, valState;
304 std::shared_ptr<TerminationReason> step_reason;
308 double descent_derivative;
315 if (descent_derivative >=0) {
316 printf(
"descent derivative: %g\n",descent_derivative);
325 if (step_reason->succeeded()) {
326 if (
m_value <= old_value + 1e-3*alpha*descent_derivative) {
331 printf(
"forward solve failed in linsearch. Shrinking.\n");
335 printf(
"alpha= %g; derivative = %g\n",alpha,descent_derivative);
348 " IP_SSATaucTikhonovGNSolver::solve.");
354 double dlogalpha = 0;
356 std::shared_ptr<TerminationReason> step_reason, reason;
359 if (step_reason->failed()) {
361 reason->set_root_cause(step_reason);
368 if (reason->done()) {
378 if (step_reason->failed()) {
380 reason->set_root_cause(step_reason);
385 if (step_reason->failed()) {
386 std::shared_ptr<TerminationReason> cause = reason;
388 reason->set_root_cause(step_reason);
394 if (step_reason->failed()) {
395 std::shared_ptr<TerminationReason> cause = reason;
397 reason->set_root_cause(step_reason);
427 KSPConvergedReason ksp_reason;
428 ierr = KSPGetConvergedReason(
m_ksp,&ksp_reason);
429 PISM_CHK(ierr,
"KSPGetConvergedReason");
453 double ddisc_sq_dalpha;
457 if (ddisc_sq_dalpha <= 0) {
461 "Adaptive Tikhonov sanity check failed (dh/dalpha= %g <= 0)."
462 " Tighten inv_gn_ksp_rtol?\n",
469 double ddisc_sq_dalpha_a;
471 double ddisc_sq_dalpha_b;
473 ddisc_sq_dalpha = 2*
m_alpha*(ddisc_sq_dalpha_a+
m_alpha*ddisc_sq_dalpha_b);
476 "Adaptive Tikhonov sanity check recovery attempt: dh/dalpha= %g. \n",
490 if (fabs(*dlogalpha)> stepmax) {
491 double sgn = *dlogalpha > 0 ? 1 : -1;
492 *dlogalpha = stepmax*sgn;
static std::shared_ptr< TerminationReason > max_iter()
static std::shared_ptr< TerminationReason > keep_iterating()
static std::shared_ptr< TerminationReason > success()
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
void copy_from(const Array2D< T > &source)
void add(double alpha, const Array2D< T > &x)
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
std::shared_ptr< const Grid > grid() const
void set(double c)
Result: v[j] <- c for all j.
std::shared_ptr< petsc::DM > dm() const
std::vector< double > norm(int n) const
Computes the norm of all the components of an Array.
void update_ghosts()
Updates ghost points.
Abstract base class for IPFunctionals arising from an inner product.
virtual std::shared_ptr< array::Vector > solution()
Returns the last solution of the SSA as computed by linearize_at.
virtual void apply_linearization(array::Scalar &dzeta, array::Vector &du)
Applies the linearization of the forward map (i.e. the reduced gradient described in the class-level...
virtual std::shared_ptr< TerminationReason > linearize_at(array::Scalar &zeta)
Sets the current value of the design variable and solves the SSA to find the associated .
virtual void apply_linearization_transpose(array::Vector &du, array::Scalar &dzeta)
Applies the transpose of the linearization of the forward map (i.e. the transpose of the reduced grad...
Implements the forward problem of the map taking to the corresponding solution of the SSA.
virtual std::shared_ptr< TerminationReason > linesearch()
virtual void apply_GN(array::Scalar &h, array::Scalar &out)
virtual void evaluateGNFunctional(DesignVec &h, double *value)
std::shared_ptr< const Logger > m_log
virtual void assemble_GN_rhs(DesignVec &out)
virtual std::shared_ptr< TerminationReason > init()
std::shared_ptr< DesignVecGhosted > m_d
virtual std::shared_ptr< TerminationReason > evaluate_objective_and_gradient()
DesignVecGhosted m_d_diff_lin
IPInnerProductFunctional< StateVec > & m_stateFunctional
DesignVec m_dh_dalphaGlobal
IPInnerProductFunctional< DesignVec > & m_designFunctional
DesignVecGhosted m_tmp_D1Local
virtual std::shared_ptr< TerminationReason > compute_dlogalpha(double *dalpha)
DesignVecGhosted m_d_diff
virtual std::shared_ptr< TerminationReason > solve()
virtual std::shared_ptr< TerminationReason > check_convergence()
virtual std::shared_ptr< TerminationReason > solve_linearized()
IP_SSATaucForwardProblem & m_ssaforward
IP_SSATaucTikhonovGNSolver(IP_SSATaucForwardProblem &ssaforward, DesignVec &d0, StateVec &u_obs, double eta, IPInnerProductFunctional< DesignVec > &designFunctional, IPInnerProductFunctional< StateVec > &stateFunctional)
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
std::string printf(const char *format,...)