PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
MassEnergyBudget.cc
Go to the documentation of this file.
1 #include <iostream>
2 
3 #include "pism/icebin/MassEnergyBudget.hh"
4 #include "pism/util/VariableMetadata.hh"
5 
6 namespace pism {
7 namespace icebin {
8 
9 MassEnthVec2S::MassEnthVec2S(std::shared_ptr<const pism::Grid> grid, const std::string &name)
10  : mass(grid, name + ".mass"), enth(grid, name + ".enth") {
11 }
12 
13 void MassEnthVec2S::set_attrs(const std::string &long_name, const std::string &units) {
14  mass.metadata().long_name(long_name + " (mass portion)").units("kg " + units);
15  enth.metadata().long_name(long_name + " (enthalpy portion)").units("J " + units);
16 }
17 
18 MassEnergyBudget::MassEnergyBudget(std::shared_ptr<const pism::Grid> grid,
19  std::string const &prefix)
20  : total(grid, prefix + "total"),
21  basal_frictional_heating(grid, prefix + "basal_frictional_heating"),
22  strain_heating(grid, prefix + "strain_heating"),
23  geothermal_flux(grid, prefix + "geothermal_flux"),
24  upward_geothermal_flux(grid, prefix + "upward_geothermal_flux"),
25  calving(grid, prefix + "calving"),
26  smb(grid, prefix + "smb"),
27  deltah(grid, prefix + "deltah"),
28  pism_smb(grid, prefix + "pism_smb"),
29  href_to_h(grid, prefix + "href_to_h"),
30  nonneg_rule(grid, prefix + "nonneg_rule"),
31  melt_grounded(grid, prefix + "melt_grounded"),
32  melt_floating(grid, prefix + "melt_floating"),
33  internal_advection(grid, prefix + "internal_advection"),
34  epsilon(grid, prefix + "epsilon") {
35 
36  // ----------- Mass and Enthalpy State of the Ice Sheet
37 
38  total.set_attrs("State of the ice sheet (NOT a difference between time steps)", "m-2");
39  add_massenth(total, TOTAL, "", "");
40 
41  // ----------- Heat generation of flows [vertical]
42  // Postive means heat is flowing INTO the ice sheet.
43 
44  basal_frictional_heating.metadata(0).long_name("Basal frictional heating").units("W m-2");
45  add_enth(basal_frictional_heating, DELTA, "basal_frictional_heating");
46 
47  strain_heating.metadata(0).long_name("Strain heating").units("W m-2");
48  add_enth(strain_heating, DELTA, "strain_heating"); //!< Total amount of strain heating [J/m^2]
49 
51  .long_name("Geothermal energy through (compare to upward_geothermal_flux?)")
52  .units("W m-2");
53  add_enth(geothermal_flux, 0, "geothermal_flux"); //!< Total amount of geothermal energy [J/m^2]
54 
56  .long_name("Geothermal energy through (compare to geothermal_flux?)")
57  .units("W m-2");
58  // Total amount of geothermal energy [J/m^2]
59  add_enth(upward_geothermal_flux, DELTA, "upward_geothermal_flux");
60 
61  // ----------- Mass advection, with accompanying enthalpy change
62  // Postive means mass/enthalpy is flowing INTO the ice sheet.
63  calving.set_attrs("Mass/Enthalpy gain from calving. Should be negative.",
64  "m-2 s-1");
65  add_massenth(calving, DELTA, "calving.mass", "calving.enth");
66 
67  // SMB as seen by PISM in iMgeometry.cc massContExplicitSte().
68  // Used to check icebin_smb.mass, but does not figure into
69  // contract.
70  pism_smb.set_attrs("pism_smb", "m-2 s-1");
71  // No DELTA< does not participate in epsilon computation
72  add_massenth(pism_smb, EPSILON, "pism_smb.mass", "pism_smb.enth");
73 
74  // accumulation / ablation, as provided by Icebin
75  smb.set_attrs("smb", "m-2 s-1");
76  add_massenth(smb, DELTA, "smb.mass", "smb.enth");
77 
78  deltah.metadata(0).long_name("deltah").units("J m-2 s-1");
79  add_enth(deltah, DELTA, "");
80 
81  href_to_h.metadata(0).long_name("href_to_h").units("kg m-2 s-1");
82  add_mass(href_to_h, 0, "");
83 
84  nonneg_rule.metadata(0).long_name("nonneg_rule").units("kg m-2 s-1");
85  add_mass(nonneg_rule, 0, "");
86 
87 
88  melt_grounded.set_attrs("Basal melting of grounded ice (negative)", "m-2 s-1");
89  add_massenth(melt_grounded, DELTA, "melt_grounded.mass", "melt_grounded.enth");
90 
91  melt_floating.set_attrs("Sub-shelf melting (negative)", "m-2 s-1");
92  add_massenth(melt_floating, DELTA, "melt_floating.mass", "melt_floating.enth");
93 
94  // ----------- Advection WITHIN the ice sheet
95  internal_advection.set_attrs("Advection within the ice sheet", "m-2 s-1");
96  add_massenth(internal_advection, DELTA, "internal_advection.mass", "internal_advection.enth");
97 
98  // ----------- Balance the Budget
99  epsilon.set_attrs("Unaccounted-for changes", "m-2 s-1");
100  add_massenth(epsilon, EPSILON, "epsilon.mass", "epsilon.enth");
101 }
102 
103 std::ostream &MassEnergyBudget::print_formulas(std::ostream &out) {
104  // MASS
105  out << "epsilon.mass = total.mass -" << std::endl;
106  out << " (";
107  for (auto ii = all_vecs.begin(); ii != all_vecs.end(); ++ii) {
108  if ((ii->flags & (DELTA | MASS)) != (DELTA | MASS)) {
109  continue;
110  }
111  char str[20];
112  sprintf(str, "%p", (void *)&ii->vec);
113  out << ii->vec.get_name() << " + ";
114  }
115  out << ")" << std::endl;
116 
117  // Energy
118  out << "epsilon.enth = total.enth -" << std::endl;
119  out << " (";
120  for (auto ii = all_vecs.begin(); ii != all_vecs.end(); ++ii) {
121  if ((ii->flags & (DELTA | ENTH)) != (DELTA | ENTH)) {
122  continue;
123  }
124  char str[20];
125  sprintf(str, "%p", (void *)&ii->vec);
126  out << ii->vec.get_name() << " + ";
127  }
128  out << ")" << std::endl;
129 
130  return out;
131 }
132 
133 
135  auto grid = epsilon.mass.grid();
136  // ==> epsilon = (sum of fluxes) - total
137 
138  // -------- Mass
141  for (int i = grid->xs(); i < grid->xs() + grid->xm(); ++i) {
142  for (int j = grid->ys(); j < grid->ys() + grid->ym(); ++j) {
143  epsilon.mass(i, j) = total.mass(i, j);
144  }
145  }
147 
148  for (auto &ii : all_vecs) {
149  // This normally does not include things marked EPSILON
150  // (which is mutually exclusive with DELTA)
151  // This excluded epsilon (ourself), as well as redundant pism_smb
152  if ((ii.flags & (DELTA | MASS)) != (DELTA | MASS)) {
153  continue;
154  }
155 
156  ii.vec.begin_access();
157  for (int i = grid->xs(); i < grid->xs() + grid->xm(); ++i) {
158  for (int j = grid->ys(); j < grid->ys() + grid->ym(); ++j) {
159  epsilon.mass(i, j) -= ii.vec(i, j);
160  }
161  }
162  ii.vec.end_access();
163  }
165 
166  // -------- Energy
169  for (int i = grid->xs(); i < grid->xs() + grid->xm(); ++i) {
170  for (int j = grid->ys(); j < grid->ys() + grid->ym(); ++j) {
171  epsilon.enth(i, j) = total.enth(i, j);
172  }
173  }
175 
176 #if 1
177  for (auto &ii : all_vecs) {
178  if ((ii.flags & (DELTA | ENTH)) != (DELTA | ENTH)) {
179  continue;
180  }
181 
182  printf("epsilon.energy: %s\n", ii.vec.get_name().c_str());
183 
184  ii.vec.begin_access();
185  for (int i = grid->xs(); i < grid->xs() + grid->xm(); ++i) {
186  for (int j = grid->ys(); j < grid->ys() + grid->ym(); ++j) {
187  epsilon.enth(i, j) -= ii.vec(i, j);
188  }
189  }
190  ii.vec.end_access();
191  }
192 #endif
194 }
195 
196 } // namespace icebin
197 } // namespace pism
VariableMetadata & long_name(const std::string &input)
VariableMetadata & units(const std::string &input)
virtual void end_access() const
Checks if an Array is allocated and calls DAVecRestoreArray.
Definition: Array.cc:667
virtual void begin_access() const
Checks if an Array is allocated and calls DAVecGetArray.
Definition: Array.cc:646
petsc::Vec & vec() const
Definition: Array.cc:339
std::shared_ptr< const Grid > grid() const
Definition: Array.cc:132
SpatialVariableMetadata & metadata(unsigned int N=0)
Returns a reference to the SpatialVariableMetadata object containing metadata for the compoment N.
Definition: Array.cc:553
pism::array::Scalar href_to_h
SMB as seen by PISM in iMgeometry.cc massContExplicitSte(). Used to check icebin_smb....
MassEnergyBudget(std::shared_ptr< const pism::Grid > grid, std::string const &prefix)
std::ostream & print_formulas(std::ostream &out)
MassEnthVec2S calving
Equal to IceModel::discharge_flux_2D_cumulative.
pism::array::Scalar geothermal_flux
Total amount of geothermal energy [J/m^2].
MassEnthVec2S smb
accumulation / ablation, as provided by Icebin
pism::array::Scalar basal_frictional_heating
Total amount of basal friction heating [J/m^2].
std::vector< VecWithFlags > all_vecs
void add_enth(pism::array::Scalar &vec, int flags, std::string const &contract_name)
pism::array::Scalar strain_heating
Total amount of strain heating [J/m^2].
MassEnthVec2S melt_grounded
basal melt (grounded) (from summing meltrate_grounded)
pism::array::Scalar upward_geothermal_flux
Total amount of geothermal energy [J/m^2].
MassEnthVec2S melt_floating
sub-shelf melt (from summing meltrate_floating)
void add_massenth(MassEnthVec2S &massenth, int flags, std::string const &contract_name_mass, std::string const &contract_name_enth)
void add_mass(pism::array::Scalar &vec, int flags, std::string const &contract_name)
pism::array::Scalar deltah
Change in enthalpy of top layer.
std::string printf(const char *format,...)
void set_attrs(const std::string &long_name, const std::string &units)
MassEnthVec2S(std::shared_ptr< const pism::Grid > grid, const std::string &name)