MFEM v2.0
|
00001 // Copyright (c) 2010, Lawrence Livermore National Security, LLC. Produced at 00002 // the Lawrence Livermore National Laboratory. LLNL-CODE-443211. All Rights 00003 // reserved. See file COPYRIGHT for details. 00004 // 00005 // This file is part of the MFEM library. For more information and source code 00006 // availability see http://mfem.googlecode.com. 00007 // 00008 // MFEM is free software; you can redistribute it and/or modify it under the 00009 // terms of the GNU Lesser General Public License (as published by the Free 00010 // Software Foundation) version 2.1 dated February 1999. 00011 00012 // Implementation of class Tetrahedron 00013 00014 #include "mesh_headers.hpp" 00015 #include <math.h> 00016 00017 const int Tetrahedron::edges[6][2] = 00018 {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}}; 00019 00020 void Tetrahedron::ParseRefinementFlag(int refinement_edges[2], int &type, 00021 int &flag) 00022 { 00023 int i, f = refinement_flag; 00024 00025 if (f == 0) 00026 mfem_error("Tetrahedron::ParseRefinementFlag :" 00027 " tetrahedron is not marked"); 00028 00029 for (i = 0; i < 2; i++) 00030 { 00031 refinement_edges[i] = f & 7; 00032 f = f >> 3; 00033 } 00034 type = f & 7; 00035 flag = (f >> 3); 00036 } 00037 00038 void Tetrahedron::CreateRefinementFlag(int refinement_edges[2], int type, 00039 int flag) 00040 { 00041 // Check for correct type 00042 #ifdef MFEM_DEBUG 00043 int e1, e2; 00044 e1 = refinement_edges[0]; 00045 e2 = refinement_edges[1]; 00046 // if (e1 > e2) e1 = e2, e2 = refinement_edges[0]; 00047 switch (type) 00048 { 00049 case Tetrahedron::TYPE_PU: 00050 if (e1 == 2 && e2 == 1) break; 00051 // if (e1 == 3 && e2 == 4) break; 00052 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #1"); 00053 break; 00054 case Tetrahedron::TYPE_A: 00055 if (e1 == 3 && e2 == 1) break; 00056 if (e1 == 2 && e2 == 4) break; 00057 // if (flag == 0) // flag is assumed to be the generation 00058 // if (e2 == 5) 00059 // if (e1 >= 1 && e1 <= 5) break; // type is actually O or M 00060 // // ==> ok for generation = 0 00061 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #2"); 00062 break; 00063 case Tetrahedron::TYPE_PF: 00064 if (flag > 0) // PF is ok only for generation > 0 00065 { 00066 if (e1 == 2 && e2 == 1) break; 00067 // if (e1 == 3 && e2 == 4) break; 00068 } 00069 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #3"); 00070 break; 00071 case Tetrahedron::TYPE_O: 00072 if (flag == 0 && e1 == 5 && e2 == 5) 00073 break; 00074 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #4"); 00075 break; 00076 case Tetrahedron::TYPE_M: 00077 if (flag == 0) 00078 { 00079 if (e1 == 5 && e2 == 1) break; 00080 if (e1 == 2 && e2 == 5) break; 00081 } 00082 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #5"); 00083 break; 00084 default: 00085 mfem_error("Error in Tetrahedron::CreateRefinementFlag(...) #6"); 00086 break; 00087 } 00088 #endif 00089 00090 refinement_flag = flag; 00091 refinement_flag = refinement_flag << 3; 00092 00093 refinement_flag = refinement_flag | type; 00094 refinement_flag = refinement_flag << 3; 00095 00096 refinement_flag = refinement_flag | refinement_edges[1]; 00097 refinement_flag = refinement_flag << 3; 00098 00099 refinement_flag = refinement_flag | refinement_edges[0]; 00100 } 00101 00102 Tetrahedron::Tetrahedron(int *ind, int attr) : Element(Geometry::TETRAHEDRON) 00103 { 00104 attribute = attr; 00105 for (int i = 0; i < 4; i++) 00106 indices[i] = ind[i]; 00107 refinement_flag = 0; 00108 } 00109 00110 Tetrahedron::Tetrahedron(int ind1, int ind2, int ind3, int ind4, int attr) 00111 : Element(Geometry::TETRAHEDRON) 00112 { 00113 attribute = attr; 00114 indices[0] = ind1; 00115 indices[1] = ind2; 00116 indices[2] = ind3; 00117 indices[3] = ind4; 00118 refinement_flag = 0; 00119 } 00120 00121 int Tetrahedron::NeedRefinement(DSTable &v_to_v, int *middle) const 00122 { 00123 int m; 00124 00125 if ((m = v_to_v(indices[0], indices[1])) != -1) 00126 if (middle[m] != -1) return 1; 00127 if ((m = v_to_v(indices[1], indices[2])) != -1) 00128 if (middle[m] != -1) return 1; 00129 if ((m = v_to_v(indices[2], indices[0])) != -1) 00130 if (middle[m] != -1) return 1; 00131 if ((m = v_to_v(indices[0], indices[3])) != -1) 00132 if (middle[m] != -1) return 1; 00133 if ((m = v_to_v(indices[1], indices[3])) != -1) 00134 if (middle[m] != -1) return 1; 00135 if ((m = v_to_v(indices[2], indices[3])) != -1) 00136 if (middle[m] != -1) return 1; 00137 return 0; 00138 } 00139 00140 void Tetrahedron::SetVertices(const int *ind) 00141 { 00142 for (int i = 0; i < 4; i++) 00143 indices[i] = ind[i]; 00144 } 00145 00146 void Tetrahedron::MarkEdge(const DSTable &v_to_v, const int *length) 00147 { 00148 int ind[4], i, j, l, L, type; 00149 00150 // determine the longest edge 00151 L = length[v_to_v(indices[0], indices[1])]; j = 0; 00152 if ((l = length[v_to_v(indices[1], indices[2])]) > L) { L = l; j = 1; } 00153 if ((l = length[v_to_v(indices[2], indices[0])]) > L) { L = l; j = 2; } 00154 if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; j = 3; } 00155 if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; j = 4; } 00156 if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; j = 5; } 00157 00158 for (i = 0; i < 4; i++) 00159 ind[i] = indices[i]; 00160 00161 switch (j) 00162 { 00163 case 1: 00164 indices[0] = ind[1]; indices[1] = ind[2]; 00165 indices[2] = ind[0]; indices[3] = ind[3]; 00166 break; 00167 case 2: 00168 indices[0] = ind[2]; indices[1] = ind[0]; 00169 indices[2] = ind[1]; indices[3] = ind[3]; 00170 break; 00171 case 3: 00172 indices[0] = ind[3]; indices[1] = ind[0]; 00173 indices[2] = ind[2]; indices[3] = ind[1]; 00174 break; 00175 case 4: 00176 indices[0] = ind[1]; indices[1] = ind[3]; 00177 indices[2] = ind[2]; indices[3] = ind[0]; 00178 break; 00179 case 5: 00180 indices[0] = ind[2]; indices[1] = ind[3]; 00181 indices[2] = ind[0]; indices[3] = ind[1]; 00182 break; 00183 } 00184 00185 // Determine the two longest edges for the other two faces and 00186 // store them in ind[0] and ind[1] 00187 ind[0] = 2; ind[1] = 1; 00188 L = length[v_to_v(indices[0], indices[2])]; 00189 if ((l = length[v_to_v(indices[0], indices[3])]) > L) { L = l; ind[0] = 3; } 00190 if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[0] = 5; } 00191 00192 L = length[v_to_v(indices[1], indices[2])]; 00193 if ((l = length[v_to_v(indices[1], indices[3])]) > L) { L = l; ind[1] = 4; } 00194 if ((l = length[v_to_v(indices[2], indices[3])]) > L) { L = l; ind[1] = 5; } 00195 00196 j = 0; 00197 switch (ind[0]) 00198 { 00199 case 2: 00200 switch (ind[1]) 00201 { 00202 case 1: type = Tetrahedron::TYPE_PU; break; 00203 case 4: type = Tetrahedron::TYPE_A; break; 00204 case 5: type = Tetrahedron::TYPE_M; 00205 } 00206 break; 00207 case 3: 00208 switch (ind[1]) 00209 { 00210 case 1: type = Tetrahedron::TYPE_A; break; 00211 case 4: type = Tetrahedron::TYPE_PU; 00212 j = 1; ind[0] = 2; ind[1] = 1; break; 00213 case 5: type = Tetrahedron::TYPE_M; 00214 j = 1; ind[0] = 5; ind[1] = 1; 00215 } 00216 break; 00217 case 5: 00218 switch (ind[1]) 00219 { 00220 case 1: type = Tetrahedron::TYPE_M; break; 00221 case 4: type = Tetrahedron::TYPE_M; 00222 j = 1; ind[0] = 2; ind[1] = 5; break; 00223 case 5: type = Tetrahedron::TYPE_O; 00224 } 00225 } 00226 00227 if (j) 00228 { 00229 j = indices[0]; indices[0] = indices[1]; indices[1] = j; 00230 j = indices[2]; indices[2] = indices[3]; indices[3] = j; 00231 } 00232 00233 CreateRefinementFlag(ind, type); 00234 } 00235 00236 void Tetrahedron::GetVertices(Array<int> &v) const 00237 { 00238 v.SetSize(4); 00239 for (int i = 0; i < 4; i++) 00240 { 00241 v[i] = indices[i]; 00242 } 00243 } 00244 00245 Element *Tetrahedron::Duplicate(Mesh *m) const 00246 { 00247 #ifdef MFEM_USE_MEMALLOC 00248 Tetrahedron *tet = m->TetMemory.Alloc(); 00249 #else 00250 Tetrahedron *tet = new Tetrahedron; 00251 #endif 00252 tet->SetVertices(indices); 00253 tet->SetAttribute(attribute); 00254 tet->SetRefinementFlag(refinement_flag); 00255 return tet; 00256 } 00257 00258 Linear3DFiniteElement TetrahedronFE;