PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
AtmosphereModel.cc
Go to the documentation of this file.
1 /* Copyright (C) 2016, 2017, 2018, 2019, 2020, 2022, 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 <gsl/gsl_math.h> // GSL_NAN
21 #include <memory>
22 
23 #include "pism/coupler/AtmosphereModel.hh"
24 #include "pism/util/Time.hh"
25 #include "pism/util/error_handling.hh"
26 #include "pism/util/MaxTimestep.hh"
27 #include "pism/util/Context.hh"
28 
29 namespace pism {
30 namespace atmosphere {
31 
32 std::shared_ptr<array::Scalar> AtmosphereModel::allocate_temperature(std::shared_ptr<const Grid> grid) {
33  auto result = std::make_shared<array::Scalar>(grid, "air_temp");
34 
35  result->metadata(0)
36  .long_name("mean annual near-surface air temperature")
37  .units("Kelvin");
38 
39  return result;
40 }
41 
42 std::shared_ptr<array::Scalar> AtmosphereModel::allocate_precipitation(std::shared_ptr<const Grid> grid) {
43  auto result = std::make_shared<array::Scalar>(grid, "precipitation");
44 
45  result->metadata(0)
46  .long_name("precipitation rate")
47  .units("kg m-2 second-1")
48  .output_units("kg m-2 year-1")
49  .standard_name("precipitation_flux");
50 
51  return result;
52 }
53 
54 AtmosphereModel::AtmosphereModel(std::shared_ptr<const Grid> g)
55  : Component(g) {
56  // empty
57 }
58 
59 AtmosphereModel::AtmosphereModel(std::shared_ptr<const Grid> g,
60  std::shared_ptr<AtmosphereModel> input)
61  :Component(g), m_input_model(input) {
62  // empty
63 }
64 
65 void AtmosphereModel::init(const Geometry &geometry) {
66  this->init_impl(geometry);
67 }
68 
69 void AtmosphereModel::update(const Geometry &geometry, double t, double dt) {
70  this->update_impl(geometry, t, dt);
71 }
72 
74  return this->precipitation_impl();
75 }
76 
78  return this->air_temperature_impl();
79 }
80 
83 }
84 
87 }
88 
89 void AtmosphereModel::init_timeseries(const std::vector<double> &ts) const {
90  this->init_timeseries_impl(ts);
91 }
92 
93 void AtmosphereModel::precip_time_series(int i, int j, std::vector<double> &result) const {
94  result.resize(m_ts_times.size());
95  this->precip_time_series_impl(i, j, result);
96 }
97 
98 void AtmosphereModel::temp_time_series(int i, int j, std::vector<double> &result) const {
99  result.resize(m_ts_times.size());
100  this->temp_time_series_impl(i, j, result);
101 }
102 
103 namespace diagnostics {
104 
105 /*! @brief Instantaneous near-surface air temperature. */
106 class AirTemperatureSnapshot : public Diag<AtmosphereModel> {
107 public:
109  m_vars = { { m_sys, "air_temp_snapshot" } };
110  m_vars[0].long_name("instantaneous value of the near-surface air temperature").units("Kelvin");
111  }
112 
113 protected:
114  std::shared_ptr<array::Array> compute_impl() const {
115 
116  auto result = allocate<array::Scalar>("air_temp_snapshot");
117 
118  std::vector<double> current_time = { m_grid->ctx()->time()->current() };
119  std::vector<double> temperature = { 0.0 };
120 
121  model->init_timeseries(current_time);
122 
123  model->begin_pointwise_access();
124 
125  array::AccessScope list(*result);
126  ParallelSection loop(m_grid->com);
127  try {
128  for (auto p = m_grid->points(); p; p.next()) {
129  const int i = p.i(), j = p.j();
130 
131  model->temp_time_series(i, j, temperature);
132 
133  (*result)(i, j) = temperature[0];
134  }
135  } catch (...) {
136  loop.failed();
137  }
138  loop.check();
139 
140  model->end_pointwise_access();
141 
142  return result;
143  }
144 };
145 
146 /*! @brief Effective near-surface mean-annual air temperature. */
147 class AirTemperature : public Diag<AtmosphereModel> {
148 public:
150  m_vars = { { m_sys, "effective_air_temp" } };
151  m_vars[0].long_name("effective mean-annual near-surface air temperature").units("Kelvin");
152  }
153 
154 protected:
155  std::shared_ptr<array::Array> compute_impl() const {
156  auto result = allocate<array::Scalar>("effective_air_temp");
157 
158  result->copy_from(model->air_temperature());
159 
160  return result;
161  }
162 };
163 
164 /*! @brief Effective precipitation rate (average over time step). */
165 class Precipitation : public Diag<AtmosphereModel> {
166 public:
168  m_vars = { { m_sys, "effective_precipitation" } };
169  m_vars[0]
170  .long_name("effective precipitation rate")
171  .standard_name("precipitation_flux")
172  .units("kg m-2 second-1")
173  .output_units("kg m-2 year-1");
174  }
175 
176 protected:
177  std::shared_ptr<array::Array> compute_impl() const {
178  auto result = allocate<array::Scalar>("effective_precipitation");
179 
180  result->copy_from(model->precipitation());
181 
182  return result;
183  }
184 };
185 
186 } // end of namespace diagnostics
187 
188 void AtmosphereModel::update_impl(const Geometry &geometry, double t, double dt) {
189  if (m_input_model) {
190  m_input_model->update_impl(geometry, t, dt);
191  }
192 }
193 
195  if (m_input_model) {
196  return m_input_model->max_timestep(my_t);
197  }
198  return MaxTimestep("atmosphere model");
199 }
200 
202  using namespace diagnostics;
203 
204  DiagnosticList result = {
205  {"air_temp_snapshot", Diagnostic::Ptr(new AirTemperatureSnapshot(this))},
206  {"effective_air_temp", Diagnostic::Ptr(new AirTemperature(this))},
207  {"effective_precipitation", Diagnostic::Ptr(new Precipitation(this))},
208  };
209 
210  if (m_input_model) {
211  result = combine(result, m_input_model->diagnostics());
212  }
213 
214  return result;
215 }
216 
218  if (m_input_model) {
219  return m_input_model->ts_diagnostics();
220  }
221 
222  return {};
223 }
224 
226  if (m_input_model) {
227  m_input_model->define_model_state(output);
228  }
229 }
230 
232  if (m_input_model) {
233  m_input_model->write_model_state(output);
234  }
235 }
236 
238  if (m_input_model) {
239  return m_input_model->precipitation();
240  }
241  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
242 }
243 
245  if (m_input_model) {
246  return m_input_model->air_temperature();
247  }
248  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
249 }
250 
252  if (m_input_model) {
253  m_input_model->begin_pointwise_access();
254  } else {
255  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
256  }
257 }
258 
260  if (m_input_model) {
261  m_input_model->end_pointwise_access();
262  } else {
263  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
264  }
265 }
266 
267 void AtmosphereModel::temp_time_series_impl(int i, int j, std::vector<double> &result) const {
268  if (m_input_model) {
269  m_input_model->temp_time_series(i, j, result);
270  } else {
271  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
272  }
273 }
274 
275 void AtmosphereModel::precip_time_series_impl(int i, int j, std::vector<double> &result) const {
276  if (m_input_model) {
277  m_input_model->precip_time_series(i, j, result);
278  } else {
279  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
280  }
281 }
282 
283 void AtmosphereModel::init_timeseries_impl(const std::vector<double> &ts) const {
284  if (m_input_model) {
285  m_input_model->init_timeseries(ts);
286  m_ts_times = ts;
287  } else {
288  throw RuntimeError::formatted(PISM_ERROR_LOCATION, "no input model");
289  }
290 }
291 
292 } // end of namespace atmosphere
293 } // end of namespace pism
std::shared_ptr< const Grid > grid() const
Definition: Component.cc:105
DiagnosticList diagnostics() const
Definition: Component.cc:89
A class defining a common interface for most PISM sub-models.
Definition: Component.hh:118
const AtmosphereModel * model
Definition: Diagnostic.hh:172
A template derived from Diagnostic, adding a "Model".
Definition: Diagnostic.hh:166
const units::System::Ptr m_sys
the unit system
Definition: Diagnostic.hh:116
std::vector< SpatialVariableMetadata > m_vars
metadata corresponding to NetCDF variables
Definition: Diagnostic.hh:120
std::shared_ptr< Diagnostic > Ptr
Definition: Diagnostic.hh:65
std::shared_ptr< const Grid > m_grid
the grid
Definition: Diagnostic.hh:114
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
virtual DiagnosticList diagnostics_impl() const
void update(const Geometry &geometry, double t, double dt)
virtual TSDiagnosticList ts_diagnostics_impl() const
virtual void update_impl(const Geometry &geometry, double t, double dt)=0
virtual void write_model_state_impl(const File &output) const
The default (empty implementation).
virtual void define_model_state_impl(const File &output) const
The default (empty implementation).
virtual void init_timeseries_impl(const std::vector< double > &ts) const
const array::Scalar & air_temperature() const
Sets result to the mean near-surface air temperature, in degrees Kelvin.
static std::shared_ptr< array::Scalar > allocate_temperature(std::shared_ptr< const Grid > grid)
void init_timeseries(const std::vector< double > &ts) const
const array::Scalar & precipitation() const
Sets result to the mean precipitation, in "kg m-2 second-1".
virtual void init_impl(const Geometry &geometry)=0
virtual const array::Scalar & precipitation_impl() const
void init(const Geometry &geometry)
virtual void precip_time_series_impl(int i, int j, std::vector< double > &result) const
virtual void begin_pointwise_access_impl() const
std::shared_ptr< AtmosphereModel > m_input_model
void temp_time_series(int i, int j, std::vector< double > &result) const
Sets a pre-allocated N-element array "result" to the time-series of near-surface air temperature (deg...
virtual const array::Scalar & air_temperature_impl() const
virtual void end_pointwise_access_impl() const
AtmosphereModel(std::shared_ptr< const Grid > g)
virtual void temp_time_series_impl(int i, int j, std::vector< double > &result) const
static std::shared_ptr< array::Scalar > allocate_precipitation(std::shared_ptr< const Grid > grid)
virtual MaxTimestep max_timestep_impl(double my_t) const
std::vector< double > m_ts_times
void precip_time_series(int i, int j, std::vector< double > &result) const
Sets a pre-allocated N-element array "result" to the time-series of ice-equivalent precipitation (m/s...
A purely virtual class defining the interface of a PISM Atmosphere Model.
std::shared_ptr< array::Array > compute_impl() const
Instantaneous near-surface air temperature.
std::shared_ptr< array::Array > compute_impl() const
Effective near-surface mean-annual air temperature.
std::shared_ptr< array::Array > compute_impl() const
Effective precipitation rate (average over time step).
#define PISM_ERROR_LOCATION
static const double g
Definition: exactTestP.cc:36
std::map< std::string, TSDiagnostic::Ptr > TSDiagnosticList
Definition: Diagnostic.hh:343
std::map< std::string, Diagnostic::Ptr > DiagnosticList
Definition: Diagnostic.hh:125
T combine(const T &a, const T &b)