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
BedDef.cc
Go to the documentation of this file.
1// Copyright (C) 2010--2024 PISM Authors
2//
3// This file is part of PISM.
4//
5// PISM is free software; you can redistribute it and/or modify it under the
6// terms of the GNU General Public License as published by the Free Software
7// Foundation; either version 3 of the License, or (at your option) any later
8// version.
9//
10// PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13// details.
14//
15// You should have received a copy of the GNU General Public License
16// along with PISM; if not, write to the Free Software
17// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18
19#include <string>
20
21#include "pism/earth/BedDef.hh"
22#include "pism/util/ConfigInterface.hh"
23#include "pism/util/Context.hh"
24#include "pism/util/Grid.hh"
25#include "pism/util/MaxTimestep.hh"
26#include "pism/util/Time.hh"
27
28
29namespace pism {
30namespace bed {
31
32BedDef::BedDef(std::shared_ptr<const Grid> grid, const std::string &model_name)
33 : Component(grid),
34 m_topg(m_grid, "topg"),
35 m_topg_last(m_grid, "topg"),
36 m_load(grid, "bed_def_load"),
37 m_load_accumulator(grid, "bed_def_load_accumulator"),
38 m_uplift(m_grid, "dbdt"),
39 m_t_last(time().current()),
40 m_model_name(model_name)
41{
42 m_time_name = m_config->get_string("time.dimension_name") + "_bed_deformation";
43 m_update_interval = m_config->get_number("bed_deformation.update_interval", "seconds");
44 m_t_eps = m_config->get_number("time_stepping.resolution", "seconds");
45
47 .long_name("bedrock surface elevation")
48 .units("m")
49 .standard_name("bedrock_altitude");
50
52 .long_name("bedrock surface elevation after the previous update (used to compute uplift)")
53 .units("m")
54 .standard_name("bedrock_altitude");
55
57 .long_name("load on the bed expressed as ice-equivalent thickness")
58 .units("m");
59 m_load.set(0.0);
60
62 .long_name("accumulated load on the bed expressed as the time integral of ice-equivalent thickness")
63 .units("m s");
64
66 .long_name("bedrock uplift rate")
67 .units("m s^-1")
68 .standard_name("tendency_of_bedrock_altitude");
69}
70
72 return m_topg;
73}
74
76 return m_uplift;
77}
78
79void BedDef::define_model_state_impl(const File &output) const {
83
84 if (not output.variable_exists(m_time_name)) {
86
87 output.write_attribute(m_time_name, "long_name",
88 "time of the last update of the Lingle-Clark bed deformation model");
89 output.write_attribute(m_time_name, "calendar", time().calendar());
90 output.write_attribute(m_time_name, "units", time().units_string());
91 }
92
93}
94
95void BedDef::write_model_state_impl(const File &output) const {
96 m_uplift.write(output);
97 m_topg.write(output);
99
100 output.write_variable(m_time_name, {0}, {1}, &m_t_last);
101}
102
104 DiagnosticList result;
105 result = { { "dbdt", Diagnostic::wrap(m_uplift) },
106 { "topg", Diagnostic::wrap(m_topg) },
107 { "bed_def_load", Diagnostic::wrap(m_load) } };
108
109 return result;
110}
111
112void BedDef::init(const InputOptions &opts, const array::Scalar &ice_thickness,
113 const array::Scalar &sea_level_elevation) {
114
115 m_log->message(2, "* Initializing the %s bed deformation model...\n",
116 m_model_name.c_str());
117
118 m_t_last = time().current();
119 if (opts.type == INIT_RESTART or opts.type == INIT_BOOTSTRAP) {
120 File input_file(m_grid->com, opts.filename, io::PISM_NETCDF3, io::PISM_READONLY);
121
122 if (input_file.variable_exists(m_time_name)) {
123 input_file.read_variable(m_time_name, {0}, {1}, &m_t_last);
124 }
125 }
126
127 {
128 switch (opts.type) {
129 case INIT_RESTART:
130 // read bed elevation and uplift rate from file
131 m_log->message(2, " reading bed topography and uplift from %s ... \n",
132 opts.filename.c_str());
133 // re-starting
134 m_topg.read(opts.filename, opts.record); // fails if not found!
135 m_uplift.read(opts.filename, opts.record); // fails if not found!
137 break;
138 case INIT_BOOTSTRAP:
139 // bootstrapping
140 m_topg.regrid(opts.filename, io::Default(m_config->get_number("bootstrapping.defaults.bed")));
142 io::Default(m_config->get_number("bootstrapping.defaults.uplift")));
144 break;
145 case INIT_OTHER:
146 default: {
147 // do nothing
148 }
149 }
150
151 // process -regrid_file and -regrid_vars
152 regrid("bed deformation", m_topg, REGRID_WITHOUT_REGRID_VARS);
154 // uplift is not a part of the model state, but the user may want to take it from a -regrid_file
155 // during bootstrapping
156 regrid("bed deformation", m_uplift, REGRID_WITHOUT_REGRID_VARS);
157
158 auto uplift_file = m_config->get_string("bed_deformation.bed_uplift_file");
159 if (not uplift_file.empty()) {
160 m_log->message(2, " reading bed uplift from %s ... \n", uplift_file.c_str());
161 m_uplift.regrid(uplift_file, io::Default::Nil());
162 }
163
164 auto correction_file = m_config->get_string("bed_deformation.bed_topography_delta_file");
165 if (not correction_file.empty()) {
166 m_log->message(2, " Adding a bed topography correction read in from '%s'...\n",
167 correction_file.c_str());
168 apply_topg_offset(correction_file, m_topg);
169 }
170 }
171
172 this->init_impl(opts, ice_thickness, sea_level_elevation);
173
174 // this should be the last thing we do
176}
177
178//! Initialize using provided bed elevation and uplift.
179void BedDef::bootstrap(const array::Scalar &bed_elevation, const array::Scalar &bed_uplift,
180 const array::Scalar &ice_thickness,
181 const array::Scalar &sea_level_elevation) {
182 m_t_last = time().current();
183
185 m_uplift.copy_from(bed_uplift);
187
188 this->bootstrap_impl(bed_elevation, bed_uplift, ice_thickness, sea_level_elevation);
189}
190
191void BedDef::bootstrap_impl(const array::Scalar & /*bed_elevation*/,
192 const array::Scalar & /*bed_uplift*/,
193 const array::Scalar & /*ice_thickness*/,
194 const array::Scalar & /*sea_level_elevation*/) {
195 // empty
196}
197
198void BedDef::update(const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation,
199 double t, double dt) {
200
201 double t_final = t + dt;
202
203 if (t_final < m_t_last) {
204 throw RuntimeError(PISM_ERROR_LOCATION, "cannot go back in time");
205 }
206
207 accumulate_load(m_topg_last, ice_thickness, sea_level_elevation, dt, m_load_accumulator);
208
209 double t_next = m_update_interval > 0.0 ? m_t_last + m_update_interval : t_final;
210 if (std::abs(t_next - t_final) < m_t_eps) { // reached the next update time
211
212 double dt_beddef = t_final - m_t_last;
213
214 // compute time-averaged load and reset the accumulator
215 {
217 m_load.scale(1.0 / dt_beddef);
219 }
220
221 this->update_impl(m_load, m_t_last, dt_beddef);
222 // note: we don't know if a derived class modified m_topg in update_impl(), so we *do
223 // not* call m_topg.inc_state_counter() here -- it should be done in update_impl(), if
224 // necessary
225
226 m_t_last = t_final;
227
228 // Update m_uplift and m_topg_last
229 {
231 //! uplift = (m_topg - m_topg_last) / dt
232 m_uplift.scale(1.0 / dt_beddef);
233 }
235 }
236}
237
239
240 if (t < m_t_last) {
242 "time %f is less than the previous time %f",
243 t, m_t_last);
244 }
245
246 if (m_update_interval == 0.0) {
247 return {};
248 }
249
250 // Find the smallest time of the form m_t_last + k * m_update_interval that is greater
251 // than t
252 double k = std::ceil((t - m_t_last) / m_update_interval);
253
254 double t_next = m_t_last + k * m_update_interval;
255
256 double dt_max = m_update_interval;
257 if (t < t_next) {
258 dt_max = t_next - t;
259 }
260
261 if (dt_max < m_t_eps) {
262 dt_max = m_update_interval;
263 }
264
265 return MaxTimestep(dt_max, "bed_def");
266}
267
268/*!
269 * Apply a correction to the bed topography by reading "topg_delta" from `filename`.
270 */
271void BedDef::apply_topg_offset(const std::string &filename, array::Scalar &bed_topography) {
272
273 auto grid = bed_topography.grid();
274
275 array::Scalar topg_delta(grid, "topg_delta");
276 topg_delta.metadata(0).long_name("bed topography correction").units("meters");
277
278 topg_delta.regrid(filename, io::Default::Nil());
279
280 bed_topography.add(1.0, topg_delta);
281}
282
283double compute_load(double bed, double ice_thickness, double sea_level,
284 double ice_density, double ocean_density) {
285
286 double
287 ice_load = ice_thickness,
288 ocean_depth = std::max(sea_level - bed, 0.0),
289 ocean_load = (ocean_density / ice_density) * ocean_depth;
290
291 // this excludes the load of ice shelves
292 return ice_load > ocean_load ? ice_load : 0.0;
293}
294
295/*! Add the load on the bedrock in units of ice-equivalent thickness to `result`.
296 *
297 * Result:
298 *
299 * `result(i, j) += C * load(bed, ice_thickness, sea_level)`
300 */
301void accumulate_load(const array::Scalar &bed_elevation, const array::Scalar &ice_thickness,
302 const array::Scalar &sea_level_elevation, double C, array::Scalar &result) {
303
304 Config::ConstPtr config = result.grid()->ctx()->config();
305
306 const double ice_density = config->get_number("constants.ice.density"),
307 ocean_density = config->get_number("constants.sea_water.density");
308
309 array::AccessScope list{ &bed_elevation, &ice_thickness, &sea_level_elevation, &result };
310
311 for (auto p = result.grid()->points(); p; p.next()) {
312 const int i = p.i(), j = p.j();
313
314 result(i, j) += C * compute_load(bed_elevation(i, j), ice_thickness(i, j), sea_level_elevation(i, j),
315 ice_density, ocean_density);
316 }
317}
318
319} // end of namespace bed
320} // end of namespace pism
const Time & time() const
Definition Component.cc:109
std::shared_ptr< const Grid > grid() const
Definition Component.cc:105
const Config::ConstPtr m_config
configuration database used by this component
Definition Component.hh:158
const Logger::ConstPtr m_log
logger (for easy access)
Definition Component.hh:162
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition Component.hh:156
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
Definition Component.cc:159
A class defining a common interface for most PISM sub-models.
Definition Component.hh:118
std::shared_ptr< const Config > ConstPtr
static Ptr wrap(const T &input)
void read_variable(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, double *ip) const
Definition File.cc:699
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
Definition File.cc:378
void write_variable(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const double *op) const
Definition File.cc:712
void define_variable(const std::string &name, io::Type nctype, const std::vector< std::string > &dims) const
Define a variable.
Definition File.cc:543
void write_attribute(const std::string &var_name, const std::string &att_name, io::Type nctype, const std::vector< double > &values) const
Write a multiple-valued double attribute.
Definition File.cc:590
High-level PISM I/O class.
Definition File.hh:55
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
double current() const
Current time, in seconds.
Definition Time.cc:461
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
VariableMetadata & standard_name(const std::string &input)
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 add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:65
void read(const std::string &filename, unsigned int time)
Definition Array.cc:731
void define(const File &file, io::Type default_type) const
Define variables corresponding to an Array in a file opened using file.
Definition Array.cc:463
void write(const std::string &filename) const
Definition Array.cc:722
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:224
std::shared_ptr< const Grid > grid() const
Definition Array.cc:131
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
std::string m_time_name
Name of the variable used to store the last update time.
Definition BedDef.hh:96
array::Scalar m_load_accumulator
Definition BedDef.hh:84
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
Definition BedDef.cc:95
virtual DiagnosticList diagnostics_impl() const
Definition BedDef.cc:103
array::Scalar m_topg_last
bed elevation at the time of the last update
Definition BedDef.hh:81
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
Definition BedDef.cc:79
virtual void update_impl(const array::Scalar &load, double t, double dt)=0
void init(const InputOptions &opts, const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation)
Definition BedDef.cc:112
virtual MaxTimestep max_timestep_impl(double t) const
Definition BedDef.cc:238
void update(const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation, double t, double dt)
Definition BedDef.cc:198
double m_update_interval
Update interval in seconds.
Definition BedDef.hh:92
void bootstrap(const array::Scalar &bed_elevation, const array::Scalar &bed_uplift, const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation)
Initialize using provided bed elevation and uplift.
Definition BedDef.cc:179
array::Scalar2 m_topg
current bed elevation
Definition BedDef.hh:78
virtual void bootstrap_impl(const array::Scalar &bed_elevation, const array::Scalar &bed_uplift, const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation)=0
Definition BedDef.cc:191
std::string m_model_name
Definition BedDef.hh:98
BedDef(std::shared_ptr< const Grid > g, const std::string &model_name)
Definition BedDef.cc:32
array::Scalar m_uplift
bed uplift rate
Definition BedDef.hh:87
const array::Scalar & uplift() const
Definition BedDef.cc:75
const array::Scalar & bed_elevation() const
Definition BedDef.cc:71
virtual void init_impl(const InputOptions &opts, const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation)=0
double m_t_last
time of the last bed deformation update
Definition BedDef.hh:90
static void apply_topg_offset(const std::string &filename, array::Scalar &bed_topography)
Definition BedDef.cc:271
array::Scalar m_load
Definition BedDef.hh:83
double m_t_eps
Temporal resolution to use when checking whether it's time to update.
Definition BedDef.hh:94
static Default Nil()
Definition IO_Flags.hh:93
#define PISM_ERROR_LOCATION
void accumulate_load(const array::Scalar &bed_elevation, const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation, double C, array::Scalar &result)
Definition BedDef.cc:301
double compute_load(double bed, double ice_thickness, double sea_level, double ice_density, double ocean_density)
Definition BedDef.cc:283
@ PISM_NETCDF3
Definition IO_Flags.hh:57
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:68
@ PISM_DOUBLE
Definition IO_Flags.hh:52
@ INIT_BOOTSTRAP
Definition Component.hh:56
@ INIT_OTHER
Definition Component.hh:56
@ INIT_RESTART
Definition Component.hh:56
std::map< std::string, Diagnostic::Ptr > DiagnosticList
static const double k
Definition exactTestP.cc:42
static std::string calendar(const File *input_file, const Config &config, const Logger &log)
Definition Time.cc:146
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