inf_fe_static.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 // Local includes
20 #include "libmesh/libmesh_config.h"
21 #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
22 #include "libmesh/inf_fe.h"
23 #include "libmesh/inf_fe_macro.h"
24 #include "libmesh/fe.h"
25 #include "libmesh/fe_interface.h"
27 #include "libmesh/elem.h"
28 
29 namespace libMesh
30 {
31 
32 
33 // ------------------------------------------------------------
34 // InfFE class static member initialization
35 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
37 
38 #ifdef DEBUG
39 
40 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
42 
43 
44 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
46 
47 #endif
48 
49 
50 
51 
52 // ------------------------------------------------------------
53 // InfFE static class members
54 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
55 unsigned int InfFE<Dim,T_radial,T_map>::n_dofs (const FEType & fet,
56  const ElemType inf_elem_type)
57 {
58  const ElemType base_et (Base::get_elem_type(inf_elem_type));
59 
60  if (Dim > 1)
61  return FEInterface::n_dofs(Dim-1, fet, base_et) * Radial::n_dofs(fet.radial_order);
62  else
63  return Radial::n_dofs(fet.radial_order);
64 }
65 
66 
67 
68 
69 
70 
71 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
73  const ElemType inf_elem_type,
74  const unsigned int n)
75 {
76  const ElemType base_et (Base::get_elem_type(inf_elem_type));
77 
78  unsigned int n_base, n_radial;
79  compute_node_indices(inf_elem_type, n, n_base, n_radial);
80 
81  // libMesh::out << "elem_type=" << inf_elem_type
82  // << ", fet.radial_order=" << fet.radial_order
83  // << ", n=" << n
84  // << ", n_radial=" << n_radial
85  // << ", n_base=" << n_base
86  // << std::endl;
87 
88  if (Dim > 1)
89  return FEInterface::n_dofs_at_node(Dim-1, fet, base_et, n_base)
90  * Radial::n_dofs_at_node(fet.radial_order, n_radial);
91  else
92  return Radial::n_dofs_at_node(fet.radial_order, n_radial);
93 }
94 
95 
96 
97 
98 
99 
100 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
102  const ElemType inf_elem_type)
103 {
104  const ElemType base_et (Base::get_elem_type(inf_elem_type));
105 
106  if (Dim > 1)
107  return FEInterface::n_dofs_per_elem(Dim-1, fet, base_et)
108  * Radial::n_dofs_per_elem(fet.radial_order);
109  else
110  return Radial::n_dofs_per_elem(fet.radial_order);
111 }
112 
113 
114 
115 
116 
117 
118 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
120  const Elem * /* elem */,
121  const std::vector<Number> & /* elem_soln */,
122  std::vector<Number> & nodal_soln)
123 {
124 #ifdef DEBUG
125  if (!_warned_for_nodal_soln)
126  {
127  libMesh::err << "WARNING: nodal_soln(...) does _not_ work for infinite elements." << std::endl
128  << " Will return an empty nodal solution. Use " << std::endl
129  << " InfFE<Dim,T_radial,T_map>::compute_data(..) instead!" << std::endl;
130  _warned_for_nodal_soln = true;
131  }
132 #endif
133 
134  /*
135  * In the base the infinite element couples to
136  * conventional finite elements. To not destroy
137  * the values there, clear \p nodal_soln. This
138  * indicates to the user of \p nodal_soln to
139  * not use this result.
140  */
141  nodal_soln.clear();
142  libmesh_assert (nodal_soln.empty());
143  return;
144 }
145 
146 
147 
148 
149 
150 
151 
152 
153 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
155  const ElemType inf_elem_type,
156  const unsigned int i,
157  const Point & p)
158 {
159  libmesh_assert_not_equal_to (Dim, 0);
160 
161 #ifdef DEBUG
162  // this makes only sense when used for mapping
163  if ((T_radial != INFINITE_MAP) && !_warned_for_shape)
164  {
165  libMesh::err << "WARNING: InfFE<Dim,T_radial,T_map>::shape(...) does _not_" << std::endl
166  << " return the correct trial function! Use " << std::endl
167  << " InfFE<Dim,T_radial,T_map>::compute_data(..) instead!"
168  << std::endl;
169  _warned_for_shape = true;
170  }
171 #endif
172 
173  const ElemType base_et (Base::get_elem_type(inf_elem_type));
174  const Order o_radial (fet.radial_order);
175  const Real v (p(Dim-1));
176 
177  unsigned int i_base, i_radial;
178  compute_shape_indices(fet, inf_elem_type, i, i_base, i_radial);
179 
180  //TODO:[SP/DD] exp(ikr) is still missing here!
181  // but is it intended? It would be probably somehow nice, but than it would be Number, not Real !
182  // --> thus it would destroy the interface...
183  if (Dim > 1)
184  return FEInterface::shape(Dim-1, fet, base_et, i_base, p)
185  * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
187  else
188  return InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
190 }
191 
192 
193 
194 
195 
196 
197 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
199  const Elem * inf_elem,
200  const unsigned int i,
201  const Point & p)
202 {
203  libmesh_assert(inf_elem);
204  libmesh_assert_not_equal_to (Dim, 0);
205 
206 #ifdef DEBUG
207  // this makes only sense when used for mapping
208  if ((T_radial != INFINITE_MAP) && !_warned_for_shape)
209  {
210  libMesh::err << "WARNING: InfFE<Dim,T_radial,T_map>::shape(...) does _not_" << std::endl
211  << " return the correct trial function! Use " << std::endl
212  << " InfFE<Dim,T_radial,T_map>::compute_data(..) instead!"
213  << std::endl;
214  _warned_for_shape = true;
215  }
216 #endif
217 
218  const Order o_radial (fet.radial_order);
219  const Real v (p(Dim-1));
220  std::unique_ptr<const Elem> base_el (inf_elem->build_side_ptr(0));
221 
222  unsigned int i_base, i_radial;
223  compute_shape_indices(fet, inf_elem->type(), i, i_base, i_radial);
224 
225  if (Dim > 1)
226  return FEInterface::shape(Dim-1, fet, base_el.get(), i_base, p)
227  * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
229  else
230  return InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)
232 }
233 
234 
235 
236 
237 
238 
239 
240 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
242  const Elem * inf_elem,
244 {
245  libmesh_assert(inf_elem);
246  libmesh_assert_not_equal_to (Dim, 0);
247 
248  const Order o_radial (fet.radial_order);
249  const Order radial_mapping_order (Radial::mapping_order());
250  const Point & p (data.p);
251  const Real v (p(Dim-1));
252  std::unique_ptr<const Elem> base_el (inf_elem->build_side_ptr(0));
253 
254  /*
255  * compute \p interpolated_dist containing the mapping-interpolated
256  * distance of the base point to the origin. This is the same
257  * for all shape functions. Set \p interpolated_dist to 0, it
258  * is added to.
259  */
260  Real interpolated_dist = 0.;
261  switch (Dim)
262  {
263  case 1:
264  {
265  libmesh_assert_equal_to (inf_elem->type(), INFEDGE2);
266  interpolated_dist = Point(inf_elem->point(0) - inf_elem->point(1)).norm();
267  break;
268  }
269 
270  case 2:
271  {
272  const unsigned int n_base_nodes = base_el->n_nodes();
273 
274  const Point origin = inf_elem->origin();
275  const Order base_mapping_order (base_el->default_order());
276  const ElemType base_mapping_elem_type (base_el->type());
277 
278  // interpolate the base nodes' distances
279  for (unsigned int n=0; n<n_base_nodes; n++)
280  interpolated_dist += Point(base_el->point(n) - origin).norm()
281  * FE<1,LAGRANGE>::shape (base_mapping_elem_type, base_mapping_order, n, p);
282  break;
283  }
284 
285  case 3:
286  {
287  const unsigned int n_base_nodes = base_el->n_nodes();
288 
289  const Point origin = inf_elem->origin();
290  const Order base_mapping_order (base_el->default_order());
291  const ElemType base_mapping_elem_type (base_el->type());
292 
293  // interpolate the base nodes' distances
294  for (unsigned int n=0; n<n_base_nodes; n++)
295  interpolated_dist += Point(base_el->point(n) - origin).norm()
296  * FE<2,LAGRANGE>::shape (base_mapping_elem_type, base_mapping_order, n, p);
297  break;
298  }
299 
300  default:
301  libmesh_error_msg("Unknown Dim = " << Dim);
302  }
303 
304 
305  const Real speed = data.speed;
306 
307  //TODO: I find it inconvenient to have a quantity phase which is phase/speed.
308  // But it might be better than redefining a quantities meaning.
309  data.phase = interpolated_dist /* together with next line: */
310  * InfFE<Dim,INFINITE_MAP,T_map>::eval(v, radial_mapping_order, 1)/speed; /* phase(s,t,v)/c */
311 
312  // We assume time-harmonic behavior in this function!
313 
314 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
315  // the wave number
316  const Number wavenumber = 2. * libMesh::pi * data.frequency / speed;
317 
318  // the exponent for time-harmonic behavior
319  // \note: this form is much less general than the implementation of dphase, which can be easily extended to
320  // other forms than e^{i kr}.
321  const Number exponent = imaginary /* imaginary unit */
322  * wavenumber /* k (can be complex) */
323  * data.phase*speed;
324 
325  const Number time_harmonic = exp(exponent); /* e^(i*k*phase(s,t,v)) */
326 #else
327  const Number time_harmonic = 1;
328 #endif //LIBMESH_USE_COMPLEX_NUMBERS
329 
330  /*
331  * compute \p shape for all dof in the element
332  */
333  if (Dim > 1)
334  {
335  const unsigned int n_dof = n_dofs (fet, inf_elem->type());
336  data.shape.resize(n_dof);
337 
338  for (unsigned int i=0; i<n_dof; i++)
339  {
340  // compute base and radial shape indices
341  unsigned int i_base, i_radial;
342  compute_shape_indices(fet, inf_elem->type(), i, i_base, i_radial);
343 
344  data.shape[i] = (InfFE<Dim,T_radial,T_map>::Radial::decay(v) /* (1.-v)/2. in 3D */
345  * FEInterface::shape(Dim-1, fet, base_el.get(), i_base, p) /* S_n(s,t) */
346  * InfFE<Dim,T_radial,T_map>::eval(v, o_radial, i_radial)) /* L_n(v) */
347  * time_harmonic; /* e^(i*k*phase(s,t,v) */
348  }
349  }
350 
351  else
352  libmesh_error_msg("compute_data() for 1-dimensional InfFE not implemented.");
353 }
354 
355 
356 
357 
358 
359 
360 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
362  const unsigned int outer_node_index,
363  unsigned int & base_node,
364  unsigned int & radial_node)
365 {
366  switch (inf_elem_type)
367  {
368  case INFEDGE2:
369  {
370  libmesh_assert_less (outer_node_index, 2);
371  base_node = 0;
372  radial_node = outer_node_index;
373  return;
374  }
375 
376 
377  // linear base approximation, easy to determine
378  case INFQUAD4:
379  {
380  libmesh_assert_less (outer_node_index, 4);
381  base_node = outer_node_index % 2;
382  radial_node = outer_node_index / 2;
383  return;
384  }
385 
386  case INFPRISM6:
387  {
388  libmesh_assert_less (outer_node_index, 6);
389  base_node = outer_node_index % 3;
390  radial_node = outer_node_index / 3;
391  return;
392  }
393 
394  case INFHEX8:
395  {
396  libmesh_assert_less (outer_node_index, 8);
397  base_node = outer_node_index % 4;
398  radial_node = outer_node_index / 4;
399  return;
400  }
401 
402 
403  // higher order base approximation, more work necessary
404  case INFQUAD6:
405  {
406  switch (outer_node_index)
407  {
408  case 0:
409  case 1:
410  {
411  radial_node = 0;
412  base_node = outer_node_index;
413  return;
414  }
415 
416  case 2:
417  case 3:
418  {
419  radial_node = 1;
420  base_node = outer_node_index-2;
421  return;
422  }
423 
424  case 4:
425  {
426  radial_node = 0;
427  base_node = 2;
428  return;
429  }
430 
431  case 5:
432  {
433  radial_node = 1;
434  base_node = 2;
435  return;
436  }
437 
438  default:
439  libmesh_error_msg("Unrecognized outer_node_index = " << outer_node_index);
440  }
441  }
442 
443 
444  case INFHEX16:
445  case INFHEX18:
446  {
447  switch (outer_node_index)
448  {
449  case 0:
450  case 1:
451  case 2:
452  case 3:
453  {
454  radial_node = 0;
455  base_node = outer_node_index;
456  return;
457  }
458 
459  case 4:
460  case 5:
461  case 6:
462  case 7:
463  {
464  radial_node = 1;
465  base_node = outer_node_index-4;
466  return;
467  }
468 
469  case 8:
470  case 9:
471  case 10:
472  case 11:
473  {
474  radial_node = 0;
475  base_node = outer_node_index-4;
476  return;
477  }
478 
479  case 12:
480  case 13:
481  case 14:
482  case 15:
483  {
484  radial_node = 1;
485  base_node = outer_node_index-8;
486  return;
487  }
488 
489  case 16:
490  {
491  libmesh_assert_equal_to (inf_elem_type, INFHEX18);
492  radial_node = 0;
493  base_node = 8;
494  return;
495  }
496 
497  case 17:
498  {
499  libmesh_assert_equal_to (inf_elem_type, INFHEX18);
500  radial_node = 1;
501  base_node = 8;
502  return;
503  }
504 
505  default:
506  libmesh_error_msg("Unrecognized outer_node_index = " << outer_node_index);
507  }
508  }
509 
510 
511  case INFPRISM12:
512  {
513  switch (outer_node_index)
514  {
515  case 0:
516  case 1:
517  case 2:
518  {
519  radial_node = 0;
520  base_node = outer_node_index;
521  return;
522  }
523 
524  case 3:
525  case 4:
526  case 5:
527  {
528  radial_node = 1;
529  base_node = outer_node_index-3;
530  return;
531  }
532 
533  case 6:
534  case 7:
535  case 8:
536  {
537  radial_node = 0;
538  base_node = outer_node_index-3;
539  return;
540  }
541 
542  case 9:
543  case 10:
544  case 11:
545  {
546  radial_node = 1;
547  base_node = outer_node_index-6;
548  return;
549  }
550 
551  default:
552  libmesh_error_msg("Unrecognized outer_node_index = " << outer_node_index);
553  }
554  }
555 
556 
557  default:
558  libmesh_error_msg("ERROR: Bad infinite element type=" << inf_elem_type << ", node=" << outer_node_index);
559  }
560 }
561 
562 
563 
564 
565 
566 
567 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
569  const unsigned int outer_node_index,
570  unsigned int & base_node,
571  unsigned int & radial_node)
572 {
573  libmesh_assert_not_equal_to (inf_elem_type, INVALID_ELEM);
574 
575  static std::vector<unsigned int> _static_base_node_index;
576  static std::vector<unsigned int> _static_radial_node_index;
577 
578  /*
579  * fast counterpart to compute_node_indices(), uses local static buffers
580  * to store the index maps. The class member
581  * \p _compute_node_indices_fast_current_elem_type remembers
582  * the current element type.
583  *
584  * Note that there exist non-static members storing the
585  * same data. However, you never know what element type
586  * is currently used by the \p InfFE object, and what
587  * request is currently directed to the static \p InfFE
588  * members (which use \p compute_node_indices_fast()).
589  * So separate these.
590  *
591  * check whether the work for this elemtype has already
592  * been done. If so, use this index. Otherwise, refresh
593  * the buffer to this element type.
594  */
595  if (inf_elem_type==_compute_node_indices_fast_current_elem_type)
596  {
597  base_node = _static_base_node_index [outer_node_index];
598  radial_node = _static_radial_node_index[outer_node_index];
599  return;
600  }
601  else
602  {
603  // store the map for _all_ nodes for this element type
604  _compute_node_indices_fast_current_elem_type = inf_elem_type;
605 
606  unsigned int n_nodes = libMesh::invalid_uint;
607 
608  switch (inf_elem_type)
609  {
610  case INFEDGE2:
611  {
612  n_nodes = 2;
613  break;
614  }
615  case INFQUAD4:
616  {
617  n_nodes = 4;
618  break;
619  }
620  case INFQUAD6:
621  {
622  n_nodes = 6;
623  break;
624  }
625  case INFHEX8:
626  {
627  n_nodes = 8;
628  break;
629  }
630  case INFHEX16:
631  {
632  n_nodes = 16;
633  break;
634  }
635  case INFHEX18:
636  {
637  n_nodes = 18;
638  break;
639  }
640  case INFPRISM6:
641  {
642  n_nodes = 6;
643  break;
644  }
645  case INFPRISM12:
646  {
647  n_nodes = 12;
648  break;
649  }
650  default:
651  libmesh_error_msg("ERROR: Bad infinite element type=" << inf_elem_type << ", node=" << outer_node_index);
652  }
653 
654 
655  _static_base_node_index.resize (n_nodes);
656  _static_radial_node_index.resize(n_nodes);
657 
658  for (unsigned int n=0; n<n_nodes; n++)
659  compute_node_indices (inf_elem_type,
660  n,
661  _static_base_node_index [outer_node_index],
662  _static_radial_node_index[outer_node_index]);
663 
664  // and return for the specified node
665  base_node = _static_base_node_index [outer_node_index];
666  radial_node = _static_radial_node_index[outer_node_index];
667  return;
668  }
669 }
670 
671 
672 
673 
674 
675 
676 template <unsigned int Dim, FEFamily T_radial, InfMapType T_map>
678  const ElemType inf_elem_type,
679  const unsigned int i,
680  unsigned int & base_shape,
681  unsigned int & radial_shape)
682 {
683 
684  /*
685  * An example is provided: the numbers in comments refer to
686  * a fictitious InfHex18. The numbers are chosen as exemplary
687  * values. There is currently no base approximation that
688  * requires this many dof's at nodes, sides, faces and in the element.
689  *
690  * the order of the shape functions is heavily related with the
691  * order the dofs are assigned in \p DofMap::distributed_dofs().
692  * Due to the infinite elements with higher-order base approximation,
693  * some more effort is necessary.
694  *
695  * numbering scheme:
696  * 1. all vertices in the base, assign node->n_comp() dofs to each vertex
697  * 2. all vertices further out: innermost loop: radial shapes,
698  * then the base approximation shapes
699  * 3. all side nodes in the base, assign node->n_comp() dofs to each side node
700  * 4. all side nodes further out: innermost loop: radial shapes,
701  * then the base approximation shapes
702  * 5. (all) face nodes in the base, assign node->n_comp() dofs to each face node
703  * 6. (all) face nodes further out: innermost loop: radial shapes,
704  * then the base approximation shapes
705  * 7. element-associated dof in the base
706  * 8. element-associated dof further out
707  */
708 
709  const unsigned int radial_order = static_cast<unsigned int>(fet.radial_order.get_order()); // 4
710  const unsigned int radial_order_p_one = radial_order+1; // 5
711 
712  const ElemType base_elem_type (Base::get_elem_type(inf_elem_type)); // QUAD9
713 
714  // assume that the number of dof is the same for all vertices
715  unsigned int n_base_vertices = libMesh::invalid_uint; // 4
716  const unsigned int n_base_vertex_dof = FEInterface::n_dofs_at_node (Dim-1, fet, base_elem_type, 0);// 2
717 
718  unsigned int n_base_side_nodes = libMesh::invalid_uint; // 4
719  unsigned int n_base_side_dof = libMesh::invalid_uint; // 3
720 
721  unsigned int n_base_face_nodes = libMesh::invalid_uint; // 1
722  unsigned int n_base_face_dof = libMesh::invalid_uint; // 5
723 
724  const unsigned int n_base_elem_dof = FEInterface::n_dofs_per_elem (Dim-1, fet, base_elem_type);// 9
725 
726 
727  switch (inf_elem_type)
728  {
729  case INFEDGE2:
730  {
731  n_base_vertices = 1;
732  n_base_side_nodes = 0;
733  n_base_face_nodes = 0;
734  n_base_side_dof = 0;
735  n_base_face_dof = 0;
736  break;
737  }
738 
739  case INFQUAD4:
740  {
741  n_base_vertices = 2;
742  n_base_side_nodes = 0;
743  n_base_face_nodes = 0;
744  n_base_side_dof = 0;
745  n_base_face_dof = 0;
746  break;
747  }
748 
749  case INFQUAD6:
750  {
751  n_base_vertices = 2;
752  n_base_side_nodes = 1;
753  n_base_face_nodes = 0;
754  n_base_side_dof = FEInterface::n_dofs_at_node (Dim-1, fet,base_elem_type, n_base_vertices);
755  n_base_face_dof = 0;
756  break;
757  }
758 
759  case INFHEX8:
760  {
761  n_base_vertices = 4;
762  n_base_side_nodes = 0;
763  n_base_face_nodes = 0;
764  n_base_side_dof = 0;
765  n_base_face_dof = 0;
766  break;
767  }
768 
769  case INFHEX16:
770  {
771  n_base_vertices = 4;
772  n_base_side_nodes = 4;
773  n_base_face_nodes = 0;
774  n_base_side_dof = FEInterface::n_dofs_at_node (Dim-1, fet,base_elem_type, n_base_vertices);
775  n_base_face_dof = 0;
776  break;
777  }
778 
779  case INFHEX18:
780  {
781  n_base_vertices = 4;
782  n_base_side_nodes = 4;
783  n_base_face_nodes = 1;
784  n_base_side_dof = FEInterface::n_dofs_at_node (Dim-1, fet,base_elem_type, n_base_vertices);
785  n_base_face_dof = FEInterface::n_dofs_at_node (Dim-1, fet,base_elem_type, 8);
786  break;
787  }
788 
789 
790  case INFPRISM6:
791  {
792  n_base_vertices = 3;
793  n_base_side_nodes = 0;
794  n_base_face_nodes = 0;
795  n_base_side_dof = 0;
796  n_base_face_dof = 0;
797  break;
798  }
799 
800  case INFPRISM12:
801  {
802  n_base_vertices = 3;
803  n_base_side_nodes = 3;
804  n_base_face_nodes = 0;
805  n_base_side_dof = FEInterface::n_dofs_at_node (Dim-1, fet,base_elem_type, n_base_vertices);
806  n_base_face_dof = 0;
807  break;
808  }
809 
810  default:
811  libmesh_error_msg("Unrecognized inf_elem_type = " << inf_elem_type);
812  }
813 
814 
815  {
816  // these are the limits describing the intervals where the shape function lies
817  const unsigned int n_dof_at_base_vertices = n_base_vertices*n_base_vertex_dof; // 8
818  const unsigned int n_dof_at_all_vertices = n_dof_at_base_vertices*radial_order_p_one; // 40
819 
820  const unsigned int n_dof_at_base_sides = n_base_side_nodes*n_base_side_dof; // 12
821  const unsigned int n_dof_at_all_sides = n_dof_at_base_sides*radial_order_p_one; // 60
822 
823  const unsigned int n_dof_at_base_face = n_base_face_nodes*n_base_face_dof; // 5
824  const unsigned int n_dof_at_all_faces = n_dof_at_base_face*radial_order_p_one; // 25
825 
826 
827  // start locating the shape function
828  if (i < n_dof_at_base_vertices) // range of i: 0..7
829  {
830  // belongs to vertex in the base
831  radial_shape = 0;
832  base_shape = i;
833  }
834 
835  else if (i < n_dof_at_all_vertices) // range of i: 8..39
836  {
837  /* belongs to vertex in the outer shell
838  *
839  * subtract the number of dof already counted,
840  * so that i_offset contains only the offset for the base
841  */
842  const unsigned int i_offset = i - n_dof_at_base_vertices; // 0..31
843 
844  // first the radial dof are counted, then the base dof
845  radial_shape = (i_offset % radial_order) + 1;
846  base_shape = i_offset / radial_order;
847  }
848 
849  else if (i < n_dof_at_all_vertices+n_dof_at_base_sides) // range of i: 40..51
850  {
851  // belongs to base, is a side node
852  radial_shape = 0;
853  base_shape = i - radial_order * n_dof_at_base_vertices; // 8..19
854  }
855 
856  else if (i < n_dof_at_all_vertices+n_dof_at_all_sides) // range of i: 52..99
857  {
858  // belongs to side node in the outer shell
859  const unsigned int i_offset = i - (n_dof_at_all_vertices
860  + n_dof_at_base_sides); // 0..47
861  radial_shape = (i_offset % radial_order) + 1;
862  base_shape = (i_offset / radial_order) + n_dof_at_base_vertices;
863  }
864 
865  else if (i < n_dof_at_all_vertices+n_dof_at_all_sides+n_dof_at_base_face) // range of i: 100..104
866  {
867  // belongs to the node in the base face
868  radial_shape = 0;
869  base_shape = i - radial_order*(n_dof_at_base_vertices
870  + n_dof_at_base_sides); // 20..24
871  }
872 
873  else if (i < n_dof_at_all_vertices+n_dof_at_all_sides+n_dof_at_all_faces) // range of i: 105..124
874  {
875  // belongs to the node in the outer face
876  const unsigned int i_offset = i - (n_dof_at_all_vertices
877  + n_dof_at_all_sides
878  + n_dof_at_base_face); // 0..19
879  radial_shape = (i_offset % radial_order) + 1;
880  base_shape = (i_offset / radial_order) + n_dof_at_base_vertices + n_dof_at_base_sides;
881  }
882 
883  else if (i < n_dof_at_all_vertices+n_dof_at_all_sides+n_dof_at_all_faces+n_base_elem_dof) // range of i: 125..133
884  {
885  // belongs to the base and is an element associated shape
886  radial_shape = 0;
887  base_shape = i - (n_dof_at_all_vertices
888  + n_dof_at_all_sides
889  + n_dof_at_all_faces); // 0..8
890  }
891 
892  else // range of i: 134..169
893  {
894  libmesh_assert_less (i, n_dofs(fet, inf_elem_type));
895  // belongs to the outer shell and is an element associated shape
896  const unsigned int i_offset = i - (n_dof_at_all_vertices
897  + n_dof_at_all_sides
898  + n_dof_at_all_faces
899  + n_base_elem_dof); // 0..19
900  radial_shape = (i_offset % radial_order) + 1;
901  base_shape = (i_offset / radial_order) + n_dof_at_base_vertices + n_dof_at_base_sides + n_dof_at_base_face;
902  }
903  }
904 
905  return;
906 }
907 
908 
909 
910 //--------------------------------------------------------------
911 // Explicit instantiations
912 //#include "libmesh/inf_fe_instantiate_1D.h"
913 //#include "libmesh/inf_fe_instantiate_2D.h"
914 //#include "libmesh/inf_fe_instantiate_3D.h"
915 
916 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, unsigned int, n_dofs(const FEType &, const ElemType));
917 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, unsigned int, n_dofs(const FEType &, const ElemType));
918 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, unsigned int, n_dofs(const FEType &, const ElemType));
919 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, unsigned int, n_dofs_per_elem(const FEType &, const ElemType));
920 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, unsigned int, n_dofs_per_elem(const FEType &, const ElemType));
921 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, unsigned int, n_dofs_per_elem(const FEType &, const ElemType));
922 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, unsigned int, n_dofs_at_node(const FEType &, const ElemType, const unsigned int));
923 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, unsigned int, n_dofs_at_node(const FEType &, const ElemType, const unsigned int));
924 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, unsigned int, n_dofs_at_node(const FEType &, const ElemType, const unsigned int));
925 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, void, compute_shape_indices(const FEType &, const ElemType, const unsigned int, unsigned int &, unsigned int &));
926 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, void, compute_shape_indices(const FEType &, const ElemType, const unsigned int, unsigned int &, unsigned int &));
927 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, void, compute_shape_indices(const FEType &, const ElemType, const unsigned int, unsigned int &, unsigned int &));
928 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, void, compute_node_indices(const ElemType, const unsigned int, unsigned int &, unsigned int &));
929 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, void, compute_node_indices(const ElemType, const unsigned int, unsigned int &, unsigned int &));
930 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, void, compute_node_indices(const ElemType, const unsigned int, unsigned int &, unsigned int &));
931 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, Real, shape(const FEType &, const Elem *, const unsigned int, const Point & p));
932 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, Real, shape(const FEType &, const Elem *, const unsigned int, const Point & p));
933 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, Real, shape(const FEType &, const Elem *, const unsigned int, const Point & p));
934 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, Real, shape(const FEType &, const ElemType, const unsigned int, const Point &));
935 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, Real, shape(const FEType &, const ElemType, const unsigned int, const Point &));
936 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, Real, shape(const FEType &, const ElemType, const unsigned int, const Point &));
937 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, void, compute_data(const FEType &, const Elem *, FEComputeData &));
938 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, void, compute_data(const FEType &, const Elem *, FEComputeData &));
939 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, void, compute_data(const FEType &, const Elem *, FEComputeData &));
940 INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, void, nodal_soln(const FEType &, const Elem *, const std::vector<Number> &, std::vector<Number> &));
941 INSTANTIATE_INF_FE_MBRF(2, CARTESIAN, void, nodal_soln(const FEType &, const Elem *, const std::vector<Number> &, std::vector<Number> &));
942 INSTANTIATE_INF_FE_MBRF(3, CARTESIAN, void, nodal_soln(const FEType &, const Elem *, const std::vector<Number> &, std::vector<Number> &));
943 
944 } // namespace libMesh
945 
946 #endif //ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
static void compute_node_indices_fast(const ElemType inf_elem_type, const unsigned int outer_node_index, unsigned int &base_node, unsigned int &radial_node)
static unsigned int n_dofs_per_elem(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:504
Manages the family, order, etc. parameters for a given FE.
Definition: fe_type.h:179
static unsigned int n_dofs_per_elem(const FEType &fet, const ElemType inf_elem_type)
static bool _warned_for_shape
Definition: inf_fe.h:808
Base class for all the infinite geometric element types.
Definition: fe.h:40
static unsigned int n_dofs(const unsigned int dim, const FEType &fe_t, const ElemType t)
Definition: fe_interface.C:454
virtual Point origin() const
Definition: elem.h:1553
const unsigned int invalid_uint
Definition: libmesh.h:245
static OutputShape shape(const ElemType t, const Order o, const unsigned int i, const Point &p)
static unsigned int n_dofs_at_node(const FEType &fet, const ElemType inf_elem_type, const unsigned int n)
Definition: inf_fe_static.C:72
Helper class used with FEInterface::compute_data().
OrderWrapper radial_order
Definition: fe_type.h:237
The base class for all geometric element types.
Definition: elem.h:100
INSTANTIATE_INF_FE_MBRF(1, CARTESIAN, Elem *, Base::build_elem(const Elem *))
static Real shape(const FEType &fet, const ElemType t, const unsigned int i, const Point &p)
static void compute_node_indices(const ElemType inf_elem_type, const unsigned int outer_node_index, unsigned int &base_node, unsigned int &radial_node)
const Number imaginary
virtual std::unique_ptr< Elem > build_side_ptr(const unsigned int i, bool proxy=true)=0
const dof_id_type n_nodes
Definition: tecplot_io.C:68
static unsigned int n_dofs(const FEType &fet, const ElemType inf_elem_type)
Definition: inf_fe_static.C:55
static Real decay(const Real v)
Definition: inf_fe.h:827
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 Real eval(Real v, Order o_radial, unsigned int i)
OStreamProxy err(std::cerr)
int get_order() const
Definition: fe_type.h:78
static unsigned int n_dofs_at_node(const unsigned int dim, const FEType &fe_t, const ElemType t, const unsigned int n)
Definition: fe_interface.C:473
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static void compute_shape_indices(const FEType &fet, const ElemType inf_elem_type, const unsigned int i, unsigned int &base_shape, unsigned int &radial_shape)
static bool _warned_for_nodal_soln
Definition: inf_fe.h:807
static void compute_data(const FEType &fe_t, const Elem *inf_elem, FEComputeData &data)
static void nodal_soln(const FEType &fet, const Elem *elem, const std::vector< Number > &elem_soln, std::vector< Number > &nodal_soln)
IterBase * data
static ElemType _compute_node_indices_fast_current_elem_type
Definition: inf_fe.h:799
virtual ElemType type() const =0
A geometric point in (x,y,z) space.
Definition: point.h:38
const Point & point(const unsigned int i) const
Definition: elem.h:1892
const Real pi
Definition: libmesh.h:233