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

makeSparse3D.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 MAKE_SPARSE_3D_HH
00026 #define MAKE_SPARSE_3D_HH
00027 
00028 #include "core/globalDefs.h"
00029 #include "offLattice/makeSparse3D.h"
00030 #include "parallelism/mpiManager.h"
00031 #include "atomicBlock/reductiveDataProcessingFunctional3D.h"
00032 #include "atomicBlock/atomicContainerBlock3D.h"
00033 #include "offLattice/domainClustering3D.h"
00034 
00035 
00036 namespace plb {
00037 
00038 struct FlagData3D : public ContainerBlockData {
00039     bool keepThisBlock;
00040     virtual FlagData3D* clone() const {
00041         return new FlagData3D(*this);
00042     }
00043 };
00044 
00045 /* ******** ComputeSparsityFunctional3D ************************************ */
00046 
00047 template<typename T>
00048 ComputeSparsityFunctional3D<T>::ComputeSparsityFunctional3D()
00049     : numBlocksId(this->getStatistics().subscribeIntSum())
00050 { }
00051 
00052 template<typename T>
00053 void ComputeSparsityFunctional3D<T>::processGenericBlocks (
00054         Box3D domain, std::vector<AtomicBlock3D*> blocks )
00055 {
00056     PLB_PRECONDITION( blocks.size()==2 );
00057     ScalarField3D<T>* field = dynamic_cast<ScalarField3D<T>*>(blocks[0]);
00058     AtomicContainerBlock3D* container = dynamic_cast<AtomicContainerBlock3D*>(blocks[1]);
00059     PLB_ASSERT( field );
00060     PLB_ASSERT( container );
00061     bool exclusivelyEliminateCells = true;
00062     for (plint iX=domain.x0; iX<=domain.x1; ++iX) {
00063         for (plint iY=domain.y0; iY<=domain.y1; ++iY) {
00064             for (plint iZ=domain.z0; iZ<=domain.z1; ++iZ) {
00065                 if (field->get(iX,iY,iZ) != 0) {
00066                     exclusivelyEliminateCells = false;
00067                 }
00068             }
00069         }
00070     }
00071     FlagData3D* flagData = new FlagData3D;
00072     if (exclusivelyEliminateCells) {
00073         flagData->keepThisBlock = false;
00074         this->getStatistics().gatherIntSum(numBlocksId, 1);
00075     }
00076     else {
00077         flagData->keepThisBlock = true;
00078     }
00079     container->setData(flagData);
00080 }
00081 
00082 template<typename T>
00083 ComputeSparsityFunctional3D<T>* ComputeSparsityFunctional3D<T>::clone() const {
00084     return new ComputeSparsityFunctional3D<T>(*this);
00085 }
00086 
00087 template<typename T>
00088 void ComputeSparsityFunctional3D<T>::getTypeOfModification(std::vector<modif::ModifT>& modified) const {
00089     modified[0] = modif::nothing; // Scalar Field.
00090     modified[1] = modif::staticVariables;  // Container Block with flag data.
00091 }
00092 
00093 template<typename T>
00094 BlockDomain::DomainT ComputeSparsityFunctional3D<T>::appliesTo() const {
00095     return BlockDomain::bulk;
00096 }
00097 
00098 template<typename T>
00099 pluint ComputeSparsityFunctional3D<T>::getNumBlocks() const {
00100     return this->getStatistics().getIntSum(numBlocksId);
00101 }
00102 
00103 
00104 /* ******** computeSparseManagement ************************************ */
00105 
00106 template<typename T>
00107 MultiBlockManagement3D computeSparseManagement (
00108         MultiScalarField3D<T>& field, plint newEnvelopeWidth )
00109 {
00110     MultiContainerBlock3D multiFlagBlock(field);
00111     std::vector<MultiBlock3D*> args;
00112     args.push_back(&field);
00113     args.push_back(&multiFlagBlock);
00114     ComputeSparsityFunctional3D<T> sparsityFunctional;
00115     applyProcessingFunctional (
00116             sparsityFunctional, field.getBoundingBox(), args );
00117 
00118     MultiBlockManagement3D const& management = multiFlagBlock.getMultiBlockManagement();
00119     ThreadAttribution const& threadAttribution = management.getThreadAttribution();
00120     SparseBlockStructure3D const& sparseBlock = management.getSparseBlockStructure();
00121 
00122     std::map<plint,Box3D> const& domains = sparseBlock.getBulks();
00123     std::vector<plint> domainIds(domains.size());
00124     std::vector<int> keepThisBlock(domains.size());
00125 
00126     std::map<plint,Box3D>::const_iterator it = domains.begin();
00127     plint pos = 0;
00128     for (; it != domains.end(); ++it) {
00129         plint id = it->first;
00130         domainIds[pos] = id;
00131         if (threadAttribution.isLocal(id)) {
00132             AtomicContainerBlock3D const& flagBlock = multiFlagBlock.getComponent(id);
00133             FlagData3D const* data =
00134                 dynamic_cast<FlagData3D const*> (flagBlock.getData());
00135             PLB_ASSERT( data );
00136             keepThisBlock[pos] = data->keepThisBlock ? 1:0;
00137         }
00138         else {
00139             keepThisBlock[pos] = 0;
00140         }
00141         ++pos;
00142     }
00143 
00144 #ifdef PLB_MPI_PARALLEL
00145     std::vector<int> tmp(keepThisBlock.size());
00146     global::mpi().reduceVect(keepThisBlock, tmp, MPI_SUM);
00147     global::mpi().bCast(&tmp[0], tmp.size());
00148     tmp.swap(keepThisBlock);
00149 #endif
00150 
00151     SparseBlockStructure3D newSparseBlock(field.getBoundingBox());
00152     plint newId = 0;
00153     for (pluint iBlock=0; iBlock<keepThisBlock.size(); ++iBlock) {
00154         if (keepThisBlock[iBlock]) {
00155             plint id = domainIds[iBlock];
00156             Box3D bulk, uniqueBulk;
00157             sparseBlock.getBulk(id, bulk);
00158             sparseBlock.getUniqueBulk(id, uniqueBulk);
00159             newSparseBlock.addBlock(bulk, uniqueBulk, newId++);
00160         }
00161     }
00162     // If this assertion fails, that means that the domain covered
00163     // by the sparse block-structure is empty.
00164     PLB_ASSERT( newId>0 );
00165 
00166     ExplicitThreadAttribution* newAttribution = new ExplicitThreadAttribution;
00167     std::vector<std::pair<plint,plint> > ranges;
00168     plint numRanges = std::min(newId, (plint)global::mpi().getSize());
00169     util::linearRepartition(0, newId-1, numRanges, ranges);
00170     
00171     std::vector<plint> localBlocks;
00172     for (pluint iProc=0; iProc<ranges.size(); ++iProc) {
00173         for (plint blockId=ranges[iProc].first; blockId<=ranges[iProc].second; ++blockId) {
00174             newAttribution -> addBlock(blockId, iProc);
00175             if (iProc==(pluint)global::mpi().getRank()) {
00176                 localBlocks.push_back(blockId);
00177             }
00178         }
00179     }
00180 
00181     MultiBlockManagement3D newManagement (
00182             newSparseBlock, newAttribution,
00183             newEnvelopeWidth,
00184             management.getRefinementLevel() );
00185     return newManagement;
00186 }
00187 
00188 }  // namespace plb
00189 
00190 #endif  // MAKE_SPARSE_3D_HH
00191