PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
IP_SSATaucForwardProblem.cc
Go to the documentation of this file.
1// Copyright (C) 2012, 2014, 2015, 2016, 2017, 2019, 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_SSATaucForwardProblem.hh"
20#include "pism/basalstrength/basal_resistance.hh"
21#include "pism/util/Grid.hh"
22#include "pism/util/Mask.hh"
23#include "pism/util/Vars.hh"
24#include "pism/util/error_handling.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/DirichletData.hh"
30#include "pism/util/fem/Quadrature.hh"
31#include "pism/util/Logger.hh"
32
33namespace pism {
34namespace inverse {
35
38 : SSAFEM(grid),
39 m_zeta(NULL),
40 m_dzeta_local(m_grid, "d_zeta_local"),
41 m_tauc_copy(m_grid, "tauc"),
42 m_fixed_tauc_locations(NULL),
43 m_tauc_param(tp),
44 m_du_global(m_grid, "linearization work vector (sans ghosts)"),
45 m_du_local(m_grid, "linearization work vector (with ghosts)"),
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
58 .long_name("yield stress for basal till (plastic or pseudo-plastic model)")
59 .units("Pa");
60
61 auto dm = m_velocity_global.dm();
62
63 ierr = DMSetMatType(*dm, MATBAIJ);
64 PISM_CHK(ierr, "DMSetMatType");
65 ierr = DMCreateMatrix(*dm, m_J_state.rawptr());
66 PISM_CHK(ierr, "DMCreateMatrix");
67
68 ierr = KSPCreate(m_grid->com, m_ksp.rawptr());
69 PISM_CHK(ierr, "KSPCreate");
70
71 double ksp_rtol = 1e-12;
72 ierr = KSPSetTolerances(m_ksp, ksp_rtol, PETSC_DEFAULT, PETSC_DEFAULT, PETSC_DEFAULT);
73 PISM_CHK(ierr, "KSPSetTolerances");
74
75 PC pc;
76 ierr = KSPGetPC(m_ksp, &pc);
77 PISM_CHK(ierr, "KSPGetPC");
78
79 ierr = PCSetType(pc, PCBJACOBI);
80 PISM_CHK(ierr, "PCSetType");
81
82 ierr = KSPSetFromOptions(m_ksp);
83 PISM_CHK(ierr, "KSPSetFromOptions");
84}
85
87
88 // This calls SSA::init(), which calls pism::Vars::get_2d_scalar()
89 // to set m_tauc.
90 SSAFEM::init();
91
92 // Get most of the inputs from Grid::variables() and fake the rest.
93 //
94 // I will need to fix this at some point.
95 {
96 Geometry geometry(m_grid);
97 geometry.ice_thickness.copy_from(*m_grid->variables().get_2d_scalar("land_ice_thickness"));
98 geometry.bed_elevation.copy_from(*m_grid->variables().get_2d_scalar("bedrock_altitude"));
99 geometry.sea_level_elevation.set(0.0);
100
101 if (m_config->get_flag("geometry.part_grid.enabled")) {
103 *m_grid->variables().get_2d_scalar("ice_area_specific_volume"));
104 } else {
105 geometry.ice_area_specific_volume.set(0.0);
106 }
107
108 geometry.ensure_consistency(m_config->get_number("stress_balance.ice_free_thickness_standard"));
109
111
112 const auto &variables = m_grid->variables();
113
114 const array::Scalar *vel_bc_mask = nullptr;
115 if (variables.is_available("vel_bc_mask")) {
116 vel_bc_mask = variables.get_2d_scalar("vel_bc_mask");
117 }
118
119 const array::Vector *vel_bc = nullptr;
120 if (variables.is_available("vel_bc")) {
121 vel_bc = variables.get_2d_vector("vel_bc");
122 }
123
124 inputs.geometry = &geometry;
125 inputs.basal_melt_rate = NULL;
126 inputs.basal_yield_stress = variables.get_2d_scalar("tauc");
127 inputs.enthalpy = variables.get_3d_scalar("enthalpy");
128 inputs.age = NULL;
129 inputs.bc_mask = vel_bc_mask;
130 inputs.bc_values = vel_bc;
131
132 inputs.water_column_pressure = NULL;
133
134 cache_inputs(inputs);
135 }
136}
137
138//! Sets the current value of of the design paramter \f$\zeta\f$.
139/*! This method sets \f$\zeta\f$ but does not solve the %SSA.
140It it intended for inverse methods that simultaneously compute
141the pair \f$u\f$ and \f$\zeta\f$ without ever solving the %SSA
142directly. Use this method in conjuction with
143\ref assemble_jacobian_state and \ref apply_jacobian_design and their friends.
144The vector \f$\zeta\f$ is not copied; a reference to the array::Array is
145kept.
146*/
148
150
151 m_zeta = &new_zeta;
152
153 // Convert zeta to tauc.
155
156 // Cache tauc at the quadrature points.
158
159 for (auto p : m_grid->points_with_ghosts(1)) {
160 const int i = p.i(), j = p.j();
161 m_coefficients(i, j).tauc = tauc(i, j);
162 }
163
164 // Flag the state jacobian as needing rebuilding.
165 m_rebuild_J_state = true;
166}
167
168//! Sets the current value of the design variable \f$\zeta\f$ and solves the %SSA to find the associated \f$u_{\rm SSA}\f$.
169/* Use this method for inverse methods employing the reduced gradient. Use this method
170in conjuction with apply_linearization and apply_linearization_transpose.*/
171std::shared_ptr<TerminationReason> IP_SSATaucForwardProblem::linearize_at(array::Scalar &zeta) {
172 this->set_design(zeta);
173 return this->solve_nocache();
174}
175
176//! Computes the residual function \f$\mathcal{R}(u, \zeta)\f$ as defined in the class-level documentation.
177/* The value of \f$\zeta\f$ is set prior to this call via set_design or linearize_at. The value
178of the residual is returned in \a RHS.*/
184
185//! Computes the residual function \f$\mathcal{R}(u, \zeta)\f$ defined in the class-level documentation.
186/* The return value is specified via a Vec for the benefit of certain TAO routines. Otherwise,
187the method is identical to the assemble_residual returning values as a StateVec (an array::Vector).*/
194
195//! Assembles the state Jacobian matrix.
196/* The matrix depends on the current value of the design variable \f$\zeta\f$ and the current
197value of the state variable \f$u\f$. The specification of \f$\zeta\f$ is done earlier
198with set_design or linearize_at. The value of \f$u\f$ is specified explicitly as an argument
199to this method.
200 @param[in] u Current state variable value.
201 @param[out] J computed state Jacobian.
202*/
208
209//! Applies the design Jacobian matrix to a perturbation of the design variable.
210/*! The return value uses a DesignVector (array::Vector), which can be ghostless. Ghosts (if present) are updated.
211\overload
212*/
219
220//! Applies the design Jacobian matrix to a perturbation of the design variable.
221/*! The return value is a Vec for the benefit of TAO. It is assumed to
222be ghostless; no communication is done. \overload
223*/
229
230//! Applies the design Jacobian matrix to a perturbation of the design variable.
231/*! The matrix depends on the current value of the design variable \f$\zeta\f$ and the current
232value of the state variable \f$u\f$. The specification of \f$\zeta\f$ is done earlier
233with set_design or linearize_at. The value of \f$u\f$ is specified explicitly as an argument
234to this method.
235 @param[in] u Current state variable value.
236 @param[in] dzeta Perturbation of the design variable. Prefers vectors with ghosts; will copy to a ghosted vector if needed.
237 @param[out] du_a Computed corresponding perturbation of the state variable. The array \a du_a
238 should be extracted first from a Vec or an array::Array.
239
240 Typically this method is called via one of its overloads.
241*/
243 array::Scalar &dzeta,
244 Vector2d **du_a) {
245 const unsigned int Nk = fem::q1::n_chi;
246 const unsigned int Nq = m_element.n_pts();
247 const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
248
250
251 array::Scalar *dzeta_local;
252 if (dzeta.stencil_width() > 0) {
253 dzeta_local = &dzeta;
254 } else {
256 dzeta_local = &m_dzeta_local;
257 }
258 list.add(*dzeta_local);
259
260 // Zero out the portion of the function we are responsible for computing.
261 for (auto p : m_grid->points()) {
262 const int i = p.i(), j = p.j();
263
264 du_a[j][i].u = 0.0;
265 du_a[j][i].v = 0.0;
266 }
267
268 // Aliases to help with notation consistency below.
269 const array::Scalar *dirichletLocations = &m_bc_mask;
270 const array::Vector *dirichletValues = &m_bc_values;
271 double dirichletWeight = m_dirichletScale;
272
273 Vector2d u_e[Nk];
274 Vector2d u_q[Nq_max];
275
276 Vector2d du_e[Nk];
277
278 double dzeta_e[Nk];
279
280 double zeta_e[Nk];
281
282 double dtauc_e[Nk];
283 double dtauc_q[Nq_max];
284
285 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues,
286 dirichletWeight);
288
289 // Loop through all elements.
290 const int
291 xs = m_element_index.xs,
292 xm = m_element_index.xm,
293 ys = m_element_index.ys,
294 ym = m_element_index.ym;
295
296 ParallelSection loop(m_grid->com);
297 try {
298 for (int j = ys; j < ys + ym; j++) {
299 for (int i = xs; i < xs + xm; i++) {
300
301 // Zero out the element residual in prep for updating it.
302 for (unsigned int k = 0; k < Nk; k++) {
303 du_e[k].u = 0;
304 du_e[k].v = 0;
305 }
306
307 // Initialize the map from global to local degrees of freedom for this element.
308 m_element.reset(i, j);
309
310 // Obtain the value of the solution at the nodes adjacent to the element,
311 // fix dirichlet values, and compute values at quad pts.
312 m_element.nodal_values(u.array(), u_e);
313 if (dirichletBC) {
314 dirichletBC.constrain(m_element);
315 dirichletBC.enforce(m_element, u_e);
316 }
317 m_element.evaluate(u_e, u_q);
318
319 // Compute dzeta at the nodes
320 m_element.nodal_values(dzeta_local->array(), dzeta_e);
321 if (fixedZeta) {
322 fixedZeta.enforce_homogeneous(m_element, dzeta_e);
323 }
324
325 // Compute the change in tau_c with respect to zeta at the quad points.
327 for (unsigned int k = 0; k < Nk; k++) {
328 m_tauc_param.toDesignVariable(zeta_e[k], NULL, dtauc_e + k);
329 dtauc_e[k] *= dzeta_e[k];
330 }
331 m_element.evaluate(dtauc_e, dtauc_q);
332
333 int mask[Nq_max];
334 {
335 Coefficients coeffs[Nk];
336 double thickness[Nq_max];
337 double tauc[Nq_max];
338 double hardness[Nq_max];
339
340 m_element.nodal_values(m_coefficients.array(), coeffs);
341
343 mask, thickness, tauc, hardness);
344 }
345
346 for (unsigned int q = 0; q < Nq; q++) {
347 Vector2d u_qq = u_q[q];
348
349 // Determine "dbeta / dzeta" at the quadrature point
350 double dbeta = 0;
351 if (mask::grounded_ice(mask[q])) {
352 dbeta = m_basal_sliding_law->drag(dtauc_q[q], u_qq.u, u_qq.v);
353 }
354
355 auto W = m_element.weight(q);
356
357 for (unsigned int k = 0; k < Nk; k++) {
358 du_e[k].u += W*dbeta*u_qq.u*m_element.chi(q, k).val;
359 du_e[k].v += W*dbeta*u_qq.v*m_element.chi(q, k).val;
360 }
361 } // q
362 m_element.add_contribution(du_e, du_a);
363 } // j
364 } // i
365 } catch (...) {
366 loop.failed();
367 }
368 loop.check();
369
370 if (dirichletBC) {
371 dirichletBC.fix_residual_homogeneous(du_a);
372 }
373}
374
375//! Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
376/*! The return value uses a StateVector (array::Scalar) which can be ghostless; ghosts (if present) are updated.
377\overload
378*/
386
387//! Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
388/*! The return value uses a Vec for the benefit of TAO. It is assumed to be ghostless; no communication is done.
389\overload */
391 array::Vector &du,
392 Vec dzeta) {
393 auto da2 = m_grid->get_dm(1, m_config->get_number("grid.max_stencil_width"));
394 petsc::DMDAVecArray dzeta_a(da2, dzeta);
395 this->apply_jacobian_design_transpose(u, du, (double**)dzeta_a.get());
396}
397
398//! Applies the transpose of the design Jacobian matrix to a perturbation of the state variable.
399/*! The matrix depends on the current value of the design variable \f$\zeta\f$ and the current
400value of the state variable \f$u\f$. The specification of \f$\zeta\f$ is done earlier
401with set_design or linearize_at. The value of \f$u\f$ is specified explicitly as an argument
402to this method.
403 @param[in] u Current state variable value.
404 @param[in] du Perturbation of the state variable. Prefers vectors with ghosts; will copy to a ghosted vector if need be.
405 @param[out] dzeta_a Computed corresponding perturbation of the design variable. The array \a dzeta_a
406 should be extracted first from a Vec or an array::Array.
407
408 Typically this method is called via one of its overloads.
409*/
411 array::Vector &du,
412 double **dzeta_a) {
413 const unsigned int Nk = fem::q1::n_chi;
414 const unsigned int Nq = m_element.n_pts();
415 const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
416
418
419 array::Vector *du_local;
420 if (du.stencil_width() > 0) {
421 du_local = &du;
422 } else {
424 du_local = &m_du_local;
425 }
426 list.add(*du_local);
427
428 Vector2d u_e[Nk];
429 Vector2d u_q[Nq_max];
430
431 Vector2d du_e[Nk];
432 Vector2d du_q[Nq_max];
433
434 double dzeta_e[Nk];
435
436 // Aliases to help with notation consistency.
437 const array::Scalar *dirichletLocations = &m_bc_mask;
438 const array::Vector *dirichletValues = &m_bc_values;
439 double dirichletWeight = m_dirichletScale;
440
441 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues,
442 dirichletWeight);
443
444 // Zero out the portion of the function we are responsible for computing.
445 for (auto p : m_grid->points()) {
446 const int i = p.i(), j = p.j();
447
448 dzeta_a[j][i] = 0;
449 }
450
451 const int
452 xs = m_element_index.xs,
453 xm = m_element_index.xm,
454 ys = m_element_index.ys,
455 ym = m_element_index.ym;
456
457 ParallelSection loop(m_grid->com);
458 try {
459 for (int j=ys; j<ys+ym; j++) {
460 for (int i=xs; i<xs+xm; i++) {
461 // Initialize the map from global to local degrees of freedom for this element.
462 m_element.reset(i, j);
463
464 // Obtain the value of the solution at the nodes adjacent to the element.
465 // Compute the solution values and symmetric gradient at the quadrature points.
466 m_element.nodal_values(du_local->array(), du_e);
467 if (dirichletBC) {
468 dirichletBC.enforce_homogeneous(m_element, du_e);
469 }
470 m_element.evaluate(du_e, du_q);
471
472 m_element.nodal_values(u.array(), u_e);
473 if (dirichletBC) {
474 dirichletBC.enforce(m_element, u_e);
475 }
476 m_element.evaluate(u_e, u_q);
477
478 // Zero out the element-local residual in prep for updating it.
479 for (unsigned int k=0; k<Nk; k++) {
480 dzeta_e[k] = 0;
481 }
482
483 int mask[Nq_max];
484 {
485 Coefficients coeffs[Nk];
486 double thickness[Nq_max];
487 double tauc[Nq_max];
488 double hardness[Nq_max];
489
490 m_element.nodal_values(m_coefficients.array(), coeffs);
491
493 mask, thickness, tauc, hardness);
494 }
495
496 for (unsigned int q=0; q<Nq; q++) {
497 Vector2d du_qq = du_q[q];
498 Vector2d u_qq = u_q[q];
499
500 // Determine "dbeta/dtauc" at the quadrature point
501 double dbeta_dtauc = 0;
502 if (mask::grounded_ice(mask[q])) {
503 dbeta_dtauc = m_basal_sliding_law->drag(1., u_qq.u, u_qq.v);
504 }
505
506 auto W = m_element.weight(q);
507
508 for (unsigned int k=0; k<Nk; k++) {
509 dzeta_e[k] += W*dbeta_dtauc*(du_qq.u*u_qq.u+du_qq.v*u_qq.v)*m_element.chi(q, k).val;
510 }
511 } // q
512
513 m_element.add_contribution(dzeta_e, dzeta_a);
514 } // j
515 } // i
516 } catch (...) {
517 loop.failed();
518 }
519 loop.check();
520
521 for (auto p : m_grid->points()) {
522 const int i = p.i(), j = p.j();
523
524 double dtauc_dzeta;
525 m_tauc_param.toDesignVariable((*m_zeta)(i, j), NULL, &dtauc_dzeta);
526 dzeta_a[j][i] *= dtauc_dzeta;
527 }
528
529 if (m_fixed_tauc_locations != nullptr) {
531 fixedTauc.fix_residual_homogeneous(dzeta_a);
532 }
533}
534
535/*!\brief Applies the linearization of the forward map (i.e. the reduced gradient \f$DF\f$ described in
536the class-level documentation.) */
537/*! As described previously,
538\f[
539Df = J_{\rm State}^{-1} J_{\rm Design}.
540\f]
541Applying the linearization then involves the solution of a linear equation.
542The matrices \f$J_{\rm State}\f$ and \f$J_{\rm Design}\f$ both depend on the value of the
543design variable \f$\zeta\f$ and the value of the corresponding state variable \f$u=F(\zeta)\f$.
544These are established by first calling linearize_at.
545 @param[in] dzeta Perturbation of the design variable
546 @param[out] du Computed corresponding perturbation of the state variable; ghosts (if present) are updated.
547*/
549
550 PetscErrorCode ierr;
551
552 if (m_rebuild_J_state) {
554 m_rebuild_J_state = false;
555 }
556
558 m_du_global.scale(-1);
559
560 // call PETSc to solve linear system by iterative method.
561 ierr = KSPSetOperators(m_ksp, m_J_state, m_J_state);
562 PISM_CHK(ierr, "KSPSetOperators");
563
564 ierr = KSPSolve(m_ksp, m_du_global.vec(), m_du_global.vec());
565 PISM_CHK(ierr, "KSPSolve"); // SOLVE
566
567 KSPConvergedReason reason;
568 ierr = KSPGetConvergedReason(m_ksp, &reason);
569 PISM_CHK(ierr, "KSPGetConvergedReason");
570 if (reason < 0) {
572 "IP_SSATaucForwardProblem::apply_linearization solve"
573 " failed to converge (KSP reason %s)",
574 KSPConvergedReasons[reason]);
575 }
576
577 m_log->message(4,
578 "IP_SSATaucForwardProblem::apply_linearization converged"
579 " (KSP reason %s)\n",
580 KSPConvergedReasons[reason]);
581
583}
584
585/*! \brief Applies the transpose of the linearization of the forward map
586 (i.e. the transpose of the reduced gradient \f$DF\f$ described in the class-level documentation.) */
587/*! As described previously,
588\f[
589Df = J_{\rm State}^{-1} J_{\rm Design}.
590\f]
591so
592\f[
593Df^t = J_{\rm Design}^t \; (J_{\rm State}^t)^{-1} .
594\f]
595Applying the transpose of the linearization then involves the solution of a linear equation.
596The matrices \f$J_{\rm State}\f$ and \f$J_{\rm Design}\f$ both depend on the value of the
597design variable \f$\zeta\f$ and the value of the corresponding state variable \f$u=F(\zeta)\f$.
598These are established by first calling linearize_at.
599 @param[in] du Perturbation of the state variable
600 @param[out] dzeta Computed corresponding perturbation of the design variable; ghosts (if present) are updated.
601*/
603 array::Scalar &dzeta) {
604
605 PetscErrorCode ierr;
606
607 if (m_rebuild_J_state) {
609 m_rebuild_J_state = false;
610 }
611
612 // Aliases to help with notation consistency below.
613 const array::Scalar *dirichletLocations = &m_bc_mask;
614 const array::Vector *dirichletValues = &m_bc_values;
615 double dirichletWeight = m_dirichletScale;
616
618
619 fem::DirichletData_Vector dirichletBC(dirichletLocations, dirichletValues, dirichletWeight);
620
621 if (dirichletBC) {
624 }
625
626 // call PETSc to solve linear system by iterative method.
627 ierr = KSPSetOperators(m_ksp, m_J_state, m_J_state);
628 PISM_CHK(ierr, "KSPSetOperators");
629
630 ierr = KSPSolve(m_ksp, m_du_global.vec(), m_du_global.vec());
631 PISM_CHK(ierr, "KSPSolve"); // SOLVE
632
633 KSPConvergedReason reason;
634 ierr = KSPGetConvergedReason(m_ksp, &reason);
635 PISM_CHK(ierr, "KSPGetConvergedReason");
636
637 if (reason < 0) {
639 "IP_SSATaucForwardProblem::apply_linearization solve"
640 " failed to converge (KSP reason %s)",
641 KSPConvergedReasons[reason]);
642 }
643
644 m_log->message(4,
645 "IP_SSATaucForwardProblem::apply_linearization converged"
646 " (KSP reason %s)\n",
647 KSPConvergedReasons[reason]);
648
650 dzeta.scale(-1);
651
652 if (dzeta.stencil_width() > 0) {
653 dzeta.update_ghosts();
654 }
655}
656
657} // end of namespace inverse
658} // end of namespace pism
std::shared_ptr< const Config > m_config
configuration database used by this component
Definition Component.hh:160
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition Component.hh:158
std::shared_ptr< const Logger > m_log
logger (for easy access)
Definition Component.hh:164
array::Scalar1 sea_level_elevation
Definition Geometry.hh:48
void ensure_consistency(double ice_free_thickness_threshold)
Definition Geometry.cc:116
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
virtual double drag(double tauc, double vx, double vy) const
Compute the drag coefficient for the basal shear stress.
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
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
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:34
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:101
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:93
petsc::Vec & vec() const
Definition Array.cc:313
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:227
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:659
std::shared_ptr< petsc::DM > dm() const
Definition Array.cc:327
void update_ghosts()
Updates ghost points.
Definition Array.cc:645
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
Definition Array.cc:467
unsigned int stencil_width() const
Get the stencil width of the current Array. Returns 0 if ghosts are not available.
Definition Array.cc:305
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 .
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 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::Scalar * m_fixed_tauc_locations
Locations where should not be adjusted.
IPDesignVariableParameterization & m_tauc_param
The function taking to .
bool m_rebuild_J_state
Flag indicating that the state jacobian matrix needs rebuilding.
array::Scalar * m_zeta
Current value of zeta, provided from caller.
petsc::KSP m_ksp
KSP used in apply_linearization and apply_linearization_transpose.
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...
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 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 .
std::shared_ptr< array::Vector > m_velocity_shared
Copy of the velocity field managed using a shared pointer.
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...
array::Vector1 m_du_local
Temporary storage when state vectors need to be used with ghosts.
array::Vector m_du_global
Temporary storage when state vectors need to be used without ghosts.
IP_SSATaucForwardProblem(std::shared_ptr< const Grid > g, IPDesignVariableParameterization &tp)
virtual void set_design(array::Scalar &zeta)
Sets the current value of of the design paramter .
array::Scalar1 m_dzeta_local
Storage for d_zeta with ghosts, if needed when an argument d_zeta is ghost-less.
virtual void assemble_jacobian_state(array::Vector &u, Mat J)
Assembles the state Jacobian matrix.
array::Scalar2 m_tauc_copy
Storage for tauc (avoids modifying fields obtained via pism::Vars)
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:268
void compute_local_jacobian(Vector2d const *const *velocity, Mat J)
Implements the callback for computing the Jacobian.
Definition SSAFEM.cc:958
array::Scalar1 m_bc_mask
Definition SSAFEM.hh:67
std::shared_ptr< TerminationReason > solve_nocache()
Definition SSAFEM.cc:195
void compute_local_function(Vector2d const *const *velocity, Vector2d **residual)
Implements the callback for computing the residual.
Definition SSAFEM.cc:736
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:346
array::Vector1 m_bc_values
Definition SSAFEM.hh:68
array::Array2D< Coefficients > m_coefficients
Definition SSAFEM.hh:74
array::Vector m_velocity_global
Definition SSA.hh:122
IceBasalResistancePlasticLaw * m_basal_sliding_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
bool grounded_ice(int M)
Definition Mask.hh:51
static const double k
Definition exactTestP.cc:42
double val
Function value.
Definition FEM.hh:153