PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
Distributed.cc
Go to the documentation of this file.
1 // Copyright (C) 2012-2019, 2021, 2022, 2023 PISM Authors
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 <algorithm> // std::min, std::max
20 
21 #include "pism/geometry/Geometry.hh"
22 #include "pism/hydrology/Distributed.hh"
23 #include "pism/util/array/CellType.hh"
24 #include "pism/util/error_handling.hh"
25 #include "pism/util/io/File.hh"
26 #include "pism/util/pism_utilities.hh"
27 
28 namespace pism {
29 namespace hydrology {
30 
31 Distributed::Distributed(std::shared_ptr<const Grid> g)
32  : Routing(g), m_P(m_grid, "bwp"), m_Pnew(m_grid, "Pnew_internal") {
33 
34  // additional variables beyond hydrology::Routing
35  m_P.metadata(0)
36  .long_name("pressure of transportable water in subglacial layer")
37  .units("Pa");
38  m_P.metadata()["valid_min"] = { 0.0 };
39 
40  m_Pnew.metadata(0)
41  .long_name("new transportable subglacial water pressure during update")
42  .units("Pa");
43  m_Pnew.metadata()["valid_min"] = { 0.0 };
44 }
45 
47  m_log->message(2,
48  "* Initializing the distributed, linked-cavities subglacial hydrology model...\n");
49 }
50 
51 void Distributed::restart_impl(const File &input_file, int record) {
52  Routing::restart_impl(input_file, record);
53 
54  m_P.read(input_file, record);
55 
56  regrid("Hydrology", m_P);
57 }
58 
59 void Distributed::bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness) {
60  Routing::bootstrap_impl(input_file, ice_thickness);
61 
62  double bwp_default = m_config->get_number("bootstrapping.defaults.bwp");
63  m_P.regrid(input_file, io::Default(bwp_default));
64 
65  regrid("Hydrology", m_P);
66 
67  bool init_P_from_steady = m_config->get_flag("hydrology.distributed.init_p_from_steady");
68 
69  if (init_P_from_steady) { // if so, just overwrite -i or -bootstrap value of P=bwp
70  m_log->message(2, " initializing P from P(W) formula which applies in steady state\n");
71 
72  compute_overburden_pressure(ice_thickness, m_Pover);
73 
74  array::Scalar sliding_speed(m_grid, "velbase_mag");
75  sliding_speed.metadata(0).long_name("basal sliding speed").units("m s-1");
76 
77  std::string filename = m_config->get_string("hydrology.distributed.sliding_speed_file");
78 
79  if (filename.empty()) {
81  "hydrology.distributed.sliding_speed_file is not set");
82  }
83 
84  sliding_speed.regrid(filename, io::Default::Nil());
85 
86  P_from_W_steady(m_W, m_Pover, sliding_speed,
87  m_P);
88  }
89 }
90 
92  const array::Scalar &W,
93  const array::Scalar &P) {
94  Routing::init_impl(W_till, W, P);
95 
96  m_P.copy_from(P);
97 }
98 
99 void Distributed::define_model_state_impl(const File &output) const {
101  m_P.define(output, io::PISM_DOUBLE);
102 }
103 
104 void Distributed::write_model_state_impl(const File &output) const {
106  m_P.write(output);
107 }
108 
109 std::map<std::string, TSDiagnostic::Ptr> Distributed::ts_diagnostics_impl() const {
110  std::map<std::string, TSDiagnostic::Ptr> result = {
111  // FIXME: add mass-conservation time-series diagnostics
112  };
113  return result;
114 }
115 
116 //! Copies the P state variable which is the modeled water pressure.
118  return m_P;
119 }
120 
121 //! Check bounds on P and fail with message if not satisfied. Optionally, enforces the
122 //! upper bound instead of checking it.
123 /*!
124  The bounds are \f$0 \le P \le P_o\f$ where \f$P_o\f$ is the overburden pressure.
125 */
127  const array::Scalar &P_o,
128  bool enforce_upper) {
129 
130  array::AccessScope list{&P, &P_o};
131 
132  ParallelSection loop(m_grid->com);
133  try {
134  for (auto p = m_grid->points(); p; p.next()) {
135  const int i = p.i(), j = p.j();
136 
137  if (P(i,j) < 0.0) {
139  "negative subglacial water pressure\n"
140  "P(%d, %d) = %.6f Pa",
141  i, j, P(i, j));
142  }
143 
144  if (enforce_upper) {
145  P(i,j) = std::min(P(i,j), P_o(i,j));
146  } else if (P(i,j) > P_o(i,j) + 0.001) {
148  "subglacial water pressure P = %.16f Pa exceeds\n"
149  "overburden pressure Po = %.16f Pa at (i,j)=(%d,%d)",
150  P(i, j), P_o(i, j), i, j);
151  }
152  }
153  } catch (...) {
154  loop.failed();
155  }
156  loop.check();
157 
158 }
159 
160 
161 //! Compute functional relationship P(W) which applies only in steady state.
162 /*!
163  In steady state in this model, water pressure is determined by a balance of
164  cavitation (opening) caused by sliding and creep closure.
165 
166  This will be used in initialization when P is otherwise unknown, and
167  in verification and/or reporting. It is not used during time-dependent
168  model runs. To be more complete, \f$P = P(W,P_o,|v_b|)\f$.
169 */
171  const array::Scalar &P_overburden,
172  const array::Scalar &sliding_speed,
173  array::Scalar &result) {
174 
175  const double
176  ice_softness = m_config->get_number("flow_law.isothermal_Glen.ice_softness"),
177  creep_closure_coefficient = m_config->get_number("hydrology.creep_closure_coefficient"),
178  cavitation_opening_coefficient = m_config->get_number("hydrology.cavitation_opening_coefficient"),
179  Glen_exponent = m_config->get_number("stress_balance.sia.Glen_exponent"),
180  Wr = m_config->get_number("hydrology.roughness_scale");
181 
182  const double CC = cavitation_opening_coefficient / (creep_closure_coefficient * ice_softness);
183 
184  array::AccessScope list{&W, &P_overburden, &sliding_speed, &result};
185 
186  for (auto p = m_grid->points(); p; p.next()) {
187  const int i = p.i(), j = p.j();
188 
189  double sb = pow(CC * sliding_speed(i, j), 1.0 / Glen_exponent);
190  if (W(i, j) == 0.0) {
191  // see P(W) formula in steady state; note P(W) is continuous (in steady
192  // state); these facts imply:
193  if (sb > 0.0) {
194  // no water + cavitation = underpressure
195  result(i, j) = 0.0;
196  } else {
197  // no water + no cavitation = creep repressurizes = overburden
198  result(i, j) = P_overburden(i, j);
199  }
200  } else {
201  double Wratio = std::max(0.0, Wr - W(i, j)) / W(i, j);
202  // in cases where steady state is actually possible this will come out positive, but
203  // otherwise we should get underpressure P=0, and that is what it yields
204  result(i, j) = std::max(0.0, P_overburden(i, j) - sb * pow(Wratio, 1.0 / Glen_exponent));
205  }
206  } // end of the loop over grid points
207 }
208 
209 double Distributed::max_timestep_P_diff(double phi0, double dt_diff_w) const {
210  return 2.0 * phi0 * dt_diff_w;
211 }
212 
213 void Distributed::update_P(double dt,
214  const array::CellType &cell_type,
215  const array::Scalar &sliding_speed,
216  const array::Scalar &surface_input_rate,
217  const array::Scalar &basal_melt_rate,
218  const array::Scalar &P_overburden,
219  const array::Scalar &Wtill,
220  const array::Scalar &Wtill_new,
221  const array::Scalar &P,
222  const array::Scalar1 &W,
223  const array::Staggered1 &Ws,
224  const array::Staggered1 &K,
225  const array::Staggered1 &Q,
226  array::Scalar &P_new) const {
227 
228  const double
229  n = m_config->get_number("stress_balance.sia.Glen_exponent"),
230  A = m_config->get_number("flow_law.isothermal_Glen.ice_softness"),
231  c1 = m_config->get_number("hydrology.cavitation_opening_coefficient"),
232  c2 = m_config->get_number("hydrology.creep_closure_coefficient"),
233  Wr = m_config->get_number("hydrology.roughness_scale"),
234  phi0 = m_config->get_number("hydrology.regularizing_porosity");
235 
236  // update Pnew from time step
237  const double
238  CC = (m_rg * dt) / phi0,
239  wux = 1.0 / (m_dx * m_dx),
240  wuy = 1.0 / (m_dy * m_dy);
241 
242  array::AccessScope list{&P, &W, &Wtill, &Wtill_new, &sliding_speed, &Ws,
243  &K, &Q, &surface_input_rate, &basal_melt_rate,
244  &cell_type, &P_overburden, &P_new};
245 
246  for (auto p = m_grid->points(); p; p.next()) {
247  const int i = p.i(), j = p.j();
248 
249  auto w = W.star(i, j);
250  double P_o = P_overburden(i, j);
251 
252  if (cell_type.ice_free_land(i, j)) {
253  P_new(i, j) = 0.0;
254  } else if (cell_type.ocean(i, j)) {
255  P_new(i, j) = P_o;
256  } else if (w.c <= 0.0) {
257  P_new(i, j) = P_o;
258  } else {
259  auto q = Q.star(i, j);
260  auto k = K.star(i, j);
261  auto ws = Ws.star(i, j);
262 
263  double
264  Open = c1 * sliding_speed(i, j) * std::max(0.0, Wr - w.c),
265  Close = c2 * A * pow(P_o - P(i, j), n) * w.c;
266 
267  // compute the flux divergence the same way as in update_W()
268  const double divadflux = (q.e - q.w) / m_dx + (q.n - q.s) / m_dy;
269  const double
270  De = m_rg * k.e * ws.e,
271  Dw = m_rg * k.w * ws.w,
272  Dn = m_rg * k.n * ws.n,
273  Ds = m_rg * k.s * ws.s;
274 
275  double diffW = (wux * (De * (w.e - w.c) - Dw * (w.c - w.w)) +
276  wuy * (Dn * (w.n - w.c) - Ds * (w.c - w.s)));
277 
278  double divflux = -divadflux + diffW;
279 
280  // pressure update equation
281  double Wtill_change = Wtill_new(i, j) - Wtill(i, j);
282  double total_input = surface_input_rate(i, j) + basal_melt_rate(i, j);
283  double ZZ = Close - Open + total_input - Wtill_change / dt;
284 
285  P_new(i, j) = P(i, j) + CC * (divflux + ZZ);
286 
287  // projection to enforce 0 <= P <= P_o
288  P_new(i, j) = clip(P_new(i, j), 0.0, P_o);
289  }
290  } // end of the loop over grid points
291 }
292 
293 
294 //! Update the model state variables W,P by running the subglacial hydrology model.
295 /*!
296  Runs the hydrology model from time t to time t + dt. Here [t,dt]
297  is generally on the order of months to years. This hydrology model will take its
298  own shorter time steps, perhaps hours to weeks.
299 */
300 void Distributed::update_impl(double t, double dt, const Inputs& inputs) {
301 
303 
304  double
305  ht = t,
306  hdt = 0.0;
307 
308  const double
309  t_final = t + dt,
310  dt_max = m_config->get_number("hydrology.maximum_time_step", "seconds"),
311  phi0 = m_config->get_number("hydrology.regularizing_porosity"),
312  tillwat_max = m_config->get_number("hydrology.tillwat_max");
313 
314  m_Qstag_average.set(0.0);
315 
316  // make sure W,P have valid ghosts before starting hydrology steps
317  m_W.update_ghosts();
318  m_P.update_ghosts();
319 
320  unsigned int step_counter = 0;
321  for (; ht < t_final; ht += hdt) {
322  step_counter++;
323 
324 #if (Pism_DEBUG==1)
325  double huge_number = 1e6;
326  check_bounds(m_W, huge_number);
327  check_bounds(m_Wtill, tillwat_max);
328 #endif
329 
330  // note that ice dynamics can change overburden pressure, so we can only check P
331  // bounds if thk has not changed; if thk could have just changed, such as in the first
332  // time through the current loop, we enforce them
333  bool enforce_upper = (step_counter == 1);
334  check_P_bounds(m_P, m_Pover, enforce_upper);
335 
337  inputs.geometry->cell_type,
338  m_Wstag);
339 
340  double maxKW = 0.0;
344  m_Kstag, maxKW);
345 
349  m_Kstag,
350  inputs.no_model_mask,
351  m_Vstag);
352 
353  // to get Q, W needs valid ghosts
355 
357 
358  {
359  const double
360  dt_cfl = max_timestep_W_cfl(),
361  dt_diff_w = max_timestep_W_diff(maxKW),
362  dt_diff_p = max_timestep_P_diff(phi0, dt_diff_w);
363 
364  hdt = std::min(t_final - ht, dt_max);
365  hdt = std::min(hdt, dt_cfl);
366  hdt = std::min(hdt, dt_diff_w);
367  hdt = std::min(hdt, dt_diff_p);
368  }
369 
370  m_log->message(3, " hydrology step %05d, dt = %f s\n", step_counter, hdt);
371 
372  // update Wtillnew from Wtill and input_rate
373  update_Wtill(hdt,
374  m_Wtill,
377  m_Wtillnew);
378  // remove water in ice-free areas and account for changes
380  inputs.no_model_mask,
381  0.0, // do not limit maximum thickness
382  tillwat_max, // till water thickness under the ocean
383  m_Wtillnew,
388 
389  update_P(hdt,
390  inputs.geometry->cell_type,
391  *inputs.ice_sliding_speed,
394  m_Pover,
397  m_W, m_Wstag,
398  m_Kstag, m_Qstag,
399  m_Pnew);
400 
401  // update Wnew from W, Wtill, Wtillnew, Wstag, Q, input_rate
402  update_W(hdt,
405  m_W, m_Wstag,
407  m_Kstag, m_Qstag,
408  m_Wnew);
409  // remove water in ice-free areas and account for changes
411  inputs.no_model_mask,
412  0.0, // do not limit maximum thickness
413  0.0, // transportable water layer thickness under the ocean
414  m_Wnew,
419 
420  // transfer new into old
424  } // end of the time-stepping loop
425 
427  m_config->get_flag("hydrology.routing.include_floating_ice"),
428  m_Q);
429  m_Q.scale(1.0 / dt);
430 
431  m_log->message(2,
432  " took %d hydrology sub-steps with average dt = %.6f years (%.6f s)\n",
433  step_counter,
434  units::convert(m_sys, dt/step_counter, "seconds", "years"),
435  dt/step_counter);
436 }
437 
438 } // end of namespace hydrology
439 } // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition: Component.hh:160
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
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition: Component.hh:156
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
Definition: Component.cc:159
High-level PISM I/O class.
Definition: File.hh:56
array::CellType2 cell_type
Definition: Geometry.hh:55
void failed()
Indicates a failure of a parallel section.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition: Array.hh:65
void copy_from(const Array2D< T > &source)
Definition: Array2D.hh:73
stencils::Star< T > star(int i, int j) const
Definition: Array2D.hh:79
void read(const std::string &filename, unsigned int time)
Definition: Array.cc:809
void define(const File &file, io::Type default_type) const
Define variables corresponding to an Array in a file opened using file.
Definition: Array.cc:540
void write(const std::string &filename) const
Definition: Array.cc:800
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition: Array.cc:253
void set(double c)
Result: v[j] <- c for all j.
Definition: Array.cc:707
void regrid(const std::string &filename, io::Default default_value)
Definition: Array.cc:814
void add(double alpha, const Array &x)
Result: v <- v + alpha * x. Calls VecAXPY.
Definition: Array.cc:235
void update_ghosts()
Updates ghost points.
Definition: Array.cc:693
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
bool ocean(int i, int j) const
Definition: CellType.hh:34
bool ice_free_land(int i, int j) const
Definition: CellType.hh:62
"Cell type" mask. Adds convenience methods to array::Scalar.
Definition: CellType.hh:30
stencils::Star< double > star(int i, int j) const
Returns the values at interfaces of the cell i,j using the staggered grid.
Definition: Staggered.hh:73
void write_model_state_impl(const File &output) const
The default (empty implementation).
Definition: Distributed.cc:104
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
Definition: Distributed.cc:59
void define_model_state_impl(const File &output) const
The default (empty implementation).
Definition: Distributed.cc:99
void update_P(double dt, const array::CellType &cell_type, const array::Scalar &sliding_speed, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, const array::Scalar &P_overburden, const array::Scalar &Wtill, const array::Scalar &Wtill_new, const array::Scalar &P, const array::Scalar1 &W, const array::Staggered1 &Ws, const array::Staggered1 &K, const array::Staggered1 &Q, array::Scalar &P_new) const
Definition: Distributed.cc:213
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
Definition: Distributed.cc:91
std::map< std::string, TSDiagnostic::Ptr > ts_diagnostics_impl() const
Definition: Distributed.cc:109
void P_from_W_steady(const array::Scalar &W, const array::Scalar &P_overburden, const array::Scalar &sliding_speed, array::Scalar &result)
Compute functional relationship P(W) which applies only in steady state.
Definition: Distributed.cc:170
const array::Scalar & subglacial_water_pressure() const
Copies the P state variable which is the modeled water pressure.
Definition: Distributed.cc:117
void initialization_message() const
Definition: Distributed.cc:46
Distributed(std::shared_ptr< const Grid > g)
Definition: Distributed.cc:31
void update_impl(double t, double dt, const Inputs &inputs)
Update the model state variables W,P by running the subglacial hydrology model.
Definition: Distributed.cc:300
virtual double max_timestep_P_diff(double phi0, double dt_diff_w) const
Definition: Distributed.cc:209
void check_P_bounds(array::Scalar &P, const array::Scalar &P_o, bool enforce_upper)
Definition: Distributed.cc:126
virtual void restart_impl(const File &input_file, int record)
Definition: Distributed.cc:51
array::Scalar m_surface_input_rate
Definition: Hydrology.hh:179
array::Scalar m_grounding_line_change
Definition: Hydrology.hh:192
const array::Scalar & surface_input_rate() const
Definition: Hydrology.cc:518
void enforce_bounds(const array::CellType &cell_type, const array::Scalar *no_model_mask, double max_thickness, double ocean_water_thickness, array::Scalar &water_thickness, array::Scalar &grounded_margin_change, array::Scalar &grounding_line_change, array::Scalar &conservation_error_change, array::Scalar &no_model_mask_change)
Correct the new water thickness based on boundary requirements.
Definition: Hydrology.cc:669
array::Scalar m_basal_melt_rate
Definition: Hydrology.hh:182
array::Scalar1 m_W
effective thickness of transportable basal water
Definition: Hydrology.hh:173
void compute_overburden_pressure(const array::Scalar &ice_thickness, array::Scalar &result) const
Update the overburden pressure from ice thickness.
Definition: Hydrology.cc:480
array::Scalar m_Wtill
effective thickness of basal water stored in till
Definition: Hydrology.hh:170
array::Scalar m_Pover
overburden pressure
Definition: Hydrology.hh:176
array::Scalar m_grounded_margin_change
Definition: Hydrology.hh:191
array::Scalar m_no_model_mask_change
Definition: Hydrology.hh:194
array::Scalar m_conservation_error_change
Definition: Hydrology.hh:190
const Geometry * geometry
Definition: Hydrology.hh:37
const array::Scalar * ice_sliding_speed
Definition: Hydrology.hh:41
const array::Scalar1 * no_model_mask
Definition: Hydrology.hh:35
virtual void init_impl(const array::Scalar &W_till, const array::Scalar &W, const array::Scalar &P)
Definition: Routing.cc:345
array::Staggered1 m_Qstag_average
Definition: Routing.hh:115
array::Staggered m_Vstag
Definition: Routing.hh:118
array::Staggered1 m_Wstag
Definition: Routing.hh:121
double max_timestep_W_diff(double KW_max) const
Definition: Routing.cc:690
virtual void bootstrap_impl(const File &input_file, const array::Scalar &ice_thickness)
Definition: Routing.cc:335
double max_timestep_W_cfl() const
Definition: Routing.cc:699
void compute_conductivity(const array::Staggered &W, const array::Scalar &P, const array::Scalar &bed, array::Staggered &result, double &maxKW) const
Compute the nonlinear conductivity at the center of cell edges.
Definition: Routing.cc:436
array::Staggered1 m_Kstag
Definition: Routing.hh:124
void advective_fluxes(const array::Staggered &V, const array::Scalar &W, array::Staggered &result) const
Compute Q = V W at edge-centers (staggered grid) by first-order upwinding.
Definition: Routing.cc:670
void update_W(double dt, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, const array::Scalar1 &W, const array::Staggered1 &Wstag, const array::Scalar &Wtill, const array::Scalar &Wtill_new, const array::Staggered1 &K, const array::Staggered1 &Q, array::Scalar &W_new)
The computation of Wnew, called by update().
Definition: Routing.cc:796
void water_thickness_staggered(const array::Scalar &W, const array::CellType1 &mask, array::Staggered &result)
Average the regular grid water thickness to values at the center of cell edges.
Definition: Routing.cc:377
void compute_velocity(const array::Staggered &W, const array::Scalar &P, const array::Scalar &bed, const array::Staggered &K, const array::Scalar1 *no_model_mask, array::Staggered &result) const
Get the advection velocity V at the center of cell edges.
Definition: Routing.cc:611
array::Staggered1 m_Qstag
Definition: Routing.hh:113
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
Definition: Routing.cc:353
void update_Wtill(double dt, const array::Scalar &Wtill, const array::Scalar &surface_input_rate, const array::Scalar &basal_melt_rate, array::Scalar &Wtill_new)
The computation of Wtillnew, called by update().
Definition: Routing.cc:730
array::Scalar m_Wtillnew
Definition: Routing.hh:127
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
Definition: Routing.cc:358
array::Scalar m_Wnew
Definition: Routing.hh:127
virtual void restart_impl(const File &input_file, int record)
Definition: Routing.cc:327
array::Scalar1 m_bottom_surface
Definition: Routing.hh:135
A subglacial hydrology model which assumes water pressure equals overburden pressure.
Definition: Routing.hh:81
static Default Nil()
Definition: IO_Flags.hh:97
#define PISM_ERROR_LOCATION
#define n
Definition: exactTestM.c:37
void staggered_to_regular(const array::CellType1 &cell_type, const array::Staggered1 &input, bool include_floating_ice, array::Scalar &result)
Definition: Staggered.cc:87
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:165
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:193
static double K(double psi_x, double psi_y, double speed, double epsilon)
void check_bounds(const array::Scalar &W, double W_max)
Definition: Hydrology.cc:553
@ PISM_DOUBLE
Definition: IO_Flags.hh:52
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
Definition: Units.cc:70
static const double g
Definition: exactTestP.cc:36
T clip(T x, T a, T b)
static const double c2
Definition: exactTestP.cc:45
static const double k
Definition: exactTestP.cc:42
static const double Wr
Definition: exactTestP.cc:43
void ice_bottom_surface(const Geometry &geometry, array::Scalar &result)
Definition: Geometry.cc:217
static const double c1
Definition: exactTestP.cc:44