PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
IceRegionalModel.cc
Go to the documentation of this file.
1 /* Copyright (C) 2015, 2016, 2017, 2018, 2019, 2020, 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 
20 #include "pism/regional/IceRegionalModel.hh"
21 #include "pism/coupler/SurfaceModel.hh"
22 #include "pism/energy/BedThermalUnit.hh"
23 #include "pism/energy/CHSystem.hh"
24 #include "pism/energy/utilities.hh"
25 #include "pism/hydrology/Hydrology.hh"
26 #include "pism/regional/EnthalpyModel_Regional.hh"
27 #include "pism/regional/RegionalYieldStress.hh"
28 #include "pism/stressbalance/StressBalance.hh"
29 #include "pism/util/array/Forcing.hh"
30 #include "pism/util/io/File.hh"
31 
32 namespace pism {
33 
34 IceRegionalModel::IceRegionalModel(std::shared_ptr<Grid> g, std::shared_ptr<Context> c)
35  : IceModel(g, c),
36  m_no_model_mask(m_grid, "no_model_mask"),
37  m_usurf_stored(m_grid, "usurfstore"),
38  m_thk_stored(m_grid, "thkstore") {
40 
41  if (m_config->get_flag("energy.ch_warming.enabled")) {
42  m_ch_warming_flux.reset(
43  new array::Array3D(m_grid, "ch_warming_flux", array::WITHOUT_GHOSTS, m_grid->z()));
44  }
45 }
46 
47 
49 
51 
52  m_log->message(2, " creating IceRegionalModel vecs ...\n");
53 
54  // stencil width of 2 needed by SIAFD_Regional::compute_surface_gradient()
56  .long_name("mask: zeros (modeling domain) and ones (no-model buffer near grid edges)")
58  .set_output_type(io::PISM_INT); // no units and no standard name
59  m_no_model_mask.metadata()["flag_values"] = { 0, 1 };
60  m_no_model_mask.metadata()["flag_meanings"] = "normal special_treatment";
61 
63 
64  // stencil width of 2 needed for differentiation because GHOSTS=1
66  .long_name(
67  "saved surface elevation for use to keep surface gradient constant in no_model strip")
68  .units("m"); // no standard name
69 
70  // stencil width of 1 needed for differentiation
72  .long_name("saved ice thickness for use to keep driving stress constant in no_model strip")
73  .units("m"); // no standard name
74 
75  m_model_state.insert(&m_thk_stored);
78 }
79 
81 
82  // initialize the model state (including special fields)
84 
86 
87  // Initialize stored ice thickness and surface elevation. This goes here and not in
88  // bootstrap_2d because bed topography is not initialized at the time bootstrap_2d is
89  // called.
90  if (input.type == INIT_BOOTSTRAP) {
91  if (m_config->get_flag("regional.zero_gradient")) {
92  m_usurf_stored.set(0.0);
93  m_thk_stored.set(0.0);
94  } else {
97  }
98  }
99 
100  m_geometry_evolution->set_no_model_mask(m_no_model_mask);
101 
102  if (m_ch_system) {
103  const bool use_input_file = input.type == INIT_BOOTSTRAP or input.type == INIT_RESTART;
104 
105  std::unique_ptr<File> input_file;
106 
107  if (use_input_file) {
108  input_file.reset(new File(m_grid->com, input.filename, io::PISM_GUESS, io::PISM_READONLY));
109  }
110 
111  switch (input.type) {
112  case INIT_RESTART: {
113  m_ch_system->restart(*input_file, input.record);
114  break;
115  }
116  case INIT_BOOTSTRAP: {
117 
118  m_ch_system->bootstrap(*input_file, m_geometry.ice_thickness, m_surface->temperature(),
119  m_surface->mass_flux(), m_btu->flux_through_top_surface());
120  break;
121  }
122  case INIT_OTHER:
123  default: {
124  m_basal_melt_rate.set(m_config->get_number("bootstrapping.defaults.bmelt"));
125 
126  m_ch_system->initialize(m_basal_melt_rate, m_geometry.ice_thickness, m_surface->temperature(),
127  m_surface->mass_flux(), m_btu->flux_through_top_surface());
128  }
129  }
130  }
131 }
132 
134  if (m_geometry_evolution) {
135  return;
136  }
137 
138  m_log->message(2, "# Allocating the geometry evolution model (regional version)...\n");
139 
141 
142  m_submodels["geometry_evolution"] = m_geometry_evolution.get();
143 }
144 
146 
147  if (m_energy_model != NULL) {
148  return;
149  }
150 
151  m_log->message(2, "# Allocating an energy balance model...\n");
152 
153  if (m_config->get_flag("energy.enabled")) {
154  if (m_config->get_flag("energy.temperature_based")) {
156  "pismr -regional does not support the '-energy cold' mode.");
157  }
158 
159  m_energy_model = std::make_shared<energy::EnthalpyModel_Regional>(m_grid, m_stress_balance);
160  } else {
161  m_energy_model = std::make_shared<energy::DummyEnergyModel>(m_grid, m_stress_balance);
162  }
163 
164  m_submodels["energy balance model"] = m_energy_model.get();
165 
166  if (m_config->get_flag("energy.ch_warming.enabled") and
167  not m_ch_system) {
168 
169  m_log->message(2, "# Allocating the cryo-hydrologic warming model...\n");
170 
171  m_ch_system = std::make_shared<energy::CHSystem>(m_grid, m_stress_balance);
172  m_submodels["cryo-hydrologic warming"] = m_ch_system.get();
173  }
174 }
175 
177 
178  if (m_stress_balance) {
179  return;
180  }
181 
182  bool regional = true;
183  m_stress_balance = stressbalance::create(m_config->get_string("stress_balance.model"),
184  m_grid, regional);
185 
186  m_submodels["stress balance"] = m_stress_balance.get();
187 }
188 
189 
191 
193  return;
194  }
195 
197 
199  // IceModel allocated a basal yield stress model. This means that we are using a
200  // stress balance model that uses it and we need to add regional modifications.
202 
203  m_submodels["basal yield stress"] = m_basal_yield_stress_model.get();
204  }
205 }
206 
207 //! Bootstrap a "regional" model.
208 /*!
209  * Need to initialize all the variables managed by IceModel, as well as
210  * - no_model_mask
211  * - usurf_stored
212  * - thk_stored
213  */
214 void IceRegionalModel::bootstrap_2d(const File &input_file) {
215 
216  IceModel::bootstrap_2d(input_file);
217 
218  // no_model_mask
219  {
220  if (input_file.find_variable(m_no_model_mask.metadata().get_name())) {
221  m_no_model_mask.regrid(input_file, io::Default::Nil());
222  } else {
223  // set using the no_model_strip parameter
224  double strip_width = m_config->get_number("regional.no_model_strip", "meters");
225  set_no_model_strip(*m_grid, strip_width, m_no_model_mask);
226  }
227 
228  // m_no_model_mask was added to m_model_state, so
229  // IceModel::regrid() will take care of regridding it, if necessary.
230  }
231 
232  if (m_config->get_flag("stress_balance.ssa.dirichlet_bc")) {
233  array::AccessScope list
235 
236  for (auto p = m_grid->points(); p; p.next()) {
237  const int i = p.i(), j = p.j();
238 
239  if (m_no_model_mask(i, j) > 0.5) {
240  m_velocity_bc_mask(i, j) = 1;
241  m_ice_thickness_bc_mask(i, j) = 1;
242  }
243  }
244  }
245 }
246 
249 
250  result.no_model_mask = &m_no_model_mask;
253 
254  return result;
255 }
256 
259 
260  result.no_model_mask = &m_no_model_mask;
261 
262  return result;
263 }
264 
266 
267  if (m_ch_system) {
269 
271  const array::Array3D *strain_heating = inputs.volumetric_heating_rate;
273 
274  energy::cryo_hydrologic_warming_flux(m_config->get_number("constants.ice.thermal_conductivity"),
275  m_config->get_number("energy.ch_warming.average_channel_spacing"),
277  m_energy_model->enthalpy(),
278  m_ch_system->enthalpy(),
280 
281  // Convert to the loss of energy by the CH system:
282  m_ch_warming_flux->scale(-1.0);
283 
284  m_ch_system->update(t_TempAge, dt_TempAge, inputs);
285 
286  // Add CH warming flux to the strain heating term:
287  m_ch_warming_flux->scale(-1.0);
288  m_ch_warming_flux->add(1.0, *strain_heating);
289 
290  m_energy_model->update(t_TempAge, dt_TempAge, inputs);
291 
292  m_stdout_flags = m_energy_model->stdout_flags() + m_stdout_flags;
293  } else {
295  }
296 }
297 
300 
301  result.no_model_mask = &m_no_model_mask;
302 
303  return result;
304 }
305 
307  return m_ch_system.get();
308 }
309 
310 /*! @brief Report temperature of the cryo-hydrologic system */
311 class CHTemperature : public Diag<IceRegionalModel>
312 {
313 public:
315  : Diag<IceRegionalModel>(m) {
316 
317  m_vars = { { m_sys, "ch_temp", m_grid->z() } };
318  m_vars[0].long_name("temperature of the cryo-hydrologic system").units("Kelvin");
319  }
320 
321 protected:
322  std::shared_ptr<array::Array> compute_impl() const {
323 
324  std::shared_ptr<array::Array3D> result(new array::Array3D(m_grid, "ch_temp", array::WITHOUT_GHOSTS, m_grid->z()));
325 
328  *result);
329  result->metadata(0) = m_vars[0];
330 
331  return result;
332  }
333 };
334 
335 /*! @brief Report liquid water fraction in the cryo-hydrologic system */
336 class CHLiquidWaterFraction : public Diag<IceRegionalModel>
337 {
338 public:
340  : Diag<IceRegionalModel>(m) {
341 
342  m_vars = { { m_sys, "ch_liqfrac", m_grid->z() } };
343 
344  m_vars[0].long_name("liquid water fraction in the cryo-hydrologic system").units("1");
345  }
346 
347 protected:
348  std::shared_ptr<array::Array> compute_impl() const {
349 
350  std::shared_ptr<array::Array3D> result(new array::Array3D(m_grid, "ch_liqfrac", array::WITHOUT_GHOSTS, m_grid->z()));
351 
354  *result);
355  result->metadata(0) = m_vars[0];
356  return result;
357  }
358 };
359 
360 
361 /*! @brief Report rate of cryo-hydrologic warming */
362 class CHHeatFlux : public Diag<IceRegionalModel>
363 {
364 public:
366  : Diag<IceRegionalModel>(m) {
367 
368  m_vars = { { m_sys, "ch_heat_flux", m_grid->z() } };
369  m_vars[0].long_name("rate of cryo-hydrologic warming").units("W m-3");
370  }
371 
372 protected:
373  std::shared_ptr<array::Array> compute_impl() const {
374 
375  std::shared_ptr<array::Array3D> result(new array::Array3D(m_grid, "ch_heat_flux", array::WITHOUT_GHOSTS, m_grid->z()));
376  result->metadata(0) = m_vars[0];
377 
378  energy::cryo_hydrologic_warming_flux(m_config->get_number("constants.ice.thermal_conductivity"),
379  m_config->get_number("energy.ch_warming.average_channel_spacing"),
383  *result);
384  return result;
385  }
386 };
387 
390 
391  if (m_ch_system) {
392  m_diagnostics["ch_temp"] = Diagnostic::Ptr(new CHTemperature(this));
393  m_diagnostics["ch_liqfrac"] = Diagnostic::Ptr(new CHLiquidWaterFraction(this));
394  m_diagnostics["ch_heat_flux"] = Diagnostic::Ptr(new CHHeatFlux(this));
395  }
396 }
397 
399  hydrology::Inputs inputs;
400 
401  array::Scalar &sliding_speed = *m_work2d[0];
402  compute_magnitude(m_stress_balance->advective_velocity(), sliding_speed);
403 
404  inputs.no_model_mask = &m_no_model_mask;
405  inputs.geometry = &m_geometry;
406  inputs.surface_input_rate = nullptr;
408  inputs.ice_sliding_speed = &sliding_speed;
409 
411  m_surface_input_for_hydrology->update(m_time->current(), m_dt);
412  m_surface_input_for_hydrology->average(m_time->current(), m_dt);
414  } else if (m_config->get_flag("hydrology.surface_input_from_runoff")) {
415  // convert [kg m-2] to [kg m-2 s-1]
416  array::Scalar &surface_input_rate = *m_work2d[1];
417  surface_input_rate.copy_from(m_surface->runoff());
418  surface_input_rate.scale(1.0 / m_dt);
419  inputs.surface_input_rate = &surface_input_rate;
420  }
421 
422  m_subglacial_hydrology->update(m_time->current(), m_dt, inputs);
423 }
424 
425 
426 } // end of namespace pism
std::shared_ptr< array::Array > compute_impl() const
CHHeatFlux(const IceRegionalModel *m)
Report rate of cryo-hydrologic warming.
std::shared_ptr< array::Array > compute_impl() const
CHLiquidWaterFraction(const IceRegionalModel *m)
Report liquid water fraction in the cryo-hydrologic system.
CHTemperature(const IceRegionalModel *m)
std::shared_ptr< array::Array > compute_impl() const
Report temperature of the cryo-hydrologic system.
const IceRegionalModel * model
Definition: Diagnostic.hh:172
A template derived from Diagnostic, adding a "Model".
Definition: Diagnostic.hh:166
const units::System::Ptr m_sys
the unit system
Definition: Diagnostic.hh:116
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
Definition: Diagnostic.hh:120
std::shared_ptr< Diagnostic > Ptr
Definition: Diagnostic.hh:65
std::shared_ptr< const Grid > m_grid
the grid
Definition: Diagnostic.hh:114
const Config::ConstPtr m_config
Configuration flags and parameters.
Definition: Diagnostic.hh:118
VariableLookupData find_variable(const std::string &short_name, const std::string &std_name) const
Find a variable using its standard name and/or short name.
Definition: File.cc:361
High-level PISM I/O class.
Definition: File.hh:56
array::Scalar2 ice_surface_elevation
Definition: Geometry.hh:57
array::Scalar2 ice_thickness
Definition: Geometry.hh:51
std::map< std::string, const Component * > m_submodels
the list of sub-models, for writing model states and obtaining diagnostics
Definition: IceModel.hh:259
virtual energy::Inputs energy_model_inputs()
Definition: IceModel.cc:356
const Geometry & geometry() const
Definition: IceModel.cc:893
virtual void model_state_setup()
Sets the starting values of model state variables.
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
Definition: IceModel.hh:397
virtual void energy_step()
Manage the solution of the energy equation, and related parallel communication.
Definition: energy.cc:60
std::shared_ptr< surface::SurfaceModel > m_surface
Definition: IceModel.hh:286
const Config::Ptr m_config
Configuration flags and parameters.
Definition: IceModel.hh:243
virtual stressbalance::Inputs stress_balance_inputs()
Definition: IceModel.cc:330
virtual void bootstrap_2d(const File &input_file)
const Time::Ptr m_time
Time manager.
Definition: IceModel.hh:251
Geometry m_geometry
Definition: IceModel.hh:295
std::shared_ptr< YieldStress > m_basal_yield_stress_model
Definition: IceModel.hh:262
array::Scalar m_basal_melt_rate
rate of production of basal meltwater (ice-equivalent); no ghosts
Definition: IceModel.hh:302
const std::shared_ptr< Context > m_ctx
Execution context.
Definition: IceModel.hh:245
const Logger::Ptr m_log
Logger.
Definition: IceModel.hh:249
std::shared_ptr< array::Forcing > m_surface_input_for_hydrology
Definition: IceModel.hh:264
const energy::EnergyModel * energy_balance_model() const
Definition: IceModel.cc:913
std::vector< std::shared_ptr< array::Scalar2 > > m_work2d
Definition: IceModel.hh:393
virtual void allocate_storage()
Allocate all Arrays defined in IceModel.
Definition: IceModel.cc:185
array::Scalar2 m_velocity_bc_mask
mask to determine Dirichlet boundary locations for the sliding velocity
Definition: IceModel.hh:309
virtual void allocate_basal_yield_stress()
Decide which basal yield stress model to use.
std::string m_stdout_flags
Definition: IceModel.hh:328
std::unique_ptr< GeometryEvolution > m_geometry_evolution
Definition: IceModel.hh:296
virtual void bedrock_thermal_model_step()
Definition: energy.cc:38
std::shared_ptr< energy::BedThermalUnit > m_btu
Definition: IceModel.hh:266
std::set< array::Array * > m_model_state
Definition: IceModel.hh:417
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
Definition: IceModel.hh:314
double t_TempAge
time of last update for enthalpy/temperature
Definition: IceModel.hh:320
std::map< std::string, Diagnostic::Ptr > m_diagnostics
Requested spatially-variable diagnostics.
Definition: IceModel.hh:419
virtual YieldStressInputs yield_stress_inputs()
Definition: IceModel.cc:378
virtual void init_diagnostics()
std::unique_ptr< hydrology::Hydrology > m_subglacial_hydrology
Definition: IceModel.hh:261
double dt_TempAge
enthalpy/temperature and age time-steps
Definition: IceModel.hh:322
double m_dt
mass continuity time step, s
Definition: IceModel.hh:318
std::shared_ptr< energy::EnergyModel > m_energy_model
Definition: IceModel.hh:267
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition: IceModel.hh:241
energy::Inputs energy_model_inputs()
void energy_step()
Manage the solution of the energy equation, and related parallel communication.
void allocate_stressbalance()
Decide which stress balance model to use.
void allocate_storage()
Allocate all Arrays defined in IceModel.
const energy::CHSystem * cryo_hydrologic_system() const
void allocate_basal_yield_stress()
Decide which basal yield stress model to use.
array::Scalar2 m_usurf_stored
std::shared_ptr< array::Array3D > m_ch_warming_flux
void model_state_setup()
Sets the starting values of model state variables.
stressbalance::Inputs stress_balance_inputs()
IceRegionalModel(std::shared_ptr< Grid > g, std::shared_ptr< Context > c)
array::Scalar2 m_no_model_mask
array::Scalar1 m_thk_stored
virtual void bootstrap_2d(const File &input_file)
Bootstrap a "regional" model.
std::shared_ptr< energy::CHSystem > m_ch_system
YieldStressInputs yield_stress_inputs()
A version of the PISM core class (IceModel) which knows about the no_model_mask and its semantics.
VariableMetadata & long_name(const std::string &input)
VariableMetadata & set_output_type(io::Type type)
VariableMetadata & units(const std::string &input)
std::string get_name() const
VariableMetadata & set_time_independent(bool flag)
const array::Scalar * no_model_mask
Definition: YieldStress.hh:39
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
A virtual class collecting methods common to ice and bedrock 3D fields.
Definition: Array3D.hh:33
void set_interpolation_type(InterpolationType type)
Definition: Array.cc:179
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
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
const array::Array3D & enthalpy() const
Definition: EnergyModel.cc:302
const array::Scalar * no_model_mask
Definition: EnergyModel.hh:58
const array::Array3D * volumetric_heating_rate
Definition: EnergyModel.hh:52
const Geometry * geometry
Definition: Hydrology.hh:37
const array::Scalar * ice_sliding_speed
Definition: Hydrology.hh:41
const array::Scalar * surface_input_rate
Definition: Hydrology.hh:39
const array::Scalar1 * no_model_mask
Definition: Hydrology.hh:35
const array::Scalar * basal_melt_rate
Definition: Hydrology.hh:40
static Default Nil()
Definition: IO_Flags.hh:97
const array::Scalar * no_model_ice_thickness
const array::Scalar2 * no_model_surface_elevation
const array::Scalar2 * no_model_mask
#define PISM_ERROR_LOCATION
@ WITHOUT_GHOSTS
Definition: Array.hh:62
void compute_magnitude(const array::Vector &input, array::Scalar &result)
Definition: Scalar.cc:66
void compute_liquid_water_fraction(const array::Array3D &enthalpy, const array::Scalar &ice_thickness, array::Array3D &result)
Compute the liquid fraction corresponding to enthalpy and ice_thickness.
Definition: utilities.cc:136
void cryo_hydrologic_warming_flux(double k, double R, const array::Scalar &ice_thickness, const array::Array3D &ice_enthalpy, const array::Array3D &ch_enthalpy, array::Array3D &result)
Definition: CHSystem.cc:251
void compute_temperature(const array::Array3D &enthalpy, const array::Scalar &ice_thickness, array::Array3D &result)
Definition: utilities.cc:76
@ PISM_GUESS
Definition: IO_Flags.hh:56
@ PISM_READONLY
open an existing file for reading only
Definition: IO_Flags.hh:72
@ PISM_INT
Definition: IO_Flags.hh:50
std::shared_ptr< StressBalance > create(const std::string &model, std::shared_ptr< const Grid > grid, bool regional)
Definition: factory.cc:38
void set_no_model_strip(const Grid &grid, double width, array::Scalar &result)
Set no_model_mask variable to have value 1 in strip of width 'strip' m around edge of computational d...
Definition: Geometry.cc:409
InputOptions process_input_options(MPI_Comm com, Config::ConstPtr config)
Definition: Component.cc:43
static const double g
Definition: exactTestP.cc:36
@ INIT_BOOTSTRAP
Definition: Component.hh:56
@ INIT_OTHER
Definition: Component.hh:56
@ INIT_RESTART
Definition: Component.hh:56
InitializationType type
initialization type
Definition: Component.hh:61
std::string filename
name of the input file (if applicable)
Definition: Component.hh:63
unsigned int record
index of the record to re-start from
Definition: Component.hh:65