23#include "pism/age/AgeModel.hh"
24#include "pism/energy/EnergyModel.hh"
25#include "pism/energy/utilities.hh"
26#include "pism/geometry/grounded_cell_fraction.hh"
27#include "pism/geometry/part_grid_threshold_thickness.hh"
28#include "pism/icemodel/IceModel.hh"
29#include "pism/rheology/FlowLaw.hh"
30#include "pism/stressbalance/SSB_Modifier.hh"
31#include "pism/stressbalance/ShallowStressBalance.hh"
32#include "pism/stressbalance/StressBalance.hh"
33#include "pism/util/Diagnostic.hh"
34#include "pism/util/EnthalpyConverter.hh"
35#include "pism/util/error_handling.hh"
36#include "pism/util/pism_utilities.hh"
37#include "pism/util/projection.hh"
38#include "pism/util/io/IO_Flags.hh"
40#if (Pism_USE_PROJ == 1)
41#include "pism/util/Proj.hh"
46namespace diagnostics {
59 std::string name =
"tendency_of_ice_amount", long_name =
"rate of change of the ice amount",
60 internal_units =
"kg m^-2 second^-1", external_units =
"kg m^-2 year^-1";
62 name =
"tendency_of_ice_mass";
63 long_name =
"rate of change of the ice mass";
64 internal_units =
"kg second^-1";
65 external_units =
"Gt year^-1";
70 m_vars[0].long_name(long_name).units(internal_units).output_units(external_units);
73 m_vars[0][
"valid_range"] = { -large_number, large_number };
75 m_vars[0][
"cell_methods"] =
"time: mean";
78 .
long_name(
"ice amount at the time of the last report of " + name)
79 .
units(internal_units +
" second");
85 auto result = std::make_shared<array::Scalar>(
m_grid,
"");
86 result->metadata() =
m_vars[0];
89 double ice_density =
m_config->get_number(
"constants.ice.density");
91 auto cell_area =
m_grid->cell_area();
98 for (
auto p :
m_grid->points()) {
99 const int i = p.i(), j = p.j();
102 double amount = (thickness(i, j) + area_specific_volume(i, j)) * ice_density;
108 (*result)(i, j) *= cell_area;
124 double ice_density =
m_config->get_number(
"constants.ice.density");
128 for (
auto p :
m_grid->points()) {
129 const int i = p.i(), j = p.j();
132 m_last_amount(i, j) = (thickness(i, j) + area_specific_volume(i, j)) * ice_density;
152 kind ==
AMOUNT ?
"tendency_of_ice_amount_due_to_flow" :
153 "tendency_of_ice_mass_due_to_flow",
157 std::string name =
"tendency_of_ice_amount_due_to_flow",
158 long_name =
"rate of change of ice amount due to flow",
159 accumulator_units =
"kg m^-2", internal_units =
"kg m^-2 second^-1",
160 external_units =
"kg m^-2 year^-1";
163 name =
"tendency_of_ice_mass_due_to_flow";
164 long_name =
"rate of change of ice mass due to flow";
165 accumulator_units =
"kg";
166 internal_units =
"kg second^-1";
167 external_units =
"Gt year^-1";
176 m_vars[0][
"cell_methods"] =
"time: mean";
178 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
184 &dV =
model->geometry_evolution().area_specific_volume_change_due_to_flow();
186 auto cell_area =
m_grid->cell_area();
190 for (
auto p :
m_grid->points()) {
191 const int i = p.i(), j = p.j();
209 "tendency_of_ice_amount_due_to_surface_mass_flux" :
210 "tendency_of_ice_mass_due_to_surface_mass_flux",
215 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
217 std::string name = ismip6 ?
"acabf" :
"tendency_of_ice_amount_due_to_surface_mass_flux",
218 accumulator_units =
"kg m^-2",
219 long_name =
"average surface mass flux over reporting interval",
220 standard_name =
"land_ice_surface_specific_mass_balance_flux",
221 internal_units =
"kg m^-2 s^-1", external_units =
"kg m^-2 year^-1";
223 name =
"tendency_of_ice_mass_due_to_surface_mass_flux", accumulator_units =
"kg",
224 long_name =
"average surface mass flux over reporting interval", standard_name =
"",
225 internal_units =
"kg second^-1", external_units =
"Gt year^-1";
234 .
units(internal_units)
237 m_vars[0][
"cell_methods"] =
"time: mean";
238 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
245 auto cell_area =
m_grid->cell_area();
249 for (
auto p :
m_grid->points()) {
250 const int i = p.i(), j = p.j();
267 kind ==
AMOUNT ?
"tendency_of_ice_amount_due_to_basal_mass_flux" :
268 "tendency_of_ice_mass_due_to_basal_mass_flux",
273 std::string name =
"tendency_of_ice_amount_due_to_basal_mass_flux",
274 accumulator_units =
"kg m^-2",
275 long_name =
"average basal mass flux over reporting interval", standard_name,
276 internal_units =
"kg m^-2 second^-1", external_units =
"kg m^-2 year^-1";
278 name =
"tendency_of_ice_mass_due_to_basal_mass_flux", accumulator_units =
"kg",
279 long_name =
"average basal mass flux over reporting interval",
280 standard_name =
"tendency_of_land_ice_mass_due_to_basal_mass_balance",
281 internal_units =
"kg second^-1", external_units =
"Gt year^-1";
289 .
units(internal_units)
292 m_vars[0][
"cell_methods"] =
"time: mean";
293 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
300 auto cell_area =
m_grid->cell_area();
304 for (
auto p :
m_grid->points()) {
305 const int i = p.i(), j = p.j();
322 "tendency_of_ice_amount_due_to_conservation_error" :
323 "tendency_of_ice_mass_due_to_conservation_error",
328 std::string name =
"tendency_of_ice_amount_due_to_conservation_error",
329 accumulator_units =
"kg m^-2",
330 long_name =
"average mass conservation error flux over reporting interval",
331 internal_units =
"kg m^-2 second^-1", external_units =
"kg m^-2 year^-1";
333 name =
"tendency_of_ice_mass_due_to_conservation_error", accumulator_units =
"kg",
334 long_name =
"average mass conservation error flux over reporting interval",
335 internal_units =
"kg second^-1", external_units =
"Gt year^-1";
343 .
units(internal_units)
346 m_vars[0][
"cell_methods"] =
"time: mean";
347 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
353 &error =
model->geometry_evolution().conservation_error();
357 auto cell_area =
m_grid->cell_area();
359 for (
auto p :
m_grid->points()) {
360 const int i = p.i(), j = p.j();
377 const auto &calving = model->
calving();
381 auto grid = accumulator.
grid();
391 if (add_frontal_melt) {
392 scope.add(frontal_melt);
394 if (add_forced_retreat) {
395 scope.add(forced_retreat);
398 for (
auto p : grid->points()) {
399 const int i = p.i(), j = p.j();
402 accumulator(i, j) += factor * calving(i, j);
404 if (add_frontal_melt) {
405 accumulator(i, j) += factor * frontal_melt(i, j);
407 if (add_forced_retreat) {
408 accumulator(i, j) += factor * forced_retreat(i, j);
419 kind ==
AMOUNT ?
"tendency_of_ice_amount_due_to_discharge" :
420 "tendency_of_ice_mass_due_to_discharge",
426 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
428 std::string name = ismip6 ?
"lifmassbf" :
"tendency_of_ice_amount_due_to_discharge",
429 long_name =
"discharge flux (calving, frontal melt, forced retreat)",
430 accumulator_units =
"kg m^-2",
431 standard_name =
"land_ice_specific_mass_flux_due_to_calving_and_ice_front_melting",
432 internal_units =
"kg m^-2 s^-1", external_units =
"kg m^-2 year^-1";
434 name =
"tendency_of_ice_mass_due_to_discharge";
435 long_name =
"discharge flux (calving, frontal melt, forced retreat)";
436 accumulator_units =
"kg";
438 internal_units =
"kg second^-1";
439 external_units =
"Gt year^-1";
448 .
units(internal_units)
450 m_vars[0][
"cell_methods"] =
"time: mean";
452 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
474 ?
"tendency_of_ice_amount_due_to_calving"
475 :
"tendency_of_ice_mass_due_to_calving",
481 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
484 name = ismip6 ?
"licalvf" :
"tendency_of_ice_amount_due_to_calving",
485 long_name =
"calving flux",
486 accumulator_units =
"kg m^-2",
487 standard_name =
"land_ice_specific_mass_flux_due_to_calving",
488 internal_units =
"kg m^-2 s^-1",
489 external_units =
"kg m^-2 year^-1";
491 name =
"tendency_of_ice_mass_due_to_calving";
492 long_name =
"calving flux";
493 accumulator_units =
"kg";
495 internal_units =
"kg second^-1";
496 external_units =
"Gt year^-1";
505 .
units(internal_units)
507 m_vars[0][
"cell_methods"] =
"time: mean";
510 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
533 ?
"tendency_of_ice_amount_due_to_frontal_melt"
534 :
"tendency_of_ice_mass_due_to_frontal_melt",
540 std::string name =
"tendency_of_ice_amount_due_to_frontal_melt", accumulator_units =
"kg m^-2",
541 internal_units =
"kg m^-2 s^-1", external_units =
"kg m^-2 year^-1";
543 name =
"tendency_of_ice_mass_due_to_frontal_melt";
544 accumulator_units =
"kg";
545 internal_units =
"kg second^-1";
546 external_units =
"Gt year^-1";
553 m_vars[0][
"cell_methods"] =
"time: mean";
555 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
577 kind ==
AMOUNT ?
"tendency_of_ice_amount_due_to_forced_retreat" :
578 "tendency_of_ice_mass_due_to_forced_retreat",
584 std::string name =
"tendency_of_ice_amount_due_to_forced_retreat", accumulator_units =
"kg m^-2",
585 internal_units =
"kg m^-2 s^-1", external_units =
"kg m^-2 year^-1";
587 name =
"tendency_of_ice_mass_due_to_forced_retreat";
588 accumulator_units =
"kg";
589 internal_units =
"kg second^-1";
590 external_units =
"Gt year^-1";
597 .
long_name(
"forced (prescribed) retreat flux")
598 .
units(internal_units)
600 m_vars[0][
"cell_methods"] =
"time: mean";
602 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
629 double thickness_threshold) {
631 auto grid = ice_thickness.
grid();
632 auto ctx = grid->ctx();
633 auto EC = ctx->enthalpy_converter();
635 auto cell_area = grid->cell_area();
636 const auto& z = grid->z();
648 auto volume_counter = [EC, kind, cell_area](
double z_min,
double z_max,
double H,
double E) {
649 double depth = H - z_min;
650 double P = EC->pressure(depth);
651 double V = cell_area * (z_max - z_min);
652 bool temperate = EC->is_temperate_relaxed(E, P);
656 return temperate ? V : 0.0;
659 return (not temperate) ? V : 0.0;
666 for (
auto p : grid->points()) {
667 const int i = p.i(), j = p.j();
669 double H = ice_thickness(i, j);
671 if (H >= thickness_threshold) {
672 auto ks = grid->kBelowHeight(H);
673 const double *E = ice_enthalpy.
get_column(i, j);
675 for (
unsigned int k = 0;
k < ks; ++
k) {
676 volume += volume_counter(z[
k], z[
k + 1], H, E[
k]);
679 volume += volume_counter(z[ks], H, H, E[ks]);
693 double thickness_threshold) {
695 auto grid = ice_thickness.
grid();
696 auto ctx = grid->ctx();
697 auto EC = ctx->enthalpy_converter();
699 auto cell_area = grid->cell_area();
706 for (
auto p : grid->points()) {
707 const int i = p.i(), j = p.j();
709 double thickness = ice_thickness(i, j);
711 if (thickness >= thickness_threshold) {
712 double basal_enthalpy = ice_enthalpy.
get_column(i, j)[0];
714 bool temperate = EC->is_temperate_relaxed(basal_enthalpy,
715 EC->pressure(thickness));
719 area += temperate ? cell_area : 0.0;
723 area += (not temperate) ? cell_area : 0.0;
742namespace diagnostics {
765 "vertically-averaged pressure difference at ice margins (including calving fronts)")
771 auto result = allocate<array::Scalar>(
"ice_margin_pressure_difference");
780 const double H_threshold =
m_config->get_number(
"stress_balance.ice_free_thickness_standard");
788 rho_ocean =
m_config->get_number(
"constants.sea_water.density"),
789 g =
m_config->get_number(
"constants.standard_gravity");
795 for (
auto p :
m_grid->points()) {
796 const int i = p.i(), j = p.j();
798 double delta_p = 0.0;
802 double P_ice = 0.5 *
rho_ice *
g * H(i, j),
806 delta_p = P_ice - P_water;
811 (*result)(i, j) = delta_p;
828 m, flag ==
GROUNDED ?
"basal_mass_flux_grounded" :
"basal_mass_flux_floating",
831 assert(flag !=
BOTH);
833 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
835 std::string name, description, standard_name;
837 name = ismip6 ?
"libmassbfgr" :
"basal_mass_flux_grounded";
838 description =
"average basal mass flux over the reporting interval (grounded areas)";
839 standard_name = ismip6 ?
"land_ice_basal_specific_mass_balance_flux" :
"";
841 name = ismip6 ?
"libmassbffl" :
"basal_mass_flux_floating";
842 description =
"average basal mass flux over the reporting interval (floating areas)";
843 standard_name = ismip6 ?
"land_ice_basal_specific_mass_balance_flux" :
"";
852 .
units(
"kg m^-2 s^-1")
854 m_vars[0][
"cell_methods"] =
"time: mean";
856 m_vars[0][
"comment"] =
"positive flux corresponds to ice gain";
862 const array::Scalar &input =
model->geometry_evolution().bottom_surface_mass_balance();
863 const auto &cell_type =
model->geometry().cell_type;
865 double ice_density =
m_config->get_number(
"constants.ice.density");
873 for (
auto p :
m_grid->points()) {
874 const int i = p.i(), j = p.j();
878 }
else if (
m_kind ==
SHELF and cell_type.ocean(i, j)) {
895 virtual std::shared_ptr<array::Array>
compute_impl()
const;
903 .long_name(
"vertical average of ice hardness")
904 .set_units_without_validation(
906 m_vars[0][
"valid_min"] = { 0.0 };
908 m_vars[0][
"comment"] =
"units depend on the Glen exponent used by the flow law";
915 if (flow_law == NULL) {
917 if (flow_law == NULL) {
919 "Can't compute vertically-averaged hardness: no flow law is used.");
923 auto result = std::make_shared<array::Scalar>(
m_grid,
"hardav");
924 result->metadata() =
m_vars[0];
934 for (
auto p :
m_grid->points()) {
935 const int i = p.i(), j = p.j();
937 const double *Eij = ice_enthalpy.
get_column(i, j);
938 const double H = ice_thickness(i, j);
939 if (cell_type.icy(i, j)) {
960 virtual std::shared_ptr<array::Array>
compute_impl()
const;
966 .long_name(
"processor rank")
968 .set_time_dependent(
false)
974 auto result = std::make_shared<array::Scalar>(
m_grid,
"rank");
975 result->metadata() =
m_vars[0];
979 for (
auto p :
m_grid->points()) {
980 (*result)(p.i(), p.j()) =
m_grid->rank();
992 virtual std::shared_ptr<array::Array>
compute_impl()
const;
998 .long_name(
"cts = E/E_s(p), so cold-temperate transition surface is at cts = 1")
1005 result->metadata() =
m_vars[0];
1019 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1025 .long_name(
"ice temperature")
1026 .standard_name(
"land_ice_temperature")
1028 m_vars[0][
"valid_min"] = { 0.0 };
1033 std::shared_ptr<array::Array3D> result(
1035 result->metadata() =
m_vars[0];
1040 auto EC =
model->
ctx()->enthalpy_converter();
1043 const double *Enthij;
1049 for (
auto p :
m_grid->points()) {
1050 const int i = p.i(), j = p.j();
1052 Tij = result->get_column(i,j);
1053 Enthij = enthalpy.get_column(i,j);
1054 for (
unsigned int k=0;
k <
m_grid->Mz(); ++
k) {
1055 const double depth = thickness(i,j) -
m_grid->z(
k);
1056 Tij[
k] = EC->temperature(Enthij[
k], EC->pressure(depth));
1074 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1082 .long_name(
"pressure-adjusted ice temperature (degrees above pressure-melting point)")
1084 m_vars[0][
"valid_max"] = {0};
1089 double melting_point_temp =
m_config->get_number(
"constants.fresh_water.melting_point_temperature");
1092 result->metadata() =
m_vars[0];
1097 auto EC =
model->
ctx()->enthalpy_converter();
1100 const double *Enthij;
1106 for (
auto pt :
m_grid->points()) {
1107 const int i = pt.i(), j = pt.j();
1109 Tij = result->get_column(i,j);
1110 Enthij = enthalpy.get_column(i,j);
1111 for (
unsigned int k=0;
k <
m_grid->Mz(); ++
k) {
1112 const double depth = thickness(i,j) -
m_grid->z(
k),
1113 p = EC->pressure(depth);
1114 Tij[
k] = EC->pressure_adjusted_temperature(Enthij[
k], p);
1118 if (EC->is_temperate_relaxed(Enthij[
k],p) && (thickness(i,j) > 0)) {
1119 Tij[
k] = melting_point_temp;
1130 result->shift(-melting_point_temp);
1141 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1147 m_vars[0].long_name(
"pressure-adjusted ice temperature at the base of ice").units(
"degree_Celsius");
1153 double melting_point_temp =
m_config->get_number(
"constants.fresh_water.melting_point_temperature");
1155 auto result = std::make_shared<array::Scalar>(
m_grid,
"temp_pa_base");
1156 result->metadata() =
m_vars[0];
1161 auto EC =
model->
ctx()->enthalpy_converter();
1167 for (
auto pt :
m_grid->points()) {
1168 const int i = pt.i(), j = pt.j();
1170 const auto *Enthij = enthalpy.get_column(i,j);
1172 const double depth = thickness(i,j),
1173 p = EC->pressure(depth);
1174 (*result)(i,j) = EC->pressure_adjusted_temperature(Enthij[0], p);
1178 if (EC->is_temperate_relaxed(Enthij[0],p) && (thickness(i,j) > 0)) {
1179 (*result)(i,j) = melting_point_temp;
1188 result->shift(-melting_point_temp);
1199 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1205 m_vars[0].long_name(
"ice enthalpy at 1m below the ice surface").units(
"J kg^-1");
1211 auto result = std::make_shared<array::Scalar>(
m_grid,
"enthalpysurf");
1212 result->metadata() =
m_vars[0];
1221 for (
auto p :
m_grid->points()) {
1222 const int i = p.i(), j = p.j();
1224 (*result)(i,j) = std::max(ice_thickness(i,j) - 1.0, 0.0);
1227 extract_surface(ice_enthalpy, *result, *result);
1229 for (
auto p :
m_grid->points()) {
1230 const int i = p.i(), j = p.j();
1232 if (ice_thickness(i,j) <= 1.0) {
1246 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1252 m_vars[0].long_name(
"ice enthalpy at the base of ice").units(
"J kg^-1");
1258 auto result = std::make_shared<array::Scalar>(
m_grid,
"enthalpybase");
1259 result->metadata() =
m_vars[0];
1282 std::string name, long_name, standard_name;
1283 switch (area_type) {
1285 name =
"litempbotgr";
1286 long_name =
"ice temperature at the bottom surface of grounded ice";
1287 standard_name =
"temperature_at_base_of_ice_sheet_model";
1290 name =
"litempbotfl";
1291 long_name =
"ice temperature at the bottom surface of floating ice";
1292 standard_name =
"temperature_at_base_of_ice_sheet_model";
1296 long_name =
"ice temperature at the base of ice";
1297 standard_name =
"land_ice_basal_temperature";
1302 m_vars[0].long_name(long_name).standard_name(standard_name).units(
"kelvin");
1308 auto result = allocate<array::Scalar>(
"basal_temperature");
1312 auto EC =
model->
ctx()->enthalpy_converter();
1323 for (
auto p :
m_grid->points()) {
1324 const int i = p.i(), j = p.j();
1326 double depth = thickness(i, j), pressure = EC->pressure(depth),
1327 T = EC->temperature((*result)(i, j), pressure);
1332 (*result)(i, j) = T;
1351 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1357 .long_name(
"ice temperature at 1m below the ice surface")
1358 .standard_name(
"temperature_at_ground_level_in_snow_or_firn")
1368 auto result = array::cast<array::Scalar>(enth);
1370 auto EC =
model->
ctx()->enthalpy_converter();
1377 double depth = 1.0, pressure = EC->pressure(depth);
1380 for (
auto p :
m_grid->points()) {
1381 const int i = p.i(), j = p.j();
1383 if (thickness(i, j) > 1) {
1384 (*result)(i, j) = EC->temperature((*result)(i, j), pressure);
1394 result->metadata(0) =
m_vars[0];
1404 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1409 m_vars[0].long_name(
"liquid water fraction in ice (between 0 and 1)").units(
"1");
1410 m_vars[0][
"valid_range"] = { 0.0, 1.0 };
1415 std::shared_ptr<array::Array3D> result(
1417 result->metadata(0) =
m_vars[0];
1437 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1442 m_vars[0].long_name(
"temperate ice thickness (total column content)").units(
"m");
1448 auto result = allocate<array::Scalar>(
"tempicethk");
1456 auto EC =
model->
ctx()->enthalpy_converter();
1460 for (
auto p :
m_grid->points()) {
1461 const int i = p.i(), j = p.j();
1463 if (cell_type.icy(i, j)) {
1464 const double *Enth = ice_enthalpy.get_column(i, j);
1465 double H_temperate = 0.0;
1466 const double H = ice_thickness(i, j);
1467 const unsigned int ks =
m_grid->kBelowHeight(H);
1469 for (
unsigned int k = 0;
k < ks; ++
k) {
1470 double pressure = EC->pressure(H -
m_grid->z(
k));
1472 if (EC->is_temperate_relaxed(Enth[
k], pressure)) {
1477 double pressure = EC->pressure(H -
m_grid->z(ks));
1478 if (EC->is_temperate_relaxed(Enth[ks], pressure)) {
1479 H_temperate += H -
m_grid->z(ks);
1482 (*result)(i, j) = H_temperate;
1502 virtual std::shared_ptr<array::Array>
compute_impl()
const;
1507 m_vars[0].long_name(
"thickness of the basal layer of temperate ice").units(
"m");
1516 auto result = allocate<array::Scalar>(
"tempicethk_basal");
1518 auto EC =
model->
ctx()->enthalpy_converter();
1528 for (
auto p :
m_grid->points()) {
1529 const int i = p.i(), j = p.j();
1531 double H = ice_thickness(i, j);
1535 if (cell_type.ice_free(i, j)) {
1540 const double *Enth = ice_enthalpy.get_column(i, j);
1542 unsigned int ks =
m_grid->kBelowHeight(H);
1545 double pressure = EC->pressure(H -
m_grid->z(
k));
1547 pressure = EC->pressure(H -
m_grid->z(
k));
1549 if (EC->is_temperate_relaxed(Enth[
k], pressure)) {
1560 (*result)(i, j) = 0.0;
1567 (*result)(i, j) =
m_grid->z(ks);
1572 slope1 = (Enth[
k] - Enth[
k - 1]) / dz,
1573 slope2 = (EC->enthalpy_cts(pressure) - EC->enthalpy_cts(pressure_0)) / dz;
1575 if (slope1 != slope2) {
1577 m_grid->z(
k - 1) + (EC->enthalpy_cts(pressure_0) - Enth[
k - 1]) / (slope1 - slope2);
1580 (*result)(i, j) = std::max((*result)(i, j),
m_grid->z(
k - 1));
1581 (*result)(i, j) = std::min((*result)(i, j),
m_grid->z(
k));
1584 "Linear interpolation of the thickness of"
1585 " the basal temperate layer failed:\n"
1586 "(i=%d, j=%d, k=%d, ks=%d)\n",
1608 m_variable[
"long_name"] =
"volume of the ice in glacierized areas";
1613 m_config->get_number(
"output.ice_free_thickness_standard"));
1623 m_variable[
"long_name"] =
"volume of the ice, including seasonal cover";
1639 m_variable[
"long_name"] =
"the sea level rise that would result if all the ice were melted";
1645 m_config->get_number(
"output.ice_free_thickness_standard"));
1656 m_variable[
"long_name"] =
"rate of change of the ice volume in glacierized areas";
1661 m_config->get_number(
"output.ice_free_thickness_standard"));
1672 m_variable[
"long_name"] =
"rate of change of the ice volume, including seasonal cover";
1687 m_variable[
"long_name"] =
"glacierized area";
1703 m_variable[
"long_name"] =
"mass of the ice not displacing sea water";
1704 m_variable[
"standard_name"] =
"land_ice_mass_not_displacing_sea_water";
1710 const double thickness_standard =
m_config->get_number(
"output.ice_free_thickness_standard"),
1711 ice_density =
m_config->get_number(
"constants.ice.density"),
1727 m_variable[
"long_name"] =
"mass of the ice in glacierized areas";
1732 double ice_density =
m_config->get_number(
"constants.ice.density"),
1733 thickness_standard =
m_config->get_number(
"output.ice_free_thickness_standard");
1743 if (
m_config->get_flag(
"output.ISMIP6")) {
1748 m_variable[
"long_name"] =
"mass of the ice, including seasonal cover";
1749 m_variable[
"standard_name"] =
"land_ice_mass";
1765 m_variable[
"long_name"] =
"rate of change of the ice mass in glacierized areas";
1769 double ice_density =
m_config->get_number(
"constants.ice.density"),
1770 thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard");
1786 m_variable[
"long_name"] =
"rate of change of the mass of ice due to flow"
1787 " (i.e. prescribed ice thickness)";
1792 const double ice_density =
m_config->get_number(
"constants.ice.density");
1797 auto cell_area =
m_grid->cell_area();
1801 double volume_change = 0.0;
1802 for (
auto p :
m_grid->points()) {
1803 const int i = p.i(), j = p.j();
1805 volume_change += (dH(i, j) + dV(i, j)) * cell_area;
1819 m_variable[
"long_name"] =
"rate of change of the mass of ice, including seasonal cover";
1823 const double ice_density =
m_config->get_number(
"constants.ice.density");
1836 m_variable[
"long_name"] =
"volume of temperate ice in glacierized areas";
1841 auto thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard");
1844 thickness_threshold);
1855 m_variable[
"long_name"] =
"volume of temperate ice, including seasonal cover";
1873 m_variable[
"long_name"] =
"volume of cold ice in glacierized areas";
1878 auto thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard");
1881 thickness_threshold);
1891 m_variable[
"long_name"] =
"volume of cold ice, including seasonal cover";
1909 m_variable[
"long_name"] =
"glacierized area where basal ice is temperate";
1914 auto thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard");
1917 thickness_threshold);
1928 m_variable[
"long_name"] =
"glacierized area where basal ice is cold";
1933 auto thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard");
1936 thickness_threshold);
1947 m_variable[
"long_name"] =
"enthalpy of the ice in glacierized areas";
1964 m_variable[
"long_name"] =
"enthalpy of the ice, including seasonal cover";
1980 if (
m_config->get_flag(
"output.ISMIP6")) {
1985 m_variable[
"long_name"] =
"area of grounded ice in glacierized areas";
1986 m_variable[
"standard_name"] =
"grounded_ice_sheet_area";
1992 m_config->get_number(
"output.ice_free_thickness_standard"));
2002 if (
m_config->get_flag(
"output.ISMIP6")) {
2007 m_variable[
"long_name"] =
"area of ice shelves in glacierized areas";
2008 m_variable[
"standard_name"] =
"floating_ice_shelf_area";
2014 m_config->get_number(
"output.ice_free_thickness_standard"));
2025 m_variable[
"long_name"] =
"volume of grounded ice in glacierized areas";
2034 const double thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard"),
2035 cell_area =
m_grid->cell_area();
2039 double volume = 0.0;
2040 for (
auto p :
m_grid->points()) {
2041 const int i = p.i(), j = p.j();
2043 const double H = ice_thickness(i, j);
2045 if (cell_type.grounded(i, j) and H >= thickness_threshold) {
2046 volume += cell_area * H;
2061 m_variable[
"long_name"] =
"volume of ice shelves in glacierized areas";
2070 const double thickness_threshold =
m_config->get_number(
"output.ice_free_thickness_standard"),
2071 cell_area =
m_grid->cell_area();
2075 double volume = 0.0;
2076 for (
auto p :
m_grid->points()) {
2077 const int i = p.i(), j = p.j();
2079 const double H = ice_thickness(i, j);
2081 if (cell_type.ocean(i, j) and H >= thickness_threshold) {
2082 volume += cell_area * H;
2096 m_variable[
"long_name"] =
"mass continuity time step";
2111 m_variable[
"long_name"] =
"ratio of max. allowed time steps "
2112 "according to CFL and SIA diffusivity criteria";
2122 auto cfl_3d = stress_balance->max_timestep_cfl_3d();
2127 m_config->get_number(
"time_stepping.adaptive_ratio"));
2129 auto dt_cfl = std::min(cfl_2d.dt_max, cfl_3d.dt_max);
2131 if (dt_cfl.finite() and dt_diff.finite() and dt_diff.value() > 0.0) {
2132 return dt_cfl.value() / dt_diff.value();
2145 m_variable[
"long_name"] =
"maximum diffusivity of the flow (usually from the SIA model)";
2171 m_variable[
"long_name"] =
"max(max(abs(u)), max(abs(v))) for the horizontal velocity of ice"
2172 " over volume of the ice in last time step during time-series reporting interval";
2209 const Config &config = *grid.ctx()->config();
2211 const double ice_density = config.
get_number(
"constants.ice.density"),
2212 cell_area = grid.cell_area();
2245 double volume_change = 0.0;
2246 for (
auto p : grid.points()) {
2247 const int i = p.i(), j = p.j();
2249 if ((area ==
BOTH) or (area ==
GROUNDED and cell_type.grounded(i, j)) or
2250 (area ==
SHELF and cell_type.ocean(i, j))) {
2252 double dV = term ==
FLOW ? dV_flow(i, j) : 0.0;
2255 volume_change += cell_area * ((*thickness_change)(i, j) + dV);
2260 return ice_density *
GlobalSum(grid.com, volume_change);
2269 if (
m_config->get_flag(
"output.ISMIP6")) {
2274 m_variable[
"long_name"] =
"total over ice domain of bottom surface ice mass flux";
2275 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_basal_mass_balance";
2276 m_variable[
"comment"] =
"positive means ice gain";
2290 if (
m_config->get_flag(
"output.ISMIP6")) {
2295 m_variable[
"long_name"] =
"total over ice domain of top surface ice mass flux";
2296 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_surface_mass_balance";
2297 m_variable[
"comment"] =
"positive means ice gain";
2312 m_variable[
"long_name"] =
"total over grounded ice domain of basal mass flux";
2313 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_basal_mass_balance";
2314 m_variable[
"comment"] =
"positive means ice gain";
2328 if (
m_config->get_flag(
"output.ISMIP6")) {
2333 m_variable[
"long_name"] =
"total sub-shelf ice flux";
2334 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_basal_mass_balance";
2335 m_variable[
"comment"] =
"positive means ice gain";
2351 m_variable[
"long_name"] =
"total numerical flux needed to preserve non-negativity"
2352 " of ice thickness";
2353 m_variable[
"comment"] =
"positive means ice gain";
2367 if (
m_config->get_flag(
"output.ISMIP6")) {
2372 m_variable[
"long_name"] =
"discharge flux (frontal melt, calving, forced retreat)";
2373 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_calving_and_ice_front_melting";
2374 m_variable[
"comment"] =
"positive means ice gain";
2378 const double ice_density =
m_config->get_number(
"constants.ice.density");
2384 auto cell_area =
m_grid->cell_area();
2386 double volume_change = 0.0;
2390 for (
auto p :
m_grid->points()) {
2391 const int i = p.i(), j = p.j();
2393 volume_change += cell_area * (calving(i, j) + frontal_melt(i, j) + forced_retreat(i, j));
2407 if (
m_config->get_flag(
"output.ISMIP6")) {
2413 m_variable[
"standard_name"] =
"tendency_of_land_ice_mass_due_to_calving";
2414 m_variable[
"comment"] =
"positive means ice gain";
2418 const double ice_density =
m_config->get_number(
"constants.ice.density");
2422 auto cell_area =
m_grid->cell_area();
2424 double volume_change = 0.0;
2428 for (
auto p :
m_grid->points()) {
2429 const int i = p.i(), j = p.j();
2431 volume_change += cell_area * calving(i, j);
2445 if (
m_config->get_flag(
"output.ISMIP6")) {
2447 m_variable[
"standard_name"] =
"tendency_of_grounded_ice_mass";
2451 m_variable[
"long_name"] =
"total ice flux across the grounding line";
2452 m_variable[
"comment"] =
"negative flux corresponds to ice loss into the ocean";
2470 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
2475 .long_name(
"ice thickness rate of change")
2476 .standard_name(
"tendency_of_land_ice_thickness")
2478 .output_units(
"m year^-1");
2482 m_vars[0][
"valid_range"] = { -large_number, large_number };
2484 m_vars[0][
"cell_methods"] =
"time: mean";
2488 "ice thickness at the time of the last report of the rate of change of ice thickness")
2496 auto result = std::make_shared<array::Scalar>(
m_grid,
"dHdt");
2497 result->metadata() =
m_vars[0];
2528 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2534 const std::string &proj_string)
2536 assert(var_name ==
"lat" || var_name ==
"lon");
2541 m_vars[0].dimension(
"z").clear().set_name(
"nv4");
2543 m_vars[0].set_time_dependent(
false);
2545 m_vars[0].long_name(
"longitude bounds").units(
"degree_east");
2546 m_vars[0][
"valid_range"] = { -180, 180 };
2548 m_vars[0].long_name(
"latitude bounds").units(
"degree_north");
2549 m_vars[0][
"valid_range"] = { -90, 90 };
2554#if (Pism_USE_PROJ == 1)
2566 result->metadata(0) =
m_vars[0];
2582 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2588 .long_name(
"fraction of a grid cell covered by ice (grounded or floating)")
2589 .standard_name(
"land_ice_area_fraction")
2603 array::AccessScope list{ &thickness, &surface_elevation, &bed_topography, &cell_type,
2606 const bool do_part_grid =
m_config->get_flag(
"geometry.part_grid.enabled");
2615 for (
auto p :
m_grid->points()) {
2616 const int i = p.i(), j = p.j();
2618 if (cell_type.
icy(i, j)) {
2620 (*result)(i, j) = 1.0;
2625 double H_reference = do_part_grid ? Href(i, j) : 0.0;
2627 if (H_reference > 0.0) {
2628 const double H_threshold =
2630 surface_elevation.star(i, j), bed_topography(i, j));
2632 if (H_threshold > 0.0) {
2633 (*result)(i, j) = std::min(H_reference / H_threshold, 1.0);
2635 (*result)(i, j) = 1.0;
2639 (*result)(i, j) = 0.0;
2643 (*result)(i, j) = 0.0;
2659 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2665 .long_name(
"fraction of a grid cell covered by grounded ice")
2666 .standard_name(
"grounded_ice_sheet_area_fraction")
2672 result->metadata() =
m_vars[0];
2674 const double ice_density =
m_config->get_number(
"constants.ice.density"),
2675 ocean_density =
m_config->get_number(
"constants.sea_water.density");
2684 bed_topography, *result);
2693 for (
auto p :
m_grid->points()) {
2694 const int i = p.i(), j = p.j();
2695 if (cell_type.ice_free(i, j)) {
2696 (*result)(i, j) = 0.0;
2712 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2718 .long_name(
"fraction of a grid cell covered by floating ice")
2719 .standard_name(
"floating_ice_shelf_area_fraction")
2728 auto result = ice_area_fraction;
2729 result->metadata() =
m_vars[0];
2743 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2750 m_vars[0].long_name(
"ice thickness in excess of the maximum floating ice thickness").units(
"m");
2752 m_vars[0][
"comment"] =
"shows how close to floatation the ice is at a given location";
2757 auto result = allocate<array::Scalar>(
"height_above_flotation");
2761 const double ice_density =
m_config->get_number(
"constants.ice.density"),
2762 ocean_density =
m_config->get_number(
"constants.sea_water.density");
2768 array::AccessScope list{ &cell_type, result.get(), &ice_thickness, &bed_topography, &sea_level };
2772 for (
auto p :
m_grid->points()) {
2773 const int i = p.i(), j = p.j();
2775 const double thickness = ice_thickness(i, j), bed = bed_topography(i, j),
2776 ocean_depth = sea_level(i, j) - bed;
2778 if (cell_type.icy(i, j) and ocean_depth > 0.0) {
2779 const double max_floating_thickness = ocean_depth * (ocean_density / ice_density);
2780 (*result)(i, j) = thickness - max_floating_thickness;
2799 virtual std::shared_ptr<array::Array>
compute_impl()
const;
2804 m_vars[0].long_name(
"ice mass per cell").units(
"kg");
2810 auto result = allocate<array::Scalar>(
"ice_mass");
2814 const double ice_density =
m_config->get_number(
"constants.ice.density");
2818 auto cell_area =
m_grid->cell_area();
2824 for (
auto p :
m_grid->points()) {
2825 const int i = p.i(), j = p.j();
2829 if (ice_thickness(i, j) > 0.0) {
2830 (*result)(i, j) = ice_density * ice_thickness(i, j) * cell_area;
2842 if (
m_config->get_flag(
"geometry.part_grid.enabled")) {
2845 for (
auto p :
m_grid->points()) {
2846 const int i = p.i(), j = p.j();
2848 if (ice_thickness(i, j) <= 0.0 and Href(i, j) > 0.0) {
2849 (*result)(i, j) = ice_density * Href(i, j) * cell_area;
2869 m_vars[0].long_name(
"sea-level adjusted bed topography (zero is at sea level)").units(
"meters");
2874 auto result = allocate<array::Scalar>(
"topg_sl_adjusted");
2881 for (
auto p :
m_grid->points()) {
2882 const int i = p.i(), j = p.j();
2884 (*result)(i, j) = bed(i, j) - sea_level(i, j);
2902 .long_name(
"ice hardness computed using the SIA flow law")
2903 .set_units_without_validation(
2905 m_vars[0][
"comment"] =
"units depend on the Glen exponent used by the flow law";
2910 std::shared_ptr<array::Array3D> result(
2912 result->metadata(0) =
m_vars[0];
2914 auto EC =
m_grid->ctx()->enthalpy_converter();
2923 const unsigned int Mz =
m_grid->Mz();
2927 for (
auto p :
m_grid->points()) {
2928 const int i = p.i(), j = p.j();
2929 const double *E = ice_enthalpy.
get_column(i, j);
2930 const double H = ice_thickness(i, j);
2932 double *hardness = result->get_column(i, j);
2934 for (
unsigned int k = 0;
k < Mz; ++
k) {
2935 const double depth = H -
m_grid->z(
k);
2938 const double pressure = EC->pressure(depth);
2940 hardness[
k] = flow_law.
hardness(E[
k], pressure);
2963 .long_name(
"effective viscosity of ice")
2964 .units(
"Pascal second")
2965 .output_units(
"kPascal second");
2966 m_vars[0][
"valid_min"] = { 0.0 };
2976 std::shared_ptr<array::Array3D> result(
2978 result->metadata(0) =
m_vars[0];
2984 auto EC =
m_grid->ctx()->enthalpy_converter();
2997 const unsigned int Mz =
m_grid->Mz();
2999 const std::vector<double> &z =
m_grid->z();
3003 array::AccessScope list{ &U, &V, &W, &ice_enthalpy, &ice_thickness, &mask, result.get() };
3007 for (
auto p :
m_grid->points()) {
3008 const int i = p.i(), j = p.j();
3010 const double *E = ice_enthalpy.
get_column(i, j);
3011 const double H = ice_thickness(i, j);
3013 const double *u = U.get_column(i, j), *u_n = U.get_column(i, j + 1),
3014 *u_e = U.get_column(i + 1, j), *u_s = U.get_column(i, j - 1),
3015 *u_w = U.get_column(i - 1, j);
3017 const double *v = V.get_column(i, j), *v_n = V.get_column(i, j + 1),
3018 *v_e = V.get_column(i + 1, j), *v_s = V.get_column(i, j - 1),
3019 *v_w = V.get_column(i - 1, j);
3026 const unsigned int east = ice_free(m.e) ? 0 : 1, west = ice_free(m.w) ? 0 : 1,
3027 south = ice_free(m.s) ? 0 : 1, north = ice_free(m.n) ? 0 : 1;
3029 double *viscosity = result->get_column(i, j);
3031 if (ice_free(m.c)) {
3036 for (
unsigned int k = 0;
k < Mz; ++
k) {
3037 const double depth = H - z[
k];
3045 const double pressure = EC->pressure(depth);
3047 const double hardness = flow_law.
hardness(E[
k], pressure);
3049 double u_x = 0.0, v_x = 0.0, w_x = 0.0;
3050 if (west + east > 0) {
3051 const double D = 1.0 / (dx * (west + east));
3052 u_x =
D * (west * (u[
k] - u_w[
k]) + east * (u_e[
k] - u[
k]));
3053 v_x =
D * (west * (v[
k] - v_w[
k]) + east * (v_e[
k] - v[
k]));
3054 w_x =
D * (west * (w[
k] - w_w[
k]) + east * (w_e[
k] - w[
k]));
3057 double u_y = 0.0, v_y = 0.0, w_y = 0.0;
3058 if (south + north > 0) {
3059 const double D = 1.0 / (dy * (south + north));
3060 u_y =
D * (south * (u[
k] - u_s[
k]) + north * (u_n[
k] - u[
k]));
3061 v_y =
D * (south * (v[
k] - v_s[
k]) + north * (v_n[
k] - v[
k]));
3062 w_y =
D * (south * (w[
k] - w_s[
k]) + north * (w_n[
k] - w[
k]));
3065 double u_z = 0.0, v_z = 0.0, w_z = 0.0;
3068 const double dz = z[1] - z[0];
3069 u_z = (u[1] - u[0]) / dz;
3070 v_z = (v[1] - v[0]) / dz;
3071 w_z = (w[1] - w[0]) / dz;
3072 }
else if (
k == Mz - 1) {
3073 const double dz = z[Mz - 1] - z[Mz - 2];
3074 u_z = (u[Mz - 1] - u[Mz - 2]) / dz;
3075 v_z = (v[Mz - 1] - v[Mz - 2]) / dz;
3076 w_z = (w[Mz - 1] - w[Mz - 2]) / dz;
3078 const double dz_p = z[
k + 1] - z[
k], dz_m = z[
k] - z[
k - 1];
3079 u_z = 0.5 * ((u[
k + 1] - u[
k]) / dz_p + (u[
k] - u[
k - 1]) / dz_m);
3080 v_z = 0.5 * ((v[
k + 1] - v[
k]) / dz_p + (v[
k] - v[
k - 1]) / dz_m);
3081 w_z = 0.5 * ((w[
k + 1] - w[
k]) / dz_p + (w[
k] - w[
k - 1]) / dz_m);
3085 const double eps_xx = u_x, eps_yy = v_y, eps_zz = w_z, eps_xy = 0.5 * (u_y + v_x),
3086 eps_xz = 0.5 * (u_z + w_x), eps_yz = 0.5 * (v_z + w_y);
3115 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
3119 m_vars[0].long_name(
"land ice thickness").standard_name(
"land_ice_thickness").units(
"m");
3120 m_vars[0][
"valid_min"] = { 0.0 };
3126 auto result = allocate<array::Scalar>(
"thk");
3139 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
3142 m_vars[0].long_name(
"ice bottom surface elevation").units(
"m");
3148 auto result = allocate<array::Scalar>(
"ice_base_elevation");
3161 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
3164 m_vars[0].long_name(
"ice top surface elevation").standard_name(
"surface_altitude").units(
"m");
3169 auto result = allocate<array::Scalar>(
"usurf");
3184 auto ismip6 =
m_config->get_flag(
"output.ISMIP6");
3190 .
units(
"kg m^-2 second^-1")
3192 m_vars[0][
"cell_methods"] =
"time: mean";
3196 "Positive flux corresponds to mass moving from the ocean to"
3197 " an icy grounded area. This convention makes it easier to compare"
3198 " grounding line flux to the total discharge into the ocean";
3204 auto cell_area = grid->cell_area();
3206 grid->ctx()->config()->get_number(
"constants.ice.density");
3209 double unit_conversion_factor = dt * (ice_density / cell_area);
3212 model->geometry_evolution().flux_staggered(),
3229 .
long_name(
"ice mass flow rate across the grounding line")
3232 m_vars[0][
"cell_methods"] =
"time: mean";
3236 "Negative values correspond to mass moving from an icy grounded area into a lake or ocean."
3237 " This convention makes it easier to compare to calving, frontal melt, and discharge fluxes.";
3242 auto grid =
model->grid();
3243 double ice_density =
3244 grid->ctx()->config()->get_number(
"constants.ice.density");
3247 double unit_conversion_factor = dt * ice_density;
3250 model->geometry_evolution().flux_staggered(),
3288 d.second->init(file, options.
record);
3294 std::set<VariableMetadata> all_variables;
3312 std::map<std::string, Diagnostic::Ptr> result;
3314 using namespace diagnostics;
3321 {
"height_above_flotation", f(
new HeightAboveFloatation(
this)) },
3323 {
"ice_mass", f(
new IceMass(
this)) },
3327 {
"thk", f(
new IceThickness(
this)) },
3328 {
"topg_sl_adjusted", f(
new BedTopographySeaLevelAdjusted(
this)) },
3329 {
"usurf", f(
new IceSurfaceElevation(
this)) },
3330 {
"ice_base_elevation", f(
new IceBottomSurfaceElevation(
this)) },
3336 {
"enthalpybase", f(
new IceEnthalpyBasal(
this)) },
3337 {
"enthalpysurf", f(
new IceEnthalpySurface(
this)) },
3339 {
"cts", f(
new CTS(
this)) },
3340 {
"liqfrac", f(
new LiquidFraction(
this)) },
3341 {
"temp", f(
new Temperature(
this)) },
3342 {
"temp_pa", f(
new TemperaturePA(
this)) },
3343 {
"tempbase", f(
new TemperatureBasal(
this, BOTH)) },
3344 {
"temppabase", f(
new TemperaturePABasal(
this)) },
3345 {
"tempsurf", f(
new TemperatureSurface(
this)) },
3348 {
"tempicethk", f(
new TemperateIceThickness(
this)) },
3349 {
"tempicethk_basal", f(
new TemperateIceThicknessBasal(
this)) },
3350 {
"hardav", f(
new HardnessAverage(
this)) },
3351 {
"hardness", f(
new IceHardness(
this)) },
3352 {
"effective_viscosity", f(
new IceViscosity(
this)) },
3357 {
"ice_margin_pressure_difference", f(
new IceMarginPressureDifference(
this)) },
3371 {
"tendency_of_ice_amount", f(
new TendencyOfIceAmount(
this, AMOUNT)) },
3372 {
"tendency_of_ice_amount_due_to_flow", f(
new TendencyOfIceAmountDueToFlow(
this, AMOUNT)) },
3373 {
"tendency_of_ice_amount_due_to_conservation_error",
3374 f(
new ConservationErrorFlux(
this, AMOUNT)) },
3375 {
"tendency_of_ice_amount_due_to_surface_mass_flux", f(
new SurfaceFlux(
this, AMOUNT)) },
3376 {
"tendency_of_ice_amount_due_to_basal_mass_flux", f(
new BasalFlux(
this, AMOUNT)) },
3377 {
"tendency_of_ice_amount_due_to_discharge", f(
new DischargeFlux(
this, AMOUNT)) },
3378 {
"tendency_of_ice_amount_due_to_calving", f(
new CalvingFlux(
this, AMOUNT)) },
3379 {
"tendency_of_ice_amount_due_to_frontal_melt", f(
new FrontalMeltFlux(
this, AMOUNT)) },
3380 {
"tendency_of_ice_amount_due_to_forced_retreat", f(
new ForcedRetreatFlux(
this, AMOUNT)) },
3393 {
"tendency_of_ice_mass", f(
new TendencyOfIceAmount(
this, MASS)) },
3394 {
"tendency_of_ice_mass_due_to_flow", f(
new TendencyOfIceAmountDueToFlow(
this, MASS)) },
3395 {
"tendency_of_ice_mass_due_to_conservation_error", f(
new ConservationErrorFlux(
this, MASS)) },
3396 {
"tendency_of_ice_mass_due_to_surface_mass_flux", f(
new SurfaceFlux(
this, MASS)) },
3397 {
"tendency_of_ice_mass_due_to_basal_mass_flux", f(
new BasalFlux(
this, MASS)) },
3398 {
"tendency_of_ice_mass_due_to_discharge", f(
new DischargeFlux(
this, MASS)) },
3399 {
"tendency_of_ice_mass_due_to_calving", f(
new CalvingFlux(
this, MASS)) },
3400 {
"tendency_of_ice_mass_due_to_frontal_melt", f(
new FrontalMeltFlux(
this, MASS)) },
3401 {
"tendency_of_ice_mass_due_to_forced_retreat", f(
new ForcedRetreatFlux(
this, MASS)) },
3404 {
"basal_mass_flux_grounded", f(
new BMBSplit(
this, GROUNDED)) },
3405 {
"basal_mass_flux_floating", f(
new BMBSplit(
this, SHELF)) },
3406 {
"dHdt", f(
new ThicknessRateOfChange(
this)) },
3408 {
"grounding_line_flux", f(
new GroundingLineFlux(
this)) },
3409 {
"ice_mass_transport_across_grounding_line", f(
new MassTransportAcrossGroundingLine(
this)) },
3412 {
"rank", f(
new Rank(
this)) },
3415#if (Pism_USE_PROJ == 1)
3416 std::string proj =
m_grid->get_mapping_info()[
"proj_params"];
3417 if (not proj.empty()) {
3418 result[
"lat_bnds"] = f(
new LatLonBounds(
this,
"lat", proj));
3419 result[
"lon_bnds"] = f(
new LatLonBounds(
this,
"lon", proj));
3424 if (
m_config->get_flag(
"output.ISMIP6")) {
3425 result[
"base"] = result[
"ice_base_elevation"];
3426 result[
"lithk"] = result[
"thk"];
3427 result[
"dlithkdt"] = result[
"dHdt"];
3428 result[
"orog"] = result[
"usurf"];
3429 result[
"acabf"] = result[
"tendency_of_ice_amount_due_to_surface_mass_flux"];
3430 result[
"libmassbfgr"] = result[
"basal_mass_flux_grounded"];
3431 result[
"libmassbffl"] = result[
"basal_mass_flux_floating"];
3432 result[
"lifmassbf"] = result[
"tendency_of_ice_amount_due_to_discharge"];
3433 result[
"licalvf"] = result[
"tendency_of_ice_amount_due_to_calving"];
3434 result[
"litempbotgr"] = f(
new TemperatureBasal(
this, GROUNDED));
3435 result[
"litempbotfl"] = f(
new TemperatureBasal(
this, SHELF));
3436 result[
"ligroundf"] = result[
"grounding_line_flux"];
3441 result =
pism::combine(result, m.second->spatial_diagnostics());
3448 std::map<std::string, TSDiagnostic::Ptr> result;
3450 using namespace diagnostics;
3456 {
"ice_area_glacierized", s(
new scalar::IceAreaGlacierized(
this))},
3457 {
"ice_area_glacierized_cold_base", s(
new scalar::IceAreaGlacierizedColdBase(
this))},
3458 {
"ice_area_glacierized_grounded", s(
new scalar::IceAreaGlacierizedGrounded(
this))},
3459 {
"ice_area_glacierized_floating", s(
new scalar::IceAreaGlacierizedShelf(
this))},
3460 {
"ice_area_glacierized_temperate_base", s(
new scalar::IceAreaGlacierizedTemperateBase(
this))},
3462 {
"ice_mass_glacierized", s(
new scalar::IceMassGlacierized(
this))},
3463 {
"ice_mass", s(
new scalar::IceMass(
this))},
3464 {
"tendency_of_ice_mass_glacierized", s(
new scalar::IceMassRateOfChangeGlacierized(
this))},
3465 {
"limnsw", s(
new scalar::IceMassNotDisplacingSeaWater(
this))},
3467 {
"ice_volume_glacierized", s(
new scalar::IceVolumeGlacierized(
this))},
3468 {
"ice_volume_glacierized_cold", s(
new scalar::IceVolumeGlacierizedCold(
this))},
3469 {
"ice_volume_glacierized_grounded", s(
new scalar::IceVolumeGlacierizedGrounded(
this))},
3470 {
"ice_volume_glacierized_floating", s(
new scalar::IceVolumeGlacierizedShelf(
this))},
3471 {
"ice_volume_glacierized_temperate", s(
new scalar::IceVolumeGlacierizedTemperate(
this))},
3472 {
"ice_volume", s(
new scalar::IceVolume(
this))},
3473 {
"ice_volume_cold", s(
new scalar::IceVolumeCold(
this))},
3474 {
"ice_volume_temperate", s(
new scalar::IceVolumeTemperate(
this))},
3475 {
"tendency_of_ice_volume_glacierized", s(
new scalar::IceVolumeRateOfChangeGlacierized(
this))},
3476 {
"tendency_of_ice_volume", s(
new scalar::IceVolumeRateOfChange(
this))},
3477 {
"sea_level_rise_potential", s(
new scalar::SeaLevelRisePotential(
this))},
3479 {
"ice_enthalpy_glacierized", s(
new scalar::IceEnthalpyGlacierized(
this))},
3480 {
"ice_enthalpy", s(
new scalar::IceEnthalpy(
this))},
3482 {
"max_diffusivity", s(
new scalar::MaxDiffusivity(
this))},
3483 {
"max_horizontal_vel", s(
new scalar::MaxHorizontalVelocity(
this))},
3484 {
"dt", s(
new scalar::TimeStepLength(
this))},
3485 {
"dt_ratio", s(
new scalar::TimeStepRatio(
this))},
3487 {
"tendency_of_ice_mass", s(
new scalar::IceMassRateOfChange(
this))},
3488 {
"tendency_of_ice_mass_due_to_flow", s(
new scalar::IceMassRateOfChangeDueToFlow(
this))},
3489 {
"tendency_of_ice_mass_due_to_conservation_error", s(
new scalar::IceMassFluxConservationError(
this))},
3490 {
"tendency_of_ice_mass_due_to_basal_mass_flux", s(
new scalar::IceMassFluxBasal(
this))},
3491 {
"tendency_of_ice_mass_due_to_surface_mass_flux", s(
new scalar::IceMassFluxSurface(
this))},
3492 {
"tendency_of_ice_mass_due_to_discharge", s(
new scalar::IceMassFluxDischarge(
this))},
3493 {
"tendency_of_ice_mass_due_to_calving", s(
new scalar::IceMassFluxCalving(
this))},
3495 {
"basal_mass_flux_grounded", s(
new scalar::IceMassFluxBasalGrounded(
this))},
3496 {
"basal_mass_flux_floating", s(
new scalar::IceMassFluxBasalFloating(
this))},
3497 {
"grounding_line_flux", s(
new scalar::IceMassFluxAtGroundingLine(
this))},
3501 if (
m_config->get_flag(
"output.ISMIP6")) {
3502 result[
"iareafl"] = result[
"ice_area_glacierized_floating"];
3503 result[
"iareagr"] = result[
"ice_area_glacierized_grounded"];
3504 result[
"lim"] = result[
"ice_mass"];
3505 result[
"tendacabf"] = result[
"tendency_of_ice_mass_due_to_surface_mass_flux"];
3506 result[
"tendlibmassbf"] = result[
"tendency_of_ice_mass_due_to_basal_mass_flux"];
3507 result[
"tendlibmassbffl"] = result[
"basal_mass_flux_floating"];
3508 result[
"tendlicalvf"] = result[
"tendency_of_ice_mass_due_to_calving"];
3509 result[
"tendlifmassbf"] = result[
"tendency_of_ice_mass_due_to_discharge"];
3510 result[
"tendligroundf"] = result[
"grounding_line_flux"];
3515 result =
pism::combine(result, m.second->scalar_diagnostics());
3521using Metadata = std::map<std::string, std::vector<VariableMetadata>>;
3524 for (
const auto &d : list) {
3525 const std::string &name = d.first;
3526 log.
message(1,
" Name: %s\n", name.c_str());
3528 for (
const auto &v : d.second) {
3531 var_name = v.get_name(),
3533 output_units = v[
"output_units"],
3534 long_name = v[
"long_name"],
3535 comment = v[
"comment"];
3537 if (not output_units.empty()) {
3538 units = output_units;
3541 log.
message(1,
" %s [%s]\n", var_name.c_str(), units.c_str());
3542 log.
message(1,
" %s\n", long_name.c_str());
3543 if (not comment.empty()) {
3544 log.
message(1,
" %s\n", comment.c_str());
3553 bool first_diagnostic =
true;
3554 for (
const auto &d : list) {
3556 if (not first_diagnostic) {
3559 first_diagnostic =
false;
3562 log.
message(1,
"\"%s\" : [\n", d.first.c_str());
3564 bool first_variable =
true;
3565 for (
const auto &variable : d.second) {
3568 var_name = variable.get_name(),
3569 units = variable[
"units"],
3570 output_units = variable[
"output_units"],
3571 long_name = variable[
"long_name"],
3572 standard_name = variable[
"standard_name"],
3573 comment = variable[
"comment"];
3575 if (not output_units.empty()) {
3576 units = output_units;
3579 if (not first_variable) {
3582 first_variable =
false;
3585 log.
message(1,
"[\"%s\", \"%s\", \"%s\", \"%s\", \"%s\"]",
3586 var_name.c_str(), units.c_str(), long_name.c_str(), standard_name.c_str(), comment.c_str());
3599 for (
const auto& f : diags) {
3600 auto diag = f.second;
3602 for (
unsigned int k = 0;
k < diag->n_variables(); ++
k) {
3603 result[f.first].push_back(diag->metadata(
k));
3616 for (
const auto& d : diags) {
3618 result[d.first] = {d.second->metadata()};
3627 m_log->message(1,
"{\n");
3629 m_log->message(1,
"\"spatial\" :\n");
3632 m_log->message(1,
",\n");
3634 m_log->message(1,
"\"scalar\" :\n");
3637 m_log->message(1,
"}\n");
3643 m_log->message(1,
"\n");
3644 m_log->message(1,
"======== Available 2D and 3D diagnostics ========\n");
3651 m_log->message(1,
"======== Available time-series ========\n");
3664 auto EC =
m_ctx->enthalpy_converter();
3666 auto cell_area =
m_grid->cell_area();
3668 double result = 0.0, meltarea = 0.0;
3675 for (
auto p :
m_grid->points()) {
3676 const int i = p.i(), j = p.j();
3683 if (EC->is_temperate_relaxed(E_basal, pressure)) {
3684 meltarea += cell_area;
3699 if (total_ice_area > 0.0) {
3700 result = result / total_ice_area;
3714 double result = -1.0;
3720 const double a =
m_grid->cell_area() * 1e-3 * 1e-3,
3721 currtime =
m_time->current();
3728 double original_ice_volume = 0.0;
3733 for (
auto p :
m_grid->points()) {
3734 const int i = p.i(), j = p.j();
3738 const double *age = ice_age.
get_column(i, j);
3740 for (
unsigned int k = 1;
k <= ks;
k++) {
3742 if (0.5 * (age[
k - 1] + age[
k]) > currtime - one_year) {
3743 original_ice_volume += a * 1.0e-3 * (
m_grid->z(
k) -
m_grid->z(
k - 1));
3758 if (total_ice_volume > 0.0) {
3759 result = result / total_ice_volume;
3767 const std::set<std::string> &vars,
3768 const std::string &type,
3769 const std::set<std::string> &available,
3771 std::vector<std::string> missing;
3772 for (
const auto &v : vars) {
3773 if (available.find(v) == available.end()) {
3774 missing.push_back(v);
3778 if (not missing.empty()) {
3779 size_t N = missing.size();
3780 const char *ending = N > 1 ?
"s" :
"";
3781 const char *verb = N > 1 ?
"are" :
"is";
3784 "%s variable%s %s %s not available!\n"
3785 "Available variables:\n- %s",
3788 join(missing,
",").c_str(),
3790 set_join(available,
",\n- ").c_str());
3794 "\nWARNING: %s variable%s %s %s not available!\n\n",
3797 join(missing,
",").c_str(),
3813 std::set<std::string> available;
3815 available.insert(d.first);
3818 auto stop =
m_config->get_flag(
"output.spatial.stop_missing");
3822 auto requested =
set_split(
m_config->get_string(
"output.runtime.viewer.variables"),
',');
3829 for (
const auto &v : available) {
3830 if (requested.find(v) == requested.end()) {
3845 d.second->update(
dt);
3849 d.second->update(t -
dt, t);
3855 const std::set<std::string> &variable_names)
const {
3856 for (
const auto &variable : variable_names) {
3860 diag->second->compute()->write(file);
3865std::set<VariableMetadata>
3867 std::set<VariableMetadata> result{};
3869 for (
const auto &var : variable_names) {
3873 const auto &
D = diag->second;
3874 for (
unsigned int k = 0;
k <
D->n_variables(); ++
k) {
3875 result.insert(
D->metadata(
k));
3883std::set<VariableMetadata>
3885 std::set<VariableMetadata> result{};
3887 for (
const auto &var : variable_names) {
3891 const auto &
D = diag->second;
3900 const std::set<std::string> &variable_names)
const {
3902 for (
const auto &var : variable_names) {
3906 const auto &
D = diag->second;
3907 D->write_state(file);
double get_number(const std::string &name, UseFlag flag=REMEMBER_THIS_USE) const
A class for storing and accessing PISM configuration flags and parameters.
array::Scalar m_accumulator
A template derived from Diagnostic, adding a "Model".
std::vector< VariableMetadata > m_vars
metadata corresponding to NetCDF variables
double m_fill_value
fill value (used often enough to justify storing it)
const units::System::Ptr m_sys
the unit system
std::shared_ptr< const Config > m_config
Configuration flags and parameters.
double to_internal(double x) const
std::shared_ptr< Diagnostic > Ptr
std::shared_ptr< const Grid > m_grid
the grid
std::shared_ptr< array::Array > compute() const
Compute a diagnostic quantity and return a pointer to a newly-allocated Array.
Class representing diagnostic computations in PISM.
High-level PISM I/O class.
void compute_mask(const array::Scalar &sea_level, const array::Scalar &bed, const array::Scalar &thickness, array::Scalar &result) const
void set_icefree_thickness(double threshold)
const array::Scalar & thickness_change_due_to_flow() const
const array::Scalar & bottom_surface_mass_balance() const
const array::Scalar & top_surface_mass_balance() const
const array::Scalar & area_specific_volume_change_due_to_flow() const
const array::Scalar & conservation_error() const
const array::Staggered1 & flux_staggered() const
array::Scalar1 sea_level_elevation
array::Scalar cell_grounded_fraction
array::Scalar2 ice_surface_elevation
array::Scalar1 ice_area_specific_volume
array::CellType2 cell_type
array::Scalar2 ice_thickness
array::Scalar2 bed_elevation
Describes the PISM grid and the distribution of data across processors.
std::map< std::string, const Component * > m_submodels
the list of sub-models, for writing model states and obtaining diagnostics
std::set< std::string > m_snapshot_vars
virtual double compute_temperate_base_fraction(double ice_area)
const Geometry & geometry() const
void init_checkpoints()
Initialize checkpointing (snapshot-on-wallclock-time) mechanism.
std::set< std::string > m_spatial_vars
std::shared_ptr< Config > m_config
Configuration flags and parameters.
virtual std::map< std::string, Diagnostic::Ptr > allocate_spatial_diagnostics()
const GeometryEvolution & geometry_evolution() const
const stressbalance::StressBalance * stress_balance() const
virtual double compute_original_ice_fraction(double ice_volume)
std::shared_ptr< Context > m_ctx
Execution context.
std::shared_ptr< Logger > m_log
Logger.
std::set< VariableMetadata > m_spatial_file_contents
set of variables that will be written to extra files
array::Scalar m_basal_melt_rate
rate of production of basal meltwater (ice-equivalent); no ghosts
std::shared_ptr< Grid > grid() const
Return the grid used by this model.
virtual std::set< VariableMetadata > diagnostic_variables(const std::set< std::string > &variable_names) const
std::set< VariableMetadata > m_output_file_contents
Set of variables that will be written to the output file.
void list_diagnostics(DiagnosticReport report_type) const
array::Scalar m_bedtoptemp
temperature at the top surface of the bedrock thermal layer
std::set< VariableMetadata > state_variables_diagnostics(const std::set< std::string > &variable_names) const
const energy::EnergyModel * energy_balance_model() const
virtual void update_diagnostics(double t, double dt)
std::shared_ptr< OutputWriter > m_snapshot_writer
void init_outputs(InputOptions options, DiagnosticReport report_type)
std::shared_ptr< Time > m_time
Time manager.
const array::Scalar & frontal_melt() const
const array::Scalar & forced_retreat() const
std::set< std::string > m_checkpoint_vars
array::Scalar2 m_velocity_bc_mask
mask to determine Dirichlet boundary locations for the sliding velocity
void init_scalar_diagnostics()
Initializes the code writing scalar time-series.
std::map< std::string, Diagnostic::Ptr > m_available_spatial_diagnostics
Available spatially-variable diagnostics.
void write_state_diagnostics(const OutputFile &file, const std::set< std::string > &variable_names) const
virtual std::map< std::string, TSDiagnostic::Ptr > allocate_scalar_diagnostics()
void write_diagnostics(const OutputFile &file, const std::set< std::string > &variable_names) const
Writes variables listed in variable_names to file.
std::set< VariableMetadata > m_snapshot_file_contents
set of variables that will be written to snapshot files
array::Scalar1 m_ice_thickness_bc_mask
Mask prescribing locations where ice thickness is held constant.
std::shared_ptr< AgeModel > m_age_model
void init_spatial_diagnostics()
Initialize the code saving spatially-variable diagnostic quantities.
const units::System::Ptr m_sys
Unit system.
std::map< std::string, TSDiagnostic::Ptr > m_available_scalar_diagnostics
Available scalar diagnostics.
array::Vector2 m_velocity_bc_values
Dirichlet boundary velocities.
void init_snapshots()
Initializes the snapshot-saving mechanism.
std::shared_ptr< OutputWriter > m_output_writer
const array::Scalar & calving() const
std::shared_ptr< Context > ctx() const
Return the context this model is running in.
std::set< std::string > m_output_vars
std::set< VariableMetadata > m_checkpoint_file_contents
set of variables that will be written to checkpoint files
std::shared_ptr< energy::EnergyModel > m_energy_model
const std::shared_ptr< Grid > m_grid
Computational grid.
void deallocate_unused_diagnostics()
void message(int threshold, const char format[],...) const __attribute__((format(printf
Print a message to the log.
void failed()
Indicates a failure of a parallel section.
A wrapper for PJ that makes sure pj_destroy is called.
static RuntimeError formatted(const ErrorLocation &location, const char format[],...) __attribute__((format(printf
build a RuntimeError with a formatted message
void set_units(const std::string &units, const std::string &output_units)
VariableMetadata m_variable
std::shared_ptr< const Config > m_config
Configuration flags and parameters.
std::shared_ptr< const Grid > m_grid
the grid
std::shared_ptr< TSDiagnostic > Ptr
Scalar diagnostic reporting a "flux".
Scalar diagnostic reporting the rate of change of a quantity modeled by PISM.
Scalar diagnostic reporting a snapshot of a quantity modeled by PISM.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
void copy_from(const Array2D< T > &source)
stencils::Star< T > star(int i, int j) const
void add(double alpha, const Array2D< T > &x)
void copy_from(const Array3D &input)
double * get_column(int i, int j)
A virtual class collecting methods common to ice and bedrock 3D fields.
std::shared_ptr< const Grid > grid() const
VariableMetadata & metadata(unsigned int N=0)
Returns a reference to the VariableMetadata object containing metadata for the compoment N.
stencils::Star< int > star_int(int i, int j) const
bool next_to_ice_free_ocean(int i, int j) const
bool ice_free_ocean(int i, int j) const
bool grounded_ice(int i, int j) const
bool icy(int i, int j) const
BMBSplit(const IceModel *m, AreaType flag)
void update_impl(double dt)
Report average basal mass balance flux over the reporting interval (grounded or floating areas)
BasalFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
Report basal mass balance flux, averaged over the reporting interval.
BedTopographySeaLevelAdjusted(const IceModel *m)
std::shared_ptr< array::Array > compute_impl() const
Sea-level adjusted bed topography (zero at sea level).
virtual std::shared_ptr< array::Array > compute_impl() const
Computes CTS, CTS = E/E_s(p).
void update_impl(double dt)
CalvingFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
ConservationErrorFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
DischargeFlux(const IceModel *m, AmountKind kind)
Report discharge (calving and frontal melt) flux.
ForcedRetreatFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
Report the frontal melt flux.
FrontalMeltFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
Report the frontal melt flux.
void update_impl(double dt)
GroundingLineFlux(const IceModel *m)
Report grounding line flux.
HardnessAverage(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes vertically-averaged ice hardness.
Computes vertically-averaged ice hardness.
HeightAboveFloatation(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes the 2D height above flotation.
IceAreaFractionFloating(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
IceAreaFractionGrounded(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
IceAreaFraction(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
std::shared_ptr< array::Array > compute_impl() const
IceBottomSurfaceElevation(const IceModel *m)
Report ice top surface elevation.
virtual std::shared_ptr< array::Array > compute_impl() const
IceEnthalpyBasal(const IceModel *m)
Computes enthalpy at the base of the ice.
IceEnthalpySurface(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes surface values of ice enthalpy.
IceHardness(const IceModel *m)
std::shared_ptr< array::Array > compute_impl() const
Ice hardness computed using the SIA flow law.
std::shared_ptr< array::Array > compute_impl() const
IceMarginPressureDifference(IceModel *m)
Ocean pressure difference at calving fronts. Used to debug CF boundary conditins.
IceMass(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes the mass per cell.
IceSurfaceElevation(const IceModel *m)
std::shared_ptr< array::Array > compute_impl() const
Report ice top surface elevation.
IceThickness(const IceModel *m)
std::shared_ptr< array::Array > compute_impl() const
std::shared_ptr< array::Array > compute_impl() const
IceViscosity(IceModel *m)
Effective viscosity of ice (3D).
LatLonBounds(const IceModel *m, const std::string &var_name, const std::string &proj_string)
std::string m_proj_string
virtual std::shared_ptr< array::Array > compute_impl() const
Computes latitude and longitude bounds.
virtual std::shared_ptr< array::Array > compute_impl() const
LiquidFraction(const IceModel *m)
Computes the liquid water fraction.
MassTransportAcrossGroundingLine(const IceModel *m)
void update_impl(double dt)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes a diagnostic field filled with processor rank values.
SurfaceFlux(const IceModel *m, AmountKind kind)
void update_impl(double dt)
Report surface mass balance flux, averaged over the reporting interval.
TemperateIceThicknessBasal(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes the thickness of the basal layer of temperate ice.
TemperateIceThickness(const IceModel *m)
virtual std::shared_ptr< array::Array > compute_impl() const
Computes the total thickness of temperate ice in a column.
std::shared_ptr< array::Array > compute_impl() const
TemperatureBasal(const IceModel *m, AreaType area_type)
Computes ice temperature at the base of the ice.
virtual std::shared_ptr< array::Array > compute_impl() const
TemperaturePABasal(const IceModel *m)
Computes basal values of the pressure-adjusted temperature.
virtual std::shared_ptr< array::Array > compute_impl() const
TemperaturePA(const IceModel *m)
Compute the pressure-adjusted temperature in degrees C corresponding to ice temperature.
virtual std::shared_ptr< array::Array > compute_impl() const
TemperatureSurface(const IceModel *m)
Computes ice temperature at the surface of the ice.
virtual std::shared_ptr< array::Array > compute_impl() const
Temperature(const IceModel *m)
Computes ice temperature from enthalpy.
void update_impl(double dt)
TendencyOfIceAmountDueToFlow(const IceModel *Model, AmountKind kind)
Computes tendency_of_ice_amount_due_to_flow, the rate of change of ice amount due to flow.
std::shared_ptr< array::Array > compute_impl() const
void update_impl(double dt)
TendencyOfIceAmount(const IceModel *Model, AmountKind kind)
array::Scalar m_last_amount
Computes tendency_of_ice_amount, the ice amount rate of change.
array::Scalar m_last_thickness
ThicknessRateOfChange(const IceModel *m)
void update_impl(double dt)
std::shared_ptr< array::Array > compute_impl() const
Computes dHdt, the ice thickness rate of change.
IceAreaGlacierizedColdBase(IceModel *m)
Computes the total area of the cold ice.
IceAreaGlacierizedGrounded(IceModel *m)
Computes the total grounded ice area.
IceAreaGlacierizedShelf(IceModel *m)
Computes the total floating ice area.
IceAreaGlacierizedTemperateBase(IceModel *m)
Computes the total area of the temperate ice.
IceAreaGlacierized(IceModel *m)
Computes the total ice area.
IceEnthalpyGlacierized(IceModel *m)
Computes the total ice enthalpy in glacierized areas.
Computes the total ice enthalpy.
IceMassFluxAtGroundingLine(const IceModel *m)
Reports the total flux across the grounding line.
IceMassFluxBasalFloating(const IceModel *m)
Reports the total sub-shelf ice flux.
IceMassFluxBasalGrounded(const IceModel *m)
Reports the total basal ice flux over the grounded region.
IceMassFluxBasal(const IceModel *m)
Reports the total bottom surface ice flux.
IceMassFluxCalving(const IceModel *m)
Reports the total calving flux.
IceMassFluxConservationError(const IceModel *m)
Reports the total numerical mass flux needed to preserve non-negativity of ice thickness.
IceMassFluxDischarge(const IceModel *m)
Reports the total discharge flux.
IceMassFluxSurface(const IceModel *m)
Reports the total top surface ice flux.
IceMassGlacierized(IceModel *m)
Computes the total ice mass in glacierized areas.
IceMassNotDisplacingSeaWater(const IceModel *m)
Computes the total mass of the ice not displacing sea water.
IceMassRateOfChangeDueToFlow(IceModel *m)
Computes the rate of change of the total ice mass due to flow (influx due to prescribed constant-in-t...
IceMassRateOfChangeGlacierized(IceModel *m)
Computes the rate of change of the total ice mass in glacierized areas.
IceMassRateOfChange(IceModel *m)
Computes the rate of change of the total ice mass.
Computes the total ice mass.
IceVolumeCold(IceModel *m)
Computes the total volume of the cold ice.
IceVolumeGlacierizedCold(IceModel *m)
Computes the total volume of the cold ice in glacierized areas.
IceVolumeGlacierizedGrounded(IceModel *m)
Computes the total grounded ice volume.
IceVolumeGlacierizedShelf(IceModel *m)
Computes the total floating ice volume.
IceVolumeGlacierizedTemperate(IceModel *m)
Computes the total volume of the temperate ice in glacierized areas.
IceVolumeGlacierized(IceModel *m)
Computes the total ice volume in glacierized areas.
IceVolumeRateOfChangeGlacierized(IceModel *m)
Computes the rate of change of the total ice volume in glacierized areas.
IceVolumeRateOfChange(IceModel *m)
Computes the rate of change of the total ice volume.
IceVolumeTemperate(IceModel *m)
Computes the total volume of the temperate ice.
Computes the total ice volume.
MaxDiffusivity(const IceModel *m)
Reports maximum diffusivity.
MaxHorizontalVelocity(const IceModel *m)
Reports the maximum horizontal absolute velocity component over the grid.
SeaLevelRisePotential(const IceModel *m)
Computes the total ice volume which is relevant for sea-level.
TimeStepLength(const IceModel *m)
Reports the mass continuity time step.
TimeStepRatio(const IceModel *m)
Reports the mass continuity time step.
const array::Array3D & enthalpy() const
void effective_viscosity(double hardness, double gamma, double *nu, double *dnu) const
Computes the regularized effective viscosity and its derivative with respect to the second invariant ...
double hardness(double E, double p) const
std::shared_ptr< const rheology::FlowLaw > flow_law() const
std::shared_ptr< const rheology::FlowLaw > flow_law() const
CFLData max_timestep_cfl_3d() const
const array::Array3D & velocity_w() const
const SSB_Modifier * modifier() const
Returns a pointer to a stress balance modifier implementation.
const array::Array3D & velocity_u() const
Get components of the the 3D velocity field.
CFLData max_timestep_cfl_2d() const
double max_diffusivity() const
Get the max diffusivity (for the adaptive time-stepping).
const ShallowStressBalance * shallow() const
Returns a pointer to a shallow stress balance solver implementation.
const array::Array3D & velocity_v() const
#define PISM_ERROR_LOCATION
static double ice_volume(const array::Scalar &ice_thickness, const array::Array3D &ice_enthalpy, IceKind kind, double thickness_threshold)
static double base_area(const array::Scalar &ice_thickness, const array::Array3D &ice_enthalpy, IceKind kind, double thickness_threshold)
double mass_change(const IceModel *model, TermType term, AreaType area)
static double square(double x)
static void accumulate_changes(const IceModel *model, double factor, ChangeKind kind, array::Scalar &accumulator)
void compute_liquid_water_fraction(const array::Array3D &enthalpy, const array::Scalar &ice_thickness, array::Array3D &result)
Compute the liquid fraction corresponding to enthalpy and ice_thickness.
void compute_cts(const array::Array3D &ice_enthalpy, const array::Scalar &ice_thickness, array::Array3D &result)
Compute the CTS field, CTS = E/E_s(p), from ice_enthalpy and ice_thickness, and put in result.
double total_ice_enthalpy(double thickness_threshold, const array::Array3D &ice_enthalpy, const array::Scalar &ice_thickness)
Computes the total ice enthalpy in J.
bool domain_edge(const Grid &grid, int i, int j)
@ PISM_READONLY
open an existing file for reading only
bool ice_free(int M)
Ice-free cell (grounded or ocean).
double averaged_hardness(const FlowLaw &ice, double thickness, unsigned int kbelowH, const double *zlevels, const double *enthalpy)
Computes vertical average of B(E, p) ice hardness, namely .
double convert(System::Ptr system, double input, const std::string &spec1, const std::string &spec2)
Convert a quantity from unit1 to unit2.
double ice_volume_not_displacing_seawater(const Geometry &geometry, double thickness_threshold)
double ice_area(const Geometry &geometry, double thickness_threshold)
Computes ice area, in m^2.
std::map< std::string, std::vector< VariableMetadata > > Metadata
double grounded_area_fraction(double a, double b, double c)
static const char * grounded_ice_sheet_area_fraction_name
double average_water_column_pressure(double ice_thickness, double bed, double floatation_level, double rho_ice, double rho_water, double g)
std::string set_join(const std::set< std::string > &input, const std::string &separator)
void compute_grounded_cell_fraction(double ice_density, double ocean_density, const array::Scalar1 &sea_level, const array::Scalar1 &ice_thickness, const array::Scalar1 &bed_topography, array::Scalar &result)
double ice_area_floating(const Geometry &geometry, double thickness_threshold)
Computes floating ice area, in m^2.
double part_grid_threshold_thickness(stencils::Star< int > cell_type, stencils::Star< double > ice_thickness, stencils::Star< double > surface_elevation, double bed_elevation)
Compute threshold thickness used when deciding if a partially-filled cell should be considered 'full'...
double sea_level_rise_potential(const Geometry &geometry, double thickness_threshold)
Computes the sea level rise that would result if all the ice were melted.
double total_grounding_line_flux(const array::CellType1 &cell_type, const array::Staggered1 &flux, double dt)
static void warn_about_missing(const Logger &log, const std::set< std::string > &vars, const std::string &type, const std::set< std::string > &available, bool stop)
std::set< std::string > set_split(const std::string &input, char separator)
Transform a separator-separated list (a string) into a set of strings.
static void print_diagnostics_json(const Logger &log, const Metadata &list)
double ice_volume(const Geometry &geometry, double thickness_threshold)
Computes the ice volume, in m^3.
void ice_flow_rate_across_grounding_line(const array::CellType1 &cell_type, const array::Staggered1 &flux, double unit_conversion_factor, array::Scalar &output)
void ice_bottom_surface(const Geometry &geometry, array::Scalar &result)
MaxTimestep max_timestep_diffusivity(double D_max, double dx, double dy, double adaptive_timestepping_ratio)
static Metadata spatial_diag_metadata(const std::map< std::string, Diagnostic::Ptr > &diags)
static void print_diagnostics(const Logger &log, const Metadata &list)
double ice_area_grounded(const Geometry &geometry, double thickness_threshold)
Computes grounded ice area, in m^2.
T combine(const T &a, const T &b)
static Metadata scalar_diag_metadata(const std::map< std::string, TSDiagnostic::Ptr > &diags)
void compute_lat_bounds(const std::string &projection, array::Array3D &result)
std::string join(const std::vector< std::string > &strings, const std::string &separator)
Concatenate strings, inserting separator between elements.
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)
void compute_lon_bounds(const std::string &projection, array::Array3D &result)
bool set_member(const std::string &string, const std::set< std::string > &set)
static const char * land_ice_area_fraction_name
static const char * floating_ice_sheet_area_fraction_name