PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
initialization.cc
Go to the documentation of this file.
1// Copyright (C) 2009--2025 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/Config.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#include "pism/util/io/IO_Flags.hh"
72
73namespace pism {
74
75//! Sets the starting values of model state variables.
76/*!
77 There are two cases:
78
79 1) Initializing from a PISM output file.
80
81 2) Setting the values using command-line options only (verification and
82 simplified geometry runs, for example) or from a bootstrapping file, using
83 heuristics to fill in missing and 3D fields.
84
85 Calls IceModel::regrid().
86
87 This function is called after all the memory allocation is done and all the
88 physical parameters are set.
89
90 Calling this method should be all one needs to set model state variables.
91 Please avoid modifying them in other parts of the initialization sequence.
92
93 Also, please avoid operations that would make it unsafe to call this more
94 than once (memory allocation is one example).
95 */
97
98 const bool use_input_file =
99 input_options.type == INIT_BOOTSTRAP or input_options.type == INIT_RESTART;
100
101 std::unique_ptr<File> input_file;
102
103 if (use_input_file) {
104 input_file.reset(
105 new File(m_grid->com, input_options.filename, io::PISM_GUESS, io::PISM_READONLY));
106 }
107
108 // Compute latitudes and longitudes *before* they might be needed.
110
111 if (use_input_file) {
112 std::string old_history = input_file->read_text_attribute("PISM_GLOBAL", "history");
113 m_output_history = old_history + "\n" + m_output_history;
114 }
115
116 // Initialize 2D fields owned by IceModel (ice geometry, etc)
117 {
118 switch (input_options.type) {
119 case INIT_RESTART:
120 restart_2d(*input_file, input_options.record);
121 break;
122 case INIT_BOOTSTRAP:
123 bootstrap_2d(*input_file);
124 break;
125 case INIT_OTHER:
126 default:
128 }
129
130 regrid();
131 }
132
133 m_sea_level->init(m_geometry);
134
135 // Initialize a bed deformation model.
136 if (m_beddef) {
137 m_beddef->init(input_options, m_geometry.ice_thickness, m_sea_level->elevation());
138 m_grid->variables().add(m_beddef->bed_elevation());
139 m_grid->variables().add(m_beddef->uplift());
140 }
141
142 // Now ice thickness, bed elevation, and sea level are available, so we can compute the ice
143 // surface elevation and the cell type mask. This also ensures consistency of ice geometry.
144 //
145 // The stress balance code is executed near the beginning of a step and ice geometry is
146 // updated near the end, so during the second time step the stress balance code is
147 // guaranteed not to see "icebergs". Here we make sure that the first time step is OK
148 // too.
150
151 // By now ice geometry is set (including regridding) and so we can initialize the ocean model,
152 // which may need ice thickness, bed topography, and the cell type mask.
153 { m_ocean->init(m_geometry); }
154
155 // Now surface elevation is initialized, so we can initialize surface models (some use
156 // elevation-based parameterizations of surface temperature and/or mass balance).
157 m_surface->init(m_geometry);
158
160
161 switch (input_options.type) {
162 case INIT_RESTART:
163 m_subglacial_hydrology->restart(*input_file, input_options.record);
164 break;
165 case INIT_BOOTSTRAP:
166 m_subglacial_hydrology->bootstrap(*input_file, m_geometry.ice_thickness);
167 break;
168 case INIT_OTHER: {
169 array::Scalar &W_till = *m_work2d[0], &W = *m_work2d[1], &P = *m_work2d[2];
170
171 W_till.set(m_config->get_number("bootstrapping.defaults.tillwat"));
172 W.set(m_config->get_number("bootstrapping.defaults.bwat"));
173 P.set(m_config->get_number("bootstrapping.defaults.bwp"));
174
175 m_subglacial_hydrology->init(W_till, W, P);
176 break;
177 }
178 }
179 }
180
181 // basal_yield_stress_model->init() needs till water thickness so this must happen
182 // after subglacial_hydrology->init()
184 auto inputs = yield_stress_inputs();
185
186 switch (input_options.type) {
187 case INIT_RESTART:
188 m_basal_yield_stress_model->restart(*input_file, input_options.record);
189 break;
190 case INIT_BOOTSTRAP:
191 m_basal_yield_stress_model->bootstrap(*input_file, inputs);
192 break;
193 default:
194 case INIT_OTHER:
195 m_basal_yield_stress_model->init(inputs);
196 }
197 m_basal_yield_stress.copy_from(m_basal_yield_stress_model->basal_material_yield_stress());
198 }
199
200 // Initialize the bedrock thermal layer model.
201 //
202 // If
203 // - PISM is bootstrapping and
204 // - we are using a non-zero-thickness thermal layer
205 //
206 // initialization of m_btu requires the temperature at the top of the bedrock. This is a problem
207 // because get_bed_top_temp() uses the enthalpy field that is not initialized until later and
208 // bootstrapping enthalpy uses the flux through the bottom surface of the ice (top surface of the
209 // bedrock) provided by m_btu.
210 //
211 // We get out of this by using the fact that the full state of m_btu is not needed and
212 // bootstrapping of the temperature field can be delayed.
213 //
214 // Note that to bootstrap m_btu we use the steady state solution of the heat equation in columns
215 // of the bedrock (a straight line at each column), so the flux through the top surface of the
216 // bedrock after bootstrapping is the same as the time-independent geothermal flux applied at the
217 // BOTTOM surface of the bedrock layer.
218 //
219 // The code then delays bootstrapping of the thickness field until the first time step.
220 if (m_btu != nullptr) {
221 m_btu->init(input_options);
222 }
223
224 if (m_age_model) {
225 m_age_model->init(input_options);
226 m_grid->variables().add(m_age_model->age());
227 }
228
229 if (m_isochrones) {
230 if (input_options.type == INIT_RESTART) {
231 m_isochrones->restart(*input_file, (int)input_options.record);
232 } else {
234 }
235 }
236
237 // Initialize the energy balance sub-model.
238 {
239 switch (input_options.type) {
240 case INIT_RESTART: {
241 m_energy_model->restart(*input_file, input_options.record);
242 break;
243 }
244 case INIT_BOOTSTRAP: {
245
246 m_energy_model->bootstrap(*input_file, m_geometry.ice_thickness, m_surface->temperature(),
247 m_surface->mass_flux(), m_btu->flux_through_top_surface());
248 break;
249 }
250 case INIT_OTHER:
251 default: {
252 m_basal_melt_rate.set(m_config->get_number("bootstrapping.defaults.bmelt"));
253
255 m_surface->temperature(), m_surface->mass_flux(),
256 m_btu->flux_through_top_surface());
257 }
258 }
259 m_grid->variables().add(m_energy_model->enthalpy());
260 }
261
262 // this has to go after we add enthalpy to m_grid->variables()
263 if (m_stress_balance) {
264 m_stress_balance->init();
265 }
266
267 // we keep ice thickness fixed at all the locations where the sliding (SSA) velocity is
268 // prescribed
269 {
271
272 for (auto p : m_grid->points()) {
273 const int i = p.i(), j = p.j();
274
275 if (m_velocity_bc_mask.as_int(i, j) != 0) {
276 m_ice_thickness_bc_mask(i, j) = 1.0;
277 }
278 }
279 }
280
281 // miscellaneous steps
282 {
284
285 auto startstr =
286 pism::printf("PISM (%s) started on %d procs.", pism::revision, (int)m_grid->size());
287 append_history(startstr + args_string());
288 }
289
290 // forget stored interpolation weights to free up some RAM
291 //
292 // FIXME: doing this makes PISM crash if it tries to a) regrid a variable from a file
293 // during initialization, then b) regrid a variable from the *same* file during the run
294 // (e.g. time-dependent forcing)
295 //
296 // Keeping all interpolation weights in memory requires more RAM if we interpolate from
297 // some grids only during initialization.
298 //
299 // m_grid->forget_interpolations();
300}
301
302//! Initialize 2D model state fields managed by IceModel from a file (for re-starting).
303/*!
304 * This method should eventually go away as IceModel turns into a "coupler" and all physical
305 * processes are handled by sub-models.
306 */
307void IceModel::restart_2d(const File &input_file, unsigned int last_record) {
308 std::string filename = input_file.name();
309
310 m_log->message(2, "initializing 2D fields from NetCDF file '%s'...\n", filename.c_str());
311
312 for (auto *variable : m_model_state) {
313 variable->read(input_file, last_record);
314 }
315}
316
317void IceModel::bootstrap_2d(const File &input_file) {
318
319 m_log->message(2, "bootstrapping from file '%s'...\n", input_file.name().c_str());
320
321 auto usurf = input_file.find_variable("usurf", "surface_altitude");
322
323 bool mask_found = input_file.variable_exists("mask");
324
325 // now work through all the 2d variables, regridding if present and otherwise
326 // setting to default values appropriately
327
328 if (mask_found) {
329 m_log->message(2, " WARNING: 'mask' found; IGNORING IT!\n");
330 }
331
332 if (usurf.exists) {
333 m_log->message(2, " WARNING: surface elevation 'usurf' found; IGNORING IT!\n");
334 }
335
336 m_log->message(2, " reading 2D model state variables by regridding ...\n");
337
338 // longitude
339 if (m_geometry.longitude.metadata().has_attribute("initialized")) {
340 m_geometry.longitude.metadata()["initialized"] = "";
341 } else {
342 m_geometry.longitude.regrid(input_file, io::Default(0.0));
343 }
344
345 // latitude
346 if (m_geometry.latitude.metadata().has_attribute("initialized")) {
347 m_geometry.latitude.metadata()["initialized"] = "";
348 } else {
349 m_geometry.latitude.regrid(input_file, io::Default(0.0));
350 }
351
353 input_file, io::Default(m_config->get_number("bootstrapping.defaults.ice_thickness")));
354
355 if (m_config->get_flag("geometry.part_grid.enabled")) {
356 // Read the Href field from an input file. This field is
357 // grid-dependent, so interpolating it from one grid to a
358 // different one does not make sense in general.
359 // (IceModel::Href_cleanup() will take care of the side effects of
360 // such interpolation, though.)
361 //
362 // On the other hand, we need to read it in to be able to re-start
363 // from a PISM output file using the -bootstrap option.
365 }
366
367 if (m_config->get_flag("stress_balance.ssa.dirichlet_bc")) {
368 // Do not use Dirichlet B.C. anywhere if bc_mask is not present.
369 m_velocity_bc_mask.regrid(input_file, io::Default(0.0));
370 // In absence of u_bc and v_bc in the file the only B.C. that make sense are the
371 // zero Dirichlet B.C.
372 m_velocity_bc_values.regrid(input_file, io::Default(0.0));
373 } else {
376 }
377
379
380 // check if Lz is valid
381 auto max_thickness = array::max(m_geometry.ice_thickness);
382
383 if (max_thickness > m_grid->Lz()) {
385 "Max. ice thickness (%3.3f m)\n"
386 "exceeds the height of the computational domain (%3.3f m).",
387 max_thickness, m_grid->Lz());
388 }
389}
390
392 // This method should NOT have the "noreturn" attribute. (This attribute does not mix with virtual
393 // methods).
394 throw RuntimeError(PISM_ERROR_LOCATION, "cannot initialize IceModel without an input file");
395}
396
397//! Manage regridding based on user options.
399
400 auto filename = m_config->get_string("input.regrid.file");
401 auto regrid_vars = set_split(m_config->get_string("input.regrid.vars"), ',');
402
403 // Return if no regridding is requested:
404 if (filename.empty()) {
405 return;
406 }
407
408 m_log->message(2, "regridding from file %s ...\n", filename.c_str());
409
410 {
411 File regrid_file(m_grid->com, filename, io::PISM_GUESS, io::PISM_READONLY);
412 for (auto *v : m_model_state) {
413 if (regrid_vars.find(v->get_name()) != regrid_vars.end()) {
414 v->regrid(regrid_file, io::Default::Nil());
415 }
416 }
417
418 // Check the range of the ice thickness.
419 {
420 double max_thickness = array::max(m_geometry.ice_thickness), Lz = m_grid->Lz();
421
422 if (max_thickness >= Lz + 1e-6) {
424 "Maximum ice thickness (%f meters)\n"
425 "exceeds the height of the computational domain (%f meters).",
426 max_thickness, Lz);
427 }
428 }
429 }
430}
431
432//! \brief Decide which stress balance model to use.
434
435 if (m_stress_balance) {
436 return;
437 }
438
439 m_log->message(2, "# Allocating a stress balance model...\n");
440
441 // false means "not regional"
443 stressbalance::create(m_config->get_string("stress_balance.model"), m_grid, false);
444
445 m_submodels["stress balance"] = m_stress_balance.get();
446}
447
450 return;
451 }
452
453 m_log->message(2, "# Allocating the geometry evolution model...\n");
454
456
457 m_submodels["geometry_evolution"] = m_geometry_evolution.get();
458}
459
460
462
463 if (m_iceberg_remover != NULL) {
464 return;
465 }
466
467 m_log->message(2, "# Allocating an iceberg remover (part of a calving model)...\n");
468
469 if (m_config->get_flag("geometry.remove_icebergs")) {
470
471 auto model = m_config->get_string("stress_balance.model");
472 auto ssa_method = m_config->get_string("stress_balance.ssa.method");
473
474 if ((set_member(model, { "ssa", "ssa+sia" }) and ssa_method == "fem") or model == "blatter") {
475 m_iceberg_remover = std::make_shared<calving::IcebergRemoverFEM>(m_grid);
476 } else {
477 m_iceberg_remover = std::make_shared<calving::IcebergRemover>(m_grid);
478 }
479
480 m_submodels["iceberg remover"] = m_iceberg_remover.get();
481 }
482}
483
485
486 if (m_age_model) {
487 return;
488 }
489
490 if (m_config->get_flag("age.enabled")) {
491 m_log->message(2, "# Allocating an ice age model...\n");
492
493 if (m_stress_balance == nullptr) {
495 "Cannot allocate an age model: m_stress_balance == nullptr.");
496 }
497
498 m_age_model = std::make_shared<AgeModel>(m_grid, m_stress_balance);
499 m_submodels["age model"] = m_age_model.get();
500 }
501}
502
504
505 if (m_isochrones) {
506 return;
507 }
508
509 auto deposition_times = m_config->get_string("isochrones.deposition_times");
510 if (not deposition_times.empty()) {
511 m_log->message(2, "# Allocating isochrone tracking...\n");
512
513 if (m_stress_balance == nullptr) {
516 "Cannot allocate the isochrone tracking model: m_stress_balance == nullptr.");
517 }
518
519 m_isochrones = std::make_shared<Isochrones>(m_grid, m_stress_balance);
520
521 m_submodels["isochrones"] = m_isochrones.get();
522 }
523}
524
526
527 if (m_energy_model != NULL) {
528 return;
529 }
530
531 m_log->message(2, "# Allocating an energy balance model...\n");
532
533 auto energy_model = m_config->get_string("energy.model");
534 if (energy_model == "enthalpy") {
535 m_energy_model = std::make_shared<energy::EnthalpyModel>(m_grid, m_stress_balance);
536 } else if (energy_model == "cold") {
537 m_energy_model = std::make_shared<energy::TemperatureModel>(m_grid, m_stress_balance);
538 } else {
539 m_energy_model = std::make_shared<energy::DummyEnergyModel>(m_grid, m_stress_balance);
540 }
541
542 m_submodels["energy balance model"] = m_energy_model.get();
543}
544
545
546//! \brief Decide which bedrock thermal unit to use.
548
549 if (m_btu != nullptr) {
550 return;
551 }
552
553 m_log->message(2, "# Allocating a bedrock thermal layer model...\n");
554
556
557 m_submodels["bedrock thermal model"] = m_btu.get();
558}
559
560//! \brief Decide which subglacial hydrology model to use.
562
563 using namespace pism::hydrology;
564
565 std::string hydrology_model = m_config->get_string("hydrology.model");
566
567 if (m_subglacial_hydrology) { // indicates it has already been allocated
568 return;
569 }
570
571 m_log->message(2, "# Allocating a subglacial hydrology model...\n");
572
573 if (hydrology_model == "null") {
575 } else if (hydrology_model == "routing") {
577 } else if (hydrology_model == "steady") {
579 } else if (hydrology_model == "distributed") {
581 } else {
582 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "unknown 'hydrology.model': %s",
583 hydrology_model.c_str());
584 }
585
586 m_submodels["subglacial hydrology"] = m_subglacial_hydrology.get();
587}
588
589//! \brief Decide which basal yield stress model to use.
591
593 return;
594 }
595
596 m_log->message(2, "# Allocating a basal yield stress model...\n");
597
598 std::string model = m_config->get_string("stress_balance.model");
599
600 // only these two use the yield stress (so far):
601 if (set_member(model, { "ssa", "ssa+sia", "blatter" })) {
602 std::string yield_stress_model = m_config->get_string("basal_yield_stress.model");
603
604 if (yield_stress_model == "constant") {
605 m_basal_yield_stress_model = std::make_shared<ConstantYieldStress>(m_grid);
606 } else if (yield_stress_model == "mohr_coulomb") {
607 m_basal_yield_stress_model = std::make_shared<MohrCoulombYieldStress>(m_grid);
608 } else if (yield_stress_model == "tillphi_opt") {
609 m_basal_yield_stress_model = std::make_shared<OptTillphiYieldStress>(m_grid);
610 } else {
612 "yield stress model '%s' is not supported.",
613 yield_stress_model.c_str());
614 }
615
616 m_submodels["basal yield stress"] = m_basal_yield_stress_model.get();
617 }
618}
619
620//! Allocate PISM's sub-models implementing some physical processes.
621/*!
622 This method is called after memory allocation but before filling any of
623 Arrays because all the physical parameters should be initialized before
624 setting up the coupling or filling model-state variables.
625 */
627
629
631
633
634 // this has to happen *after* allocate_stressbalance()
635 {
640 }
641
642 // this has to happen *after* allocate_subglacial_hydrology()
644
646
648
650
651 if (m_config->get_flag("fracture_density.enabled")) {
652 m_fracture = std::make_shared<FractureDensity>(m_grid, m_stress_balance->shallow()->flow_law());
653 m_submodels["fracture_density"] = m_fracture.get();
654 }
655}
656
657
659 // Initialize boundary models:
660
661 if (not m_surface) {
662
663 m_log->message(2, "# Allocating a surface process model or coupler...\n");
664
666
667 m_surface = std::make_shared<surface::InitializationHelper>(m_grid, ps.create());
668
669 m_submodels["surface process model"] = m_surface.get();
670 }
671
672 if (not m_sea_level) {
673 m_log->message(2, "# Allocating sea level forcing...\n");
674
675 using namespace ocean::sea_level;
676
677 m_sea_level = std::make_shared<InitializationHelper>(m_grid, Factory(m_grid).create());
678
679 m_submodels["sea level forcing"] = m_sea_level.get();
680 }
681
682 if (not m_ocean) {
683 m_log->message(2, "# Allocating an ocean model or coupler...\n");
684
685 using namespace ocean;
686
687 m_ocean = std::make_shared<InitializationHelper>(m_grid, Factory(m_grid).create());
688
689 m_submodels["ocean model"] = m_ocean.get();
690 }
691}
692
693//! Miscellaneous initialization tasks plus tasks that need the fields that can come from regridding.
694void IceModel::misc_setup(InputOptions input_options, DiagnosticReport report_type) {
695
696 m_log->message(3, "Finishing initialization...\n");
697
698 if (not(input_options.type == INIT_OTHER)) {
699 // initializing from a file
700 File file(m_grid->com, input_options.filename, io::PISM_GUESS, io::PISM_READONLY);
701
702 std::string source = file.read_text_attribute("PISM_GLOBAL", "source");
703
704 if (input_options.type == INIT_RESTART) {
705 // If it's missing, print a warning
706 if (source.empty()) {
707 m_log->message(
708 1,
709 "PISM WARNING: file '%s' does not have the 'source' global attribute.\n"
710 " If '%s' is a PISM output file, please run the following to get rid of this warning:\n"
711 " ncatted -a source,global,c,c,PISM %s\n",
712 input_options.filename.c_str(), input_options.filename.c_str(),
713 input_options.filename.c_str());
714 } else if (source.find("PISM") == std::string::npos) {
715 // If the 'source' attribute does not contain the string "PISM", then print
716 // a message and stop:
717 m_log->message(
718 1,
719 "PISM WARNING: '%s' does not seem to be a PISM output file.\n"
720 " If it is, please make sure that the 'source' global attribute contains the string \"PISM\".\n",
721 input_options.filename.c_str());
722 }
723 }
724 }
725
726 {
727 // A single record of a time-dependent variable cannot exceed 2^32-4
728 // bytes in size. See the NetCDF User's Guide
729 // <http://www.unidata.ucar.edu/software/netcdf/docs/netcdf.html#g_t64-bit-Offset-Limitations>.
730 // Here we use "long int" to avoid integer overflow.
731 const long int two_to_thirty_two = 4294967296L;
732 const long int Mx = m_grid->Mx(), My = m_grid->My(), Mz = m_grid->Mz();
733 std::string output_format = m_config->get_string("output.format");
734 if (Mx * My * Mz * sizeof(double) > two_to_thirty_two - 4 and
735 (output_format == io::PISM_NETCDF3)) {
738 "The computational grid is too big to fit in a NetCDF-3 file.\n"
739 "Each 3D variable requires %lu Mb.\n"
740 "Please use '-o_format pnetcdf or -o_format netcdf4_parallel to proceed.",
741 Mx * My * Mz * sizeof(double) / (1024 * 1024));
742 }
743 }
744
745 init_calving();
748
749 // initialize outputs
750 init_outputs(input_options, report_type);
751
752 // a report on whether PISM-PIK modifications of IceModel are in use
753 {
754 std::vector<std::string> pik_methods;
755 if (m_config->get_flag("geometry.part_grid.enabled")) {
756 pik_methods.push_back("part_grid");
757 }
758 if (m_config->get_flag("geometry.remove_icebergs")) {
759 pik_methods.push_back("kill_icebergs");
760 }
761
762 if (not pik_methods.empty()) {
763 m_log->message(2, "* PISM-PIK mass/geometry methods are in use: %s\n",
764 join(pik_methods, ", ").c_str());
765 }
766 }
767
769 ForcingOptions surface_input(*m_ctx, "hydrology.surface_input");
770 m_surface_input_for_hydrology->init(surface_input.filename, surface_input.periodic);
771 }
772
773 if (m_fracture) {
774 if (input_options.type == INIT_OTHER) {
775 m_fracture->initialize();
776 } else {
777 // initializing from a file
778 File file(m_grid->com, input_options.filename, io::PISM_GUESS, io::PISM_READONLY);
779
780 if (input_options.type == INIT_RESTART) {
781 m_fracture->restart(file, input_options.record);
782 } else if (input_options.type == INIT_BOOTSTRAP) {
783 m_fracture->bootstrap(file);
784 }
785 }
786 }
787}
788
790
791 auto frontal_melt = m_config->get_string("frontal_melt.models");
792
793 if (not frontal_melt.empty()) {
794 if (not m_config->get_flag("geometry.part_grid.enabled")) {
796 PISM_ERROR_LOCATION, "ERROR: frontal melt models require geometry.part_grid.enabled");
797 }
798
800
802
803 m_submodels["frontal melt"] = m_frontal_melt.get();
804
805 if (not m_front_retreat) {
806 m_front_retreat = std::make_shared<FrontRetreat>(m_grid);
807 }
808 }
809}
810
812 auto front_retreat_file = m_config->get_string("geometry.front_retreat.prescribed.file");
813
814 if (not front_retreat_file.empty()) {
815 m_prescribed_retreat = std::make_shared<PrescribedRetreat>(m_grid);
816
817 m_prescribed_retreat->init();
818
819 m_submodels["prescribed front retreat"] = m_prescribed_retreat.get();
820 }
821}
822
823//! \brief Initialize calving mechanisms.
825
826 std::set<std::string> methods = set_split(m_config->get_string("calving.methods"), ',');
827 bool allocate_front_retreat = false;
828
829 if (set_member("thickness_calving", methods)) {
830
832 m_thickness_threshold_calving = std::make_shared<calving::CalvingAtThickness>(m_grid);
833 }
834
836 methods.erase("thickness_calving");
837
838 m_submodels["thickness threshold calving"] = m_thickness_threshold_calving.get();
839 }
840
841
842 if (set_member("eigen_calving", methods)) {
843 allocate_front_retreat = true;
844
845 if (not m_eigen_calving) {
846 m_eigen_calving = std::make_shared<calving::EigenCalving>(m_grid);
847 }
848
849 m_eigen_calving->init();
850 methods.erase("eigen_calving");
851
852 m_submodels["eigen calving"] = m_eigen_calving.get();
853 }
854
855 if (set_member("vonmises_calving", methods)) {
856 allocate_front_retreat = true;
857
858 if (not m_vonmises_calving) {
859 m_vonmises_calving = std::make_shared<calving::vonMisesCalving>(
860 m_grid, m_stress_balance->shallow()->flow_law());
861 }
862
863 m_vonmises_calving->init();
864 methods.erase("vonmises_calving");
865
866 m_submodels["von Mises calving"] = m_vonmises_calving.get();
867 }
868
869 if (set_member("hayhurst_calving", methods)) {
870 allocate_front_retreat = true;
871
872 if (not m_hayhurst_calving) {
873 m_hayhurst_calving = std::make_shared<calving::HayhurstCalving>(m_grid);
874 }
875
876 m_hayhurst_calving->init();
877 methods.erase("hayhurst_calving");
878
879 m_submodels["Hayhurst calving"] = m_hayhurst_calving.get();
880 }
881
882 if (set_member("float_kill", methods)) {
883 if (not m_float_kill_calving) {
884 m_float_kill_calving = std::make_shared<calving::FloatKill>(m_grid);
885 }
886
887 m_float_kill_calving->init();
888 methods.erase("float_kill");
889
890 m_submodels["float kill calving"] = m_float_kill_calving.get();
891 }
892
893 if (not methods.empty()) {
895 "PISM ERROR: calving method(s) [%s] are not supported.\n",
896 set_join(methods, ",").c_str());
897 }
898
899 // allocate front retreat code if necessary
900 if (not m_front_retreat and allocate_front_retreat) {
901 m_front_retreat = std::make_shared<FrontRetreat>(m_grid);
902 }
903
904 {
905 auto filename = m_config->get_string("calving.rate_scaling.file");
906 if (not filename.empty()) {
907 m_calving_rate_factor.reset(new ScalarForcing(*m_ctx, "calving.rate_scaling",
908 "frac_calving_rate", "1", "1",
909 "calving rate scaling factor"));
910 }
911 }
912}
913
915 if (m_beddef) {
916 return;
917 }
918
919 m_log->message(2, "# Allocating a bed deformation model...\n");
920
921 std::string model = m_config->get_string("bed_deformation.model");
922
923 if (model == "none") {
924 m_beddef = std::make_shared<bed::Null>(m_grid);
925 } else if (model == "iso") {
926 m_beddef = std::make_shared<bed::PointwiseIsostasy>(m_grid);
927 } else if (model == "lc") {
928 m_beddef = std::make_shared<bed::LingleClark>(m_grid);
929 } else if (model == "given") {
930 m_beddef = std::make_shared<bed::Given>(m_grid);
931 }
932
933 m_submodels["bed deformation"] = m_beddef.get();
934}
935
936//! Assembles a list of diagnostics corresponding to an output file size.
937std::set<std::string> IceModel::output_variables(const std::string &keyword) {
938
939 std::string variables;
940
941 if (keyword == "none" or
942 keyword == "small") {
943 variables = "";
944 } else if (keyword == "medium") {
945 variables = m_config->get_string("output.sizes.medium");
946 } else if (keyword == "big_2d") {
947 variables = (m_config->get_string("output.sizes.medium") + "," +
948 m_config->get_string("output.sizes.big_2d"));
949 } else if (keyword == "big") {
950 variables = (m_config->get_string("output.sizes.medium") + "," +
951 m_config->get_string("output.sizes.big_2d") + "," +
952 m_config->get_string("output.sizes.big"));
953 }
954
955 return set_split(variables, ',');
956}
957
959
960 std::string projection = m_grid->get_mapping_info()["proj_params"];
961
962 const char *compute_lon_lat = "grid.recompute_longitude_and_latitude";
963
964 if (m_config->get_flag(compute_lon_lat) and not projection.empty()) {
965 m_log->message(2, "* Computing longitude and latitude using projection parameters...\n");
966
967#if (Pism_USE_PROJ==1)
970#else
972 "Cannot compute longitude and latitude.\n"
973 "Please rebuild PISM with PROJ\n"
974 "or set '%s' to 'false'.",
976#endif
977
978 // IceModel::bootstrap_2d() uses these attributes to determine if it needs to regrid
979 // longitude and latitude.
980 m_geometry.longitude.metadata()["initialized"] = "true";
981 m_geometry.latitude.metadata()["initialized"] = "true";
982 }
983}
984
985} // 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:650
High-level PISM I/O class.
Definition File.hh:57
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:297
void enforce_consistency_of_geometry(ConsistencyFlag flag)
Update the surface elevation and the flow-type mask when the geometry has changed.
Definition IceModel.cc:302
virtual void allocate_bed_deformation()
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
Definition IceModel.hh:439
std::shared_ptr< Isochrones > m_isochrones
Definition IceModel.hh:308
virtual void init_calving()
Initialize calving mechanisms.
std::shared_ptr< ocean::OceanModel > m_ocean
Definition IceModel.hh:325
std::shared_ptr< surface::SurfaceModel > m_surface
Definition IceModel.hh:324
virtual void compute_lat_lon()
std::shared_ptr< FractureDensity > m_fracture
Definition IceModel.hh:344
std::shared_ptr< Config > m_config
Configuration flags and parameters.
Definition IceModel.hh:278
virtual void bootstrap_2d(const File &input_file)
Geometry m_geometry
Definition IceModel.hh:333
std::shared_ptr< YieldStress > m_basal_yield_stress_model
Definition IceModel.hh:300
std::shared_ptr< calving::IcebergRemover > m_iceberg_remover
Definition IceModel.hh:310
virtual void initialize_2d()
std::shared_ptr< Context > m_ctx
Execution context.
Definition IceModel.hh:280
std::shared_ptr< frontalmelt::FrontalMelt > m_frontal_melt
Definition IceModel.hh:326
std::shared_ptr< Logger > m_log
Logger.
Definition IceModel.hh:284
array::Scalar m_basal_melt_rate
rate of production of basal meltwater (ice-equivalent); no ghosts
Definition IceModel.hh:340
std::shared_ptr< array::Forcing > m_surface_input_for_hydrology
Definition IceModel.hh:302
virtual void allocate_stressbalance()
Decide which stress balance model to use.
std::shared_ptr< calving::EigenCalving > m_eigen_calving
Definition IceModel.hh:313
std::unique_ptr< ScalarForcing > m_calving_rate_factor
Definition IceModel.hh:320
void init_outputs(InputOptions options, DiagnosticReport report_type)
const array::Scalar & frontal_melt() const
Definition IceModel.cc:945
virtual void allocate_iceberg_remover()
std::vector< std::shared_ptr< array::Scalar2 > > m_work2d
Definition IceModel.hh:437
std::shared_ptr< calving::CalvingAtThickness > m_thickness_threshold_calving
Definition IceModel.hh:312
std::shared_ptr< calving::FloatKill > m_float_kill_calving
Definition IceModel.hh:311
virtual void allocate_subglacial_hydrology()
Decide which subglacial hydrology model to use.
std::shared_ptr< PrescribedRetreat > m_prescribed_retreat
Definition IceModel.hh:316
array::Scalar2 m_velocity_bc_mask
mask to determine Dirichlet boundary locations for the sliding velocity
Definition IceModel.hh:347
void reset_counters()
Definition IceModel.cc:155
std::shared_ptr< calving::HayhurstCalving > m_hayhurst_calving
Definition IceModel.hh:314
virtual void allocate_basal_yield_stress()
Decide which basal yield stress model to use.
std::unique_ptr< GeometryEvolution > m_geometry_evolution
Definition IceModel.hh:334
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).
std::shared_ptr< energy::BedThermalUnit > m_btu
Definition IceModel.hh:304
virtual void model_state_setup(InputOptions input_options)
Sets the starting values of model state variables.
std::set< array::Array * > m_model_state
Definition IceModel.hh:459
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
Definition IceModel.hh:352
std::shared_ptr< AgeModel > m_age_model
Definition IceModel.hh:307
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.
array::Vector2 m_velocity_bc_values
Dirichlet boundary velocities.
Definition IceModel.hh:349
virtual void allocate_geometry_evolution()
std::shared_ptr< ocean::sea_level::SeaLevel > m_sea_level
Definition IceModel.hh:327
virtual void allocate_age_model()
std::string m_output_history
Definition IceModel.hh:294
virtual YieldStressInputs yield_stress_inputs()
Definition IceModel.cc:387
virtual void misc_setup(InputOptions input_options, DiagnosticReport report_type)
Miscellaneous initialization tasks plus tasks that need the fields that can come from regridding.
virtual void allocate_couplers()
virtual void append_history(const std::string &string)
Get time and user/host name and add it to the given string.
Definition utilities.cc:106
std::unique_ptr< hydrology::Hydrology > m_subglacial_hydrology
Definition IceModel.hh:299
std::shared_ptr< calving::vonMisesCalving > m_vonmises_calving
Definition IceModel.hh:315
virtual void allocate_isochrones()
virtual void init_frontal_melt()
std::shared_ptr< energy::EnergyModel > m_energy_model
Definition IceModel.hh:305
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition IceModel.hh:276
std::shared_ptr< bed::BedDef > m_beddef
Definition IceModel.hh:329
virtual void allocate_submodels()
Allocate PISM's sub-models implementing some physical processes.
std::shared_ptr< FrontRetreat > m_front_retreat
Definition IceModel.hh:322
array::Scalar2 m_basal_yield_stress
ghosted
Definition IceModel.hh:338
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
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:66
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:101
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:659
void regrid(const std::string &filename, io::Default default_value)
Definition Array.cc:758
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
Definition Array.cc:467
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:94
#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:57
@ PISM_NETCDF3
Definition IO_Flags.hh:58
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:69
std::shared_ptr< StressBalance > create(const std::string &model, std::shared_ptr< const Grid > grid, bool regional)
Definition factory.cc:39
DiagnosticReport
Definition IceModel.hh:117
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.
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.
bool set_member(const std::string &string, const std::set< std::string > &set)
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