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
PSVerification.cc
Go to the documentation of this file.
1/* Copyright (C) 2014, 2015, 2016, 2017, 2018, 2023 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 <algorithm>
21#include <vector>
22
23#include "pism/verification/PSVerification.hh"
24#include "pism/coupler/AtmosphereModel.hh"
25#include "pism/rheology/PatersonBuddCold.hh"
26#include "pism/util/EnthalpyConverter.hh"
27#include "pism/util/Time.hh"
28#include "pism/util/ConfigInterface.hh"
29
30#include "pism/verification/tests/exactTestsABCD.h"
31#include "pism/verification/tests/exactTestsFG.hh"
32#include "pism/verification/tests/exactTestH.h"
33#include "pism/verification/tests/exactTestL.hh"
34
35#include "pism/util/error_handling.hh"
36#include "pism/util/Grid.hh"
37#include "pism/util/MaxTimestep.hh"
38#include "pism/util/Context.hh"
39
40namespace pism {
41namespace surface {
42
43const double Verification::ablationRateOutside = 0.02; // m year-1
44const double Verification::secpera = 3.15569259747e7;
45
46const double Verification::ST = 1.67e-5;
47const double Verification::Tmin = 223.15; // K
48const double Verification::LforFG = 750000; // m
49const double Verification::ApforG = 200; // m
50
51Verification::Verification(std::shared_ptr<const Grid> g,
52 EnthalpyConverter::Ptr EC, int test)
53 : PSFormulas(g), m_testname(test), m_EC(EC) {
54 // empty
55}
56
57void Verification::init_impl(const Geometry &geometry) {
58 // Make sure that ice surface temperature and climatic mass balance
59 // get initialized at the beginning of the run (as far as I can tell
60 // this affects zero-length runs only).
61 update(geometry, time().current(), 0);
62}
63
65 m_mass_flux->define(output, io::PISM_DOUBLE);
66 m_temperature->define(output, io::PISM_DOUBLE);
67}
68
69void Verification::write_model_state_impl(const File &output) const {
70 m_mass_flux->write(output);
71 m_temperature->write(output);
72}
73
75 (void) t;
76 return MaxTimestep("verification surface model");
77}
78
79/** Initialize climate inputs of tests K and O.
80 *
81 * @return 0 on success
82 */
84
85 m_mass_flux->set(0.0);
86 m_temperature->set(223.15);
87}
88
89/** Update the test L climate input (once).
90 *
91 * Unlike other `update_...()` methods, this one uses [kg m-2 s-1]
92 * as units of the climatic_mass_balance.
93 *
94 * @return 0 on success
95 */
97 double A0, T0;
98
99 rheology::PatersonBuddCold tgaIce("stress_balance.sia.", *m_config, m_EC);
100
101 // compute T so that A0 = A(T) = Acold exp(-Qcold/(R T)) (i.e. for PatersonBuddCold);
102 // set all temps to this constant
103 A0 = 1.0e-16/secpera; // = 3.17e-24 1/(Pa^3 s); (EISMINT value) flow law parameter
104 T0 = tgaIce.tempFromSoftness(A0);
105
106 m_temperature->set(T0);
107
108 const double
109 ice_density = m_config->get_number("constants.ice.density"),
110 a0 = units::convert(m_sys, 0.3, "m year^-1", "m second^-1"),
111 L = 750e3,
112 Lsqr = L * L;
113
115 for (auto p = m_grid->points(); p; p.next()) {
116 const int i = p.i(), j = p.j();
117
118 double r = grid::radius(*m_grid, i, j);
119 (*m_mass_flux)(i, j) = a0 * (1.0 - (2.0 * r * r / Lsqr));
120
121 (*m_mass_flux)(i, j) *= ice_density; // convert to [kg m-2 s-1]
122 }
123}
124
126
127 // initialize temperature; the value used does not matter
128 m_temperature->set(273.15);
129
130 // initialize mass balance:
131 m_mass_flux->set(0.0);
132}
133
134void Verification::update_impl(const Geometry &geometry, double t, double dt) {
135 (void) geometry;
136 (void) dt;
137
138 switch (m_testname) {
139 case 'A':
140 case 'B':
141 case 'C':
142 case 'D':
143 case 'H':
144 update_ABCDH(t);
145 break;
146 case 'F':
147 case 'G':
148 update_FG(t);
149 break;
150 case 'K':
151 case 'O':
152 update_KO();
153 break;
154 case 'L':
155 {
156 update_L();
157 // return here; note update_L() uses correct units
158 return;
159 }
160 case 'V':
161 update_V();
162 break;
163 default:
164 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "Test %c is not implemented.", m_testname);
165 }
166
167 // convert from [m second-1] to [kg m-2 s-1]
168 m_mass_flux->scale(m_config->get_number("constants.ice.density"));
169}
170
171/** Update climate inputs for tests A, B, C, D, E, H.
172 *
173 * @return 0 on success
174 */
175void Verification::update_ABCDH(double time) {
176 double A0, T0, accum;
177
178 double f = m_config->get_number("constants.ice.density") / m_config->get_number("bed_deformation.mantle_density");
179
180 rheology::PatersonBuddCold tgaIce("stress_balance.sia.", *m_config, m_EC);
181
182 // compute T so that A0 = A(T) = Acold exp(-Qcold/(R T)) (i.e. for PatersonBuddCold);
183 // set all temps to this constant
184 A0 = 1.0e-16/secpera; // = 3.17e-24 1/(Pa^3 s); (EISMINT value) flow law parameter
185 T0 = tgaIce.tempFromSoftness(A0);
186
187 m_temperature->set(T0);
188
190 ParallelSection loop(m_grid->com);
191 try {
192 for (auto p = m_grid->points(); p; p.next()) {
193 const int i = p.i(), j = p.j();
194
195 const double r = grid::radius(*m_grid, i, j);
196 switch (m_testname) {
197 case 'A':
198 accum = exactA(r).M;
199 break;
200 case 'B':
201 accum = exactB(time, r).M;
202 break;
203 case 'C':
204 accum = exactC(time, r).M;
205 break;
206 case 'D':
207 accum = exactD(time, r).M;
208 break;
209 case 'H':
210 accum = exactH(f, time, r).M;
211 break;
212 default:
213 throw RuntimeError::formatted(PISM_ERROR_LOCATION, "test must be A, B, C, D, or H, got %c",
214 m_testname);
215 }
216 (*m_mass_flux)(i, j) = accum;
217 }
218 } catch (...) {
219 loop.failed();
220 }
221 loop.check();
222}
223
224void Verification::update_FG(double time) {
225
226 const double t = m_testname == 'F' ? 0.0 : time;
227 const double A = m_testname == 'F' ? 0.0 : ApforG;
228
230
231 for (auto p = m_grid->points(); p; p.next()) {
232 const int i = p.i(), j = p.j();
233
234 // avoid singularity at origin
235 const double r = std::max(grid::radius(*m_grid, i, j), 1.0);
236
237 (*m_temperature)(i, j) = Tmin + ST * r;
238
239 if (r > LforFG - 1.0) {
240 // if (essentially) outside of sheet
241 (*m_mass_flux)(i, j) = - ablationRateOutside / secpera;
242 } else {
243 (*m_mass_flux)(i, j) = exactFG(t, r, m_grid->z(), A).M;
244 }
245 }
246}
247
248} // end of namespace surface
249} // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition Component.hh:160
const Time & time() const
Definition Component.cc:109
const Config::ConstPtr m_config
configuration database used by this component
Definition Component.hh:158
const std::shared_ptr< const Grid > m_grid
grid used by this component
Definition Component.hh:156
std::shared_ptr< EnthalpyConverter > Ptr
High-level PISM I/O class.
Definition File.hh:55
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.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
double tempFromSoftness(double A) const
Return the temperature T corresponding to a given value A=A(T).
Cold case of Paterson-Budd.
std::shared_ptr< array::Scalar > m_temperature
Definition Formulas.hh:50
std::shared_ptr< array::Scalar > m_mass_flux
Definition Formulas.hh:49
void update(const Geometry &geometry, double t, double dt)
static const double ablationRateOutside
void write_model_state_impl(const File &output) const
The default (empty implementation).
MaxTimestep max_timestep_impl(double t) const
static const double ApforG
Verification(std::shared_ptr< const Grid > g, EnthalpyConverter::Ptr EC, int test)
void update_impl(const Geometry &geometry, double t, double dt)
void init_impl(const Geometry &geometry)
static const double LforFG
EnthalpyConverter::Ptr m_EC
void define_model_state_impl(const File &output) const
The default (empty implementation).
static const double secpera
#define PISM_ERROR_LOCATION
struct TestHParameters exactH(const double f, const double t, const double r)
Definition exactTestH.c:76
static const double L
Definition exactTestL.cc:40
struct TestABCDParameters exactB(const double t, const double r)
struct TestABCDParameters exactD(const double t, const double r)
struct TestABCDParameters exactA(double r)
struct TestABCDParameters exactC(const double t, const double r)
double radius(const Grid &grid, int i, int j)
Returns the distance from the point (i,j) to the origin.
Definition Grid.cc:1377
@ PISM_DOUBLE
Definition IO_Flags.hh:52
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
Definition Units.cc:70
static const double g
Definition exactTestP.cc:36
TestFGParameters exactFG(double t, double r, const std::vector< double > &z, double Cp)