![]() |
TAPs 0.7.7.3
|
00001 /****************************************************************************** 00002 TAPsFEMMeshTetrahedraGen.cpp 00003 ******************************************************************************/ 00007 /****************************************************************************** 00008 SUKITTI PUNAK (12/15/2009) 00009 UPDATE (04/16/2010) 00010 ******************************************************************************/ 00011 #include "TAPsFEMMeshTetrahedraGen.hpp" 00012 // Using Inclusion Model (i.e. definitions are included in declarations) 00013 // (this name.cpp is included in name.hpp) 00014 // Each friend is defined directly inside its declaration. 00015 00016 BEGIN_NAMESPACE_TAPs__FEM 00017 //============================================================================= 00018 //template <typename T> std::vector< Tetrahedron<T> > * MeshTetrahedraGen<T>::m_pListOfElements = NULL; 00019 //template <typename T> std::vector< Vector3<T> > * MeshTetrahedraGen<T>::m_pListOfDeformedMeshNodes = NULL; 00020 //template <typename T> std::vector< Vector3<T> > * MeshTetrahedraGen<T>::m_pListOfUndeformedMeshNodes = NULL; 00021 //----------------------------------------------------------------------------- 00022 00024 //template <typename T> 00025 //void MeshTetrahedraGen<T>::SetAccessors ( MeshTetrahedra<T> & rTetFemMesh ) 00026 //{ 00027 // m_pListOfElements = &( rTetFemMesh.RetListOfElements() ); 00028 // m_pListOfDeformedMeshNodes = &( rTetFemMesh.RetListOfDeformedMeshNodes() ); 00029 // m_pListOfUndeformedMeshNodes = &( rTetFemMesh.RetListOfUndeformedMeshNodes() ); 00030 //} 00032 //template <typename T> 00033 //void MeshTetrahedraGen<T>::ClearAccessors () 00034 //{ 00035 // m_pListOfElements = NULL; 00036 // m_pListOfDeformedMeshNodes = NULL; 00037 // m_pListOfUndeformedMeshNodes = NULL; 00038 //} 00039 00040 //----------------------------------------------------------------------------- 00041 template <typename T, typename DATA> 00042 void MeshTetrahedraGen<T,DATA>::OneElementMesh ( MeshTetrahedra<T> & rTetFemMesh, T mass, T YoungsModulus, T PoissonsRatio ) 00043 { 00044 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00045 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00046 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00047 00048 // Clear the mesh 00049 E.clear(); 00050 Nd.clear(); 00051 Nu.clear(); 00052 00053 /* 00054 // 4 deformed nodes 00055 Nd.push_back( Vector3<T>(0,0,1.0) ); 00056 Nd.push_back( Vector3<T>(0,1.0,0) ); 00057 Nd.push_back( Vector3<T>(1.0,0,0) ); 00058 Nd.push_back( Vector3<T>(0,0,0.0) ); 00059 // 4 undeformed nodes 00060 Nu.push_back( Vector3<T>(0,0,1) ); 00061 Nu.push_back( Vector3<T>(0,1,0) ); 00062 Nu.push_back( Vector3<T>(1,0,0) ); 00063 Nu.push_back( Vector3<T>(0,0,0) ); 00064 //*/ 00065 00066 //* 00067 // TEST DATA 00068 // 4 deformed nodes 00069 Nd.push_back( Vector3<T>(2,3,4) ); 00070 Nd.push_back( Vector3<T>(6,3,2) ); 00071 Nd.push_back( Vector3<T>(2,5,1) ); 00072 Nd.push_back( Vector3<T>(4,3,6) ); 00073 // 4 undeformed nodes 00074 Nu.push_back( Vector3<T>(2,3,4) ); 00075 Nu.push_back( Vector3<T>(6,3,2) ); 00076 Nu.push_back( Vector3<T>(2,5,1) ); 00077 Nu.push_back( Vector3<T>(4,3,6) ); 00078 //*/ 00079 00080 // 1st element 00081 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 1, 2, 3 ) ); 00082 00083 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00084 rTetFemMesh.AssembleStiffnessMatrix(); 00085 00086 // Allocate data for simulation 00087 rTetFemMesh.AllocateDataForSimulation( mass ); 00088 } 00089 00090 //----------------------------------------------------------------------------- 00091 template <typename T, typename DATA> 00092 void MeshTetrahedraGen<T,DATA>::TwoElementMeshJoinByNode ( MeshTetrahedra<T> & rTetFemMesh, T mass, T YoungsModulus, T PoissonsRatio ) 00093 { 00094 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00095 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00096 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00097 00098 // Clear the mesh 00099 E.clear(); 00100 Nd.clear(); 00101 Nu.clear(); 00102 00103 // 7 deformed nodes 00104 Nd.push_back( Vector3<T>(0,0,1) ); 00105 Nd.push_back( Vector3<T>(0,1,0) ); 00106 Nd.push_back( Vector3<T>(1,0,0) ); 00107 Nd.push_back( Vector3<T>(0,0,0) ); 00108 Nd.push_back( Vector3<T>(-1,0,0) ); 00109 Nd.push_back( Vector3<T>(0,-1,0) ); 00110 Nd.push_back( Vector3<T>(0,0,-1) ); 00111 // 7 undeformed nodes 00112 Nu.push_back( Vector3<T>(0,0,1) ); 00113 Nu.push_back( Vector3<T>(0,1,0) ); 00114 Nu.push_back( Vector3<T>(1,0,0) ); 00115 Nu.push_back( Vector3<T>(0,0,0) ); 00116 Nu.push_back( Vector3<T>(-1,0,0) ); 00117 Nu.push_back( Vector3<T>(0,-1,0) ); 00118 Nu.push_back( Vector3<T>(0,0,-1) ); 00119 00120 // 1st element 00121 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 1, 2, 3 ) ); 00122 // 2st element 00123 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 4, 5, 6, 3 ) ); 00124 00125 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00126 rTetFemMesh.AssembleStiffnessMatrix(); 00127 00128 // Allocate data for simulation 00129 rTetFemMesh.AllocateDataForSimulation( mass ); 00130 } 00131 00132 //----------------------------------------------------------------------------- 00133 template <typename T, typename DATA> 00134 void MeshTetrahedraGen<T,DATA>::TwoElementMeshJoinByEdge ( MeshTetrahedra<T> & rTetFemMesh, T mass, T YoungsModulus, T PoissonsRatio ) 00135 { 00136 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00137 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00138 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00139 00140 // Clear the mesh 00141 E.clear(); 00142 Nd.clear(); 00143 Nu.clear(); 00144 00145 // 6 deformed nodes 00146 Nd.push_back( Vector3<T>(0,0,1) ); 00147 Nd.push_back( Vector3<T>(0,1,0) ); 00148 Nd.push_back( Vector3<T>(1,0,0) ); 00149 Nd.push_back( Vector3<T>(0,0,0) ); 00150 Nd.push_back( Vector3<T>(-1,0,0) ); 00151 Nd.push_back( Vector3<T>(0,-1,0) ); 00152 // 6 undeformed nodes 00153 Nu.push_back( Vector3<T>(0,0,1) ); 00154 Nu.push_back( Vector3<T>(0,1,0) ); 00155 Nu.push_back( Vector3<T>(1,0,0) ); 00156 Nu.push_back( Vector3<T>(0,0,0) ); 00157 Nu.push_back( Vector3<T>(-1,0,0) ); 00158 Nu.push_back( Vector3<T>(0,-1,0) ); 00159 00160 // 1st element 00161 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 1, 2, 3 ) ); 00162 // 2st element 00163 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 3, 0, 4, 5 ) ); 00164 00165 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00166 rTetFemMesh.AssembleStiffnessMatrix(); 00167 00168 // Allocate data for simulation 00169 rTetFemMesh.AllocateDataForSimulation( mass ); 00170 } 00171 00172 //----------------------------------------------------------------------------- 00173 template <typename T, typename DATA> 00174 void MeshTetrahedraGen<T,DATA>::TwoElementMeshJoinByFace ( MeshTetrahedra<T> & rTetFemMesh, T mass, T YoungsModulus, T PoissonsRatio ) 00175 { 00176 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00177 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00178 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00179 00180 // Clear the mesh 00181 E.clear(); 00182 Nd.clear(); 00183 Nu.clear(); 00184 00185 // 5 deformed nodes 00186 Nd.push_back( Vector3<T>(-0.1,0.2,1) ); 00187 Nd.push_back( Vector3<T>(0.15,1,-0.25) ); 00188 Nd.push_back( Vector3<T>(1,-0.1,0.2) ); 00189 Nd.push_back( Vector3<T>(-1.1,-1.1,-1.1) ); 00190 Nd.push_back( Vector3<T>(-1,-0.1,0.2) ); 00191 // 5 undeformed nodes 00192 Nu.push_back( Vector3<T>(-0.1,0.2,1) ); 00193 Nu.push_back( Vector3<T>(0.15,1,-0.25) ); 00194 Nu.push_back( Vector3<T>(1,-0.1,0.2) ); 00195 Nu.push_back( Vector3<T>(-1.1,-1.1,-1.1) ); 00196 Nu.push_back( Vector3<T>(-1,-0.1,0.2) ); 00197 00198 // 1st element 00199 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 1, 2, 3 ) ); 00200 // 2st element 00201 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 1, 3, 4 ) ); 00202 00203 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00204 rTetFemMesh.AssembleStiffnessMatrix(); 00205 00206 // Allocate data for simulation 00207 rTetFemMesh.AllocateDataForSimulation( mass ); 00208 } 00209 00210 //----------------------------------------------------------------------------- 00211 template <typename T, typename DATA> 00212 void MeshTetrahedraGen<T,DATA>::SixTetrahedraSubFromHexahedron ( MeshTetrahedra<T> & rTetFemMesh, T mass, T YoungsModulus, T PoissonsRatio ) 00213 { 00214 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00215 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00216 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00217 00218 // Clear the mesh 00219 E.clear(); 00220 Nd.clear(); 00221 Nu.clear(); 00222 00223 T s = T(0.5); 00224 // 8 undeformed nodes 00225 Nu.push_back( Vector3<T>(-s,-s,-s) ); 00226 Nu.push_back( Vector3<T>(+s,-s,-s) ); 00227 Nu.push_back( Vector3<T>(+s,+s,-s) ); 00228 Nu.push_back( Vector3<T>(-s,+s,-s) ); 00229 Nu.push_back( Vector3<T>(-s,-s,+s) ); 00230 Nu.push_back( Vector3<T>(+s,-s,+s) ); 00231 Nu.push_back( Vector3<T>(+s,+s,+s) ); 00232 Nu.push_back( Vector3<T>(-s,+s,+s) ); 00233 00234 //s += T(0.05); 00235 // 8 deformed nodes 00236 Nd.push_back( Vector3<T>(-s,-s,-s) ); 00237 Nd.push_back( Vector3<T>(+s,-s,-s) ); 00238 Nd.push_back( Vector3<T>(+s,+s,-s) ); 00239 Nd.push_back( Vector3<T>(-s,+s,-s) ); 00240 Nd.push_back( Vector3<T>(-s,-s,+s) ); 00241 Nd.push_back( Vector3<T>(+s,-s,+s) ); 00242 Nd.push_back( Vector3<T>(+s,+s,+s) ); 00243 Nd.push_back( Vector3<T>(-s,+s,+s) ); 00244 00245 // 6 tetrahedra 00246 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 2, 3, 6 ) ); 00247 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 3, 7, 6 ) ); 00248 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 7, 4, 6 ) ); 00249 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 0, 5, 6, 4 ) ); 00250 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 1, 5, 6, 0 ) ); 00251 E.push_back( Tetrahedron<T>( &Nd, &Nu, YoungsModulus, PoissonsRatio, 1, 6, 2, 0 ) ); 00252 00253 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00254 rTetFemMesh.AssembleStiffnessMatrix(); 00255 00256 // Allocate data for simulation 00257 rTetFemMesh.AllocateDataForSimulation( mass ); 00258 } 00259 00260 00261 //----------------------------------------------------------------------------- 00262 template <typename T, typename DATA> 00263 bool MeshTetrahedraGen<T,DATA>::MeshFromGridGenerator ( 00264 MeshTetrahedra<T> & rTetFemMesh, 00265 GridGenerator<T,DATA> & rGridGen, 00266 T mass, 00267 T YoungsModulus, 00268 T PoissonsRatio 00269 ) 00270 { 00271 00272 if ( !rGridGen.IsGridGenerated() ) { 00273 return false; 00274 } 00275 00276 // Grid layout (right-handed coordinates) 00277 // ^ y 00278 // | 00279 // | 00280 // 0-----> x x = column 00281 // / y = row 00282 // / z = depth 00283 // v z 00284 // 00285 // Where X := #columns-1, Y := #rows-1, and Z := #slices-1. 00286 // 00287 // O-------O-------O---------------O-------O 00288 // /| /| /| ... /| /| 00289 // / |(0,Y,0)| / | ... / |(X,Y,0)| 00290 // / | / | / | ... / | / | 00291 // / O---/---O---/---O-----------/---O---/---O 00292 // / | / | / | ... / | / /| 00293 // / | / | / | .../ | / / | 00294 // / |/ |/ | ../ |/ / | 00295 // / /-------/-------O-------/-------/---/---O 00296 // / /| / HIGHEST / POINT /| 00297 // O-------O-------O---------------O-------@ / / | 00298 // | | | ... | . | / / | 00299 // |(0,Y,Z)| | ... |(X,Y,Z)| / / | 00300 // | | | ... | . |/ / | 00301 // O-------O-------O---------------O-------O / | 00302 // | | | ... | . | / | 00303 // | | | ... | . | / | 00304 // | | | ... | . |/ | 00305 // O-------O-------O---------------O-------O | 00306 // | | . . | | 00307 // | O-------O-----.-O-------------|-O-------0 00308 // | /| | . | ... | | /| 00309 // | / |(0,0,0)| . | ... | |(X,0,0)| 00310 // | / | | . | ... | | / | 00311 // | / @-------O-----.-O-------------|-O---/---O 00312 // | LOWEST / POINT / ./ |/ / / 00313 // | / / / . | / / 00314 // | / / / /. /| / / 00315 // | / / / / . / | / / 00316 // |/ / / / . / |/ / 00317 // O-------O-------O---------------O-------O / 00318 // | / | / | / ... | / | / 00319 // |(0,0,Z)| / | / ... |(X,0,Z)| / 00320 // |/ |/ |/ ... |/ |/ 00321 // O-------O-------O---------------O-------O 00322 // 00323 // where D := Z; R := Y; C := X; 00324 // 00325 // The n-th Z-slice 00326 // 00327 // (nRC+(R-1)+C+0)--(nRC+(R-1)+C+1)--(nRC+(R-1)+C+2)-- ... --(nRC+(R+1)C+C-1) 00328 // | | | | 00329 // | | | | 00330 // | | | | 00331 // ... ... ... ... ... 00332 // | | | | 00333 // | | | | 00334 // | | | | 00335 // (nRC+2C+0)-------(nRC+2C+1)-------(nRC+2C+2)---- ... -----(nRC+2C+C-1) 00336 // | | | | 00337 // | | | | 00338 // | | | | 00339 // (nRC+C+0)--------(nRC+C+1)--------(nRC+C+2)---- ... ------(nRC+C+C-1) 00340 // | | | | 00341 // | | | | 00342 // | | | | 00343 // (nRC+0)----------(nRC+1)----------(nRC+2)----- ... -------(nRC+C-1) 00344 // 00345 // 00346 // 00347 // @---------@ ^ y 00348 // /| /| | 00349 // / | SLICE /A| | 00350 // @---------@ | | 00351 // /| @- - -/| -@ +------>x 00352 // / | SLICE /B| / / 00353 // @---------@ |/ / 00354 // | @------|--@ v z 00355 // | /SLICE C| / 00356 // |/ |/ 00357 // @---------@ 00358 00359 //* 00360 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00361 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00362 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00363 00364 // Clear the mesh 00365 E.clear(); 00366 Nd.clear(); 00367 Nu.clear(); 00368 00369 // Z goes first follows by Y then X. 00370 // So the slice is in Z-plane with Y as rows and X as columns 00371 T **** const GridVertices = rGridGen.ReturnPtrToVertexPositionData(); 00372 unsigned int z,y,x; 00373 unsigned int C = rGridGen.GetGridSizeX(); 00374 unsigned int R = rGridGen.GetGridSizeY(); 00375 unsigned int D = rGridGen.GetGridSizeZ(); 00376 00377 // Add FEM mesh vertices from the grid data 00378 for ( z = 0; z < D; ++z ) { 00379 for ( y = 0; y < R; ++y ) { 00380 for ( x = 0; x < C; ++x ) { 00381 Vector3<T> V( GridVertices[x][y][z][0], GridVertices[x][y][z][1], GridVertices[x][y][z][2] ); 00382 Nd.push_back( V ); 00383 Nu.push_back( V ); 00384 } 00385 } 00386 } 00387 00388 // Add tetrahedra from the FEM mesh vertices 00389 unsigned int v[8]; 00390 unsigned int RC = R*C; 00391 unsigned int SLICE = 0; 00392 unsigned int ROW; 00393 for ( z = 0; z < D-1; ++z ) { 00394 ROW = 0; 00395 for ( y = 0; y < R-1; ++y ) { 00396 for ( x = 0; x < C-1; ++x ) { 00397 // Pt 1 to 8 00398 // 00399 // 3---------2 ^ y 00400 // /| /| | 00401 // / | / | | 00402 // 7---------6 | | 00403 // | 0- - - | -1 +------>x 00404 // | / | / / 00405 // |/ |/ / 00406 // 4---------5 v z 00407 v[0] = SLICE + ROW + x; 00408 v[3] = v[0] + C; 00409 v[4] = v[0] + RC; 00410 v[7] = v[4] + C; 00411 v[1] = v[0]+1; 00412 v[2] = v[3]+1; 00413 v[5] = v[4]+1; 00414 v[6] = v[7]+1; 00415 // Subdivided into six tetrahedra 00416 // 0-2-3-6 00417 E.push_back( Tetrahedron<T>( 00418 &Nd, // the 4 deformed nodes 00419 &Nu, // the 4 undeformed nodes 00420 YoungsModulus, // Young's modulus 00421 PoissonsRatio, // Poisson's ratio 00422 v[0], v[2], v[3], v[6] ) 00423 ); 00424 // 0-3-7-6 00425 E.push_back( Tetrahedron<T>( 00426 &Nd, // the 4 deformed nodes 00427 &Nu, // the 4 undeformed nodes 00428 YoungsModulus, // Young's modulus 00429 PoissonsRatio, // Poisson's ratio 00430 v[0], v[3], v[7], v[6] ) 00431 ); 00432 // 0-7-4-6 00433 E.push_back( Tetrahedron<T>( 00434 &Nd, // the 4 deformed nodes 00435 &Nu, // the 4 undeformed nodes 00436 YoungsModulus, // Young's modulus 00437 PoissonsRatio, // Poisson's ratio 00438 v[0], v[7], v[4], v[6] ) 00439 ); 00440 // 0-5-6-4 00441 E.push_back( Tetrahedron<T>( 00442 &Nd, // the 4 deformed nodes 00443 &Nu, // the 4 undeformed nodes 00444 YoungsModulus, // Young's modulus 00445 PoissonsRatio, // Poisson's ratio 00446 v[0], v[5], v[6], v[4] ) 00447 ); 00448 // 1-5-6-0 00449 E.push_back( Tetrahedron<T>( 00450 &Nd, // the 4 deformed nodes 00451 &Nu, // the 4 undeformed nodes 00452 YoungsModulus, // Young's modulus 00453 PoissonsRatio, // Poisson's ratio 00454 v[1], v[5], v[6], v[0] ) 00455 ); 00456 // 1-6-2-0 00457 E.push_back( Tetrahedron<T>( 00458 &Nd, // the 4 deformed nodes 00459 &Nu, // the 4 undeformed nodes 00460 YoungsModulus, // Young's modulus 00461 PoissonsRatio, // Poisson's ratio 00462 v[1], v[6], v[2], v[0] ) 00463 ); 00464 } 00465 ROW += C; 00466 } 00467 SLICE += RC; 00468 } 00469 00470 rTetFemMesh.SetSizeOfStiffnessMatrix(); 00471 rTetFemMesh.AssembleStiffnessMatrix(); 00472 00473 // Allocate data for simulation 00474 rTetFemMesh.AllocateDataForSimulation( mass ); 00475 //*/ 00476 00477 // DEBUG 00478 std::cout << "Generated Tetrahedral FEM mesh has " << rTetFemMesh.GetNumOfNodes() 00479 << " nodes and " << rTetFemMesh.GetNumOfElements() << " elements.\n"; 00480 00481 return true; 00482 } 00483 00484 00485 //----------------------------------------------------------------------------- 00486 template <typename T, typename DATA> 00487 bool MeshTetrahedraGen<T,DATA>::MeshFromGridGenerator ( 00488 MeshTetrahedra<T> & rTetFemMesh, 00489 std::vector< TetBarycentricCoordsForVertexRef<T> > & rBaryCoords, 00490 //std::vector< unsigned int > & r_ElementID, //!< identify the element that the barycentric coordinates are embedded in 00491 GridGenerator<T,DATA> & rGridGen, 00492 T mass, 00493 T YoungsModulus, 00494 T PoissonsRatio, 00495 bool bGenElementsInsideVolume 00496 ) 00497 { 00498 00499 if ( !rGridGen.IsGridGenerated() ) { 00500 return false; 00501 } 00502 00503 // Grid layout (right-handed coordinates) 00504 // ^ y 00505 // | 00506 // | 00507 // 0-----> x x = column 00508 // / y = row 00509 // / z = depth 00510 // v z 00511 // 00512 // Where X := #columns-1, Y := #rows-1, and Z := #slices-1. 00513 // 00514 // O-------O-------O---------------O-------O 00515 // /| /| /| ... /| /| 00516 // / |(0,Y,0)| / | ... / |(X,Y,0)| 00517 // / | / | / | ... / | / | 00518 // / O---/---O---/---O-----------/---O---/---O 00519 // / | / | / | ... / | / /| 00520 // / | / | / | .../ | / / | 00521 // / |/ |/ | ../ |/ / | 00522 // / /-------/-------O-------/-------/---/---O 00523 // / /| / HIGHEST / POINT /| 00524 // O-------O-------O---------------O-------@ / / | 00525 // | | | ... | . | / / | 00526 // |(0,Y,Z)| | ... |(X,Y,Z)| / / | 00527 // | | | ... | . |/ / | 00528 // O-------O-------O---------------O-------O / | 00529 // | | | ... | . | / | 00530 // | | | ... | . | / | 00531 // | | | ... | . |/ | 00532 // O-------O-------O---------------O-------O | 00533 // | | . . | | 00534 // | O-------O-----.-O-------------|-O-------0 00535 // | /| | . | ... | | /| 00536 // | / |(0,0,0)| . | ... | |(X,0,0)| 00537 // | / | | . | ... | | / | 00538 // | / @-------O-----.-O-------------|-O---/---O 00539 // | LOWEST / POINT / ./ |/ / / 00540 // | / / / . | / / 00541 // | / / / /. /| / / 00542 // | / / / / . / | / / 00543 // |/ / / / . / |/ / 00544 // O-------O-------O---------------O-------O / 00545 // | / | / | / ... | / | / 00546 // |(0,0,Z)| / | / ... |(X,0,Z)| / 00547 // |/ |/ |/ ... |/ |/ 00548 // O-------O-------O---------------O-------O 00549 // 00550 // where D := Z; R := Y; C := X; 00551 // 00552 // The n-th Z-slice 00553 // 00554 // (nRC+(R-1)+C+0)--(nRC+(R-1)+C+1)--(nRC+(R-1)+C+2)-- ... --(nRC+(R+1)C+C-1) 00555 // | | | | 00556 // | | | | 00557 // | | | | 00558 // ... ... ... ... ... 00559 // | | | | 00560 // | | | | 00561 // | | | | 00562 // (nRC+2C+0)-------(nRC+2C+1)-------(nRC+2C+2)---- ... -----(nRC+2C+C-1) 00563 // | | | | 00564 // | | | | 00565 // | | | | 00566 // (nRC+C+0)--------(nRC+C+1)--------(nRC+C+2)---- ... ------(nRC+C+C-1) 00567 // | | | | 00568 // | | | | 00569 // | | | | 00570 // (nRC+0)----------(nRC+1)----------(nRC+2)----- ... -------(nRC+C-1) 00571 // 00572 // 00573 // 00574 // @---------@ ^ y 00575 // /| /| | 00576 // / | SLICE /A| | 00577 // @---------@ | | 00578 // /| @- - -/| -@ +------>x 00579 // / | SLICE /B| / / 00580 // @---------@ |/ / 00581 // | @------|--@ v z 00582 // | /SLICE C| / 00583 // |/ |/ 00584 // @---------@ 00585 00586 //* 00587 std::vector< Tetrahedron<T> > & E = rTetFemMesh.RetListOfElements(); 00588 std::vector< Vector3<T> > & Nd = rTetFemMesh.RetListOfDeformedMeshNodes(); 00589 std::vector< Vector3<T> > & Nu = rTetFemMesh.RetListOfUndeformedMeshNodes(); 00590 00591 // Clear the mesh 00592 E.clear(); 00593 Nd.clear(); 00594 Nu.clear(); 00595 00596 // Create temp data 00597 unsigned int gridsize[3] = { rGridGen.GetGridSizeX()-1, rGridGen.GetGridSizeY()-1, rGridGen.GetGridSizeZ()-1 }; 00598 unsigned int gx = gridsize[0]; 00599 unsigned int gxgy = gridsize[0]*gridsize[1]; 00600 bool **** pValidElements = new bool***[gridsize[2]]; 00601 for ( unsigned int k = 0; k < gridsize[2]; ++k ) { 00602 pValidElements[k] = new bool**[gridsize[1]]; 00603 for ( unsigned int j = 0; j < gridsize[1]; ++j ) { 00604 pValidElements[k][j] = new bool*[gridsize[0]]; 00605 for ( unsigned int i = 0; i < gridsize[0]; ++i ) { 00606 pValidElements[k][j][i] = new bool[6]; 00607 for ( unsigned int e = 0; e < 6; ++e ) { 00608 pValidElements[k][j][i][e] = false; 00609 } 00610 } 00611 } 00612 } 00613 00614 // Find all barycentric coordinates and mark all valid elements 00615 //FindAllBaryCoordsAndTheirLocInTheGrids( rBaryCoords, r_ElementID, rGridGen, pValidElements ); 00616 FindAllBaryCoordsAndTheirLocInTheGrids( rBaryCoords, rGridGen, pValidElements ); 00617 // Now rBaryCoords contain the barycentric coordinates of all vertices 00618 // but not yet have the correct pointer to tetrehedra since they are not yet created. 00619 // pValidElements now contain all valid elements 00620 // r_ElementID store the element IDs associated with rBaryCoords in the format of 6(z(R-1)(C-1)+y(C-1)+x). 00621 // These values (format) has to be changed to the element IDs stored in the FEM mesh. 00622 00623 /* 00624 // DID NOT SEE THE BENEFIT OF THIS ONE -- SEPARATING OF RIGHT_OUTSIDE_BOUNDARY AND ON_BOUNDARY FROM RIGHT_INSIDE_BOUNDARY AND INSIDE_MODEL! 00625 // FEM MESH DATA FROM THE ADJACENT ELEMENTS ON THE BOUNDARY OF THE SURFACE MESH 00626 if ( true ) { 00627 // Mark the valid vertices (location) in temp data based on the grid vertex data stored in rGridGen 00628 GridGenerator<T,DATA>::VertexFlag *** const vertexFlag = rGridGen.ReturnPtrToVertexFlagData(); 00629 // Mark the valid vertices (location) in temp data 00630 bool b[8]; 00631 for ( unsigned int x = 0; x < gridsize[0]; ++x ) { 00632 for ( unsigned int y = 0; y < gridsize[1]; ++y ) { 00633 for ( unsigned int z = 0; z < gridsize[2]; ++z ) { 00634 // Find valid FEM mesh vertices 00635 if ( vertexFlag[x][y][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00636 || vertexFlag[x][y][z] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00637 {b[0] = true;} else {b[0] = false;} 00638 if ( vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00639 || vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00640 {b[1] = true;} else {b[1] = false;} 00641 if ( vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00642 || vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00643 {b[2] = true;} else {b[2] = false;} 00644 if ( vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00645 || vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00646 {b[3] = true;} else {b[3] = false;} 00647 if ( vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00648 || vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00649 {b[4] = true;} else {b[4] = false;} 00650 if ( vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00651 || vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00652 {b[5] = true;} else {b[5] = false;} 00653 if ( vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00654 || vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00655 {b[6] = true;} else {b[6] = false;} 00656 if ( vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00657 || vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY ) 00658 {b[7] = true;} else {b[7] = false;} 00659 00660 // Six tetrahedra subdivided from a brick 00661 // 0-2-3-6 --> #0 00662 // 0-3-7-6 --> #1 00663 // 0-7-4-6 --> #2 00664 // 0-5-6-4 --> #3 00665 // 1-5-6-0 --> #4 00666 // 1-6-2-0 --> #5 00667 if ( b[0] && b[2] && b[3] && b[6] ) pValidElements[z][y][x][0] = true; 00668 if ( b[0] && b[3] && b[7] && b[6] ) pValidElements[z][y][x][1] = true; 00669 if ( b[0] && b[7] && b[4] && b[6] ) pValidElements[z][y][x][2] = true; 00670 if ( b[0] && b[5] && b[6] && b[4] ) pValidElements[z][y][x][3] = true; 00671 if ( b[1] && b[5] && b[6] && b[0] ) pValidElements[z][y][x][4] = true; 00672 if ( b[1] && b[6] && b[2] && b[0] ) pValidElements[z][y][x][5] = true; 00673 } 00674 } 00675 } 00676 } 00677 //*/ 00678 00679 // FEM MESH DATA FROM VOLUME INSIDE THE SURFACE MESH 00680 if ( bGenElementsInsideVolume ) { 00681 // Mark the valid vertices (location) in temp data based on the grid vertex data stored in rGridGen 00682 GridGenerator<T,DATA>::VertexFlag *** const vertexFlag = rGridGen.ReturnPtrToVertexFlagData(); 00683 // Mark the valid vertices (location) in temp data 00684 bool b[8]; 00685 for ( unsigned int x = 0; x < gridsize[0]; ++x ) { 00686 for ( unsigned int y = 0; y < gridsize[1]; ++y ) { 00687 for ( unsigned int z = 0; z < gridsize[2]; ++z ) { 00688 // Find valid FEM mesh vertices 00689 if ( vertexFlag[x][y][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00690 || vertexFlag[x][y][z] == GridGenerator<T,DATA>::ON_BOUNDARY 00691 || vertexFlag[x][y][z] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00692 || vertexFlag[x][y][z] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00693 {b[0] = true;} else {b[0] = false;} 00694 if ( vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00695 || vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::ON_BOUNDARY 00696 || vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00697 || vertexFlag[x+1][y][z] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00698 {b[1] = true;} else {b[1] = false;} 00699 if ( vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00700 || vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::ON_BOUNDARY 00701 || vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00702 || vertexFlag[x+1][y+1][z] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00703 {b[2] = true;} else {b[2] = false;} 00704 if ( vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00705 || vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::ON_BOUNDARY 00706 || vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00707 || vertexFlag[x][y+1][z] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00708 {b[3] = true;} else {b[3] = false;} 00709 if ( vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00710 || vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY 00711 || vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00712 || vertexFlag[x][y][z+1] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00713 {b[4] = true;} else {b[4] = false;} 00714 if ( vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00715 || vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY 00716 || vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00717 || vertexFlag[x+1][y][z+1] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00718 {b[5] = true;} else {b[5] = false;} 00719 if ( vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00720 || vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY 00721 || vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00722 || vertexFlag[x+1][y+1][z+1] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00723 {b[6] = true;} else {b[6] = false;} 00724 if ( vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_OUTSIDE_BOUNDARY 00725 || vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::ON_BOUNDARY 00726 || vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::RIGHT_INSIDE_BOUNDARY 00727 || vertexFlag[x][y+1][z+1] == GridGenerator<T,DATA>::INSIDE_MODEL ) 00728 {b[7] = true;} else {b[7] = false;} 00729 00730 // Six tetrahedra subdivided from a brick 00731 // 0-2-3-6 --> #0 00732 // 0-3-7-6 --> #1 00733 // 0-7-4-6 --> #2 00734 // 0-5-6-4 --> #3 00735 // 1-5-6-0 --> #4 00736 // 1-6-2-0 --> #5 00737 if ( b[0] && b[2] && b[3] && b[6] ) pValidElements[z][y][x][0] = true; 00738 if ( b[0] && b[3] && b[7] && b[6] ) pValidElements[z][y][x][1] = true; 00739 if ( b[0] && b[7] && b[4] && b[6] ) pValidElements[z][y][x][2] = true; 00740 if ( b[0] && b[5] && b[6] && b[4] ) pValidElements[z][y][x][3] = true; 00741 if ( b[1] && b[5] && b[6] && b[0] ) pValidElements[z][y][x][4] = true; 00742 if ( b[1] && b[6] && b[2] && b[0] ) pValidElements[z][y][x][5] = true; 00743 } 00744 } 00745 } 00746 } 00747 00748 // Z goes first follows by Y then X. 00749 // So the slice is in Z-plane with Y as rows and X as columns 00750 T **** const GridVertices = rGridGen.ReturnPtrToVertexPositionData(); 00751 unsigned int C = rGridGen.GetGridSizeX(); 00752 unsigned int R = rGridGen.GetGridSizeY(); 00753 unsigned int D = rGridGen.GetGridSizeZ(); 00754 unsigned int RC = R*C; 00755 unsigned int DRC = D*RC; 00756 unsigned int SLICE = 0; 00757 unsigned int ROW; 00758 00759 // Temp data for finding valid FEM mesh vertices 00760 unsigned int *** pVertexLocs = new unsigned int**[D]; 00761 for ( unsigned int k = 0; k < D; ++k ) { 00762 pVertexLocs[k] = new unsigned int*[R]; 00763 for ( unsigned int j = 0; j < R; ++j ) { 00764 pVertexLocs[k][j] = new unsigned int[C]; 00765 for ( unsigned int i = 0; i < C; ++i ) { 00766 pVertexLocs[k][j][i] = DRC; 00767 } 00768 } 00769 } 00770 00771 // Temp data for storing element ID 00772 std::vector< unsigned int > elementIDs( gridsize[2]*gridsize[1]*gridsize[0]*6 ); 00773 00774 // Find valid FEM mesh vertices 00775 // Six tetrahedra subdivided from a brick 00776 // 0-2-3-6 00777 // 0-3-7-6 00778 // 0-7-4-6 00779 // 0-5-6-4 00780 // 1-5-6-0 00781 // 1-6-2-0 00782 // @---------@ ^ y 00783 // /| /| | 00784 // / | SLICE /A| | 00785 // 3---------2 | | 00786 // /| @- - -/| -@ +------>x 00787 // / | SLICE /B| / / 00788 // 7---------6 |/ / 00789 // | 0------|--1 v z 00790 // | /SLICE C| / 00791 // |/ |/ 00792 // 4---------5 00793 unsigned int countV = 0; 00794 for ( unsigned int k = 0; k < gridsize[2]; ++k ) { 00795 for ( unsigned int j = 0; j < gridsize[1]; ++j ) { 00796 for ( unsigned int i = 0; i < gridsize[0]; ++i ) { 00797 00798 //std::cout << "k,j,i: " << k << "," << j << "," << i << "\n"; 00799 //std::cout << pValidElements[k][j][i][0] 00800 // << " " << pValidElements[k][j][i][1] 00801 // << " " << pValidElements[k][j][i][2] 00802 // << " " << pValidElements[k][j][i][3] 00803 // << " " << pValidElements[k][j][i][4] 00804 // << " " << pValidElements[k][j][i][5] << "\n"; 00805 00806 // v0 00807 if ( pVertexLocs[k][j][i] == DRC ) { 00808 if ( pValidElements[k][j][i][0] 00809 || pValidElements[k][j][i][1] 00810 || pValidElements[k][j][i][2] 00811 || pValidElements[k][j][i][3] 00812 || pValidElements[k][j][i][4] 00813 || pValidElements[k][j][i][5] ) 00814 { 00815 Vector3<T> V( GridVertices[i][j][k][0], GridVertices[i][j][k][1], GridVertices[i][j][k][2] ); 00816 Nd.push_back( V ); 00817 Nu.push_back( V ); 00818 pVertexLocs[k][j][i] = countV; 00819 ++countV; 00820 } 00821 } 00822 // v1 00823 if ( pVertexLocs[k][j][i+1] == DRC ) { 00824 if ( pValidElements[k][j][i][4] 00825 || pValidElements[k][j][i][5] ) 00826 { 00827 Vector3<T> V( GridVertices[i+1][j][k][0], GridVertices[i+1][j][k][1], GridVertices[i+1][j][k][2] ); 00828 Nd.push_back( V ); 00829 Nu.push_back( V ); 00830 pVertexLocs[k][j][i+1] = countV; 00831 ++countV; 00832 } 00833 } 00834 // v2 00835 if ( pVertexLocs[k][j+1][i+1] == DRC ) { 00836 if ( pValidElements[k][j][i][0] 00837 || pValidElements[k][j][i][5] ) 00838 { 00839 Vector3<T> V( GridVertices[i+1][j+1][k][0], GridVertices[i+1][j+1][k][1], GridVertices[i+1][j+1][k][2] ); 00840 Nd.push_back( V ); 00841 Nu.push_back( V ); 00842 pVertexLocs[k][j+1][i+1] = countV; 00843 ++countV; 00844 } 00845 } 00846 // v3 00847 if ( pVertexLocs[k][j+1][i] == DRC ) { 00848 if ( pValidElements[k][j][i][0] 00849 || pValidElements[k][j][i][1] ) 00850 { 00851 Vector3<T> V( GridVertices[i][j+1][k][0], GridVertices[i][j+1][k][1], GridVertices[i][j+1][k][2] ); 00852 Nd.push_back( V ); 00853 Nu.push_back( V ); 00854 pVertexLocs[k][j+1][i] = countV; 00855 ++countV; 00856 } 00857 } 00858 // v4 00859 if ( pVertexLocs[k+1][j][i] == DRC ) { 00860 if ( pValidElements[k][j][i][2] 00861 || pValidElements[k][j][i][3] ) 00862 { 00863 Vector3<T> V( GridVertices[i][j][k+1][0], GridVertices[i][j][k+1][1], GridVertices[i][j][k+1][2] ); 00864 Nd.push_back( V ); 00865 Nu.push_back( V ); 00866 pVertexLocs[k+1][j][i] = countV; 00867 ++countV; 00868 } 00869 } 00870 // v5 00871 if ( pVertexLocs[k+1][j][i+1] == DRC ) { 00872 if ( pValidElements[k][j][i][3] 00873 || pValidElements[k][j][i][4] ) 00874 { 00875 Vector3<T> V( GridVertices[i+1][j][k+1][0], GridVertices[i+1][j][k+1][1], GridVertices[i+1][j][k+1][2] ); 00876 Nd.push_back( V ); 00877 Nu.push_back( V ); 00878 pVertexLocs[k+1][j][i+1] = countV; 00879 ++countV; 00880 } 00881 } 00882 // v6 00883 if ( pVertexLocs[k+1][j+1][i+1] == DRC ) { 00884 if ( pValidElements[k][j][i][0] 00885 || pValidElements[k][j][i][1] 00886 || pValidElements[k][j][i][2] 00887 || pValidElements[k][j][i][3] 00888 || pValidElements[k][j][i][4] 00889 || pValidElements[k][j][i][5] ) 00890 { 00891 Vector3<T> V( GridVertices[i+1][j+1][k+1][0], GridVertices[i+1][j+1][k+1][1], GridVertices[i+1][j+1][k+1][2] ); 00892 Nd.push_back( V ); 00893 Nu.push_back( V ); 00894 pVertexLocs[k+1][j+1][i+1] = countV; 00895 ++countV; 00896 } 00897 } 00898 // v7 00899 if ( pVertexLocs[k+1][j+1][i] == DRC ) { 00900 if ( pValidElements[k][j][i][1] 00901 || pValidElements[k][j][i][2] ) 00902 { 00903 Vector3<T> V( GridVertices[i][j+1][k+1][0], GridVertices[i][j+1][k+1][1], GridVertices[i][j+1][k+1][2] ); 00904 Nd.push_back( V ); 00905 Nu.push_back( V ); 00906 pVertexLocs[k+1][j+1][i] = countV; 00907 ++countV; 00908 } 00909 } 00910 } 00911 } 00912 } 00913 00914 // Add tetrahedron elements from the valid FEM mesh vertices 00915 unsigned int countE = 0; 00916 for ( unsigned int k = 0; k < D-1; ++k ) { 00917 ROW = 0; 00918 for ( unsigned int j = 0; j < R-1; ++j ) { 00919 for ( unsigned int i = 0; i < C-1; ++i ) { 00920 unsigned int elementID = (k*gxgy + j*gx + i) * 6; 00921 // Pt 1 to 8 00922 // 00923 // 3---------2 ^ y 00924 // /| /| | 00925 // / | / | | 00926 // 7---------6 | | 00927 // | 0- - - | -1 +------>x 00928 // | / | / / 00929 // |/ |/ / 00930 // 4---------5 v z 00931 // Subdivided into six tetrahedra 00932 // 0-2-3-6 00933 if ( pValidElements[k][j][i][0] ) { 00934 E.push_back( Tetrahedron<T>( 00935 &Nd, // the 4 deformed nodes 00936 &Nu, // the 4 undeformed nodes 00937 YoungsModulus, // Young's modulus 00938 PoissonsRatio, // Poisson's ratio 00939 pVertexLocs[k][j][i], pVertexLocs[k][j+1][i+1], pVertexLocs[k][j+1][i], pVertexLocs[k+1][j+1][i+1] ) 00940 ); 00941 elementIDs[elementID] = countE++; 00942 } 00943 // 0-3-7-6 00944 if ( pValidElements[k][j][i][1] ) { 00945 E.push_back( Tetrahedron<T>( 00946 &Nd, // the 4 deformed nodes 00947 &Nu, // the 4 undeformed nodes 00948 YoungsModulus, // Young's modulus 00949 PoissonsRatio, // Poisson's ratio 00950 pVertexLocs[k][j][i], pVertexLocs[k][j+1][i], pVertexLocs[k+1][j+1][i], pVertexLocs[k+1][j+1][i+1] ) 00951 ); 00952 elementIDs[elementID+1] = countE++; 00953 } 00954 // 0-7-4-6 00955 if ( pValidElements[k][j][i][2] ) { 00956 E.push_back( Tetrahedron<T>( 00957 &Nd, // the 4 deformed nodes 00958 &Nu, // the 4 undeformed nodes 00959 YoungsModulus, // Young's modulus 00960 PoissonsRatio, // Poisson's ratio 00961 pVertexLocs[k][j][i], pVertexLocs[k+1][j+1][i], pVertexLocs[k+1][j][i], pVertexLocs[k+1][j+1][i+1] ) 00962 ); 00963 elementIDs[elementID+2] = countE++; 00964 } 00965 // 0-5-6-4 00966 if ( pValidElements[k][j][i][3] ) { 00967 E.push_back( Tetrahedron<T>( 00968 &Nd, // the 4 deformed nodes 00969 &Nu, // the 4 undeformed nodes 00970 YoungsModulus, // Young's modulus 00971 PoissonsRatio, // Poisson's ratio 00972 pVertexLocs[k][j][i], pVertexLocs[k+1][j][i+1], pVertexLocs[k+1][j+1][i+1], pVertexLocs[k+1][j][i] ) 00973 ); 00974 elementIDs[elementID+3] = countE++; 00975 } 00976 // 1-5-6-0 00977 if ( pValidElements[k][j][i][4] ) { 00978 E.push_back( Tetrahedron<T>( 00979 &Nd, // the 4 deformed nodes 00980 &Nu, // the 4 undeformed nodes 00981 YoungsModulus, // Young's modulus 00982 PoissonsRatio, // Poisson's ratio 00983 pVertexLocs[k][j][i+1], pVertexLocs[k+1][j][i+1], pVertexLocs[k+1][j+1][i+1], pVertexLocs[k][j][i] ) 00984 ); 00985 elementIDs[elementID+4] = countE++; 00986 } 00987 // 1-6-2-0 00988 if ( pValidElements[k][j][i][5] ) { 00989 E.push_back( Tetrahedron<T>( 00990 &Nd, // the 4 deformed nodes 00991 &Nu, // the 4 undeformed nodes 00992 YoungsModulus, // Young's modulus 00993 PoissonsRatio, // Poisson's ratio 00994 pVertexLocs[k][j][i+1], pVertexLocs[k+1][j+1][i+1], pVertexLocs[k][j+1][i+1], pVertexLocs[k][j][i] ) 00995 ); 00996 elementIDs[elementID+5] = countE++; 00997 } 00998 } 00999 ROW += C; 01000 } 01001 SLICE += RC; 01002 } 01003 01004 // Associated barycentric coordinates with tetrahedra 01005 // MUST BE DONE AFTER ALL TETRAHEDRAL ELEMENTS ARE GENERATED! 01006 // OTHERWISE THE POINTERS WILL NOT BE VALID DUE TO 01007 // THE AUTOMATICAL RESIZING OF STD::VECTOR! 01008 for ( unsigned int i = 0; i < rBaryCoords.size(); ++i ) { 01009 rBaryCoords[i].SetElementID( elementIDs[ rBaryCoords[i].GetElementID() ] ); 01010 //r_ElementID[i] = elementIDs[ r_ElementID[i] ]; 01011 //rBaryCoords[i].SetPtrToTetrahedron( &(E[ r_ElementID[i] ]) ); 01012 rBaryCoords[i].SetPtrToTetrahedron( &(E[ rBaryCoords[i].GetElementID() ]) ); 01013 } 01014 01015 // Delete temp data 01016 for ( unsigned int k = 0; k < gridsize[2]; ++k ) { 01017 for ( unsigned int j = 0; j < gridsize[1]; ++j ) { 01018 delete [] pVertexLocs[k][j]; 01019 } 01020 delete [] pVertexLocs[k]; 01021 } 01022 delete [] pVertexLocs; 01023 01024 // Delete temp data 01025 for ( unsigned int k = 0; k < gridsize[2]; ++k ) { 01026 for ( unsigned int j = 0; j < gridsize[1]; ++j ) { 01027 for ( unsigned int i = 0; i < gridsize[0]; ++i ) { 01028 delete [] pValidElements[k][j][i]; 01029 } 01030 delete [] pValidElements[k][j]; 01031 } 01032 delete [] pValidElements[k]; 01033 } 01034 delete [] pValidElements; 01035 01036 // Assemble the stiffness matrix 01037 rTetFemMesh.SetSizeOfStiffnessMatrix(); 01038 rTetFemMesh.AssembleStiffnessMatrix(); 01039 01040 // Allocate data for simulation 01041 rTetFemMesh.AllocateDataForSimulation( mass ); 01042 01043 // DEBUG 01044 std::cout << "Generated Tetrahedral FEM mesh has " << rTetFemMesh.GetNumOfNodes() 01045 << " nodes and " << rTetFemMesh.GetNumOfElements() << " elements.\n"; 01046 std::cout << std::flush; 01047 01048 return true; 01049 } 01050 01051 01052 //----------------------------------------------------------------------------- 01053 template <typename T, typename DATA> 01054 void MeshTetrahedraGen<T,DATA>::FindAllBaryCoordsAndTheirLocInTheGrids ( 01055 std::vector< TetBarycentricCoordsForVertexRef<T> > & rBaryCoords, 01056 //std::vector< unsigned int > & r_ElementID, //!< identify the element that the barycentric coordinates are embedded in 01057 GridGenerator<T,DATA> & rGridGen, 01058 bool **** pValidElements 01059 ) 01060 { 01061 // FOR HALFEDGE MESH MODEL ONLY 01062 TAPs::OpenGL::HalfEdgeModel<T> * pHEModel = dynamic_cast< TAPs::OpenGL::HalfEdgeModel<T> * >( rGridGen.GetModelUseToGenGrid() ); 01063 if ( pHEModel == NULL ) { 01064 std::cout << "MeshTetrahedraGen<...> --> MeshModel is not HalfEdge!" << std::endl; 01065 exit(-1); 01066 } 01067 rBaryCoords.clear(); 01068 //std::cout << "#vertices: " << pHEModel->GetNoVertices() << "\n"; 01069 //std::cout << "#vertices: " << pHEModel->GetNumVertices() << "\n"; 01070 //std::cout << "#vertices: " << pHEModel->GetVertexList()->Size() << "\n"; 01071 HEVertex<T> * pVertex = pHEModel->GetVertexList()->Head(); 01072 unsigned int i,j,k; 01073 //T u,v,w; 01074 //T sx = 1.0 / (m_atGridDimension[0]*m_atGridDimension[0]); 01075 //T sy = 1.0 / (m_atGridDimension[1]*m_atGridDimension[1]); 01076 //T sz = 1.0 / (m_atGridDimension[2]*m_atGridDimension[2]); 01077 unsigned int gx = rGridGen.GetGridSizeX()-1; // width 01078 unsigned int gy = rGridGen.GetGridSizeY()-1; // height 01079 unsigned int gz = rGridGen.GetGridSizeZ()-1; // depth 01080 unsigned int gxgy = gx*gy; 01081 unsigned int numOfElements = gx*gy*gz*6; 01082 01083 // checkedElements for marking that the computed inverted matrices of 6 tetrahedra forming a brick 01084 // has been computed and stored in storedMatrices 01085 // so that the computations do not have to be repeated. 01086 std::vector< unsigned int > checkedElements( numOfElements ); 01087 unsigned int locateMatrices = 0; 01088 std::vector< Matrix3x3<T> > storedMatrices; 01089 for ( unsigned int i = 0; i < numOfElements; ++i ) { 01090 checkedElements[i] = numOfElements; 01091 } 01092 01093 unsigned int count = 0; 01094 T **** VP = rGridGen.ReturnPtrToVertexPositionData(); 01095 while ( pVertex != NULL ) { 01096 01097 Vector3<T> P = pVertex->GetPosition(); 01098 rGridGen.LocateHexGrid( P[0], P[1], P[2], i, j, k ); 01099 01100 Vector3<T> v0( VP[i ][j ][k ][0], VP[i ][j ][k ][1], VP[i ][j ][k ][2] ); 01101 Vector3<T> v1( VP[i+1][j ][k ][0], VP[i+1][j ][k ][1], VP[i+1][j ][k ][2] ); 01102 Vector3<T> v2( VP[i+1][j+1][k ][0], VP[i+1][j+1][k ][1], VP[i+1][j+1][k ][2] ); 01103 Vector3<T> v3( VP[i ][j+1][k ][0], VP[i ][j+1][k ][1], VP[i ][j+1][k ][2] ); 01104 Vector3<T> v4( VP[i ][j ][k+1][0], VP[i ][j ][k+1][1], VP[i ][j ][k+1][2] ); 01105 Vector3<T> v5( VP[i+1][j ][k+1][0], VP[i+1][j ][k+1][1], VP[i+1][j ][k+1][2] ); 01106 Vector3<T> v6( VP[i+1][j+1][k+1][0], VP[i+1][j+1][k+1][1], VP[i+1][j+1][k+1][2] ); 01107 Vector3<T> v7( VP[i ][j+1][k+1][0], VP[i ][j+1][k+1][1], VP[i ][j+1][k+1][2] ); 01108 01109 // Test against six tetrahedra 01110 // 0-2-3-6 01111 // 0-3-7-6 01112 // 0-7-4-6 01113 // 0-5-6-4 01114 // 1-5-6-0 01115 // 1-6-2-0 01116 01117 // Computed the inverted matrices of 6 tetrahedra 01118 unsigned int enumber = i + j*gx + k*gxgy; 01119 if ( checkedElements[enumber] == numOfElements ) { 01120 checkedElements[enumber] = locateMatrices++; 01121 // 0-2-3-6 01122 storedMatrices.push_back( Matrix3x3<T>( 01123 v2[0]-v0[0], v3[0]-v0[0], v6[0]-v0[0], 01124 v2[1]-v0[1], v3[1]-v0[1], v6[1]-v0[1], 01125 v2[2]-v0[2], v3[2]-v0[2], v6[2]-v0[2] 01126 ).Inversed() ); 01127 // 0-3-7-6 01128 storedMatrices.push_back( Matrix3x3<T>( 01129 v3[0]-v0[0], v7[0]-v0[0], v6[0]-v0[0], 01130 v3[1]-v0[1], v7[1]-v0[1], v6[1]-v0[1], 01131 v3[2]-v0[2], v7[2]-v0[2], v6[2]-v0[2] 01132 ).Inversed() ); 01133 // 0-7-4-6 01134 storedMatrices.push_back( Matrix3x3<T>( 01135 v7[0]-v0[0], v4[0]-v0[0], v6[0]-v0[0], 01136 v7[1]-v0[1], v4[1]-v0[1], v6[1]-v0[1], 01137 v7[2]-v0[2], v4[2]-v0[2], v6[2]-v0[2] 01138 ).Inversed() ); 01139 // 0-5-6-4 01140 storedMatrices.push_back( Matrix3x3<T>( 01141 v5[0]-v0[0], v6[0]-v0[0], v4[0]-v0[0], 01142 v5[1]-v0[1], v6[1]-v0[1], v4[1]-v0[1], 01143 v5[2]-v0[2], v6[2]-v0[2], v4[2]-v0[2] 01144 ).Inversed() ); 01145 // 1-5-6-0 01146 storedMatrices.push_back( Matrix3x3<T>( 01147 v5[0]-v1[0], v6[0]-v1[0], v0[0]-v1[0], 01148 v5[1]-v1[1], v6[1]-v1[1], v0[1]-v1[1], 01149 v5[2]-v1[2], v6[2]-v1[2], v0[2]-v1[2] 01150 ).Inversed() ); 01151 // 1-6-2-0 01152 storedMatrices.push_back( Matrix3x3<T>( 01153 v6[0]-v1[0], v2[0]-v1[0], v0[0]-v1[0], 01154 v6[1]-v1[1], v2[1]-v1[1], v0[1]-v1[1], 01155 v6[2]-v1[2], v2[2]-v1[2], v0[2]-v1[2] 01156 ).Inversed() ); 01157 } 01158 01159 bool notFound = true; 01160 unsigned int elementID = enumber * 6; 01161 unsigned int matID = checkedElements[enumber] * 6; 01162 01163 // 0-2-3-6 01164 if ( notFound ) { 01165 Vector3<T> baryCoords = storedMatrices[matID] * (P-v0); 01166 if ( 01167 0 <= baryCoords[0] && baryCoords[0] <= 1 01168 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01169 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01170 { 01171 notFound = false; 01172 rBaryCoords.push_back( 01173 TetBarycentricCoordsForVertexRef<T>( 01174 pVertex->RefToPosition(), 01175 NULL, 01176 baryCoords[0], baryCoords[1], baryCoords[2] 01177 ) 01178 ); 01179 pValidElements[k][j][i][0] = true; 01180 //r_ElementID.push_back( elementID ); 01181 rBaryCoords[count].SetElementID( elementID ); 01182 ++count; 01183 //std::cout << "0 baryCoords: " << baryCoords << "\n"; 01184 } 01185 } 01186 // 0-3-7-6 01187 if ( notFound ) { 01188 Vector3<T> baryCoords = storedMatrices[++matID] * (P-v0); 01189 if ( 01190 0 <= baryCoords[0] && baryCoords[0] <= 1 01191 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01192 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01193 { 01194 notFound = false; 01195 rBaryCoords.push_back( 01196 TetBarycentricCoordsForVertexRef<T>( 01197 pVertex->RefToPosition(), 01198 NULL, 01199 baryCoords[0], baryCoords[1], baryCoords[2] 01200 ) 01201 ); 01202 pValidElements[k][j][i][1] = true; 01203 //r_ElementID.push_back( elementID+1 ); 01204 rBaryCoords[count].SetElementID( elementID+1 ); 01205 ++count; 01206 //std::cout << "1 baryCoords: " << baryCoords << "\n"; 01207 } 01208 } 01209 // 0-7-4-6 01210 if ( notFound ) { 01211 Vector3<T> baryCoords = storedMatrices[++matID] * (P-v0); 01212 if ( 01213 0 <= baryCoords[0] && baryCoords[0] <= 1 01214 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01215 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01216 { 01217 notFound = false; 01218 rBaryCoords.push_back( 01219 TetBarycentricCoordsForVertexRef<T>( 01220 pVertex->RefToPosition(), 01221 NULL, 01222 baryCoords[0], baryCoords[1], baryCoords[2] 01223 ) 01224 ); 01225 pValidElements[k][j][i][2] = true; 01226 //r_ElementID.push_back( elementID+2 ); 01227 rBaryCoords[count].SetElementID( elementID+2 ); 01228 ++count; 01229 //std::cout << "2 baryCoords: " << baryCoords << "\n"; 01230 } 01231 } 01232 // 0-5-6-4 01233 if ( notFound ) { 01234 Vector3<T> baryCoords = storedMatrices[++matID] * (P-v0); 01235 if ( 01236 0 <= baryCoords[0] && baryCoords[0] <= 1 01237 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01238 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01239 { 01240 notFound = false; 01241 rBaryCoords.push_back( 01242 TetBarycentricCoordsForVertexRef<T>( 01243 pVertex->RefToPosition(), 01244 NULL, 01245 baryCoords[0], baryCoords[1], baryCoords[2] 01246 ) 01247 ); 01248 pValidElements[k][j][i][3] = true; 01249 //r_ElementID.push_back( elementID+3 ); 01250 rBaryCoords[count].SetElementID( elementID+3 ); 01251 ++count; 01252 //std::cout << "3 baryCoords: " << baryCoords << "\n"; 01253 } 01254 } 01255 // 1-5-6-0 01256 if ( notFound ) { 01257 Vector3<T> baryCoords = storedMatrices[++matID] * (P-v1); 01258 if ( 01259 0 <= baryCoords[0] && baryCoords[0] <= 1 01260 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01261 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01262 { 01263 notFound = false; 01264 rBaryCoords.push_back( 01265 TetBarycentricCoordsForVertexRef<T>( 01266 pVertex->RefToPosition(), 01267 NULL, 01268 baryCoords[0], baryCoords[1], baryCoords[2] 01269 ) 01270 ); 01271 pValidElements[k][j][i][4] = true; 01272 //r_ElementID.push_back( elementID+4 ); 01273 rBaryCoords[count].SetElementID( elementID+4 ); 01274 ++count; 01275 //std::cout << "4 baryCoords: " << baryCoords << "\n"; 01276 } 01277 } 01278 // 1-6-2-0 01279 if ( notFound ) { 01280 Vector3<T> baryCoords = storedMatrices[++matID] * (P-v1); 01281 if ( 01282 0 <= baryCoords[0] && baryCoords[0] <= 1 01283 && 0 <= baryCoords[1] && baryCoords[1] <= 1 01284 && 0 <= baryCoords[2] && baryCoords[2] <= 1 ) 01285 { 01286 notFound = false; 01287 rBaryCoords.push_back( 01288 TetBarycentricCoordsForVertexRef<T>( 01289 pVertex->RefToPosition(), 01290 NULL, 01291 baryCoords[0], baryCoords[1], baryCoords[2] 01292 ) 01293 ); 01294 pValidElements[k][j][i][5] = true; 01295 //r_ElementID.push_back( elementID+5 ); 01296 rBaryCoords[count].SetElementID( elementID+5 ); 01297 ++count; 01298 //std::cout << "5 baryCoords: " << baryCoords << "\n"; 01299 } 01300 } 01301 01302 pVertex = pVertex->Next(); 01303 } 01304 01305 // Set the barycentric pointer for each vertex 01306 // MUST BE DONE AFTER ALL BARY COORDS ARE GENERATED! 01307 // OTHERWISE THE POINTERS WILL NOT BE VALID DUE TO 01308 // THE AUTOMATICAL RESIZING OF STD::VECTOR! 01309 count = 0; 01310 pVertex = pHEModel->GetVertexList()->Head(); 01311 while ( pVertex != NULL ) { 01312 pVertex->SetBarycentricPtr( &rBaryCoords[count] ); 01313 //std::cout << count << "\tTet\t" << pVertex << "\t" << pVertex->GetBarycentricPtr() << "\t" << *(pVertex->GetBarycentricPtr()) << "\n"; 01314 pVertex = pVertex->Next(); 01315 ++count; 01316 } 01317 01318 // DEBUG 01319 //std::cout << "Surface mesh with Tetrahedral FEM mesh - #surface mesh vertices: " << pHEModel->GetNumVertices() << "\n"; 01320 //std::cout << "Surface mesh with Tetrahedral FEM mesh - #barycoords (must equal to # surface mesh vertices): " << count << "\n"; 01321 //std::cout << "#ElementIDs: " << r_ElementID.size() << "\n"; 01322 //for ( unsigned int i = 0; i < r_ElementID.size(); ++i ) { 01323 // std::cout << "ElementID["<<i<<"]: " << r_ElementID[i] << "\n"; 01324 //} 01325 //std::cout << "#BaryCoords: " << rBaryCoords.size() << "\n"; 01326 //for ( unsigned int i = 0; i < rBaryCoords.size(); ++i ) { 01327 // std::cout << "rBaryCoords["<<i<<"]: " << rBaryCoords[i] << "\n"; 01328 //} 01329 } 01330 01331 //============================================================================= 01332 END_NAMESPACE_TAPs__FEM 01333 //34567890123456789012345678901234567890123456789012345678901234567890123456789 01334 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----