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"
26 #include "pism/stressbalance/blatter/util/DataAccess.hh"
27 #include "pism/stressbalance/blatter/util/grid_hierarchy.hh"
30 namespace stressbalance {
37 const double *B_nodal,
49 element.
evaluate(u_nodal, u, u_x, u_y, u_z);
53 for (
int q = 0; q < element.
n_pts(); ++q) {
64 double gamma = (ux * ux + vy * vy + ux * vy +
65 0.25 * ((uy + vx) * (uy + vx) + uz * uz + vz * vz));
76 for (
int t = 0; t < Nk; ++t) {
77 auto psi = element.
chi(q, t);
78 for (
int s = t; s < Nk; ++s) {
79 auto phi = element.
chi(q, s);
83 gamma_u = 2.0 * ux *
phi.dx + vy *
phi.dx + 0.5 *
phi.dy * (uy + vx) + 0.5 * uz *
phi.dz,
84 gamma_v = 2.0 * vy *
phi.dy + ux *
phi.dy + 0.5 *
phi.dx * (uy + vx) + 0.5 * vz *
phi.dz;
88 eta_u = deta * gamma_u,
89 eta_v = deta * gamma_v;
94 F_u = (psi.dx * (4.0 * ux + 2.0 * vy) + psi.dy * (uy + vx) + psi.dz * uz),
95 F_v = (psi.dx * (uy + vx) + psi.dy * (4.0 * vy + 2.0 * ux) + psi.dz * vz);
99 F_uu = 4.0 * psi.dx *
phi.dx + psi.dy *
phi.dy + psi.dz *
phi.dz,
100 F_uv = 2.0 * psi.dx *
phi.dy + psi.dy *
phi.dx;
104 F_vu = 2.0 * psi.dy *
phi.dx + psi.dx *
phi.dy,
105 F_vv = 4.0 * psi.dy *
phi.dy + psi.dx *
phi.dx + psi.dz *
phi.dz;
107 K[t * 2 + 0][s * 2 + 0] += W * (eta * F_uu + eta_u * F_u);
108 K[t * 2 + 0][s * 2 + 1] += W * (eta * F_uv + eta_v * F_u);
109 K[t * 2 + 1][s * 2 + 0] += W * (eta * F_vu + eta_u * F_v);
110 K[t * 2 + 1][s * 2 + 1] += W * (eta * F_vv + eta_v * F_v);
123 const double *tauc_nodal,
124 const double *f_nodal,
139 for (
int q = 0; q < face.
n_pts(); ++q) {
142 bool grounded = floatation[q] <= 0.0;
143 double beta = 0.0, dbeta = 0.0;
149 for (
int t = 0; t < Nk; ++t) {
150 auto psi = face.
chi(q, t);
151 for (
int s = 0; s < Nk; ++s) {
152 auto phi = face.
chi(q, s);
154 double p = psi *
phi;
156 K[t * 2 + 0][s * 2 + 0] += W * p * (beta + dbeta * u[q].
u * u[q].
u);
157 K[t * 2 + 0][s * 2 + 1] += W * p * dbeta * u[q].
u * u[q].
v;
158 K[t * 2 + 1][s * 2 + 0] += W * p * dbeta * u[q].
v * u[q].
u;
159 K[t * 2 + 1][s * 2 + 1] += W * p * (beta + dbeta * u[q].
v * u[q].
v);
177 for (
int j = info.ys; j < info.ys + info.ym; j++) {
178 for (
int i = info.xs; i < info.xs + info.xm; i++) {
179 for (
int k = info.zs;
k < info.zs + info.zm;
k++) {
182 double identity[4] = {scaling.
u, 0, 0, scaling.
v};
188 ierr = MatSetValuesBlockedStencil(
J, 1, &
row, 1, &
row, identity, ADD_VALUES);
189 PISM_CHK(ierr,
"MatSetValuesBlockedStencil");
204 PetscErrorCode ierr = MatZeroEntries(
J);
207 ierr = MatSetOption(A, MAT_SUBSET_OFF_PROC_ENTRIES, PETSC_TRUE);
210 ierr = MatSetOption(
J, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);
213 ierr = MatSetOption(
J, MAT_SYMMETRIC, PETSC_TRUE);
216 ierr = PetscObjectSetName((PetscObject)
J,
"bp_jacobian");
217 PISM_CHK(ierr,
"PetscObjectSetName");
222 assert(info.sw == 1);
233 dx, dy, x_min, y_min);
237 assert(element.
n_chi() <= Nk);
242 double floatation[Nk], bottom_elevation[Nk], ice_thickness[Nk];
243 double B_nodal[Nk], basal_yield_stress[Nk];
259 for (
int j = info.gys; j < info.gys + info.gym - 1; j++) {
260 for (
int i = info.gxs; i < info.gxs + info.gxm - 1; i++) {
275 for (
int k = info.gzs;
k < info.gzs + info.gzm - 1;
k++) {
279 double K[2*Nk][2*Nk];
280 memset(
K, 0,
sizeof(
K));
283 for (
int n = 0;
n < Nk; ++
n) {
286 z[
n] =
grid_z(bottom_elevation[
n], ice_thickness[
n], info.mz,
I.k);
291 element.
reset(i, j,
k, z);
298 for (
int n = 0;
n < Nk; ++
n) {
314 for (
int n = 0;
n < Nk; ++
n) {
317 basal_yield_stress[
n] = P[
I.j][
I.i].tauc;
318 floatation[
n] = P[
I.j][
I.i].floatation;
330 for (
int t = 0; t < Nk; ++t) {
331 for (
int s = 0; s < t; ++s) {
332 K[t * 2 + 0][s * 2 + 0] =
K[s * 2 + 0][t * 2 + 0];
333 K[t * 2 + 1][s * 2 + 0] =
K[s * 2 + 0][t * 2 + 1];
334 K[t * 2 + 0][s * 2 + 1] =
K[s * 2 + 1][t * 2 + 0];
335 K[t * 2 + 1][s * 2 + 1] =
K[s * 2 + 1][t * 2 + 1];
346 ierr = MatAssemblyBegin(
J, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyBegin");
347 ierr = MatAssemblyEnd(
J, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyEnd");
349 ierr = MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyBegin");
350 ierr = MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY);
PISM_CHK(ierr,
"MatAssemblyEnd");
361 MPI_Comm com = solver->
grid()->com;
363 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 void drag_with_derivative(double tauc, double vx, double vy, double *drag, double *ddrag) const
Compute the drag coefficient and its derivative with respect to .
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
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...
void mark_col_invalid(unsigned int k)
Mark that the column corresponding to local degree of freedom k should not be updated when inserting ...
void jacobian_dirichlet(const DMDALocalInfo &info, Parameters **P, Mat J)
virtual Vector2d u_bc(double x, double y, double z) const
fem::Q1Element3Face m_face4
double m_work[m_n_work][m_Nq]
static PetscErrorCode jacobian_callback(DMDALocalInfo *info, const Vector2d ***x, Mat A, Mat J, Blatter *solver)
fem::Q1Element3Face m_face100
static bool exterior_element(const int *node_type)
virtual void jacobian_f(const fem::Q1Element3 &element, const Vector2d *u_nodal, const double *B_nodal, double K[2 *fem::q13d::n_chi][2 *fem::q13d::n_chi])
static bool grounding_line(const double *F)
virtual void jacobian_basal(const fem::Q1Element3Face &face, const double *tauc_nodal, const double *f_nodal, const Vector2d *u_nodal, double K[2 *fem::q13d::n_chi][2 *fem::q13d::n_chi])
void compute_jacobian(DMDALocalInfo *info, const Vector2d ***x, Mat A, Mat J)
array::Array2D< Parameters > m_parameters
virtual bool dirichlet_node(const DMDALocalInfo &info, const fem::Element3::GlobalIndex &I)
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
#define PISM_CHK(errcode, name)
const int n_chi
Number of shape functions on a Q1 element.
static Vector3 row(const double A[3][3], size_t k)
static double K(double psi_x, double psi_y, double speed, double epsilon)
bool grounded(int M)
Grounded cell (grounded ice or ice-free).
double grid_z(double b, double H, int Mz, int k)
DMDALocalInfo grid_transpose(const DMDALocalInfo &input)
void handle_fatal_errors(MPI_Comm com)