PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
Elevation.cc
Go to the documentation of this file.
1 // Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2022, 2023 Andy Aschwanden 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/coupler/surface/Elevation.hh"
20 
21 #include "pism/util/Grid.hh"
22 #include "pism/util/ConfigInterface.hh"
23 #include "pism/util/error_handling.hh"
24 #include "pism/util/pism_options.hh"
25 #include "pism/util/MaxTimestep.hh"
26 #include "pism/geometry/Geometry.hh"
27 
28 namespace pism {
29 namespace surface {
30 
31 ///// Elevation-dependent temperature and surface mass balance.
32 Elevation::Elevation(std::shared_ptr<const Grid> grid, std::shared_ptr<atmosphere::AtmosphereModel> input)
33  : SurfaceModel(grid) {
34  (void) input;
35 
38 }
39 
40 void Elevation::init_impl(const Geometry &geometry) {
41  (void) geometry;
42 
43  bool limits_set = false;
44 
45  m_log->message(2,
46  "* Initializing the constant-in-time surface processes model Elevation. Setting...\n");
47 
48  units::Converter K(m_sys, "Celsius", "Kelvin");
49  // options
50  {
51  // ice surface temperature
52  {
53  options::RealList IST("-ice_surface_temp", "ice surface temperature parameterization",
54  {-5.0, 0.0, 1325.0, 1350.0});
55 
56  if (IST->size() != 4) {
57  throw RuntimeError(PISM_ERROR_LOCATION, "option -ice_surface_temp requires an argument"
58  " (comma-separated list of 4 numbers)");
59  }
60  m_T_min = K(IST[0]);
61  m_T_max = K(IST[1]);
62  m_z_T_min = IST[2];
63  m_z_T_max = IST[3];
64  }
65 
66  // climatic mass balance
67  units::Converter meter_per_second(m_sys, "m year-1", "m second-1");
68  {
69  options::RealList CMB("-climatic_mass_balance",
70  "climatic mass balance parameterization",
71  {-3.0, 4.0, 1100.0, 1450.0, 1700.0});
72  if (CMB->size() != 5) {
73  throw RuntimeError(PISM_ERROR_LOCATION, "-climatic_mass_balance requires an argument"
74  " (comma-separated list of 5 numbers)");
75  }
76  m_M_min = meter_per_second(CMB[0]);
77  m_M_max = meter_per_second(CMB[1]);
78  m_z_M_min = CMB[2];
79  m_z_ELA = CMB[3];
80  m_z_M_max = CMB[4];
81  }
82 
83  // limits of the climatic mass balance
84  {
85  options::RealList limits("-climatic_mass_balance_limits",
86  "lower and upper limits of the climatic mass balance", {});
87  limits_set = limits.is_set();
88  if (limits.is_set()) {
89  if (limits->size() != 2) {
90  throw RuntimeError(PISM_ERROR_LOCATION, "-climatic_mass_balance_limits requires an argument"
91  " (a comma-separated list of 2 numbers)");
92  }
93  m_M_limit_min = meter_per_second(limits[0]);
94  m_M_limit_max = meter_per_second(limits[1]);
95  } else {
98  }
99  }
100  }
101 
102  units::Converter meter_per_year(m_sys, "m second-1", "m year-1");
103  m_log->message(3,
104  " temperature at %.0f m a.s.l. = %.2f deg C\n"
105  " temperature at %.0f m a.s.l. = %.2f deg C\n"
106  " mass balance below %.0f m a.s.l. = %.2f m year-1\n"
107  " mass balance at %.0f m a.s.l. = %.2f m year-1\n"
108  " mass balance at %.0f m a.s.l. = %.2f m year-1\n"
109  " mass balance above %.0f m a.s.l. = %.2f m year-1\n"
110  " equilibrium line altitude z_ELA = %.2f m a.s.l.\n",
113  m_z_M_min, meter_per_year(m_M_limit_min),
115  m_z_M_max, meter_per_year(m_M_max),
116  m_z_M_max, meter_per_year(m_M_limit_max),
117  m_z_ELA);
118 
119  // parameterizing the ice surface temperature 'ice_surface_temp'
120  m_log->message(2, " - parameterizing the ice surface temperature 'ice_surface_temp' ... \n");
121  m_log->message(2,
122  " ice temperature at the ice surface (T = ice_surface_temp) is piecewise-linear function\n"
123  " of surface altitude (usurf):\n"
124  " / %2.2f K for usurf < %.f m\n"
125  " T = | %5.2f K + %5.3f * (usurf - %.f m) for %.f m < usurf < %.f m\n"
126  " \\ %5.2f K for %.f m < usurf\n",
129  m_T_max, m_z_T_max);
130 
131  // parameterizing the ice surface mass balance 'climatic_mass_balance'
132  m_log->message(2,
133 
134  " - parameterizing the ice surface mass balance 'climatic_mass_balance' ... \n");
135 
136  if (limits_set) {
137  m_log->message(2,
138  " - option '-climatic_mass_balance_limits' seen, limiting upper and lower bounds ... \n");
139  }
140 
141  m_log->message(2,
142  " surface mass balance (M = climatic_mass_balance) is piecewise-linear function\n"
143  " of surface altitue (usurf):\n"
144  " / %5.2f m year-1 for usurf < %3.f m\n"
145  " M = | %5.3f 1/a * (usurf-%.0f m) for %3.f m < usurf < %3.f m\n"
146  " \\ %5.3f 1/a * (usurf-%.0f m) for %3.f m < usurf < %3.f m\n"
147  " \\ %5.2f m year-1 for %3.f m < usurf\n",
148  meter_per_year(m_M_limit_min), m_z_M_min,
149  meter_per_year(-m_M_min)/(m_z_ELA - m_z_M_min), m_z_ELA, m_z_M_min, m_z_ELA,
150  meter_per_year(m_M_max)/(m_z_M_max - m_z_ELA), m_z_ELA, m_z_ELA, m_z_M_max,
151  meter_per_year(m_M_limit_max), m_z_M_max);
152 }
153 
155  (void) t;
156  return MaxTimestep("surface 'elevation'");
157 }
158 
159 void Elevation::update_impl(const Geometry &geometry, double t, double dt) {
160  (void) t;
161  (void) dt;
162 
165 
169 
170 }
171 
173  return *m_mass_flux;
174 }
175 
177  return *m_temperature;
178 }
179 
181  return *m_accumulation;
182 }
183 
185  return *m_melt;
186 }
187 
189  return *m_runoff;
190 }
191 
192 void Elevation::compute_mass_flux(const array::Scalar &surface, array::Scalar &result) const {
193  double dabdz = -m_M_min/(m_z_ELA - m_z_M_min);
194  double dacdz = m_M_max/(m_z_M_max - m_z_ELA);
195 
196  array::AccessScope list{&result, &surface};
197 
198  ParallelSection loop(m_grid->com);
199  try {
200  for (auto p = m_grid->points(); p; p.next()) {
201  const int i = p.i(), j = p.j();
202 
203  double z = surface(i, j);
204 
205  if (z < m_z_M_min) {
206  result(i, j) = m_M_limit_min;
207  }
208  else if ((z >= m_z_M_min) and (z < m_z_ELA)) {
209  result(i, j) = dabdz * (z - m_z_ELA);
210  }
211  else if ((z >= m_z_ELA) and (z <= m_z_M_max)) {
212  result(i, j) = dacdz * (z - m_z_ELA);
213  }
214  else if (z > m_z_M_max) {
215  result(i, j) = m_M_limit_max;
216  }
217  else {
219  "Elevation::compute_mass_flux: HOW DID I GET HERE?");
220  }
221  }
222  } catch (...) {
223  loop.failed();
224  }
225  loop.check();
226 
227  // convert from m second-1 ice equivalent to kg m-2 s-1:
228  result.scale(m_config->get_number("constants.ice.density"));
229 }
230 
231 void Elevation::compute_temperature(const array::Scalar &surface, array::Scalar &result) const {
232 
233  array::AccessScope list{&result, &surface};
234 
235  double dTdz = (m_T_max - m_T_min)/(m_z_T_max - m_z_T_min);
236  ParallelSection loop(m_grid->com);
237  try {
238  for (auto p = m_grid->points(); p; p.next()) {
239  const int i = p.i(), j = p.j();
240 
241  double z = surface(i, j);
242 
243  if (z <= m_z_T_min) {
244  result(i, j) = m_T_min;
245  }
246  else if ((z > m_z_T_min) and (z < m_z_T_max)) {
247  result(i, j) = m_T_min + dTdz * (z - m_z_T_min);
248  }
249  else if (z >= m_z_T_max) {
250  result(i, j) = m_T_max;
251  }
252  else {
254  "Elevation::compute_temperature: HOW DID I GET HERE?");
255  }
256  }
257  } catch (...) {
258  loop.failed();
259  }
260  loop.check();
261 }
262 
263 } // end of namespace surface
264 } // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition: Component.hh:160
std::shared_ptr< const Grid > grid() const
Definition: Component.cc:105
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
array::Scalar2 ice_surface_elevation
Definition: Geometry.hh:57
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
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 scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition: Array.cc:253
bool is_set() const
Definition: options.hh:35
void compute_temperature(const array::Scalar &surface, array::Scalar &result) const
Definition: Elevation.cc:231
const array::Scalar & temperature_impl() const
Definition: Elevation.cc:176
void compute_mass_flux(const array::Scalar &surface, array::Scalar &result) const
Definition: Elevation.cc:192
void init_impl(const Geometry &geometry)
Definition: Elevation.cc:40
std::shared_ptr< array::Scalar > m_mass_flux
Definition: Elevation.hh:53
void update_impl(const Geometry &geometry, double t, double dt)
Definition: Elevation.cc:159
Elevation(std::shared_ptr< const Grid > grid, std::shared_ptr< atmosphere::AtmosphereModel > input)
Definition: Elevation.cc:32
virtual const array::Scalar & accumulation_impl() const
Definition: Elevation.cc:180
std::shared_ptr< array::Scalar > m_temperature
Definition: Elevation.hh:54
virtual const array::Scalar & runoff_impl() const
Definition: Elevation.cc:188
virtual const array::Scalar & melt_impl() const
Definition: Elevation.cc:184
const array::Scalar & mass_flux_impl() const
Definition: Elevation.cc:172
MaxTimestep max_timestep_impl(double t) const
Definition: Elevation.cc:154
static std::shared_ptr< array::Scalar > allocate_mass_flux(std::shared_ptr< const Grid > grid)
Definition: SurfaceModel.cc:73
void dummy_accumulation(const array::Scalar &smb, array::Scalar &result)
std::shared_ptr< array::Scalar > m_melt
static std::shared_ptr< array::Scalar > allocate_temperature(std::shared_ptr< const Grid > grid)
Definition: SurfaceModel.cc:92
std::shared_ptr< array::Scalar > m_runoff
void dummy_melt(const array::Scalar &smb, array::Scalar &result)
std::shared_ptr< array::Scalar > m_accumulation
void dummy_runoff(const array::Scalar &smb, array::Scalar &result)
The interface of PISM's surface models.
Definition: SurfaceModel.hh:42
#define PISM_ERROR_LOCATION
static double K(double psi_x, double psi_y, double speed, double epsilon)