PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IPFunctional.hh
Go to the documentation of this file.
1 // Copyright (C) 2012, 2013, 2014, 2015, 2016, 2017, 2020, 2022 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 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 #ifndef PISM_IPFUNCTIONAL_H
20 #define PISM_IPFUNCTIONAL_H
21 
22 #include "pism/util/fem/FEM.hh"
23 
24 namespace pism {
25 
26 class Grid;
27 
28 //! Inverse modeling code.
29 namespace inverse {
30 //! Abstract base class for functions from ice model vectors to \f$\mathbb{R}\f$.
31 /*! Inverse problems frequently involve minimizing a functional,
32  such such as the misfit
33  \f[
34  J(u) = \int_\Omega |u-u_{\rm obs}|^2
35  \f]
36  between observed (\f$u_{\rm obs}\f$) and modeled (\f$u\f$)
37  surface velocities. Subclasses of IPFunctional define such maps,
38  and permit computation of their gradients.
39 */
40 template<class IMVecType>
41 class IPFunctional {
42 
43 public:
44  IPFunctional(std::shared_ptr<const Grid> grid)
45  : m_grid(grid),
47  m_element(*m_grid, fem::Q1Quadrature4())
48  {
49  // empty
50  }
51 
52  virtual ~IPFunctional() {};
53 
54  //! Computes the value of the functional at the vector x.
55  virtual void valueAt(IMVecType &x, double *OUTPUT) = 0;
56 
57  //! Computes the gradient of the functional at the vector x.
58  /*! On an \f$m\times n\f$ Grid, an array::Array \f$x\f$ with \f$d\f$
59  degrees of freedom will be \f$d m n\f$-dimensional with components \f$x_i\f$.
60  The gradient computed here is the vector of directional derivatives \f$\nabla J\f$ of the functional
61  \f$J\f$ with respect to \f$x\f$. Concretely, the \f$i^{\rm th}\f$ component of \f$\nabla J\f$
62  is
63  \f[
64  \nabla J_i = \frac{\partial}{\partial x_i} J(x).
65  \f]
66  This vector is returned as `gradient`.
67  */
68  virtual void gradientAt(IMVecType &x, IMVecType &gradient) = 0;
69 
70 protected:
71  std::shared_ptr<const Grid> m_grid;
72 
75 
76 private:
77  // Hide copy/assignment operations
80 
81 };
82 
83 //! Abstract base class for IPFunctionals arising from an inner product.
84 /*!
85  Frequently functionals have the structure
86  \f[
87  J(u) = Q(u, u)
88  \f]
89  where \f$Q\f$ is a symmetric, non-negative definite, bilinear form. Certain
90  minimization algorithms only apply to such functionals, which should subclass
91  from IPInnerProductFunctional.
92 */
93 template<class IMVecType>
94 class IPInnerProductFunctional : public IPFunctional<IMVecType> {
95 
96 public:
97  IPInnerProductFunctional(std::shared_ptr<const Grid> grid) : IPFunctional<IMVecType>(grid) {};
98 
99  //! Computes the inner product \f$Q(a, b)\f$.
100  virtual void dot(IMVecType &a, IMVecType &b, double *OUTPUT) = 0;
101 
102  //! Computes the interior product of a vector with the IPInnerProductFunctional's underlying bilinear form.
103  /*! If \f$Q(x, y)\f$ is a bilinear form, and \f$a\f$ is a vector, then the
104  interior product of \f$a\f$ with \f$Q\f$ is the functional
105  \f[
106  I(z) = Q(a, z).
107  \f]
108  Such a functional is always linear and hence can be represented by taking
109  the standard dot product with some vector \f$y\f$:
110  \f[
111  I(z) = y^T z.
112  \f]
113  This method returns the vector \f$y\f$.
114  */
115  virtual void interior_product(IMVecType &x, IMVecType &y) {
116  this->gradientAt(x, y);
117  y.scale(0.5);
118  }
119 
120  // Assembles the matrix \f$Q_{ij}\f$ corresponding to the bilinear form.
121  /* If \f$\{x_i\}\f$ is a basis for the vector space IMVecType,
122  \f$Q_{ij}= Q(x_i, x_j)\f$. */
123  // virtual void assemble_form(Mat Q) = 0;
124 
125 };
126 
127 //! Computes finite difference approximations of a IPFunctional<array::Scalar> gradient.
128 /*! Useful for debugging a hand coded gradient. */
129 void gradientFD(IPFunctional<array::Scalar> &f, array::Scalar &x, array::Scalar &gradient);
130 
131 //! Computes finite difference approximations of a IPFunctional<array::Vector> gradient.
132 /*! Useful for debugging a hand coded gradient. */
133 void gradientFD(IPFunctional<array::Vector> &f, array::Vector &x, array::Vector &gradient);
134 
135 } // end of namespace inverse
136 } // end of namespace pism
137 
138 #endif // PISM_IPFUNCTIONAL_H
Manages iterating over element indices.
Q1 element with sides parallel to X and Y axes.
Definition: Element.hh:257
virtual void valueAt(IMVecType &x, double *OUTPUT)=0
Computes the value of the functional at the vector x.
IPFunctional(std::shared_ptr< const Grid > grid)
Definition: IPFunctional.hh:44
IPFunctional(IPFunctional const &)
IPFunctional & operator=(IPFunctional const &)
virtual void gradientAt(IMVecType &x, IMVecType &gradient)=0
Computes the gradient of the functional at the vector x.
fem::ElementIterator m_element_index
Definition: IPFunctional.hh:73
std::shared_ptr< const Grid > m_grid
Definition: IPFunctional.hh:71
Abstract base class for functions from ice model vectors to .
Definition: IPFunctional.hh:41
virtual void dot(IMVecType &a, IMVecType &b, double *OUTPUT)=0
Computes the inner product .
virtual void interior_product(IMVecType &x, IMVecType &y)
Computes the interior product of a vector with the IPInnerProductFunctional's underlying bilinear for...
IPInnerProductFunctional(std::shared_ptr< const Grid > grid)
Definition: IPFunctional.hh:97
Abstract base class for IPFunctionals arising from an inner product.
Definition: IPFunctional.hh:94
void gradientFD(IPFunctional< array::Scalar > &f, array::Scalar &x, array::Scalar &gradient)
Computes finite difference approximations of a IPFunctional<array::Scalar> gradient.
Definition: IPFunctional.cc:28