fe_hermite.C
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2018 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/elem.h"
22 #include "libmesh/fe.h"
23 #include "libmesh/fe_interface.h"
24 #include "libmesh/string_to_enum.h"
25 
26 namespace libMesh
27 {
28 
29 // ------------------------------------------------------------
30 // Hermite-specific implementations
31 
32 // Anonymous namespace for local helper functions
33 namespace {
34 
35 void hermite_nodal_soln(const Elem * elem,
36  const Order order,
37  const std::vector<Number> & elem_soln,
38  std::vector<Number> & nodal_soln,
39  unsigned Dim)
40 {
41  const unsigned int n_nodes = elem->n_nodes();
42 
43  const ElemType elem_type = elem->type();
44 
45  nodal_soln.resize(n_nodes);
46 
47  const Order totalorder = static_cast<Order>(order + elem->p_level());
48 
49  // FEType object to be passed to various FEInterface functions below.
50  FEType fe_type(totalorder, HERMITE);
51 
52  const unsigned int n_sf =
53  // FE<Dim,T>::n_shape_functions(elem_type, totalorder);
54  FEInterface::n_shape_functions(Dim, fe_type, elem_type);
55 
56  std::vector<Point> refspace_nodes;
57  FEBase::get_refspace_nodes(elem_type,refspace_nodes);
58  libmesh_assert_equal_to (refspace_nodes.size(), n_nodes);
59 
60  for (unsigned int n=0; n<n_nodes; n++)
61  {
62  libmesh_assert_equal_to (elem_soln.size(), n_sf);
63 
64  // Zero before summation
65  nodal_soln[n] = 0;
66 
67  // u_i = Sum (alpha_i phi_i)
68  for (unsigned int i=0; i<n_sf; i++)
69  nodal_soln[n] += elem_soln[i] *
70  // FE<Dim,T>::shape(elem, order, i, mapped_point);
71  FEInterface::shape(Dim, fe_type, elem, i, refspace_nodes[n]);
72  }
73 } // hermite_nodal_soln()
74 
75 
76 
77 unsigned int hermite_n_dofs(const ElemType t, const Order o)
78 {
79 #ifdef DEBUG
80  if (o < 3)
81  libmesh_error_msg("Error: Hermite elements require order>=3, but you asked for order=" << o);
82 #endif
83 
84  // Piecewise (bi/tri)cubic C1 Hermite splines
85  switch (t)
86  {
87  case NODEELEM:
88  return 1;
89  case EDGE2:
90  libmesh_assert_less (o, 4);
91  libmesh_fallthrough();
92  case EDGE3:
93  return (o+1);
94 
95  case QUAD4:
96  case QUADSHELL4:
97  case QUAD8:
98  case QUADSHELL8:
99  libmesh_assert_less (o, 4);
100  libmesh_fallthrough();
101  case QUAD9:
102  return ((o+1)*(o+1));
103 
104  case HEX8:
105  case HEX20:
106  libmesh_assert_less (o, 4);
107  libmesh_fallthrough();
108  case HEX27:
109  return ((o+1)*(o+1)*(o+1));
110 
111  case INVALID_ELEM:
112  return 0;
113 
114  default:
115  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
116  }
117 } // hermite_n_dofs()
118 
119 
120 
121 
122 unsigned int hermite_n_dofs_at_node(const ElemType t,
123  const Order o,
124  const unsigned int n)
125 {
126  libmesh_assert_greater (o, 2);
127  // Piecewise (bi/tri)cubic C1 Hermite splines
128  switch (t)
129  {
130  case NODEELEM:
131  return 1;
132  case EDGE2:
133  case EDGE3:
134  {
135  switch (n)
136  {
137  case 0:
138  case 1:
139  return 2;
140  case 2:
141  // Interior DoFs are carried on Elems
142  // return (o-3);
143  return 0;
144 
145  default:
146  libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for EDGE2/3!");
147  }
148  }
149 
150  case QUAD4:
151  case QUADSHELL4:
152  libmesh_assert_less (o, 4);
153  libmesh_fallthrough();
154  case QUAD8:
155  case QUADSHELL8:
156  case QUAD9:
157  {
158  switch (n)
159  {
160  // Vertices
161  case 0:
162  case 1:
163  case 2:
164  case 3:
165  return 4;
166  // Edges
167  case 4:
168  case 5:
169  case 6:
170  case 7:
171  return (2*(o-3));
172  case 8:
173  // Interior DoFs are carried on Elems
174  // return ((o-3)*(o-3));
175  return 0;
176 
177  default:
178  libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for QUAD4/8/9!");
179  }
180  }
181 
182  case HEX8:
183  case HEX20:
184  libmesh_assert_less (o, 4);
185  libmesh_fallthrough();
186  case HEX27:
187  {
188  switch (n)
189  {
190  // Vertices
191  case 0:
192  case 1:
193  case 2:
194  case 3:
195  case 4:
196  case 5:
197  case 6:
198  case 7:
199  return 8;
200  // Edges
201  case 8:
202  case 9:
203  case 10:
204  case 11:
205  case 12:
206  case 13:
207  case 14:
208  case 15:
209  case 16:
210  case 17:
211  case 18:
212  case 19:
213  return (4*(o-3));
214  // Faces
215  case 20:
216  case 21:
217  case 22:
218  case 23:
219  case 24:
220  case 25:
221  return (2*(o-3)*(o-3));
222  case 26:
223  // Interior DoFs are carried on Elems
224  // return ((o-3)*(o-3)*(o-3));
225  return 0;
226 
227  default:
228  libmesh_error_msg("ERROR: Invalid node ID " << n << " selected for HEX8/20/27!");
229  }
230  }
231 
232  case INVALID_ELEM:
233  return 0;
234 
235  default:
236  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
237  }
238 } // hermite_n_dofs_at_node()
239 
240 
241 
242 unsigned int hermite_n_dofs_per_elem(const ElemType t,
243  const Order o)
244 {
245  libmesh_assert_greater (o, 2);
246 
247  switch (t)
248  {
249  case NODEELEM:
250  return 0;
251  case EDGE2:
252  case EDGE3:
253  return (o-3);
254  case QUAD4:
255  case QUADSHELL4:
256  libmesh_assert_less (o, 4);
257  libmesh_fallthrough();
258  case QUAD8:
259  case QUADSHELL8:
260  case QUAD9:
261  return ((o-3)*(o-3));
262  case HEX8:
263  libmesh_assert_less (o, 4);
264  libmesh_fallthrough();
265  case HEX20:
266  case HEX27:
267  return ((o-3)*(o-3)*(o-3));
268 
269  case INVALID_ELEM:
270  return 0;
271 
272  default:
273  libmesh_error_msg("ERROR: Bad ElemType = " << Utility::enum_to_string(t) << " for " << Utility::enum_to_string(o) << " order approximation!");
274  }
275 } // hermite_n_dofs_per_elem()
276 
277 
278 } // anonymous namespace
279 
280 
281 
282 
283  // Do full-specialization of nodal_soln() function for every
284  // dimension, instead of explicit instantiation at the end of this
285  // file.
286  // This could be macro-ified so that it fits on one line...
287 template <>
288 void FE<0,HERMITE>::nodal_soln(const Elem * elem,
289  const Order order,
290  const std::vector<Number> & elem_soln,
291  std::vector<Number> & nodal_soln)
292 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/0); }
293 
294 template <>
295 void FE<1,HERMITE>::nodal_soln(const Elem * elem,
296  const Order order,
297  const std::vector<Number> & elem_soln,
298  std::vector<Number> & nodal_soln)
299 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/1); }
300 
301 template <>
302 void FE<2,HERMITE>::nodal_soln(const Elem * elem,
303  const Order order,
304  const std::vector<Number> & elem_soln,
305  std::vector<Number> & nodal_soln)
306 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/2); }
307 
308 template <>
309 void FE<3,HERMITE>::nodal_soln(const Elem * elem,
310  const Order order,
311  const std::vector<Number> & elem_soln,
312  std::vector<Number> & nodal_soln)
313 { hermite_nodal_soln(elem, order, elem_soln, nodal_soln, /*Dim=*/3); }
314 
315 
316 
317 
318 // Do full-specialization for every dimension, instead
319 // of explicit instantiation at the end of this function.
320 // This could be macro-ified.
321 template <> unsigned int FE<0,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); }
322 template <> unsigned int FE<1,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); }
323 template <> unsigned int FE<2,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); }
324 template <> unsigned int FE<3,HERMITE>::n_dofs(const ElemType t, const Order o) { return hermite_n_dofs(t, o); }
325 
326 // Do full-specialization for every dimension, instead
327 // of explicit instantiation at the end of this function.
328 template <> unsigned int FE<0,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); }
329 template <> unsigned int FE<1,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); }
330 template <> unsigned int FE<2,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); }
331 template <> unsigned int FE<3,HERMITE>::n_dofs_at_node(const ElemType t, const Order o, const unsigned int n) { return hermite_n_dofs_at_node(t, o, n); }
332 
333 // Full specialization of n_dofs_per_elem() function for every dimension.
334 template <> unsigned int FE<0,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); }
335 template <> unsigned int FE<1,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); }
336 template <> unsigned int FE<2,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); }
337 template <> unsigned int FE<3,HERMITE>::n_dofs_per_elem(const ElemType t, const Order o) { return hermite_n_dofs_per_elem(t, o); }
338 
339 // Hermite FEMs are C^1 continuous
340 template <> FEContinuity FE<0,HERMITE>::get_continuity() const { return C_ONE; }
341 template <> FEContinuity FE<1,HERMITE>::get_continuity() const { return C_ONE; }
342 template <> FEContinuity FE<2,HERMITE>::get_continuity() const { return C_ONE; }
343 template <> FEContinuity FE<3,HERMITE>::get_continuity() const { return C_ONE; }
344 
345 // Hermite FEMs are hierarchic
346 template <> bool FE<0,HERMITE>::is_hierarchic() const { return true; }
347 template <> bool FE<1,HERMITE>::is_hierarchic() const { return true; }
348 template <> bool FE<2,HERMITE>::is_hierarchic() const { return true; }
349 template <> bool FE<3,HERMITE>::is_hierarchic() const { return true; }
350 
351 
352 #ifdef LIBMESH_ENABLE_AMR
353 // compute_constraints() specializations are only needed for 2 and 3D
354 template <>
356  DofMap & dof_map,
357  const unsigned int variable_number,
358  const Elem * elem)
359 { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
360 
361 template <>
363  DofMap & dof_map,
364  const unsigned int variable_number,
365  const Elem * elem)
366 { compute_proj_constraints(constraints, dof_map, variable_number, elem); }
367 #endif // #ifdef LIBMESH_ENABLE_AMR
368 
369 // Hermite FEM shapes need reinit
370 template <> bool FE<0,HERMITE>::shapes_need_reinit() const { return true; }
371 template <> bool FE<1,HERMITE>::shapes_need_reinit() const { return true; }
372 template <> bool FE<2,HERMITE>::shapes_need_reinit() const { return true; }
373 template <> bool FE<3,HERMITE>::shapes_need_reinit() const { return true; }
374 
375 } // namespace libMesh
static unsigned int n_dofs(const ElemType t, const Order o)
The base class for all geometric element types.
Definition: elem.h:100
static unsigned int n_dofs_at_node(const ElemType t, const Order o, const unsigned int n)
virtual bool shapes_need_reinit() const override
virtual bool is_hierarchic() const override
Manages the degrees of freedom (DOFs) in a simulation.
Definition: dof_map.h:176
const dof_id_type n_nodes
Definition: tecplot_io.C:68
static unsigned int n_shape_functions(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:428
static Real shape(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int i, const Point &p)
Definition: fe_interface.C:657
static void get_refspace_nodes(const ElemType t, std::vector< Point > &nodes)
Definition: fe_abstract.C:283
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)
static void nodal_soln(const Elem *elem, const Order o, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln)