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