20 #include "libmesh/fe.h"
21 #include "libmesh/libmesh_logging.h"
22 #include "libmesh/fe_type.h"
23 #include "libmesh/quadrature.h"
24 #include "libmesh/face_tri3_subdivision.h"
25 #include "libmesh/fe_macro.h"
26 #include "libmesh/dense_matrix.h"
27 #include "libmesh/utility.h"
37 libmesh_assert_equal_to(LIBMESH_DIM, 3);
45 A.resize(valence + 12, valence + 12);
51 A(valence+ 1,0 ) = 0.125;
52 A(valence+ 1,1 ) = 0.375;
53 A(valence+ 1,valence ) = 0.375;
54 A(valence+ 2,0 ) = 0.0625;
55 A(valence+ 2,1 ) = 0.625;
56 A(valence+ 2,2 ) = 0.0625;
57 A(valence+ 2,valence ) = 0.0625;
58 A(valence+ 3,0 ) = 0.125;
59 A(valence+ 3,1 ) = 0.375;
60 A(valence+ 3,2 ) = 0.375;
61 A(valence+ 4,0 ) = 0.0625;
62 A(valence+ 4,1 ) = 0.0625;
63 A(valence+ 4,valence-1) = 0.0625;
64 A(valence+ 4,valence ) = 0.625;
65 A(valence+ 5,0 ) = 0.125;
66 A(valence+ 5,valence-1) = 0.375;
67 A(valence+ 5,valence ) = 0.375;
68 A(valence+ 6,1 ) = 0.375;
69 A(valence+ 6,valence ) = 0.125;
70 A(valence+ 7,1 ) = 0.375;
71 A(valence+ 8,1 ) = 0.375;
72 A(valence+ 8,2 ) = 0.125;
73 A(valence+ 9,1 ) = 0.125;
74 A(valence+ 9,valence ) = 0.375;
75 A(valence+10,valence ) = 0.375;
76 A(valence+11,valence-1) = 0.125;
77 A(valence+11,valence ) = 0.375;
80 A(valence+ 1,valence+1) = 0.125;
81 A(valence+ 2,valence+1) = 0.0625;
82 A(valence+ 2,valence+2) = 0.0625;
83 A(valence+ 2,valence+3) = 0.0625;
84 A(valence+ 3,valence+3) = 0.125;
85 A(valence+ 4,valence+1) = 0.0625;
86 A(valence+ 4,valence+4) = 0.0625;
87 A(valence+ 4,valence+5) = 0.0625;
88 A(valence+ 5,valence+5) = 0.125;
89 A(valence+ 6,valence+1) = 0.375;
90 A(valence+ 6,valence+2) = 0.125;
91 A(valence+ 7,valence+1) = 0.125;
92 A(valence+ 7,valence+2) = 0.375;
93 A(valence+ 7,valence+3) = 0.125;
94 A(valence+ 8,valence+2) = 0.125;
95 A(valence+ 8,valence+3) = 0.375;
96 A(valence+ 9,valence+1) = 0.375;
97 A(valence+ 9,valence+4) = 0.125;
98 A(valence+10,valence+1) = 0.125;
99 A(valence+10,valence+4) = 0.375;
100 A(valence+10,valence+5) = 0.125;
101 A(valence+11,valence+4) = 0.125;
102 A(valence+11,valence+5) = 0.375;
105 std::vector<Real> weights;
107 for (
unsigned int i = 0; i <= valence; ++i)
114 A(1,valence) = 0.125;
117 for (
unsigned int i = 2; i < valence; ++i)
126 A(valence,0) = 0.375;
127 A(valence,1) = 0.125;
128 A(valence,valence-1) = 0.125;
129 A(valence,valence ) = 0.375;
141 const Real u = 1 - v - w;
142 libmesh_assert_less_equal(0, v);
143 libmesh_assert_less_equal(0, w);
144 libmesh_assert_less_equal(0, u);
147 const Real factor = 1. / 12;
152 return factor*(pow<4>(u) + 2*u*u*u*v);
154 return factor*(pow<4>(u) + 2*u*u*u*w);
156 return factor*(pow<4>(u) + 2*u*u*u*w + 6*u*u*u*v + 6*u*u*v*w + 12*u*u*v*v + 6*u*v*v*w + 6*u*v*v*v +
157 2*v*v*v*w + pow<4>(v));
159 return factor*(6*pow<4>(u) + 24*u*u*u*w + 24*u*u*w*w + 8*u*w*w*w + pow<4>(w) + 24*u*u*u*v +
160 60*u*u*v*w + 36*u*v*w*w + 6*v*w*w*w + 24*u*u*v*v + 36*u*v*v*w + 12*v*v*w*w + 8*u*v*v*v +
161 6*v*v*v*w + pow<4>(v));
163 return factor*(pow<4>(u) + 6*u*u*u*w + 12*u*u*w*w + 6*u*w*w*w + pow<4>(w) + 2*u*u*u*v + 6*u*u*v*w +
164 6*u*v*w*w + 2*v*w*w*w);
166 return factor*(2*u*v*v*v + pow<4>(v));
168 return factor*(pow<4>(u) + 6*u*u*u*w + 12*u*u*w*w + 6*u*w*w*w + pow<4>(w) + 8*u*u*u*v + 36*u*u*v*w +
169 36*u*v*w*w + 8*v*w*w*w + 24*u*u*v*v + 60*u*v*v*w + 24*v*v*w*w + 24*u*v*v*v + 24*v*v*v*w + 6*pow<4>(v));
171 return factor*(pow<4>(u) + 8*u*u*u*w + 24*u*u*w*w + 24*u*w*w*w + 6*pow<4>(w) + 6*u*u*u*v + 36*u*u*v*w +
172 60*u*v*w*w + 24*v*w*w*w + 12*u*u*v*v + 36*u*v*v*w + 24*v*v*w*w + 6*u*v*v*v + 8*v*v*v*w + pow<4>(v));
174 return factor*(2*u*w*w*w + pow<4>(w));
176 return factor*(2*v*v*v*w + pow<4>(v));
178 return factor*(2*u*w*w*w + pow<4>(w) + 6*u*v*w*w + 6*v*w*w*w + 6*u*v*v*w + 12*v*v*w*w + 2*u*v*v*v +
179 6*v*v*v*w + pow<4>(v));
181 return factor*(pow<4>(w) + 2*v*w*w*w);
184 libmesh_error_msg(
"Invalid i = " << i);
191 const unsigned int j,
195 const Real u = 1 - v - w;
196 const Real factor = 1. / 12;
205 return factor*(-6*v*u*u - 2*u*u*u);
207 return factor*(-4*u*u*u - 6*u*u*w);
209 return factor*(-2*v*v*v - 6*v*v*u + 6*v*u*u + 2*u*u*u);
211 return factor*(-4*v*v*v - 24*v*v*u - 24*v*u*u - 18*v*v*w - 48*v*u*w - 12*u*u*w -
212 12*v*w*w - 12*u*w*w - 2*w*w*w);
214 return factor*(-6*v*u*u - 2*u*u*u - 12*v*u*w-12*u*u*w - 6*v*w*w - 18*u*w*w - 4*w*w*w);
216 return factor*(2*v*v*v + 6*v*v*u);
218 return factor*(24*v*v*u + 24*v*u*u + 4*u*u*u + 12*v*v*w + 48*v*u*w + 18*u*u*w +
219 12*v*w*w + 12*u*w*w + 2*w*w*w);
221 return factor*(-2*v*v*v - 6*v*v*u + 6*v*u*u + 2*u*u*u - 12*v*v*w + 12*u*u*w -
222 12*v*w*w + 12*u*w*w);
226 return factor*(4*v*v*v + 6*v*v*w);
228 return factor*(2*v*v*v + 6*v*v*u + 12*v*v*w + 12*v*u*w + 18*v*w*w + 6*u*w*w + 4*w*w*w);
232 libmesh_error_msg(
"Invalid i = " << i);
240 return factor*(-6*v*u*u - 4*u*u*u);
242 return factor*(-2*u*u*u - 6*u*u*w);
244 return factor*(-4*v*v*v - 18*v*v*u - 12*v*u*u - 2*u*u*u - 6*v*v*w - 12*v*u*w -
247 return factor*(-2*v*v*v-12*v*v*u - 12*v*u*u - 12*v*v*w - 48*v*u*w - 24*u*u*w -
248 18*v*w*w - 24*u*w*w - 4*w*w*w);
250 return factor*(2*u*u*u + 6*u*u*w - 6*u*w*w - 2*w*w*w);
254 return factor*(12*v*v*u + 12*v*u*u + 2*u*u*u - 12*v*v*w + 6*u*u*w - 12*v*w*w -
257 return factor*(2*v*v*v + 12*v*v*u + 18*v*u*u + 4*u*u*u + 12*v*v*w + 48*v*u*w +
258 24*u*u*w + 12*v*w*w + 24*u*w*w);
260 return factor*(6*u*w*w + 2*w*w*w);
264 return factor*(4*v*v*v + 6*v*v*u + 18*v*v*w + 12*v*u*w + 12*v*w*w + 6*u*w*w +
267 return factor*(6*v*w*w + 4*w*w*w);
269 libmesh_error_msg(
"Invalid i = " << i);
273 libmesh_error_msg(
"Invalid j = " << j);
279 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
281 const unsigned int j,
285 const Real u = 1 - v - w;
286 const Real factor = 1. / 12;
301 return v*v - 2*u*u + v*w - 2*u*w;
303 return v*u + v*w + u*w + w*w;
307 return factor*(-24*v*v + 12*u*u - 24*v*w + 12*u*w);
309 return -2*v*u - 2*v*w - 2*u*w - 2*w*w;
315 return v*u + v*w + u*w + w*w;
319 libmesh_error_msg(
"Invalid i = " << i);
327 return factor*(12*v*u + 6*u*u);
329 return factor*(6*u*u + 12*u*w);
331 return factor*(6*v*v - 12*v*u - 6*u*u);
333 return factor*(6*v*v - 12*u*u + 24*v*w + 6*w*w);
335 return factor*(-6*u*u - 12*u*w + 6*w*w);
339 return factor*(-12*v*v + 6*u*u - 24*v*w - 12*u*w - 6*w*w);
341 return factor*(-6*v*v - 12*v*u + 6*u*u - 24*v*w - 12*w*w);
347 return factor*(6*v*v + 12*v*u + 24*v*w + 12*u*w + 6*w*w);
351 libmesh_error_msg(
"Invalid i = " << i);
363 return v*v + v*u + v*w + u*w;
365 return -2*v*u - 2*u*u + v*w + w*w;
371 return -2*v*v - 2*v*u - 2*v*w - 2*u*w;
373 return v*u + u*u - 2*v*w - 2*w*w;
379 return v*v + v*u + v*w + u*w;
383 libmesh_error_msg(
"Invalid i = " << i);
387 libmesh_error_msg(
"Invalid j = " << j);
391 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES
395 const unsigned int valence)
397 libmesh_assert_greater(valence, 0);
399 const Real nb_weight = (0.625 - Utility::pow<2>(0.375 + 0.25 * cs)) / valence;
400 weights.resize(1 + valence, nb_weight);
401 weights[0] = 1.0 - valence * nb_weight;
411 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
413 LOG_SCOPE(
"init_shape_functions()",
"FESubdivision");
417 const unsigned int valence = sd_elem->get_ordered_valence(0);
418 const unsigned int n_qp = cast_int<unsigned int>(qp.size());
419 const unsigned int n_approx_shape_functions = valence + 6;
422 phi.resize (n_approx_shape_functions);
423 dphi.resize (n_approx_shape_functions);
424 dphidxi.resize (n_approx_shape_functions);
425 dphideta.resize (n_approx_shape_functions);
426 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
427 d2phi.resize (n_approx_shape_functions);
428 d2phidxi2.resize (n_approx_shape_functions);
433 for (
unsigned int i = 0; i < n_approx_shape_functions; ++i)
435 phi[i].resize (n_qp);
436 dphi[i].resize (n_qp);
439 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
440 d2phi[i].resize (n_qp);
448 static const unsigned int cvi[12] = {3,6,2,0,1,4,7,10,9,5,11,8};
452 for (
unsigned int i = 0; i < n_approx_shape_functions; ++i)
454 for (
unsigned int p = 0; p < n_qp; ++p)
461 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
474 static const Real eps = 1e-10;
477 std::vector<Real> tphi(12);
478 std::vector<Real> tdphidxi(12);
479 std::vector<Real> tdphideta(12);
480 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
481 std::vector<Real> td2phidxi2(12);
482 std::vector<Real> td2phidxideta(12);
483 std::vector<Real> td2phideta2(12);
486 for (
unsigned int p = 0; p < n_qp; ++p)
492 Real min = 0, max = 0.5;
494 while (!(u > min-eps && u < max+eps))
506 libmesh_assert_less(u, 0.5 + eps);
507 libmesh_assert_greater(u, -eps);
532 else if (w > 0.5 - eps)
538 P( 1,valence- 1) = 1;
541 P( 4,valence+ 5) = 1;
542 P( 5,valence+ 2) = 1;
543 P( 6,valence+ 1) = 1;
544 P( 7,valence+ 4) = 1;
545 P( 8,valence+11) = 1;
546 P( 9,valence+ 6) = 1;
547 P(10,valence+ 9) = 1;
548 P(11,valence+10) = 1;
570 if ((u > 1 + eps) || (u < -eps))
571 libmesh_error_msg(
"SUBDIVISION irregular patch: u is outside valid range!");
580 for (
int e = 1; e < k; ++e)
581 A.right_multiply(Acopy);
585 const Point transformed_p(v,w);
587 for (
unsigned int i = 0; i < 12; ++i)
593 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
602 Real sum1, sum2, sum3, sum4, sum5, sum6;
603 for (
unsigned int j = 0; j < n_approx_shape_functions; ++j)
605 sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = 0;
606 for (
unsigned int i = 0; i < 12; ++i)
608 sum1 += P(i,j) * tphi[i];
609 sum2 += P(i,j) * tdphidxi[i];
610 sum3 += P(i,j) * tdphideta[i];
612 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
613 sum4 += P(i,j) * td2phidxi2[i];
614 sum5 += P(i,j) * td2phidxideta[i];
615 sum6 += P(i,j) * td2phideta2[i];
624 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
641 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
663 const std::vector<Point> *
const libmesh_dbg_var(pts),
664 const std::vector<Real> *
const)
669 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
672 LOG_SCOPE(
"reinit()",
"FESubdivision");
678 libmesh_assert_equal_to(sd_elem->get_ordered_valence(1), 6);
679 libmesh_assert_equal_to(sd_elem->get_ordered_valence(2), 6);
704 const unsigned int i,
714 libmesh_assert_less(i, 12);
715 return FESubdivision::regular_shape(i,p(0),p(1));
717 libmesh_error_msg(
"ERROR: Unsupported element type!");
721 libmesh_error_msg(
"ERROR: Unsupported polynomial order!");
730 const unsigned int i,
732 const bool add_p_level)
735 const Order totalorder =
736 static_cast<Order>(order+add_p_level*elem->
p_level());
745 const unsigned int i,
746 const unsigned int j,
756 libmesh_assert_less(i, 12);
757 return FESubdivision::regular_shape_deriv(i,j,p(0),p(1));
759 libmesh_error_msg(
"ERROR: Unsupported element type!");
763 libmesh_error_msg(
"ERROR: Unsupported polynomial order!");
772 const unsigned int i,
773 const unsigned int j,
775 const bool add_p_level)
778 const Order totalorder =
779 static_cast<Order>(order+add_p_level*elem->
p_level());
784 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES
789 const unsigned int i,
790 const unsigned int j,
800 libmesh_assert_less(i, 12);
801 return FESubdivision::regular_shape_second_deriv(i,j,p(0),p(1));
803 libmesh_error_msg(
"ERROR: Unsupported element type!");
807 libmesh_error_msg(
"ERROR: Unsupported polynomial order!");
816 const unsigned int i,
817 const unsigned int j,
819 const bool add_p_level)
822 const Order totalorder =
823 static_cast<Order>(order+add_p_level*elem->
p_level());
827 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES
832 const std::vector<Number> & elem_soln,
833 std::vector<Number> & nodal_soln)
837 const Tri3Subdivision * sd_elem = static_cast<const Tri3Subdivision *>(elem);
839 nodal_soln.resize(3);
842 if (sd_elem->is_ghost())
851 unsigned int j = sd_elem->local_node_number(sd_elem->get_ordered_node(0)->id());
852 nodal_soln[j] = elem_soln[0];
855 j = sd_elem->local_node_number(sd_elem->get_ordered_node(1)->id());
856 nodal_soln[j] = elem_soln[1];
859 j = sd_elem->local_node_number(sd_elem->get_ordered_node(2)->id());
860 nodal_soln[j] = elem_soln[sd_elem->get_ordered_valence(0)];
871 const std::vector<Point> &,
872 std::vector<Point> &)
874 libmesh_not_implemented();
881 const std::vector<Point> *
const,
882 const std::vector<Real> *
const)
884 libmesh_not_implemented();
893 libmesh_not_implemented();
898 const std::vector<Point> &,
899 std::vector<Point> &,
903 libmesh_not_implemented();