libMesh
fe_l2_lagrange.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/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 
28 namespace libMesh
29 {
30 
31 // ------------------------------------------------------------
32 // Lagrange-specific implementations
33 
34 
35 // Anonymous namespace for local helper functions
36 namespace {
37 unsigned 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 
206 unsigned int l2_lagrange_n_dofs(const Elem * e, const Order o)
207 {
208  libmesh_assert(e);
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.
223 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
224 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
225 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
226 template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
227 
228 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
229 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
230 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs(const Elem * e, const Order o) { return l2_lagrange_n_dofs(e, o); }
231 template <> 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)
234 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
235 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
236 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
237 template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
238 
239 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
240 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
241 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_at_node(const Elem &, const Order, const unsigned int) { return 0; }
242 template <> 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
245 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
246 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
247 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
248 template <> unsigned int FE<3,L2_LAGRANGE>::n_dofs_per_elem(const ElemType t, const Order o) { return l2_lagrange_n_dofs(t, o); }
249 
250 template <> unsigned int FE<0,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
251 template <> unsigned int FE<1,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
252 template <> unsigned int FE<2,L2_LAGRANGE>::n_dofs_per_elem(const Elem & e, const Order o) { return l2_lagrange_n_dofs(&e, o); }
253 template <> 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
262 template <> bool FE<0,L2_LAGRANGE>::is_hierarchic() const { return false; }
263 template <> bool FE<1,L2_LAGRANGE>::is_hierarchic() const { return false; }
264 template <> bool FE<2,L2_LAGRANGE>::is_hierarchic() const { return false; }
265 template <> bool FE<3,L2_LAGRANGE>::is_hierarchic() const { return false; }
266 
267 // Lagrange FEM shapes do not need reinit (is this always true?)
268 template <> bool FE<0,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
269 template <> bool FE<1,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
270 template <> bool FE<2,L2_LAGRANGE>::shapes_need_reinit() const { return false; }
271 template <> 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
276 template <>
278  DofMap &,
279  const unsigned int,
280  const Elem *)
281 { }
282 
283 template <>
285  DofMap &,
286  const unsigned int,
287  const Elem *)
288 { }
289 #endif // LIBMESH_ENABLE_AMR
290 
291 } // namespace libMesh
static unsigned int n_dofs(const ElemType t, const Order o)
ElemType
Defines an enum for geometric element types.
Order
defines an enum for polynomial orders.
Definition: enum_order.h:40
This is the base class from which all geometric element types are derived.
Definition: elem.h:94
static unsigned int n_dofs_at_node(const ElemType t, const Order o, const unsigned int n)
virtual bool shapes_need_reinit() const override
The libMesh namespace provides an interface to certain functionality in the library.
LIBMESH_FE_NODAL_SOLN(LIBMESH_FE_SIDE_NODAL_SOLN() LIBMESH_DEFAULT_NDOFS(BERNSTEIN) template<> FEContinuity FE< 0 BERNSTEIN, bernstein_nodal_soln)
Definition: fe_bernstein.C:415
virtual bool is_hierarchic() const override
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:179
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)
libmesh_assert(ctx)
static unsigned int n_dofs_per_elem(const ElemType t, const Order o)
virtual FEContinuity get_continuity() const override
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
std::string enum_to_string(const T e)
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...
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
The constraint matrix storage format.
Definition: dof_map.h:108