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" 28 #include "libmesh/enum_to_string.h" 41 libmesh_assert_equal_to(LIBMESH_DIM, 3);
49 A.
resize(valence + 12, valence + 12);
55 A(valence+ 1,0 ) = 0.125;
56 A(valence+ 1,1 ) = 0.375;
57 A(valence+ 1,valence ) = 0.375;
58 A(valence+ 2,0 ) = 0.0625;
59 A(valence+ 2,1 ) = 0.625;
60 A(valence+ 2,2 ) = 0.0625;
61 A(valence+ 2,valence ) = 0.0625;
62 A(valence+ 3,0 ) = 0.125;
63 A(valence+ 3,1 ) = 0.375;
64 A(valence+ 3,2 ) = 0.375;
65 A(valence+ 4,0 ) = 0.0625;
66 A(valence+ 4,1 ) = 0.0625;
67 A(valence+ 4,valence-1) = 0.0625;
68 A(valence+ 4,valence ) = 0.625;
69 A(valence+ 5,0 ) = 0.125;
70 A(valence+ 5,valence-1) = 0.375;
71 A(valence+ 5,valence ) = 0.375;
72 A(valence+ 6,1 ) = 0.375;
73 A(valence+ 6,valence ) = 0.125;
74 A(valence+ 7,1 ) = 0.375;
75 A(valence+ 8,1 ) = 0.375;
76 A(valence+ 8,2 ) = 0.125;
77 A(valence+ 9,1 ) = 0.125;
78 A(valence+ 9,valence ) = 0.375;
79 A(valence+10,valence ) = 0.375;
80 A(valence+11,valence-1) = 0.125;
81 A(valence+11,valence ) = 0.375;
84 A(valence+ 1,valence+1) = 0.125;
85 A(valence+ 2,valence+1) = 0.0625;
86 A(valence+ 2,valence+2) = 0.0625;
87 A(valence+ 2,valence+3) = 0.0625;
88 A(valence+ 3,valence+3) = 0.125;
89 A(valence+ 4,valence+1) = 0.0625;
90 A(valence+ 4,valence+4) = 0.0625;
91 A(valence+ 4,valence+5) = 0.0625;
92 A(valence+ 5,valence+5) = 0.125;
93 A(valence+ 6,valence+1) = 0.375;
94 A(valence+ 6,valence+2) = 0.125;
95 A(valence+ 7,valence+1) = 0.125;
96 A(valence+ 7,valence+2) = 0.375;
97 A(valence+ 7,valence+3) = 0.125;
98 A(valence+ 8,valence+2) = 0.125;
99 A(valence+ 8,valence+3) = 0.375;
100 A(valence+ 9,valence+1) = 0.375;
101 A(valence+ 9,valence+4) = 0.125;
102 A(valence+10,valence+1) = 0.125;
103 A(valence+10,valence+4) = 0.375;
104 A(valence+10,valence+5) = 0.125;
105 A(valence+11,valence+4) = 0.125;
106 A(valence+11,valence+5) = 0.375;
109 std::vector<Real> weights;
110 loop_subdivision_mask(weights, valence);
111 for (
unsigned int i = 0; i <= valence; ++i)
118 A(1,valence) = 0.125;
121 for (
unsigned int i = 2; i < valence; ++i)
130 A(valence,0) = 0.375;
131 A(valence,1) = 0.125;
132 A(valence,valence-1) = 0.125;
133 A(valence,valence ) = 0.375;
138 Real FESubdivision::regular_shape(
const unsigned int i,
145 const Real u = 1 - v - w;
146 libmesh_assert_less_equal(0, v);
147 libmesh_assert_less_equal(0, w);
148 libmesh_assert_less_equal(0, u);
151 const Real factor = 1. / 12;
156 return factor*(pow<4>(u) + 2*u*u*u*v);
158 return factor*(pow<4>(u) + 2*u*u*u*w);
160 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 +
161 2*v*v*v*w + pow<4>(v));
163 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 +
164 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 +
165 6*v*v*v*w + pow<4>(v));
167 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 +
168 6*u*v*w*w + 2*v*w*w*w);
170 return factor*(2*u*v*v*v + pow<4>(v));
172 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 +
173 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));
175 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 +
176 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));
178 return factor*(2*u*w*w*w + pow<4>(w));
180 return factor*(2*v*v*v*w + pow<4>(v));
182 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 +
183 6*v*v*v*w + pow<4>(v));
185 return factor*(pow<4>(w) + 2*v*w*w*w);
188 libmesh_error_msg(
"Invalid i = " << i);
194 Real FESubdivision::regular_shape_deriv(
const unsigned int i,
195 const unsigned int j,
199 const Real u = 1 - v - w;
200 const Real factor = 1. / 12;
209 return factor*(-6*v*u*u - 2*u*u*u);
211 return factor*(-4*u*u*u - 6*u*u*w);
213 return factor*(-2*v*v*v - 6*v*v*u + 6*v*u*u + 2*u*u*u);
215 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 -
216 12*v*w*w - 12*u*w*w - 2*w*w*w);
218 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);
220 return factor*(2*v*v*v + 6*v*v*u);
222 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 +
223 12*v*w*w + 12*u*w*w + 2*w*w*w);
225 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 -
226 12*v*w*w + 12*u*w*w);
230 return factor*(4*v*v*v + 6*v*v*w);
232 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);
236 libmesh_error_msg(
"Invalid i = " << i);
244 return factor*(-6*v*u*u - 4*u*u*u);
246 return factor*(-2*u*u*u - 6*u*u*w);
248 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 -
251 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 -
252 18*v*w*w - 24*u*w*w - 4*w*w*w);
254 return factor*(2*u*u*u + 6*u*u*w - 6*u*w*w - 2*w*w*w);
258 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 -
261 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 +
262 24*u*u*w + 12*v*w*w + 24*u*w*w);
264 return factor*(6*u*w*w + 2*w*w*w);
268 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 +
271 return factor*(6*v*w*w + 4*w*w*w);
273 libmesh_error_msg(
"Invalid i = " << i);
277 libmesh_error_msg(
"Invalid j = " << j);
283 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 284 Real FESubdivision::regular_shape_second_deriv(
const unsigned int i,
285 const unsigned int j,
289 const Real u = 1 - v - w;
290 const Real factor = 1. / 12;
305 return v*v - 2*u*u + v*w - 2*u*w;
307 return v*u + v*w + u*w + w*w;
311 return factor*(-24*v*v + 12*u*u - 24*v*w + 12*u*w);
313 return -2*v*u - 2*v*w - 2*u*w - 2*w*w;
319 return v*u + v*w + u*w + w*w;
323 libmesh_error_msg(
"Invalid i = " << i);
331 return factor*(12*v*u + 6*u*u);
333 return factor*(6*u*u + 12*u*w);
335 return factor*(6*v*v - 12*v*u - 6*u*u);
337 return factor*(6*v*v - 12*u*u + 24*v*w + 6*w*w);
339 return factor*(-6*u*u - 12*u*w + 6*w*w);
343 return factor*(-12*v*v + 6*u*u - 24*v*w - 12*u*w - 6*w*w);
345 return factor*(-6*v*v - 12*v*u + 6*u*u - 24*v*w - 12*w*w);
351 return factor*(6*v*v + 12*v*u + 24*v*w + 12*u*w + 6*w*w);
355 libmesh_error_msg(
"Invalid i = " << i);
367 return v*v + v*u + v*w + u*w;
369 return -2*v*u - 2*u*u + v*w + w*w;
375 return -2*v*v - 2*v*u - 2*v*w - 2*u*w;
377 return v*u + u*u - 2*v*w - 2*w*w;
383 return v*v + v*u + v*w + u*w;
387 libmesh_error_msg(
"Invalid i = " << i);
391 libmesh_error_msg(
"Invalid j = " << j);
395 #endif //LIBMESH_ENABLE_SECOND_DERIVATIVES 398 void FESubdivision::loop_subdivision_mask(std::vector<Real> & weights,
399 const unsigned int valence)
401 libmesh_assert_greater(valence, 0);
403 const Real nb_weight = (0.625 - Utility::pow<2>(0.375 + 0.25 * cs)) / valence;
404 weights.resize(1 + valence, nb_weight);
405 weights[0] = 1.0 - valence * nb_weight;
410 void FESubdivision::init_shape_functions(
const std::vector<Point> & qp,
417 LOG_SCOPE(
"init_shape_functions()",
"FESubdivision");
419 calculations_started =
true;
421 const unsigned int valence = sd_elem->get_ordered_valence(0);
422 const unsigned int n_qp = cast_int<unsigned int>(qp.size());
423 const unsigned int n_approx_shape_functions = valence + 6;
426 phi.resize (n_approx_shape_functions);
427 dphi.resize (n_approx_shape_functions);
428 dphidxi.resize (n_approx_shape_functions);
429 dphideta.resize (n_approx_shape_functions);
430 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 431 d2phi.resize (n_approx_shape_functions);
432 d2phidxi2.resize (n_approx_shape_functions);
433 d2phidxideta.resize(n_approx_shape_functions);
434 d2phideta2.resize (n_approx_shape_functions);
437 for (
unsigned int i = 0; i < n_approx_shape_functions; ++i)
439 phi[i].resize (n_qp);
440 dphi[i].resize (n_qp);
441 dphidxi[i].resize (n_qp);
442 dphideta[i].resize (n_qp);
443 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 444 d2phi[i].resize (n_qp);
445 d2phidxi2[i].resize (n_qp);
446 d2phidxideta[i].resize(n_qp);
447 d2phideta2[i].resize (n_qp);
452 static const unsigned int cvi[12] = {3,6,2,0,1,4,7,10,9,5,11,8};
456 for (
unsigned int i = 0; i < n_approx_shape_functions; ++i)
458 for (
unsigned int p = 0; p < n_qp; ++p)
463 dphi[i][p](0) = dphidxi[i][p];
464 dphi[i][p](1) = dphideta[i][p];
465 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 469 d2phi[i][p](0,0) = d2phidxi2[i][p];
470 d2phi[i][p](0,1) = d2phi[i][p](1,0) = d2phidxideta[i][p];
471 d2phi[i][p](1,1) = d2phideta2[i][p];
478 static const Real eps = 1e-10;
481 std::vector<Real> tphi(12);
482 std::vector<Real> tdphidxi(12);
483 std::vector<Real> tdphideta(12);
484 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 485 std::vector<Real> td2phidxi2(12);
486 std::vector<Real> td2phidxideta(12);
487 std::vector<Real> td2phideta2(12);
490 for (
unsigned int p = 0; p < n_qp; ++p)
496 Real min = 0, max = 0.5;
498 while (!(u > min-eps && u < max+eps))
510 libmesh_assert_less(u, 0.5 + eps);
511 libmesh_assert_greater(u, -eps);
536 else if (w > 0.5 - eps)
542 P( 1,valence- 1) = 1;
545 P( 4,valence+ 5) = 1;
546 P( 5,valence+ 2) = 1;
547 P( 6,valence+ 1) = 1;
548 P( 7,valence+ 4) = 1;
549 P( 8,valence+11) = 1;
550 P( 9,valence+ 6) = 1;
551 P(10,valence+ 9) = 1;
552 P(11,valence+10) = 1;
574 libmesh_error_msg_if((u > 1 + eps) || (u < -eps),
"SUBDIVISION irregular patch: u is outside valid range!");
577 init_subdivision_matrix(A, valence);
583 for (
int e = 1; e < k; ++e)
588 const Point transformed_p(v,w);
590 for (
unsigned int i = 0; i < 12; ++i)
596 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 605 Real sum1, sum2, sum3, sum4, sum5, sum6;
606 for (
unsigned int j = 0; j < n_approx_shape_functions; ++j)
608 sum1 = sum2 = sum3 = sum4 = sum5 = sum6 = 0;
609 for (
unsigned int i = 0; i < 12; ++i)
611 sum1 += P(i,j) * tphi[i];
612 sum2 += P(i,j) * tdphidxi[i];
613 sum3 += P(i,j) * tdphideta[i];
615 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 616 sum4 += P(i,j) * td2phidxi2[i];
617 sum5 += P(i,j) * td2phidxideta[i];
618 sum6 += P(i,j) * td2phideta2[i];
622 dphidxi[j][p] = sum2 * jfac;
623 dphideta[j][p] = sum3 * jfac;
624 dphi[j][p](0) = dphidxi[j][p];
625 dphi[j][p](1) = dphideta[j][p];
627 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 628 d2phidxi2[j][p] = sum4 * jfac * jfac;
629 d2phidxideta[j][p] = sum5 * jfac * jfac;
630 d2phideta2[j][p] = sum6 * jfac * jfac;
631 d2phi[j][p](0,0) = d2phidxi2[j][p];
632 d2phi[j][p](0,1) = d2phi[j][p](1,0) = d2phidxideta[j][p];
633 d2phi[j][p](1,1) = d2phideta2[j][p];
640 this->_fe_map->get_phi_map() = phi;
641 this->_fe_map->get_dphidxi_map() = dphidxi;
642 this->_fe_map->get_dphideta_map() = dphideta;
644 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 645 this->_fe_map->get_d2phidxi2_map() = d2phidxi2;
646 this->_fe_map->get_d2phideta2_map() = d2phideta2;
647 this->_fe_map->get_d2phidxideta_map() = d2phidxideta;
650 if (this->calculate_dual)
651 this->init_dual_shape_functions(n_approx_shape_functions, n_qp);
656 void FESubdivision::attach_quadrature_rule(
QBase * q)
668 void FESubdivision::reinit(
const Elem * elem,
669 const std::vector<Point> *
const libmesh_dbg_var(pts),
670 const std::vector<Real> *
const)
678 LOG_SCOPE(
"reinit()",
"FESubdivision");
684 libmesh_assert_equal_to(sd_elem->get_ordered_valence(1), 6);
685 libmesh_assert_equal_to(sd_elem->get_ordered_valence(2), 6);
688 this->determine_calculations();
693 qrule->init(elem->
type());
696 this->init_shape_functions(this->qrule->get_points(), elem);
699 shapes_on_quadrature =
true;
702 this->_fe_map->compute_map (this->
dim, this->qrule->get_weights(), elem, this->calculate_d2phi);
710 const unsigned int i,
720 libmesh_assert_less(i, 12);
721 return FESubdivision::regular_shape(i,p(0),p(1));
727 libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
736 const unsigned int i,
738 const bool add_p_level)
741 const Order totalorder =
750 const unsigned int i,
752 const bool add_p_level)
755 const Order totalorder =
765 const unsigned int i,
766 const unsigned int j,
776 libmesh_assert_less(i, 12);
777 return FESubdivision::regular_shape_deriv(i,j,p(0),p(1));
783 libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
792 const unsigned int i,
793 const unsigned int j,
795 const bool add_p_level)
798 const Order totalorder =
807 const unsigned int i,
808 const unsigned int j,
810 const bool add_p_level)
813 const Order totalorder =
819 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES 824 const unsigned int i,
825 const unsigned int j,
835 libmesh_assert_less(i, 12);
836 return FESubdivision::regular_shape_second_deriv(i,j,p(0),p(1));
842 libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
851 const unsigned int i,
852 const unsigned int j,
854 const bool add_p_level)
857 const Order totalorder =
867 const unsigned int i,
868 const unsigned int j,
870 const bool add_p_level)
873 const Order totalorder =
879 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES 884 const std::vector<Number> & elem_soln,
885 std::vector<Number> & nodal_soln,
892 nodal_soln.resize(3);
895 if (sd_elem->is_ghost())
905 nodal_soln[j] = elem_soln[0];
908 j = sd_elem->local_node_number(sd_elem->get_ordered_node(1)->id());
909 nodal_soln[j] = elem_soln[1];
912 j = sd_elem->local_node_number(sd_elem->get_ordered_node(2)->id());
913 nodal_soln[j] = elem_soln[sd_elem->get_ordered_valence(0)];
924 const std::vector<Point> &,
925 std::vector<Point> &)
927 libmesh_not_implemented();
934 const std::vector<Point> *
const,
935 const std::vector<Real> *
const)
937 libmesh_not_implemented();
946 libmesh_not_implemented();
951 const std::vector<Point> &,
952 std::vector<Point> &,
956 libmesh_not_implemented();
class FEType hides (possibly multiple) FEFamily and approximation orders, thereby enabling specialize...
FESubdivision(const FEType &fet)
Constructor.
ElemType
Defines an enum for geometric element types.
Order
defines an enum for polynomial orders.
This is the base class from which all geometric element types are derived.
unsigned int p_level() const
OrderWrapper order
The approximation order of the element.
The libMesh namespace provides an interface to certain functionality in the library.
LIBMESH_DEFAULT_VECTORIZED_FE(template<>Real FE< 0, BERNSTEIN)
A specific instantiation of the FEBase class.
The Tri3Subdivision element is a three-noded subdivision surface shell element used in mechanics calc...
unsigned int local_node_number(unsigned int node_id) const
std::string enum_to_string(const T e)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
FEContinuity
defines an enum for finite element types to libmesh_assert a certain level (or type? Hcurl?) of continuity.
virtual void right_multiply(const DenseMatrixBase< T > &M2) override final
Performs the operation: (*this) <- (*this) * M3.
void resize(const unsigned int new_m, const unsigned int new_n)
Resizes the matrix to the specified size and calls zero().
virtual ElemType type() const =0
A Point defines a location in LIBMESH_DIM dimensional Real space.
The QBase class provides the basic functionality from which various quadrature rules can be derived...