PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
DEBMSimple.cc
Go to the documentation of this file.
1// Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 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 <algorithm> // std::min
20
21#include "pism/coupler/surface/DEBMSimple.hh"
22
23#include "pism/coupler/AtmosphereModel.hh"
24#include "pism/util/Grid.hh"
25#include "pism/util/Mask.hh"
26#include "pism/util/Time.hh"
27#include "pism/util/io/File.hh"
28
29#include "pism/coupler/util/options.hh"
30#include "pism/geometry/Geometry.hh"
31#include "pism/util/array/CellType.hh"
32#include "pism/util/error_handling.hh"
33#include "pism/util/pism_utilities.hh"
34#include "pism/util/Vars.hh"
35#include "pism/util/array/Forcing.hh"
36#include "pism/util/Logger.hh"
37#include "pism/util/io/IO_Flags.hh"
38
39namespace pism {
40namespace surface {
41
42///// PISM surface model implementing a dEBM-Simple scheme.
43
44DEBMSimple::DEBMSimple(std::shared_ptr<const Grid> g, std::shared_ptr<atmosphere::AtmosphereModel> input)
45 : SurfaceModel(g, std::move(input)),
46 m_model(*g->ctx()),
47 m_mass_flux(m_grid, "climatic_mass_balance"),
48 m_snow_depth(m_grid, "snow_depth"),
49 m_temperature_driven_melt(m_grid, "debm_temperature_driven_melt_flux"),
50 m_insolation_driven_melt(m_grid, "debm_insolation_driven_melt_flux"),
51 m_offset_melt(m_grid, "debm_offset_melt_flux"),
52 m_surface_albedo(m_grid, "surface_albedo"),
53 m_transmissivity(m_grid, "atmosphere_transmissivity") {
54
55 m_sd_use_param = m_config->get_flag("surface.debm_simple.std_dev.param.enabled");
56 m_sd_param_a = m_config->get_number("surface.debm_simple.std_dev.param.a");
57 m_sd_param_b = m_config->get_number("surface.debm_simple.std_dev.param.b");
58
59 m_precip_as_snow = m_config->get_flag("surface.debm_simple.interpret_precip_as_snow");
60 m_Tmax = m_config->get_number("surface.debm_simple.air_temp_all_precip_as_rain");
61 m_Tmin = m_config->get_number("surface.debm_simple.air_temp_all_precip_as_snow");
62
63 if (m_Tmax <= m_Tmin) {
65 "surface.debm_simple.air_temp_all_precip_as_rain has to exceed "
66 "surface.debm_simple.air_temp_all_precip_as_snow");
67 }
68
69 // note: does not need to be calendar-aware
70 m_year_length = units::convert(g->ctx()->unit_system(), 1.0, "years", "seconds");
71
72 m_n_per_year = static_cast<unsigned int>(m_config->get_number("surface.debm_simple.max_evals_per_year"));
73
74 auto albedo_input = m_config->get_string("surface.debm_simple.albedo_input.file");
75 if (not albedo_input.empty()) {
76
77 m_log->message(2, " Surface albedo is read in from %s...", albedo_input.c_str());
78
79 File file(m_grid->com, albedo_input, io::PISM_GUESS, io::PISM_READONLY);
80
81 int buffer_size = static_cast<int>(m_config->get_number("input.forcing.buffer_size"));
82 bool periodic = m_config->get_flag("surface.debm_simple.albedo_input.periodic");
83 m_input_albedo = std::make_shared<array::Forcing>(m_grid,
84 file,
85 "surface_albedo",
86 "surface_albedo",
87 buffer_size,
88 periodic,
89 LINEAR);
90 } else {
91 m_input_albedo = nullptr;
92 }
93
94 // initialize the spatially-variable air temperature standard deviation
95
96 auto air_temp_sd = m_config->get_string("surface.debm_simple.std_dev.file");
97 if (not air_temp_sd.empty()) {
98 m_log->message(2, " Reading standard deviation of near-surface air temperature from '%s'...\n",
99 air_temp_sd.c_str());
100
101 int buffer_size = static_cast<int>(m_config->get_number("input.forcing.buffer_size"));
102
104
105 bool periodic = m_config->get_flag("surface.debm_simple.std_dev.periodic");
106 m_air_temp_sd = std::make_shared<array::Forcing>(m_grid, file, "air_temp_sd",
107 "", // no standard name
108 buffer_size, periodic, LINEAR);
109 } else {
110 double temp_std_dev = m_config->get_number("surface.debm_simple.std_dev");
111
112 m_air_temp_sd = array::Forcing::Constant(m_grid, "air_temp_sd", temp_std_dev);
113 m_log->message(2, " Using constant standard deviation of near-surface air temperature.\n");
114 }
115
116 m_air_temp_sd->metadata(0)
117 .long_name("standard deviation of near-surface air temperature")
118 .units("kelvin");
119
121 .long_name("instantaneous surface mass balance (accumulation/ablation) rate")
122 .units("kg m^-2 s^-1")
123 .standard_name("land_ice_surface_specific_mass_balance_flux");
124 m_mass_flux.metadata().set_string("comment", "positive values correspond to ice gain");
125
126 // diagnostic fields:
127
128 {
133
135 .long_name("temperature-driven melt in dEBM-simple")
136 .units("kg m^-2");
138
140 .long_name("insolation-driven melt in dEBM-simple")
141 .units("kg m^-2");
143
145 .long_name("offset melt in dEBM-simple")
146 .units("kg m^-2");
147 m_offset_melt.set(0.0);
148 }
149
151 .long_name("snow cover depth (set to zero once a year)")
152 .units("m");
153 m_snow_depth.set(0.0);
154
156 .long_name("surface_albedo")
157 .units("1")
158 .standard_name("surface_albedo");
160
162 .long_name("atmosphere_transmissivity")
163 .units("1");
164
166}
167
168void DEBMSimple::init_impl(const Geometry &geometry) {
169
170 // call the default implementation (not the interface method init())
171 SurfaceModel::init_impl(geometry);
172
173 {
174 m_log->message(2,
175 "* Initializing dEBM-simple, the diurnal Energy Balance Model (simple version).\n"
176 " Inputs: precipitation and 2m air temperature from an atmosphere model.\n"
177 " Outputs: SMB and ice upper surface temperature.\n");
178 }
179
180 // initializing the model state
182
183 auto default_albedo = m_config->get_number("surface.debm_simple.albedo_max");
184 if (input.type == INIT_RESTART) {
185 m_snow_depth.read(input.filename, input.record);
186 m_surface_albedo.read(input.filename, input.record);
187 } else if (input.type == INIT_BOOTSTRAP) {
189 m_surface_albedo.regrid(input.filename, io::Default(default_albedo));
190 } else {
191 m_snow_depth.set(0.0);
192 m_surface_albedo.set(default_albedo);
193 }
194
195 {
196 regrid("dEBM-simple surface model", m_snow_depth);
197 regrid("dEBM-simple surface model", m_surface_albedo);
198 }
199
200 if ((bool)m_input_albedo) {
201 auto filename = m_config->get_string("surface.debm_simple.albedo_input.file");
202 bool periodic = m_config->get_flag("surface.debm_simple.albedo_input.periodic");
203 m_input_albedo->init(filename, periodic);
204 }
205
206 // finish up
207 {
209
210 m_accumulation->set(0.0);
211 m_melt->set(0.0);
212 m_runoff->set(0.0);
213 }
214}
215
217 return m_atmosphere->max_timestep(my_t);
218}
219
221 // compute the time corresponding to the beginning of the next balance year
222 double balance_year_start_day = m_config->get_number("surface.mass_balance_year_start_day"),
223 one_day = units::convert(m_sys, 1.0, "days", "seconds"),
224 year_start = this->time().calendar_year_start(time),
225 balance_year_start = year_start + (balance_year_start_day - 1.0) * one_day;
226
227 if (balance_year_start > time) {
228 return balance_year_start;
229 }
230 return this->time().increment_date(balance_year_start, 1);
231}
232
233/** @brief Extracts snow accumulation from mixed (snow and rain) precipitation using a
234 * temperature threshold with a linear transition.
235 *
236 * Rain is removed entirely from the surface mass balance, and will not be included in
237 * the computed runoff, which is meltwater runoff.
238 *
239 * There is an linear transition for Tmin below which all precipitation is interpreted as
240 * snow, and Tmax above which all precipitation is rain (see, e.g. [\ref Hock2005b]).
241 *
242 * Returns the *solid* (snow) accumulation *rate*.
243 *
244 * @param[in] T air temperature
245 * @param[in] P precipitation rate
246 */
247double DEBMSimple::snow_accumulation(double T, double P) const {
248
249 // do not allow negative precipitation
250 if (P < 0.0) {
251 return 0.0;
252 }
253
254 if (m_precip_as_snow or T <= m_Tmin) {
255 // T <= Tmin, all precip is snow
256 return P;
257 }
258
259 if (T < m_Tmax) { // linear transition from Tmin to Tmax
260 return P * (m_Tmax - T) / (m_Tmax - m_Tmin);
261 }
262
263 // T >= Tmax, all precip is rain -- ignore it
264 return 0.0;
265}
266
267
268void DEBMSimple::update_impl(const Geometry &geometry, double t, double dt) {
269
270 const double melting_point = 273.15;
271
272 // update to ensure that temperature and precipitation time series are correct:
273 m_atmosphere->update(geometry, t, dt);
274
275 // Use near-surface air temperature as the top-of-the-ice temperature:
276 m_temperature->copy_from(m_atmosphere->air_temperature());
277
278 // Set up air temperature and precipitation time series
279 int N = static_cast<int>(timeseries_length(dt));
280
281 const double dtseries = dt / N;
282 std::vector<double> ts(N), T(N), S(N), P(N), Alb(N);
283 std::vector<DEBMSimpleOrbitalParameters> orbital(N);
284
285 for (int k = 0; k < N; ++k) {
286 ts[k] = t + k * dtseries;
287
288 // pre-compute orbital parameters which depend on time and *not* on the map-plane
289 // location
290 orbital[k] = m_model.orbital_parameters(ts[k]);
291 }
292
293 // update standard deviation time series
294 m_air_temp_sd->update(t, dt);
295 m_air_temp_sd->init_interpolation(ts);
296
297 const auto &mask = geometry.cell_type;
298 const auto &H = geometry.ice_thickness;
299 const auto &surface_altitude = geometry.ice_surface_elevation;
300
302 { &mask,
303 &H,
304 m_air_temp_sd.get(),
307 m_accumulation.get(),
308 m_melt.get(),
309 m_runoff.get(),
315 &geometry.latitude,
316 &surface_altitude
317 };
318
319 if ((bool)m_input_albedo) {
320 m_input_albedo->update(t, dt);
321 m_input_albedo->init_interpolation(ts);
322 list.add(*m_input_albedo);
323 }
324
325 double
326 ice_density = m_config->get_number("constants.ice.density"),
327 sigmalapserate = m_config->get_number("surface.pdd.std_dev.lapse_lat_rate"),
328 sigmabaselat = m_config->get_number("surface.pdd.std_dev.lapse_lat_base");
329
330 m_atmosphere->init_timeseries(ts);
331 m_atmosphere->begin_pointwise_access();
332
333 ParallelSection loop(m_grid->com);
334 try {
335 for (auto p : m_grid->points()) {
336 const int i = p.i(), j = p.j();
337
338 double latitude = geometry.latitude(i, j);
339
340 // Get the temperature time series from an atmosphere model and its modifiers
341 m_atmosphere->temp_time_series(i, j, T);
342
343 if (mask.ice_free_ocean(i, j)) {
344 // ignore precipitation over ice-free ocean
345 for (int k = 0; k < N; ++k) {
346 P[k] = 0.0;
347 }
348 } else {
349 // elsewhere, get precipitation from the atmosphere model
350 m_atmosphere->precip_time_series(i, j, P);
351
352 // Use temperature time series to remove rainfall from precipitation and convert to
353 // m/s ice equivalent.
354 for (int k = 0; k < N; ++k) {
355 P[k] = snow_accumulation(T[k], // air temperature (input)
356 P[k] / ice_density); // precipitation rate (input, gets overwritten)
357 }
358 }
359
360 if ((bool)m_input_albedo) {
361 m_input_albedo->interp(i, j, Alb);
362 }
363
364 // standard deviation of daily variability of air temperature
365 {
366 // interpolate temperature standard deviation time series
367 //
368 // Note: this works when m_air_temp_sd is constant in time.
369 m_air_temp_sd->interp(i, j, S);
370
371 if (sigmalapserate != 0.0) {
372 // apply standard deviation lapse rate on top of prescribed values
373 for (int k = 0; k < N; ++k) {
374 S[k] += sigmalapserate * (latitude - sigmabaselat);
375 }
376 (*m_air_temp_sd)(i, j) = S[0]; // ensure correct SD reporting
377 } else if (m_sd_use_param and mask.icy(i, j)) {
378 // apply standard deviation parameterization over ice if in use
379 for (int k = 0; k < N; ++k) {
380 S[k] = std::max(m_sd_param_a * (T[k] - melting_point) + m_sd_param_b, 0.0);
381 }
382 (*m_air_temp_sd)(i, j) = S[0]; // ensure correct SD reporting
383 }
384 }
385
386 {
387 double next_snow_depth_reset = m_next_balance_year_start;
388
389 // make copies of firn and snow depth values at this point to avoid accessing 2D
390 // fields in the inner loop
391 double
392 ice_thickness = H(i, j),
393 snow = m_snow_depth(i, j),
394 surfelev = surface_altitude(i, j),
395 albedo = m_surface_albedo(i, j);
396
397 auto cell_type = static_cast<MaskValue>(mask.as_int(i, j));
398
399 double
400 A = 0.0, // accumulation
401 M = 0.0, // melt
402 R = 0.0, // runoff
403 SMB = 0.0, // resulting mass balance
404 Mi = 0.0, // insolation melt contribution
405 Mt = 0.0, // temperature melt contribution
406 Mc = 0.0, // offset melt contribution
407 Al = 0.0; // albedo
408
409 // beginning of the loop over small time steps:
410 for (int k = 0; k < N; ++k) {
411
412 if (ts[k] >= next_snow_depth_reset) {
413 snow = 0.0;
414 while (next_snow_depth_reset <= ts[k]) {
415 next_snow_depth_reset = time().increment_date(next_snow_depth_reset, 1);
416 }
417 }
418
419 auto accumulation = P[k] * dtseries;
420
421 DEBMSimpleMelt melt_info{};
422 if (not mask::ice_free_ocean(cell_type)) {
423
424 melt_info = m_model.melt(orbital[k].solar_declination,
425 orbital[k].distance_factor,
426 dtseries,
427 S[k],
428 T[k],
429 surfelev,
430 latitude,
431 (bool)m_input_albedo ? Alb[k] : albedo);
432 }
433
434 auto changes = m_model.step(ice_thickness,
435 melt_info.total_melt,
436 snow,
438
439 if ((bool) m_input_albedo) {
440 albedo = Alb[k];
441 } else {
442 albedo = m_model.albedo(changes.melt / dtseries, cell_type);
443 }
444
445 // update ice thickness
446 ice_thickness += changes.smb;
447 assert(ice_thickness >= 0);
448 // update snow depth
449 snow += changes.snow_depth;
450 assert(snow >= 0);
451 // update total accumulation, melt, and runoff
452 {
453 A += accumulation;
454 M += changes.melt;
455 Mt += melt_info.temperature_melt;
456 Mi += melt_info.insolation_melt;
457 Mc += melt_info.offset_melt;
458 R += changes.runoff;
459 SMB += changes.smb;
460 Al += albedo;
461 }
462 } // end of the time-stepping loop
463
464 // set firn and snow depths
465 m_snow_depth(i, j) = snow;
466 m_surface_albedo(i, j) = Al / N;
468
469 // set melt terms at this point, converting
470 // from "meters, ice equivalent" to "kg / m^2"
471 m_temperature_driven_melt(i, j) = Mt * ice_density;
472 m_insolation_driven_melt(i, j) = Mi * ice_density;
473 m_offset_melt(i, j) = Mc * ice_density;
474
475 // set total accumulation, melt, and runoff, and SMB at this point, converting
476 // from "meters, ice equivalent" to "kg / m^2"
477 {
478 (*m_accumulation)(i, j) = A * ice_density;
479 (*m_melt)(i, j) = M * ice_density;
480 (*m_runoff)(i, j) = R * ice_density;
481 // m_mass_flux (unlike m_accumulation, m_melt, and m_runoff), is a
482 // rate. m * (kg / m^3) / second = kg / m^2 / second
483 m_mass_flux(i, j) = SMB * ice_density / dt;
484 }
485 }
486
487 if (mask.ice_free_ocean(i, j)) {
488 m_snow_depth(i, j) = 0.0; // snow over the ocean does not stick
489 }
490 }
491 } catch (...) {
492 loop.failed();
493 }
494 loop.check();
495
496 m_atmosphere->end_pointwise_access();
497
500}
501
502
504 return m_mass_flux;
505}
506
510
514
516 return *m_melt;
517}
518
520 return *m_runoff;
521}
522
524 return m_snow_depth;
525}
526
528 return *m_air_temp_sd;
529}
530
534
538
540 return m_offset_melt;
541}
542
546
550
551std::set<VariableMetadata> DEBMSimple::state_impl() const {
552 auto variables = array::metadata({&m_snow_depth, &m_surface_albedo});
553 return pism::combine(variables, SurfaceModel::state_impl());
554}
555
556void DEBMSimple::write_state_impl(const OutputFile &output) const {
558 m_snow_depth.write(output);
559 m_surface_albedo.write(output);
560}
561
565
566namespace diagnostics {
567
568/*! @brief Report mean top of atmosphere insolation */
569class DEBMSInsolation : public Diag<DEBMSimple>
570{
571public:
573 m_vars = { { m_sys, "insolation", *m_grid } };
574 m_vars[0]
575 .long_name(
576 "mean top of atmosphere insolation during the period when the sun is above the critical angle Phi")
577 .units("W m^-2");
578 }
579
580protected:
581 std::shared_ptr<array::Array> compute_impl() const {
582
583 auto result = allocate<array::Scalar>("insolation");
584
585 const auto *latitude = m_grid->variables().get_2d_scalar("latitude");
586 auto ctx = m_grid->ctx();
587
588 {
589 const auto& M = model->pointwise_model();
590
591 auto orbital = M.orbital_parameters(ctx->time()->current());
592
593 array::AccessScope list{latitude, result.get()};
594
595 for (auto p : m_grid->points()) {
596 const int i = p.i(), j = p.j();
597
598 (*result)(i, j) = M.insolation_diagnostic(orbital.solar_declination,
599 orbital.distance_factor,
600 (*latitude)(i, j));
601 }
602 }
603
604 return result;
605 }
606};
607
609
610/*! @brief Report surface insolation melt, averaged over the reporting interval */
611class DEBMSInsolationMelt : public DiagAverageRate<DEBMSimple> {
612public:
615 kind == AMOUNT
616 ? "debm_insolation_driven_melt_flux"
617 : "debm_insolation_driven_melt_rate",
619 m_kind(kind),
620 m_melt_mass(m_grid, "debm_insolation_driven_melt_mass") {
621
622 std::string
623 name = "debm_insolation_driven_melt_flux",
624 long_name = "surface insolation melt, averaged over the reporting interval",
625 accumulator_units = "kg m^-2",
626 internal_units = "kg m^-2 second^-1",
627 external_units = "kg m^-2 year^-1";
628 if (kind == MASS) {
629 name = "debm_insolation_driven_melt_rate";
630 accumulator_units = "kg";
631 internal_units = "kg second^-1";
632 external_units = "Gt year^-1";
633 }
634
635 m_accumulator.metadata().units(accumulator_units);
636
637 m_vars = { { m_sys, name, *m_grid } };
638 m_vars[0]
639 .long_name(long_name)
640 .units(internal_units)
641 .output_units(external_units);
642 m_vars[0].set_string("cell_methods", "time: mean");
643
644 double fill_value = units::convert(m_sys, m_fill_value, external_units, internal_units);
645 m_vars[0].set_number("_FillValue", fill_value);
646 }
647
648protected:
650 const auto &melt_amount = model->insolation_driven_melt();
651
652 if (m_kind == MASS) {
653 m_melt_mass.copy_from(melt_amount);
654 m_melt_mass.scale(m_grid->cell_area());
655 return m_melt_mass;
656 }
657
658 return melt_amount;
659 }
660
661private:
664};
665
666/*! @brief Report surface temperature melt, averaged over the reporting interval */
667class DEBMSTemperatureMelt : public DiagAverageRate<DEBMSimple> {
668public:
671 kind == AMOUNT
672 ? "debm_temperature_driven_melt_flux"
673 : "debm_temperature_driven_melt_rate",
675 m_kind(kind),
676 m_melt_mass(m_grid, "temperature_melt_mass") {
677
678 std::string
679 name = "debm_temperature_driven_melt_flux",
680 long_name = "temperature-driven melt, averaged over the reporting interval",
681 accumulator_units = "kg m^-2",
682 internal_units = "kg m^-2 second^-1",
683 external_units = "kg m^-2 year^-1";
684 if (kind == MASS) {
685 name = "debm_temperature_driven_melt_rate";
686 accumulator_units = "kg";
687 internal_units = "kg second^-1";
688 external_units = "Gt year^-1";
689 }
690
691 m_accumulator.metadata().units(accumulator_units);
692
693 m_vars = { { m_sys, name, *m_grid } };
694 m_vars[0]
695 .long_name(long_name)
696 .units(internal_units)
697 .output_units(external_units);
698 m_vars[0].set_string("cell_methods", "time: mean");
699 m_vars[0].set_number("_FillValue", to_internal(m_fill_value));
700 }
701
702protected:
704 const auto &melt_amount = model->temperature_driven_melt();
705
706 if (m_kind == MASS) {
707 m_melt_mass.copy_from(melt_amount);
708 m_melt_mass.scale(m_grid->cell_area());
709 return m_melt_mass;
710 }
711
712 return melt_amount;
713 }
714
715private:
718};
719
720/*! @brief Report surface backround melt, averaged over the reporting interval */
721class DEBMSBackroundMelt : public DiagAverageRate<DEBMSimple> {
722public:
725 kind == AMOUNT
726 ? "debm_offset_melt_flux"
727 : "debm_offset_melt_rate",
729 m_kind(kind),
730 m_melt_mass(m_grid, "backround_melt_mass") {
731
732 std::string name = "debm_offset_melt_flux",
733 long_name = "offset melt, averaged over the reporting interval",
734 accumulator_units = "kg m^-2",
735 internal_units = "kg m^-2 second^-1",
736 external_units = "kg m^-2 year^-1";
737
738 if (kind == MASS) {
739 name = "debm_offset_melt_rate";
740 accumulator_units = "kg";
741 internal_units = "kg second^-1";
742 external_units = "Gt year^-1";
743 }
744 m_accumulator.metadata().units(accumulator_units);
745
746 m_vars = { { m_sys, name, *m_grid } };
747 m_vars[0]
748 .long_name(long_name)
749 .units(internal_units)
750 .output_units(external_units);
751 m_vars[0].set_string("cell_methods", "time: mean");
752 m_vars[0].set_number("_FillValue", to_internal(m_fill_value));
753 }
754
755protected:
757 const auto &melt_amount = model->offset_melt();
758
759 if (m_kind == MASS) {
760 m_melt_mass.copy_from(melt_amount);
761 m_melt_mass.scale(m_grid->cell_area());
762 return m_melt_mass;
763 }
764
765 return melt_amount;
766 }
767
768private:
771};
772
773} // end of namespace diagnostics
774
775/*! @brief The number of points for temperature and precipitation time-series.
776 */
777unsigned int DEBMSimple::timeseries_length(double dt) const {
778 double dt_years = dt / m_year_length;
779
780 return std::max(1U, static_cast<unsigned int>(ceil(m_n_per_year * dt_years)));
781}
782
784 using namespace diagnostics;
785
786 DiagnosticList result = {
787 { "debm_insolation_driven_melt_flux", Diagnostic::Ptr(new DEBMSInsolationMelt(this, AMOUNT)) },
788 { "debm_insolation_driven_melt_rate", Diagnostic::Ptr(new DEBMSInsolationMelt(this, MASS)) },
789 { "debm_temperature_driven_melt_flux", Diagnostic::Ptr(new DEBMSTemperatureMelt(this, AMOUNT)) },
790 { "debm_temperature_driven_melt_rate", Diagnostic::Ptr(new DEBMSTemperatureMelt(this, MASS)) },
791 { "debm_offset_melt_flux", Diagnostic::Ptr(new DEBMSBackroundMelt(this, AMOUNT)) },
792 { "debm_offset_melt_rate", Diagnostic::Ptr(new DEBMSBackroundMelt(this, MASS)) },
793 { "air_temp_sd", Diagnostic::wrap(*m_air_temp_sd) },
794 { "snow_depth", Diagnostic::wrap(m_snow_depth) },
795 { "surface_albedo", Diagnostic::wrap(m_surface_albedo) },
796 { "atmosphere_transmissivity", Diagnostic::wrap(m_transmissivity) },
797 { "insolation", Diagnostic::Ptr(new DEBMSInsolation(this)) }
798 };
799
801
802 return result;
803}
804
805} // end of namespace surface
806} // end of namespace pism
const units::System::Ptr m_sys
unit system used by this component
Definition Component.hh:162
const Time & time() const
Definition Component.cc:111
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
void regrid(const std::string &module_name, array::Array &variable, RegriddingFlag flag=NO_REGRID_WITHOUT_REGRID_VARS)
Definition Component.cc:152
std::shared_ptr< const Logger > m_log
logger (for easy access)
Definition Component.hh:164
const DEBMSimple * model
A template derived from Diagnostic, adding a "Model".
std::vector< VariableMetadata > m_vars
metadata corresponding to NetCDF variables
static Ptr wrap(const T &input)
double m_fill_value
fill value (used often enough to justify storing it)
const units::System::Ptr m_sys
the unit system
double to_internal(double x) const
Definition Diagnostic.cc:62
std::shared_ptr< Diagnostic > Ptr
Definition Diagnostic.hh:67
std::shared_ptr< const Grid > m_grid
the grid
High-level PISM I/O class.
Definition File.hh:57
array::Scalar2 ice_surface_elevation
Definition Geometry.hh:57
array::CellType2 cell_type
Definition Geometry.hh:55
array::Scalar2 ice_thickness
Definition Geometry.hh:51
array::Scalar latitude
Definition Geometry.hh:41
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
double increment_date(double T, double years) const
Definition Time.cc:867
double calendar_year_start(double T) const
Returns the model time in seconds corresponding to the beginning of the year T falls into.
Definition Time.cc:858
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
VariableMetadata & standard_name(const std::string &input)
VariableMetadata & set_number(const std::string &name, double value)
Set a scalar attribute to a single (scalar) value.
VariableMetadata & output_units(const std::string &input)
VariableMetadata & set_string(const std::string &name, const std::string &value)
Set a string attribute.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
void copy_from(const Array2D< T > &source)
Definition Array2D.hh:101
void add(double alpha, const Array2D< T > &x)
Definition Array2D.hh:93
void read(const std::string &filename, unsigned int time)
Definition Array.cc:753
void write(const OutputFile &file) const
Definition Array.cc:859
void scale(double alpha)
Result: v <- v * alpha. Calls VecScale.
Definition Array.cc:227
void set(double c)
Result: v[j] <- c for all j.
Definition Array.cc:659
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
static std::shared_ptr< Forcing > Constant(std::shared_ptr< const Grid > grid, const std::string &short_name, double value)
Definition Forcing.cc:148
double albedo(double melt_rate, MaskValue cell_type) const
DEBMSimpleMelt melt(double declination, double distance_factor, double dt, double T_std_deviation, double T, double surface_elevation, double lat, double albedo) const
double atmosphere_transmissivity(double elevation) const
DEBMSimpleOrbitalParameters orbital_parameters(double time) const
DEBMSimpleChanges step(double ice_thickness, double max_melt, double snow_depth, double accumulation) const
Compute the surface mass balance at a location from the amount of melted snow and the solid accumulat...
A dEBM-simple implementation.
array::Scalar m_insolation_driven_melt
total insolation melt during the last time step
const array::Scalar & atmosphere_transmissivity() const
virtual const array::Scalar & mass_flux_impl() const
std::shared_ptr< array::Scalar > m_melt
total melt during the last time step
virtual void update_impl(const Geometry &geometry, double t, double dt)
double snow_accumulation(double T, double P) const
Extracts snow accumulation from mixed (snow and rain) precipitation using a temperature threshold wit...
const array::Scalar & insolation_driven_melt() const
const array::Scalar & surface_albedo() const
array::Scalar m_surface_albedo
albedo field
array::Scalar m_mass_flux
cached surface mass balance rate
Definition DEBMSimple.hh:87
std::shared_ptr< array::Scalar > m_runoff
total runoff during the last time step
array::Scalar m_temperature_driven_melt
total temperature melt during the last time step
const array::Scalar & air_temp_sd() const
array::Scalar m_snow_depth
snow depth (reset once a year)
Definition DEBMSimple.hh:92
std::shared_ptr< array::Forcing > m_air_temp_sd
standard deviation of the daily variability of the air temperature
Definition DEBMSimple.hh:95
virtual DiagnosticList spatial_diagnostics_impl() const
double m_Tmax
the temperature above which all precipitation is rain
const array::Scalar & runoff_impl() const
unsigned int m_n_per_year
number of small time steps per year
array::Scalar m_transmissivity
transmissivity field
double compute_next_balance_year_start(double time)
std::shared_ptr< array::Scalar > m_accumulation
total accumulation during the last time step
Definition DEBMSimple.hh:98
unsigned int timeseries_length(double dt) const
The number of points for temperature and precipitation time-series.
DEBMSimplePointwise m_model
Definition DEBMSimple.hh:82
const array::Scalar & offset_melt() const
const array::Scalar & accumulation_impl() const
const array::Scalar & snow_depth() const
const array::Scalar & temperature_driven_melt() const
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
virtual MaxTimestep max_timestep_impl(double t) const
const array::Scalar & melt_impl() const
array::Scalar m_offset_melt
total offset_melt during the last timestep
DEBMSimple(std::shared_ptr< const Grid > g, std::shared_ptr< atmosphere::AtmosphereModel > input)
Definition DEBMSimple.cc:44
virtual void init_impl(const Geometry &geometry)
double m_Tmin
the temperature below which all precipitation is snow
std::shared_ptr< array::Scalar > m_temperature
Definition DEBMSimple.hh:89
const DEBMSimplePointwise & pointwise_model() const
virtual std::set< VariableMetadata > state_impl() const
std::shared_ptr< array::Forcing > m_input_albedo
if albedo is given as input field
virtual const array::Scalar & temperature_impl() const
bool m_precip_as_snow
interpret all the precipitation as snow (no rain)
A class implementing a temperature-index (positive degree-day) scheme to compute melt and runoff,...
Definition DEBMSimple.hh:39
static std::shared_ptr< array::Scalar > allocate_runoff(std::shared_ptr< const Grid > grid)
std::shared_ptr< atmosphere::AtmosphereModel > m_atmosphere
static std::shared_ptr< array::Scalar > allocate_temperature(std::shared_ptr< const Grid > grid)
const array::Scalar & accumulation() const
Returns accumulation.
static std::shared_ptr< array::Scalar > allocate_accumulation(std::shared_ptr< const Grid > grid)
static std::shared_ptr< array::Scalar > allocate_melt(std::shared_ptr< const Grid > grid)
virtual void write_state_impl(const OutputFile &output) const
The default (empty implementation).
virtual std::set< VariableMetadata > state_impl() const
virtual DiagnosticList spatial_diagnostics_impl() const
virtual void init_impl(const Geometry &geometry)
The interface of PISM's surface models.
DEBMSBackroundMelt(const DEBMSimple *m, AmountKind kind)
Report surface backround melt, averaged over the reporting interval.
DEBMSInsolationMelt(const DEBMSimple *m, AmountKind kind)
Report surface insolation melt, averaged over the reporting interval.
std::shared_ptr< array::Array > compute_impl() const
Report mean top of atmosphere insolation.
DEBMSTemperatureMelt(const DEBMSimple *m, AmountKind kind)
Report surface temperature melt, averaged over the reporting interval.
#define PISM_ERROR_LOCATION
std::set< VariableMetadata > metadata(std::initializer_list< const Array * > vecs)
Definition Array.cc:1244
@ PISM_GUESS
Definition IO_Flags.hh:57
@ PISM_READONLY
open an existing file for reading only
Definition IO_Flags.hh:69
bool ice_free_ocean(int M)
Definition Mask.hh:61
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
@ INIT_BOOTSTRAP
Definition Component.hh:56
@ INIT_RESTART
Definition Component.hh:56
std::map< std::string, Diagnostic::Ptr > DiagnosticList
static const double k
Definition exactTestP.cc:42
MaskValue
Definition Mask.hh:30
T combine(const T &a, const T &b)
InputOptions process_input_options(MPI_Comm com, std::shared_ptr< const Config > config)
Definition Component.cc:45
InitializationType type
initialization type
Definition Component.hh:61
std::string filename
name of the input file (if applicable)
Definition Component.hh:63
unsigned int record
index of the record to re-start from
Definition Component.hh:65
static double S(unsigned n)
Definition test_cube.c:58