PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
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 
40 namespace pism {
41 namespace surface {
42 
43 const double Verification::ablationRateOutside = 0.02; // m year-1
44 const double Verification::secpera = 3.15569259747e7;
45 
46 const double Verification::ST = 1.67e-5;
47 const double Verification::Tmin = 223.15; // K
48 const double Verification::LforFG = 750000; // m
49 const double Verification::ApforG = 200; // m
50 
51 Verification::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 
57 void 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 
64 void Verification::define_model_state_impl(const File &output) const {
65  m_mass_flux->define(output, io::PISM_DOUBLE);
66  m_temperature->define(output, io::PISM_DOUBLE);
67 }
68 
69 void 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 
134 void 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  */
175 void 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 
224 void 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 
229  array::AccessScope list{m_mass_flux.get(), m_temperature.get()};
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:56
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
Definition: MaxTimestep.hh:31
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:65
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).
static const double ST
MaxTimestep max_timestep_impl(double t) const
static const double ApforG
Verification(std::shared_ptr< const Grid > g, EnthalpyConverter::Ptr EC, int test)
static const double Tmin
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 max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
Definition: Scalar.cc:165
double radius(const Grid &grid, int i, int j)
Returns the distance from the point (i,j) to the origin.
Definition: Grid.cc:1407
@ 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)
Definition: exactTestsFG.cc:38