Loading [MathJax]/jax/input/TeX/config.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
IP_SSAHardavForwardProblem.cc
Go to the documentation of this file.
1// Copyright (C) 2013, 2014, 2015, 2016, 2017, 2018, 2020, 2021, 2022, 2023, 2024, 2025 David Maxwell and Constantine Khroulev
2//
3// This file is part of PISM.
4//
5// PISM is free software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the Free Software
7// Foundation; either version 3 of the License, or (at your option) any later
8// version.
9//
10// PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13// details.
14//
15// You should have received a copy of the GNU General Public License
16// along with PISM; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19#include "pism/inverse/IP_SSAHardavForwardProblem.hh"
20#include "pism/util/Grid.hh"
21#include "pism/util/ConfigInterface.hh"
22#include "pism/util/Vars.hh"
23#include "pism/util/error_handling.hh"
24#include "pism/rheology/FlowLaw.hh"
25#include "pism/geometry/Geometry.hh"
26#include "pism/stressbalance/StressBalance.hh"
27#include "pism/util/petscwrappers/DM.hh"
28#include "pism/util/petscwrappers/Vec.hh"
29#include "pism/util/fem/Quadrature.hh"
30#include "pism/util/fem/DirichletData.hh"
31
32namespace pism {
33namespace inverse {
34
37 : SSAFEM(g),
38 m_stencil_width(1),
39 m_zeta(NULL),
40 m_dzeta_local(m_grid, "d_zeta_local"),
41 m_fixed_design_locations(NULL),
42 m_design_param(tp),
43 m_du_global(m_grid, "linearization work vector (sans ghosts)"),
44 m_du_local(m_grid, "linearization work vector (with ghosts)"),
45 m_hardav(m_grid, "hardav"),
46 m_element_index(*m_grid),
47 m_element(*m_grid, fem::Q1Quadrature4()),
48 m_rebuild_J_state(true)
49{
50
51 PetscErrorCode ierr;
52
53 m_velocity_shared.reset(new array::Vector(m_grid, "dummy"));
54 m_velocity_shared->metadata(0) = m_velocity.metadata(0);
55 m_velocity_shared->metadata(1) = m_velocity.metadata(1);
56
57 auto dm = m_velocity_global.dm();
58
59 ierr = DMSetMatType(*dm, MATBAIJ);
60 PISM_CHK(ierr, "DMSetMatType");
61
62 ierr = DMCreateMatrix(*dm, m_J_state.rawptr());
63 PISM_CHK(ierr, "DMCreateMatrix");
64
65 ierr = KSPCreate(m_grid->com, m_ksp.rawptr());
66 PISM_CHK(ierr, "KSPCreate");
67
68 double ksp_rtol = 1e-12;
69 ierr = KSPSetTolerances(m_ksp, ksp_rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
70 PISM_CHK(ierr, "KSPSetTolerances");
71
72 PC pc;
73 ierr = KSPGetPC(m_ksp, &pc);
74 PISM_CHK(ierr, "KSPGetPC");
75
76 ierr = PCSetType(pc, PCBJACOBI);
77 PISM_CHK(ierr, "PCSetType");
78
79 ierr = KSPSetFromOptions(m_ksp);
80 PISM_CHK(ierr, "KSPSetFromOptions");
81}
82
84
85 SSAFEM::init();
86
87 // Get most of the inputs from Grid::variables() and fake the rest.
88 //
89 // I will need to fix this at some point.
90 {
91 Geometry geometry(m_grid);
92 geometry.ice_thickness.copy_from(*m_grid->variables().get_2d_scalar("land_ice_thickness"));
93 geometry.bed_elevation.copy_from(*m_grid->variables().get_2d_scalar("bedrock_altitude"));
94 geometry.sea_level_elevation.set(0.0); // FIXME: this should be an input
95
96 if (m_config->get_flag("geometry.part_grid.enabled")) {
98 *m_grid->variables().get_2d_scalar("ice_area_specific_volume"));
99 } else {
100 geometry.ice_area_specific_volume.set(0.0);
101 }
102
103 geometry.ensure_consistency(m_config->get_number("stress_balance.ice_free_thickness_standard"));
104
106
107 const auto &variables = m_grid->variables();
108
109 const array::Scalar *vel_bc_mask = nullptr;
110 if (variables.is_available("vel_bc_mask")) {
111 vel_bc_mask = variables.get_2d_scalar("vel_bc_mask");
112 }
113
114 const array::Vector *vel_bc = nullptr;
115 if (variables.is_available("vel_bc")) {
116 vel_bc = variables.get_2d_vector("vel_bc");
117 }
118
119 inputs.geometry = &geometry;
120 inputs.basal_melt_rate = NULL;
121 inputs.basal_yield_stress = variables.get_2d_scalar("tauc");
122 inputs.enthalpy = variables.get_3d_scalar("enthalpy");
123 inputs.age = NULL;
124 inputs.bc_mask = vel_bc_mask;
125 inputs.bc_values = vel_bc;
126
127 inputs.water_column_pressure = NULL;
128
129 cache_inputs(inputs);
130 }
131}
132
133//! Sets the current value of of the design paramter \f$\zeta\f$.
134/*! This method sets \f$\zeta\f$ but does not solve the %SSA.
135It it intended for inverse methods that simultaneously compute
136the pair \f$u\f$ and \f$\zeta\f$ without ever solving the %SSA
137directly. Use this method in conjuction with
138\ref assemble_jacobian_state and \ref apply_jacobian_design and their friends.
139The vector \f$\zeta\f$ is not copied; a reference to the array::Array is
140kept.
141*/
143
144 m_zeta = &new_zeta;
145
146 // Convert zeta to hardav.
148
149 // Cache hardav at the quadrature points.
151
152 for (auto p = m_grid->points(1); p; p.next()) {
153 const int i = p.i(), j = p.j();
154 m_coefficients(i, j).hardness = m_hardav(i, j);
155 }
156
157 // Flag the state jacobian as needing rebuilding.
158 m_rebuild_J_state = true;
159}
160
161//! Sets the current value of the design variable \f$\zeta\f$ and solves the %SSA to find the associated \f$u_{\rm SSA}\f$.
162/* Use this method for inverse methods employing the reduced gradient. Use this method
163in conjuction with apply_linearization and apply_linearization_transpose.*/
164std::shared_ptr<TerminationReason> IP_SSAHardavForwardProblem::linearize_at(array::Scalar &zeta) {
165 this->set_design(zeta);
166 return this->solve_nocache();
167}
168
169//! Computes the residual function \f$\mathcal{R}(u, \zeta)\f$ as defined in the class-level documentation.
170/* The value of \f$\zeta\f$ is set prior to this call via set_design or linearize_at. The value
171of the residual is returned in \a RHS.*/
178
179//! Computes the residual function \f$\mathcal{R}(u, \zeta)\f$ defined in the class-level documentation.
180/* The return value is specified via a Vec for the benefit of certain TAO routines. Otherwise,
181the method is identical to the assemble_residual returning values as a StateVec (an array::Vector).*/
183
184 array::AccessScope l{&u};
185
187
188 this->compute_local_function(u.array(), (Vector2d**)rhs_a.get());
189}
190
191//! Assembles the state Jacobian matrix.
192/* The matrix depends on the current value of the design variable \f$\zeta\f$ and the current
193value of the state variable \f$u\f$. The specification of \f$\zeta\f$ is done earlier
194with set_design or linearize_at. The value of \f$u\f$ is specified explicitly as an argument
195to this method.
196 @param[in] u Current state variable value.
197 @param[out] J computed state Jacobian.
198*/
204
205//! Applies the design Jacobian matrix to a perturbation of the design variable.
206/*! The return value uses a DesignVector (array::Vector), which can be ghostless. Ghosts (if present) are updated.
207\overload
208*/
216
217//! Applies the design Jacobian matrix to a perturbation of the design variable.
218/*! The return value is a Vec for the benefit of TAO. It is assumed to be ghostless; no communication is done.
219\overload
220*/
227
228//! @brief Applies the design Jacobian matrix to a perturbation of the
229//! design variable.
230
231/*! The matrix depends on the current value of the design variable
232 \f$\zeta\f$ and the current value of the state variable \f$u\f$.
233 The specification of \f$\zeta\f$ is done earlier with set_design
234 or linearize_at. The value of \f$u\f$ is specified explicitly as
235 an argument to this method.
236
237 @param[in] u Current state variable value.
238
239 @param[in] dzeta Perturbation of the design variable. Prefers
240 vectors with ghosts; will copy to a ghosted vector
241 if needed.
242
243 @param[out] du_a Computed corresponding perturbation of the state
244 variable. The array \a du_a should be extracted
245 first from a Vec or an array::Array.
246
247 Typically this method is called via one of its overloads.
248*/
250 array::Scalar &dzeta,
251 Vector2d **du_a) {
252
253 const unsigned int Nk = fem::q1::n_chi;
254 const unsigned int Nq = m_element.n_pts();
255 const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
256
258
259 array::Scalar *dzeta_local;
260 if (dzeta.stencil_width() > 0) {
261 dzeta_local = &dzeta;
262 } else {
264 dzeta_local = &m_dzeta_local;
265 }
266 list.add(*dzeta_local);
267
268 // Zero out the portion of the function we are responsible for computing.
269 for (auto p = m_grid->points(); p; p.next()) {
270 const int i = p.i(), j = p.j();
271
272 du_a[j][i].u = 0.0;
273 du_a[j][i].v = 0.0;
274 }
275
276 // Aliases to help with notation consistency below.
277 const array::Scalar *dirichletLocations = &m_bc_mask;
278 const array::Vector *dirichletValues = &m_bc_values;
279 double dirichletWeight = m_dirichletScale;
280
281 Vector2d u_e[Nk];
282 Vector2d U[Nq_max], U_x[Nq_max], U_y[Nq_max];
283
284 Vector2d du_e[Nk];
285
286 double dzeta_e[Nk];
287
288 double zeta_e[Nk];
289
290 double dB_e[Nk];
291 double dB_q[Nq_max];
292
293 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues,
294 dirichletWeight);
296
297 // Loop through all elements.
298 const int
299 xs = m_element_index.xs,
300 xm = m_element_index.xm,
301 ys = m_element_index.ys,
302 ym = m_element_index.ym;
303
304 ParallelSection loop(m_grid->com);
305 try {
306 for (int j =ys; j<ys+ym; j++) {
307 for (int i =xs; i<xs+xm; i++) {
308
309 // Zero out the element-local residual in prep for updating it.
310 for (unsigned int k=0; k<Nk; k++) {
311 du_e[k].u = 0;
312 du_e[k].v = 0;
313 }
314
315 // Initialize the map from global to local degrees of freedom for this element.
316 m_element.reset(i, j);
317
318 // Obtain the value of the solution at the nodes adjacent to the element,
319 // fix dirichlet values, and compute values at quad pts.
320 m_element.nodal_values(u.array(), u_e);
321 if (dirichletBC) {
322 dirichletBC.constrain(m_element);
323 dirichletBC.enforce(m_element, u_e);
324 }
325 m_element.evaluate(u_e, U, U_x, U_y);
326
327 // Compute dzeta at the nodes
328 m_element.nodal_values(dzeta_local->array(), dzeta_e);
329 if (fixedZeta) {
330 fixedZeta.enforce_homogeneous(m_element, dzeta_e);
331 }
332
333 // Compute the change in hardav with respect to zeta at the quad points.
335 for (unsigned int k=0; k<Nk; k++) {
336 m_design_param.toDesignVariable(zeta_e[k], NULL, dB_e + k);
337 dB_e[k]*=dzeta_e[k];
338 }
339 m_element.evaluate(dB_e, dB_q);
340
341 double thickness[Nq_max];
342 {
343 Coefficients coeffs[Nk];
344 int mask[Nq_max];
345 double tauc[Nq_max];
346 double hardness[Nq_max];
347
348 m_element.nodal_values(m_coefficients.array(), coeffs);
349
351 mask, thickness, tauc, hardness);
352 }
353
354 for (unsigned int q = 0; q < Nq; q++) {
355 // Symmetric gradient at the quadrature point.
356 double Duqq[3] = {U_x[q].u, U_y[q].v, 0.5 * (U_y[q].u + U_x[q].v)};
357
358 double d_nuH = 0;
359 if (thickness[q] >= strength_extension->get_min_thickness()) {
360 m_flow_law->effective_viscosity(dB_q[q],
361 secondInvariant_2D(U_x[q], U_y[q]),
362 &d_nuH, NULL);
363 d_nuH *= (2.0 * thickness[q]);
364 }
365
366 auto W = m_element.weight(q);
367
368 for (unsigned int k = 0; k < Nk; k++) {
369 const fem::Germ &testqk = m_element.chi(q, k);
370 du_e[k].u += W*d_nuH*(testqk.dx*(2*Duqq[0] + Duqq[1]) + testqk.dy*Duqq[2]);
371 du_e[k].v += W*d_nuH*(testqk.dy*(2*Duqq[1] + Duqq[0]) + testqk.dx*Duqq[2]);
372 }
373 } // q
374 m_element.add_contribution(du_e, du_a);
375 } // j
376 } // i
377 } catch (...) {
378 loop.failed();
379 }
380 loop.check();
381
382 if (dirichletBC) {
383 dirichletBC.fix_residual_homogeneous(du_a);
384 }
385}
386
387//! Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
388/*! The return value uses a StateVector (array::Scalar) which can be ghostless; ghosts (if present) are updated.
389\overload
390*/
397
398//! Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
399/*! The return value uses a Vec for the benefit of TAO. It is assumed to be ghostless; no communication is done.
400\overload */
402 array::Vector &du,
403 Vec dzeta) {
404
405 petsc::DM::Ptr da2 = m_grid->get_dm(1, m_config->get_number("grid.max_stencil_width"));
406 petsc::DMDAVecArray dzeta_a(da2, dzeta);
407 this->apply_jacobian_design_transpose(u, du, (double**)dzeta_a.get());
408}
409
410//! @brief Applies the transpose of the design Jacobian matrix to a
411//! perturbation of the state variable.
412
413/*! The matrix depends on the current value of the design variable
414 \f$\zeta\f$ and the current value of the state variable \f$u\f$.
415 The specification of \f$\zeta\f$ is done earlier with set_design
416 or linearize_at. The value of \f$u\f$ is specified explicitly as
417 an argument to this method.
418
419 @param[in] u Current state variable value.
420
421 @param[in] du Perturbation of the state variable. Prefers vectors
422 with ghosts; will copy to a ghosted vector if need be.
423
424 @param[out] dzeta_a Computed corresponding perturbation of the
425 design variable. The array \a dzeta_a should be
426 extracted first from a Vec or an array::Array.
427
428 Typically this method is called via one of its overloads.
429*/
431 array::Vector &du,
432 double **dzeta_a) {
433
434 const unsigned int Nk = fem::q1::n_chi;
435 const unsigned int Nq = m_element.n_pts();
436 const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
437
439
440 array::Vector *du_local;
441 if (du.stencil_width() > 0) {
442 du_local = &du;
443 } else {
445 du_local = &m_du_local;
446 }
447 list.add(*du_local);
448
449 Vector2d u_e[Nk];
450 Vector2d U[Nq_max], U_x[Nq_max], U_y[Nq_max];
451
452 Vector2d du_e[Nk];
453 Vector2d du_q[Nq_max];
454 Vector2d du_dx_q[Nq_max];
455 Vector2d du_dy_q[Nq_max];
456
457 double dzeta_e[Nk];
458
459 // Aliases to help with notation consistency.
460 const array::Scalar *dirichletLocations = &m_bc_mask;
461 const array::Vector *dirichletValues = &m_bc_values;
462 double dirichletWeight = m_dirichletScale;
463
464 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues,
465 dirichletWeight);
466
467 // Zero out the portion of the function we are responsible for computing.
468 for (auto p = m_grid->points(); p; p.next()) {
469 const int i = p.i(), j = p.j();
470
471 dzeta_a[j][i] = 0;
472 }
473
474 const int
475 xs = m_element_index.xs,
476 xm = m_element_index.xm,
477 ys = m_element_index.ys,
478 ym = m_element_index.ym;
479
480 ParallelSection loop(m_grid->com);
481 try {
482 for (int j = ys; j < ys + ym; j++) {
483 for (int i = xs; i < xs + xm; i++) {
484 // Initialize the map from global to local degrees of freedom for this element.
485 m_element.reset(i, j);
486
487 // Obtain the value of the solution at the nodes adjacent to the element.
488 // Compute the solution values and symmetric gradient at the quadrature points.
489 m_element.nodal_values(du.array(), du_e);
490 if (dirichletBC) {
491 dirichletBC.enforce_homogeneous(m_element, du_e);
492 }
493 m_element.evaluate(du_e, du_q, du_dx_q, du_dy_q);
494
495 m_element.nodal_values(u.array(), u_e);
496 if (dirichletBC) {
497 dirichletBC.enforce(m_element, u_e);
498 }
499 m_element.evaluate(u_e, U, U_x, U_y);
500
501 // Zero out the element-local residual in prep for updating it.
502 for (unsigned int k = 0; k < Nk; k++) {
503 dzeta_e[k] = 0;
504 }
505
506 double thickness[Nq_max];
507 {
508 Coefficients coeffs[Nk];
509 int mask[Nq_max];
510 double tauc[Nq_max];
511 double hardness[Nq_max];
512
513 m_element.nodal_values(m_coefficients.array(), coeffs);
514
516 mask, thickness, tauc, hardness);
517 }
518
519 for (unsigned int q = 0; q < Nq; q++) {
520 // Symmetric gradient at the quadrature point.
521 double Duqq[3] = {U_x[q].u, U_y[q].v, 0.5 * (U_y[q].u + U_x[q].v)};
522
523 // Determine "d_nuH / dB" at the quadrature point
524 double d_nuH_dB = 0;
525 if (thickness[q] >= strength_extension->get_min_thickness()) {
526 m_flow_law->effective_viscosity(1.0,
527 secondInvariant_2D(U_x[q], U_y[q]),
528 &d_nuH_dB, NULL);
529 d_nuH_dB *= (2.0 * thickness[q]);
530 }
531
532 auto W = m_element.weight(q);
533
534 for (unsigned int k = 0; k < Nk; k++) {
535 dzeta_e[k] += W*d_nuH_dB*m_element.chi(q, k).val*((du_dx_q[q].u*(2*Duqq[0] + Duqq[1]) +
536 du_dy_q[q].u*Duqq[2]) +
537 (du_dy_q[q].v*(2*Duqq[1] + Duqq[0]) +
538 du_dx_q[q].v*Duqq[2]));
539 }
540 } // q
541
542 m_element.add_contribution(dzeta_e, dzeta_a);
543 } // j
544 } // i
545 } catch (...) {
546 loop.failed();
547 }
548 loop.check();
549
550 for (auto p = m_grid->points(); p; p.next()) {
551 const int i = p.i(), j = p.j();
552
553 double dB_dzeta;
554 m_design_param.toDesignVariable((*m_zeta)(i, j), NULL, &dB_dzeta);
555 dzeta_a[j][i] *= dB_dzeta;
556 }
557
558 if (m_fixed_design_locations != nullptr) {
560 fixedZeta.fix_residual_homogeneous(dzeta_a);
561 }
562}
563
564/*!\brief Applies the linearization of the forward map (i.e. the reduced gradient \f$DF\f$ described in
565the class-level documentation.) */
566/*! As described previously,
567\f[
568Df = J_{\rm State}^{-1} J_{\rm Design}.
569\f]
570Applying the linearization then involves the solution of a linear equation.
571The matrices \f$J_{\rm State}\f$ and \f$J_{\rm Design}\f$ both depend on the value of the
572design variable \f$\zeta\f$ and the value of the corresponding state variable \f$u=F(\zeta)\f$.
573These are established by first calling linearize_at.
574 @param[in] dzeta Perturbation of the design variable
575 @param[out] du Computed corresponding perturbation of the state variable; ghosts (if present) are updated.
576*/
578
579 PetscErrorCode ierr;
580
581 if (m_rebuild_J_state) {
583 m_rebuild_J_state = false;
584 }
585
587 m_du_global.scale(-1);
588
589 // call PETSc to solve linear system by iterative method.
590 ierr = KSPSetOperators(m_ksp, m_J_state, m_J_state);
591 PISM_CHK(ierr, "KSPSetOperators");
592
593 ierr = KSPSolve(m_ksp, m_du_global.vec(), m_du_global.vec());
594 PISM_CHK(ierr, "KSPSolve"); // SOLVE
595
596 KSPConvergedReason reason;
597 ierr = KSPGetConvergedReason(m_ksp, &reason);
598 PISM_CHK(ierr, "KSPGetConvergedReason");
599
600 if (reason < 0) {
601 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "IP_SSAHardavForwardProblem::apply_linearization solve"
602 " failed to converge (KSP reason %s)",
603 KSPConvergedReasons[reason]);
604 }
605
606 m_log->message(4,
607 "IP_SSAHardavForwardProblem::apply_linearization converged"
608 " (KSP reason %s)\n",
609 KSPConvergedReasons[reason]);
610
612}
613
614/*! \brief Applies the transpose of the linearization of the forward map
615 (i.e. the transpose of the reduced gradient \f$DF\f$ described in the class-level documentation.) */
616/*! As described previously,
617\f[
618Df = J_{\rm State}^{-1} J_{\rm Design}.
619\f]
620so
621\f[
622Df^t = J_{\rm Design}^t \; (J_{\rm State}^t)^{-1} .
623\f]
624Applying the transpose of the linearization then involves the solution of a linear equation.
625The matrices \f$J_{\rm State}\f$ and \f$J_{\rm Design}\f$ both depend on the value of the
626design variable \f$\zeta\f$ and the value of the corresponding state variable \f$u=F(\zeta)\f$.
627These are established by first calling linearize_at.
628 @param[in] du Perturbation of the state variable
629 @param[out] dzeta Computed corresponding perturbation of the design variable; ghosts (if present) are updated.
630*/
632 array::Scalar &dzeta) {
633
634 PetscErrorCode ierr;
635
636 if (m_rebuild_J_state) {
638 m_rebuild_J_state = false;
639 }
640
641 // Aliases to help with notation consistency below.
642 const array::Scalar *dirichletLocations = &m_bc_mask;
643 const array::Vector *dirichletValues = &m_bc_values;
644 double dirichletWeight = m_dirichletScale;
645
647
648 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues,
649 dirichletWeight);
650 if (dirichletBC) {
653 }
654
655 // call PETSc to solve linear system by iterative method.
656 ierr = KSPSetOperators(m_ksp, m_J_state, m_J_state);
657 PISM_CHK(ierr, "KSPSetOperators");
658
659 ierr = KSPSolve(m_ksp, m_du_global.vec(), m_du_global.vec());
660 PISM_CHK(ierr, "KSPSolve"); // SOLVE
661
662 KSPConvergedReason reason;
663 ierr = KSPGetConvergedReason(m_ksp, &reason);
664 PISM_CHK(ierr, "KSPGetConvergedReason");
665
666 if (reason < 0) {
667 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "IP_SSAHardavForwardProblem::apply_linearization solve failed to converge (KSP reason %s)",
668 KSPConvergedReasons[reason]);
669 }
670
671 m_log->message(4, "IP_SSAHardavForwardProblem::apply_linearization converged (KSP reason %s)\n",
672 KSPConvergedReasons[reason]);
673
675 dzeta.scale(-1);
676
677 if (dzeta.stencil_width() > 0) {
678 dzeta.update_ghosts();
679 }
680}
681
682} // end of namespace inverse
683} // end of namespace pism
const Config::ConstPtr m_config
configuration database used by this component
Definition Component.hh:158
const Logger::ConstPtr m_log
logger (for easy access)
Definition Component.hh:162
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition Component.hh:156
array::Scalar1 sea_level_elevation
Definition Geometry.hh:48
void ensure_consistency(double ice_free_thickness_threshold)
Definition Geometry.cc:114
array::Scalar1 ice_area_specific_volume
Definition Geometry.hh:52
array::Scalar2 ice_thickness
Definition Geometry.hh:51
array::Scalar2 bed_elevation
Definition Geometry.hh:47
void failed()
Indicates a failure of a parallel section.
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.
Definition Vector2d.hh:29
T * rawptr()
Definition Wrapper.hh:39
std::shared_ptr< Wrapper > Ptr
Definition Wrapper.hh:30
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:73
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:65
petsc::Vec & vec() const
Definition Array.cc:310
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:224
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:629
std::shared_ptr< petsc::DM > dm() const
Definition Array.cc:324
void update_ghosts()
Updates ghost points.
Definition Array.cc:615
unsigned int stencil_width() const
Get the stencil width of the current Array. Returns 0 if ghosts are not available.
Definition Array.cc:302
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition Array.cc:476
void enforce_homogeneous(const Element2 &element, double *x_e)
void fix_residual_homogeneous(double **r_global)
void enforce(const Element2 &element, Vector2d *x_e)
void fix_residual_homogeneous(Vector2d **r)
void enforce_homogeneous(const Element2 &element, Vector2d *x_e)
void constrain(Element2 &element)
Constrain element, i.e. ensure that quadratures do not contribute to Dirichlet nodes by marking corre...
void evaluate(const T *x, T *vals, T *dx, T *dy)
Given nodal values, compute the values and partial derivatives at the quadrature points.
Definition Element.hh:195
void reset(int i, int j)
Initialize the Element to element (i, j) for the purposes of inserting into global residual and Jacob...
Definition Element.cc:196
void add_contribution(const T *local, T **y_global) const
Add the values of element-local contributions y to the global vector y_global.
Definition Element.hh:238
void nodal_values(const array::Scalar &x_global, int *result) const
Get nodal values of an integer mask.
Definition Element.cc:185
int xm
total number of elements to loop over in the x-direction.
int ym
total number of elements to loop over in the y-direction.
int ys
y-coordinate of the first element to loop over.
int xs
x-coordinate of the first element to loop over.
double weight(unsigned int q) const
Weight of the quadrature point q
Definition Element.hh:85
const Germ & chi(unsigned int q, unsigned int k) const
Definition Element.hh:73
unsigned int n_pts() const
Number of quadrature points.
Definition Element.hh:80
virtual void convertToDesignVariable(array::Scalar &zeta, array::Scalar &d, bool communicate=true)
Transforms a vector of values to a vector of values.
virtual void toDesignVariable(double zeta, double *value, double *derivative)=0
Converts from parameterization value to .
petsc::Mat m_J_state
Mat used in apply_linearization and apply_linearization_transpose.
virtual void assemble_residual(array::Vector &u, array::Vector &R)
Computes the residual function as defined in the class-level documentation.
virtual void apply_jacobian_design_transpose(array::Vector &u, array::Vector &du, array::Scalar &dzeta)
Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
array::Vector m_du_global
Temporary storage when state vectors need to be used without ghosts.
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 void assemble_jacobian_state(array::Vector &u, Mat J)
Assembles the state Jacobian matrix.
IPDesignVariableParameterization & m_design_param
The function taking to .
array::Scalar1 m_hardav
Vertically-averaged ice hardness.
array::Scalar * m_fixed_design_locations
Locations where should not be adjusted.
array::Scalar1 m_dzeta_local
Storage for d_zeta with ghosts, if needed when an argument d_zeta is ghost-less.
IP_SSAHardavForwardProblem(std::shared_ptr< const Grid > g, IPDesignVariableParameterization &tp)
Constructs from the same objects as SSAFEM, plus a specification of how is parameterized.
virtual void apply_jacobian_design(array::Vector &u, array::Scalar &dzeta, array::Vector &du)
Applies the design Jacobian matrix to a perturbation of the design variable.
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 .
array::Scalar * m_zeta
Current value of zeta, provided from caller.
bool m_rebuild_J_state
Flag indicating that the state jacobian matrix needs rebuilding.
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...
virtual void set_design(array::Scalar &zeta)
Sets the current value of of the design paramter .
array::Vector1 m_du_local
Temporary storage when state vectors need to be used with ghosts.
petsc::KSP m_ksp
KSP used in apply_linearization and apply_linearization_transpose.
const array::Scalar * basal_yield_stress
const array::Scalar * bc_mask
const array::Array3D * age
const array::Scalar * water_column_pressure
const array::Array3D * enthalpy
const array::Scalar * basal_melt_rate
const array::Vector * bc_values
void cache_inputs(const Inputs &inputs)
Initialize stored data from the coefficients in the SSA. Called by SSAFEM::solve.
Definition SSAFEM.cc:267
void compute_local_jacobian(Vector2d const *const *velocity, Mat J)
Implements the callback for computing the Jacobian.
Definition SSAFEM.cc:957
array::Scalar1 m_bc_mask
Definition SSAFEM.hh:67
std::shared_ptr< TerminationReason > solve_nocache()
Definition SSAFEM.cc:194
void compute_local_function(Vector2d const *const *velocity, Vector2d **residual)
Implements the callback for computing the residual.
Definition SSAFEM.cc:735
void quad_point_values(const fem::Element &E, const Coefficients *x, int *mask, double *thickness, double *tauc, double *hardness) const
Compute quadrature point values of various coefficients given a quadrature Q and nodal values.
Definition SSAFEM.cc:345
array::Vector1 m_bc_values
Definition SSAFEM.hh:68
array::Array2D< Coefficients > m_coefficients
Definition SSAFEM.hh:74
double get_min_thickness() const
Returns minimum thickness to trigger use of extension.
Definition SSA.cc:64
array::Vector m_velocity_global
Definition SSA.hh:133
SSAStrengthExtension * strength_extension
Definition SSA.hh:115
std::shared_ptr< rheology::FlowLaw > m_flow_law
#define PISM_CHK(errcode, name)
#define PISM_ERROR_LOCATION
const int n_chi
Definition FEM.hh:191
const unsigned int MAX_QUADRATURE_SIZE
Definition FEM.hh:173
static double secondInvariant_2D(const Vector2d &U_x, const Vector2d &U_y)
Definition FlowLaw.hh:45
static const double g
Definition exactTestP.cc:36
static const double k
Definition exactTestP.cc:42
double dy
Function derivative with respect to y.
Definition FEM.hh:157
double val
Function value.
Definition FEM.hh:153
double dx
Function deriviative with respect to x.
Definition FEM.hh:155
Struct for gathering the value and derivative of a function at a point.
Definition FEM.hh:151