PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IPFunctional.cc
Go to the documentation of this file.
1 // Copyright (C) 2012, 2013, 2014, 2015, 2017, 2020, 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 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/IPFunctional.hh"
20 #include "pism/util/Grid.hh"
21 #include "pism/util/array/Vector.hh"
22 #include "pism/util/array/Scalar.hh"
23 #include "pism/util/error_handling.hh"
24 
25 namespace pism {
26 namespace inverse {
27 
29  const Grid &grid = *x.grid();
30  double h = PETSC_SQRT_MACHINE_EPSILON;
31 
32  double F0,Fh;
33 
34  f.valueAt(x,&F0);
35 
36  array::AccessScope list(gradient);
37 
38  ParallelSection loop(grid.com);
39  try {
40  for (auto p = grid.points(); p; p.next()) {
41  const int i = p.i(), j = p.j();
42 
43  {
44  array::AccessScope access_x(x);
45  x(i,j) += h;
46  }
47  x.update_ghosts();
48 
49  f.valueAt(x,&Fh);
50 
51  {
52  array::AccessScope access_x(x);
53  x(i,j) -= h;
54  }
55  x.update_ghosts();
56 
57  gradient(i,j) = (Fh-F0)/h;
58  }
59  } catch (...) {
60  loop.failed();
61  }
62  loop.check();
63 }
64 
66  const Grid &grid = *x.grid();
67  double h = PETSC_SQRT_MACHINE_EPSILON;
68 
69  double F0,Fh;
70 
71  f.valueAt(x,&F0);
72 
73  array::AccessScope access_gradient(gradient);
74 
75  ParallelSection loop(grid.com);
76  try {
77  for (auto p = grid.points(); p; p.next()) {
78  const int i = p.i(), j = p.j();
79 
80  {
81  array::AccessScope access_x(x);
82  x(i,j).u += h;
83  }
84  x.update_ghosts();
85 
86  f.valueAt(x,&Fh);
87 
88  {
89  array::AccessScope access_x(x);
90  x(i,j).u -= h;
91  }
92  x.update_ghosts();
93 
94  gradient(i,j).u = (Fh-F0)/h;
95 
96  {
97  array::AccessScope access_x(x);
98  x(i,j).v += h;
99  }
100  x.update_ghosts();
101 
102  f.valueAt(x,&Fh);
103 
104  {
105  array::AccessScope access_x(x);
106  x(i,j).v -= h;
107  }
108  x.update_ghosts();
109 
110  gradient(i,j).v = (Fh-F0)/h;
111  }
112  } catch (...) {
113  loop.failed();
114  }
115  loop.check();
116 }
117 
118 // PetscErrorCode gradientFD(IPFunctional<array::Vector> &f, array::Vector &x, array::Vector &gradient);
119 
120 } // end of namespace inverse
121 } // end of namespace pism
PointsWithGhosts points(unsigned int stencil_width=0) const
Definition: Grid.hh:362
const MPI_Comm com
Definition: Grid.hh:355
Describes the PISM grid and the distribution of data across processors.
Definition: Grid.hh:282
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
std::shared_ptr< const Grid > grid() const
Definition: Array.cc:132
void update_ghosts()
Updates ghost points.
Definition: Array.cc:693
virtual void valueAt(IMVecType &x, double *OUTPUT)=0
Computes the value of the functional at the vector x.
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