libMesh
Loading...
Searching...
No Matches
fe_l2_lagrange.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/dof_map.h"
22#include "libmesh/elem.h"
23#include "libmesh/enum_to_string.h"
24#include "libmesh/fe.h"
25#include "libmesh/fe_interface.h"
26#include "libmesh/fe_macro.h"
27
28namespace libMesh
29{
30
31// ------------------------------------------------------------
32// Lagrange-specific implementations
33
34
35// Anonymous namespace for local helper functions
36namespace {
37unsigned int l2_lagrange_n_dofs(const ElemType t, const Order o)
38{
39 switch (o)
40 {
41
42 // linear Lagrange shape functions
43 case FIRST:
44 {
45 switch (t)
46 {
47 case NODEELEM:
48 return 1;
49
50 case EDGE2:
51 case EDGE3:
52 case EDGE4:
53 return 2;
54
55 case TRI3:
56 case TRISHELL3:
57 case TRI6:
58 case TRI7:
59 return 3;
60
61 case QUAD4:
62 case QUADSHELL4:
63 case QUAD8:
64 case QUADSHELL8:
65 case QUAD9:
66 case QUADSHELL9:
67 return 4;
68
69 case TET4:
70 case TET10:
71 case TET14:
72 return 4;
73
74 case HEX8:
75 case HEX20:
76 case HEX27:
77 return 8;
78
79 case PRISM6:
80 case PRISM15:
81 case PRISM18:
82 case PRISM20:
83 case PRISM21:
84 return 6;
85
86 case PYRAMID5:
87 case PYRAMID13:
88 case PYRAMID14:
89 case PYRAMID18:
90 return 5;
91
92 case INVALID_ELEM:
93 return 0;
94
95 default:
96 libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
97 }
98 }
99
100
101 // quadratic Lagrange shape functions
102 case SECOND:
103 {
104 switch (t)
105 {
106 case NODEELEM:
107 return 1;
108
109 case EDGE2:
110 case EDGE3:
111 return 3;
112
113 case TRI3:
114 case TRI6:
115 case TRI7:
116 return 6;
117
118 case QUAD8:
119 case QUADSHELL8:
120 return 8;
121
122 case QUAD4:
123 case QUAD9:
124 case QUADSHELL9:
125 return 9;
126
127 case TET4:
128 case TET10:
129 case TET14:
130 return 10;
131
132 case HEX20:
133 return 20;
134
135 case HEX8:
136 case HEX27:
137 return 27;
138
139 case PRISM15:
140 return 15;
141
142 case PRISM6:
143 case PRISM18:
144 case PRISM20:
145 case PRISM21:
146 return 18;
147
148 case PYRAMID13:
149 return 13;
150
151 case PYRAMID5:
152 case PYRAMID14:
153 case PYRAMID18:
154 return 14;
155
156 case INVALID_ELEM:
157 return 0;
158
159 default:
160 libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
161 }
162 }
163
164 case THIRD:
165 {
166 switch (t)
167 {
168 case NODEELEM:
169 return 1;
170
171 case EDGE2:
172 case EDGE3:
173 case EDGE4:
174 return 4;
175
176 case TRI7:
177 return 7;
178
179 case TET14:
180 return 14;
181
182 case PRISM20:
183 return 20;
184
185 case PRISM21:
186 return 21;
187
188 case PYRAMID18:
189 return 18;
190
191 case INVALID_ELEM:
192 return 0;
193
194 default:
195 libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
196 }
197 }
198
199 default:
200 libmesh_error_msg("ERROR: Invalid Order " << Utility::enum_to_string(o) << " selected for L2_LAGRANGE FE family!");
201 }
202}
203
204
205
206unsigned int l2_lagrange_n_dofs(const Elem * e, const Order o)
207{
209 return l2_lagrange_n_dofs(e->type(), o);
210}
211
212} // anonymous namespace
213
214
215// Instantiate (side_) nodal_soln() function for every dimension
218
219
220// Do full-specialization for every dimension, instead
221// of explicit instantiation at the end of this function.
222// This could be macro-ified.
223template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
224template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
225template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
226template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
227
228template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
229template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
230template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
231template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
232
233// L2 Lagrange elements have all dofs on elements (hence none on nodes)
234template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
235template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
236template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
237template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
238
239template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
240template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
241template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
242template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
243
244// L2 Lagrange elements have all dofs on elements
245template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
246template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
247template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
248template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
249
250template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
251template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
252template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
253template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
254
255// L2 Lagrange FEMs are DISCONTINUOUS
260
261// Lagrange FEMs are not hierarchic
262template <> bool FE<0,L2_LAGRANGE>::is_hierarchic() const { return false; }
263template <> bool FE<1,L2_LAGRANGE>::is_hierarchic() const { return false; }
264template <> bool FE<2,L2_LAGRANGE>::is_hierarchic() const { return false; }
265template <> bool FE<3,L2_LAGRANGE>::is_hierarchic() const { return false; }
266
267// Lagrange FEM shapes do not need reinit (is this always true?)
268template <> bool FE<0,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
269template <> bool FE<1,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
270template <> bool FE<2,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
271template <> bool FE<3,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
272
273// We don't need any constraints for this DISCONTINUOUS basis, hence these
274// are NOOPs
275#ifdef LIBMESH_ENABLE_AMR
276template <>
278 DofMap &,
279 const unsigned int,
280 const Elem *)
281{ }
282
283template <>
285 DofMap &,
286 const unsigned int,
287 const Elem *)
288{ }
289#endif // LIBMESH_ENABLE_AMR
290
291} // namespace libMesh
The constraint matrix storage format.
Definition dof_map.h:112
This class handles the numbering of degrees of freedom on a mesh.
Definition dof_map.h:181
This is the base class from which all geometric element types are derived.
Definition elem.h:96
virtual bool is_hierarchic() const override
static unsigned int n_dofs_per_elem(const ElemType t, const Order o)
virtual FEContinuity get_continuity() const override
static void compute_constraints(DofConstraints &constraints, DofMap &dof_map, const unsigned int variable_number, const Elem *elem)
Computes the constraint matrix contributions (for non-conforming adapted meshes) corresponding to var...
static unsigned int n_dofs(const ElemType t, const Order o)
static unsigned int n_dofs_at_node(const ElemType t, const Order o, const unsigned int n)
virtual bool shapes_need_reinit() const override
std::string enum_to_string(const T e)
The libMesh namespace provides an interface to certain functionality in the library.
LIBMESH_FE_NODAL_SOLN(BERNSTEIN, bernstein_nodal_soln)
ElemType
Defines an enum for geometric element types.
libmesh_assert(ctx)
void lagrange_nodal_soln(const Elem *elem, const Order order, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln, bool add_p_level=true)
Helper functions for Lagrange-based basis functions.
Definition fe_lagrange.C:43
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)