20#include "pism/stressbalance/blatter/Blatter.hh"
22#include "pism/basalstrength/basal_resistance.hh"
23#include "pism/rheology/FlowLaw.hh"
24#include "pism/util/node_types.hh"
25#include "pism/stressbalance/blatter/util/DataAccess.hh"
26#include "pism/stressbalance/blatter/util/grid_hierarchy.hh"
27#include "pism/util/fem/Quadrature.hh"
30namespace stressbalance {
39 const double *B_nodal,
51 element.
evaluate(u_nodal, u, u_x, u_y, u_z);
57 for (
unsigned int q = 0; q < element.
n_pts(); ++q) {
68 double gamma = (ux * ux + vy * vy + ux * vy +
69 0.25 * ((uy + vx) * (uy + vx) + uz * uz + vz * vz));
78 for (
int t = 0; t < element.
n_chi(); ++t) {
79 const auto &psi = element.
chi(q, t);
81 residual[t].
u += W * (eta * (psi.dx * (4.0 * ux + 2.0 * vy) +
84 residual[t].
v += W * (eta * (psi.dx * (uy + vx) +
85 psi.dy * (2.0 * ux + 4.0 * vy) +
96 const double *surface,
121 p = (2.0 *
n + 2.0) /
n;
123 for (
int k = 0;
k < element.
n_chi(); ++
k) {
124 eta_nodal[
k] = pow(surface[
k] - bed[
k], p);
127 element.
evaluate(eta_nodal, eta, eta_x, eta_y, eta_z);
128 element.
evaluate(bed, b, b_x, b_y, b_z);
130 for (
unsigned int q = 0; q < element.
n_pts(); ++q) {
131 double C = pow(eta[q], 1.0 / p - 1.0) / p;
133 s_x[q] = C * eta_x[q] + b_x[q];
134 s_y[q] = C * eta_y[q] + b_y[q];
142 element.
evaluate(surface, s, s_x, s_y, s_z);
145 for (
unsigned int q = 0; q < element.
n_pts(); ++q) {
151 for (
int t = 0; t < element.
n_chi(); ++t) {
152 const auto &psi = element.
chi(q, t);
154 residual[t] += W * psi.val *
F;
166 const double *tauc_nodal,
167 const double *f_nodal,
181 for (
unsigned int q = 0; q < face.
n_pts(); ++q) {
184 bool grounded = floatation[q] <= 0.0;
188 for (
int t = 0; t < element.
n_chi(); ++t) {
189 auto psi = face.
chi(q, t);
191 residual[t] += W * psi * beta * u[q];
220 const double *surface_nodal,
221 const double *z_nodal,
222 const double *sl_nodal,
235 for (
unsigned int q = 0; q < face.
n_pts(); ++q) {
241 ice_depth = s[q] - z[q],
243 water_depth = std::max(sea_level[q] - z[q], 0.0),
247 for (
int t = 0; t < element.
n_chi(); ++t) {
248 auto psi = face.
chi(q, t);
250 residual[t] += - W * psi * (p_ice - p_ocean) * N;
278 for (
int j = info.ys; j < info.ys + info.ym; j++) {
279 for (
int i = info.xs; i < info.xs + info.xm; i++) {
283 for (
int k = info.zs;
k < info.zs + info.zm;
k++) {
289 for (
int k = info.zs;
k < info.zs + info.zm;
k++) {
302 R[j][i][
k] = scaling * (x[j][i][
k] - U_bc);
319 assert(info.sw == 1);
329 dx, dy, x_min, y_min);
333 assert(element.
n_chi() <= Nk);
338 double floatation[Nk], sea_level[Nk], bottom_elevation[Nk], ice_thickness[Nk], surface_elevation[Nk];
339 double B[Nk], basal_yield_stress[Nk];
358 for (
int j = info.gys; j < info.gys + info.gym - 1; j++) {
359 for (
int i = info.gxs; i < info.gxs + info.gxm - 1; i++) {
375 for (
int k = info.gzs;
k < info.gzs + info.gzm - 1;
k++) {
378 for (
int n = 0;
n < Nk; ++
n) {
383 for (
int n = 0;
n < Nk; ++
n) {
385 z[
n] =
grid_z(bottom_elevation[
n], ice_thickness[
n], info.mz, I.k);
390 element.
reset(i, j,
k, z);
398 for (
int n = 0;
n < Nk; ++
n) {
418 for (
int n = 0;
n < Nk; ++
n) {
421 basal_yield_stress[
n] = P[I.j][I.i].tauc;
422 floatation[
n] = P[I.j][I.i].floatation;
434 for (
int f = 0; f < 4; ++f) {
446 if (
k == info.mz - 2) {
464 MPI_Comm com = solver->
grid()->com;
466 SETERRQ(com, 1,
"A PISM callback failed");
std::shared_ptr< const Grid > grid() const
const std::shared_ptr< const Grid > m_grid
grid used by this component
virtual double drag(double tauc, double vx, double vy) const
Compute the drag coefficient for the basal shear stress.
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.
void nodal_values(T const *const *const *x_global, T *result) const
Extract nodal values for the element (i,j,k) from global array x_global into the element-local array ...
void add_contribution(const T *local, T ***y_global) const
Add the values of element-local contributions y to the global vector y_global.
GlobalIndex local_to_global(int i, int j, int k, unsigned int n) const
void evaluate(const T *x, T *vals, T *dx, T *dy, T *dz) const
Given nodal values, compute the values and partial derivatives at the quadrature points.
double weight(unsigned int q) const
Weight of the quadrature point q
const Germ & chi(unsigned int q, unsigned int k) const
unsigned int n_pts() const
Number of quadrature points.
double weight(unsigned int q) const
unsigned int n_pts() const
Number of quadrature points.
const double & chi(unsigned int q, unsigned int k) const
void evaluate(const T *x, T *result) const
const Vector3 & normal(unsigned int q) const
void reset(int face, const double *z)
void reset(int i, int j, int k, const double *z)
void mark_row_invalid(unsigned int k)
Mark that the row corresponding to local degree of freedom k should not be updated when inserting int...
virtual void residual_f(const fem::Q1Element3 &element, const Vector2d *u_nodal, const double *B_nodal, Vector2d *residual)
virtual Vector2d u_bc(double x, double y, double z) const
virtual void residual_source_term(const fem::Q1Element3 &element, const double *surface, const double *bed, Vector2d *residual)
virtual void residual_basal(const fem::Q1Element3 &element, const fem::Q1Element3Face &face, const double *tauc_nodal, const double *f_nodal, const Vector2d *u_nodal, Vector2d *residual)
void compute_residual(DMDALocalInfo *info, const Vector2d ***X, Vector2d ***R)
virtual bool marine_boundary(int face, const int *node_type, const double *ice_bottom, const double *sea_level)
fem::Q1Element3Face m_face4
static bool partially_submerged_face(int face, const double *z, const double *sea_level)
virtual void residual_lateral(const fem::Q1Element3 &element, const fem::Q1Element3Face &face, const double *surface_nodal, const double *z_nodal, const double *sl_nodal, Vector2d *residual)
double m_work[m_n_work][m_Nq]
void residual_dirichlet(const DMDALocalInfo &info, Parameters **P, const Vector2d ***x, Vector2d ***R)
static PetscErrorCode function_callback(DMDALocalInfo *info, const Vector2d ***x, Vector2d ***f, Blatter *solver)
fem::Q1Element3Face m_face100
static bool exterior_element(const int *node_type)
static bool grounding_line(const double *F)
array::Array2D< Parameters > m_parameters
virtual bool dirichlet_node(const DMDALocalInfo &info, const fem::Element3::GlobalIndex &I)
virtual void residual_surface(const fem::Q1Element3 &element, const fem::Q1Element3Face &face, Vector2d *residual)
Vector2d m_work2[m_n_work][m_Nq]
virtual void nodal_parameter_values(const fem::Q1Element3 &element, Parameters **P, int i, int j, int *node_type, double *bottom, double *thickness, double *surface, double *sea_level) const
const array::Vector1 & velocity() const
Get the thickness-advective 2D velocity.
std::shared_ptr< rheology::FlowLaw > m_flow_law
IceBasalResistancePlasticLaw * m_basal_sliding_law
const int n_chi
Number of shape functions on a Q1 element.
static const Vector2d u_exterior
double grid_z(double b, double H, int Mz, int k)
static double F(double SL, double B, double H, double alpha)
DMDALocalInfo grid_transpose(const DMDALocalInfo &input)
void handle_fatal_errors(MPI_Comm com)