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"
29 namespace stressbalance {
38 const double *B_nodal,
50 element.
evaluate(u_nodal, u, u_x, u_y, u_z);
56 for (
int q = 0; q < element.
n_pts(); ++q) {
67 double gamma = (ux * ux + vy * vy + ux * vy +
68 0.25 * ((uy + vx) * (uy + vx) + uz * uz + vz * vz));
77 for (
int t = 0; t < element.
n_chi(); ++t) {
78 const auto &psi = element.
chi(q, t);
80 residual[t].
u += W * (eta * (psi.dx * (4.0 * ux + 2.0 * vy) +
83 residual[t].
v += W * (eta * (psi.dx * (uy + vx) +
84 psi.dy * (2.0 * ux + 4.0 * vy) +
95 const double *surface,
120 p = (2.0 *
n + 2.0) /
n;
122 for (
int k = 0;
k < element.
n_chi(); ++
k) {
123 eta_nodal[
k] = pow(surface[
k] - bed[
k], p);
126 element.
evaluate(eta_nodal, eta, eta_x, eta_y, eta_z);
127 element.
evaluate(bed, b, b_x, b_y, b_z);
129 for (
int q = 0; q < element.
n_pts(); ++q) {
130 double C = pow(eta[q], 1.0 / p - 1.0) / p;
132 s_x[q] =
C * eta_x[q] + b_x[q];
133 s_y[q] =
C * eta_y[q] + b_y[q];
141 element.
evaluate(surface, s, s_x, s_y, s_z);
144 for (
int q = 0; q < element.
n_pts(); ++q) {
150 for (
int t = 0; t < element.
n_chi(); ++t) {
151 const auto &psi = element.
chi(q, t);
153 residual[t] += W * psi.val *
F;
165 const double *tauc_nodal,
166 const double *f_nodal,
180 for (
int q = 0; q < face.
n_pts(); ++q) {
183 bool grounded = floatation[q] <= 0.0;
187 for (
int t = 0; t < element.
n_chi(); ++t) {
188 auto psi = face.
chi(q, t);
190 residual[t] += W * psi * beta * u[q];
219 const double *surface_nodal,
220 const double *z_nodal,
221 const double *sl_nodal,
234 for (
int q = 0; q < face.
n_pts(); ++q) {
240 ice_depth = s[q] - z[q],
242 water_depth =
std::max(sea_level[q] - z[q], 0.0),
246 for (
int t = 0; t < element.
n_chi(); ++t) {
247 auto psi = face.
chi(q, t);
249 residual[t] += - W * psi * (p_ice - p_ocean) * N;
277 for (
int j = info.ys; j < info.ys + info.ym; j++) {
278 for (
int i = info.xs; i < info.xs + info.xm; i++) {
282 for (
int k = info.zs;
k < info.zs + info.zm;
k++) {
288 for (
int k = info.zs;
k < info.zs + info.zm;
k++) {
301 R[j][i][
k] = scaling * (x[j][i][
k] - U_bc);
318 assert(info.sw == 1);
328 dx, dy, x_min, y_min);
332 assert(element.
n_chi() <= Nk);
337 double floatation[Nk], sea_level[Nk], bottom_elevation[Nk], ice_thickness[Nk], surface_elevation[Nk];
338 double B[Nk], basal_yield_stress[Nk];
357 for (
int j = info.gys; j < info.gys + info.gym - 1; j++) {
358 for (
int i = info.gxs; i < info.gxs + info.gxm - 1; i++) {
374 for (
int k = info.gzs;
k < info.gzs + info.gzm - 1;
k++) {
377 for (
int n = 0;
n < Nk; ++
n) {
382 for (
int n = 0;
n < Nk; ++
n) {
384 z[
n] =
grid_z(bottom_elevation[
n], ice_thickness[
n], info.mz,
I.k);
389 element.
reset(i, j,
k, z);
397 for (
int n = 0;
n < Nk; ++
n) {
417 for (
int n = 0;
n < Nk; ++
n) {
420 basal_yield_stress[
n] = P[
I.j][
I.i].tauc;
421 floatation[
n] = P[
I.j][
I.i].floatation;
433 for (
int f = 0; f < 4; ++f) {
445 if (
k == info.mz - 2) {
463 MPI_Comm com = solver->
grid()->com;
465 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.
const Germ & chi(unsigned int q, unsigned int k) const
int n_pts() const
Number of quadrature points.
double weight(unsigned int q) const
Weight of the quadrature point q
double weight(unsigned int q) const
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
int n_pts() const
Number of quadrature points.
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
double max(const array::Scalar &input)
Finds maximum over all the values in an array::Scalar object. Ignores ghosts.
const int n_chi
Number of shape functions on a Q1 element.
bool grounded(int M)
Grounded cell (grounded ice or ice-free).
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)