PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
BedDef.cc
Go to the documentation of this file.
1// Copyright (C) 2010--2025 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/Config.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#include "pism/util/Logger.hh"
28#include "pism/util/io/IO_Flags.hh"
29#include "pism/util/io/io_helpers.hh"
30
31
32namespace pism {
33namespace bed {
34
35BedDef::BedDef(std::shared_ptr<const Grid> grid, const std::string &model_name)
36 : Component(grid),
37 m_topg(m_grid, "topg"),
38 m_topg_last(m_grid, "topg"),
39 m_load(grid, "bed_def_load"),
40 m_load_accumulator(grid, "bed_def_load_accumulator"),
41 m_uplift(m_grid, "dbdt"),
42 m_t_last(time().current()),
43 m_time_name(time().variable_name() + "_bed_deformation"),
44 m_model_name(model_name)
45{
46 m_update_interval = m_config->get_number("bed_deformation.update_interval", "seconds");
47 m_t_eps = m_config->get_number("time_stepping.resolution", "seconds");
48
50 .long_name("bedrock surface elevation")
51 .units("m")
52 .standard_name("bedrock_altitude");
53
55 .long_name("bedrock surface elevation after the previous update (used to compute uplift)")
56 .units("m")
57 .standard_name("bedrock_altitude");
58
60 .long_name("load on the bed expressed as ice-equivalent thickness")
61 .units("m");
62 m_load.set(0.0);
63
65 .long_name("accumulated load on the bed expressed as the time integral of ice-equivalent thickness")
66 .units("m s");
67
69 .long_name("bedrock uplift rate")
70 .units("m s^-1")
71 .standard_name("tendency_of_bedrock_altitude");
72}
73
75 return m_topg;
76}
77
79 return m_uplift;
80}
81
82std::set<VariableMetadata> BedDef::state_impl() const {
83 auto variables = array::metadata({ &m_uplift, &m_topg, &m_load_accumulator });
84
86 T.long_name("time of the last update of the bed deformation model")
87 .units(time().units())
88 .set_time_dependent(true);
89 T["calendar"] = time().calendar();
90
91 variables.insert(T);
92
93 return variables;
94}
95
96void BedDef::write_state_impl(const OutputFile &output) const {
97 m_uplift.write(output);
98 m_topg.write(output);
100
101 auto t_length = output.time_dimension_length();
102 auto t_start = t_length > 0 ? t_length - 1 : 0;
103
104 output.write_timeseries(m_time_name, { t_start }, { 1 }, { m_t_last });
105}
106
108 DiagnosticList result;
109 result = { { "dbdt", Diagnostic::wrap(m_uplift) },
110 { "topg", Diagnostic::wrap(m_topg) },
111 { "bed_def_load", Diagnostic::wrap(m_load) } };
112
113 return result;
114}
115
116void BedDef::init(const InputOptions &opts, const array::Scalar &ice_thickness,
117 const array::Scalar &sea_level_elevation) {
118
119 m_log->message(2, "* Initializing the %s bed deformation model...\n",
120 m_model_name.c_str());
121
122 m_t_last = time().current();
123 if (opts.type == INIT_RESTART or opts.type == INIT_BOOTSTRAP) {
124 File input_file(m_grid->com, opts.filename, io::PISM_NETCDF3, io::PISM_READONLY);
125
126 if (input_file.variable_exists(m_time_name)) {
127 auto t_length = input_file.nrecords(m_time_name, "", m_sys);
128 auto t_last = t_length > 0 ? t_length - 1 : 0;
129
130 auto t =
131 io::read_timeseries_variable(input_file, m_time_name, time().units(), m_sys, t_last, 1);
132 m_t_last = t[0];
133 }
134 }
135
136 {
137 switch (opts.type) {
138 case INIT_RESTART:
139 // read bed elevation and uplift rate from file
140 m_log->message(2, " reading bed topography and uplift from %s ... \n",
141 opts.filename.c_str());
142 // re-starting
143 m_topg.read(opts.filename, opts.record); // fails if not found!
144 m_uplift.read(opts.filename, opts.record); // fails if not found!
146 break;
147 case INIT_BOOTSTRAP:
148 // bootstrapping
149 m_topg.regrid(opts.filename, io::Default(m_config->get_number("bootstrapping.defaults.bed")));
151 io::Default(m_config->get_number("bootstrapping.defaults.uplift")));
153 break;
154 case INIT_OTHER:
155 default: {
156 // do nothing
157 }
158 }
159
160 // process -regrid_file and -regrid_vars
161 regrid("bed deformation", m_topg, REGRID_WITHOUT_REGRID_VARS);
163 // uplift is not a part of the model state, but the user may want to take it from a -regrid_file
164 // during bootstrapping
165 regrid("bed deformation", m_uplift, REGRID_WITHOUT_REGRID_VARS);
166
167 auto uplift_file = m_config->get_string("bed_deformation.bed_uplift_file");
168 if (not uplift_file.empty()) {
169 m_log->message(2, " reading bed uplift from %s ... \n", uplift_file.c_str());
170 m_uplift.regrid(uplift_file, io::Default::Nil());
171 }
172
173 auto correction_file = m_config->get_string("bed_deformation.bed_topography_delta_file");
174 if (not correction_file.empty()) {
175 m_log->message(2, " Adding a bed topography correction read in from '%s'...\n",
176 correction_file.c_str());
177 apply_topg_offset(correction_file, m_topg);
178 }
179 }
180
181 this->init_impl(opts, ice_thickness, sea_level_elevation);
182
183 // this should be the last thing we do
185}
186
187//! Initialize using provided bed elevation and uplift.
188void BedDef::bootstrap(const array::Scalar &bed_elevation, const array::Scalar &bed_uplift,
189 const array::Scalar &ice_thickness,
190 const array::Scalar &sea_level_elevation) {
191 m_t_last = time().current();
192
194 m_uplift.copy_from(bed_uplift);
196
197 this->bootstrap_impl(bed_elevation, bed_uplift, ice_thickness, sea_level_elevation);
198}
199
200void BedDef::bootstrap_impl(const array::Scalar & /*bed_elevation*/,
201 const array::Scalar & /*bed_uplift*/,
202 const array::Scalar & /*ice_thickness*/,
203 const array::Scalar & /*sea_level_elevation*/) {
204 // empty
205}
206
207void BedDef::update(const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation,
208 double t, double dt) {
209
210 double t_final = t + dt;
211
212 if (t_final < m_t_last) {
213 throw RuntimeError(PISM_ERROR_LOCATION, "cannot go back in time");
214 }
215
216 accumulate_load(m_topg_last, ice_thickness, sea_level_elevation, dt, m_load_accumulator);
217
218 double t_next = m_update_interval > 0.0 ? m_t_last + m_update_interval : t_final;
219 if (std::abs(t_next - t_final) < m_t_eps) { // reached the next update time
220
221 double dt_beddef = t_final - m_t_last;
222
223 // compute time-averaged load and reset the accumulator
224 {
226 m_load.scale(1.0 / dt_beddef);
228 }
229
230 this->update_impl(m_load, m_t_last, dt_beddef);
231 // note: we don't know if a derived class modified m_topg in update_impl(), so we *do
232 // not* call m_topg.inc_state_counter() here -- it should be done in update_impl(), if
233 // necessary
234
235 m_t_last = t_final;
236
237 // Update m_uplift and m_topg_last
238 {
240 //! uplift = (m_topg - m_topg_last) / dt
241 m_uplift.scale(1.0 / dt_beddef);
242 }
244 }
245}
246
248
249 if (t < m_t_last) {
251 "time %f is less than the previous time %f",
252 t, m_t_last);
253 }
254
255 if (m_update_interval == 0.0) {
256 return {};
257 }
258
259 // Find the smallest time of the form m_t_last + k * m_update_interval that is greater
260 // than t
261 double k = std::ceil((t - m_t_last) / m_update_interval);
262
263 double t_next = m_t_last + k * m_update_interval;
264
265 double dt_max = m_update_interval;
266 if (t < t_next) {
267 dt_max = t_next - t;
268 }
269
270 if (dt_max < m_t_eps) {
271 dt_max = m_update_interval;
272 }
273
274 return MaxTimestep(dt_max, "bed_def");
275}
276
277/*!
278 * Apply a correction to the bed topography by reading "topg_delta" from `filename`.
279 */
280void BedDef::apply_topg_offset(const std::string &filename, array::Scalar &bed_topography) {
281
282 auto grid = bed_topography.grid();
283
284 array::Scalar topg_delta(grid, "topg_delta");
285 topg_delta.metadata(0).long_name("bed topography correction").units("meters");
286
287 topg_delta.regrid(filename, io::Default::Nil());
288
289 bed_topography.add(1.0, topg_delta);
290}
291
292double compute_load(double bed, double ice_thickness, double sea_level,
293 double ice_density, double ocean_density) {
294
295 double
296 ice_load = ice_thickness,
297 ocean_depth = std::max(sea_level - bed, 0.0),
298 ocean_load = (ocean_density / ice_density) * ocean_depth;
299
300 // this excludes the load of ice shelves
301 return ice_load > ocean_load ? ice_load : 0.0;
302}
303
304/*! Add the load on the bedrock in units of ice-equivalent thickness to `result`.
305 *
306 * Result:
307 *
308 * `result(i, j) += C * load(bed, ice_thickness, sea_level)`
309 */
310void accumulate_load(const array::Scalar &bed_elevation, const array::Scalar &ice_thickness,
311 const array::Scalar &sea_level_elevation, double C, array::Scalar &result) {
312
313 auto config = result.grid()->ctx()->config();
314
315 const double ice_density = config->get_number("constants.ice.density"),
316 ocean_density = config->get_number("constants.sea_water.density");
317
318 array::AccessScope list{ &bed_elevation, &ice_thickness, &sea_level_elevation, &result };
319
320 for (auto p : result.grid()->points()) {
321 const int i = p.i(), j = p.j();
322
323 result(i, j) += C * compute_load(bed_elevation(i, j), ice_thickness(i, j), sea_level_elevation(i, j),
324 ice_density, ocean_density);
325 }
326}
327
328} // end of namespace bed
329} // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition Component.hh:162
const Time & time() const
Definition Component.cc:111
std::shared_ptr< const Grid > grid() const
Definition Component.cc:107
std::shared_ptr< const Config > m_config
configuration database used by this component
Definition Component.hh:160
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition Component.hh:158
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
Definition Component.cc:152
std::shared_ptr< const Logger > m_log
logger (for easy access)
Definition Component.hh:164
A class defining a common interface for most PISM sub-models.
Definition Component.hh:118
static Ptr wrap(const T &input)
unsigned int nrecords() const
Get the number of records. Uses the length of an unlimited dimension.
Definition File.cc:280
bool variable_exists(const std::string &short_name) const
Checks if a variable exists.
Definition File.cc:378
High-level PISM I/O class.
Definition File.hh:57
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
unsigned int time_dimension_length() const
Definition OutputFile.cc:86
void write_timeseries(const std::string &variable_name, const std::vector< unsigned int > &start, const std::vector< unsigned int > &count, const std::vector< double > &input) const
Definition OutputFile.cc:61
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
std::string calendar() const
Returns the calendar string.
Definition Time.cc:506
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:66
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:101
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:93
void read(const std::string &filename, unsigned int time)
Definition Array.cc:753
void write(const OutputFile &file) const
Definition Array.cc:859
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:227
std::shared_ptr< const Grid > grid() const
Definition Array.cc:134
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
virtual DiagnosticList spatial_diagnostics_impl() const
Definition BedDef.cc:107
std::string m_time_name
Name of the variable used to store the last update time.
Definition BedDef.hh:97
array::Scalar m_load_accumulator
Definition BedDef.hh:84
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
Definition BedDef.cc:96
array::Scalar m_topg_last
bed elevation at the time of the last update
Definition BedDef.hh:81
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:116
virtual MaxTimestep max_timestep_impl(double t) const
Definition BedDef.cc:247
void update(const array::Scalar &ice_thickness, const array::Scalar &sea_level_elevation, double t, double dt)
Definition BedDef.cc:207
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:188
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:200
std::string m_model_name
Definition BedDef.hh:100
BedDef(std::shared_ptr< const Grid > g, const std::string &model_name)
Definition BedDef.cc:35
array::Scalar m_uplift
bed uplift rate
Definition BedDef.hh:87
const array::Scalar & uplift() const
Definition BedDef.cc:78
const array::Scalar & bed_elevation() const
Definition BedDef.cc:74
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:280
array::Scalar m_load
Definition BedDef.hh:83
virtual std::set< VariableMetadata > state_impl() const
Definition BedDef.cc:82
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:94
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
Definition Array.cc:1244
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:310
double compute_load(double bed, double ice_thickness, double sea_level, double ice_density, double ocean_density)
Definition BedDef.cc:292
std::vector< double > read_timeseries_variable(const File &file, const std::string &variable_name, const std::string &units, std::shared_ptr< units::System > unit_system, size_t start, size_t count)
@ PISM_NETCDF3
Definition IO_Flags.hh:58
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:69
@ 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
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