22#include "pism/util/fem/Element.hh"
23#include "pism/util/fem/Quadrature.hh"
24#include "pism/util/Grid.hh"
25#include "pism/util/array/Scalar.hh"
26#include "pism/util/error_handling.hh"
27#include "pism/util/petscwrappers/DM.hh"
33static double det(
const double a[3][3]) {
34 return (a[0][0] * (a[1][1] * a[2][2] - a[1][2] * a[2][1]) -
35 a[0][1] * (a[1][0] * a[2][2] - a[1][2] * a[2][0]) +
36 a[0][2] * (a[1][0] * a[2][1] - a[1][1] * a[2][0]));
33static double det(
const double a[3][3]) {
…}
41 return {a.
y * b.
z - a.
z * b.
y,
42 a.
z * b.
x - a.
x * b.
z,
43 a.
x * b.
y - a.
y * b.
x};
48 return {A[
k][0], A[
k][1], A[
k][2]};
53 return {A[0][
k], A[1][
k], A[2][
k]};
58 return a.
dx * v.
x + a.
dy * v.
y + a.
dz + v.
z;
62static void invert(
const double A[3][3],
double result[3][3]) {
63 const double det_A =
det(A);
75 double A_cofactor[3][3] = {{a.x, a.y, a.z},
80 for (
int i = 0; i < 3; ++i) {
81 for (
int j = 0; j < 3; ++j) {
83 result[i][j] = A_cofactor[j][i] / det_A;
62static void invert(
const double A[3][3],
double result[3][3]) {
…}
112 m_block_size(block_size) {
116 assert(m_block_size >= 1);
119 auto da = grid.get_dm(1, 0);
120 PetscErrorCode ierr = DMDAGetLocalInfo(*da, &m_grid);
122 throw std::runtime_error(
"Failed to allocate an Element instance");
127 m_germs.resize(Nq * n_chi);
128 m_row.resize(block_size);
129 m_col.resize(block_size);
135 m_block_size(block_size) {
146 m_row.resize(block_size);
147 m_col.resize(block_size);
156 const std::vector<QuadPoint>& points,
157 const std::vector<double>& W) {
162 for (
unsigned int q = 0; q <
m_Nq; q++) {
163 for (
unsigned int k = 0;
k <
n_chi;
k++) {
169 const double J_det =
det(J);
170 for (
unsigned int q = 0; q <
m_Nq; q++) {
176 :
Element(grid, Nq, n_chi, block_size) {
181 :
Element(grid_info, Nq, n_chi, block_size) {
190 result[
k] = floor(x_global(ii, jj) + 0.5);
210 int pism_i = 0, pism_j = 0;
242 PetscErrorCode ierr = MatSetValuesBlockedStencil(J,
246 PISM_CHK(ierr,
"MatSetValuesBlockedStencil");
250 :
Element2(grid, quadrature.weights().size(), q1::n_chi, q1::n_chi) {
252 double dx = grid.dx();
253 double dy = grid.dy();
259 m_normals = {{0.0, -1.0}, {1.0, 0.0}, {0.0, 1.0}, {-1.0, 0.0}};
281 :
Element2(grid_info, quadrature.weights().size(), q1::n_chi, q1::n_chi) {
287 m_normals = {{0.0, -1.0}, {1.0, 0.0}, {0.0, 1.0}, {-1.0, 0.0}};
306 :
Element2(grid, quadrature.weights().size(), p1::n_chi, q1::n_chi) {
308 double dx = grid.dx();
309 double dy = grid.dy();
325 n13 /= n13.magnitude();
330 Vector2d p[] = {{0, 0}, {dx, 0}, {dx, dy}, {0, dy}};
331 std::vector<Vector2d> pts;
338 pts = {p[0], p[1], p[3]};
344 pts = {p[1], p[2], p[0]};
350 pts = {p[2], p[3], p[1]};
357 pts = {p[3], p[0], p[2]};
368 for (
unsigned int k = 0;
k <
n_sides(); ++
k) {
375 J[0][0] = pts[1].u - pts[0].u;
376 J[0][1] = pts[1].v - pts[0].v;
377 J[1][0] = pts[2].u - pts[0].u;
378 J[1][1] = pts[2].v - pts[0].v;
386 :
Element(grid_info, Nq, n_chi, block_size) {
393 :
Element(grid, Nq, n_chi, block_size) {
405 :
Element3(grid_info, quadrature.weights().size(), q13d::n_chi, q13d::n_chi),
410 m_points(quadrature.points()),
411 m_w(quadrature.weights()) {
421 for (
unsigned int q = 0; q <
m_Nq; q++) {
430 :
Element3(grid, quadrature.weights().size(), q13d::n_chi, q13d::n_chi),
433 m_points(quadrature.points()),
434 m_w(quadrature.weights()) {
444 for (
unsigned int q = 0; q <
m_Nq; q++) {
490 for (
unsigned int q = 0; q <
m_Nq; q++) {
500 double J[3][3] = {{
m_dx / 2.0, 0.0, dz.x},
501 { 0.0,
m_dy / 2.0, dz.y},
504 double J_det = J[0][0] * J[1][1] * J[2][2];
506 assert(J_det != 0.0);
508 double J_inv[3][3] = {{1.0 / J[0][0], 0.0, -J[0][2] / (J[0][0] * J[2][2])},
509 {0.0, 1.0 / J[1][1], -J[1][2] / (J[1][1] * J[2][2])},
510 {0.0, 0.0, 1.0 / J[2][2]}};
529 m_points(quadrature.points()),
530 m_w(quadrature.weights()),
531 m_n_chi(q13d::n_chi),
547 for (
unsigned int q = 0; q <
m_Nq; q++) {
555 P = {-1.0, pt.
xi, pt.eta};
558 P = { 1.0, pt.
xi, pt.eta};
561 P = {pt.
xi, -1.0, pt.eta};
564 P = {pt.
xi, 1.0, pt.eta};
567 P = {pt.
xi, pt.eta, -1.0};
570 P = {pt.
xi, pt.eta, 1.0};
585 dz.x +=
chi.dx * z[
n];
586 dz.y +=
chi.dy * z[
n];
587 dz.z +=
chi.dz * z[
n];
597 double sign = 2 * (face % 2) - 1;
614 a = 0.5 *
m_dy * dz.x,
615 b = 0.5 *
m_dx * dz.y,
617 M = std::sqrt(a * a + b * b + c * c);
110 : m_n_chi(n_chi), {
…}
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
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 Germ & chi(unsigned int q, unsigned int k) const
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.
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.