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
frontretreat.cc
Go to the documentation of this file.
1// Copyright (C) 2004--2021, 2023 Torsten Albrecht 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#include "pism/icemodel/IceModel.hh"
20
21#include "pism/util/ConfigInterface.hh"
22#include "pism/util/Grid.hh"
23
24#include "pism/frontretreat/FrontRetreat.hh"
25#include "pism/frontretreat/calving/CalvingAtThickness.hh"
26#include "pism/frontretreat/calving/EigenCalving.hh"
27#include "pism/frontretreat/calving/FloatKill.hh"
28#include "pism/frontretreat/calving/HayhurstCalving.hh"
29#include "pism/frontretreat/calving/vonMisesCalving.hh"
30
31#include "pism/energy/EnergyModel.hh"
32#include "pism/coupler/FrontalMelt.hh"
33#include "pism/stressbalance/ShallowStressBalance.hh"
34#include "pism/hydrology/Hydrology.hh"
35#include "pism/frontretreat/util/remove_narrow_tongues.hh"
36#include "pism/frontretreat/PrescribedRetreat.hh"
37#include "pism/util/ScalarForcing.hh"
38#include "pism/util/connected_components/label_components.hh"
39
40namespace pism {
41
43
44 array::AccessScope list{ &cell_type, &result };
45
46 auto grid = cell_type.grid();
47
48 const int water = 1;
49 const int water_reachable_from_domain_edge = 2;
50
51 // assume that ice-free ocean points at the edge of the domain belong to the "global
52 // ocean"
53 for (auto p = grid->points(); p; p.next()) {
54 const int i = p.i(), j = p.j();
55
56 if (cell_type.ice_free_ocean(i, j)) {
57 result(i, j) = water;
58
59 if (grid::domain_edge(*grid, i, j)) {
60 result(i, j) = water_reachable_from_domain_edge;
61 }
62 } else {
63 result(i, j) = 0.0;
64 }
65 }
66
67 connected_components::label_isolated(result, water_reachable_from_domain_edge);
68
69 // now `result` contains ones in "ice free ocean" cells that are not connected to the edge
70 // of the domain and zeros elsewhere
71
72 // create a mask that contains ones at "ice free ocean" locations connected to the edge
73 // of the domain and zeros elsewhere:
74 for (auto p = grid->points(); p; p.next()) {
75 const int i = p.i(), j = p.j();
76
77 if (cell_type.ice_free_ocean(i, j) and result.as_int(i, j) == 0) {
78 result(i, j) = 1;
79 } else {
80 result(i, j) = 0;
81 }
82 }
83
84 result.update_ghosts();
85}
86
88
89 bool retreat_rate_based_calving = m_eigen_calving or m_vonmises_calving or m_hayhurst_calving;
90 bool calving_is_active =
91 retreat_rate_based_calving or m_float_kill_calving or m_thickness_threshold_calving;
92 bool frontal_melt_only_open_ocean = m_config->get_flag("frontal_melt.open_ocean_margins_only");
93
94 auto &open_ocean_mask = *m_work2d[3];
95 if (calving_is_active or (m_frontal_melt and frontal_melt_only_open_ocean)) {
97 } else {
98 open_ocean_mask.set(1.0);
99 }
100
101 // compute retreat rates due to eigencalving, von Mises calving, Hayhurst calving,
102 // and frontal melt.
103 // We do this first to make sure that all three mechanisms use the same ice geometry.
104 {
105 if (m_eigen_calving) {
107 m_stress_balance->shallow()->velocity());
108 }
109
110 if (m_hayhurst_calving) {
115 }
116
117 if (m_vonmises_calving) {
118 // FIXME: consider computing vertically-averaged hardness here and providing that
119 // instead of using ice thickness and enthalpy.
122 m_stress_balance->shallow()->velocity(),
123 m_energy_model->enthalpy());
124 }
125
126 if (m_frontal_melt) {
127 array::Scalar &flux_magnitude = *m_work2d[0];
128
129 compute_magnitude(m_subglacial_hydrology->flux(), flux_magnitude);
130
131 FrontalMeltInputs inputs;
132
133 inputs.geometry = &m_geometry;
134 inputs.subglacial_water_flux = &flux_magnitude;
135
136 m_frontal_melt->update(inputs, m_time->current(), m_dt);
137 }
138 }
139
141 &old_H = *m_work2d[0],
142 &old_Href = *m_work2d[1];
143
144 // frontal melt
145 if (m_frontal_melt) {
146 assert(m_front_retreat);
147
149 old_Href.copy_from(m_geometry.ice_area_specific_volume);
150
151 array::Scalar &retreat_rate = *m_work2d[2];
152 retreat_rate.copy_from(m_frontal_melt->retreat_rate());
153
154 if (frontal_melt_only_open_ocean) {
155 array::AccessScope list{ &retreat_rate, &open_ocean_mask };
156
157 for (Points p(*m_grid); p; p.next()) {
158 const int i = p.i(), j = p.j();
159
160 if (open_ocean_mask(i, j) < 0.5) {
161 retreat_rate(i, j) = 0.0;
162 }
163 }
164 }
165
166 // apply the frontal melt rate
168 retreat_rate,
171 bool add_values = false;
174 old_H, old_Href,
175 add_values,
177 } else {
179 }
180
181 // calving
182 if (calving_is_active) {
183
185 old_Href.copy_from(m_geometry.ice_area_specific_volume);
186
187 // retreat-rate-based calving parameterizations:
188 if (retreat_rate_based_calving) {
189 assert(m_front_retreat);
190
191 array::Scalar &retreat_rate = *m_work2d[2];
192 retreat_rate.set(0.0);
193
194 if (m_eigen_calving) {
195 retreat_rate.add(1.0, m_eigen_calving->calving_rate());
196 }
197
198 if (m_hayhurst_calving) {
199 retreat_rate.add(1.0, m_hayhurst_calving->calving_rate());
200 }
201
202 if (m_vonmises_calving) {
203 retreat_rate.add(1.0, m_vonmises_calving->calving_rate());
204 }
205
207 double T = m_time->current() + 0.5 * m_dt;
208 retreat_rate.scale(m_calving_rate_factor->value(T));
209 }
210
211 // modify the retreat rate to avoid calving into "holes" in ice shelves that are not
212 // connected to the open ocean
213 {
214 array::AccessScope list{ &open_ocean_mask, &retreat_rate };
215
216 for (Points p(*m_grid); p; p.next()) {
217 const int i = p.i(), j = p.j();
218
219 if (open_ocean_mask(i, j) < 0.5) {
220 retreat_rate(i, j) = 0.0;
221 }
222 }
223 }
224
226 retreat_rate,
229
230 auto thickness_threshold = m_config->get_number("stress_balance.ice_free_thickness_standard");
231
232 m_geometry.ensure_consistency(thickness_threshold);
233
236
237 m_geometry.ensure_consistency(thickness_threshold);
238 }
239 }
240
241 // calving using local geometry (usually calving one grid cell per time step)
242 {
243 auto &modified_cell_type = *m_work2d[2];
244
245 // create a modified cell type mask to avoid calving into holes in ice shelves that
246 // are not connected to the open ocean
247 {
248 const auto &cell_type = m_geometry.cell_type;
249
250 array::AccessScope list{ &modified_cell_type, &cell_type, &open_ocean_mask };
251
252 for (Points p(*m_grid); p; p.next()) {
253 const int i = p.i(), j = p.j();
254
255 if (cell_type.ice_free_ocean(i, j) and open_ocean_mask(i, j) < 0.5) {
256 // This modification will ensure that cells next to *these* ice free ocean
257 // cells will not be considered "marginal" and so thickness threshold and
258 // float-kill parameterizations will not apply.
259 modified_cell_type(i, j) = MASK_UNKNOWN;
260 } else {
261 modified_cell_type(i, j) = cell_type(i, j);
262 }
263 }
264 }
265
267 m_float_kill_calving->update(modified_cell_type, m_geometry.ice_thickness);
268 }
269
271 m_thickness_threshold_calving->update(m_time->current(), m_dt, modified_cell_type,
273 }
274 }
275
276 bool add_values = false;
279 old_H, old_Href,
280 add_values,
282 } else {
284 }
285
286 // prescribed retreat
287
290 old_Href.copy_from(m_geometry.ice_area_specific_volume);
291
292 m_prescribed_retreat->update(m_time->current(), m_dt,
295
296 bool add_values = false;
299 old_H, old_Href,
300 add_values,
302
303 } else {
305 }
306
307 // Changes above may create icebergs; here we remove them and account for additional
308 // mass losses.
309 {
311 old_Href.copy_from(m_geometry.ice_area_specific_volume);
312
314
315 bool add_values = true;
318 old_H, old_Href,
319 add_values,
321 }
322}
323
324/**
325 * Compute the change in ice geometry from "old" to "current".
326 *
327 * Units: ice equivalent meters.
328 *
329 * @param thickness current ice thickness
330 * @param Href current "reference ice thickness"
331 * @param thickness_old old ice thickness
332 * @param Href_old old "reference ice thickness"
333 * @param[in] add_values if `true`, add computed values to `output`, otherwise
334 * overwrite them
335 * @param[in,out] output computed change
336 */
338 const array::Scalar &Href,
339 const array::Scalar &thickness_old,
340 const array::Scalar &Href_old,
341 bool add_values,
342 array::Scalar &output) {
343
344 array::AccessScope list{&thickness, &thickness_old,
345 &Href, &Href_old, &output};
346
347 for (auto p = m_grid->points(); p; p.next()) {
348 const int i = p.i(), j = p.j();
349
350 const double
351 H_old = thickness_old(i, j) + Href_old(i, j),
352 H_new = thickness(i, j) + Href(i, j),
353 change = H_new - H_old;
354
355 if (add_values) {
356 output(i, j) += change;
357 } else {
358 output(i, j) = change;
359 }
360 }
361}
362
363} // end of namespace pism
const Geometry * geometry
const array::Scalar * subglacial_water_flux
array::Scalar1 sea_level_elevation
Definition Geometry.hh:48
void ensure_consistency(double ice_free_thickness_threshold)
Definition Geometry.cc:114
array::Scalar1 ice_area_specific_volume
Definition Geometry.hh:52
array::CellType2 cell_type
Definition Geometry.hh:55
array::Scalar2 ice_thickness
Definition Geometry.hh:51
array::Scalar2 bed_elevation
Definition Geometry.hh:47
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
void compute_geometry_change(const array::Scalar &thickness, const array::Scalar &Href, const array::Scalar &thickness_old, const array::Scalar &Href_old, bool add_values, array::Scalar &output)
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
Definition IceModel.hh:395
ThicknessChanges m_thickness_change
Definition IceModel.hh:410
const Time::Ptr m_time
Time manager.
Definition IceModel.hh:246
Geometry m_geometry
Definition IceModel.hh:288
std::shared_ptr< frontalmelt::FrontalMelt > m_frontal_melt
Definition IceModel.hh:281
std::shared_ptr< Grid > grid() const
Return the grid used by this model.
Definition utilities.cc:121
virtual void front_retreat_step()
std::shared_ptr< calving::EigenCalving > m_eigen_calving
Definition IceModel.hh:268
std::unique_ptr< ScalarForcing > m_calving_rate_factor
Definition IceModel.hh:275
std::vector< std::shared_ptr< array::Scalar2 > > m_work2d
Definition IceModel.hh:393
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
std::shared_ptr< PrescribedRetreat > m_prescribed_retreat
Definition IceModel.hh:271
std::shared_ptr< calving::HayhurstCalving > m_hayhurst_calving
Definition IceModel.hh:269
Config::Ptr m_config
Configuration flags and parameters.
Definition IceModel.hh:238
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
Definition IceModel.hh:307
std::unique_ptr< hydrology::Hydrology > m_subglacial_hydrology
Definition IceModel.hh:254
std::shared_ptr< calving::vonMisesCalving > m_vonmises_calving
Definition IceModel.hh:270
double m_dt
mass continuity time step, s
Definition IceModel.hh:311
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
void identify_open_ocean(const array::CellType &cell_type, array::Scalar1 &result)
std::shared_ptr< FrontRetreat > m_front_retreat
Definition IceModel.hh:277
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 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 update_ghosts()
Updates ghost points.
Definition Array.cc:615
bool ice_free_ocean(int i, int j) const
Definition CellType.hh:58
"Cell type" mask. Adds convenience methods to array::Scalar.
Definition CellType.hh:30
int as_int(int i, int j) const
Definition Scalar.hh:45
void label_isolated(array::Scalar1 &mask, int reachable)
bool domain_edge(const Grid &grid, int i, int j)
Definition Grid.hh:409
void remove_narrow_tongues(const Geometry &geometry, array::Scalar &ice_thickness)
@ MASK_UNKNOWN
Definition Mask.hh:31