libMesh
quadrature_nodal_2D.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 
19 
20 // Local includes
21 #include "libmesh/quadrature_nodal.h"
22 
23 #include "libmesh/enum_to_string.h"
24 #include "libmesh/face_c0polygon.h"
25 #include "libmesh/quadrature_trap.h"
26 #include "libmesh/quadrature_simpson.h"
27 
28 namespace libMesh
29 {
30 
32 {
33 #if LIBMESH_DIM > 1
34 
35  switch (_type)
36  {
37 
38  case QUAD4:
39  case QUADSHELL4:
40  case TRI3:
41  case TRISHELL3:
42  {
43  QTrap rule(/*dim=*/2, /*ignored*/_order);
44  rule.init(*this);
45  _points.swap (rule.get_points());
46  _weights.swap(rule.get_weights());
47  return;
48  }
49 
50  case QUAD8:
51  case QUADSHELL8:
52  {
53  // A rule with 8 points which is exact for linears, and
54  // naturally produces a lumped approximation to the mass
55  // matrix. The quadrature points are numbered the same way as
56  // the reference element nodes.
57  _points =
58  {
59  Point(-1,-1), Point(+1,-1), Point(+1,+1), Point(-1,+1),
60  Point(0.,-1), Point(+1,0.), Point(0.,+1), Point(-1,0.)
61  };
62 
63  // The weights for the Quad8 nodal quadrature rule are
64  // obtained from the following specific steps. Other
65  // "serendipity" type rules are obtained similarly.
66  //
67  // 1.) Due to the symmetry of the bi-unit square domain, we
68  // first note that there are only two "classes" of node in the
69  // Quad8: vertices (with associated weight wv) and edges (with
70  // associated weight we).
71  //
72  // 2.) In order for such a nodal quadrature rule to be exact
73  // for constants, the weights must sum to the area of the
74  // reference element, and therefore we must have:
75  // 4*wv + 4*we = 4 --> wv + we = 1
76  //
77  // 3.) Due to symmetry (once again), such a rule is then
78  // automatically exact for the linear polynomials "x" and "y",
79  // regardless of the values of wv and we.
80  //
81  // 4.) We therefore still have two unknowns and one equation.
82  // Attempting to additionally make the nodal quadrature rule
83  // exact for the quadratic polynomials "x^2" and "y^2" leads
84  // to a rule with negative weights, namely:
85  // wv = -1/3
86  // we = 4/3
87  // Note: these are the same values one obtains by integrating
88  // the corresponding Quad8 Lagrange basis functions over the
89  // reference element.
90  //
91  // Since the weights appear on the diagonal of the nodal
92  // quadrature rule's approximation to the mass matrix, rules
93  // with negative weights yield an indefinite mass matrix,
94  // i.e. one with both positive and negative eigenvalues. Rules
95  // with negative weights can also produce a negative integral
96  // approximation to a strictly positive integrand, which may
97  // be unacceptable in some situations.
98  //
99  // 5.) Requiring all positive weights therefore restricts the
100  // nodal quadrature rule to only be exact for linears. But
101  // there is still one free parameter remaining, and thus we
102  // need some other criterion in order to complete the
103  // description of the rule.
104  //
105  // Here, we have decided to choose the quadrature weights in
106  // such a way that the resulting nodal quadrature mass matrix
107  // approximation is "proportional" to the true mass matrix's
108  // diagonal entries for the reference element. We therefore
109  // pose the following constrained optimization problem:
110  //
111  // { min_{wv, we} |diag(M) - C*diag(W)|^2
112  // (O) {
113  // { subject to wv + we = 1
114  //
115  // where:
116  // * M is the true mass matrix
117  // * W is the nodal quadrature approximation to the mass
118  // matrix. In this particular case:
119  // diag(W) = [wv,wv,wv,wv,we,we,we,we]
120  // * C = tr(M) / vol(E) is the ratio between the trace of the
121  // true mass matrix and the volume of the reference
122  // element. For all Lagrange finite elements, we have C<1.
123  //
124  // 6.) The optimization problem (O) is solved directly by
125  // substituting the algebraic constraint into the functional
126  // which is to be minimized, then setting the derivative with
127  // respect to the remaining parameter equal to zero and
128  // solving. In the Quad8 and Hex20 cases, there is only one
129  // free parameter, while in the Prism15 case there are two
130  // free parameters, so a 2x2 system of linear equations must
131  // be solved.
132  Real wv = Real(12) / 79;
133  Real we = Real(67) / 79;
134 
135  _weights = {wv, wv, wv, wv, we, we, we, we};
136 
137  return;
138  }
139 
140  case QUAD9:
141  case QUADSHELL9:
142  case TRI6:
143  {
144  QSimpson rule(/*dim=*/2, /*ignored*/_order);
145  rule.init(*this);
146  _points.swap (rule.get_points());
147  _weights.swap(rule.get_weights());
148  return;
149  }
150 
151  case TRI7:
152  {
153  // We can't exactly represent cubics with only seven nodes,
154  // but with w_i = integral(phi_i) for Lagrange shape functions
155  // phi_i, we not only get exact integrals of every Lagrange
156  // shape function, including the cubic bubble, we also get
157  // exact integrals of the rest of P^3 too.
158  _points =
159  {
160  Point(0.,0.), Point(+1,0.), Point(0.,+1), Point(.5,0.),
161  Point(.5,.5), Point(0.,.5), Point(1/Real(3),1/Real(3))
162  };
163 
164  Real wv = Real(1)/40;
165  Real we = Real(1)/15;
166  _weights = {wv, wv, wv, we, we, we, Real(9)/40};
167  return;
168  }
169 
170  //---------------------------------------------
171  // Arbitrary polygon quadrature rules
172  case C0POLYGON:
173  {
174  // C0Polygon requires the newer Quadrature API
175  if (!_elem)
176  libmesh_error();
177 
179 
180  const C0Polygon & poly = *cast_ptr<const C0Polygon *>(_elem);
181 
182  const unsigned int ns = poly.n_sides();
183  const Real pi_over_ns = libMesh::pi / ns;
184  const Real master_poly_area = ns * 0.25 / tan(pi_over_ns);
185 
186  const unsigned int nn = poly.n_nodes();
187  const Real weight = master_poly_area / nn;
188  _weights.resize(nn, weight);
189 
190  _points.resize(poly.n_nodes());
191  for (auto n : make_range(nn))
192  _points[n] = poly.master_point(n);
193 
194  return;
195  }
196 
197  default:
198  libmesh_error_msg("Element type not supported!:" << Utility::enum_to_string(_type));
199  }
200 #endif
201 }
202 
203 } // namespace libMesh
virtual void init_2D() override
Initializes the 2D quadrature rule by filling the points and weights vectors with the appropriate val...
This class implements Simpson quadrature.
ElemType _type
The type of element for which the current values have been computed.
Definition: quadrature.h:391
const std::vector< Real > & get_weights() const
Definition: quadrature.h:168
const Elem * _elem
The element for which the current values were computed, or nullptr if values were computed without a ...
Definition: quadrature.h:397
The libMesh namespace provides an interface to certain functionality in the library.
std::vector< Point > _points
The locations of the quadrature points in reference element space.
Definition: quadrature.h:409
std::vector< Real > _weights
The quadrature weights.
Definition: quadrature.h:415
dof_id_type weight(const MeshBase &mesh, const processor_id_type pid)
Definition: mesh_tools.C:437
libmesh_assert(ctx)
std::string enum_to_string(const T e)
Order _order
The polynomial order which the quadrature rule is capable of integrating exactly. ...
Definition: quadrature.h:385
The C0Polygon is an element in 2D with an arbitrary (but fixed) number of first-order (EDGE2) sides...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const std::vector< Point > & get_points() const
Definition: quadrature.h:156
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
virtual void init(const Elem &e, unsigned int p_level=invalid_uint)
Initializes the data structures for a quadrature rule for the element e.
Definition: quadrature.C:65
virtual unsigned int n_sides() const override final
Definition: face_polygon.h:84
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
This class implements trapezoidal quadrature.
const Real pi
.
Definition: libmesh.h:299