libMesh
Loading...
Searching...
No Matches
quadrature_nodal_2D.C
Go to the documentation of this file.
1// The libMesh Finite Element Library.
2// Copyright (C) 2002-2026 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
28namespace 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
The C0Polygon is an element in 2D with an arbitrary (but fixed) number of first-order (EDGE2) sides.
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition point.h:40
virtual Point master_point(const unsigned int i) const override
virtual unsigned int n_nodes() const override
virtual unsigned int n_sides() const override final
std::vector< Point > _points
The locations of the quadrature points in reference element space.
Definition quadrature.h:409
ElemType _type
The type of element for which the current values have been computed.
Definition quadrature.h:391
const std::vector< Point > & get_points() const
Definition quadrature.h:156
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
std::vector< Real > _weights
The quadrature weights.
Definition quadrature.h:415
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
Order _order
The polynomial order which the quadrature rule is capable of integrating exactly.
Definition quadrature.h:385
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.
This class implements trapezoidal quadrature.
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
libmesh_assert(ctx)
const Real pi
.
Definition libmesh.h:292
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
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:176