$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

triangleBoundary3D.hh

Go to the documentation of this file.
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