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)
   662   this->_elem = 
nullptr;
   669 void FESubdivision::reinit(
const Elem * elem,
   670                            const std::vector<Point> * 
const libmesh_dbg_var(pts),
   671                            const std::vector<Real> * 
const)
   679   LOG_SCOPE(
"reinit()", 
"FESubdivision");
   685   libmesh_assert_equal_to(sd_elem->get_ordered_valence(1), 6);
   686   libmesh_assert_equal_to(sd_elem->get_ordered_valence(2), 6);
   689   this->determine_calculations();
   697   this->init_shape_functions(this->qrule->get_points(), elem);
   700   shapes_on_quadrature = 
true;
   703   this->_fe_map->compute_map (this->
dim, this->qrule->get_weights(), elem, this->calculate_d2phi);
   711                               const unsigned int i,
   721             libmesh_assert_less(i, 12);
   722             return FESubdivision::regular_shape(i,p(0),p(1));
   728       libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
   737                               const unsigned int i,
   739                               const bool add_p_level)
   742   const Order totalorder = order + add_p_level*elem->
p_level();
   750                               const unsigned int i,
   752                               const bool add_p_level)
   764                                     const unsigned int i,
   765                                     const unsigned int j,
   775             libmesh_assert_less(i, 12);
   776             return FESubdivision::regular_shape_deriv(i,j,p(0),p(1));
   782       libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
   791                                     const unsigned int i,
   792                                     const unsigned int j,
   794                                     const bool add_p_level)
   797   const Order totalorder = order + add_p_level*elem->
p_level();
   805                                     const unsigned int i,
   806                                     const unsigned int j,
   808                                     const bool add_p_level)
   816 #ifdef LIBMESH_ENABLE_SECOND_DERIVATIVES   821                                            const unsigned int i,
   822                                            const unsigned int j,
   832             libmesh_assert_less(i, 12);
   833             return FESubdivision::regular_shape_second_deriv(i,j,p(0),p(1));
   839       libmesh_error_msg(
"ERROR: Unsupported polynomial order == " << order);
   848                                            const unsigned int i,
   849                                            const unsigned int j,
   851                                            const bool add_p_level)
   854   const Order totalorder = order + add_p_level*elem->
p_level();
   863                                            const unsigned int i,
   864                                            const unsigned int j,
   866                                            const bool add_p_level)
   874 #endif // LIBMESH_ENABLE_SECOND_DERIVATIVES   879                                    const std::vector<Number> & elem_soln,
   880                                    std::vector<Number> & nodal_soln,
   888   nodal_soln.resize(3); 
   891   if (sd_elem->is_ghost())
   901   nodal_soln[j] = elem_soln[0];
   904   j = sd_elem->local_node_number(sd_elem->get_ordered_node(1)->id());
   905   nodal_soln[j] = elem_soln[1];
   908   j = sd_elem->local_node_number(sd_elem->get_ordered_node(2)->id());
   909   nodal_soln[j] = elem_soln[sd_elem->get_ordered_valence(0)];
   920                                  const std::vector<Point> &,
   921                                  std::vector<Point> &)
   923   libmesh_not_implemented();
   930                                     const std::vector<Point> * 
const,
   931                                     const std::vector<Real> * 
const)
   933   libmesh_not_implemented();
   942   libmesh_not_implemented();
   947                                     const std::vector<Point> &,
   948                                     std::vector<Point> &,
   952   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...