PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IP_SSAHardavForwardProblem.hh
Go to the documentation of this file.
1 // Copyright (C) 2013, 2014, 2015, 2016, 2017, 2020, 2021, 2022, 2023 David Maxwell
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 2 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 #ifndef IP_SSAHARDAVFORWARDPROBLEM_HH_HAD68BK7
20 #define IP_SSAHARDAVFORWARDPROBLEM_HH_HAD68BK7
21 
22 #include "pism/stressbalance/ssa/SSAFEM.hh"
23 #include "pism/inverse/IPDesignVariableParameterization.hh"
24 #include "pism/util/petscwrappers/KSP.hh"
25 #include "pism/util/petscwrappers/Mat.hh"
26 
27 namespace pism {
28 namespace inverse {
29 
30 //! Implements the forward problem of the map taking \f$\tau_c\f$ to the corresponding solution of the %SSA.
31 /*! The class SSAFEM solves the %SSA, and the solution depends on a large number of parameters. Considering
32  all of these to be fixed except for \f$\tau_c\f$, we obtain a map \f$F_{\rm SSA}\f$ taking
33  \f$\tau_c\f$ to the corresponding solution \f$u_{\rm SSA}\f$ of the %SSA. This is a forward problem which
34  we would like to invert; given \f$u_{\rm SSA}\f$ determine \f$\tau_c\f$ such that
35  \f$F_{\rm SSA}(\tau_c) = u_{\rm SSA}\f$. The forward problem actually implemented by
36  IP_SSAHardavForwardProblem is a mild variation \f$F_{\rm SSA}\f$.
37 
38  First, given the constraint \f$\tau_c\ge 0\f$ it can be helpful to parameterize \f$\tau_c\f$ by some other
39  parameter \f$\zeta\f$,
40  \f[
41  \tau_c = g(\zeta),
42  \f]
43  where the function \f$g\f$ is non-negative. The function \f$g\f$ is specified by an instance
44  of IPDesignVariableParameterization.
45 
46  Second, there may be locations where the value of \f$\tau_c\f$ (and hence \f$\zeta\f$)
47  is known a-priori, and should not be adjusted. Let \f$\pi\f$ be the map that replaces
48  the values of \f$\zeta\f$ with known values at these locations.
49 
50  IP_SSAHardavForwardProblem implements the forward problem
51  \f[
52  F(\zeta) = F_{\rm SSA}(g(\pi(\zeta))).
53  \f]
54 
55  Algorithms to solve the inverse problem make use of variations on the linearization
56  of \f$F\f$, which are explained below.
57 
58  The solution of the %SSA in SSAFEM is implemented using SNES to solve
59  a nonlinear residual function of the form
60  \f[
61  \mathcal{R}_{SSA}(u;\tau_c, \text{other parameters})= \vec 0,
62  \f]
63  usually using Newton's method. Let
64  \f[
65  \mathcal{R}(u, \zeta) = \mathcal{R}_{SSA}(u; g(\pi(\zeta)), \text{other parameters}).
66  \f]
67 
68  The derivative of \f$\mathcal{R}\f$ with respect to \f$ u\f$ is called the state Jacobian,
69  \f$J_{\rm State}\f$. Specifically, if \f$u=[U_j]\f$ then
70  \f[
71  (J_{\rm State})_{ij} = \frac{d \mathcal{R}_i}{dU_j}.
72  \f]
73  This is exactly the same Jacobian that is computed by SSAFEM for solving the %SSA via SNES. The
74  matrix for the design Jacobian can be obtained with \ref assemble_jacobian_state.
75 
76  The derivative of \f$\mathcal{R}\f$ with respect to \f$ \zeta\f$ is called the design Jacobian,
77  \f$J_{\rm Design}\f$. Specifically, if \f$\zeta=[Z_k]\f$ then
78  \f[
79  (J_{\rm Design})_{ik} = \frac{d \mathcal{R}_i}{dZ_k}.
80  \f]
81  The map \f$J_{\rm Design}\f$ can be applied to a vector \f$d\zeta\f$ with
82  apply_jacobian_design. For inverse methods using adjoints, one also
83  needs to be able to apply the transpose of \f$J_{\rm Design}\f$,
84  which is done using \ref apply_jacobian_design_transpose.
85 
86  The forward problem map \f$F\f$ solves the implicit equation
87  \f[
88  \mathcal{R}(F(\zeta), \zeta) = 0.
89  \f]
90  Its linearisation \f$DF\f$ then satisfies
91  \f[
92  J_{\rm State}\; DF\; d\zeta + J_{\rm Design}\; d\zeta = 0
93  \f]
94  for any perturbation \f$d\zeta\f$. Hence
95  \f[
96  DF = -J_{\rm State}^{-1}\circ J_{\rm Design}.
97  \f]
98  This derivative is sometimes called the reduced gradient in the literature. To
99  apply \f$DF\f$ to a perturbation \f$d\zeta\f$, use \ref apply_linearization. Adjoint
100  methods require the transpose of this map; to apply \f$DF^t\f$ to \f$du\f$ use
101  \ref apply_linearization_transpose.
102 */
104 {
105 public:
106 
107  /// The function space for the design variable, i.e. \f$\tau_c\f$.
110 
111  /// The function space for the state variable, \f$u_{\rm SSA}\f$.
114 
115  //! Constructs from the same objects as SSAFEM, plus a specification of how \f$\tau_c\f$ is parameterized.
116  IP_SSAHardavForwardProblem(std::shared_ptr<const Grid> g,
118 
119  virtual ~IP_SSAHardavForwardProblem() = default;
120 
121  //! Selects nodes where \f$\tau_c\f$ (more specifically \f$\zeta\f$) should not be adjusted.
122  /*! The paramter \a locations should be set to 1 at each node where \f$\tau_c\f$
123  is fixed. The forward map then effectively treats the design space as the subspace
124  of nodes where \a locations is 0. Tangent vectors to this subspace, as would be
125  generated by, e.g., \f$J_{\rm Design}^t\f$ are represented as vectors in the full
126  space with entries set to zero in the fixed locations. These can safely be added
127  to preexisting values of \f$\zeta\f$ without changing the entries of \f$\zeta\f$ at the
128  fixed locations. Inversion can be done by setting an initial value of \f$\zeta\f$
129  having the desired values in the fixed locations, and using set_tauc_fixed_locations()
130  to indicated the nodes that should not be changed.
131  */
132  virtual void set_design_fixed_locations(array::Scalar &locations)
133  {
134  m_fixed_design_locations = &locations;
135  }
136 
137  //! Returns the last solution of the %SSA as computed by \ref linearize_at.
138  virtual std::shared_ptr<array::Vector> solution() {
139  m_velocity_shared->copy_from(m_velocity);
140  return m_velocity_shared;
141  }
142 
143  //! Exposes the design variable parameterization being used.
145  return m_design_param;
146  }
147 
148  void init();
149 
150  virtual void set_design(array::Scalar &zeta);
151 
152  virtual std::shared_ptr<TerminationReason> linearize_at(array::Scalar &zeta);
153 
154  virtual void assemble_residual(array::Vector &u, array::Vector &R);
155  virtual void assemble_residual(array::Vector &u, Vec R);
156 
157  virtual void assemble_jacobian_state(array::Vector &u, Mat J);
158 
159  virtual void apply_jacobian_design(array::Vector &u, array::Scalar &dzeta, array::Vector &du);
160  virtual void apply_jacobian_design(array::Vector &u, array::Scalar &dzeta, Vec du);
161  virtual void apply_jacobian_design(array::Vector &u, array::Scalar &dzeta, Vector2d **du_a);
162 
164  virtual void apply_jacobian_design_transpose(array::Vector &u, array::Vector &du, Vec dzeta);
165  virtual void apply_jacobian_design_transpose(array::Vector &u, array::Vector &du, double **dzeta);
166 
167  virtual void apply_linearization(array::Scalar &dzeta, array::Vector &du);
169 
170  //! Exposes the DMDA of the underlying grid for the benefit of TAO.
171  petsc::DM& get_da() const {
172  return *m_da;
173  }
174 
175 protected:
176  const int m_stencil_width;
177 
178  /// Current value of zeta, provided from caller.
180  /// Storage for d_zeta with ghosts, if needed when an argument d_zeta is ghost-less.
182 
183  /// Locations where \f$\tau_c\f$ should not be adjusted.
185 
186  /// The function taking \f$\zeta\f$ to \f$\tau_c\f$.
188 
189  std::shared_ptr<array::Vector> m_velocity_shared;
190 
191  /// Temporary storage when state vectors need to be used without ghosts.
193  /// Temporary storage when state vectors need to be used with ghosts.
195  /// Vertically-averaged ice hardness.
197 
200 
201  /// KSP used in \ref apply_linearization and \ref apply_linearization_transpose
203  /// Mat used in \ref apply_linearization and \ref apply_linearization_transpose
205 
206  SNESConvergedReason m_reason;
207 
208  /// Flag indicating that the state jacobian matrix needs rebuilding.
210 };
211 
212 } // end of namespace inverse
213 } // end of namespace pism
214 
215 #endif /* end of include guard: IP_SSAHARDAVFORWARDPROBLEM_HH_HAD68BK7 */
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
Definition: Vector2d.hh:29
Manages iterating over element indices.
Q1 element with sides parallel to X and Y axes.
Definition: Element.hh:257
petsc::Mat m_J_state
Mat used in apply_linearization and apply_linearization_transpose.
virtual std::shared_ptr< array::Vector > solution()
Returns the last solution of the SSA as computed by linearize_at.
virtual IPDesignVariableParameterization & design_param()
Exposes the design variable parameterization being used.
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::Scalar DesignVec
The function space for the design variable, i.e. .
array::Scalar1 m_hardav
Vertically-averaged ice hardness.
array::Scalar * m_fixed_design_locations
Locations where should not be adjusted.
petsc::DM & get_da() const
Exposes the DMDA of the underlying grid for the benefit of TAO.
array::Scalar1 m_dzeta_local
Storage for d_zeta with ghosts, if needed when an argument d_zeta is ghost-less.
virtual void set_design_fixed_locations(array::Scalar &locations)
Selects nodes where (more specifically ) should not be adjusted.
IP_SSAHardavForwardProblem(std::shared_ptr< const Grid > g, IPDesignVariableParameterization &tp)
Constructs from the same objects as SSAFEM, plus a specification of how is parameterized.
std::shared_ptr< array::Vector > m_velocity_shared
array::Vector StateVec
The function space for the state variable, .
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.
Implements the forward problem of the map taking to the corresponding solution of the SSA.
PISM's SSA solver: the finite element method implementation written by Jed and David.
Definition: SSAFEM.hh:40
std::shared_ptr< petsc::DM > m_da
Definition: SSA.hh:149
static const double g
Definition: exactTestP.cc:36
const int J[]
Definition: ssafd_code.cc:34