PISM, A Parallel Ice Sheet Model 2.3.0-79cae578d committed by Constantine Khrulev on 2026-03-22
Loading...
Searching...
No Matches
timestepping.cc
Go to the documentation of this file.
1/* Copyright (C) 2016, 2017, 2020, 2022, 2023, 2024, 2025, 2026 PISM Authors
2 *
3 * This file is part of PISM.
4 *
5 * PISM is free software; you can redistribute it and/or modify it under the
6 * terms of the GNU General Public License as published by the Free Software
7 * Foundation; either version 3 of the License, or (at your option) any later
8 * version.
9 *
10 * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13 * details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with PISM; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "pism/stressbalance/timestepping.hh"
21#include "pism/util/Grid.hh"
22#include "pism/util/array/Array3D.hh"
23#include "pism/util/array/Scalar.hh"
24#include "pism/util/array/CellType.hh"
25#include "pism/util/array/Vector.hh"
26#include "pism/util/pism_utilities.hh"
27#include "pism/util/Context.hh"
28#include <limits>
29#include <vector>
30
31namespace pism {
32
34 u_max = 0.0;
35 v_max = 0.0;
36 w_max = 0.0;
37}
38
39//! Compute the maximum velocities for time-stepping and reporting to user.
40/*!
41Computes the maximum magnitude of the components \f$u,v,w\f$ of the 3D velocity.
42
43Under BOMBPROOF there is no CFL condition for the vertical advection.
44The maximum vertical velocity is computed but it does not affect the output.
45 */
47 const array::CellType &cell_type,
48 const array::Scalar1 *no_model_mask,
49 const array::Array3D &u3,
50 const array::Array3D &v3,
51 const array::Array3D &w3) {
52
53 auto grid = ice_thickness.grid();
54 auto config = grid->ctx()->config();
55
56 double dt_max = config->get_number("time_stepping.maximum_time_step", "seconds");
57
58 array::AccessScope list{&ice_thickness, &u3, &v3, &w3, &cell_type};
59
60 bool has_no_model_mask;
61 if (no_model_mask != nullptr) {
62 has_no_model_mask = true;
63 list.add(*no_model_mask);
64 } else {
65 has_no_model_mask = false;
66 }
67
68 // update global max of abs of velocities for CFL; only velocities under surface
69 const double
70 one_over_dx = 1.0 / grid->dx(),
71 one_over_dy = 1.0 / grid->dy();
72
73 double u_max = 0.0, v_max = 0.0, w_max = 0.0;
74 ParallelSection loop(grid->com);
75 try {
76 for (auto p : grid->points()) {
77 const int i = p.i(), j = p.j();
78
79 bool is_modeled = true;
80 if (has_no_model_mask) {
81 if ((*no_model_mask)(i, j) == 1) {
82 is_modeled = false;
83 }
84 }
85
86 if ((cell_type.icy(i, j)) && is_modeled) {
87 const int ks = grid->kBelowHeight(ice_thickness(i, j));
88 const double
89 *u = u3.get_column(i, j),
90 *v = v3.get_column(i, j),
91 *w = w3.get_column(i, j);
92
93 for (int k = 0; k <= ks; ++k) {
94 const double
95 u_abs = fabs(u[k]),
96 v_abs = fabs(v[k]);
97 u_max = std::max(u_max, u_abs);
98 v_max = std::max(v_max, v_abs);
99 const double denom = fabs(u_abs * one_over_dx) + fabs(v_abs * one_over_dy);
100 // note: use std::numeric_limits<double>::min() to avoid FP overflow when
101 // computing the inverse in 1.0 / denom
102 if (denom > std::numeric_limits<double>::min()) {
103 dt_max = std::min(dt_max, 1.0 / denom);
104 }
105 }
106
107 for (int k = 0; k <= ks; ++k) {
108 w_max = std::max(w_max, fabs(w[k]));
109 }
110 }
111 }
112 } catch (...) {
113 loop.failed();
114 }
115 loop.check();
116
117 CFLData result;
118
119 std::vector<double> data = {u_max, v_max, w_max}, tmp(3, 0.0);
120 GlobalMax(grid->com, data.data(), tmp.data(), 3);
121 result.u_max = tmp[0];
122 result.v_max = tmp[1];
123 result.w_max = tmp[2];
124 result.dt_max = MaxTimestep(GlobalMin(grid->com, dt_max));
125
126 return result;
127}
128
129//! Compute the CFL constant associated to first-order upwinding for the sliding contribution to mass continuity.
130/*!
131 This procedure computes the maximum horizontal speed in the icy
132 areas. In particular it computes CFL constant for the upwinding, in
133 GeometryEvolution::step(), which applies to the basal component of mass
134 flux.
135
136 That is, because the map-plane mass continuity is advective in the
137 sliding case we have a CFL condition.
138 */
140 const array::CellType &cell_type,
141 const array::Scalar1 *no_model_mask,
142 const array::Vector &velocity) {
143
144 auto grid = ice_thickness.grid();
145 auto config = grid->ctx()->config();
146
147 double dt_max = config->get_number("time_stepping.maximum_time_step", "seconds");
148
149 const double
150 dx = grid->dx(),
151 dy = grid->dy();
152
153 array::AccessScope list{&velocity, &cell_type};
154
155 bool has_no_model_mask;
156 if (no_model_mask != nullptr) {
157 has_no_model_mask = true;
158 list.add(*no_model_mask);
159 } else {
160 has_no_model_mask = false;
161 }
162
163 double u_max = 0.0, v_max = 0.0;
164 for (auto p : grid->points()) {
165 const int i = p.i(), j = p.j();
166
167 bool is_modeled = true;
168 if (has_no_model_mask) {
169 if ((*no_model_mask)(i, j) == 1) {
170 is_modeled = false;
171 }
172 }
173
174 if ((cell_type.icy(i, j)) && is_modeled) {
175 const double
176 u_abs = fabs(velocity(i, j).u),
177 v_abs = fabs(velocity(i, j).v);
178
179 u_max = std::max(u_max, u_abs);
180 v_max = std::max(v_max, v_abs);
181
182 const double denom = u_abs / dx + v_abs / dy;
183 if (denom > std::numeric_limits<double>::min()) {
184 dt_max = std::min(dt_max, 1.0 / denom);
185 }
186 }
187 }
188
189 CFLData result;
190
191 std::vector<double> data = {u_max, v_max}, tmp(2, 0.0);
192 GlobalMax(grid->com, data.data(), tmp.data(), 2);
193 result.u_max = tmp[0];
194 result.v_max = tmp[1];
195 result.w_max = 0.0;
196 result.dt_max = MaxTimestep(GlobalMin(grid->com, dt_max));
197
198 return result;
199}
200
201MaxTimestep max_timestep_diffusivity(double D_max, double dx, double dy,
202 double adaptive_timestepping_ratio) {
203 if (D_max > 0.0) {
204 double grid_factor = 1.0 / (dx * dx) + 1.0 / (dy * dy);
205 return MaxTimestep(adaptive_timestepping_ratio * 2.0 / (D_max * grid_factor), "diffusivity");
206 }
207
208 return {};
209}
210
211} // end of namespace pism
Combines the max. time step with the flag indicating if a restriction is active. Makes is possible to...
void failed()
Indicates a failure of a parallel section.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
Definition Array.hh:66
double * get_column(int i, int j)
Definition Array3D.cc:127
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:134
bool icy(int i, int j) const
Definition CellType.hh:42
"Cell type" mask. Adds convenience methods to array::Scalar.
Definition CellType.hh:30
void GlobalMax(MPI_Comm comm, double *local, double *result, int count)
CFLData max_timestep_cfl_2d(const array::Scalar &ice_thickness, const array::CellType &cell_type, const array::Scalar1 *no_model_mask, const array::Vector &velocity)
Compute the CFL constant associated to first-order upwinding for the sliding contribution to mass con...
static const double k
Definition exactTestP.cc:42
MaxTimestep max_timestep_diffusivity(double D_max, double dx, double dy, double adaptive_timestepping_ratio)
void GlobalMin(MPI_Comm comm, double *local, double *result, int count)
CFLData max_timestep_cfl_3d(const array::Scalar &ice_thickness, const array::CellType &cell_type, const array::Scalar1 *no_model_mask, const array::Array3D &u3, const array::Array3D &v3, const array::Array3D &w3)
Compute the maximum velocities for time-stepping and reporting to user.
MaxTimestep dt_max