22 #include "pism/util/fem/Element.hh"
23 #include "pism/util/Grid.hh"
24 #include "pism/util/array/Scalar.hh"
25 #include "pism/util/error_handling.hh"
26 #include "pism/util/petscwrappers/DM.hh"
32 static double det(
const double a[3][3]) {
33 return (a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) -
34 a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) +
35 a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]));
40 return {a.
y * b.
z - a.
z * b.
y,
41 a.
z * b.
x - a.
x * b.
z,
42 a.
x * b.
y - a.
y * b.
x};
47 return {A[
k][0], A[
k][1], A[
k][2]};
52 return {A[0][
k], A[1][
k], A[2][
k]};
57 return a.
dx * v.
x + a.
dy * v.
y + a.
dz + v.
z;
61 static void invert(
const double A[3][3],
double result[3][3]) {
62 const double det_A =
det(A);
74 double A_cofactor[3][3] = {{a.x, a.y, a.z},
79 for (
int i = 0; i < 3; ++i) {
80 for (
int j = 0; j < 3; ++j) {
82 result[i][j] = A_cofactor[j][i] / det_A;
111 m_block_size(block_size) {
114 auto da = grid.
get_dm(1, 0);
115 PetscErrorCode ierr = DMDAGetLocalInfo(*da, &m_grid);
117 throw std::runtime_error(
"Failed to allocate an Element instance");
122 m_germs.resize(Nq *
n_chi);
123 m_row.resize(block_size);
124 m_col.resize(block_size);
130 m_block_size(block_size) {
137 m_row.resize(block_size);
138 m_col.resize(block_size);
147 const std::vector<QuadPoint>& points,
148 const std::vector<double>& W) {
153 for (
unsigned int q = 0; q <
m_Nq; q++) {
154 for (
unsigned int k = 0;
k <
n_chi;
k++) {
160 const double J_det =
det(
J);
161 for (
unsigned int q = 0; q <
m_Nq; q++) {
181 result[
k] = floor(x_global(ii, jj) + 0.5);
201 int pism_i = 0, pism_j = 0;
233 PetscErrorCode ierr = MatSetValuesBlockedStencil(
J,
237 PISM_CHK(ierr,
"MatSetValuesBlockedStencil");
243 double dx = grid.
dx();
244 double dy = grid.
dy();
250 m_normals = {{0.0, -1.0}, {1.0, 0.0}, {0.0, 1.0}, {-1.0, 0.0}};
278 m_normals = {{0.0, -1.0}, {1.0, 0.0}, {0.0, 1.0}, {-1.0, 0.0}};
299 double dx = grid.
dx();
300 double dy = grid.
dy();
316 n13 /= n13.magnitude();
321 Vector2d p[] = {{0, 0}, {dx, 0}, {dx, dy}, {0, dy}};
322 std::vector<Vector2d> pts;
329 pts = {p[0], p[1], p[3]};
335 pts = {p[1], p[2], p[0]};
341 pts = {p[2], p[3], p[1]};
348 pts = {p[3], p[0], p[2]};
359 for (
unsigned int k = 0;
k <
n_sides(); ++
k) {
366 J[0][0] = pts[1].u - pts[0].u;
367 J[0][1] = pts[1].v - pts[0].v;
368 J[1][0] = pts[2].u - pts[0].u;
369 J[1][1] = pts[2].v - pts[0].v;
401 m_points(quadrature.points()),
402 m_w(quadrature.weights()) {
412 for (
unsigned int q = 0; q <
m_Nq; q++) {
424 m_points(quadrature.points()),
425 m_w(quadrature.weights()) {
435 for (
unsigned int q = 0; q <
m_Nq; q++) {
481 for (
unsigned int q = 0; q <
m_Nq; q++) {
491 double J[3][3] = {{
m_dx / 2.0, 0.0, dz.x},
492 { 0.0,
m_dy / 2.0, dz.y},
495 double J_det =
J[0][0] *
J[1][1] *
J[2][2];
497 assert(J_det != 0.0);
499 double J_inv[3][3] = {{1.0 /
J[0][0], 0.0, -
J[0][2] / (
J[0][0] *
J[2][2])},
500 {0.0, 1.0 /
J[1][1], -
J[1][2] / (
J[1][1] *
J[2][2])},
501 {0.0, 0.0, 1.0 /
J[2][2]}};
520 m_points(quadrature.points()),
521 m_w(quadrature.weights()),
522 m_n_chi(q13d::
n_chi),
538 for (
unsigned int q = 0; q <
m_Nq; q++) {
546 P = {-1.0, pt.
xi, pt.eta};
549 P = { 1.0, pt.
xi, pt.eta};
552 P = {pt.
xi, -1.0, pt.eta};
555 P = {pt.
xi, 1.0, pt.eta};
558 P = {pt.
xi, pt.eta, -1.0};
561 P = {pt.
xi, pt.eta, 1.0};
576 dz.x +=
chi.dx * z[
n];
577 dz.y +=
chi.dy * z[
n];
578 dz.z +=
chi.dz * z[
n];
588 double sign = 2 * (face % 2) - 1;
605 a = 0.5 *
m_dy * dz.x,
606 b = 0.5 *
m_dx * dz.y,
608 M = std::sqrt(a * a + b * b + c * c);
double dx() const
Horizontal grid spacing.
std::shared_ptr< petsc::DM > get_dm(unsigned int dm_dof, unsigned int stencil_width) const
Get a PETSc DM ("distributed array manager") object for given dof (number of degrees of freedom per g...
double dy() const
Horizontal grid spacing.
Describes the PISM grid and the distribution of data across processors.
double magnitude() const
Magnitude.
This class represents a 2D vector field (such as ice velocity) at a certain grid point.
Element2(const Grid &grid, int Nq, int n_chi, int block_size)
void local_to_global(unsigned int k, int &i, int &j) const
Convert a local degree of freedom index k to a global degree of freedom index (i,j).
void reset(int i, int j)
Initialize the Element to element (i, j) for the purposes of inserting into global residual and Jacob...
std::vector< double > m_side_lengths
std::vector< Vector2d > m_normals
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 nodal_values(const array::Scalar &x_global, int *result) const
Get nodal values of an integer mask.
unsigned int n_sides() const
void mark_col_invalid(unsigned int k)
Mark that the column corresponding to local degree of freedom k should not be updated when inserting ...
Element3(const DMDALocalInfo &grid_info, int Nq, int n_chi, int block_size)
std::vector< int > m_k_offset
GlobalIndex local_to_global(int i, int j, int k, unsigned int n) const
const Germ & chi(unsigned int q, unsigned int k) const
std::vector< int > m_i_offset
void initialize(const double J[3][3], ShapeFunction f, unsigned int n_chi, const std::vector< QuadPoint > &points, const std::vector< double > &W)
Initialize shape function values and quadrature weights of a 2D physical element.
std::vector< double > m_weights
Quadrature weights for a particular physical element.
std::vector< MatStencil > m_col
const unsigned int m_n_chi
void add_contribution(const double *K, Mat J) const
Add Jacobian contributions.
std::vector< Germ > m_germs
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...
const unsigned int m_Nq
Number of quadrature points.
static const int m_invalid_dof
std::vector< MatStencil > m_row
Stencils for updating entries of the Jacobian matrix.
void mark_col_invalid(unsigned int k)
Mark that the column corresponding to local degree of freedom k should not be updated when inserting ...
std::vector< int > m_j_offset
int m_i
Indices of the current element.
The mapping from global to local degrees of freedom.
P1Element2(const Grid &grid, const Quadrature &quadrature, int type)
Q1Element2(const Grid &grid, const Quadrature &quadrature)
Q1Element3Face(double dx, double dy, const Quadrature &quadrature)
std::vector< Vector3 > m_normals
const double & chi(unsigned int q, unsigned int k) const
std::vector< double > m_w
std::vector< double > m_chi
std::vector< QuadPoint > m_points
std::vector< double > m_weights
const unsigned int m_n_chi
void reset(int face, const double *z)
void reset(int i, int j, int k, const double *z)
std::vector< QuadPoint > m_points
Q1Element3(const DMDALocalInfo &grid, const Quadrature &quadrature, double dx, double dy, double x_min, double y_min)
double m_z_nodal[q13d::n_chi]
std::vector< double > m_w
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...
std::vector< Germ > m_chi
const std::vector< double > & weights() const
const std::vector< QuadPoint > & points() const
Numerical integration of finite element functions.
#define PISM_CHK(errcode, name)
Germ chi(unsigned int k, const QuadPoint &pt)
P1 basis functions on the reference element with nodes (0,0), (1,0), (0,1).
Germ chi(unsigned int k, const QuadPoint &p)
Evaluate a Q1 shape function and its derivatives with respect to xi and eta.
Germ chi(unsigned int k, const QuadPoint &pt)
Q1 basis functions on the reference element with nodes (-1,-1), (1,-1), (1,1), (-1,...
static double det(const double a[3][3])
Determinant of a 3x3 matrix.
static double dot(const Vector3 &v, const Germ &a)
static void invert(const double A[3][3], double result[3][3])
Invert a 3x3 matrix.
static Vector3 row(const double A[3][3], size_t k)
static void set_to_identity(double A[3][3])
static Germ multiply(const double A[3][3], const Germ &v)
Compute derivatives with respect to x,y using J^{-1} and derivatives with respect to xi,...
static Vector3 column(const double A[3][3], size_t k)
static Vector3 cross(const Vector3 &a, const Vector3 &b)
Cross product of two 3D vectors.
static double K(double psi_x, double psi_y, double speed, double epsilon)
static double sign(double x)
double dy
Function derivative with respect to y.
double val
Function value.
double dz
Function derivative with respect to z.
double dx
Function deriviative with respect to x.
Struct for gathering the value and derivative of a function at a point.