PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
PIK.cc
Go to the documentation of this file.
1 // Copyright (C) 2009-2018, 2023 Ricarda Winkelmann, Torsten Albrecht, Constantine Khrulev
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 2 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 // Implementation of the atmosphere model using constant-in-time precipitation
20 // and a cosine yearly cycle for near-surface air temperatures.
21 
22 // This includes the PIK temperature parameterization.
23 
24 #include "pism/coupler/atmosphere/PIK.hh"
25 
26 #include "pism/geometry/Geometry.hh"
27 #include "pism/util/ConfigInterface.hh"
28 #include "pism/util/Grid.hh"
29 #include "pism/util/MaxTimestep.hh"
30 #include "pism/util/error_handling.hh"
31 
32 namespace pism {
33 namespace atmosphere {
34 
35 PIK::PIK(std::shared_ptr<const Grid> g)
36  : YearlyCycle(g) {
37 
38  auto parameterization = m_config->get_string("atmosphere.pik.parameterization");
39 
40  std::map<std::string, Parameterization>
41  models = {{"martin", MARTIN},
42  {"huybrechts_dewolde", HUYBRECHTS_DEWOLDE},
43  {"martin_huybrechts_dewolde", MARTIN_HUYBRECHTS_DEWOLDE},
44  {"era_interim", ERA_INTERIM},
45  {"era_interim_sin", ERA_INTERIM_SIN},
46  {"era_interim_lon", ERA_INTERIM_LON}};
47 
48  if (models.find(parameterization) == models.end()) {
50  "invalid pik parameterization: %s",
51  parameterization.c_str());
52  }
53 
54  m_parameterization = models[parameterization];
55 }
56 
57 void PIK::init_impl(const Geometry &geometry) {
58 
59  m_log->message(2,
60  "* Initializing PIK atmosphere model with air temperature parameterization based on \n"
61  " Huybrechts & De Wolde (1999) or multiple regression analysis of ERA INTERIM data...\n"
62  " Uses a time-independent precipitation field read from a file.");
63 
64  m_reference = "Winkelmann et al.";
65 
66  auto precip_file = m_config->get_string("atmosphere.pik.file");
67 
68  if (not precip_file.empty()) {
69  YearlyCycle::init_internal(precip_file,
70  true, /* do regrid */
71  0 /* start (irrelevant) */);
72  } else {
73  // try to read precipitation from the input (-i) file
74  YearlyCycle::init_impl(geometry);
75  }
76 
77  switch (m_parameterization) {
78  case HUYBRECHTS_DEWOLDE:
79  m_log->message(2,
80  " Parameterization based on: Huybrechts & De Wolde (1999).\n");
81  break;
82  case ERA_INTERIM:
83  m_log->message(2,
84  " Parameterization based on: multiple regression analysis of ERA INTERIM data.\n");
85  break;
86  case ERA_INTERIM_SIN:
87  m_log->message(2,
88  " Parameterization based on: multiple regression analysis of ERA INTERIM data with a sin(lat) dependence.\n");
89  break;
90  case ERA_INTERIM_LON:
91  m_log->message(2,
92  " Parameterization based on: multiple regression analysis of ERA INTERIM data with a cos(lon) dependence.\n");
93  break;
95  m_log->message(2,
96  " Mean annual temperature: as in Martin et al (2011).\n"
97  " Mean summer temperature: anomaly to the parameterization used by Huybrechts & De Wolde (1999).\n");
98  break;
99  default:
100  case MARTIN:
101  m_log->message(2,
102  " Mean annual temperature: as in Martin et al (2011).\n"
103  " No seasonal variation in air temperature.\n");
104  }
105 }
106 
108  (void) t;
109  return MaxTimestep("atmosphere pik");
110 }
111 
112 /*!
113  * See equation C1 in HuybrechtsdeWolde.
114  */
115 static double huybrechts_dewolde_mean_annual(double surface_elevation, double latitude) {
116  double gamma_a = surface_elevation < 1500.0 ? -0.005102 : -0.014285;
117  return 273.15 + 34.46 + gamma_a * surface_elevation - 0.68775 * latitude * (-1.0);
118 }
119 
120 /*!
121  * See equation C2 in HuybrechtsdeWolde.
122  */
123 static double huybrechts_dewolde_mean_summer(double surface_elevation, double latitude) {
124  return 273.15 + 16.81 - 0.00692 * surface_elevation - 0.27937 * latitude * (-1.0);
125 }
126 
127 /*!
128  * Parameterization of mean annual and mean summer near-surface temperature as in
129  * Huybrechts & DeWolde (1999)
130  */
131 static void huybrechts_dewolde(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
132  auto grid = T_ma.grid();
133 
134  const array::Scalar
135  &h = geometry.ice_surface_elevation,
136  &lat = geometry.latitude;
137 
138  array::AccessScope list{&h, &lat, &T_ma, &T_ms};
139 
140  for (auto p = grid->points(); p; p.next()) {
141  const int i = p.i(), j = p.j();
142 
143  T_ma(i, j) = huybrechts_dewolde_mean_annual(h(i, j), lat(i, j));
144  T_ms(i, j) = huybrechts_dewolde_mean_summer(h(i, j), lat(i, j));
145  }
146 }
147 
148 /*!
149  * Parametrization based on multiple regression analysis of ERA INTERIM data
150  */
151 static void era_interim(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
152  auto grid = T_ma.grid();
153 
154  const array::Scalar
155  &h = geometry.ice_surface_elevation,
156  &lat = geometry.latitude;
157 
158  array::AccessScope list{&h, &lat, &T_ma, &T_ms};
159 
160  for (auto p = grid->points(); p; p.next()) {
161  const int i = p.i(), j = p.j();
162 
163  T_ma(i, j) = 273.15 + 29.2 - 0.0082 * h(i, j) - 0.576 * lat(i, j) * (-1.0);
164  T_ms(i, j) = 273.15 + 16.5 - 0.0068 * h(i, j) - 0.248 * lat(i, j) * (-1.0);
165  }
166 }
167 
168 /*!
169  * Parametrization based on multiple regression analysis of ERA INTERIM data with sin(lat)
170  */
171 static void era_interim_sin(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
172  auto grid = T_ma.grid();
173 
174  const array::Scalar
175  &h = geometry.ice_surface_elevation,
176  &lat = geometry.latitude;
177 
178  array::AccessScope list{&h, &lat, &T_ma, &T_ms};
179 
180  for (auto p = grid->points(); p; p.next()) {
181  const int i = p.i(), j = p.j();
182 
183  T_ma(i, j) = 273.15 - 2.0 - 0.0082 * h(i, j) + 18.4 * (sin(3.1415 * lat(i, j) / 180.0) + 0.8910) / (1 - 0.8910);
184  T_ms(i, j) = 273.15 + 3.2 - 0.0067 * h(i, j) + 8.3 * (sin(3.1415 * lat(i, j) / 180.0) + 0.8910) / (1 - 0.8910);
185  }
186 }
187 
188 /*!
189  * Parametrization based on multiple regression analysis of ERA INTERIM data with cos(lon)
190  */
191 static void era_interim_lon(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
192  auto grid = T_ma.grid();
193 
194  const array::Scalar
195  &h = geometry.ice_surface_elevation,
196  &lat = geometry.latitude,
197  &lon = geometry.longitude;
198 
199  array::AccessScope list{&h, &lat, &lon, &T_ma, &T_ms};
200 
201  for (auto p = grid->points(); p; p.next()) {
202  const int i = p.i(), j = p.j();
203 
204  double hmod = std::max(1000.0, h(i, j));
205  T_ma(i, j) = 273.15 + 37.49 - 0.0095 * hmod - 0.644 * lat(i, j) * (-1.0) + 2.146 * cos(3.1415 * (lon(i, j) + 110.0) / 180.0);
206  T_ms(i, j) = 273.15 + 15.74 - 0.0083 * hmod - 0.196 * lat(i, j) * (-1.0) + 0.225 * cos(3.1415 * (lon(i, j) + 110.0) / 180.0);
207 
208  }
209 }
210 
211 /*!
212  * Parameterization of the mean annual near-surface air temperature, see equation (1) in
213  * Martin et al, 2011.
214  */
215 static double martin2011_mean_annual(double elevation, double latitude) {
216  return 273.15 + 30 - 0.0075 * elevation - 0.68775 * latitude * (-1.0);
217 }
218 
219 /*!
220  * - annual mean temperature as in Martin et al. (2011)
221  * - no seasonal variation of air temperature
222  */
223 static void martin2011(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
224  auto grid = T_ma.grid();
225 
226  const array::Scalar
227  &h = geometry.ice_surface_elevation,
228  &lat = geometry.latitude;
229 
230  array::AccessScope list{&h, &lat, &T_ma, &T_ms};
231 
232  for (auto p = grid->points(); p; p.next()) {
233  const int i = p.i(), j = p.j();
234 
235  T_ma(i, j) = martin2011_mean_annual(h(i, j), lat(i, j));
236  T_ms(i, j) = T_ma(i, j);
237  }
238 }
239 
240 /*!
241  * - annual mean temperature as in Martin et al. (2011)
242  * - summer mean temperature computed as an anomaly to Huybrechts & DeWolde (1999)
243  */
244 static void martin_huybrechts_dewolde(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms) {
245  auto grid = T_ma.grid();
246 
247  const array::Scalar
248  &h = geometry.ice_surface_elevation,
249  &lat = geometry.latitude;
250 
251  array::AccessScope list{&h, &lat, &T_ma, &T_ms};
252 
253  for (auto p = grid->points(); p; p.next()) {
254  const int i = p.i(), j = p.j();
255 
256  // mean annual surface temperature as in Martin et al. 2011, equation (1)
257  T_ma(i, j) = 273.15 + 30 - 0.0075 * h(i, j) - 0.68775 * lat(i, j) * (-1.0);
258 
259  double
260  TMA = huybrechts_dewolde_mean_annual(h(i, j), lat(i, j)),
261  TMS = huybrechts_dewolde_mean_summer(h(i, j), lat(i, j));
262 
263  T_ms(i, j) = T_ma(i, j) + (TMS - TMA);
264  }
265 }
266 
267 
268 /*!
269  * Updates mean annual and mean summer (January) near-surface air temperatures. Note that
270  * the precipitation rate is time-independent and does not need to be updated.
271  */
272 void PIK::update_impl(const Geometry &geometry, double t, double dt) {
273  (void) t;
274  (void) dt;
275 
276  if (geometry.latitude.metadata().has_attribute("missing_at_bootstrap")) {
278  "latitude variable was missing at bootstrap;\n"
279  "PIK atmosphere model depends on latitude and would return nonsense!");
280  }
281 
282  switch (m_parameterization) {
283  case HUYBRECHTS_DEWOLDE:
285  break;
286  case ERA_INTERIM:
288  break;
289  case ERA_INTERIM_SIN:
291  break;
292  case ERA_INTERIM_LON:
294  break;
297  break;
298  default:
299  case MARTIN:
301  break;
302  }
303 }
304 
305 } // end of namespace atmosphere
306 } // end of namespace pism
const Config::ConstPtr m_config
configuration database used by this component
Definition: Component.hh:158
const Logger::ConstPtr m_log
logger (for easy access)
Definition: Component.hh:162
array::Scalar2 ice_surface_elevation
Definition: Geometry.hh:57
array::Scalar longitude
Definition: Geometry.hh:42
array::Scalar latitude
Definition: Geometry.hh:41
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
bool has_attribute(const std::string &name) const
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
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
MaxTimestep max_timestep_impl(double t) const
Definition: PIK.cc:107
@ MARTIN_HUYBRECHTS_DEWOLDE
Definition: PIK.hh:38
void update_impl(const Geometry &geometry, double t, double dt)
Definition: PIK.cc:272
PIK(std::shared_ptr< const Grid > g)
Definition: PIK.cc:35
void init_impl(const Geometry &geometry)
Reads in the precipitation data from the input file.
Definition: PIK.cc:57
Parameterization m_parameterization
Definition: PIK.hh:41
array::Scalar m_air_temp_mean_summer
Definition: YearlyCycle.hh:63
void init_internal(const std::string &input_filename, bool regrid, unsigned int start)
Read precipitation data from a given file.
Definition: YearlyCycle.cc:73
virtual void init_impl(const Geometry &geometry)
Reads in the precipitation data from the input file.
Definition: YearlyCycle.cc:65
array::Scalar m_air_temp_mean_annual
Definition: YearlyCycle.hh:63
#define PISM_ERROR_LOCATION
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:165
static void martin2011(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:223
static void era_interim_sin(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:171
static void martin_huybrechts_dewolde(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:244
static void era_interim_lon(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:191
static void era_interim(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:151
static void huybrechts_dewolde(const Geometry &geometry, array::Scalar &T_ma, array::Scalar &T_ms)
Definition: PIK.cc:131
static double huybrechts_dewolde_mean_summer(double surface_elevation, double latitude)
Definition: PIK.cc:123
static double huybrechts_dewolde_mean_annual(double surface_elevation, double latitude)
Definition: PIK.cc:115
static double martin2011_mean_annual(double elevation, double latitude)
Definition: PIK.cc:215
static const double g
Definition: exactTestP.cc:36