20 #include "libmesh/fe.h"
21 #include "libmesh/elem.h"
22 #include "libmesh/number_lookups.h"
32 Real fe_hierarchic_2D_shape(
const Elem * elem,
36 const bool add_p_level);
38 Real fe_hierarchic_2D_shape_deriv(
const Elem * elem,
43 const bool add_p_level);
45 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
47 Real fe_hierarchic_2D_shape_second_deriv(
const Elem * elem,
52 const bool add_p_level);
54 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
69 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
81 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
92 const bool add_p_level)
94 return fe_hierarchic_2D_shape(elem, order, i, p, add_p_level);
102 const unsigned int i,
104 const bool add_p_level)
106 return fe_hierarchic_2D_shape(elem, order, i, p, add_p_level);
118 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
131 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
140 const unsigned int i,
141 const unsigned int j,
143 const bool add_p_level)
145 return fe_hierarchic_2D_shape_deriv(elem, order, i, j, p, add_p_level);
153 const unsigned int i,
154 const unsigned int j,
156 const bool add_p_level)
158 return fe_hierarchic_2D_shape_deriv(elem, order, i, j, p, add_p_level);
163 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
172 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
185 libmesh_error_msg(
"Hierarchic shape functions require an Elem for edge orientation.");
194 const unsigned int i,
195 const unsigned int j,
197 const bool add_p_level)
199 return fe_hierarchic_2D_shape_second_deriv(elem, order, i, j, p, add_p_level);
207 const unsigned int i,
208 const unsigned int j,
210 const bool add_p_level)
212 return fe_hierarchic_2D_shape_second_deriv(elem, order, i, j, p, add_p_level);
215 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
225 Real fe_hierarchic_2D_shape(
const Elem * elem,
227 const unsigned int i,
229 const bool add_p_level)
233 const Order totalorder =
234 static_cast<Order>(order+add_p_level*elem->
p_level());
235 libmesh_assert_greater (totalorder, 0);
237 switch (elem->
type())
243 const Real zeta1 = p(0);
244 const Real zeta2 = p(1);
245 const Real zeta0 = 1. - zeta1 - zeta2;
247 libmesh_assert_less (i, (totalorder+1u)*(totalorder+2u)/2);
258 else if (i < totalorder + 2u)
261 if (zeta0 + zeta1 == 0.)
264 const unsigned int basisorder = i - 1;
267 if (basisorder%2 && (elem->
point(0) > elem->
point(1)))
270 Real edgeval = (zeta1 - zeta0) / (zeta1 + zeta0);
271 Real crossfunc = zeta0 + zeta1;
272 for (
unsigned int n=1; n != basisorder; ++n)
273 crossfunc *= (zeta0 + zeta1);
275 return f0 * crossfunc *
277 basisorder, edgeval);
279 else if (i < 2u*totalorder + 1)
282 if (zeta1 + zeta2 == 0.)
285 const unsigned int basisorder = i - totalorder;
288 if (basisorder%2 && (elem->
point(1) > elem->
point(2)))
291 Real edgeval = (zeta2 - zeta1) / (zeta2 + zeta1);
292 Real crossfunc = zeta2 + zeta1;
293 for (
unsigned int n=1; n != basisorder; ++n)
294 crossfunc *= (zeta2 + zeta1);
296 return f1 * crossfunc *
298 basisorder, edgeval);
300 else if (i < 3u*totalorder)
303 if (zeta0 + zeta2 == 0.)
306 const unsigned int basisorder = i - (2u*totalorder) + 1;
309 if (basisorder%2 && (elem->
point(2) > elem->
point(0)))
312 Real edgeval = (zeta0 - zeta2) / (zeta0 + zeta2);
313 Real crossfunc = zeta0 + zeta2;
314 for (
unsigned int n=1; n != basisorder; ++n)
315 crossfunc *= (zeta0 + zeta2);
317 return f2 * crossfunc *
319 basisorder, edgeval);
324 const unsigned int basisnum = i - (3u*totalorder);
330 for (
unsigned int n = 0; n != exp0; ++n)
332 for (
unsigned int n = 0; n != exp1; ++n)
342 libmesh_assert_less (totalorder, 2);
343 libmesh_fallthrough();
349 const Real xi = p(0);
350 const Real eta = p(1);
352 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
371 else if (i < totalorder + 3u)
372 { i0 = i - 2; i1 = 0; }
373 else if (i < 2u*totalorder + 2)
374 { i0 = 1; i1 = i - totalorder - 1; }
375 else if (i < 3u*totalorder + 1)
376 { i0 = i - 2u*totalorder; i1 = 1; }
377 else if (i < 4u*totalorder)
378 { i0 = 0; i1 = i - 3u*totalorder + 1; }
382 unsigned int basisnum = i - 4*totalorder;
391 if ((i0%2) && (i0 > 2) && (i1 == 0))
393 else if ((i0%2) && (i0>2) && (i1 == 1))
395 else if ((i0 == 0) && (i1%2) && (i1>2))
397 else if ((i0 == 1) && (i1%2) && (i1>2))
405 libmesh_error_msg(
"ERROR: Unsupported element type = " << elem->
type());
413 Real fe_hierarchic_2D_shape_deriv(
const Elem * elem,
415 const unsigned int i,
416 const unsigned int j,
418 const bool add_p_level)
424 const Order totalorder =
425 static_cast<Order>(order+add_p_level*elem->
p_level());
427 libmesh_assert_greater (totalorder, 0);
436 const Real eps = 1.e-6;
438 libmesh_assert_less (j, 2);
445 const Point pp(p(0)+eps, p(1));
446 const Point pm(p(0)-eps, p(1));
455 const Point pp(p(0), p(1)+eps);
456 const Point pm(p(0), p(1)-eps);
463 libmesh_error_msg(
"Invalid derivative index j = " << j);
469 libmesh_assert_less (totalorder, 2);
470 libmesh_fallthrough();
476 const Real xi = p(0);
477 const Real eta = p(1);
479 libmesh_assert_less (i, (totalorder+1u)*(totalorder+1u));
498 else if (i < totalorder + 3u)
499 { i0 = i - 2; i1 = 0; }
500 else if (i < 2u*totalorder + 2)
501 { i0 = 1; i1 = i - totalorder - 1; }
502 else if (i < 3u*totalorder + 1u)
503 { i0 = i - 2u*totalorder; i1 = 1; }
504 else if (i < 4u*totalorder)
505 { i0 = 0; i1 = i - 3u*totalorder + 1; }
509 unsigned int basisnum = i - 4*totalorder;
518 if ((i0%2) && (i0 > 2) && (i1 == 0))
520 else if ((i0%2) && (i0>2) && (i1 == 1))
522 else if ((i0 == 0) && (i1%2) && (i1>2))
524 else if ((i0 == 1) && (i1%2) && (i1>2))
540 libmesh_error_msg(
"Invalid derivative index j = " << j);
545 libmesh_error_msg(
"ERROR: Unsupported element type = " << type);
553 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
555 Real fe_hierarchic_2D_shape_second_deriv(
const Elem * elem,
557 const unsigned int i,
558 const unsigned int j,
560 const bool add_p_level)
566 const Real eps = 1.e-6;
575 pp =
Point(p(0)+eps, p(1));
576 pm =
Point(p(0)-eps, p(1));
584 pp =
Point(p(0), p(1)+eps);
585 pm =
Point(p(0), p(1)-eps);
593 pp =
Point(p(0), p(1)+eps);
594 pm =
Point(p(0), p(1)-eps);
599 libmesh_error_msg(
"Invalid derivative index j = " << j);
607 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES