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();