PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
ISMIP6Climate.cc
Go to the documentation of this file.
1// Copyright (C) 2019, 2021, 2022, 2023, 2024, 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 "pism/coupler/surface/ISMIP6Climate.hh"
20
21#include "pism/util/Grid.hh"
22#include "pism/coupler/util/options.hh"
23#include "pism/geometry/Geometry.hh"
24#include "pism/util/array/Forcing.hh"
25#include "pism/util/Logger.hh"
26#include "pism/util/io/IO_Flags.hh"
27
28namespace pism {
29namespace surface {
30
31ISMIP6::ISMIP6(std::shared_ptr<const Grid> grid, std::shared_ptr<atmosphere::AtmosphereModel> input)
32 : SurfaceModel(grid),
33 m_mass_flux_reference(m_grid, "climatic_mass_balance"),
34 m_temperature_reference(m_grid, "ice_surface_temp"),
35 m_surface_reference(m_grid, "usurf")
36{
37 (void) input;
38
39 // allocate model outputs
42
43 // set metadata of reference fields
44 {
46 .long_name("reference surface mass balance rate")
47 .units("kg m^-2 s^-1")
48 .output_units("kg m^-2 year^-1")
49 .standard_name("land_ice_surface_specific_mass_balance_flux")
50 .set_time_dependent(false);
51
52 auto smb_max = m_config->get_number("surface.given.smb_max", "kg m-2 second-1");
53 m_mass_flux_reference.metadata()["valid_range"] = { -smb_max, smb_max };
54
56 .long_name("reference surface altitude")
57 .units("m")
58 .standard_name("surface_altitude")
59 .set_time_dependent(false);
60
61 m_surface_reference.metadata()["valid_range"] = { 0.0, m_grid->Lz() };
62
64 .long_name("reference temperature")
65 .units("kelvin")
66 .set_time_dependent(false);
67
68 m_temperature_reference.metadata()["valid_range"] = { 0.0, 373.15 };
69 }
70
71 // allocate storage for time-dependent inputs
72 ForcingOptions opt(*m_grid->ctx(), "surface.ismip6");
73
74 {
75 unsigned int buffer_size = m_config->get_number("input.forcing.buffer_size");
76
78
79 {
81 std::make_shared<array::Forcing>(m_grid, file, "climatic_mass_balance_anomaly",
82 "", // no standard name
83 buffer_size, opt.periodic);
84
85 m_mass_flux_anomaly->metadata(0)
86 .long_name("surface mass balance rate anomaly")
87 .units("kg m^-2 s^-1")
88 .output_units("kg m^-2 year^-1");
89 }
90
91 {
93 std::make_shared<array::Forcing>(m_grid, file, "climatic_mass_balance_gradient",
94 "", // no standard name
95 buffer_size, opt.periodic);
96
97 m_mass_flux_gradient->metadata(0)
98 .long_name("surface mass balance rate elevation lapse rate")
99 .units("kg m^-2 s^-1 m^-1")
100 .output_units("kg m^-2 year^-1 m^-1");
101 }
102
103 {
105 std::make_shared<array::Forcing>(m_grid, file, "ice_surface_temp_anomaly",
106 "", // no standard name
107 buffer_size, opt.periodic);
108
109 m_temperature_anomaly->metadata(0)
110 .long_name("ice surface temperature anomaly")
111 .units("kelvin");
112 }
113
114 {
116 std::make_shared<array::Forcing>(m_grid, file, "ice_surface_temp_gradient",
117 "", // no standard name
118 buffer_size, opt.periodic);
119
120 m_temperature_gradient->metadata(0)
121 .long_name("ice surface temperature elevation lapse rate")
122 .units("kelvin m^-1");
123 }
124 }
125}
126
127void ISMIP6::init_impl(const Geometry &geometry) {
128 (void) geometry;
129
130 m_log->message(2, "* Initializing the ISMIP6 surface model...\n");
131
132 {
133 // File with reference surface elevation, temperature, and climatic mass balance
134 auto reference_filename = m_config->get_string("surface.ismip6.reference_file");
135 File reference_file(m_grid->com, reference_filename, io::PISM_GUESS, io::PISM_READONLY);
136
140 }
141
142 {
143 ForcingOptions opt(*m_grid->ctx(), "surface.ismip6");
144
145 m_mass_flux_anomaly->init(opt.filename, opt.periodic);
146 m_mass_flux_gradient->init(opt.filename, opt.periodic);
147
150 }
151}
152
153void ISMIP6::update_impl(const Geometry &geometry, double t, double dt) {
154
155 // inputs
156 const array::Scalar &h = geometry.ice_surface_elevation;
157 const array::Scalar &h_ref = m_surface_reference;
159 const array::Scalar &SMB_ref = m_mass_flux_reference;
160
165
166 // outputs
169
170 // get time-dependent input fields at the current time
171 {
172 aT.update(t, dt);
173 aSMB.update(t, dt);
174 dTdz.update(t, dt);
175 dSMBdz.update(t, dt);
176
177 aT.average(t, dt);
178 aSMB.average(t, dt);
179 dTdz.average(t, dt);
180 dSMBdz.average(t, dt);
181 }
182
183 // From http://www.climate-cryosphere.org/wiki/index.php?title=ISMIP6-Projections-Greenland:
184 // SMB(x,y,t) = SMB_ref(x,y) + aSMB(x,y,t) + dSMBdz(x,y,t) * [h(x,y,t) - h_ref(x,y)]
185
186 array::AccessScope list{ &h, &h_ref, &SMB, &SMB_ref, &aSMB, &dSMBdz, &T, &T_ref, &aT, &dTdz };
187
188 for (auto p : m_grid->points()) {
189 const int i = p.i(), j = p.j();
190
191 SMB(i, j) = SMB_ref(i, j) + aSMB(i, j) + dSMBdz(i, j) * (h(i, j) - h_ref(i, j));
192 T(i, j) = T_ref(i, j) + aT(i, j) + dTdz(i, j) * (h(i, j) - h_ref(i, j));
193 }
194
196 dummy_melt(SMB, *m_melt);
197 dummy_runoff(SMB, *m_runoff);
198}
199
201 using std::min;
202
203 auto dt = m_temperature_anomaly->max_timestep(t);
204 dt = min(dt, m_temperature_gradient->max_timestep(t));
205 dt = min(dt, m_mass_flux_anomaly->max_timestep(t));
206 dt = min(dt, m_mass_flux_gradient->max_timestep(t));
207
208 if (dt.finite()) {
209 return MaxTimestep(dt.value(), "surface ISMIP6");
210 }
211 return MaxTimestep("surface ISMIP6");
212}
213
215 return *m_mass_flux;
216}
217
219 return *m_temperature;
220}
221
223 return *m_accumulation;
224}
225
227 return *m_melt;
228}
229
231 return *m_runoff;
232}
233
234} // end of namespace surface
235} // end of namespace pism
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
std::shared_ptr< const Logger > m_log
logger (for easy access)
Definition Component.hh:164
High-level PISM I/O class.
Definition File.hh:57
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...
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
VariableMetadata & standard_name(const std::string &input)
double get_number(const std::string &name) const
Get a single-valued scalar attribute.
VariableMetadata & output_units(const std::string &input)
VariableMetadata & set_time_dependent(bool flag)
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
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
void average(double t, double dt)
Definition Forcing.cc:660
void update(double t, double dt)
Read some data to make sure that the interval (t, t + dt) is covered.
Definition Forcing.cc:424
2D time-dependent inputs (for climate forcing, etc)
Definition Forcing.hh:41
static Default Nil()
Definition IO_Flags.hh:94
array::Scalar m_mass_flux_reference
const array::Scalar & mass_flux_impl() const
std::shared_ptr< array::Forcing > m_mass_flux_anomaly
const array::Scalar & temperature_impl() const
void update_impl(const Geometry &geometry, double t, double dt)
const array::Scalar & accumulation_impl() const
std::shared_ptr< array::Scalar > m_temperature
std::shared_ptr< array::Scalar > m_mass_flux
void init_impl(const Geometry &geometry)
std::shared_ptr< array::Forcing > m_temperature_anomaly
std::shared_ptr< array::Forcing > m_temperature_gradient
const array::Scalar & melt_impl() const
MaxTimestep max_timestep_impl(double t) const
const array::Scalar & runoff_impl() const
array::Scalar m_temperature_reference
std::shared_ptr< array::Forcing > m_mass_flux_gradient
array::Scalar m_surface_reference
ISMIP6(std::shared_ptr< const Grid > g, std::shared_ptr< atmosphere::AtmosphereModel > input)
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.
@ PISM_GUESS
Definition IO_Flags.hh:57
@ PISM_NETCDF3
Definition IO_Flags.hh:58
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:69
std::string filename
Definition options.hh:33