PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IPDesignVariableParameterization.cc
Go to the documentation of this file.
1 // Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 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 <cmath>
20 #include <petsc.h>
21 
22 #include "pism/util/array/Scalar.hh"
23 #include "pism/inverse/IPDesignVariableParameterization.hh"
24 #include "pism/util/ConfigInterface.hh"
25 #include "pism/util/Grid.hh"
26 #include "pism/util/error_handling.hh"
27 #include "pism/util/pism_utilities.hh"
28 
29 namespace pism {
30 namespace inverse {
31 
32 //! Initializes the scale parameters of the parameterization.
33 /*! Every IPDesignVariableParameterization has an associated scale for the design variable
34 \f$d_{\rm scale}\f$ that equals 1 in internal units. The scale for a design variable named \a foo
35 is stored in an Config file as design_param_foo_scale. Subclasses may have additional
36 parameters that are follow the naming convention \a design_param_foo_*.
37 
38 \param config The config file to read the scale parameters from.
39 \param design_var_name The associated name of the design variable, e.g. 'tauc' or 'hardav'
40 */
42  const std::string &design_var_name) {
43  std::string key("inverse.design.param_");
44  key += design_var_name;
45  key += "_scale";
46  m_d_scale = config.get_number(key);
47 }
48 
49 //! Transforms a vector of \f$\zeta\f$ values to a vector of \f$d\f$ values.
51  array::Scalar &d,
52  bool communicate) {
53  PetscErrorCode ierr;
54 
55  array::AccessScope list{&zeta, &d};
56 
57  const Grid &grid = *zeta.grid();
58 
59  ParallelSection loop(grid.com);
60  try {
61  for (auto p = grid.points(); p; p.next()) {
62  const int i = p.i(), j = p.j();
63 
64  this->toDesignVariable(zeta(i, j), &d(i, j), NULL);
65  if (std::isnan(d(i, j))) {
66  ierr = PetscPrintf(PETSC_COMM_WORLD,
67  "made a d nan zeta = %g d = %g\n",
68  zeta(i, j), d(i, j));
69  PISM_CHK(ierr, "PetscPrintf");
70  }
71  }
72  } catch (...) {
73  loop.failed();
74  }
75  loop.check();
76 
77  if (communicate) {
78  d.update_ghosts();
79  }
80 }
81 
82  //! Transforms a vector of \f$d\f$ values to a vector of \f$\zeta\f$ values.
84  array::Scalar &zeta,
85  bool communicate) {
86  PetscErrorCode ierr;
87  array::AccessScope list{&zeta, &d};
88 
89  const Grid &grid = *zeta.grid();
90 
91  ParallelSection loop(grid.com);
92  try {
93  for (auto p = grid.points(); p; p.next()) {
94  const int i = p.i(), j = p.j();
95 
96  this->fromDesignVariable(d(i, j), &zeta(i, j));
97  if (std::isnan(zeta(i, j))) {
98  ierr = PetscPrintf(PETSC_COMM_WORLD,
99  "made a zeta nan d = %g zeta = %g\n",
100  d(i, j), zeta(i, j));
101  PISM_CHK(ierr, "PetscPrintf");
102  }
103  }
104  } catch (...) {
105  loop.failed();
106  }
107  loop.check();
108 
109  if (communicate) {
110  zeta.update_ghosts();
111  }
112 }
113 
114 void IPDesignVariableParamIdent::toDesignVariable(double p, double *value,
115  double *derivative) {
116  if (value != NULL) {
117  *value = m_d_scale*p;
118  }
119  if (derivative != NULL) {
120  *derivative = m_d_scale;
121  }
122 }
123 
124 void IPDesignVariableParamIdent::fromDesignVariable(double d, double *OUTPUT) {
125  *OUTPUT = d / m_d_scale;
126 }
127 
128 
130  double *derivative) {
131  if (value != NULL) {
132  *value = m_d_scale*p*p;
133  }
134  if (derivative != NULL) {
135  *derivative = m_d_scale*2*p;
136  }
137 }
138 
139 void IPDesignVariableParamSquare::fromDesignVariable(double d, double *OUTPUT) {
140  if (d < 0) {
141  d = 0;
142  }
143  *OUTPUT = sqrt(d / m_d_scale);
144 }
145 
146 void IPDesignVariableParamExp::set_scales(const Config &config, const std::string &design_var_name) {
147  IPDesignVariableParameterization::set_scales(config, design_var_name);
148 
149  std::string key("inverse.design.param_");
150  key += design_var_name;
151  key += "_eps";
152  m_d_eps = config.get_number(key);
153 }
154 
155 void IPDesignVariableParamExp::toDesignVariable(double p, double *value,
156  double *derivative) {
157  if (value != NULL) {
158  *value = m_d_scale*exp(p);
159  }
160 
161  if (derivative != NULL) {
162  *derivative = m_d_scale*exp(p);
163  }
164 }
165 
166 void IPDesignVariableParamExp::fromDesignVariable(double d, double *OUTPUT) {
167  if (d < m_d_eps) {
168  d = m_d_eps;
169  }
170  *OUTPUT = log(d / m_d_scale);
171 }
172 
173 
175  const std::string &design_var_name) {
176  IPDesignVariableParameterization::set_scales(config, design_var_name);
177 
178  auto key = pism::printf("inverse.design.param_trunc_%s0", design_var_name.c_str());
179 
180  double d0 = config.get_number(key);
181  m_d0_sq = d0*d0 / (m_d_scale*m_d_scale);
182 
183  key = pism::printf("inverse.design.param_%s_eps", design_var_name.c_str());
184  m_d_eps = config.get_number(key);
185 }
186 
188  double *value,
189  double *derivative) {
190  double alpha = sqrt(p*p + 4*m_d0_sq);
191  if (value != NULL) {
192  *value = m_d_scale*(p + alpha)*0.5;
193  }
194  if (derivative != NULL) {
195  *derivative = m_d_scale*(1 + p / alpha)*0.5;
196  }
197 }
198 
200  if (d < m_d_eps) {
201  d = m_d_eps;
202  }
203 
204  double d_dimensionless = d / m_d_scale;
205  *OUTPUT = d_dimensionless - m_d0_sq / d_dimensionless;
206 }
207 
208 } // end of namespace inverse
209 } // end of namespace pism
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
A class for storing and accessing PISM configuration flags and parameters.
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 set_scales(const Config &config, const std::string &design_var_name)
Initializes the scale parameters of the parameterization.
virtual void toDesignVariable(double p, double *value, double *derivative)
Converts from parameterization value to .
virtual void fromDesignVariable(double tauc, double *OUTPUT)
Converts from to a parameterization value such that .
virtual void toDesignVariable(double p, double *value, double *derivative)
Converts from parameterization value to .
virtual void fromDesignVariable(double tauc, double *OUTPUT)
Converts from to a parameterization value such that .
virtual void toDesignVariable(double p, double *value, double *derivative)
Converts from parameterization value to .
virtual void fromDesignVariable(double tauc, double *OUTPUT)
Converts from to a parameterization value such that .
virtual void toDesignVariable(double p, double *value, double *derivative)
Converts from parameterization value to .
virtual void set_scales(const Config &config, const std::string &design_var_name)
Initializes the scale parameters of the parameterization.
virtual void fromDesignVariable(double d, double *OUTPUT)
Converts from to a parameterization value such that .
double m_d_scale
Value of in PISM units that equals 1 for IPDesignVariableParameterization's units.
virtual void convertToDesignVariable(array::Scalar &zeta, array::Scalar &d, bool communicate=true)
Transforms a vector of values to a vector of values.
virtual void convertFromDesignVariable(array::Scalar &d, array::Scalar &zeta, bool communicate=true)
Transforms a vector of values to a vector of values.
virtual void fromDesignVariable(double d, double *OUTPUT)=0
Converts from to a parameterization value such that .
virtual void toDesignVariable(double zeta, double *value, double *derivative)=0
Converts from parameterization value to .
virtual void set_scales(const Config &config, const std::string &design_var_name)
Initializes the scale parameters of the parameterization.
#define PISM_CHK(errcode, name)
std::string printf(const char *format,...)