$treeview $search $mathjax
|
Palabos
Version 1.1
$projectbrief
|
$projectbrief
|
$searchbox |
00001 /* This file is part of the Palabos library. 00002 * 00003 * Copyright (C) 2011 FlowKit Sarl 00004 * Avenue de Chailly 23 00005 * 1012 Lausanne, Switzerland 00006 * E-mail contact: contact@flowkit.com 00007 * 00008 * The most recent release of Palabos can be downloaded at 00009 * <http://www.palabos.org/> 00010 * 00011 * The library Palabos is free software: you can redistribute it and/or 00012 * modify it under the terms of the GNU Affero General Public License as 00013 * published by the Free Software Foundation, either version 3 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * The library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Affero General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Affero General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 #ifndef INNER_FLOW_BOUNDARY_3D_HH 00026 #define INNER_FLOW_BOUNDARY_3D_HH 00027 00028 #include "core/globalDefs.h" 00029 #include "offLattice/triangleBoundary3D.h" 00030 #include "offLattice/triangularSurfaceMesh.h" 00031 #include "offLattice/offLatticeBoundaryProfiles3D.h" 00032 #include "offLattice/triangleToDef.h" 00033 #include "multiBlock/nonLocalTransfer3D.h" 00034 #include <cmath> 00035 #include <limits> 00036 00037 namespace plb { 00038 00039 /******** class BoundaryProfiles3D *****************************************/ 00040 00041 template<typename T, class SurfaceData> 00042 BoundaryProfiles3D<T,SurfaceData>::BoundaryProfiles3D() 00043 { 00044 wallProfile = generateDefaultWallProfile3D<T,SurfaceData>(); 00045 replaceProfile(0, wallProfile->clone()); 00046 } 00047 00048 template<typename T, class SurfaceData> 00049 BoundaryProfiles3D<T,SurfaceData>::~BoundaryProfiles3D() { 00050 clearProfiles(); 00051 delete wallProfile; 00052 } 00053 00054 template<typename T, class SurfaceData> 00055 BoundaryProfiles3D<T,SurfaceData>::BoundaryProfiles3D(BoundaryProfiles3D<T,SurfaceData> const& rhs) 00056 { 00057 wallProfile = rhs.wallProfile->clone(); 00058 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::const_iterator it = rhs.profiles.begin(); 00059 for (; it!=rhs.profiles.end(); ++it) { 00060 profiles.insert ( 00061 std::pair<plint,BoundaryProfile3D<T,SurfaceData>*> ( 00062 it->first,it->second->clone() ) ); 00063 } 00064 inletOutletIds = rhs.inletOutletIds; 00065 lidNormal = rhs.lidNormal; 00066 lidCenter = rhs.lidCenter; 00067 lidRadius = rhs.lidRadius; 00068 } 00069 00070 template<typename T, class SurfaceData> 00071 BoundaryProfiles3D<T,SurfaceData>& BoundaryProfiles3D<T,SurfaceData>::operator= ( 00072 BoundaryProfiles3D<T,SurfaceData> const& rhs ) 00073 { 00074 BoundaryProfiles3D<T,SurfaceData>(rhs).swap(*this); 00075 } 00076 00077 template<typename T, class SurfaceData> 00078 void BoundaryProfiles3D<T,SurfaceData>::swap(BoundaryProfiles3D<T,SurfaceData>& rhs) { 00079 std::swap(wallProfile, rhs.wallProfile); 00080 profiles.swap(rhs.profiles); 00081 inletOutletIds.swap(rhs.inletOutletIds); 00082 lidNormal.swap(rhs.lidNormal); 00083 lidCenter.swap(rhs.lidCenter); 00084 lidRadius.swap(rhs.lidRadius); 00085 } 00086 00087 template<typename T, class SurfaceData> 00088 void BoundaryProfiles3D<T,SurfaceData>::setWallProfile(BoundaryProfile3D<T,SurfaceData>* wallProfile_) 00089 { 00090 PLB_PRECONDITION( wallProfile_ ); 00091 delete wallProfile; 00092 wallProfile = wallProfile_; 00093 replaceProfile(0, wallProfile->clone()); 00094 } 00095 00096 template<typename T, class SurfaceData> 00097 void BoundaryProfiles3D<T,SurfaceData>::resetProfiles(std::map<plint,BoundaryProfile3D<T,SurfaceData>*> profiles_) 00098 { 00099 PLB_ASSERT( !profiles_.empty() ); 00100 clearProfiles(); 00101 profiles = profiles_; 00102 } 00103 00104 template<typename T, class SurfaceData> 00105 void BoundaryProfiles3D<T,SurfaceData>::defineInletOutletTags ( 00106 TriangleBoundary3D<T> const& boundary, plint sortDirection ) 00107 { 00108 inletOutletIds = boundary.getInletOutletIds(sortDirection); 00109 boundary.getLidProperties(sortDirection, lidNormal, lidCenter, lidRadius); 00110 } 00111 00112 template<typename T, class SurfaceData> 00113 void BoundaryProfiles3D<T,SurfaceData>::adjustInletOutlet ( 00114 TriangleBoundary3D<T> const& boundary, plint sortDirection ) 00115 { 00116 boundary.getLidProperties(sortDirection, lidNormal, lidCenter, lidRadius); 00117 for (pluint iProfile=0; iProfile<inletOutletIds.size(); ++iProfile) { 00118 plint id = inletOutletIds[iProfile]; 00119 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::iterator it = profiles.find(id); 00120 PLB_ASSERT( it != profiles.end() ); 00121 it->second->setNormal(lidNormal[iProfile]); 00122 it->second->defineCircularShape(lidCenter[iProfile], lidRadius[iProfile]); 00123 } 00124 } 00125 00126 template<typename T, class SurfaceData> 00127 void BoundaryProfiles3D<T,SurfaceData>::setInletOutlet ( 00128 std::vector<BoundaryProfile3D<T,SurfaceData>*> inletOutlets ) 00129 { 00130 PLB_ASSERT( inletOutletIds.size() == inletOutlets.size() ); 00131 std::map<plint,BoundaryProfile3D<T,SurfaceData>*> newProfiles; 00132 newProfiles[0] = wallProfile->clone(); 00133 for (pluint iProfile=0; iProfile<inletOutlets.size(); ++iProfile) { 00134 plint id = inletOutletIds[iProfile]; 00135 #ifdef PLB_DEBUG 00136 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::const_iterator it = newProfiles.find(id); 00137 PLB_ASSERT( it==newProfiles.end() ); 00138 #endif 00139 newProfiles[id] = inletOutlets[iProfile]; 00140 newProfiles[id]->setNormal(lidNormal[iProfile]); 00141 newProfiles[id]->defineCircularShape(lidCenter[iProfile], lidRadius[iProfile]); 00142 00143 } 00144 resetProfiles(newProfiles); 00145 } 00146 00147 template<typename T, class SurfaceData> 00148 void BoundaryProfiles3D<T,SurfaceData>::setInletOutlet ( 00149 BoundaryProfile3D<T,SurfaceData>* profile1, BoundaryProfile3D<T,SurfaceData>* profile2 ) 00150 { 00151 std::vector<BoundaryProfile3D<T,SurfaceData>*> inletOutlets(2); 00152 inletOutlets[0] = profile1; 00153 inletOutlets[1] = profile2; 00154 setInletOutlet(inletOutlets); 00155 } 00156 00157 template<typename T, class SurfaceData> 00158 void BoundaryProfiles3D<T,SurfaceData>::setInletOutlet ( 00159 BoundaryProfile3D<T,SurfaceData>* profile1, BoundaryProfile3D<T,SurfaceData>* profile2, 00160 BoundaryProfile3D<T,SurfaceData>* profile3 ) 00161 { 00162 std::vector<BoundaryProfile3D<T,SurfaceData>*> inletOutlets(3); 00163 inletOutlets[0] = profile1; 00164 inletOutlets[1] = profile2; 00165 inletOutlets[2] = profile3; 00166 setInletOutlet(inletOutlets); 00167 } 00168 00169 template<typename T, class SurfaceData> 00170 void BoundaryProfiles3D<T,SurfaceData>::setInletOutlet ( 00171 BoundaryProfile3D<T,SurfaceData>* profile1, BoundaryProfile3D<T,SurfaceData>* profile2, 00172 BoundaryProfile3D<T,SurfaceData>* profile3, BoundaryProfile3D<T,SurfaceData>* profile4 ) 00173 { 00174 std::vector<BoundaryProfile3D<T,SurfaceData>*> inletOutlets(4); 00175 inletOutlets[0] = profile1; 00176 inletOutlets[1] = profile2; 00177 inletOutlets[2] = profile3; 00178 inletOutlets[3] = profile4; 00179 setInletOutlet(inletOutlets); 00180 } 00181 00182 template<typename T, class SurfaceData> 00183 void BoundaryProfiles3D<T,SurfaceData>::defineProfile ( 00184 plint tag, BoundaryProfile3D<T,SurfaceData>* profile ) 00185 { 00186 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::iterator it = profiles.find(tag); 00187 if (it!=profiles.end()) { 00188 delete it->second; 00189 } 00190 profiles[tag] = profile; 00191 } 00192 00193 template<typename T, class SurfaceData> 00194 BoundaryProfile3D<T,SurfaceData> const& BoundaryProfiles3D<T,SurfaceData>::getProfile ( 00195 TriangleBoundary3D<T> const& boundary, plint iTriangle ) const 00196 { 00197 PLB_ASSERT( iTriangle < (plint) boundary.getTriangleTags().size() ); 00198 plint triangleTag = boundary.getTriangleTags()[iTriangle]; 00199 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::const_iterator it = profiles.find(triangleTag); 00200 if (it==profiles.end()) { 00201 PLB_ASSERT(wallProfile); 00202 return *wallProfile; 00203 } 00204 else { 00205 PLB_ASSERT(it->second); 00206 return *(it->second); 00207 } 00208 } 00209 00210 template<typename T, class SurfaceData> 00211 void BoundaryProfiles3D<T,SurfaceData>::replaceProfile ( 00212 plint id, BoundaryProfile3D<T,SurfaceData>* newProfile ) 00213 { 00214 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::iterator it = profiles.find(id); 00215 if (it!=profiles.end()) { 00216 delete it->second; 00217 } 00218 profiles[id] = newProfile; 00219 } 00220 00221 template<typename T, class SurfaceData> 00222 void BoundaryProfiles3D<T,SurfaceData>::clearProfiles() { 00223 typename std::map<plint,BoundaryProfile3D<T,SurfaceData>*>::iterator it = profiles.begin(); 00224 for (; it!=profiles.end(); ++it) { 00225 delete it->second; 00226 } 00227 profiles.clear(); 00228 } 00229 00230 /******** class DEFscaledMesh *****************************************/ 00231 00232 template<typename T> 00233 DEFscaledMesh<T>::DEFscaledMesh ( 00234 TriangleSet<T> const& triangleSet_ ) 00235 : margin(0) 00236 { 00237 initialize(triangleSet_, 0, 0, Dot3D()); 00238 } 00239 00240 template<typename T> 00241 DEFscaledMesh<T>::DEFscaledMesh ( 00242 TriangleSet<T> const& triangleSet_, 00243 plint resolution_, plint referenceDirection_, 00244 plint margin_, Dot3D location ) 00245 : margin(margin_) 00246 { 00247 initialize(triangleSet_, resolution_, referenceDirection_, location); 00248 } 00249 00250 template<typename T> 00251 DEFscaledMesh<T>::DEFscaledMesh ( 00252 TriangleSet<T> const& triangleSet_, 00253 plint resolution_, plint referenceDirection_, 00254 plint margin_, plint extraLayer ) 00255 : margin(margin_) 00256 { 00257 plint layer = margin+extraLayer; 00258 initialize( triangleSet_, resolution_, referenceDirection_, 00259 Dot3D(layer,layer,layer) ); 00260 } 00261 00262 template<typename T> 00263 DEFscaledMesh<T>::~DEFscaledMesh() { 00264 delete mesh; 00265 } 00266 00267 template<typename T> 00268 void DEFscaledMesh<T>::initialize ( 00269 TriangleSet<T> const& triangleSet_, plint resolution_, 00270 plint referenceDirection_, Dot3D location ) 00271 { 00272 T eps = getEpsilon<T>(triangleSet_.getPrecision()); 00273 00274 constructSurfaceMesh<T> ( 00275 triangleSet_.getTriangles(), 00276 vertexList, emanatingEdgeList, edgeList, eps ); 00277 mesh = new TriangularSurfaceMesh<T>(vertexList, emanatingEdgeList, edgeList); 00278 00279 if (resolution_!=0) { 00280 // Convert the mesh to lattice units. 00281 toLatticeUnits<T> ( 00282 getMesh(), resolution_, referenceDirection_, physicalLocation, dx ); 00283 00284 Array<T,3> luOffset(location.x,location.y,location.z); 00285 getMesh().translate(luOffset); 00286 physicalLocation -= luOffset*dx; 00287 } 00288 } 00289 00290 template<typename T> 00291 DEFscaledMesh<T>::DEFscaledMesh ( 00292 DEFscaledMesh<T> const& rhs ) 00293 : vertexList(rhs.vertexList), 00294 emanatingEdgeList(rhs.emanatingEdgeList), 00295 edgeList(rhs.edgeList), 00296 margin(rhs.margin) 00297 { 00298 mesh = new TriangularSurfaceMesh<T>(vertexList, emanatingEdgeList, edgeList); 00299 } 00300 00301 template<typename T> 00302 DEFscaledMesh<T>& 00303 DEFscaledMesh<T>::operator=(DEFscaledMesh<T> const& rhs) 00304 { 00305 DEFscaledMesh<T>(rhs).swap(*this); 00306 return *this; 00307 } 00308 00309 template<typename T> 00310 void DEFscaledMesh<T>::swap(DEFscaledMesh<T>& rhs) 00311 { 00312 vertexList.swap(rhs.vertexList); 00313 emanatingEdgeList.swap(rhs.emanatingEdgeList); 00314 edgeList.swap(rhs.edgeList); 00315 std::swap(mesh,rhs.mesh); 00316 std::swap(margin, rhs.margin); 00317 std::swap(physicalLocation, rhs.physicalLocation); 00318 std::swap(dx, rhs.dx); 00319 } 00320 00321 template<typename T> 00322 TriangularSurfaceMesh<T> const& DEFscaledMesh<T>::getMesh() const 00323 { 00324 return *mesh; 00325 } 00326 00327 template<typename T> 00328 TriangularSurfaceMesh<T>& DEFscaledMesh<T>::getMesh() 00329 { 00330 return *mesh; 00331 } 00332 00333 template<typename T> 00334 plint DEFscaledMesh<T>::getMargin() const { 00335 return margin; 00336 } 00337 00338 00339 /******** class TriangleBoundary3D *****************************************/ 00340 00341 template<typename T> 00342 TriangleBoundary3D<T>::TriangleBoundary3D ( 00343 DEFscaledMesh<T> const& defMesh, bool automaticCloseHoles ) 00344 : currentTagNum(0), 00345 margin(defMesh.getMargin()), 00346 physicalLocation(defMesh.getPhysicalLocation()), 00347 dx(defMesh.getDx()) 00348 { 00349 topology.push(1); // By default, closed mesh. 00350 vertexSet.push(0); // By default, static mesh. 00351 00352 vertexLists.reserve(3); // Vertex lists are expensive to copy. Better 00353 // pre-allocate a slot for three of them. 00354 vertexLists.push_back(defMesh.getVertexList()); 00355 emanatingEdgeLists[0] = defMesh.getEmanatingEdgeList(); 00356 edgeLists[0] = defMesh.getEdgeList(); 00357 00358 emanatingEdgeLists[1] = emanatingEdgeLists[0]; 00359 edgeLists[1] = edgeLists[0]; 00360 00361 meshes.push_back(TriangularSurfaceMesh<T> ( 00362 vertexLists[0], emanatingEdgeLists[0], edgeLists[0] ) ); 00363 meshes.push_back(TriangularSurfaceMesh<T> ( 00364 vertexLists[0], emanatingEdgeLists[1], edgeLists[1] ) ); 00365 00366 // Prepare the vector "triangle type", which later on will inform on 00367 // the type of boundary condition implemented by a given triangle. 00368 // The default, 0, stands for no-slip. 00369 triangleTagList.resize(meshes[1].getNumTriangles()); 00370 std::fill(triangleTagList.begin(), triangleTagList.end(), 0); 00371 00372 if (automaticCloseHoles) { 00373 closeHoles(); 00374 } 00375 } 00376 00377 template<typename T> 00378 void TriangleBoundary3D<T>::closeHoles() 00379 { 00380 // Close the holes and assign inlets/outlets. 00381 std::vector<typename TriangularSurfaceMesh<T>::Lid> newlids 00382 = meshes[1].closeHoles(); 00383 00384 // Prepare the vector "triangle type", which later on will inform on 00385 // the type of boundary condition implemented by a given triangle. 00386 // The default, 0, stands for no-slip. 00387 pluint oldNumTriangles = triangleTagList.size(); 00388 triangleTagList.resize(meshes[1].getNumTriangles()); 00389 std::fill(triangleTagList.begin()+oldNumTriangles, triangleTagList.end(), 0); 00390 00391 // Assign default functions to inlet/outlets to avoid undefined state. 00392 tagInletOutlet(newlids); 00393 lids.insert(lids.end(),newlids.begin(),newlids.end()); 00394 assignLidVertexProperty(); 00395 } 00396 00397 template<typename T> 00398 TriangleBoundary3D<T>::~TriangleBoundary3D() { 00399 for (pluint iProp=0; iProp<vertexProperties.size(); ++iProp) { 00400 delete vertexProperties[iProp]; 00401 } 00402 } 00403 00404 template<typename T> 00405 TriangleBoundary3D<T>::TriangleBoundary3D ( 00406 TriangleBoundary3D<T> const& rhs ) 00407 : vertexLists(rhs.vertexLists), 00408 emanatingEdgeLists(rhs.emanatingEdgeLists), 00409 edgeLists(rhs.edgeLists), 00410 triangleTagList(rhs.triangleTagList), 00411 currentTagNum(rhs.currentTagNum), 00412 vertexTagList(rhs.vertexTagList), 00413 vertexProperties(rhs.vertexProperties.size()), 00414 lids(rhs.lids), 00415 margin(rhs.margin), 00416 topology(rhs.topology), 00417 vertexSet(rhs.vertexSet) 00418 { 00419 defineMeshes(); 00420 for (pluint iProp=0; iProp<vertexProperties.size(); ++iProp) { 00421 vertexProperties[iProp] = rhs.vertexProperties[iProp]->clone(); 00422 } 00423 } 00424 00425 template<typename T> 00426 void TriangleBoundary3D<T>::defineMeshes() { 00427 meshes.clear(); 00428 for (pluint iVertices=0; iVertices<vertexLists.size(); ++iVertices) { 00429 meshes.push_back( TriangularSurfaceMesh<T> ( 00430 vertexLists[iVertices], emanatingEdgeLists[0], edgeLists[0]) ); 00431 meshes.push_back( TriangularSurfaceMesh<T> ( 00432 vertexLists[iVertices], emanatingEdgeLists[1], edgeLists[1]) ); 00433 } 00434 } 00435 00436 template<typename T> 00437 TriangleBoundary3D<T>& 00438 TriangleBoundary3D<T>::operator=(TriangleBoundary3D<T> const& rhs) 00439 { 00440 TriangleBoundary3D<T>(rhs).swap(*this); 00441 return *this; 00442 } 00443 00444 template<typename T> 00445 void TriangleBoundary3D<T>::swap(TriangleBoundary3D<T>& rhs) 00446 { 00447 vertexLists.swap(rhs.vertexLists); 00448 emanatingEdgeLists[0].swap(rhs.emanatingEdgeLists[0]); 00449 emanatingEdgeLists[1].swap(rhs.emanatingEdgeLists[1]); 00450 edgeLists[0].swap(rhs.edgeLists[0]); 00451 edgeLists[1].swap(rhs.edgeLists[1]); 00452 triangleTagList.swap(rhs.triangleTagList); 00453 std::swap(currentTagNum, rhs.currentTagNum); 00454 vertexTagList.swap(rhs.vertexTagList); 00455 vertexProperties.swap(rhs.vertexProperties); 00456 std::swap(lids, rhs.lids); 00457 std::swap(margin, rhs.margin); 00458 std::swap(topology, rhs.topology); 00459 std::swap(vertexSet, rhs.vertexSet); 00460 defineMeshes(); 00461 } 00462 00463 template<typename T> 00464 TriangleBoundary3D<T> const& 00465 TriangleBoundary3D<T>::select ( 00466 plint whichTopology, plint whichVertices ) const 00467 { 00468 PLB_PRECONDITION( whichTopology==0 || whichTopology==1 ); 00469 PLB_PRECONDITION( whichVertices>=0 && whichVertices < (plint)vertexLists.size() ); 00470 topology.top() = whichTopology; 00471 vertexSet.top() = whichVertices; 00472 return *this; 00473 } 00474 00475 template<typename T> 00476 TriangleBoundary3D<T> const& 00477 TriangleBoundary3D<T>::pushSelect ( 00478 plint whichTopology, plint whichVertices ) const 00479 { 00480 PLB_PRECONDITION( whichTopology==0 || whichTopology==1 ); 00481 PLB_PRECONDITION( whichVertices>=0 && whichVertices < (plint)vertexLists.size() ); 00482 topology.push(whichTopology); 00483 vertexSet.push(whichVertices); 00484 return *this; 00485 } 00486 00487 template<typename T> 00488 TriangleBoundary3D<T> const& 00489 TriangleBoundary3D<T>::popSelect() const 00490 { 00491 PLB_PRECONDITION( topology.size() >= 2 ); 00492 PLB_PRECONDITION( vertexSet.size() >= 2 ); 00493 topology.pop(); 00494 vertexSet.pop(); 00495 return *this; 00496 } 00497 00498 template<typename T> 00499 void TriangleBoundary3D<T>::getSelection ( 00500 plint& whichTopology, plint& whichVertices ) const 00501 { 00502 whichTopology = topology.top(); 00503 whichVertices = vertexSet.top(); 00504 } 00505 00506 template<typename T> 00507 plint TriangleBoundary3D<T>::currentMesh() const { 00508 return 2*vertexSet.top()+topology.top(); 00509 } 00510 00511 template<typename T> 00512 TriangularSurfaceMesh<T> const& TriangleBoundary3D<T>::getMesh() const 00513 { 00514 return meshes[currentMesh()]; 00515 } 00516 00517 template<typename T> 00518 TriangularSurfaceMesh<T>& TriangleBoundary3D<T>::getMesh() 00519 { 00520 return meshes[currentMesh()]; 00521 } 00522 00523 template<typename T> 00524 plint TriangleBoundary3D<T>::getMargin() const { 00525 return margin; 00526 } 00527 00528 template<typename T> 00529 plint TriangleBoundary3D<T>::getTag(plint iTriangle) const { 00530 PLB_ASSERT( iTriangle<(plint)triangleTagList.size() ); 00531 return triangleTagList[iTriangle]; 00532 } 00533 00534 template<typename T> 00535 VertexProperty3D<T> const* 00536 TriangleBoundary3D<T>::getVertexProperty(plint iVertex) const 00537 { 00538 if (vertexTagList.empty()) { 00539 return 0; 00540 } 00541 PLB_ASSERT( iVertex < (plint)vertexTagList.size() ); 00542 return vertexProperties[vertexTagList[iVertex]]; 00543 } 00544 00545 template<typename T> 00546 bool TriangleBoundary3D<T>::intersectSegment ( 00547 plint iTriangle, AtomicBlock3D* boundaryArg, 00548 Array<T,3> const& fromPoint, Array<T,3> const& direction, 00549 Array<T,3>& locatedPoint, T& distance, Array<T,3>& wallNormal ) const 00550 { 00551 int flag = 0; // Intersection with line segment. 00552 Array<T,3> point2(fromPoint+direction); 00553 bool doesIntersect = 00554 getMesh().pointOnTriangle(fromPoint, point2, flag, iTriangle, 00555 locatedPoint, wallNormal, distance) == 1; 00556 return doesIntersect; 00557 } 00558 00559 template<typename T> 00560 Array<T,3> TriangleBoundary3D<T>::computeContinuousNormal ( 00561 Array<T,3> const& p, plint iTriangle, bool isAreaWeighted ) const 00562 { 00563 return getMesh().computeContinuousNormal(p, iTriangle, isAreaWeighted); 00564 } 00565 00566 template<typename T> 00567 void TriangleBoundary3D<T>::cloneVertexSet(plint whichVertexSet) 00568 { 00569 PLB_PRECONDITION( whichVertexSet < (plint)vertexLists.size() && 00570 whichVertexSet >= 0 ); 00571 vertexLists.push_back(vertexLists[whichVertexSet]); 00572 plint newVertexSet = (plint)vertexLists.size()-1; 00573 plint numVertexOpen = vertexLists[newVertexSet].size(); 00574 for (plint iLid=0; (plint)iLid<lids.size(); ++iLid) { 00575 numVertexOpen -= lids[iLid].numAddedVertices; 00576 } 00577 meshes.push_back( TriangularSurfaceMesh<T> ( 00578 vertexLists[newVertexSet], emanatingEdgeLists[0], edgeLists[0], numVertexOpen ) ); 00579 meshes.push_back( TriangularSurfaceMesh<T> ( 00580 vertexLists[newVertexSet], emanatingEdgeLists[1], edgeLists[1]) ); 00581 } 00582 00583 template<typename T> 00584 std::vector<typename TriangularSurfaceMesh<T>::Lid> const& 00585 TriangleBoundary3D<T>::getInletOutlet() const 00586 { 00587 PLB_PRECONDITION( topology.top()==1 ); 00588 return lids; 00589 } 00590 00591 template<typename T> 00592 std::vector<typename TriangularSurfaceMesh<T>::Lid> 00593 TriangleBoundary3D<T>::getInletOutlet(plint sortDirection) const 00594 { 00595 PLB_PRECONDITION( topology.top()==1 ); 00596 std::vector<typename TriangularSurfaceMesh<T>::Lid> lids_copy(lids); 00597 std::sort(lids_copy.begin(), lids_copy.end(), LidLessThan<T>(sortDirection, getMesh())); 00598 return lids_copy; 00599 } 00600 00601 template<typename T> 00602 std::vector<plint> TriangleBoundary3D<T>::getInletOutletIds(plint sortDirection) const { 00603 std::map<plint,plint> triangleToOriginalLid; 00604 for (pluint iLid=0; iLid<lids.size(); ++iLid) { 00605 triangleToOriginalLid[lids[iLid].firstTriangle] = iLid; 00606 } 00607 std::vector<typename TriangularSurfaceMesh<T>::Lid> tmpLids(lids); 00608 std::sort(tmpLids.begin(), tmpLids.end(), LidLessThan<T>(sortDirection, getMesh())); 00609 std::vector<plint> ids(tmpLids.size()); 00610 for (pluint iLid=0; iLid<tmpLids.size(); ++iLid) { 00611 plint originalId = triangleToOriginalLid[tmpLids[iLid].firstTriangle]; 00612 ids[iLid] = originalId+1; 00613 } 00614 return ids; 00615 } 00616 00617 template<typename T> 00618 void TriangleBoundary3D<T>::getLidProperties ( 00619 plint sortDirection, std::vector<Array<T,3> >& normal, 00620 std::vector<Array<T,3> >& center, std::vector<T>& radius ) const 00621 { 00622 // Lid properties can only be computed in a closed mesh, by definition. 00623 PLB_PRECONDITION( topology.top()==1 ); 00624 std::vector<typename TriangularSurfaceMesh<T>::Lid> tmpLids(lids); 00625 std::sort(tmpLids.begin(), tmpLids.end(), LidLessThan<T>(sortDirection, getMesh())); 00626 normal.resize(tmpLids.size()); 00627 center.resize(tmpLids.size()); 00628 radius.resize(tmpLids.size()); 00629 for (pluint iLid=0; iLid<tmpLids.size(); ++iLid) { 00630 normal[iLid] = computeNormal(getMesh(), tmpLids[iLid]); 00631 center[iLid] = computeBaryCenter(getMesh(), tmpLids[iLid]); 00632 radius[iLid] = (T)0.5 * ( 00633 computeInnerRadius(getMesh(), tmpLids[iLid]) + 00634 computeOuterRadius(getMesh(), tmpLids[iLid]) ); 00635 } 00636 } 00637 00638 template<typename T> 00639 void TriangleBoundary3D<T>::tagInletOutlet ( 00640 std::vector<typename TriangularSurfaceMesh<T>::Lid> const& newLids ) 00641 { 00642 // Inlet/Outlet can only be set for a closed mesh, by definition. 00643 PLB_PRECONDITION( topology.top()==1 ); 00644 00645 for (pluint iLid=0; iLid<newLids.size(); ++iLid) { 00646 ++currentTagNum; // Tag 0 is for default wall portions. 00647 plint firstTriangle = newLids[iLid].firstTriangle; 00648 plint numTriangles = newLids[iLid].numTriangles; 00649 for (plint iTriangle = firstTriangle; iTriangle<firstTriangle+numTriangles; ++iTriangle) 00650 { 00651 triangleTagList[iTriangle] = currentTagNum; 00652 } 00653 } 00654 } 00655 00656 template<typename T> 00657 template<typename DomainFunctional> 00658 plint TriangleBoundary3D<T>::tagDomain(DomainFunctional functional) 00659 { 00660 // Make sure we're working with the closed mesh. 00661 PLB_PRECONDITION( topology.top()==1 ); 00662 ++currentTagNum; 00663 plint newTag = currentTagNum; 00664 for (plint iTriangle=0; iTriangle<getMesh().getNumTriangles(); ++iTriangle) { 00665 bool isInside = true; 00666 for (plint iVertex=0; iVertex<3; ++iVertex) { 00667 Array<T,3> vertex = getMesh().getVertex(iTriangle, iVertex); 00668 if (!functional(vertex)) { 00669 isInside = false; 00670 break; 00671 } 00672 } 00673 if (isInside) { 00674 triangleTagList[iTriangle] = newTag; 00675 } 00676 } 00677 return newTag; 00678 } 00679 00680 template<typename T> 00681 template<typename DomainFunctional> 00682 plint TriangleBoundary3D<T>::tagDomain(DomainFunctional functional, Array<T,3> normal, T angleTolerance, plint previousTag) 00683 { 00684 // Make sure we're working with the closed mesh. 00685 PLB_PRECONDITION( topology.top()==1 ); 00686 ++currentTagNum; 00687 plint newTag = currentTagNum; 00688 for (plint iTriangle=0; iTriangle<getMesh().getNumTriangles(); ++iTriangle) { 00689 if (previousTag<0 || triangleTagList[iTriangle]==previousTag) { 00690 bool isInside = true; 00691 for (plint iVertex=0; iVertex<3; ++iVertex) { 00692 Array<T,3> vertex = getMesh().getVertex(iTriangle, iVertex); 00693 if (!functional(vertex)) { 00694 isInside = false; 00695 break; 00696 } 00697 } 00698 if (isInside) { 00699 Array<T,3> triangleNormal = getMesh().computeTriangleNormal(iTriangle); 00700 if (fabs(angleBetweenVectors(normal,triangleNormal)<angleTolerance)) { 00701 triangleTagList[iTriangle] = newTag; 00702 } 00703 } 00704 } 00705 } 00706 return newTag; 00707 } 00708 00709 template<typename T> 00710 template<typename DomainFunctional> 00711 plint TriangleBoundary3D<T>::setVertexProperty ( 00712 VertexProperty3D<T> const& property, DomainFunctional functional ) 00713 { 00714 // Make sure we're working with the closed mesh. 00715 PLB_PRECONDITION( topology.top()==1 ); 00716 if (vertexTagList.empty()) { 00717 PLB_ASSERT(vertexProperties.empty()); 00718 vertexTagList.resize(getMesh().getNumVertices()); 00719 std::fill(vertexTagList.begin(), vertexTagList.end(), 0); 00720 vertexProperties.push_back(0); 00721 } 00722 vertexProperties.push_back(property.clone()); 00723 plint nextTag = (plint)vertexProperties.size()-1; 00724 for (plint iVertex=0; iVertex<getMesh().getNumVertices(); ++iVertex) { 00725 Array<T,3> const& vertex = getMesh().getVertex(iVertex); 00726 bool isInside = functional(vertex); 00727 if (isInside) { 00728 vertexTagList[iVertex] = nextTag; 00729 } 00730 } 00731 return nextTag; 00732 } 00733 00734 template<typename T> 00735 void TriangleBoundary3D<T>::assignLidVertexProperty() 00736 { 00737 // Make sure we're working with the closed mesh. 00738 PLB_PRECONDITION( topology.top()==1 ); 00739 std::vector<typename TriangularSurfaceMesh<T>::Lid> const& lids = getInletOutlet(); 00740 if (lids.empty()) return; 00741 00742 if (vertexTagList.empty()) { 00743 PLB_ASSERT(vertexProperties.empty()); 00744 vertexTagList.resize(getMesh().getNumVertices()); 00745 std::fill(vertexTagList.begin(), vertexTagList.end(), 0); 00746 vertexProperties.push_back(0); 00747 } 00748 00749 vertexProperties.push_back(new InletOutletProperty3D<T>); 00750 plint lidVertexTag = (plint)vertexProperties.size()-1; 00751 for (pluint iLid=0; iLid<lids.size(); ++iLid) { 00752 plint centerVertex = lids[iLid].centerVertex; 00753 vertexTagList[centerVertex] = lidVertexTag; 00754 } 00755 } 00756 00757 00758 /******** class TriangleFlowShape3D ****************************************/ 00759 00760 template< typename T, class SurfaceData > 00761 TriangleFlowShape3D<T,SurfaceData>::TriangleFlowShape3D ( 00762 TriangleBoundary3D<T> const& boundary_, 00763 BoundaryProfiles3D<T,SurfaceData> const& profiles_ ) 00764 : boundary(boundary_), 00765 profiles(profiles_), 00766 voxelFlags(0), hashContainer(0), boundaryArg(0) 00767 { } 00768 00769 template< typename T, class SurfaceData > 00770 bool TriangleFlowShape3D<T,SurfaceData>::isInside ( 00771 Dot3D const& location) const 00772 { 00773 PLB_PRECONDITION( voxelFlags ); 00774 Dot3D localPos = location-voxelFlags->getLocation(); 00775 return voxelFlag::insideFlag(voxelFlags->get(localPos.x,localPos.y,localPos.z)); 00776 } 00777 00778 template< typename T, class SurfaceData > 00779 bool TriangleFlowShape3D<T,SurfaceData>::pointOnSurface ( 00780 Array<T,3> const& fromPoint, Array<T,3> const& direction, 00781 Array<T,3>& locatedPoint, T& distance, 00782 Array<T,3>& wallNormal, SurfaceData& surfaceData, 00783 OffBoundary::Type& bdType, plint& id ) const 00784 { 00785 PLB_PRECONDITION( hashContainer ); // Make sure these arguments have 00786 PLB_PRECONDITION( boundaryArg ); // been provided by the user through 00787 // the clone function. 00788 static const T maxDistance = sqrt(3); 00789 Array<T,2> xRange(fromPoint[0]-maxDistance, fromPoint[0]+maxDistance); 00790 Array<T,2> yRange(fromPoint[1]-maxDistance, fromPoint[1]+maxDistance); 00791 Array<T,2> zRange(fromPoint[2]-maxDistance, fromPoint[2]+maxDistance); 00792 TriangleHash<T> triangleHash(*hashContainer); 00793 std::vector<plint> possibleTriangles; 00794 if (id>=0 && id<boundary.getMesh().getNumTriangles()) { 00795 possibleTriangles.push_back(id); 00796 } 00797 else { 00798 triangleHash.getTriangles(xRange, yRange, zRange, possibleTriangles); 00799 } 00800 00801 Array<T,3> tmpLocatedPoint; 00802 T tmpDistance; 00803 Array<T,3> tmpNormal; 00804 T shortestDistance = T(); 00805 plint locatedTriangle = -1; 00806 00807 for (pluint iPossible=0; iPossible<possibleTriangles.size(); ++iPossible) { 00808 plint iTriangle = possibleTriangles[iPossible]; 00809 if (boundary.intersectSegment( 00810 iTriangle, boundaryArg, 00811 fromPoint, direction, 00812 tmpLocatedPoint, tmpDistance, tmpNormal) ) 00813 { 00814 if (locatedTriangle==-1 || tmpDistance<shortestDistance) { 00815 shortestDistance = tmpDistance; 00816 locatedTriangle = iTriangle; 00817 locatedPoint = tmpLocatedPoint; 00818 distance = tmpDistance; 00819 wallNormal = tmpNormal; 00820 profiles.getProfile(boundary, iTriangle).getData ( 00821 locatedPoint, iTriangle, boundaryArg, surfaceData, bdType ); 00822 } 00823 } 00824 } 00825 if (locatedTriangle != -1) { 00826 id = locatedTriangle; 00827 return true; 00828 } 00829 else { 00830 return false; 00831 } 00832 } 00833 00834 template<typename T, class SurfaceData> 00835 Array<T,3> TriangleFlowShape3D<T,SurfaceData>::computeContinuousNormal ( 00836 Array<T,3> const& p, plint id, bool isAreaWeighted ) const 00837 { 00838 return boundary.computeContinuousNormal(p, id, isAreaWeighted); 00839 } 00840 00841 template<typename T, class SurfaceData> 00842 bool TriangleFlowShape3D<T,SurfaceData>::intersectsSurface ( 00843 Array<T,3> const& p1, Array<T,3> const& p2, plint& id ) const 00844 { 00845 PLB_PRECONDITION( hashContainer ); // Make sure these arguments have 00846 PLB_PRECONDITION( boundaryArg ); // been provided by the user through 00847 // the clone function. 00848 static const T maxDistance = sqrt(3); 00849 Array<T,2> xRange(p1[0]-maxDistance, p1[0]+maxDistance); 00850 Array<T,2> yRange(p1[1]-maxDistance, p1[1]+maxDistance); 00851 Array<T,2> zRange(p1[2]-maxDistance, p1[2]+maxDistance); 00852 TriangleHash<T> triangleHash(*hashContainer); 00853 std::vector<plint> possibleTriangles; 00854 if (id>=0 && id<boundary.getMesh().getNumTriangles()) { 00855 possibleTriangles.push_back(id); 00856 } 00857 else { 00858 triangleHash.getTriangles(xRange, yRange, zRange, possibleTriangles); 00859 } 00860 00861 std::vector<plint> selection; 00862 for (pluint iPossible=0; iPossible<possibleTriangles.size(); ++iPossible) { 00863 plint iTriangle = possibleTriangles[iPossible]; 00864 int flag = 0; 00865 Array<T,3> intersection, normal; 00866 T distance; 00867 if (boundary.getMesh().pointOnTriangle(p1, p2, flag, iTriangle, intersection, normal, distance)) { 00868 selection.push_back(iTriangle); 00869 } 00870 } 00871 if (selection.empty()) { 00872 return false; 00873 } 00874 else if (selection.size()==1) { 00875 id = selection[0]; 00876 return true; 00877 } 00878 else { 00879 Array<T,3> locatedPoint; 00880 T distance; 00881 Array<T,3> wallNormal; 00882 SurfaceData surfaceData; 00883 OffBoundary::Type bdType; 00884 return pointOnSurface(p1, p2-p1, locatedPoint, distance, wallNormal, surfaceData, bdType, id); 00885 } 00886 } 00887 00888 template< typename T, class SurfaceData > 00889 plint TriangleFlowShape3D<T,SurfaceData>::getTag(plint id) const { 00890 return boundary.getTag(id); 00891 } 00892 00893 template< typename T, class SurfaceData > 00894 bool TriangleFlowShape3D<T,SurfaceData>::distanceToSurface ( 00895 Array<T,3> const& point, T& distance, bool& isBehind ) const 00896 { 00897 PLB_PRECONDITION( hashContainer ); // Make sure these arguments have 00898 PLB_PRECONDITION( boundaryArg ); // been provided by the user through 00899 // the clone function. 00900 T maxDistance = sqrt(3); 00901 Array<T,2> xRange(point[0]-maxDistance, point[0]+maxDistance); 00902 Array<T,2> yRange(point[1]-maxDistance, point[1]+maxDistance); 00903 Array<T,2> zRange(point[2]-maxDistance, point[2]+maxDistance); 00904 TriangleHash<T> triangleHash(*hashContainer); 00905 std::vector<plint> possibleTriangles; 00906 triangleHash.getTriangles(xRange, yRange, zRange, possibleTriangles); 00907 00908 T tmpDistance; 00909 bool tmpIsBehind; 00910 bool triangleFound = false; 00911 00912 for (pluint iPossible=0; iPossible<possibleTriangles.size(); ++iPossible) { 00913 plint iTriangle = possibleTriangles[iPossible]; 00914 boundary.getMesh().distanceToTriangle ( 00915 point, iTriangle, tmpDistance, tmpIsBehind ); 00916 if( !triangleFound || tmpDistance<distance) { 00917 distance = tmpDistance; 00918 isBehind = tmpIsBehind; 00919 triangleFound = true; 00920 } 00921 } 00922 return triangleFound; 00923 } 00924 00925 template< typename T, class SurfaceData > 00926 TriangleFlowShape3D<T,SurfaceData>* 00927 TriangleFlowShape3D<T,SurfaceData>::clone() const 00928 { 00929 return new TriangleFlowShape3D<T,SurfaceData>(*this); 00930 } 00931 00932 template< typename T, class SurfaceData > 00933 TriangleFlowShape3D<T,SurfaceData>* 00934 TriangleFlowShape3D<T,SurfaceData>::clone ( 00935 std::vector<AtomicBlock3D*> args ) const 00936 { 00937 PLB_PRECONDITION( args.size()==3 ); 00938 TriangleFlowShape3D<T,SurfaceData>* 00939 newShape = new TriangleFlowShape3D<T,SurfaceData>(*this); 00940 newShape->voxelFlags = dynamic_cast<ScalarField3D<int>*>(args[0]); 00941 newShape->hashContainer = dynamic_cast<AtomicContainerBlock3D*>(args[1]); 00942 newShape->boundaryArg = args[2]; 00943 PLB_ASSERT( newShape->voxelFlags ); 00944 PLB_ASSERT( newShape->hashContainer ); 00945 PLB_ASSERT( newShape->boundaryArg ); 00946 return newShape; 00947 } 00948 00949 00950 /******** class VoxelizedDomain3D *****************************************/ 00951 00952 template<typename T> 00953 VoxelizedDomain3D<T>::VoxelizedDomain3D ( 00954 TriangleBoundary3D<T> const& boundary_, 00955 int flowType_, plint extraLayer_, plint borderWidth_, 00956 plint envelopeWidth_, plint blockSize_, plint gridLevel_, bool dynamicMesh_ ) 00957 : flowType(flowType_), 00958 borderWidth(borderWidth_), 00959 boundary(boundary_) 00960 { 00961 PLB_ASSERT( flowType==voxelFlag::inside || flowType==voxelFlag::outside ); 00962 PLB_ASSERT( boundary.getMargin() >= borderWidth ); 00963 if (dynamicMesh_) { 00964 boundary.pushSelect(1,1); // Closed, Dynamic. 00965 } 00966 else { 00967 boundary.pushSelect(1,0); // Closed, Static. 00968 } 00969 std::auto_ptr<MultiScalarField3D<int> > fullVoxelMatrix ( 00970 voxelize( boundary.getMesh(), 00971 boundary.getMargin()+extraLayer_, borderWidth ) ); 00972 fullVoxelMatrix->setRefinementLevel(gridLevel_); 00973 createSparseVoxelMatrix(*fullVoxelMatrix, blockSize_, envelopeWidth_); 00974 createTriangleHash(); 00975 boundary.popSelect(); 00976 } 00977 00978 template<typename T> 00979 VoxelizedDomain3D<T>::VoxelizedDomain3D ( 00980 TriangleBoundary3D<T> const& boundary_, 00981 int flowType_, Box3D const& boundingBox, plint borderWidth_, 00982 plint envelopeWidth_, plint blockSize_, plint gridLevel_, bool dynamicMesh_ ) 00983 : flowType(flowType_), 00984 borderWidth(borderWidth_), 00985 boundary(boundary_) 00986 { 00987 PLB_ASSERT( flowType==voxelFlag::inside || flowType==voxelFlag::outside ); 00988 PLB_ASSERT( boundary.getMargin() >= borderWidth ); 00989 if (dynamicMesh_) { 00990 boundary.pushSelect(1,1); // Closed, Dynamic. 00991 } 00992 else { 00993 boundary.pushSelect(1,0); // Closed, Static. 00994 } 00995 std::auto_ptr<MultiScalarField3D<int> > fullVoxelMatrix ( 00996 voxelize( boundary.getMesh(), boundingBox, borderWidth ) ); 00997 fullVoxelMatrix->setRefinementLevel(gridLevel_); 00998 createSparseVoxelMatrix(*fullVoxelMatrix, blockSize_, envelopeWidth_); 00999 createTriangleHash(); 01000 boundary.popSelect(); 01001 } 01002 01003 template<typename T> 01004 void VoxelizedDomain3D<T>::createSparseVoxelMatrix ( 01005 MultiScalarField3D<int>& fullVoxelMatrix, 01006 plint blockSize_, plint envelopeWidth_ ) 01007 { 01008 if (blockSize_>0) { 01009 computeSparseVoxelMatrix(fullVoxelMatrix, blockSize_, envelopeWidth_); 01010 } 01011 else { 01012 // blockSize=0 means: don't create a sparse representation of the 01013 // multi-block. The envelope of the voxel-matrix needs to be extended 01014 // for future usage, though. 01015 extendEnvelopeWidth(fullVoxelMatrix, envelopeWidth_); 01016 } 01017 } 01018 01019 template<typename T> 01020 VoxelizedDomain3D<T>::VoxelizedDomain3D ( 01021 VoxelizedDomain3D<T> const& rhs ) 01022 : boundary(rhs.boundary), 01023 voxelMatrix(new MultiScalarField3D<int>(*rhs.voxelMatrix)), 01024 triangleHash(new MultiContainerBlock3D(*rhs.triangleHash)) 01025 { } 01026 01027 template<typename T> 01028 VoxelizedDomain3D<T>::~VoxelizedDomain3D() { 01029 delete voxelMatrix; 01030 delete triangleHash; 01031 } 01032 01033 01034 template<typename T> 01035 MultiScalarField3D<int>& 01036 VoxelizedDomain3D<T>::getVoxelMatrix() 01037 { 01038 return *voxelMatrix; 01039 } 01040 01041 template<typename T> 01042 MultiScalarField3D<int> const& 01043 VoxelizedDomain3D<T>::getVoxelMatrix() const 01044 { 01045 return *voxelMatrix; 01046 } 01047 01048 template<typename T> 01049 MultiContainerBlock3D& 01050 VoxelizedDomain3D<T>::getTriangleHash() 01051 { 01052 return *triangleHash; 01053 } 01054 01055 template<typename T> 01056 template<class ParticleFieldT> 01057 void VoxelizedDomain3D<T>::adjustVoxelization ( 01058 MultiParticleField3D<ParticleFieldT>& particles, bool dynamicMesh ) 01059 { 01060 if (dynamicMesh) { 01061 boundary.pushSelect(1,1); // Closed, Dynamic. 01062 } 01063 else { 01064 boundary.pushSelect(1,0); // Closed, Static. 01065 } 01066 reCreateTriangleHash(particles); 01067 MultiScalarField3D<int>* newVoxelMatrix = 01068 revoxelize(boundary.getMesh(), *voxelMatrix, *triangleHash, borderWidth).release(); 01069 std::swap(voxelMatrix, newVoxelMatrix); 01070 delete newVoxelMatrix; 01071 boundary.popSelect(); 01072 } 01073 01074 template<typename T> 01075 void VoxelizedDomain3D<T>::reparallelize(MultiBlockRedistribute3D const& redistribute) { 01076 MultiBlockManagement3D newManagement = redistribute.redistribute(voxelMatrix->getMultiBlockManagement()); 01077 MultiScalarField3D<int>* newVoxelMatrix = 01078 new MultiScalarField3D<int>( 01079 newManagement, 01080 voxelMatrix->getBlockCommunicator().clone(), 01081 voxelMatrix->getCombinedStatistics().clone(), 01082 defaultMultiBlockPolicy3D().getMultiScalarAccess<int>(), 0 ); 01083 copyNonLocal(*voxelMatrix, *newVoxelMatrix, voxelMatrix->getBoundingBox()); 01084 std::swap(voxelMatrix, newVoxelMatrix); 01085 delete newVoxelMatrix; 01086 delete triangleHash; 01087 createTriangleHash(); 01088 } 01089 01090 template<typename T> 01091 MultiBlockManagement3D const& 01092 VoxelizedDomain3D<T>::getMultiBlockManagement() const 01093 { 01094 return voxelMatrix->getMultiBlockManagement(); 01095 } 01096 01097 template<typename T> 01098 void VoxelizedDomain3D<T>::computeSparseVoxelMatrix ( 01099 MultiScalarField3D<int>& fullVoxelMatrix, 01100 plint blockSize, plint envelopeWidth ) 01101 { 01102 // Initialized to zero. 01103 MultiScalarField3D<int> domainMatrix((MultiBlock3D const&)fullVoxelMatrix); 01104 setToConstant( domainMatrix, fullVoxelMatrix, 01105 flowType, domainMatrix.getBoundingBox(), 1 ); 01106 for (int iLayer=1; iLayer<=boundary.getMargin(); ++iLayer) { 01107 addLayer(domainMatrix, domainMatrix.getBoundingBox(), iLayer); 01108 } 01109 MultiBlockManagement3D sparseBlockManagement = 01110 computeSparseManagement ( 01111 *plb::reparallelize(domainMatrix, blockSize,blockSize,blockSize), 01112 envelopeWidth ); 01113 01114 voxelMatrix = new MultiScalarField3D<int> ( 01115 sparseBlockManagement, 01116 fullVoxelMatrix.getBlockCommunicator().clone(), 01117 fullVoxelMatrix.getCombinedStatistics().clone(), 01118 defaultMultiBlockPolicy3D().getMultiScalarAccess<int>(), 01119 voxelFlag::undetermined ); 01120 copyNonLocal(fullVoxelMatrix, *voxelMatrix, voxelMatrix->getBoundingBox()); 01121 } 01122 01123 template<typename T> 01124 void VoxelizedDomain3D<T>::extendEnvelopeWidth ( 01125 MultiScalarField3D<int>& fullVoxelMatrix, plint envelopeWidth ) 01126 { 01127 MultiBlockManagement3D const& oldManagement = 01128 fullVoxelMatrix.getMultiBlockManagement(); 01129 MultiBlockManagement3D newManagement ( 01130 oldManagement.getSparseBlockStructure(), 01131 oldManagement.getThreadAttribution().clone(), 01132 envelopeWidth, 01133 oldManagement.getRefinementLevel() ); 01134 voxelMatrix = new MultiScalarField3D<int> ( 01135 newManagement, 01136 fullVoxelMatrix.getBlockCommunicator().clone(), 01137 fullVoxelMatrix.getCombinedStatistics().clone(), 01138 defaultMultiBlockPolicy3D().getMultiScalarAccess<int>(), 01139 voxelFlag::undetermined ); 01140 plb::copy(fullVoxelMatrix, *voxelMatrix, fullVoxelMatrix.getBoundingBox()); 01141 } 01142 01143 template<typename T> 01144 void VoxelizedDomain3D<T>::createTriangleHash() 01145 { 01146 triangleHash = new MultiContainerBlock3D(*voxelMatrix); 01147 std::vector<MultiBlock3D*> hashArg; 01148 hashArg.push_back(triangleHash); 01149 applyProcessingFunctional ( 01150 new CreateTriangleHash<T>(boundary.getMesh()), 01151 triangleHash->getBoundingBox(), hashArg ); 01152 } 01153 01154 template<typename T> 01155 template<class ParticleFieldT> 01156 void VoxelizedDomain3D<T>::reCreateTriangleHash ( 01157 MultiParticleField3D<ParticleFieldT>& particles ) 01158 { 01159 // The lids are non-parallel, an info which must be provided 01160 // to the hash algorithm by means of a list of barycenters. 01161 // This is a necessary and sufficient information because 01162 // all triangles connected to the barycenters are non-parallel, 01163 // and all non-parallel triangles are connected to a barycenter. 01164 std::vector<typename TriangularSurfaceMesh<T>::Lid> const& lids = 01165 boundary.getInletOutlet(); 01166 plint numLids = (plint) lids.size(); 01167 std::vector<plint> lidBaryCenters(numLids); 01168 for (plint iLid=0; iLid<numLids; ++iLid) { 01169 lidBaryCenters[iLid] = lids[iLid].centerVertex; 01170 } 01171 01172 std::vector<MultiBlock3D*> hashParticleArg; 01173 hashParticleArg.push_back(triangleHash); 01174 hashParticleArg.push_back(&particles); 01175 applyProcessingFunctional ( 01176 new ReAssignTriangleHash<T,ParticleFieldT>(boundary.getMesh(),lidBaryCenters), 01177 triangleHash->getBoundingBox(), hashParticleArg ); 01178 } 01179 01180 01181 /* ******** DetectBorderLineFunctional3D ************************************* */ 01182 01183 template<typename T> 01184 void addLayer( MultiScalarField3D<T>& matrix, 01185 Box3D const& domain, T previousLayer ) 01186 { 01187 applyProcessingFunctional( new AddLayerFunctional3D<T>(previousLayer), 01188 domain, matrix ); 01189 } 01190 01191 template<typename T> 01192 AddLayerFunctional3D<T>::AddLayerFunctional3D(T previousLayer_) 01193 : previousLayer(previousLayer_) 01194 { } 01195 01196 template<typename T> 01197 void AddLayerFunctional3D<T>::process ( 01198 Box3D domain, ScalarField3D<T>& voxels ) 01199 { 01200 for (plint iX = domain.x0; iX <= domain.x1; ++iX) { 01201 for (plint iY = domain.y0; iY <= domain.y1; ++iY) { 01202 for (plint iZ = domain.z0; iZ <= domain.z1; ++iZ) { 01203 for (plint dx=-1; dx<=1; ++dx) 01204 for (plint dy=-1; dy<=1; ++dy) 01205 for (plint dz=-1; dz<=1; ++dz) 01206 if(!(dx==0 && dy==0 && dz==0)) { 01207 plint nextX = iX + dx; 01208 plint nextY = iY + dy; 01209 plint nextZ = iZ + dz; 01210 if ( voxels.get(iX,iY,iZ)==0 && 01211 voxels.get(nextX,nextY,nextZ)==previousLayer ) 01212 { 01213 voxels.get(iX,iY,iZ) = previousLayer+1; 01214 } 01215 } 01216 } 01217 } 01218 } 01219 } 01220 01221 template<typename T> 01222 AddLayerFunctional3D<T>* AddLayerFunctional3D<T>::clone() const { 01223 return new AddLayerFunctional3D<T>(*this); 01224 } 01225 01226 template<typename T> 01227 void AddLayerFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const { 01228 modified[0] = modif::staticVariables; 01229 } 01230 01231 template<typename T> 01232 BlockDomain::DomainT AddLayerFunctional3D<T>::appliesTo() const { 01233 return BlockDomain::bulk; 01234 } 01235 01236 } // namespace plb 01237 01238 #endif // INNER_FLOW_BOUNDARY_3D_HH
1.6.3
1.6.3