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
NoGLRetreat.cc
Go to the documentation of this file.
1/* Copyright (C) 2021, 2022, 2023, 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
20#include "pism/coupler/surface/NoGLRetreat.hh"
21
22#include "pism/geometry/Geometry.hh"
23#include "pism/util/Diagnostic.hh"
24#include "pism/util/pism_utilities.hh" // combine()
25
26namespace pism {
27namespace surface {
28
29NoGLRetreat::NoGLRetreat(std::shared_ptr<const Grid> grid,
30 std::shared_ptr<SurfaceModel> input)
31 : SurfaceModel(grid, input),
32 m_smb_adjustment(grid, "smb_adjustment"),
33 m_min_ice_thickness(grid, "minimum_ice_thickness") {
34
35 m_smb_adjustment.metadata()["units"] = "kg m^-2 s^-1";
36
41}
42
43void NoGLRetreat::init_impl(const Geometry &geometry) {
44 m_input_model->init(geometry);
45
46 m_log->message(2,
47 "* Initializing a SMB adjustment preventing grounding line retreat...\n");
48
49 const auto &ice_thickness = geometry.ice_thickness;
50 const auto &sea_level = geometry.sea_level_elevation;
51 const auto &bed = geometry.bed_elevation;
52
53 double rho_i = m_config->get_number("constants.ice.density");
54 double rho_w = m_config->get_number("constants.sea_water.density");
55 double eps = m_config->get_number("geometry.ice_free_thickness_standard");
56
57 array::AccessScope list{&sea_level, &bed, &ice_thickness,
59
60 for (auto p = m_grid->points(); p; p.next()) {
61 const int i = p.i(), j = p.j();
62
63 double H_min = 0.0;
64 if (sea_level(i, j) > bed(i, j)) {
65 // compute the minimum grounded ice thickess
66 H_min = (sea_level(i, j) - bed(i, j)) * (rho_w / rho_i) + eps;
67
68 // exclude areas where the ice thickness is below this threshold (i.e. the area is
69 // ice free or covered by floating ice)
70 if (ice_thickness(i, j) < H_min) {
71 H_min = 0.0;
72 }
73 }
74
75 m_min_ice_thickness(i, j) = H_min;
76
77 }
78}
79
80void NoGLRetreat::update_impl(const Geometry &geometry, double t, double dt) {
81
82 m_input_model->update(geometry, t, dt);
83
84 const auto &mass_flux = m_input_model->mass_flux();
85 const auto &ice_thickness = geometry.ice_thickness;
86
87 double rho_i = m_config->get_number("constants.ice.density");
88
90 &ice_thickness,
91 m_mass_flux.get(),
94
95 for (auto p = m_grid->points(); p; p.next()) {
96 const int i = p.i(), j = p.j();
97
98 double SMB_old = mass_flux(i, j);
99 double SMB_new = SMB_old;
100
101 // convert from kg/(m^2 s) to m:
102 double H_min = m_min_ice_thickness(i, j);
103 double H = ice_thickness(i, j);
104 double dH = mass_flux(i, j) * (dt / rho_i);
105 double H_new = H + dH;
106
107 if (H_min > 0.0 and H_new < H_min) {
108 SMB_new = (H_min - H) * (rho_i / dt);
109 }
110
111 (*m_mass_flux)(i, j) = SMB_new;
112 m_smb_adjustment(i, j) = SMB_new - SMB_old;
113 }
114
118}
119
121 return *m_mass_flux;
122}
123
127
129 return *m_melt;
130}
131
133 return *m_runoff;
134}
135
139
140namespace diagnostics {
141
142class SMBAdjustment : public DiagAverageRate<NoGLRetreat>
143{
144public:
147 "no_gl_retreat_smb_adjustment",
148 RATE)
149 {
150 m_accumulator.metadata()["units"] = "kg m^-2";
151
152 m_vars = { { m_sys, "no_gl_retreat_smb_adjustment" } };
153 m_vars[0]
154 .long_name("SMB adjustment needed to maintain grounded ice extent")
155 .units("kg m^-2 s^-1")
156 .output_units("kg m^-2 year^-1");
157 m_vars[0]["cell_methods"] = "time: mean";
158 m_vars[0]["_FillValue"] = {to_internal(m_fill_value)};
159 }
160
161protected:
163 return model->smb_adjustment();
164 }
165};
166
167} // end of namespace diagnostics
168
170 return combine({{"no_gl_retreat_smb_adjustment",
172 m_input_model->diagnostics());
173}
174
175} // end of namespace surface
176} // end of namespace pism
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
const Model * model
double m_fill_value
fill value (used often enough to justify storing it)
const units::System::Ptr m_sys
the unit system
double to_internal(double x) const
Definition Diagnostic.cc:59
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
std::shared_ptr< Diagnostic > Ptr
Definition Diagnostic.hh:65
array::Scalar1 sea_level_elevation
Definition Geometry.hh:48
array::Scalar2 ice_thickness
Definition Geometry.hh:51
array::Scalar2 bed_elevation
Definition Geometry.hh:47
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
VariableMetadata & output_units(const std::string &input)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition Array.cc:476
DiagnosticList diagnostics_impl() const
array::Scalar m_min_ice_thickness
std::shared_ptr< array::Scalar > m_mass_flux
NoGLRetreat(std::shared_ptr< const Grid > g, std::shared_ptr< SurfaceModel > input)
const array::Scalar & runoff_impl() const
const array::Scalar & melt_impl() const
void update_impl(const Geometry &geometry, double t, double dt)
const array::Scalar & accumulation_impl() const
const array::Scalar & mass_flux_impl() const
array::Scalar m_smb_adjustment
const array::Scalar & smb_adjustment() const
void init_impl(const Geometry &geometry)
static std::shared_ptr< array::Scalar > allocate_runoff(std::shared_ptr< const Grid > grid)
static std::shared_ptr< array::Scalar > allocate_mass_flux(std::shared_ptr< const Grid > grid)
void dummy_accumulation(const array::Scalar &smb, array::Scalar &result)
std::shared_ptr< array::Scalar > m_melt
const array::Scalar & mass_flux() const
static std::shared_ptr< array::Scalar > allocate_accumulation(std::shared_ptr< const Grid > grid)
static std::shared_ptr< array::Scalar > allocate_melt(std::shared_ptr< const Grid > grid)
std::shared_ptr< array::Scalar > m_runoff
void dummy_melt(const array::Scalar &smb, array::Scalar &result)
std::shared_ptr< SurfaceModel > m_input_model
std::shared_ptr< array::Scalar > m_accumulation
void dummy_runoff(const array::Scalar &smb, array::Scalar &result)
The interface of PISM's surface models.
std::map< std::string, Diagnostic::Ptr > DiagnosticList
T combine(const T &a, const T &b)