LCOV - code coverage report
Current view: top level - src/geom - face_quad.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 72 213 33.8 %
Date: 2025-08-19 19:27:09 Functions: 10 15 66.7 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : // Local includes
      19             : #include "libmesh/face_quad.h"
      20             : #include "libmesh/edge_edge2.h"
      21             : #include "libmesh/face_quad4.h"
      22             : #include "libmesh/enum_elem_quality.h"
      23             : 
      24             : // C++ includes
      25             : #include <array>
      26             : 
      27             : 
      28             : namespace libMesh
      29             : {
      30             : 
      31             : // ------------------------------------------------------------
      32             : // Quad class static member initializations
      33             : const int Quad::num_sides;
      34             : const int Quad::num_children;
      35             : 
      36             : // Note: we can omit initialization of the third entry of each row because
      37             : // static variables are automatically zero-initialized.
      38             : const Real Quad::_master_points[9][3] =
      39             :   {
      40             :     {-1, -1},
      41             :     {1, -1},
      42             :     {1, 1},
      43             :     {-1, 1},
      44             :     {0, -1},
      45             :     {1, 0},
      46             :     {0, 1},
      47             :     {-1, 0},
      48             :     {0, 0}
      49             :   };
      50             : 
      51             : const unsigned int Quad::adjacent_sides_map[/*num_vertices*/4][/*n_adjacent_sides*/2] =
      52             :   {
      53             :     {0, 3},  // Sides adjacent to node 0
      54             :     {0, 1},  // Sides adjacent to node 1
      55             :     {1, 2},  // Sides adjacent to node 2
      56             :     {2, 3}   // Sides adjacent to node 3
      57             :   };
      58             : 
      59             : 
      60             : 
      61             : // ------------------------------------------------------------
      62             : // Quad class member functions
      63           0 : dof_id_type Quad::key (const unsigned int s) const
      64             : {
      65           0 :   libmesh_assert_less (s, this->n_sides());
      66             : 
      67           0 :   return this->compute_key(this->node_id(Quad4::side_nodes_map[s][0]),
      68           0 :                            this->node_id(Quad4::side_nodes_map[s][1]));
      69             : }
      70             : 
      71             : 
      72             : 
      73   146924694 : dof_id_type Quad::low_order_key (const unsigned int s) const
      74             : {
      75     1890688 :   libmesh_assert_less (s, this->n_sides());
      76             : 
      77   148815382 :   return this->compute_key(this->node_id(Quad4::side_nodes_map[s][0]),
      78   148815382 :                            this->node_id(Quad4::side_nodes_map[s][1]));
      79             : }
      80             : 
      81             : 
      82             : 
      83    65513642 : unsigned int Quad::local_side_node(unsigned int side,
      84             :                                    unsigned int side_node) const
      85             : {
      86     5782800 :   libmesh_assert_less (side, this->n_sides());
      87     5782800 :   libmesh_assert_less (side_node, Quad4::nodes_per_side);
      88             : 
      89    65513642 :   return Quad4::side_nodes_map[side][side_node];
      90             : }
      91             : 
      92             : 
      93             : 
      94   153171132 : unsigned int Quad::local_edge_node(unsigned int edge,
      95             :                                    unsigned int edge_node) const
      96             : {
      97   153171132 :   return local_side_node(edge, edge_node);
      98             : }
      99             : 
     100             : 
     101             : 
     102           0 : dof_id_type Quad::key () const
     103             : {
     104           0 :   return this->compute_key(this->node_id(0),
     105             :                            this->node_id(1),
     106             :                            this->node_id(2),
     107           0 :                            this->node_id(3));
     108             : }
     109             : 
     110             : 
     111             : 
     112      239886 : std::unique_ptr<Elem> Quad::side_ptr (const unsigned int i)
     113             : {
     114        6674 :   libmesh_assert_less (i, this->n_sides());
     115             : 
     116      239886 :   std::unique_ptr<Elem> edge = std::make_unique<Edge2>();
     117             : 
     118      719658 :   for (auto n : edge->node_index_range())
     119      493120 :     edge->set_node(n, this->node_ptr(Quad4::side_nodes_map[i][n]));
     120             : 
     121      239886 :   return edge;
     122           0 : }
     123             : 
     124             : 
     125             : 
     126   140057957 : void Quad::side_ptr (std::unique_ptr<Elem> & side,
     127             :                      const unsigned int i)
     128             : {
     129   140057957 :   this->simple_side_ptr<Quad,Quad4>(side, i, EDGE2);
     130   140057957 : }
     131             : 
     132             : 
     133             : 
     134    12451391 : bool Quad::is_child_on_side(const unsigned int c,
     135             :                             const unsigned int s) const
     136             : {
     137     8579529 :   libmesh_assert_less (c, this->n_children());
     138     8579529 :   libmesh_assert_less (s, this->n_sides());
     139             : 
     140             :   // A quad's children and nodes don't share the same ordering:
     141             :   // child 2 and 3 are swapped;
     142    12451391 :   unsigned int n = (c < 2) ? c : 5-c;
     143    12451391 :   return (n == s || n == (s+1)%4);
     144             : }
     145             : 
     146             : 
     147             : 
     148           0 : unsigned int Quad::opposite_side(const unsigned int side_in) const
     149             : {
     150           0 :   libmesh_assert_less (side_in, 4);
     151             : 
     152           0 :   return (side_in + 2) % 4;
     153             : }
     154             : 
     155             : 
     156             : 
     157           0 : unsigned int Quad::opposite_node(const unsigned int node_in,
     158             :                                  const unsigned int side_in) const
     159             : {
     160           0 :   libmesh_assert_less (node_in, 8);
     161           0 :   libmesh_assert_less (node_in, this->n_nodes());
     162           0 :   libmesh_assert_less (side_in, this->n_sides());
     163           0 :   libmesh_assert(this->is_node_on_side(node_in, side_in));
     164             : 
     165             :   static const unsigned char side02_nodes_map[] =
     166             :     {3, 2, 1, 0, 6, 255, 4, 255};
     167             :   static const unsigned char side13_nodes_map[] =
     168             :     {1, 0, 3, 2, 255, 7, 255, 5};
     169             : 
     170           0 :   switch (side_in)
     171             :     {
     172           0 :     case 0:
     173             :     case 2:
     174           0 :       return side02_nodes_map[node_in];
     175           0 :     case 1:
     176             :     case 3:
     177           0 :       return side13_nodes_map[node_in];
     178           0 :     default:
     179           0 :       libmesh_error_msg("Unsupported side_in = " << side_in);
     180             :     }
     181             : }
     182             : 
     183             : 
     184        2280 : bool Quad::is_flipped() const
     185             : {
     186             :   return (
     187             : #if LIBMESH_DIM > 2
     188             :           // Don't bother outside the XY plane
     189        2448 :           !this->point(0)(2) && !this->point(1)(2) &&
     190        4728 :           !this->point(2)(2) && !this->point(3)(2) &&
     191             : #endif
     192        2448 :           ((this->point(1)(0)-this->point(0)(0))*
     193        2280 :            (this->point(3)(1)-this->point(0)(1)) <
     194        2448 :            (this->point(3)(0)-this->point(0)(0))*
     195        2448 :            (this->point(1)(1)-this->point(0)(1))));
     196             : }
     197             : 
     198             : 
     199             : std::vector<unsigned int>
     200       14624 : Quad::edges_adjacent_to_node(const unsigned int n) const
     201             : {
     202         968 :   libmesh_assert_less(n, this->n_nodes());
     203             : 
     204             :   // For vertices, we use the Quad::adjacent_sides_map, otherwise each
     205             :   // of the mid-edge nodes is adjacent only to the edge it is on, and the
     206             :   // center node is not adjacent to any edge.
     207       14624 :   if (this->is_vertex(n))
     208       10912 :     return {std::begin(adjacent_sides_map[n]), std::end(adjacent_sides_map[n])};
     209        4320 :   else if (this->is_edge(n))
     210        3840 :     return {n - this->n_vertices()};
     211             : 
     212          40 :   libmesh_assert(this->is_face(n));
     213         440 :   return {};
     214             : }
     215             : 
     216        3783 : Real Quad::quality (const ElemQuality q) const
     217             : {
     218        3783 :   switch (q)
     219             :     {
     220             :       // The EDGE_LENGTH_RATIO metric is handled by the base class.
     221             :       //
     222             :       // The CUBIT 15.1 User Documentation refers to the
     223             :       // EDGE_LENGTH_RATIO as the "Aspect Ratio" metric for Quads,
     224             :       // however, we prefer the slightly more robust aspect ratio
     225             :       // formula employed by Ansys, and have therefore designated that
     226             :       // as our ASPECT_RATIO metric here.
     227             :       //
     228             :       // As a counter-example for employing the EDGE_LENGTH_RATIO in
     229             :       // Quads, consider a "rhombus". All four side lengths are equal,
     230             :       // so the EDGE_LENGTH_RATIO of this element is always (the
     231             :       // optimal value) 1.0, regardless of the internal angle "theta"
     232             :       // of the rhombus. A more sensitive shape quality metric should
     233             :       // take this internal angle into account, so that very thin
     234             :       // rhombus-shaped Quads are not considered optimal.
     235             : 
     236         781 :     case ASPECT_RATIO:
     237             :       {
     238             :         // Aspect Ratio definition from Ansys Theory Manual.
     239             :         // Reference: Ansys, Inc. Theory Reference, Ansys Release 9.0, 2004 (Chapter: 13.7.3)
     240             :         //
     241             :         // For the rhombus case described above, the aspect ratio of
     242             :         // the element using the Ansys Aspect Ratio metric is
     243             :         // 1/sin(theta), where theta is the acute interior angle of
     244             :         // the rhombus. The aspect ratio therefore has a minimum value
     245             :         // of 1.0 (when theta = pi/2), and blows up to infinity as
     246             :         // sin(theta) -> 0, rather than remaining equal to 1.0 as in
     247             :         // the CUBIT formula.
     248             : 
     249             :         // Compute midpoint positions along each edge
     250          44 :         Point m0 = Real(0.5) * (this->point(0) + this->point(1));
     251          22 :         Point m1 = Real(0.5) * (this->point(1) + this->point(2));
     252          22 :         Point m2 = Real(0.5) * (this->point(2) + this->point(3));
     253          22 :         Point m3 = Real(0.5) * (this->point(3) + this->point(0));
     254             : 
     255             :         // Compute vectors adjoining opposite side midpoints
     256          22 :         Point v0 = m2 - m0;
     257          22 :         Point v1 = m1 - m3;
     258             : 
     259             :         // Compute the length of the midlines
     260         781 :         Real v0_norm = v0.norm();
     261         781 :         Real v1_norm = v1.norm();
     262             : 
     263             :         // Instead of dividing by zero in the next step, just return
     264             :         // 0.  The optimal aspect ratio is 1.0, and "high" aspect
     265             :         // ratios are bad, but an aspect ratio of 0 should also be
     266             :         // considered bad.
     267         781 :         if (v0_norm == 0. || v1_norm == 0.)
     268           0 :           return 0.;
     269             : 
     270             :         // Compute sine of the angle between v0, v1. For rectangular
     271             :         // elements, sin_theta == 1.
     272         781 :         Real sin_theta = cross_norm(v0, v1) / v0_norm / v1_norm;
     273         781 :         Real v0s = v0_norm*sin_theta;
     274         781 :         Real v1s = v1_norm*sin_theta;
     275             : 
     276             :         // Determine the min, max of each midline length and its
     277             :         // projection.
     278             :         //
     279             :         // Note: The return values min{0,1} and max{0,1} here are
     280             :         // *references* and we cannot pass a temporary to
     281             :         // std::minmax() since the reference returned becomes a
     282             :         // dangling reference at "the end of the full expression that
     283             :         // contains the call to std::minmax()"
     284             :         // https://en.cppreference.com/w/cpp/algorithm/minmax
     285          22 :         auto [min0, max0] = std::minmax(v0_norm, v1s);
     286          22 :         auto [min1, max1] = std::minmax(v0s, v1_norm);
     287             : 
     288             :         // Return the max of the two quotients
     289         919 :         return std::max(max0/min0, max1/min1);
     290             :       }
     291             : 
     292             :       // Compute the min/max diagonal ratio.
     293             :       // This is modeled after the Hex element
     294           0 :     case DISTORTION:
     295             :     case DIAGONAL:
     296             :       {
     297             :         // Diagonal between node 0 and node 2
     298           0 :         const Real d02 = this->length(0,2);
     299             : 
     300             :         // Diagonal between node 1 and node 3
     301           0 :         const Real d13 = this->length(1,3);
     302             : 
     303             :         // Find the biggest and smallest diagonals
     304           0 :         if ((d02 > 0.) && (d13 >0.))
     305           0 :           if (d02 < d13) return d02 / d13;
     306           0 :           else return d13 / d02;
     307             :         else
     308           0 :           return 0.;
     309             :         break;
     310             :       }
     311             : 
     312             :       // CUBIT 15.1 User Documentation:
     313             :       // Stretch: Sqrt(2) * minimum edge length / maximum diagonal length
     314           0 :     case STRETCH:
     315             :       {
     316           0 :         Real lengths[4] = {this->length(0,1), this->length(1,2), this->length(2,3), this->length(3,0)};
     317           0 :         Real min_edge = *std::min_element(lengths, lengths+4);
     318           0 :         Real d_max = std::max(this->length(0,2), this->length(1,3));
     319             : 
     320             :         // Return 0. instead of dividing by zero.
     321           0 :         if (d_max == 0.)
     322           0 :           return 0.;
     323             :         else
     324           0 :           return std::sqrt(2) * min_edge / d_max;
     325             :       }
     326             : 
     327           0 :     case SHAPE:
     328             :     case SKEW:
     329             :       {
     330             :         // From: P. Knupp, "Algebraic mesh quality metrics for
     331             :         // unstructured initial meshes," Finite Elements in Analysis
     332             :         // and Design 39, 2003, p. 217-241, Sections 5.2 and 5.3.
     333             :         typedef std::array<Real, 4> Array4;
     334             :         typedef std::array<Real, 6> Array6;
     335             : 
     336             :         // x, y, z node coordinates.
     337             :         std::vector<Real>
     338           0 :           x = {this->point(0)(0), this->point(1)(0), this->point(2)(0), this->point(3)(0)},
     339           0 :           y = {this->point(0)(1), this->point(1)(1), this->point(2)(1), this->point(3)(1)},
     340           0 :           z = {this->point(0)(2), this->point(1)(2), this->point(2)(2), this->point(3)(2)};
     341             : 
     342             :         // Nodal Jacobians. These are 3x2 matrices, hence we represent
     343             :         // them by Array6.
     344             :         std::array<Array6, 4> A;
     345           0 :         for (unsigned int k=0; k<4; ++k)
     346             :           {
     347             :             unsigned int
     348           0 :               kp1 = k+1 > 3 ? k+1-4 : k+1,
     349           0 :               kp3 = k+3 > 3 ? k+3-4 : k+3;
     350             : 
     351             :             // To initialize std::array we need double curly braces in
     352             :             // C++11 but not C++14 apparently.
     353           0 :             A[k] = {{x[kp1] - x[k], x[kp3] - x[k],
     354           0 :                      y[kp1] - y[k], y[kp3] - y[k],
     355           0 :                      z[kp1] - z[k], z[kp3] - z[k]}};
     356             :           }
     357             : 
     358             :         // Compute metric tensors, T_k = A_k^T * A_k. These are 2x2
     359             :         // square matrices, hence we represent them by Array4.
     360             :         std::array<Array4, 4> T;
     361           0 :         for (unsigned int k=0; k<4; ++k)
     362             :           {
     363             :             Real
     364           0 :               top_left = A[k][0]*A[k][0] + A[k][2]*A[k][2] + A[k][4]*A[k][4],
     365           0 :               off_diag = A[k][0]*A[k][1] + A[k][2]*A[k][3] + A[k][4]*A[k][5],
     366           0 :               bot_rigt = A[k][1]*A[k][1] + A[k][3]*A[k][3] + A[k][5]*A[k][5];
     367             : 
     368           0 :             T[k] = {{top_left, off_diag,
     369             :                      off_diag, bot_rigt}};
     370             :           }
     371             : 
     372             : 
     373             :         // Nodal areas. These are approximated as sqrt(det(A^T * A))
     374             :         // to handle the general case of a 2D element living in 3D.
     375             :         Array4 alpha;
     376           0 :         for (unsigned int k=0; k<4; ++k)
     377           0 :           alpha[k] = std::sqrt(T[k][0]*T[k][3] - T[k][1]*T[k][2]);
     378             : 
     379             :         // All nodal areas must be strictly positive. Return 0 (the
     380             :         // lowest quality) otherwise. We know they can't be negative
     381             :         // because they are the result of a sqrt, but they might be
     382             :         // identically 0.
     383           0 :         if (*std::min_element(alpha.begin(), alpha.end()) == 0.)
     384           0 :           return 0.;
     385             : 
     386             :         // Compute and return the shape metric. These only use the
     387             :         // diagonal entries of the T_k.
     388           0 :         Real den = 0.;
     389           0 :         if (q == SHAPE)
     390             :           {
     391           0 :             for (unsigned int k=0; k<4; ++k)
     392           0 :               den += (T[k][0] + T[k][3]) / alpha[k];
     393           0 :             return (den == 0.) ? 0 : (8. / den);
     394             :           }
     395             :         else
     396             :           {
     397           0 :             for (unsigned int k=0; k<4; ++k)
     398           0 :               den += std::sqrt(T[k][0] * T[k][3]) / alpha[k];
     399           0 :             return (den == 0.) ? 0 : (4. / den);
     400             :           }
     401             :       }
     402             : 
     403             :       // This test returns 0 if a Quad:
     404             :       // 1) Is "twisted" (i.e. has an invalid numbering)
     405             :       // 2) Has nearly parallel adjacent edges
     406             :       // 3) Has a nearly zero length edge
     407             :       // Otherwise, it returns 1.
     408           0 :     case TWIST:
     409             :       {
     410             :         // Compute the cross product induced by each "corner" of the QUAD
     411             :         // and check that:
     412             :         // 1) None of the cross products are zero (within a tolernace), and
     413             :         // 2) all of the cross products point in the same direction.
     414             : 
     415             :         // Corner 0
     416           0 :         Point vec_01 = point(1) - point(0);
     417           0 :         Point vec_03 = point(3) - point(0);
     418           0 :         Point corner_0_vec = vec_01.cross(vec_03);
     419             : 
     420             :         // Corner 1
     421           0 :         Point vec_12 = point(2) - point(1);
     422           0 :         Point vec_10 = point(0) - point(1);
     423           0 :         Point corner_1_vec = vec_12.cross(vec_10);
     424             : 
     425             :         // Corner 2
     426           0 :         Point vec_23 = point(3) - point(2);
     427           0 :         Point vec_21 = point(1) - point(2);
     428           0 :         Point corner_2_vec = vec_23.cross(vec_21);
     429             : 
     430             :         // Corner 3
     431           0 :         Point vec_30 = point(0) - point(3);
     432           0 :         Point vec_32 = point(2) - point(3);
     433           0 :         Point corner_3_vec = vec_30.cross(vec_32);
     434             : 
     435             :         // If any of these cross products is nearly zero, then either
     436             :         // we have nearly parallel adjacent edges or a nearly zero
     437             :         // length edge. We return 0 in this case.
     438           0 :         if ((corner_0_vec.norm() < TOLERANCE*TOLERANCE) ||
     439           0 :             (corner_1_vec.norm() < TOLERANCE*TOLERANCE) ||
     440           0 :             (corner_2_vec.norm() < TOLERANCE*TOLERANCE) ||
     441           0 :             (corner_3_vec.norm() < TOLERANCE*TOLERANCE))
     442             :           {
     443           0 :             return 0.;
     444             :           }
     445             : 
     446             :         // Now check whether the element is twisted.
     447           0 :         Real dot_01 = corner_0_vec * corner_1_vec;
     448           0 :         Real dot_02 = corner_0_vec * corner_2_vec;
     449           0 :         Real dot_03 = corner_0_vec * corner_3_vec;
     450             : 
     451           0 :         if ((dot_01 <= 0.) || (dot_02 <= 0.) || (dot_03 <= 0.))
     452           0 :           return 0.;
     453             : 
     454             :         // If we made it here, then Elem is not twisted.
     455           0 :         return 1.;
     456             :       }
     457             : 
     458         426 :     case WARP:
     459             :       {
     460             :         // We compute the angle between the two planes formed by
     461             :         // drawing an imaginary diagonal separating opposite vertices
     462             :         // A and B, where (A,B) = (0,2) and (1,3). The element warpage
     463             :         // is then taken to be the smaller of these two angles. For a
     464             :         // flat quadrilateral, the planes are parallel, thus the angle
     465             :         // between them is zero, and the element warpage is therefore
     466             :         // 1.
     467             :         //
     468             :         // Reference: https://cubit.sandia.gov/files/cubit/16.08/help_manual/WebHelp/mesh_generation/mesh_quality_assessment/quadrilateral_metrics.htm
     469             :         Point
     470         438 :           n0 = (this->point(1) - this->point(0)).cross(this->point(3) - this->point(0)).unit(),
     471         438 :           n1 = (this->point(2) - this->point(1)).cross(this->point(0) - this->point(1)).unit(),
     472         438 :           n2 = (this->point(3) - this->point(2)).cross(this->point(1) - this->point(2)).unit(),
     473         438 :           n3 = (this->point(0) - this->point(3)).cross(this->point(2) - this->point(3)).unit();
     474             : 
     475         576 :         return std::min(n0*n2, n1*n3);
     476             :       }
     477             : 
     478        2576 :     default:
     479        2576 :       return Elem::quality(q);
     480             :     }
     481             : }
     482             : 
     483             : 
     484             : 
     485             : 
     486             : 
     487             : 
     488           0 : std::pair<Real, Real> Quad::qual_bounds (const ElemQuality q) const
     489             : {
     490           0 :   std::pair<Real, Real> bounds;
     491             : 
     492           0 :   switch (q)
     493             :     {
     494           0 :     case EDGE_LENGTH_RATIO:
     495             :     case ASPECT_RATIO:
     496           0 :       bounds.first  = 1.;
     497           0 :       bounds.second = 4.;
     498           0 :       break;
     499             : 
     500           0 :     case TAPER:
     501           0 :       bounds.first  = 0.;
     502           0 :       bounds.second = 0.7;
     503           0 :       break;
     504             : 
     505           0 :     case WARP:
     506           0 :       bounds.first  = 0.9;
     507           0 :       bounds.second = 1.;
     508           0 :       break;
     509             : 
     510           0 :     case STRETCH:
     511           0 :       bounds.first  = 0.25;
     512           0 :       bounds.second = 1.;
     513           0 :       break;
     514             : 
     515           0 :     case MIN_ANGLE:
     516           0 :       bounds.first  = 45.;
     517           0 :       bounds.second = 90.;
     518           0 :       break;
     519             : 
     520           0 :     case MAX_ANGLE:
     521           0 :       bounds.first  = 90.;
     522           0 :       bounds.second = 135.;
     523           0 :       break;
     524             : 
     525           0 :     case CONDITION:
     526           0 :       bounds.first  = 1.;
     527           0 :       bounds.second = 4.;
     528           0 :       break;
     529             : 
     530           0 :     case JACOBIAN:
     531             :     case SCALED_JACOBIAN:
     532           0 :       bounds.first  = 0.5;
     533           0 :       bounds.second = 1.;
     534           0 :       break;
     535             : 
     536           0 :     case SHEAR:
     537             :     case SHAPE:
     538             :     case SKEW:
     539             :     case SIZE:
     540           0 :       bounds.first  = 0.3;
     541           0 :       bounds.second = 1.;
     542           0 :       break;
     543             : 
     544           0 :     case DISTORTION:
     545           0 :       bounds.first  = 0.6;
     546           0 :       bounds.second = 1.;
     547           0 :       break;
     548             : 
     549           0 :     case TWIST:
     550           0 :       bounds.first  = 0.;
     551           0 :       bounds.second = 1.;
     552           0 :       break;
     553             : 
     554           0 :     default:
     555           0 :       libMesh::out << "Warning: Invalid quality measure chosen." << std::endl;
     556           0 :       bounds.first  = -1;
     557           0 :       bounds.second = -1;
     558             :     }
     559             : 
     560           0 :   return bounds;
     561             : }
     562             : 
     563             : 
     564             : 
     565    12432592 : bool Quad::on_reference_element(const Point & p,
     566             :                                 const Real eps) const
     567             : {
     568     1874831 :   const Real & xi = p(0);
     569     1874831 :   const Real & eta = p(1);
     570             : 
     571             :   // The reference quadrilateral element is [-1,1]^2.
     572    22801869 :   return ((xi  >= -1.-eps) &&
     573    10369277 :           (xi  <=  1.+eps) &&
     574    22362737 :           (eta >= -1.-eps) &&
     575    14063208 :           (eta <=  1.+eps));
     576             : }
     577             : 
     578             : 
     579             : 
     580             : const unsigned short int Quad::_second_order_adjacent_vertices[4][2] =
     581             :   {
     582             :     {0, 1}, // vertices adjacent to node 4
     583             :     {1, 2}, // vertices adjacent to node 5
     584             :     {2, 3}, // vertices adjacent to node 6
     585             :     {0, 3}  // vertices adjacent to node 7
     586             :   };
     587             : 
     588             : 
     589             : 
     590             : const unsigned short int Quad::_second_order_vertex_child_number[9] =
     591             :   {
     592             :     99,99,99,99, // Vertices
     593             :     0,1,2,0,     // Edges
     594             :     0            // Interior
     595             :   };
     596             : 
     597             : 
     598             : 
     599             : const unsigned short int Quad::_second_order_vertex_child_index[9] =
     600             :   {
     601             :     99,99,99,99, // Vertices
     602             :     1,2,3,3,     // Edges
     603             :     2            // Interior
     604             :   };
     605             : 
     606             : 
     607             : 
     608             : #ifdef LIBMESH_ENABLE_AMR
     609             : 
     610             : // We number 25 "possible node locations" for a 2x2 refinement of
     611             : // quads with up to 3x3 nodes each
     612             : const int Quad::_child_node_lookup[4][9] =
     613             :   {
     614             :     // node lookup for child 0 (near node 0)
     615             :     { 0, 2, 12, 10,  1, 7, 11, 5,  6},
     616             : 
     617             :     // node lookup for child 1 (near node 1)
     618             :     { 2, 4, 14, 12,  3, 9, 13, 7,  8},
     619             : 
     620             :     // node lookup for child 2 (near node 3)
     621             :     { 10, 12, 22, 20,  11, 17, 21, 15,  16},
     622             : 
     623             :     // node lookup for child 3 (near node 2)
     624             :     { 12, 14, 24, 22,  13, 19, 23, 17,  18}
     625             :   };
     626             : 
     627             : 
     628             : #endif
     629             : 
     630             : } // namespace libMesh

Generated by: LCOV version 1.14