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
Elevation.cc
Go to the documentation of this file.
1// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2022, 2023, 2024 Andy Aschwanden 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/coupler/surface/Elevation.hh"
20
21#include "pism/util/Grid.hh"
22#include "pism/util/ConfigInterface.hh"
23#include "pism/util/error_handling.hh"
24#include "pism/util/pism_options.hh"
25#include "pism/util/MaxTimestep.hh"
26#include "pism/geometry/Geometry.hh"
27
28namespace pism {
29namespace surface {
30
31///// Elevation-dependent temperature and surface mass balance.
32Elevation::Elevation(std::shared_ptr<const Grid> grid, std::shared_ptr<atmosphere::AtmosphereModel> input)
33 : SurfaceModel(grid) {
34 (void) input;
35
38}
39
40void Elevation::init_impl(const Geometry &geometry) {
41 (void) geometry;
42
43 bool limits_set = false;
44
45 m_log->message(2,
46 "* Initializing the constant-in-time surface processes model Elevation. Setting...\n");
47
48 {
49 // ice surface temperature
50 {
51 m_T_min = m_config->get_number("surface.elevation_dependent.T_min", "kelvin");
52 m_T_max = m_config->get_number("surface.elevation_dependent.T_max", "kelvin");
53 m_z_T_min = m_config->get_number("surface.elevation_dependent.z_T_min");
54 m_z_T_max = m_config->get_number("surface.elevation_dependent.z_T_max");
55 }
56
57 // climatic mass balance
58 {
59 m_M_min = m_config->get_number("surface.elevation_dependent.M_min", "m s^-1");
60 m_M_max = m_config->get_number("surface.elevation_dependent.M_max", "m s^-1");
61 m_z_M_min = m_config->get_number("surface.elevation_dependent.z_M_min");
62 m_z_ELA = m_config->get_number("surface.elevation_dependent.z_ELA");
63 m_z_M_max = m_config->get_number("surface.elevation_dependent.z_M_max");
64 }
65
66 // limits of the climatic mass balance
67 {
68 m_M_limit_min = m_config->get_number("surface.elevation_dependent.M_limit_min", "m s^-1");
69 m_M_limit_max = m_config->get_number("surface.elevation_dependent.M_limit_max", "m s^-1");
70
71 double eps = 1e-16;
72 if (std::fabs(m_M_limit_min - m_M_limit_max) < eps) {
75 }
76 }
77 }
78
79 units::Converter meter_per_year(m_sys, "m second^-1", "m year^-1");
80 m_log->message(3,
81 " temperature at %.0f m a.s.l. = %.2f deg C\n"
82 " temperature at %.0f m a.s.l. = %.2f deg C\n"
83 " mass balance below %.0f m a.s.l. = %.2f m year-1\n"
84 " mass balance at %.0f m a.s.l. = %.2f m year-1\n"
85 " mass balance at %.0f m a.s.l. = %.2f m year-1\n"
86 " mass balance above %.0f m a.s.l. = %.2f m year-1\n"
87 " equilibrium line altitude z_ELA = %.2f m a.s.l.\n",
90 m_z_M_min, meter_per_year(m_M_limit_min),
92 m_z_M_max, meter_per_year(m_M_max),
93 m_z_M_max, meter_per_year(m_M_limit_max),
94 m_z_ELA);
95
96 // parameterizing the ice surface temperature 'ice_surface_temp'
97 m_log->message(2, " - parameterizing the ice surface temperature 'ice_surface_temp' ... \n");
98 m_log->message(2,
99 " ice temperature at the ice surface (T = ice_surface_temp) is piecewise-linear function\n"
100 " of surface altitude (usurf):\n"
101 " / %2.2f K for usurf < %.f m\n"
102 " T = | %5.2f K + %5.3f * (usurf - %.f m) for %.f m < usurf < %.f m\n"
103 " \\ %5.2f K for %.f m < usurf\n",
107
108 // parameterizing the ice surface mass balance 'climatic_mass_balance'
109 m_log->message(2,
110
111 " - parameterizing the ice surface mass balance 'climatic_mass_balance' ... \n");
112
113 if (limits_set) {
114 m_log->message(2,
115 " - option '-climatic_mass_balance_limits' seen, limiting upper and lower bounds ... \n");
116 }
117
118 m_log->message(2,
119 " surface mass balance (M = climatic_mass_balance) is piecewise-linear function\n"
120 " of surface altitue (usurf):\n"
121 " / %5.2f m year-1 for usurf < %3.f m\n"
122 " M = | %5.3f 1/a * (usurf-%.0f m) for %3.f m < usurf < %3.f m\n"
123 " \\ %5.3f 1/a * (usurf-%.0f m) for %3.f m < usurf < %3.f m\n"
124 " \\ %5.2f m year-1 for %3.f m < usurf\n",
125 meter_per_year(m_M_limit_min), m_z_M_min,
126 meter_per_year(-m_M_min)/(m_z_ELA - m_z_M_min), m_z_ELA, m_z_M_min, m_z_ELA,
127 meter_per_year(m_M_max)/(m_z_M_max - m_z_ELA), m_z_ELA, m_z_ELA, m_z_M_max,
128 meter_per_year(m_M_limit_max), m_z_M_max);
129}
130
132 (void) t;
133 return MaxTimestep("surface 'elevation'");
134}
135
136void Elevation::update_impl(const Geometry &geometry, double t, double dt) {
137 (void) t;
138 (void) dt;
139
142
146
147}
148
150 return *m_mass_flux;
151}
152
154 return *m_temperature;
155}
156
160
162 return *m_melt;
163}
164
166 return *m_runoff;
167}
168
169void Elevation::compute_mass_flux(const array::Scalar &surface, array::Scalar &result) const {
170 double dabdz = -m_M_min/(m_z_ELA - m_z_M_min);
171 double dacdz = m_M_max/(m_z_M_max - m_z_ELA);
172
173 array::AccessScope list{&result, &surface};
174
175 ParallelSection loop(m_grid->com);
176 try {
177 for (auto p = m_grid->points(); p; p.next()) {
178 const int i = p.i(), j = p.j();
179
180 double z = surface(i, j);
181
182 if (z < m_z_M_min) {
183 result(i, j) = m_M_limit_min;
184 }
185 else if ((z >= m_z_M_min) and (z < m_z_ELA)) {
186 result(i, j) = dabdz * (z - m_z_ELA);
187 }
188 else if ((z >= m_z_ELA) and (z <= m_z_M_max)) {
189 result(i, j) = dacdz * (z - m_z_ELA);
190 }
191 else if (z > m_z_M_max) {
192 result(i, j) = m_M_limit_max;
193 }
194 else {
196 "Elevation::compute_mass_flux: HOW DID I GET HERE?");
197 }
198 }
199 } catch (...) {
200 loop.failed();
201 }
202 loop.check();
203
204 // convert from m second-1 ice equivalent to kg m-2 s-1:
205 result.scale(m_config->get_number("constants.ice.density"));
206}
207
208void Elevation::compute_temperature(const array::Scalar &surface, array::Scalar &result) const {
209
210 array::AccessScope list{&result, &surface};
211
212 double dTdz = (m_T_max - m_T_min)/(m_z_T_max - m_z_T_min);
213 ParallelSection loop(m_grid->com);
214 try {
215 for (auto p = m_grid->points(); p; p.next()) {
216 const int i = p.i(), j = p.j();
217
218 double z = surface(i, j);
219
220 if (z <= m_z_T_min) {
221 result(i, j) = m_T_min;
222 }
223 else if ((z > m_z_T_min) and (z < m_z_T_max)) {
224 result(i, j) = m_T_min + dTdz * (z - m_z_T_min);
225 }
226 else if (z >= m_z_T_max) {
227 result(i, j) = m_T_max;
228 }
229 else {
231 "Elevation::compute_temperature: HOW DID I GET HERE?");
232 }
233 }
234 } catch (...) {
235 loop.failed();
236 }
237 loop.check();
238}
239
240} // end of namespace surface
241} // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition Component.hh:160
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
array::Scalar2 ice_surface_elevation
Definition Geometry.hh:57
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void failed()
Indicates a failure of a parallel section.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:224
void compute_temperature(const array::Scalar &surface, array::Scalar &result) const
Definition Elevation.cc:208
const array::Scalar & temperature_impl() const
Definition Elevation.cc:153
void compute_mass_flux(const array::Scalar &surface, array::Scalar &result) const
Definition Elevation.cc:169
void init_impl(const Geometry &geometry)
Definition Elevation.cc:40
std::shared_ptr< array::Scalar > m_mass_flux
Definition Elevation.hh:53
void update_impl(const Geometry &geometry, double t, double dt)
Definition Elevation.cc:136
Elevation(std::shared_ptr< const Grid > grid, std::shared_ptr< atmosphere::AtmosphereModel > input)
Definition Elevation.cc:32
virtual const array::Scalar & accumulation_impl() const
Definition Elevation.cc:157
std::shared_ptr< array::Scalar > m_temperature
Definition Elevation.hh:54
virtual const array::Scalar & runoff_impl() const
Definition Elevation.cc:165
virtual const array::Scalar & melt_impl() const
Definition Elevation.cc:161
const array::Scalar & mass_flux_impl() const
Definition Elevation.cc:149
MaxTimestep max_timestep_impl(double t) const
Definition Elevation.cc:131
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
static std::shared_ptr< array::Scalar > allocate_temperature(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< array::Scalar > m_accumulation
void dummy_runoff(const array::Scalar &smb, array::Scalar &result)
The interface of PISM's surface models.
#define PISM_ERROR_LOCATION