libMesh
fe_monomial.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2024 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/fe.h"
22 #include "libmesh/elem.h"
23 #include "libmesh/enum_to_string.h"
24 #include "libmesh/fe_interface.h"
25 #include "libmesh/fe_macro.h"
26 
27 namespace libMesh
28 {
29 
30 unsigned int monomial_n_dofs(const ElemType t, const Order o)
31 {
32  switch (o)
33  {
34 
35  // constant shape functions
36  // no matter what shape there is only one DOF.
37  case CONSTANT:
38  return (t != INVALID_ELEM) ? 1 : 0;
39 
40 
41  // Discontinuous linear shape functions
42  // expressed in the monomials.
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  case QUAD4:
60  case QUADSHELL4:
61  case QUAD8:
62  case QUADSHELL8:
63  case QUAD9:
64  return 3;
65 
66  case TET4:
67  case TET10:
68  case TET14:
69  case HEX8:
70  case HEX20:
71  case HEX27:
72  case PRISM6:
73  case PRISM15:
74  case PRISM18:
75  case PRISM20:
76  case PRISM21:
77  case PYRAMID5:
78  case PYRAMID13:
79  case PYRAMID14:
80  case PYRAMID18:
81  return 4;
82 
83  case INVALID_ELEM:
84  return 0;
85 
86  default:
87  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
88  }
89  }
90 
91 
92  // Discontinuous quadratic shape functions
93  // expressed in the monomials.
94  case SECOND:
95  {
96  switch (t)
97  {
98  case NODEELEM:
99  return 1;
100 
101  case EDGE2:
102  case EDGE3:
103  case EDGE4:
104  return 3;
105 
106  case TRI3:
107  case TRISHELL3:
108  case TRI6:
109  case TRI7:
110  case QUAD4:
111  case QUADSHELL4:
112  case QUAD8:
113  case QUADSHELL8:
114  case QUAD9:
115  return 6;
116 
117  case TET4:
118  case TET10:
119  case TET14:
120  case HEX8:
121  case HEX20:
122  case HEX27:
123  case PRISM6:
124  case PRISM15:
125  case PRISM18:
126  case PRISM20:
127  case PRISM21:
128  case PYRAMID5:
129  case PYRAMID13:
130  case PYRAMID14:
131  case PYRAMID18:
132  return 10;
133 
134  case INVALID_ELEM:
135  return 0;
136 
137  default:
138  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
139  }
140  }
141 
142 
143  // Discontinuous cubic shape functions
144  // expressed in the monomials.
145  case THIRD:
146  {
147  switch (t)
148  {
149  case NODEELEM:
150  return 1;
151 
152  case EDGE2:
153  case EDGE3:
154  case EDGE4:
155  return 4;
156 
157  case TRI3:
158  case TRISHELL3:
159  case TRI6:
160  case TRI7:
161  case QUAD4:
162  case QUADSHELL4:
163  case QUAD8:
164  case QUADSHELL8:
165  case QUAD9:
166  return 10;
167 
168  case TET4:
169  case TET10:
170  case TET14:
171  case HEX8:
172  case HEX20:
173  case HEX27:
174  case PRISM6:
175  case PRISM15:
176  case PRISM18:
177  case PRISM20:
178  case PRISM21:
179  case PYRAMID5:
180  case PYRAMID13:
181  case PYRAMID14:
182  case PYRAMID18:
183  return 20;
184 
185  case INVALID_ELEM:
186  return 0;
187 
188  default:
189  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
190  }
191  }
192 
193 
194  // Discontinuous quartic shape functions
195  // expressed in the monomials.
196  case FOURTH:
197  {
198  switch (t)
199  {
200  case NODEELEM:
201  return 1;
202 
203  case EDGE2:
204  case EDGE3:
205  return 5;
206 
207  case TRI3:
208  case TRISHELL3:
209  case TRI6:
210  case TRI7:
211  case QUAD4:
212  case QUADSHELL4:
213  case QUAD8:
214  case QUADSHELL8:
215  case QUAD9:
216  return 15;
217 
218  case TET4:
219  case TET10:
220  case TET14:
221  case HEX8:
222  case HEX20:
223  case HEX27:
224  case PRISM6:
225  case PRISM15:
226  case PRISM18:
227  case PRISM20:
228  case PRISM21:
229  case PYRAMID5:
230  case PYRAMID13:
231  case PYRAMID14:
232  return 35;
233 
234  case INVALID_ELEM:
235  return 0;
236 
237  default:
238  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
239  }
240  }
241 
242 
243  default:
244  {
245  const unsigned int order = static_cast<unsigned int>(o);
246  switch (t)
247  {
248  case NODEELEM:
249  return 1;
250 
251  case EDGE2:
252  case EDGE3:
253  return (order+1);
254 
255  case TRI3:
256  case TRISHELL3:
257  case TRI6:
258  case TRI7:
259  case QUAD4:
260  case QUADSHELL4:
261  case QUAD8:
262  case QUADSHELL8:
263  case QUAD9:
264  return (order+1)*(order+2)/2;
265 
266  case TET4:
267  case TET10:
268  case TET14:
269  case HEX8:
270  case HEX20:
271  case HEX27:
272  case PRISM6:
273  case PRISM15:
274  case PRISM18:
275  case PRISM20:
276  case PRISM21:
277  case PYRAMID5:
278  case PYRAMID13:
279  case PYRAMID14:
280  return (order+1)*(order+2)*(order+3)/6;
281 
282  case INVALID_ELEM:
283  return 0;
284 
285  default:
286  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
287  }
288  }
289  }
290 } // monomial_n_dofs()
291 
292 
293 // Anonymous namespace for local helper functions
294 namespace {
295 
296 void monomial_nodal_soln(const Elem * elem,
297  const Order order,
298  const std::vector<Number> & elem_soln,
299  std::vector<Number> & nodal_soln,
300  const bool add_p_level)
301 {
302  const unsigned int n_nodes = elem->n_nodes();
303 
304  const ElemType elem_type = elem->type();
305 
306  nodal_soln.resize(n_nodes);
307 
308  const Order totalorder = static_cast<Order>(order+add_p_level*elem->p_level());
309 
310  switch (totalorder)
311  {
312  // Constant shape functions
313  case CONSTANT:
314  {
315  libmesh_assert_equal_to (elem_soln.size(), 1);
316 
317  const Number val = elem_soln[0];
318 
319  for (unsigned int n=0; n<n_nodes; n++)
320  nodal_soln[n] = val;
321 
322  return;
323  }
324 
325 
326  // For other orders, do interpolation at the nodes
327  // explicitly.
328  default:
329  {
330  // FEType object to be passed to various FEInterface functions below.
331  FEType fe_type(order, MONOMIAL);
332 
333  const unsigned int n_sf =
334  FEInterface::n_shape_functions(fe_type, elem);
335 
336  std::vector<Point> refspace_nodes;
337  FEBase::get_refspace_nodes(elem_type,refspace_nodes);
338  libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
339 
340  for (unsigned int n=0; n<n_nodes; n++)
341  {
342  libmesh_assert_equal_to (elem_soln.size(), n_sf);
343 
344  // Zero before summation
345  nodal_soln[n] = 0;
346 
347  // u_i = Sum (alpha_i phi_i)
348  for (unsigned int i=0; i<n_sf; i++)
349  nodal_soln[n] += elem_soln[i] *
350  FEInterface::shape(fe_type, elem, i, refspace_nodes[n]);
351  }
352 
353  return;
354  } // default
355  } // switch
356 } // monomial_nodal_soln()
357 
358 
359 
360 
361 } // anonymous namespace
362 
363 
364 // Instantiate (side_) nodal_soln() function for every dimension
365 LIBMESH_FE_NODAL_SOLN(MONOMIAL, monomial_nodal_soln)
367 
368 
369 // Full specialization of n_dofs() function for every dimension
370 template <> unsigned int FE<0,MONOMIAL>::n_dofs(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
371 template <> unsigned int FE<1,MONOMIAL>::n_dofs(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
372 template <> unsigned int FE<2,MONOMIAL>::n_dofs(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
373 template <> unsigned int FE<3,MONOMIAL>::n_dofs(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
374 
375 // Full specialization of n_dofs_at_node() function for every dimension.
376 // Monomials have no dofs at nodes, only element dofs.
377 template <> unsigned int FE<0,MONOMIAL>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
378 template <> unsigned int FE<1,MONOMIAL>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
379 template <> unsigned int FE<2,MONOMIAL>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
380 template <> unsigned int FE<3,MONOMIAL>::n_dofs_at_node(const ElemType, const Order, const unsigned int) { return 0; }
381 
382 // Full specialization of n_dofs_per_elem() function for every dimension.
383 template <> unsigned int FE<0,MONOMIAL>::n_dofs_per_elem(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
384 template <> unsigned int FE<1,MONOMIAL>::n_dofs_per_elem(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
385 template <> unsigned int FE<2,MONOMIAL>::n_dofs_per_elem(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
386 template <> unsigned int FE<3,MONOMIAL>::n_dofs_per_elem(const ElemType t, const Order o) { return monomial_n_dofs(t, o); }
387 
388 
389 // Full specialization of get_continuity() function for every dimension.
394 
395 // Full specialization of is_hierarchic() function for every dimension.
396 // The monomials are hierarchic!
397 template <> bool FE<0,MONOMIAL>::is_hierarchic() const { return true; }
398 template <> bool FE<1,MONOMIAL>::is_hierarchic() const { return true; }
399 template <> bool FE<2,MONOMIAL>::is_hierarchic() const { return true; }
400 template <> bool FE<3,MONOMIAL>::is_hierarchic() const { return true; }
401 
402 #ifdef LIBMESH_ENABLE_AMR
403 
404 // Full specialization of compute_constraints() function for 2D and
405 // 3D only. There are no constraints for discontinuous elements, so
406 // we do nothing.
407 template <> void FE<2,MONOMIAL>::compute_constraints (DofConstraints &, DofMap &, const unsigned int, const Elem *) {}
408 template <> void FE<3,MONOMIAL>::compute_constraints (DofConstraints &, DofMap &, const unsigned int, const Elem *) {}
409 
410 #endif // #ifdef LIBMESH_ENABLE_AMR
411 
412 // Full specialization of shapes_need_reinit() function for every dimension.
413 template <> bool FE<0,MONOMIAL>::shapes_need_reinit() const { return false; }
414 template <> bool FE<1,MONOMIAL>::shapes_need_reinit() const { return false; }
415 template <> bool FE<2,MONOMIAL>::shapes_need_reinit() const { return false; }
416 template <> bool FE<3,MONOMIAL>::shapes_need_reinit() const { return false; }
417 
418 } // 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.
virtual bool is_hierarchic() const override
This class handles the numbering of degrees of freedom on a mesh.
Definition: dof_map.h:169
LIBMESH_FE_NODAL_SOLN(BERNSTEIN, bernstein_nodal_soln)
Definition: fe_bernstein.C:397
LIBMESH_FE_SIDE_NODAL_SOLN(HIERARCHIC_VEC)
const dof_id_type n_nodes
Definition: tecplot_io.C:67
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:515
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
static void get_refspace_nodes(const ElemType t, std::vector< Point > &nodes)
Definition: fe_abstract.C:373
unsigned int monomial_n_dofs(const ElemType t, const Order o)
Helper functions for Discontinuous-Pn type basis functions.
Definition: fe_monomial.C:30
static unsigned int n_dofs_per_elem(const ElemType t, const Order o)
virtual FEContinuity get_continuity() const override
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:98