PISM, A Parallel Ice Sheet Model  stable v2.1-1-g6902d5502 committed by Ed Bueler on 2023-12-20 08:38:27 -0800
FEM.cc
Go to the documentation of this file.
1 /* Copyright (C) 2020, 2023 PISM Authors
2  *
3  * This file is part of PISM.
4  *
5  * PISM is free software; you can redistribute it and/or modify it under the
6  * terms of the GNU General Public License as published by the Free Software
7  * Foundation; either version 3 of the License, or (at your option) any later
8  * version.
9  *
10  * PISM is distributed in the hope that it will be useful, but WITHOUT ANY
11  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
13  * details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with PISM; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19 
20 #include "pism/util/fem/FEM.hh"
21 #include "pism/util/node_types.hh"
22 
23 namespace pism {
24 namespace fem {
25 
26 namespace linear {
27 
28 //! Linear basis functions on the interval [-1, -1]
29 Germ chi(unsigned int k, const QuadPoint &pt) {
30  // coordinates of reference element nodes
31  static const double xis[n_chi] = {-1.0, 1.0};
32 
33  assert(k < linear::n_chi);
34 
35  return {0.5 * (1.0 + xis[k] * pt.xi),
36  0.5 * xis[k],
37  0.0, 0.0}; // unused
38 }
39 
40 } // end of namespace linear
41 
42 namespace q0 {
43 /*!
44  * Piecewise-constant shape functions.
45  */
46 Germ chi(unsigned int k, const QuadPoint &pt) {
47  assert(k < q0::n_chi);
48 
49  Germ result;
50 
51  if ((k == 0 and pt.xi <= 0.0 and pt.eta <= 0.0) or
52  (k == 1 and pt.xi > 0.0 and pt.eta <= 0.0) or
53  (k == 2 and pt.xi > 0.0 and pt.eta > 0.0) or
54  (k == 3 and pt.xi <= 0.0 and pt.eta > 0.0)) {
55  result.val = 1.0;
56  } else {
57  result.val = 0.0;
58  }
59 
60  result.dx = 0.0;
61  result.dy = 0.0;
62 
63  return result;
64 }
65 } // end of namespace q0
66 
67 namespace q1 {
68 
69 //! Q1 basis functions on the reference element with nodes (-1,-1), (1,-1), (1,1), (-1,1).
70 Germ chi(unsigned int k, const QuadPoint &pt) {
71  // coordinates of reference element nodes
72  static const double xi[n_chi] = {-1.0, 1.0, 1.0, -1.0};
73  static const double eta[n_chi] = {-1.0, -1.0, 1.0, 1.0};
74 
75  assert(k < q1::n_chi);
76 
77  return {0.25 * (1.0 + xi[k] * pt.xi) * (1.0 + eta[k] * pt.eta),
78  0.25 * xi[k] * (1.0 + eta[k] * pt.eta),
79  0.25 * eta[k] * (1.0 + xi[k] * pt.xi),
80  0.0}; // unused
81 }
82 
83 } // end of namespace q1
84 
85 namespace p1 {
86 
87 //! P1 basis functions on the reference element with nodes (0,0), (1,0), (0,1).
88 Germ chi(unsigned int k, const QuadPoint &pt) {
89  assert(k < q1::n_chi);
90 
91  switch (k) {
92  default:
93  case 0:
94  return {1.0 - pt.xi - pt.eta, -1.0, -1.0, 0.0};
95  case 1:
96  return {pt.xi, 1.0, 0.0, 0.0};
97  case 2:
98  return {pt.eta, 0.0, 1.0, 0.0};
99  }
100 }
101 
102 } // end of namespace p1
103 
105 
106  // number of exterior nodes in this element
107  const int n_exterior_nodes = ((node_type[0] == NODE_EXTERIOR) +
108  (node_type[1] == NODE_EXTERIOR) +
109  (node_type[2] == NODE_EXTERIOR) +
110  (node_type[3] == NODE_EXTERIOR));
111 
112  // an element is a "Q1 interior" if all its nodes are interior or boundary
113  if (n_exterior_nodes == 0) {
114  return ELEMENT_Q;
115  }
116 
117  if (n_exterior_nodes == 1) {
118  // an element is a "P1 interior" if it has exactly 1 exterior node
119 
120  for (unsigned int k = 0; k < q1::n_chi; ++k) {
121  // Consider a Q1 element with one exterior node and three interior (or boundary)
122  // nodes. This is not an interior element by itself, but it contains an embedded P1
123  // element that *is* interior and should contribute. We need to find which of the four
124  // types of embedded P1 elements to use, but P1 elements are numbered using the node
125  // at the right angle of the reference element, not the "missing" node. Here we map
126  // "missing" nodes to "opposite" nodes, i.e. nodes used to choose P1 element types.
127  if (node_type[k] == NODE_EXTERIOR) {
128  return ElementType((k + 2) % 4);
129  }
130  }
131  }
132 
133  return ELEMENT_EXTERIOR;
134 }
135 
136 namespace q13d {
137 
138 Germ chi(unsigned int k, const QuadPoint &p) {
139  /* Coordinated of the nodes of the reference element: */
140  double xis[8] = {-1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0};
141  double etas[8] = {-1.0, -1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0};
142  double zetas[8] = {-1.0, -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, 1.0};
143 
144  return {0.125 * (1.0 + xis[k]*p.xi) * (1.0 + etas[k]*p.eta) * (1.0 + zetas[k]*p.zeta),
145  0.125 * xis[k] * (1.0 + etas[k] * p.eta) * (1.0 + zetas[k] * p.zeta),
146  0.125 * etas[k] * (1.0 + xis[k] * p.xi) * (1.0 + zetas[k] * p.zeta),
147  0.125 * zetas[k] * (1.0 + xis[k] * p.xi) * (1.0 + etas[k] * p.eta)};
148 }
149 
150 } // end of namespace q13d
151 
152 } // end of namespace fem
153 } // end of namespace pism
Germ chi(unsigned int k, const QuadPoint &pt)
Linear basis functions on the interval [-1, -1].
Definition: FEM.cc:29
const int n_chi
Definition: FEM.hh:177
Germ chi(unsigned int k, const QuadPoint &pt)
P1 basis functions on the reference element with nodes (0,0), (1,0), (0,1).
Definition: FEM.cc:88
Germ chi(unsigned int k, const QuadPoint &pt)
Definition: FEM.cc:46
const int n_chi
Definition: FEM.hh:184
Germ chi(unsigned int k, const QuadPoint &p)
Evaluate a Q1 shape function and its derivatives with respect to xi and eta.
Definition: FEM.cc:138
const int n_chi
Definition: FEM.hh:191
Germ chi(unsigned int k, const QuadPoint &pt)
Q1 basis functions on the reference element with nodes (-1,-1), (1,-1), (1,1), (-1,...
Definition: FEM.cc:70
ElementType
Definition: FEM.hh:203
@ ELEMENT_Q
Definition: FEM.hh:203
@ ELEMENT_EXTERIOR
Definition: FEM.hh:205
ElementType element_type(int node_type[q1::n_chi])
Definition: FEM.cc:104
@ NODE_EXTERIOR
Definition: node_types.hh:36
static const double k
Definition: exactTestP.cc:42
double dy
Function derivative with respect to y.
Definition: FEM.hh:157
double val
Function value.
Definition: FEM.hh:153
double dx
Function deriviative with respect to x.
Definition: FEM.hh:155
Struct for gathering the value and derivative of a function at a point.
Definition: FEM.hh:151