Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
initialization.cc
Go to the documentation of this file.
1// Copyright (C) 2009--2024 Ed Bueler 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//This file contains various initialization routines. See the IceModel::init()
20//documentation comment in iceModel.cc for the order in which they are called.
21
22#include "pism/icemodel/IceModel.hh"
23#include "pism/basalstrength/ConstantYieldStress.hh"
24#include "pism/basalstrength/MohrCoulombYieldStress.hh"
25#include "pism/basalstrength/OptTillphiYieldStress.hh"
26#include "pism/frontretreat/util/IcebergRemover.hh"
27#include "pism/frontretreat/util/IcebergRemoverFEM.hh"
28#include "pism/frontretreat/calving/CalvingAtThickness.hh"
29#include "pism/frontretreat/calving/EigenCalving.hh"
30#include "pism/frontretreat/calving/FloatKill.hh"
31#include "pism/frontretreat/calving/HayhurstCalving.hh"
32#include "pism/frontretreat/calving/vonMisesCalving.hh"
33#include "pism/energy/BedThermalUnit.hh"
34#include "pism/hydrology/NullTransport.hh"
35#include "pism/hydrology/Routing.hh"
36#include "pism/hydrology/SteadyState.hh"
37#include "pism/hydrology/Distributed.hh"
38#include "pism/stressbalance/StressBalance.hh"
39#include "pism/util/ConfigInterface.hh"
40#include "pism/util/Time.hh"
41#include "pism/util/error_handling.hh"
42#include "pism/util/io/File.hh"
43#include "pism/coupler/OceanModel.hh"
44#include "pism/coupler/SurfaceModel.hh"
45#include "pism/coupler/atmosphere/Factory.hh"
46#include "pism/coupler/ocean/Factory.hh"
47#include "pism/coupler/ocean/Initialization.hh"
48#include "pism/coupler/ocean/sea_level/Factory.hh"
49#include "pism/coupler/ocean/sea_level/Initialization.hh"
50#include "pism/coupler/surface/Factory.hh"
51#include "pism/coupler/surface/Initialization.hh"
52#include "pism/earth/LingleClark.hh"
53#include "pism/earth/BedDef.hh"
54#include "pism/earth/Given.hh"
55#include "pism/util/Vars.hh"
56#include "pism/util/projection.hh"
57#include "pism/util/pism_utilities.hh"
58#include "pism/age/AgeModel.hh"
59#include "pism/age/Isochrones.hh"
60#include "pism/energy/EnthalpyModel.hh"
61#include "pism/energy/TemperatureModel.hh"
62#include "pism/fracturedensity/FractureDensity.hh"
63#include "pism/frontretreat/FrontRetreat.hh"
64#include "pism/frontretreat/PrescribedRetreat.hh"
65#include "pism/coupler/frontalmelt/Factory.hh"
66#include "pism/coupler/util/options.hh" // ForcingOptions
67#include "pism/util/ScalarForcing.hh"
68#include "pism/stressbalance/ShallowStressBalance.hh"
69#include "pism/util/array/Forcing.hh"
70#include <memory>
71
72namespace pism {
73
74//! Initialize time from an input file or command-line options.
76
77 bool use_calendar = m_config->get_flag("output.runtime.time_use_calendar");
78
79 if (use_calendar) {
80 m_log->message(2,
81 "* Run time: [%s, %s] (%s years, using the '%s' calendar)\n",
82 m_time->date(m_time->start()).c_str(),
83 m_time->date(m_time->end()).c_str(),
84 m_time->run_length().c_str(),
85 m_time->calendar().c_str());
86 } else {
87 std::string time_units = m_config->get_string("output.runtime.time_unit_name");
88
89 double
90 start = m_time->convert_time_interval(m_time->start(), time_units),
91 end = m_time->convert_time_interval(m_time->end(), time_units),
92 length = end - start;
93
94 m_log->message(2,
95 "* Run time: [%f %s, %f %s] (%f %s)\n",
96 start, time_units.c_str(),
97 end, time_units.c_str(),
98 length, time_units.c_str());
99 }
100}
101
102//! Sets the starting values of model state variables.
103/*!
104 There are two cases:
105
106 1) Initializing from a PISM output file.
107
108 2) Setting the values using command-line options only (verification and
109 simplified geometry runs, for example) or from a bootstrapping file, using
110 heuristics to fill in missing and 3D fields.
111
112 Calls IceModel::regrid().
113
114 This function is called after all the memory allocation is done and all the
115 physical parameters are set.
116
117 Calling this method should be all one needs to set model state variables.
118 Please avoid modifying them in other parts of the initialization sequence.
119
120 Also, please avoid operations that would make it unsafe to call this more
121 than once (memory allocation is one example).
122 */
124
125 // Check if we are initializing from a PISM output file:
127
128 const bool use_input_file = input.type == INIT_BOOTSTRAP or input.type == INIT_RESTART;
129
130 std::unique_ptr<File> input_file;
131
132 if (use_input_file) {
133 input_file.reset(new File(m_grid->com, input.filename, io::PISM_GUESS, io::PISM_READONLY));
134 }
135
136 // Compute latitudes and longitudes *before* they might be needed.
138
139 if (use_input_file) {
140 std::string history = input_file->read_text_attribute("PISM_GLOBAL", "history");
141 m_output_global_attributes["history"] =
142 history + m_output_global_attributes.get_string("history");
143 }
144
145 // Initialize 2D fields owned by IceModel (ice geometry, etc)
146 {
147 switch (input.type) {
148 case INIT_RESTART:
149 restart_2d(*input_file, input.record);
150 break;
151 case INIT_BOOTSTRAP:
152 bootstrap_2d(*input_file);
153 break;
154 case INIT_OTHER:
155 default:
157 }
158
159 regrid();
160 }
161
162 m_sea_level->init(m_geometry);
163
164 // Initialize a bed deformation model.
165 if (m_beddef) {
166 m_beddef->init(input, m_geometry.ice_thickness, m_sea_level->elevation());
167 m_grid->variables().add(m_beddef->bed_elevation());
168 m_grid->variables().add(m_beddef->uplift());
169 }
170
171 // Now ice thickness, bed elevation, and sea level are available, so we can compute the ice
172 // surface elevation and the cell type mask. This also ensures consistency of ice geometry.
173 //
174 // The stress balance code is executed near the beginning of a step and ice geometry is
175 // updated near the end, so during the second time step the stress balance code is
176 // guaranteed not to see "icebergs". Here we make sure that the first time step is OK
177 // too.
179
180 // By now ice geometry is set (including regridding) and so we can initialize the ocean model,
181 // which may need ice thickness, bed topography, and the cell type mask.
182 {
183 m_ocean->init(m_geometry);
184 }
185
186 // Now surface elevation is initialized, so we can initialize surface models (some use
187 // elevation-based parameterizations of surface temperature and/or mass balance).
188 m_surface->init(m_geometry);
189
191
192 switch (input.type) {
193 case INIT_RESTART:
194 m_subglacial_hydrology->restart(*input_file, input.record);
195 break;
196 case INIT_BOOTSTRAP:
197 m_subglacial_hydrology->bootstrap(*input_file,
199 break;
200 case INIT_OTHER:
201 {
203 &W_till = *m_work2d[0],
204 &W = *m_work2d[1],
205 &P = *m_work2d[2];
206
207 W_till.set(m_config->get_number("bootstrapping.defaults.tillwat"));
208 W.set(m_config->get_number("bootstrapping.defaults.bwat"));
209 P.set(m_config->get_number("bootstrapping.defaults.bwp"));
210
211 m_subglacial_hydrology->init(W_till, W, P);
212 break;
213 }
214 }
215 }
216
217 // basal_yield_stress_model->init() needs till water thickness so this must happen
218 // after subglacial_hydrology->init()
220 auto inputs = yield_stress_inputs();
221
222 switch (input.type) {
223 case INIT_RESTART:
224 m_basal_yield_stress_model->restart(*input_file, input.record);
225 break;
226 case INIT_BOOTSTRAP:
227 m_basal_yield_stress_model->bootstrap(*input_file, inputs);
228 break;
229 default:
230 case INIT_OTHER:
231 m_basal_yield_stress_model->init(inputs);
232 }
233 m_basal_yield_stress.copy_from(m_basal_yield_stress_model->basal_material_yield_stress());
234 }
235
236 // Initialize the bedrock thermal layer model.
237 //
238 // If
239 // - PISM is bootstrapping and
240 // - we are using a non-zero-thickness thermal layer
241 //
242 // initialization of m_btu requires the temperature at the top of the bedrock. This is a problem
243 // because get_bed_top_temp() uses the enthalpy field that is not initialized until later and
244 // bootstrapping enthalpy uses the flux through the bottom surface of the ice (top surface of the
245 // bedrock) provided by m_btu.
246 //
247 // We get out of this by using the fact that the full state of m_btu is not needed and
248 // bootstrapping of the temperature field can be delayed.
249 //
250 // Note that to bootstrap m_btu we use the steady state solution of the heat equation in columns
251 // of the bedrock (a straight line at each column), so the flux through the top surface of the
252 // bedrock after bootstrapping is the same as the time-independent geothermal flux applied at the
253 // BOTTOM surface of the bedrock layer.
254 //
255 // The code then delays bootstrapping of the thickness field until the first time step.
256 if (m_btu != nullptr) {
257 m_btu->init(input);
258 }
259
260 if (m_age_model) {
261 m_age_model->init(input);
262 m_grid->variables().add(m_age_model->age());
263 }
264
265 if (m_isochrones) {
266 if (input.type == INIT_RESTART) {
267 m_isochrones->restart(*input_file, (int)input.record);
268 } else {
270 }
271 }
272
273 // Initialize the energy balance sub-model.
274 {
275 switch (input.type) {
276 case INIT_RESTART:
277 {
278 m_energy_model->restart(*input_file, input.record);
279 break;
280 }
281 case INIT_BOOTSTRAP:
282 {
283
284 m_energy_model->bootstrap(*input_file,
286 m_surface->temperature(),
287 m_surface->mass_flux(),
288 m_btu->flux_through_top_surface());
289 break;
290 }
291 case INIT_OTHER:
292 default:
293 {
294 m_basal_melt_rate.set(m_config->get_number("bootstrapping.defaults.bmelt"));
295
298 m_surface->temperature(),
299 m_surface->mass_flux(),
300 m_btu->flux_through_top_surface());
301
302 }
303 }
304 m_grid->variables().add(m_energy_model->enthalpy());
305 }
306
307 // this has to go after we add enthalpy to m_grid->variables()
308 if (m_stress_balance) {
309 m_stress_balance->init();
310 }
311
312 // we keep ice thickness fixed at all the locations where the sliding (SSA) velocity is
313 // prescribed
314 {
316
317 for (auto p = m_grid->points(); p; p.next()) {
318 const int i = p.i(), j = p.j();
319
320 if (m_velocity_bc_mask.as_int(i, j) != 0) {
321 m_ice_thickness_bc_mask(i, j) = 1.0;
322 }
323 }
324 }
325
326 // miscellaneous steps
327 {
329
330 auto startstr = pism::printf("PISM (%s) started on %d procs.",
331 pism::revision, (int)m_grid->size());
332 prepend_history(startstr + args_string());
333 }
334
335 // forget stored interpolation weights to free up some RAM
336 m_grid->forget_interpolations();
337}
338
339//! Initialize 2D model state fields managed by IceModel from a file (for re-starting).
340/*!
341 * This method should eventually go away as IceModel turns into a "coupler" and all physical
342 * processes are handled by sub-models.
343 */
344void IceModel::restart_2d(const File &input_file, unsigned int last_record) {
345 std::string filename = input_file.name();
346
347 m_log->message(2, "initializing 2D fields from NetCDF file '%s'...\n", filename.c_str());
348
349 for (auto *variable : m_model_state) {
350 variable->read(input_file, last_record);
351 }
352}
353
354void IceModel::bootstrap_2d(const File &input_file) {
355
356 m_log->message(2, "bootstrapping from file '%s'...\n", input_file.name().c_str());
357
358 auto usurf = input_file.find_variable("usurf", "surface_altitude");
359
360 bool mask_found = input_file.variable_exists("mask");
361
362 // now work through all the 2d variables, regridding if present and otherwise
363 // setting to default values appropriately
364
365 if (mask_found) {
366 m_log->message(2, " WARNING: 'mask' found; IGNORING IT!\n");
367 }
368
369 if (usurf.exists) {
370 m_log->message(2, " WARNING: surface elevation 'usurf' found; IGNORING IT!\n");
371 }
372
373 m_log->message(2, " reading 2D model state variables by regridding ...\n");
374
375 // longitude
376 if (m_geometry.longitude.metadata().has_attribute("initialized")) {
377 m_geometry.longitude.metadata()["initialized"] = "";
378 } else {
379 m_geometry.longitude.regrid(input_file, io::Default(0.0));
380 }
381
382 // latitude
383 if (m_geometry.latitude.metadata().has_attribute("initialized")) {
384 m_geometry.latitude.metadata()["initialized"] = "";
385 } else {
386 m_geometry.latitude.regrid(input_file, io::Default(0.0));
387 }
388
390 input_file, io::Default(m_config->get_number("bootstrapping.defaults.ice_thickness")));
391
392 if (m_config->get_flag("geometry.part_grid.enabled")) {
393 // Read the Href field from an input file. This field is
394 // grid-dependent, so interpolating it from one grid to a
395 // different one does not make sense in general.
396 // (IceModel::Href_cleanup() will take care of the side effects of
397 // such interpolation, though.)
398 //
399 // On the other hand, we need to read it in to be able to re-start
400 // from a PISM output file using the -bootstrap option.
402 }
403
404 if (m_config->get_flag("stress_balance.ssa.dirichlet_bc")) {
405 // Do not use Dirichlet B.C. anywhere if bc_mask is not present.
406 m_velocity_bc_mask.regrid(input_file, io::Default(0.0));
407 // In absence of u_bc and v_bc in the file the only B.C. that make sense are the
408 // zero Dirichlet B.C.
409 m_velocity_bc_values.regrid(input_file, io::Default(0.0));
410 } else {
413 }
414
416
417 // check if Lz is valid
418 auto max_thickness = array::max(m_geometry.ice_thickness);
419
420 if (max_thickness > m_grid->Lz()) {
421 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Max. ice thickness (%3.3f m)\n"
422 "exceeds the height of the computational domain (%3.3f m).",
423 max_thickness, m_grid->Lz());
424 }
425}
426
428 // This method should NOT have the "noreturn" attribute. (This attribute does not mix with virtual
429 // methods).
430 throw RuntimeError(PISM_ERROR_LOCATION, "cannot initialize IceModel without an input file");
431}
432
433//! Manage regridding based on user options.
435
436 auto filename = m_config->get_string("input.regrid.file");
437 auto regrid_vars = set_split(m_config->get_string("input.regrid.vars"), ',');
438
439 // Return if no regridding is requested:
440 if (filename.empty()) {
441 return;
442 }
443
444 m_log->message(2, "regridding from file %s ...\n", filename.c_str());
445
446 {
447 File regrid_file(m_grid->com, filename, io::PISM_GUESS, io::PISM_READONLY);
448 for (auto *v : m_model_state) {
449 if (regrid_vars.find(v->get_name()) != regrid_vars.end()) {
450 v->regrid(regrid_file, io::Default::Nil());
451 }
452 }
453
454 // Check the range of the ice thickness.
455 {
456 double
457 max_thickness = array::max(m_geometry.ice_thickness),
458 Lz = m_grid->Lz();
459
460 if (max_thickness >= Lz + 1e-6) {
461 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Maximum ice thickness (%f meters)\n"
462 "exceeds the height of the computational domain (%f meters).",
463 max_thickness, Lz);
464 }
465 }
466 }
467}
468
469//! \brief Decide which stress balance model to use.
471
472 if (m_stress_balance) {
473 return;
474 }
475
476 m_log->message(2, "# Allocating a stress balance model...\n");
477
478 // false means "not regional"
479 m_stress_balance = stressbalance::create(m_config->get_string("stress_balance.model"),
480 m_grid, false);
481
482 m_submodels["stress balance"] = m_stress_balance.get();
483}
484
487 return;
488 }
489
490 m_log->message(2, "# Allocating the geometry evolution model...\n");
491
493
494 m_submodels["geometry_evolution"] = m_geometry_evolution.get();
495}
496
497
499
500 if (m_iceberg_remover != NULL) {
501 return;
502 }
503
504 m_log->message(2,
505 "# Allocating an iceberg remover (part of a calving model)...\n");
506
507 if (m_config->get_flag("geometry.remove_icebergs")) {
508
509 auto model = m_config->get_string("stress_balance.model");
510 auto ssa_method = m_config->get_string("stress_balance.ssa.method");
511
512 if ((member(model, {"ssa", "ssa+sia"}) and ssa_method == "fem") or
513 model == "blatter") {
514 m_iceberg_remover = std::make_shared<calving::IcebergRemoverFEM>(m_grid);
515 } else {
516 m_iceberg_remover = std::make_shared<calving::IcebergRemover>(m_grid);
517 }
518
519 m_submodels["iceberg remover"] = m_iceberg_remover.get();
520 }
521}
522
524
525 if (m_age_model) {
526 return;
527 }
528
529 if (m_config->get_flag("age.enabled")) {
530 m_log->message(2, "# Allocating an ice age model...\n");
531
532 if (m_stress_balance == nullptr) {
534 "Cannot allocate an age model: m_stress_balance == nullptr.");
535 }
536
537 m_age_model = std::make_shared<AgeModel>(m_grid, m_stress_balance);
538 m_submodels["age model"] = m_age_model.get();
539 }
540}
541
543
544 if (m_isochrones) {
545 return;
546 }
547
548 auto deposition_times = m_config->get_string("isochrones.deposition_times");
549 if (not deposition_times.empty()) {
550 m_log->message(2, "# Allocating isochrone tracking...\n");
551
552 if (m_stress_balance == nullptr) {
555 "Cannot allocate the isochrone tracking model: m_stress_balance == nullptr.");
556 }
557
558 m_isochrones = std::make_shared<Isochrones>(m_grid, m_stress_balance);
559
560 m_submodels["isochrones"] = m_isochrones.get();
561 }
562}
563
565
566 if (m_energy_model != NULL) {
567 return;
568 }
569
570 m_log->message(2, "# Allocating an energy balance model...\n");
571
572 auto energy_model = m_config->get_string("energy.model");
573 if (energy_model == "enthalpy") {
574 m_energy_model = std::make_shared<energy::EnthalpyModel>(m_grid, m_stress_balance);
575 } else if (energy_model == "cold") {
576 m_energy_model = std::make_shared<energy::TemperatureModel>(m_grid, m_stress_balance);
577 } else {
578 m_energy_model = std::make_shared<energy::DummyEnergyModel>(m_grid, m_stress_balance);
579 }
580
581 m_submodels["energy balance model"] = m_energy_model.get();
582}
583
584
585//! \brief Decide which bedrock thermal unit to use.
587
588 if (m_btu != nullptr) {
589 return;
590 }
591
592 m_log->message(2, "# Allocating a bedrock thermal layer model...\n");
593
595
596 m_submodels["bedrock thermal model"] = m_btu.get();
597}
598
599//! \brief Decide which subglacial hydrology model to use.
601
602 using namespace pism::hydrology;
603
604 std::string hydrology_model = m_config->get_string("hydrology.model");
605
606 if (m_subglacial_hydrology) { // indicates it has already been allocated
607 return;
608 }
609
610 m_log->message(2, "# Allocating a subglacial hydrology model...\n");
611
612 if (hydrology_model == "null") {
614 } else if (hydrology_model == "routing") {
616 } else if (hydrology_model == "steady") {
618 } else if (hydrology_model == "distributed") {
620 } else {
622 "unknown 'hydrology.model': %s", hydrology_model.c_str());
623 }
624
625 m_submodels["subglacial hydrology"] = m_subglacial_hydrology.get();
626}
627
628//! \brief Decide which basal yield stress model to use.
630
632 return;
633 }
634
635 m_log->message(2,
636 "# Allocating a basal yield stress model...\n");
637
638 std::string model = m_config->get_string("stress_balance.model");
639
640 // only these two use the yield stress (so far):
641 if (member(model, {"ssa", "ssa+sia", "blatter"})) {
642 std::string yield_stress_model = m_config->get_string("basal_yield_stress.model");
643
644 if (yield_stress_model == "constant") {
645 m_basal_yield_stress_model = std::make_shared<ConstantYieldStress>(m_grid);
646 } else if (yield_stress_model == "mohr_coulomb") {
647 m_basal_yield_stress_model = std::make_shared<MohrCoulombYieldStress>(m_grid);
648 } else if (yield_stress_model == "tillphi_opt") {
649 m_basal_yield_stress_model = std::make_shared<OptTillphiYieldStress>(m_grid);
650 } else {
651 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "yield stress model '%s' is not supported.",
652 yield_stress_model.c_str());
653 }
654
655 m_submodels["basal yield stress"] = m_basal_yield_stress_model.get();
656 }
657}
658
659//! Allocate PISM's sub-models implementing some physical processes.
660/*!
661 This method is called after memory allocation but before filling any of
662 Arrays because all the physical parameters should be initialized before
663 setting up the coupling or filling model-state variables.
664 */
666
668
670
672
673 // this has to happen *after* allocate_stressbalance()
674 {
679 }
680
681 // this has to happen *after* allocate_subglacial_hydrology()
683
685
687
689
690 if (m_config->get_flag("fracture_density.enabled")) {
691 m_fracture = std::make_shared<FractureDensity>(m_grid, m_stress_balance->shallow()->flow_law());
692 m_submodels["fracture_density"] = m_fracture.get();
693 }
694}
695
696
698 // Initialize boundary models:
699
700 if (not m_surface) {
701
702 m_log->message(2, "# Allocating a surface process model or coupler...\n");
703
705
706 m_surface = std::make_shared<surface::InitializationHelper>(m_grid, ps.create());
707
708 m_submodels["surface process model"] = m_surface.get();
709 }
710
711 if (not m_sea_level) {
712 m_log->message(2, "# Allocating sea level forcing...\n");
713
714 using namespace ocean::sea_level;
715
716 m_sea_level = std::make_shared<InitializationHelper>(m_grid, Factory(m_grid).create());
717
718 m_submodels["sea level forcing"] = m_sea_level.get();
719 }
720
721 if (not m_ocean) {
722 m_log->message(2, "# Allocating an ocean model or coupler...\n");
723
724 using namespace ocean;
725
726 m_ocean = std::make_shared<InitializationHelper>(m_grid, Factory(m_grid).create());
727
728 m_submodels["ocean model"] = m_ocean.get();
729 }
730}
731
732//! Miscellaneous initialization tasks plus tasks that need the fields that can come from regridding.
734
735 m_log->message(3, "Finishing initialization...\n");
737
738 if (not (opts.type == INIT_OTHER)) {
739 // initializing from a file
741
742 std::string source = file.read_text_attribute("PISM_GLOBAL", "source");
743
744 if (opts.type == INIT_RESTART) {
745 // If it's missing, print a warning
746 if (source.empty()) {
747 m_log->message(1,
748 "PISM WARNING: file '%s' does not have the 'source' global attribute.\n"
749 " If '%s' is a PISM output file, please run the following to get rid of this warning:\n"
750 " ncatted -a source,global,c,c,PISM %s\n",
751 opts.filename.c_str(), opts.filename.c_str(), opts.filename.c_str());
752 } else if (source.find("PISM") == std::string::npos) {
753 // If the 'source' attribute does not contain the string "PISM", then print
754 // a message and stop:
755 m_log->message(1,
756 "PISM WARNING: '%s' does not seem to be a PISM output file.\n"
757 " If it is, please make sure that the 'source' global attribute contains the string \"PISM\".\n",
758 opts.filename.c_str());
759 }
760 }
761 }
762
763 {
764 // A single record of a time-dependent variable cannot exceed 2^32-4
765 // bytes in size. See the NetCDF User's Guide
766 // <http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#g_t64-bit-Offset-Limitations>.
767 // Here we use "long int" to avoid integer overflow.
768 const long int two_to_thirty_two = 4294967296L;
769 const long int
770 Mx = m_grid->Mx(),
771 My = m_grid->My(),
772 Mz = m_grid->Mz();
773 std::string output_format = m_config->get_string("output.format");
774 if (Mx * My * Mz * sizeof(double) > two_to_thirty_two - 4 and
775 (output_format == io::PISM_NETCDF3)) {
777 "The computational grid is too big to fit in a NetCDF-3 file.\n"
778 "Each 3D variable requires %lu Mb.\n"
779 "Please use '-o_format pnetcdf or -o_format netcdf4_parallel to proceed.",
780 Mx * My * Mz * sizeof(double) / (1024 * 1024));
781 }
782 }
783
784 m_output_vars = output_variables(m_config->get_string("output.size"));
785
786#if (Pism_USE_PROJ==1)
787 {
788 std::string proj_string = m_grid->get_mapping_info().proj_string;
789 if (not proj_string.empty()) {
790 m_output_vars.insert("lon_bnds");
791 m_output_vars.insert("lat_bnds");
792 }
793 }
794#endif
795
796 init_calving();
803 init_extras();
804
805 // a report on whether PISM-PIK modifications of IceModel are in use
806 {
807 std::vector<std::string> pik_methods;
808 if (m_config->get_flag("geometry.part_grid.enabled")) {
809 pik_methods.push_back("part_grid");
810 }
811 if (m_config->get_flag("geometry.remove_icebergs")) {
812 pik_methods.push_back("kill_icebergs");
813 }
814
815 if (not pik_methods.empty()) {
816 m_log->message(2,
817 "* PISM-PIK mass/geometry methods are in use: %s\n",
818 join(pik_methods, ", ").c_str());
819 }
820 }
821
822 // initialize diagnostics
823 {
824 // reset: this gives diagnostics a chance to capture the current state of the model at the
825 // beginning of the run
826 for (const auto& d : m_diagnostics) {
827 d.second->reset();
828 }
829
830 // read in the state (accumulators) if we are re-starting a run
831 if (opts.type == INIT_RESTART) {
833 for (const auto& d : m_diagnostics) {
834 d.second->init(file, opts.record);
835 }
836 }
837 }
838
840 ForcingOptions surface_input(*m_ctx, "hydrology.surface_input");
841 m_surface_input_for_hydrology->init(surface_input.filename,
842 surface_input.periodic);
843 }
844
845 if (m_fracture) {
846 if (opts.type == INIT_OTHER) {
847 m_fracture->initialize();
848 } else {
849 // initializing from a file
851
852 if (opts.type == INIT_RESTART) {
853 m_fracture->restart(file, opts.record);
854 } else if (opts.type == INIT_BOOTSTRAP) {
855 m_fracture->bootstrap(file);
856 }
857 }
858 }
859}
860
862
863 auto frontal_melt = m_config->get_string("frontal_melt.models");
864
865 if (not frontal_melt.empty()) {
866 if (not m_config->get_flag("geometry.part_grid.enabled")) {
868 "ERROR: frontal melt models require geometry.part_grid.enabled");
869 }
870
872
874
875 m_submodels["frontal melt"] = m_frontal_melt.get();
876
877 if (not m_front_retreat) {
878 m_front_retreat = std::make_shared<FrontRetreat>(m_grid);
879 }
880 }
881}
882
884 auto front_retreat_file = m_config->get_string("geometry.front_retreat.prescribed.file");
885
886 if (not front_retreat_file.empty()) {
887 m_prescribed_retreat = std::make_shared<PrescribedRetreat>(m_grid);
888
889 m_prescribed_retreat->init();
890
891 m_submodels["prescribed front retreat"] = m_prescribed_retreat.get();
892 }
893}
894
895//! \brief Initialize calving mechanisms.
897
898 std::set<std::string> methods = set_split(m_config->get_string("calving.methods"), ',');
899 bool allocate_front_retreat = false;
900
901 if (member("thickness_calving", methods)) {
902
904 m_thickness_threshold_calving = std::make_shared<calving::CalvingAtThickness>(m_grid);
905 }
906
908 methods.erase("thickness_calving");
909
910 m_submodels["thickness threshold calving"] = m_thickness_threshold_calving.get();
911 }
912
913
914 if (member("eigen_calving", methods)) {
915 allocate_front_retreat = true;
916
917 if (not m_eigen_calving) {
918 m_eigen_calving = std::make_shared<calving::EigenCalving>(m_grid);
919 }
920
921 m_eigen_calving->init();
922 methods.erase("eigen_calving");
923
924 m_submodels["eigen calving"] = m_eigen_calving.get();
925 }
926
927 if (member("vonmises_calving", methods)) {
928 allocate_front_retreat = true;
929
930 if (not m_vonmises_calving) {
931 m_vonmises_calving = std::make_shared<calving::vonMisesCalving>(
932 m_grid, m_stress_balance->shallow()->flow_law());
933 }
934
935 m_vonmises_calving->init();
936 methods.erase("vonmises_calving");
937
938 m_submodels["von Mises calving"] = m_vonmises_calving.get();
939 }
940
941 if (member("hayhurst_calving", methods)) {
942 allocate_front_retreat = true;
943
944 if (not m_hayhurst_calving) {
945 m_hayhurst_calving = std::make_shared<calving::HayhurstCalving>(m_grid);
946 }
947
948 m_hayhurst_calving->init();
949 methods.erase("hayhurst_calving");
950
951 m_submodels["Hayhurst calving"] = m_hayhurst_calving.get();
952 }
953
954 if (member("float_kill", methods)) {
955 if (not m_float_kill_calving) {
956 m_float_kill_calving = std::make_shared<calving::FloatKill>(m_grid);
957 }
958
959 m_float_kill_calving->init();
960 methods.erase("float_kill");
961
962 m_submodels["float kill calving"] = m_float_kill_calving.get();
963 }
964
965 if (not methods.empty()) {
967 "PISM ERROR: calving method(s) [%s] are not supported.\n",
968 set_join(methods, ",").c_str());
969 }
970
971 // allocate front retreat code if necessary
972 if (not m_front_retreat and allocate_front_retreat) {
973 m_front_retreat = std::make_shared<FrontRetreat>(m_grid);
974 }
975
976 {
977 auto filename = m_config->get_string("calving.rate_scaling.file");
978 if (not filename.empty()) {
980 "calving.rate_scaling",
981 "frac_calving_rate",
982 "1",
983 "1",
984 "calving rate scaling factor"));
985 }
986 }
987}
988
990 if (m_beddef) {
991 return;
992 }
993
994 m_log->message(2,
995 "# Allocating a bed deformation model...\n");
996
997 std::string model = m_config->get_string("bed_deformation.model");
998
999 if (model == "none") {
1000 m_beddef = std::make_shared<bed::Null>(m_grid);
1001 }
1002 else if (model == "iso") {
1003 m_beddef = std::make_shared<bed::PointwiseIsostasy>(m_grid);
1004 }
1005 else if (model == "lc") {
1006 m_beddef = std::make_shared<bed::LingleClark>(m_grid);
1007 }
1008 else if (model == "given") {
1009 m_beddef = std::make_shared<bed::Given>(m_grid);
1010 }
1011
1012 m_submodels["bed deformation"] = m_beddef.get();
1013}
1014
1015//! Read some runtime (command line) options and alter the
1016//! corresponding parameters or flags as appropriate.
1018
1019 m_log->message(3,
1020 "Processing physics-related command-line options...\n");
1021
1023 m_config->resolve_filenames();
1024
1025 // Set global attributes using the config database:
1026 m_output_global_attributes["title"] = m_config->get_string("run_info.title");
1027 m_output_global_attributes["institution"] = m_config->get_string("run_info.institution");
1029
1030 // warn about some option combinations
1031
1032 if (m_config->get_number("time_stepping.maximum_time_step") <= 0) {
1033 throw RuntimeError(PISM_ERROR_LOCATION, "time_stepping.maximum_time_step has to be greater than 0.");
1034 }
1035
1036 if (not m_config->get_flag("geometry.update.enabled") &&
1037 m_config->get_flag("time_stepping.skip.enabled")) {
1038 m_log->message(2,
1039 "PISM WARNING: Both -skip and -no_mass are set.\n"
1040 " -skip only makes sense in runs updating ice geometry.\n");
1041 }
1042
1043 if (m_config->get_string("calving.methods").find("thickness_calving") != std::string::npos &&
1044 not m_config->get_flag("geometry.part_grid.enabled")) {
1045 m_log->message(2,
1046 "PISM WARNING: Calving at certain terminal ice thickness (-calving thickness_calving)\n"
1047 " without application of partially filled grid cell scheme (-part_grid)\n"
1048 " may lead to (incorrect) non-moving ice shelf front.\n");
1049 }
1050}
1051
1052//! Assembles a list of diagnostics corresponding to an output file size.
1053std::set<std::string> IceModel::output_variables(const std::string &keyword) {
1054
1055 std::string variables;
1056
1057 if (keyword == "none" or
1058 keyword == "small") {
1059 variables = "";
1060 } else if (keyword == "medium") {
1061 variables = m_config->get_string("output.sizes.medium");
1062 } else if (keyword == "big_2d") {
1063 variables = (m_config->get_string("output.sizes.medium") + "," +
1064 m_config->get_string("output.sizes.big_2d"));
1065 } else if (keyword == "big") {
1066 variables = (m_config->get_string("output.sizes.medium") + "," +
1067 m_config->get_string("output.sizes.big_2d") + "," +
1068 m_config->get_string("output.sizes.big"));
1069 }
1070
1071 return set_split(variables, ',');
1072}
1073
1075
1076 std::string projection = m_grid->get_mapping_info().proj_string;
1077
1078 const char *compute_lon_lat = "grid.recompute_longitude_and_latitude";
1079
1080 if (m_config->get_flag(compute_lon_lat) and not projection.empty()) {
1081 m_log->message(2, "* Computing longitude and latitude using projection parameters...\n");
1082
1083#if (Pism_USE_PROJ==1)
1086#else
1088 "Cannot compute longitude and latitude.\n"
1089 "Please rebuild PISM with PROJ\n"
1090 "or set '%s' to 'false'.",
1092#endif
1093
1094 // IceModel::bootstrap_2d() uses these attributes to determine if it needs to regrid
1095 // longitude and latitude.
1096 m_geometry.longitude.metadata()["initialized"] = "true";
1097 m_geometry.latitude.metadata()["initialized"] = "true";
1098 }
1099}
1100
1101} // end of namespace pism
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:328
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
Definition File.cc:378
std::string name() const
Definition File.cc:274
std::string read_text_attribute(const std::string &var_name, const std::string &att_name) const
Get a text attribute.
Definition File.cc:645
High-level PISM I/O class.
Definition File.hh:55
array::Scalar1 ice_area_specific_volume
Definition Geometry.hh:52
array::Scalar2 ice_thickness
Definition Geometry.hh:51
array::Scalar longitude
Definition Geometry.hh:42
array::Scalar latitude
Definition Geometry.hh:41
std::map< std::string, const Component * > m_submodels
the list of sub-models, for writing model states and obtaining diagnostics
Definition IceModel.hh:252
void enforce_consistency_of_geometry(ConsistencyFlag flag)
Update the surface elevation and the flow-type mask when the geometry has changed.
Definition IceModel.cc:279
virtual void allocate_bed_deformation()
virtual void model_state_setup()
Sets the starting values of model state variables.
void init_checkpoints()
Initialize checkpointing (snapshot-on-wallclock-time) mechanism.
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
Definition IceModel.hh:395
std::shared_ptr< Isochrones > m_isochrones
Definition IceModel.hh:263
virtual void init_calving()
Initialize calving mechanisms.
std::shared_ptr< ocean::OceanModel > m_ocean
Definition IceModel.hh:280
std::shared_ptr< surface::SurfaceModel > m_surface
Definition IceModel.hh:279
virtual void compute_lat_lon()
std::shared_ptr< FractureDensity > m_fracture
Definition IceModel.hh:299
virtual void bootstrap_2d(const File &input_file)
const Time::Ptr m_time
Time manager.
Definition IceModel.hh:246
Geometry m_geometry
Definition IceModel.hh:288
std::shared_ptr< YieldStress > m_basal_yield_stress_model
Definition IceModel.hh:255
std::shared_ptr< calving::IcebergRemover > m_iceberg_remover
Definition IceModel.hh:265
virtual void initialize_2d()
std::shared_ptr< Context > m_ctx
Execution context.
Definition IceModel.hh:240
std::shared_ptr< frontalmelt::FrontalMelt > m_frontal_melt
Definition IceModel.hh:281
void init_extras()
Initialize the code saving spatially-variable diagnostic quantities.
array::Scalar m_basal_melt_rate
rate of production of basal meltwater (ice-equivalent); no ghosts
Definition IceModel.hh:295
virtual void misc_setup()
Miscellaneous initialization tasks plus tasks that need the fields that can come from regridding.
const Logger::Ptr m_log
Logger.
Definition IceModel.hh:244
std::shared_ptr< array::Forcing > m_surface_input_for_hydrology
Definition IceModel.hh:257
virtual void allocate_stressbalance()
Decide which stress balance model to use.
std::shared_ptr< calving::EigenCalving > m_eigen_calving
Definition IceModel.hh:268
std::unique_ptr< ScalarForcing > m_calving_rate_factor
Definition IceModel.hh:275
VariableMetadata m_output_global_attributes
stores global attributes saved in a PISM output file
Definition IceModel.hh:249
const array::Scalar & frontal_melt() const
Definition IceModel.cc:919
virtual void allocate_iceberg_remover()
std::vector< std::shared_ptr< array::Scalar2 > > m_work2d
Definition IceModel.hh:393
virtual void process_options()
std::shared_ptr< calving::CalvingAtThickness > m_thickness_threshold_calving
Definition IceModel.hh:267
std::shared_ptr< calving::FloatKill > m_float_kill_calving
Definition IceModel.hh:266
virtual void allocate_subglacial_hydrology()
Decide which subglacial hydrology model to use.
std::shared_ptr< PrescribedRetreat > m_prescribed_retreat
Definition IceModel.hh:271
array::Scalar2 m_velocity_bc_mask
mask to determine Dirichlet boundary locations for the sliding velocity
Definition IceModel.hh:302
void reset_counters()
Definition IceModel.cc:130
virtual void prepend_history(const std::string &string)
Get time and user/host name and add it to the given string.
Definition utilities.cc:114
std::shared_ptr< calving::HayhurstCalving > m_hayhurst_calving
Definition IceModel.hh:269
virtual void allocate_basal_yield_stress()
Decide which basal yield stress model to use.
Config::Ptr m_config
Configuration flags and parameters.
Definition IceModel.hh:238
std::unique_ptr< GeometryEvolution > m_geometry_evolution
Definition IceModel.hh:289
virtual void allocate_energy_model()
virtual void restart_2d(const File &input_file, unsigned int record)
Initialize 2D model state fields managed by IceModel from a file (for re-starting).
virtual void time_setup()
Initialize time from an input file or command-line options.
std::shared_ptr< energy::BedThermalUnit > m_btu
Definition IceModel.hh:259
std::set< array::Array * > m_model_state
Definition IceModel.hh:415
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
Definition IceModel.hh:307
std::shared_ptr< AgeModel > m_age_model
Definition IceModel.hh:262
virtual void init_front_retreat()
virtual void allocate_bedrock_thermal_unit()
Decide which bedrock thermal unit to use.
virtual std::set< std::string > output_variables(const std::string &keyword)
Assembles a list of diagnostics corresponding to an output file size.
virtual void regrid()
Manage regridding based on user options.
const units::System::Ptr m_sys
Unit system.
Definition IceModel.hh:242
array::Vector2 m_velocity_bc_values
Dirichlet boundary velocities.
Definition IceModel.hh:304
virtual void allocate_geometry_evolution()
std::map< std::string, Diagnostic::Ptr > m_diagnostics
Requested spatially-variable diagnostics.
Definition IceModel.hh:417
void init_snapshots()
Initializes the snapshot-saving mechanism.
std::shared_ptr< ocean::sea_level::SeaLevel > m_sea_level
Definition IceModel.hh:282
virtual void allocate_age_model()
virtual YieldStressInputs yield_stress_inputs()
Definition IceModel.cc:364
virtual void init_diagnostics()
virtual void allocate_couplers()
std::unique_ptr< hydrology::Hydrology > m_subglacial_hydrology
Definition IceModel.hh:254
std::shared_ptr< calving::vonMisesCalving > m_vonmises_calving
Definition IceModel.hh:270
void init_timeseries()
Initializes the code writing scalar time-series.
Definition output_ts.cc:45
std::set< std::string > m_output_vars
Definition IceModel.hh:422
virtual void allocate_isochrones()
virtual void init_frontal_melt()
std::shared_ptr< energy::EnergyModel > m_energy_model
Definition IceModel.hh:260
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition IceModel.hh:236
std::shared_ptr< bed::BedDef > m_beddef
Definition IceModel.hh:284
virtual void allocate_submodels()
Allocate PISM's sub-models implementing some physical processes.
std::shared_ptr< FrontRetreat > m_front_retreat
Definition IceModel.hh:277
array::Scalar2 m_basal_yield_stress
ghosted
Definition IceModel.hh:293
virtual std::shared_ptr< Model > create()
Creates a boundary model. Processes command-line options.
Definition PCFactory.hh:42
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
std::string get_string(const std::string &name) const
Get a string attribute.
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:64
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:73
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:629
void regrid(const std::string &filename, io::Default default_value)
Definition Array.cc:736
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition Array.cc:476
int as_int(int i, int j) const
Definition Scalar.hh:45
static std::shared_ptr< BedThermalUnit > FromOptions(std::shared_ptr< const Grid > g, std::shared_ptr< const Context > ctx)
The PISM subglacial hydrology model for a distributed linked-cavity system.
A subglacial hydrology model which assumes water pressure equals overburden pressure.
Definition Routing.hh:81
static Default Nil()
Definition IO_Flags.hh:93
#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
Sub-glacial hydrology models and related diagnostics.
@ PISM_GUESS
Definition IO_Flags.hh:56
@ PISM_NETCDF3
Definition IO_Flags.hh:57
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:68
std::shared_ptr< StressBalance > create(const std::string &model, std::shared_ptr< const Grid > grid, bool regional)
Definition factory.cc:39
InputOptions process_input_options(MPI_Comm com, Config::ConstPtr config)
Definition Component.cc:43
void compute_latitude(const std::string &projection, array::Scalar &result)
@ INIT_BOOTSTRAP
Definition Component.hh:56
@ INIT_OTHER
Definition Component.hh:56
@ INIT_RESTART
Definition Component.hh:56
std::string set_join(const std::set< std::string > &input, const std::string &separator)
std::string printf(const char *format,...)
void compute_longitude(const std::string &projection, array::Scalar &result)
std::set< std::string > set_split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a set of strings.
bool member(const std::string &string, const std::set< std::string > &set)
void set_config_from_options(units::System::Ptr unit_system, Config &config)
Set configuration parameters using command-line options.
std::string args_string()
Uses argc and argv to create the string with current PISM command-line arguments.
static void compute_lon_lat(const std::string &projection, LonLat which, array::Scalar &result)
std::string join(const std::vector< std::string > &strings, const std::string &separator)
Concatenate strings, inserting separator between elements.
std::string filename
Definition options.hh:33
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