PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IPTotalVariationFunctional.cc
Go to the documentation of this file.
1 // Copyright (C) 2012, 2013, 2014, 2015, 2016, 2017, 2020, 2022, 2023 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/functional/IPTotalVariationFunctional.hh"
20 #include "pism/util/Grid.hh"
21 #include "pism/util/pism_utilities.hh"
22 #include "pism/util/array/Scalar.hh"
23 
24 namespace pism {
25 namespace inverse {
26 
28  double c, double exponent, double eps,
29  array::Scalar *dirichletLocations) :
30  IPFunctional<array::Scalar>(grid), m_dirichletIndices(dirichletLocations),
31  m_c(c), m_lebesgue_exp(exponent), m_epsilon_sq(eps*eps) {
32 }
33 
35 
36  const unsigned int Nk = fem::q1::n_chi;
37  const unsigned int Nq = m_element.n_pts();
38  const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
39 
40  // The value of the objective
41  double value = 0;
42 
43  double x_e[Nk];
44  double x_q[Nq_max], dxdx_q[Nq_max], dxdy_q[Nq_max];
45 
46  array::AccessScope list(x);
47 
49 
50  // Loop through all LOCAL elements.
51  const int
52  xs = m_element_index.lxs,
53  xm = m_element_index.lxm,
54  ys = m_element_index.lys,
55  ym = m_element_index.lym;
56 
57  for (int j = ys; j < ys + ym; j++) {
58  for (int i = xs; i < xs + xm; i++) {
59  m_element.reset(i, j);
60 
61  // Obtain values of x at the quadrature points for the element.
62  m_element.nodal_values(x.array(), x_e);
63  if (dirichletBC) {
64  dirichletBC.enforce_homogeneous(m_element, x_e);
65  }
66  m_element.evaluate(x_e, x_q, dxdx_q, dxdy_q);
67 
68  for (unsigned int q = 0; q < Nq; q++) {
69  auto W = m_element.weight(q);
70  value += m_c*W*pow(m_epsilon_sq + dxdx_q[q]*dxdx_q[q] + dxdy_q[q]*dxdy_q[q], m_lebesgue_exp / 2);
71  } // q
72  } // j
73  } // i
74 
75  GlobalSum(m_grid->com, &value, OUTPUT, 1);
76 }
77 
79 
80  const unsigned int Nk = fem::q1::n_chi;
81  const unsigned int Nq = m_element.n_pts();
82  const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
83 
84  // Clear the gradient before doing anything with it.
85  gradient.set(0);
86 
87  double x_e[Nk];
88  double x_q[Nq_max], dxdx_q[Nq_max], dxdy_q[Nq_max];
89 
90  double gradient_e[Nk];
91 
92  array::AccessScope list{&x, &gradient};
93 
95 
96  // Loop through all local and ghosted elements.
97  const int
98  xs = m_element_index.xs,
99  xm = m_element_index.xm,
100  ys = m_element_index.ys,
101  ym = m_element_index.ym;
102 
103  for (int j = ys; j < ys + ym; j++) {
104  for (int i = xs; i < xs + xm; i++) {
105 
106  // Reset the DOF map for this element.
107  m_element.reset(i, j);
108 
109  // Obtain values of x at the quadrature points for the element.
110  m_element.nodal_values(x.array(), x_e);
111  if (dirichletBC) {
112  dirichletBC.constrain(m_element);
113  dirichletBC.enforce_homogeneous(m_element, x_e);
114  }
115  m_element.evaluate(x_e, x_q, dxdx_q, dxdy_q);
116 
117  // Zero out the element-local residual in preparation for updating it.
118  for (unsigned int k = 0; k < Nk; k++) {
119  gradient_e[k] = 0;
120  }
121 
122  for (unsigned int q = 0; q < Nq; q++) {
123  auto W = m_element.weight(q);
124  const double &dxdx_qq = dxdx_q[q], &dxdy_qq = dxdy_q[q];
125  for (unsigned int k = 0; k < Nk; k++) {
126  gradient_e[k] += m_c*W*(m_lebesgue_exp)*pow(m_epsilon_sq + dxdx_q[q]*dxdx_q[q] + dxdy_q[q]*dxdy_q[q], m_lebesgue_exp / 2 - 1)
127  *(dxdx_qq*m_element.chi(q, k).dx + dxdy_qq*m_element.chi(q, k).dy);
128  } // k
129  } // q
130  m_element.add_contribution(gradient_e, gradient.array());
131  } // j
132  } // i
133 }
134 
135 } // end of namespace inverse
136 } // end of namespace pism
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition: Array.hh:65
void set(double c)
Result: v[j] <- c for all j.
Definition: Array.cc:707
void enforce_homogeneous(const Element2 &element, double *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:187
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:231
void nodal_values(const array::Scalar &x_global, int *result) const
Get nodal values of an integer mask.
Definition: Element.cc:176
int xm
total number of elements to loop over in the x-direction.
int lym
total number local elements in y direction.
int lxm
total number local elements in x direction.
int lxs
x-index of the first local element.
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 lys
y-index of the first local element.
int xs
x-coordinate of the first element to loop over.
const Germ & chi(unsigned int q, unsigned int k) const
Definition: Element.hh:73
int n_pts() const
Number of quadrature points.
Definition: Element.hh:80
double weight(unsigned int q) const
Weight of the quadrature point q
Definition: Element.hh:85
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 valueAt(array::Scalar &x, double *OUTPUT)
Computes the value of the functional at the vector x.
virtual void gradientAt(array::Scalar &x, array::Scalar &gradient)
Computes the gradient of the functional at the vector x.
IPTotalVariationFunctional2S(std::shared_ptr< const Grid > grid, double c, double q, double eps, array::Scalar *dirichletLocations=NULL)
const int n_chi
Definition: FEM.hh:191
const unsigned int MAX_QUADRATURE_SIZE
Definition: FEM.hh:173
static const double k
Definition: exactTestP.cc:42
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)
double dy
Function derivative with respect to y.
Definition: FEM.hh:157
double dx
Function deriviative with respect to x.
Definition: FEM.hh:155