Loading [MathJax]/extensions/tex2jax.js
PISM, A Parallel Ice Sheet Model 2.2.2-d6b3a29ca committed by Constantine Khrulev on 2025-03-28
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
printout.cc
Go to the documentation of this file.
1// Copyright (C) 2004-2019, 2021, 2023, 2024 Jed Brown, Ed Bueler and Constantine Khroulev
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 <cstring>
20#include <cstdlib>
21
22#include <petscsys.h>
23
24#include "pism/icemodel/IceModel.hh"
25
26#include "pism/stressbalance/StressBalance.hh"
27
28#include "pism/util/Grid.hh"
29#include "pism/util/ConfigInterface.hh"
30#include "pism/util/Time.hh"
31
32#include "pism/util/pism_utilities.hh"
33
34namespace pism {
35
36
37//! Because of the -skip mechanism it is still possible that we can have CFL violations: count them.
38/*! This applies to the horizontal part of the 3D advection problem solved by AgeModel and the
39horizontal part of the 3D convection-diffusion problems solved by EnthalpyModel and
40TemperatureModel.
41*/
42unsigned int count_CFL_violations(const array::Array3D &u3,
43 const array::Array3D &v3,
44 const array::Scalar &ice_thickness,
45 double dt) {
46
47 if (dt == 0.0) {
48 return 0;
49 }
50
51 std::shared_ptr<const Grid> grid = u3.grid();
52
53 const double
54 CFL_x = grid->dx() / dt,
55 CFL_y = grid->dy() / dt;
56
57 array::AccessScope list{&ice_thickness, &u3, &v3};
58
59 unsigned int CFL_violation_count = 0;
60 ParallelSection loop(grid->com);
61 try {
62 for (auto p = grid->points(); p; p.next()) {
63 const int i = p.i(), j = p.j();
64
65 const int ks = grid->kBelowHeight(ice_thickness(i,j));
66
67 const double
68 *u = u3.get_column(i, j),
69 *v = v3.get_column(i, j);
70
71 // check horizontal CFL conditions at each point
72 for (int k = 0; k <= ks; k++) {
73 if (fabs(u[k]) > CFL_x) {
74 CFL_violation_count += 1;
75 }
76 if (fabs(v[k]) > CFL_y) {
77 CFL_violation_count += 1;
78 }
79 }
80 }
81 } catch (...) {
82 loop.failed();
83 }
84 loop.check();
85
86 return (unsigned int)GlobalMax(grid->com, CFL_violation_count);
87}
88
89void IceModel::print_summary(bool tempAndAge) {
90
91 const array::Array3D
92 &u3 = m_stress_balance->velocity_u(),
93 &v3 = m_stress_balance->velocity_v();
94
95 unsigned int n_CFL_violations = count_CFL_violations(u3, v3, m_geometry.ice_thickness,
96 tempAndAge ? dt_TempAge : m_dt);
97
98 // report CFL violations
99 if (n_CFL_violations > 0.0) {
100 const double CFLviolpercent = 100.0 * n_CFL_violations / (m_grid->Mx() * m_grid->My() * m_grid->Mz());
101 // at default verbosity level, only report CFL viols if above:
102 const double CFLVIOL_REPORT_VERB2_PERCENT = 0.1;
103 if (CFLviolpercent > CFLVIOL_REPORT_VERB2_PERCENT ||
104 m_log->get_threshold() > 2) {
105 auto tempstr = pism::printf(" [!CFL#=%d (=%5.2f%% of 3D grid)] ",
106 n_CFL_violations, CFLviolpercent);
107 m_stdout_flags = tempstr + m_stdout_flags;
108 }
109 }
110
111 // get maximum diffusivity
112 double max_diffusivity = m_stress_balance->max_diffusivity();
113 // get volumes in m^3 and areas in m^2
114 double volume = ice_volume(m_geometry, 0.0);
115 double area = ice_area(m_geometry, 0.0);
116
117 double meltfrac = 0.0;
118 if (tempAndAge or m_log->get_threshold() >= 3) {
119 meltfrac = compute_temperate_base_fraction(area);
120 }
121
122 // main report: 'S' line
123 print_summary_line(false, tempAndAge, m_dt,
124 volume, area, meltfrac, max_diffusivity);
125}
126
127
128//! Print a line to stdout which summarizes the state of the modeled ice sheet at the end of the time step.
129/*!
130This method is for casual inspection of model behavior, and to provide the user
131with some indication of the state of the run.
132
133Generally, two lines are printed to stdout, the first starting with a space
134and the second starting with the character 'S' in the left-most column (column 1).
135
136The first line shows flags for which processes executed, and the length of the
137time step (and/or substeps under option -skip). See IceModel::run()
138for meaning of these flags.
139
140If printPrototype is TRUE then the first line does not appear and
141the second line has alternate appearance. Specifically, different column 1
142characters are printed:
143 - 'P' line gives names of the quantities reported in the 'S' line, the
144 "prototype", while
145 - 'U' line gives units of these quantities.
146This column 1 convention allows automatic tools to read PISM stdout
147and produce time-series. The 'P' and 'U' lines are intended to appear once at
148the beginning of the run, while an 'S' line appears at every time step.
149
150These quantities are reported in this base class version:
151 - `time` is the current model time
152 - `ivol` is the total ice sheet volume
153 - `iarea` is the total area occupied by positive thickness ice
154 - `max_diffusivity` is the maximum diffusivity
155 - `max_sliding_vel` is max(max(abs(u)), max(abs(v)))
156
157Configuration parameters `output.runtime.time_unit_name`, `output.runtime.volume_scale_factor_log10`,
158and `output.runtime.area_scale_factor_log10` control the appearance and units.
159
160For more description and examples, see the PISM User's Manual.
161Derived classes of IceModel may redefine this method and print alternate
162information.
163 */
164void IceModel::print_summary_line(bool printPrototype, bool tempAndAge,
165 double delta_t,
166 double volume, double area,
167 double /* meltfrac */, double max_diffusivity) {
168 const bool do_energy = member(m_config->get_string("energy.model"), {"cold", "enthalpy"});
169 const int log10scalevol = static_cast<int>(m_config->get_number("output.runtime.volume_scale_factor_log10")),
170 log10scalearea = static_cast<int>(m_config->get_number("output.runtime.area_scale_factor_log10"));
171 const std::string time_units = m_config->get_string("output.runtime.time_unit_name");
172 const bool use_calendar = m_config->get_flag("output.runtime.time_use_calendar");
173
174 const double scalevol = pow(10.0, static_cast<double>(log10scalevol)),
175 scalearea = pow(10.0, static_cast<double>(log10scalearea));
176 std::string
177 volscalestr = " ",
178 areascalestr = " "; // blank when 10^0 = 1 scaling
179 if (log10scalevol != 0) {
180 volscalestr = pism::printf("10^%1d_", log10scalevol);
181 }
182 if (log10scalearea != 0) {
183 areascalestr = pism::printf("10^%1d_", log10scalearea);
184 }
185
186 if (printPrototype) {
187 m_log->message(2,
188 "P time: ivol iarea max_diffusivity max_sliding_vel\n");
189 m_log->message(2,
190 "U %s %skm^3 %skm^2 m^2 s^-1 m/%s\n",
191 time_units.c_str(),
192 volscalestr.c_str(),
193 areascalestr.c_str(),
194 time_units.c_str());
195 return;
196 }
197
198 // this version keeps track of what has been done so as to minimize stdout:
199 // FIXME: turn these static variables into class members.
200 static std::string stdout_flags_count0;
201 static int mass_cont_sub_counter = 0;
202 static double mass_cont_sub_dtsum = 0.0;
203 if (mass_cont_sub_counter == 0) {
204 stdout_flags_count0 = m_stdout_flags;
205 }
206 if (delta_t > 0.0) {
207 mass_cont_sub_counter++;
208 mass_cont_sub_dtsum += delta_t;
209 }
210
211 if (tempAndAge or (not do_energy) or (m_log->get_threshold() > 2)) {
212 std::string tempstr;
213
214 const double major_dt = m_time->convert_time_interval(mass_cont_sub_dtsum, time_units);
215 if (mass_cont_sub_counter <= 1) {
216 tempstr = pism::printf(" (dt=%.5f)", major_dt);
217 } else {
218 tempstr = pism::printf(" (dt=%.5f in %d substeps; av dt_sub_mass_cont=%.5f)",
219 major_dt, mass_cont_sub_counter, major_dt / mass_cont_sub_counter);
220 }
221 stdout_flags_count0 += tempstr;
222
223 if (delta_t > 0.0) { // avoids printing an empty line if we have not done anything
224 stdout_flags_count0 += "\n";
225 m_log->message(2, stdout_flags_count0);
226 }
227
228 double T = m_time->current();
229 if (use_calendar) {
230 tempstr = pism::printf("%12s", m_time->date(T).c_str());
231 } else {
232 tempstr = pism::printf("%.3f", m_time->convert_time_interval(T, time_units));
233 }
234
235 const CFLData cfl = m_stress_balance->max_timestep_cfl_2d();
236 std::string velocity_units = "meters / (" + time_units + ")";
237 const double maxvel = units::convert(m_sys, std::max(cfl.u_max, cfl.v_max),
238 "m second^-1", velocity_units);
239
240 m_log->message(2,
241 "S %s: %8.5f %9.5f %12.5f %12.5f\n",
242 tempstr.c_str(),
243 volume/(scalevol*1.0e9), area/(scalearea*1.0e6),
244 max_diffusivity, maxvel);
245
246 mass_cont_sub_counter = 0;
247 mass_cont_sub_dtsum = 0.0;
248 }
249}
250
251
252} // end of namespace pism
array::Scalar2 ice_thickness
Definition Geometry.hh:51
virtual double compute_temperate_base_fraction(double ice_area)
std::shared_ptr< stressbalance::StressBalance > m_stress_balance
Definition IceModel.hh:395
const Time::Ptr m_time
Time manager.
Definition IceModel.hh:246
Geometry m_geometry
Definition IceModel.hh:288
const Logger::Ptr m_log
Logger.
Definition IceModel.hh:244
virtual void print_summary(bool tempAndAge)
Definition printout.cc:89
std::string m_stdout_flags
Definition IceModel.hh:321
Config::Ptr m_config
Configuration flags and parameters.
Definition IceModel.hh:238
const units::System::Ptr m_sys
Unit system.
Definition IceModel.hh:242
virtual void print_summary_line(bool printPrototype, bool tempAndAge, double delta_t, double volume, double area, double meltfrac, double max_diffusivity)
Print a line to stdout which summarizes the state of the modeled ice sheet at the end of the time ste...
Definition printout.cc:164
double dt_TempAge
enthalpy/temperature and age time-steps
Definition IceModel.hh:315
double m_dt
mass continuity time step, s
Definition IceModel.hh:311
const std::shared_ptr< Grid > m_grid
Computational grid.
Definition IceModel.hh:236
void failed()
Indicates a failure of a parallel section.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:64
double * get_column(int i, int j)
Definition Array3D.cc:121
A virtual class collecting methods common to ice and bedrock 3D fields.
Definition Array3D.hh:33
std::shared_ptr< const Grid > grid() const
Definition Array.cc:131
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
unsigned int count_CFL_violations(const array::Array3D &u3, const array::Array3D &v3, const array::Scalar &ice_thickness, double dt)
Because of the -skip mechanism it is still possible that we can have CFL violations: count them.
Definition printout.cc:42
double ice_area(const Geometry &geometry, double thickness_threshold)
Computes ice area, in m^2.
Definition Geometry.cc:336
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
std::string printf(const char *format,...)
static const double k
Definition exactTestP.cc:42
double ice_volume(const Geometry &geometry, double thickness_threshold)
Computes the ice volume, in m^3.
Definition Geometry.cc:254
bool member(const std::string &string, const std::set< std::string > &set)