22 #include "pism/geometry/MPDATA2.hh"
24 #include "pism/util/array/CellType.hh"
41 static double pp(
double x) {
46 static double np(
double x) {
62 double dx,
double dy,
double dt) {
63 return dt * ((
pp(u.
w) * psi.
w -
np(u.
e) * psi.
e) / dx +
64 (
pp(u.
s) * psi.
s -
np(u.
n) * psi.
n) / dy);
69 double dx,
double dy,
double dt) {
70 return dt * ((
pp(u.
e) * psi.
c -
np(u.
w) * psi.
c) / dx +
71 (
pp(u.
n) * psi.
c -
np(u.
s) * psi.
c) / dy);
77 double dx,
double dy,
double dt) {
78 const double eps = 1e-15;
81 return (psi_max - psi.
c) / (
flux_in(u, psi, dx, dy, dt) + eps);
87 double dx,
double dy,
double dt) {
88 const double eps = 1e-15;
91 return (psi.
c - psi_min) / (
flux_out(u, psi, dx, dy, dt) + eps);
100 auto grid = x_old.
grid();
108 for (
auto p = grid->points(); p; p.next()) {
109 const int i = p.i(), j = p.j();
116 X_old = x_old.
star(i, j),
117 u = velocity.
star(i, j);
119 beta_u =
beta_up(u, X, X_old, dx, dy, dt);
120 beta_d =
beta_down(u, X, X_old, dx, dy, dt);
126 X = x.
star(i + 1, j),
127 X_old = x_old.
star(i + 1, j),
128 u = velocity.
star(i + 1, j);
138 result(i, j, 0) = u.w *
C;
144 X = x.
star(i, j + 1),
145 X_old = x_old.
star(i, j + 1),
146 u = velocity.
star(i, j + 1);
156 result(i, j, 1) = u.s *
C;
168 : m_v(grid,
"velocity_staggered"),
169 m_v_old(grid,
"tmp"),
170 m_v_ghosted(grid,
"velocity_ghosted"),
171 m_x_previous(grid,
"previous_state"),
172 m_x_input(grid,
"input_field"),
173 m_x(grid,
"new_state"),
186 auto grid = cell_type.
grid();
190 for (
auto p = grid->points(); p; p.next()) {
191 const int i = p.i(), j = p.j();
195 V_e = velocity(i + 1, j),
196 V_n = velocity(i, j + 1);
199 W =
static_cast<int>(cell_type.
icy(i, j)),
200 W_n =
static_cast<int>(cell_type.
icy(i, j + 1)),
201 W_e =
static_cast<int>(cell_type.
icy(i + 1, j));
203 result(i, j, 0) = (W * V.
u + W_e * V_e.u) /
std::max(W + W_e, 1);
204 result(i, j, 1) = (W * V.
v + W_n * V_n.v) /
std::max(W + W_n, 1);
218 auto grid = x.
grid();
227 for (
auto p = grid->points(); p; p.next()) {
228 const int i = p.i(), j = p.j();
230 auto X = x.
box(i, j);
235 u = velocity(i, j, 0),
236 v_bar = 0.25 * (velocity(i + 1, j, 1) + velocity(i, j, 1) +
237 velocity(i, j - 1, 1) + velocity(i + 1, j - 1, 1));
241 double U = ((fabs(u) * dx - dt * u * u) * (X.e - X.c) / ((X.e + X.c + eps) * dx)
242 - 0.5 * dt * u * v_bar
243 * (X.ne - X.se + X.n - X.s) / ((X.ne + X.se + X.n + X.s + eps) * dy));
251 v = velocity(i, j, 1),
252 u_bar = 0.25 * (velocity(i, j + 1, 0) + velocity(i, j, 0) +
253 velocity(i - 1, j, 0) + velocity(i - 1, j + 1, 0));
257 double V = ((fabs(v) * dy - dt * v * v) * (X.n - X.c) / ((X.n + X.c + eps) * dy)
258 - 0.5 * dt * v * u_bar *
259 (X.ne - X.nw + X.e - X.w) / ((X.ne + X.nw + X.e + X.w + eps) * dx));
269 static double upwind(
double x,
double x_n,
double u) {
270 return u * (u >= 0.0 ? x : x_n);
286 auto grid = x.
grid();
293 for (
auto p = grid->points(); p; p.next()) {
294 const int i = p.i(), j = p.j();
296 auto u = velocity.
star(i, j);
297 auto f = x_old.
star(i, j);
300 Q_e =
upwind(f.c, f.e, u.e),
301 Q_w =
upwind(f.w, f.c, u.w),
302 Q_n =
upwind(f.c, f.n, u.n),
303 Q_s =
upwind(f.s, f.c, u.s);
305 x(i, j) = x_old(i, j) - dt * ((Q_e - Q_w) / dx + (Q_n - Q_s) / dy);
313 bool nonoscillatory) {
318 for (
int k = 0;
k <
m_N; ++
k) {
327 if (nonoscillatory) {
array::Vector1 m_v_ghosted
array::Staggered1 m_v_old
const array::Scalar & x() const
MPDATA2(std::shared_ptr< const Grid > grid, int N)
array::Scalar2 m_x_previous
void update(double dt, const array::CellType &cell_type, const array::Scalar &x, const array::Vector &velocity, bool nonoscillatory=false)
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
Makes sure that we call begin_access() and end_access() for all accessed array::Arrays.
stencils::Box< T > box(int i, int j) const
void copy_from(const Array2D< T > &source)
stencils::Star< T > star(int i, int j) const
std::shared_ptr< const Grid > grid() const
void update_ghosts()
Updates ghost points.
bool icy(int i, int j) const
"Cell type" mask. Adds convenience methods to array::Scalar.
stencils::Star< double > star(int i, int j) const
Returns the values at interfaces of the cell i,j using the staggered grid.
void copy_from(const array::Staggered &input)
A class for storing and accessing internal staggered-grid 2D fields. Uses dof=2 storage....
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
double min(const array::Scalar &input)
Finds minimum over all the values in an array::Scalar object. Ignores ghosts.
static double flux_out(const stencils::Star< double > &u, const stencils::Star< double > &psi, double dx, double dy, double dt)
static double beta_up(const stencils::Star< double > &u, const stencils::Star< double > &psi, const stencils::Star< double > &psi_old, double dx, double dy, double dt)
static double maximum(const stencils::Star< double > &psi)
static double minimum(const stencils::Star< double > &psi)
static double beta_down(const stencils::Star< double > &u, const stencils::Star< double > &psi, const stencils::Star< double > &psi_old, double dx, double dy, double dt)
static double np(double x)
static void limit(double dt, const array::Scalar2 &x_old, const array::Scalar2 &x, const array::Staggered1 &velocity, array::Staggered &result)
static double pp(double x)
static double flux_in(const stencils::Star< double > &u, const stencils::Star< double > &psi, double dx, double dy, double dt)
static void step(double dt, const array::Staggered1 &velocity, const array::Scalar1 &x_old, array::Scalar &x)
static double upwind(double x, double x_n, double u)
static void compute_corrective_velocity(double dt, const array::Staggered &velocity, const array::Scalar2 &x, array::Staggered &result)
static void compute_interface_velocity(const array::CellType &cell_type, const array::Vector &velocity, array::Staggered &result)
Star stencil points (in the map-plane).