20#include "pism/geometry/flux_limiter.hh"
27#include "pism/util/array/Scalar.hh"
28#include "pism/util/array/Staggered.hh"
29#include "pism/util/pism_utilities.hh"
47static inline double pp(
double x) {
48 return std::max(x, 0.0);
54static inline double np(
double x) {
55 return -std::min(x, 0.0);
60 return dt * ((
pp(u.
e) +
np(u.
w)) / dx + (
pp(u.
n) +
np(u.
s)) / dy);
107double flux_limiter(
double F,
double F_out_c,
double F_out_n,
double x_c,
double x_n) {
111 double F_c = F_out_c != 0.0 ? pp(
F) / F_out_c * x_c : 0.0;
112 double F_n = F_out_n != 0.0 ? -np(
F) / F_out_n * x_n : 0.0;
114 double F_limited = std::max(std::min(
F, F_c), F_n);
116 assert(std::isfinite(F_limited));
146 double x_n,
double dx,
double dy,
double dt,
double eps) {
159 double F_out = flux_out(Q_c, dx, dy, dt);
160 double F_out_n = flux_out(Q_n, dx, dy, dt);
161 double F_out_e = flux_out(Q_e, dx, dy, dt);
164 double F_e = Q_c.
e * dt / dx;
165 double F_n = Q_c.
n * dt / dy;
178 double X_c = pp(x_c - eps);
179 double X_e = pp(x_e - eps);
180 double X_n = pp(x_n - eps);
183 double F_e_limited =
flux_limiter(F_e, F_out, F_out_e, X_c, X_e);
184 assert(x_c - F_e_limited >= 0);
185 assert(x_e + F_e_limited >= 0);
187 double F_n_limited =
flux_limiter(F_n, F_out, F_out_n, X_c, X_n);
188 assert(x_c - F_n_limited >= 0);
189 assert(x_n + F_n_limited >= 0);
192 return { F_e_limited * dx / dt, F_n_limited * dy / dt };
202 auto grid = result.
grid();
204 double eps = std::numeric_limits<double>::epsilon(), dx = grid->dx(), dy = grid->dy();
210 return (Q.e - Q.w) / dx + (Q.n - Q.s) / dy;
213 int limiter_count = 0;
215 for (
auto p : grid->points()) {
216 const int i = p.i(), j = p.j();
218 auto Q = flux.
star(i, j);
219 auto Q_n = flux.
star(i, j + 1);
220 auto Q_e = flux.
star(i + 1, j);
222 double x_c = x(i, j);
223 double x_e = x.
E(i, j);
224 double x_n = x.
N(i, j);
226 const double div_Q = div(Q), div_Q_e = div(Q_e), div_Q_n = div(Q_n);
228 if ((div_Q <= 0.0 or x_c - dt * div_Q >= eps) and
229 (div_Q_e <= 0.0 or x_e - dt * div_Q_e >= eps) and
230 (div_Q_n <= 0.0 or x_n - dt * div_Q_n >= eps)) {
236 result(i, j, 0) = Q.e;
237 result(i, j, 1) = Q.n;
243 auto Q_l =
flux_limiter(Q, Q_e, Q_n, x_c, x_e, x_n, dx, dy, dt, eps);
245 result(i, j, 0) = Q_l[0];
246 result(i, j, 1) = Q_l[1];
249 return GlobalSum(grid->com, limiter_count);
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
const T & N(int i, int j) const
const T & E(int i, int j) const
std::shared_ptr< const Grid > grid() const
stencils::Star< double > star(int i, int j) const
Returns the values at interfaces of the cell i,j using the staggered grid.
A class for storing and accessing internal staggered-grid 2D fields. Uses dof=2 storage....
static double pp(double x)
static double np(double x)
static double flux_out(const stencils::Star< double > &u, double dx, double dy, double dt)
int make_nonnegative_preserving(double dt, const array::Scalar1 &x, const array::Staggered1 &flux, array::Staggered &result)
static double F(double SL, double B, double H, double alpha)
double flux_limiter(double F, double F_out_c, double F_out_n, double x_c, double x_n)
void GlobalSum(MPI_Comm comm, double *local, double *result, int count)
Star stencil points (in the map-plane).