cell_tet.C
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 // C++ includes 00020 00021 // Local includes 00022 #include "libmesh/cell_tet.h" 00023 #include "libmesh/cell_tet4.h" 00024 #include "libmesh/face_tri3.h" 00025 00026 namespace libMesh 00027 { 00028 00029 00030 00031 // ------------------------------------------------------------ 00032 // Tet class member functions 00033 dof_id_type Tet::key (const unsigned int s) const 00034 { 00035 libmesh_assert_less (s, this->n_sides()); 00036 00037 switch (s) 00038 { 00039 case 0: 00040 return 00041 this->compute_key (this->node(0), 00042 this->node(2), 00043 this->node(1)); 00044 00045 case 1: 00046 return 00047 this->compute_key (this->node(0), 00048 this->node(1), 00049 this->node(3)); 00050 00051 case 2: 00052 return 00053 this->compute_key (this->node(1), 00054 this->node(2), 00055 this->node(3)); 00056 00057 case 3: 00058 return 00059 this->compute_key (this->node(2), 00060 this->node(0), 00061 this->node(3)); 00062 } 00063 00064 // We'll never get here. 00065 libmesh_error(); 00066 return 0; 00067 } 00068 00069 00070 00071 AutoPtr<Elem> Tet::side (const unsigned int i) const 00072 { 00073 libmesh_assert_less (i, this->n_sides()); 00074 00075 00076 00077 Elem* face = new Tri3; 00078 00079 switch (i) 00080 { 00081 case 0: 00082 { 00083 face->set_node(0) = this->get_node(0); 00084 face->set_node(1) = this->get_node(2); 00085 face->set_node(2) = this->get_node(1); 00086 00087 AutoPtr<Elem> ap_face(face); 00088 return ap_face; 00089 } 00090 case 1: 00091 { 00092 face->set_node(0) = this->get_node(0); 00093 face->set_node(1) = this->get_node(1); 00094 face->set_node(2) = this->get_node(3); 00095 00096 AutoPtr<Elem> ap_face(face); 00097 return ap_face; 00098 } 00099 case 2: 00100 { 00101 face->set_node(0) = this->get_node(1); 00102 face->set_node(1) = this->get_node(2); 00103 face->set_node(2) = this->get_node(3); 00104 00105 AutoPtr<Elem> ap_face(face); 00106 return ap_face; 00107 } 00108 case 3: 00109 { 00110 face->set_node(0) = this->get_node(2); 00111 face->set_node(1) = this->get_node(0); 00112 face->set_node(2) = this->get_node(3); 00113 00114 AutoPtr<Elem> ap_face(face); 00115 return ap_face; 00116 } 00117 default: 00118 { 00119 libmesh_error(); 00120 } 00121 } 00122 00123 // We'll never get here. 00124 libmesh_error(); 00125 AutoPtr<Elem> ap_face(face); 00126 return ap_face; 00127 } 00128 00129 00130 void Tet::select_diagonal (const Diagonal diag) const 00131 { 00132 libmesh_assert_equal_to (_diagonal_selection, INVALID_DIAG); 00133 _diagonal_selection = diag; 00134 } 00135 00136 00137 00138 00139 00140 #ifdef LIBMESH_ENABLE_AMR 00141 00142 00143 bool Tet::is_child_on_side_helper(const unsigned int c, 00144 const unsigned int s, 00145 const unsigned int checked_nodes[][3]) const 00146 { 00147 libmesh_assert_less (c, this->n_children()); 00148 libmesh_assert_less (s, this->n_sides()); 00149 00150 // For the 4 vertices, child c touches vertex c, so we can return 00151 // true if that vertex is on side s 00152 for (unsigned int i = 0; i != 3; ++i) 00153 if (Tet4::side_nodes_map[s][i] == c) 00154 return true; 00155 00156 // If we are a "vertex child" and we didn't already return true, 00157 // we must not be on the side in question 00158 if (c < 4) 00159 return false; 00160 00161 // For the 4 non-vertex children, the child ordering depends on the 00162 // diagonal selection. We'll let the embedding matrix figure that 00163 // out: if this child has three nodes that don't depend on the 00164 // position of the node_facing_side[s], then we're on side s. Which 00165 // three nodes those are depends on the subclass, so their responsibility 00166 // is to call this function with the proper check_nodes array 00167 const unsigned int node_facing_side[4] = {3, 2, 0, 1}; 00168 const unsigned int n = node_facing_side[s]; 00169 00170 // Add up the absolute values of the entries of the embedding matrix for the 00171 // nodes opposite node n. If it is equal to zero, then the child in question is 00172 // on side s, so return true. 00173 Real embedding_sum = 0.; 00174 for (unsigned i=0; i<3; ++i) 00175 embedding_sum += std::abs(this->embedding_matrix(c, checked_nodes[n][i], n)); 00176 00177 return ( std::abs(embedding_sum) < 1.e-3 ); 00178 } 00179 00180 #else 00181 00182 bool Tet::is_child_on_side_helper(const unsigned int /*c*/, 00183 const unsigned int /*s*/, 00184 const unsigned int /*checked_nodes*/[][3]) const 00185 { 00186 libmesh_not_implemented(); 00187 return false; 00188 } 00189 00190 #endif //LIBMESH_ENABLE_AMR 00191 00192 00193 00194 00195 void Tet::choose_diagonal() const 00196 { 00197 // Check for uninitialized diagonal selection 00198 if (this->_diagonal_selection==INVALID_DIAG) 00199 { 00200 Real diag_01_23 = (this->point(0)+this->point(1)-this->point(2)-this->point(3)).size_sq(); 00201 Real diag_02_13 = (this->point(0)-this->point(1)+this->point(2)-this->point(3)).size_sq(); 00202 Real diag_03_12 = (this->point(0)-this->point(1)-this->point(2)+this->point(3)).size_sq(); 00203 00204 this->_diagonal_selection=DIAG_02_13; 00205 00206 if (diag_01_23 < diag_02_13 || diag_03_12 < diag_02_13) 00207 { 00208 if (diag_01_23 < diag_03_12) 00209 this->_diagonal_selection=DIAG_01_23; 00210 00211 else 00212 this->_diagonal_selection=DIAG_03_12; 00213 } 00214 } 00215 } 00216 00217 00218 00219 bool Tet::is_edge_on_side(const unsigned int e, 00220 const unsigned int s) const 00221 { 00222 libmesh_assert_less (e, this->n_edges()); 00223 libmesh_assert_less (s, this->n_sides()); 00224 00225 return (is_node_on_side(Tet4::edge_nodes_map[e][0],s) && 00226 is_node_on_side(Tet4::edge_nodes_map[e][1],s)); 00227 } 00228 00229 00230 00231 Real Tet::quality(const ElemQuality q) const 00232 { 00233 return Elem::quality(q); // Not implemented 00234 } 00235 00236 00237 00238 00239 std::pair<Real, Real> Tet::qual_bounds (const ElemQuality q) const 00240 { 00241 std::pair<Real, Real> bounds; 00242 00243 switch (q) 00244 { 00245 00246 case ASPECT_RATIO_BETA: 00247 case ASPECT_RATIO_GAMMA: 00248 bounds.first = 1.; 00249 bounds.second = 3.; 00250 break; 00251 00252 case SIZE: 00253 case SHAPE: 00254 bounds.first = 0.2; 00255 bounds.second = 1.; 00256 break; 00257 00258 case CONDITION: 00259 bounds.first = 1.; 00260 bounds.second = 3.; 00261 break; 00262 00263 case DISTORTION: 00264 bounds.first = 0.6; 00265 bounds.second = 1.; 00266 break; 00267 00268 case JACOBIAN: 00269 bounds.first = 0.5; 00270 bounds.second = 1.414; 00271 break; 00272 00273 default: 00274 libMesh::out << "Warning: Invalid quality measure chosen." << std::endl; 00275 bounds.first = -1; 00276 bounds.second = -1; 00277 } 00278 00279 return bounds; 00280 } 00281 00282 } // namespace libMesh
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:45 UTC
Hosted By: