PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IP_H1NormFunctional.cc
Go to the documentation of this file.
1 // Copyright (C) 2012, 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/IP_H1NormFunctional.hh"
20 #include "pism/util/error_handling.hh"
21 #include "pism/util/Grid.hh"
22 #include "pism/util/pism_utilities.hh"
23 #include "pism/util/array/Scalar.hh"
24 
25 namespace pism {
26 namespace inverse {
27 
29 
30  const unsigned int Nk = fem::q1::n_chi;
31  const unsigned int Nq = m_element.n_pts();
32  const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
33 
34  // The value of the objective
35  double value = 0;
36 
37  double x_e[Nk];
38  double x_q[Nq_max], dxdx_q[Nq_max], dxdy_q[Nq_max];
39  array::AccessScope list(x);
40 
42 
43  // Loop through all LOCAL elements.
44  const int
45  xs = m_element_index.lxs,
46  xm = m_element_index.lxm,
47  ys = m_element_index.lys,
48  ym = m_element_index.lym;
49 
50  for (int j=ys; j<ys+ym; j++) {
51  for (int i=xs; i<xs+xm; i++) {
52  m_element.reset(i, j);
53 
54  // Obtain values of x at the quadrature points for the element.
55  m_element.nodal_values(x.array(), x_e);
56  if (dirichletBC) {
57  dirichletBC.enforce_homogeneous(m_element, x_e);
58  }
59  m_element.evaluate(x_e, x_q, dxdx_q, dxdy_q);
60 
61  for (unsigned int q=0; q<Nq; q++) {
62  auto W = m_element.weight(q);
63  value += W*(m_cL2*x_q[q]*x_q[q]+ m_cH1*(dxdx_q[q]*dxdx_q[q]+dxdy_q[q]*dxdy_q[q]));
64  } // q
65  } // j
66  } // i
67 
68  GlobalSum(m_grid->com, &value, OUTPUT, 1);
69 }
70 
72 
73  const unsigned int Nk = fem::q1::n_chi;
74  const unsigned int Nq = m_element.n_pts();
75  const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
76 
77  // The value of the objective
78  double value = 0;
79 
80  double a_e[Nk];
81  double a_q[Nq_max], dadx_q[Nq_max], dady_q[Nq_max];
82 
83  double b_e[Nk];
84  double b_q[Nq_max], dbdx_q[Nq_max], dbdy_q[Nq_max];
85 
86  array::AccessScope list{&a, &b};
87 
89 
90  // Loop through all LOCAL elements.
91  const int
92  xs = m_element_index.lxs,
93  xm = m_element_index.lxm,
94  ys = m_element_index.lys,
95  ym = m_element_index.lym;
96 
97  for (int j=ys; j<ys+ym; j++) {
98  for (int i=xs; i<xs+xm; i++) {
99  m_element.reset(i, j);
100 
101  // Obtain values of x at the quadrature points for the element.
102  m_element.nodal_values(a.array(), a_e);
103  if (dirichletBC) {
104  dirichletBC.enforce_homogeneous(m_element, a_e);
105  }
106  m_element.evaluate(a_e, a_q, dadx_q, dady_q);
107 
108  m_element.nodal_values(b.array(), b_e);
109  if (dirichletBC) {
110  dirichletBC.enforce_homogeneous(m_element, b_e);
111  }
112  m_element.evaluate(b_e, b_q, dbdx_q, dbdy_q);
113 
114  for (unsigned int q=0; q<Nq; q++) {
115  auto W = m_element.weight(q);
116  value += W*(m_cL2*a_q[q]*b_q[q]+ m_cH1*(dadx_q[q]*dbdx_q[q]+dady_q[q]*dbdy_q[q]));
117  } // q
118  } // j
119  } // i
120 
121  GlobalSum(m_grid->com, &value, OUTPUT, 1);
122 }
123 
124 
126 
127  const unsigned int Nk = fem::q1::n_chi;
128  const unsigned int Nq = m_element.n_pts();
129  const unsigned int Nq_max = fem::MAX_QUADRATURE_SIZE;
130 
131  // Clear the gradient before doing anything with it!
132  gradient.set(0);
133 
134  double x_e[Nk];
135  double x_q[Nq_max], dxdx_q[Nq_max], dxdy_q[Nq_max];
136 
137  double gradient_e[Nk];
138 
139  array::AccessScope list{&x, &gradient};
140 
142 
143  // Loop through all local and ghosted elements.
144  const int
145  xs = m_element_index.xs,
146  xm = m_element_index.xm,
147  ys = m_element_index.ys,
148  ym = m_element_index.ym;
149 
150  for (int j=ys; j<ys+ym; j++) {
151  for (int i=xs; i<xs+xm; i++) {
152 
153  // Reset the DOF map for this element.
154  m_element.reset(i, j);
155 
156  // Obtain values of x at the quadrature points for the element.
157  m_element.nodal_values(x.array(), x_e);
158  if (dirichletBC) {
159  dirichletBC.constrain(m_element);
160  dirichletBC.enforce_homogeneous(m_element, x_e);
161  }
162  m_element.evaluate(x_e, x_q, dxdx_q, dxdy_q);
163 
164  // Zero out the element-local residual in prep for updating it.
165  for (unsigned int k=0; k<Nk; k++) {
166  gradient_e[k] = 0;
167  }
168 
169  for (unsigned int q=0; q<Nq; q++) {
170  auto W = m_element.weight(q);
171  const double &x_qq=x_q[q];
172  const double &dxdx_qq=dxdx_q[q], &dxdy_qq=dxdy_q[q];
173  for (unsigned int k=0; k<Nk; k++) {
174  gradient_e[k] += 2*W*(m_cL2*x_qq*m_element.chi(q, k).val +
175  m_cH1*(dxdx_qq*m_element.chi(q, k).dx + dxdy_qq*m_element.chi(q, k).dy));
176  } // k
177  } // q
178  m_element.add_contribution(gradient_e, gradient.array());
179  } // j
180  } // i
181 }
182 
184 
185  const unsigned int Nk = fem::q1::n_chi;
186  const unsigned int Nq = m_element.n_pts();
187 
188  PetscErrorCode ierr;
189 
190  // Zero out the Jacobian in preparation for updating it.
191  ierr = MatZeroEntries(form);
192  PISM_CHK(ierr, "MatZeroEntries");
193 
195 
196  // Loop through all the elements.
197  const int
198  xs = m_element_index.xs,
199  xm = m_element_index.xm,
200  ys = m_element_index.ys,
201  ym = m_element_index.ym;
202 
203  ParallelSection loop(m_grid->com);
204  try {
205  for (int j=ys; j<ys+ym; j++) {
206  for (int i=xs; i<xs+xm; i++) {
207  // Element-local Jacobian matrix (there are Nk vector valued degrees
208  // of freedom per elment, for a total of (2*Nk)*(2*Nk) = 16
209  // entries in the local Jacobian.
210  double K[Nk][Nk];
211 
212  // Initialize the map from global to local degrees of freedom for this element.
213  m_element.reset(i, j);
214 
215  // Don't update rows/cols where we project to zero.
216  if (zeroLocs) {
217  zeroLocs.constrain(m_element);
218  }
219 
220  // Build the element-local Jacobian.
221  ierr = PetscMemzero(K, sizeof(K));
222  PISM_CHK(ierr, "PetscMemzero");
223 
224  for (unsigned int q=0; q<Nq; q++) {
225  auto W = m_element.weight(q);
226  for (unsigned int k = 0; k < Nk; k++) { // Test functions
227  const fem::Germ &test_qk = m_element.chi(q, k);
228  for (unsigned int l = 0; l < Nk; l++) { // Trial functions
229  const fem::Germ &test_ql=m_element.chi(q, l);
230  K[k][l] += W*(m_cL2*test_qk.val*test_ql.val +
231  m_cH1*(test_qk.dx*test_ql.dx +
232  test_qk.dy*test_ql.dy));
233  } // l
234  } // k
235  } // q
236  m_element.add_contribution(&K[0][0], form);
237  } // j
238  } // i
239  } catch (...) {
240  loop.failed();
241  }
242  loop.check();
243 
244  if (zeroLocs) {
245  zeroLocs.fix_jacobian(form);
246  }
247 
248  ierr = MatAssemblyBegin(form, MAT_FINAL_ASSEMBLY);
249  PISM_CHK(ierr, "MatAssemblyBegin");
250 
251  ierr = MatAssemblyEnd(form, MAT_FINAL_ASSEMBLY);
252  PISM_CHK(ierr, "MatAssemblyEnd");
253 }
254 
255 } // end of namespace inverse
256 } // end of namespace pism
void failed()
Indicates a failure of a parallel section.
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
virtual void dot(array::Scalar &a, array::Scalar &b, double *OUTPUT)
Computes the inner product .
virtual void gradientAt(array::Scalar &x, array::Scalar &gradient)
Computes the gradient of the functional at the vector x.
virtual void valueAt(array::Scalar &x, double *OUTPUT)
Computes the value of the functional at the vector x.
#define PISM_CHK(errcode, name)
const int n_chi
Definition: FEM.hh:191
const unsigned int MAX_QUADRATURE_SIZE
Definition: FEM.hh:173
static double K(double psi_x, double psi_y, double speed, double epsilon)
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 val
Function value.
Definition: FEM.hh:153
double dx
Function deriviative with respect to x.
Definition: FEM.hh:155
Struct for gathering the value and derivative of a function at a point.
Definition: FEM.hh:151