/* This file is part of the OpenLB library * * Copyright (C) 2013, 2014 Mathias J. Krause, Peter Weisbrod * E-mail contact: info@openlb.net * The most recent release of OpenLB can be downloaded at * * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** \file * Representation of the 2D geometry -- generic implementation. */ #ifndef SUPER_GEOMETRY_2D_HH #define SUPER_GEOMETRY_2D_HH #include #include #include #include #include #include "geometry/cuboid2D.h" #include "geometry/cuboidGeometry2D.h" #include "geometry/superGeometry2D.h" #include "communication/superStructure2D.h" #include "communication/loadBalancer.h" #include "functors/analytical/indicator/indicatorF2D.h" #include "functors/lattice/indicator/superIndicatorF2D.h" #include "io/ostreamManager.h" namespace olb { template SuperGeometry2D::SuperGeometry2D(CuboidGeometry2D& cuboidGeometry, LoadBalancer& loadBalancer, int overlap) : SuperStructure2D(cuboidGeometry, loadBalancer, overlap), _statistics(this), clout(std::cout,"SuperGeometry2D") { // init communicator this->_communicator.init_nh(); this->_communicator.add_cells(this->_overlap); this->_communicator.init(); this->_communicationNeeded = true; // constructing the block and extended block geometries from the cuboid geometry _blockGeometries.clear(); for (int iCloc=0; iClocgetLoadBalancer().size(); iCloc++) { int iCglob = this->getLoadBalancer().glob(iCloc); Cuboid2D extendedCuboid(cuboidGeometry.get(iCglob),overlap); BlockGeometry2D tmp(extendedCuboid,iCglob); _extendedBlockGeometries.push_back(tmp); } for (int iCloc=0; iClocgetLoadBalancer().size(); iCloc++) { int iCglob = this->getLoadBalancer().glob(iCloc); int nX = cuboidGeometry.get(iCglob).getNx(); int nY = cuboidGeometry.get(iCglob).getNy(); BlockGeometryView2D tmp2(_extendedBlockGeometries[iCloc],overlap,overlap+nX-1,overlap,overlap+nY-1); _blockGeometries.push_back(tmp2); } _statistics.getStatisticsStatus() = true; } template SuperGeometry2D::SuperGeometry2D(SuperGeometry2D const& rhs) : SuperStructure2D(rhs._cuboidGeometry, rhs._loadBalancer, rhs._overlap), _statistics(this), clout(std::cout,"SuperGeometry2D") { // init communicator this->_communicator.init_nh(); this->_communicator.add_cells(this->_overlap); this->_communicator.init(); this->_communicationNeeded = true; // copy block and extended block geometries _blockGeometries = rhs._blockGeometries; _extendedBlockGeometries = rhs._extendedBlockGeometries; _statistics.getStatisticsStatus() = true; } template SuperGeometry2D& SuperGeometry2D::operator=(SuperGeometry2D const& rhs) { // init communicator this->_communicator.init_nh(); this->_communicator.add_cells(this->_overlap); this->_communicator.init(); this->_communicationNeeded = true; // copy mother data this->_cuboidGeometry = rhs._cuboidGeometry; this->_loadBalancer = rhs._loadBalancer; this->_overlap = rhs._overlap; // copy block and extended block geometrie _blockGeometries = rhs._blockGeometries; _extendedBlockGeometries = rhs._extendedBlockGeometries; _statistics = SuperGeometryStatistics2D(this); return *this; } template bool* SuperGeometry2D::operator() (int iCloc, int iX, int iY, int iData) { return (bool*)&getExtendedBlockGeometry(iCloc).get(iX+this->_overlap, iY+this->_overlap); } template int SuperGeometry2D::getDataSize() const { return 1; } template int SuperGeometry2D::getDataTypeSize() const { return sizeof(int); } template int& SuperGeometry2D::set(int iCglob, int iXloc, int iYloc) { if ( this->getLoadBalancer().rank(iCglob) == singleton::mpi().getRank() ) { std::cout << "warning: read only access to data which is not available in"; this->_communicationNeeded = true; _statistics.getStatisticsStatus() = true; return _extendedBlockGeometries[this->getLoadBalancer().loc(iCglob)].get(iXloc+this->_overlap, iYloc+this->_overlap); } else { std::cout << "error: write access to data which is not available in the any block geometry"; exit(-1); //return 0; } } template int const& SuperGeometry2D::get(int iCglob, int iXloc, int iYloc) const { if ( this->getLoadBalancer().rank(iCglob) == singleton::mpi().getRank() ) { return _extendedBlockGeometries[this->getLoadBalancer().loc(iCglob)].get(iXloc+this->_overlap, iYloc+this->_overlap); } else { std::cout << "error: read only access to data which is not available in the any block geometry, returning 0 as default" << std::endl; exit(-1); //return 0; } } template int SuperGeometry2D::getAndCommunicate(int iCglob, int iXloc, int iYloc) const { int material = 0; if ( this->getLoadBalancer().rank(iCglob) == singleton::mpi().getRank() ) { material = _extendedBlockGeometries[this->getLoadBalancer().loc(iCglob)].get(iXloc+this->_overlap, iYloc+this->_overlap); } #ifdef PARALLEL_MODE_MPI singleton::mpi().bCast(&material, 1, this->_loadBalancer.rank(iCglob)); #endif return material; } template int& SuperGeometry2D::set(std::vector latticeR) { return set(latticeR[0], latticeR[1], latticeR[2]); } template int const& SuperGeometry2D::get(std::vector latticeR) const { return get(latticeR[0], latticeR[1], latticeR[2]); } template int SuperGeometry2D::getAndCommunicate(std::vector latticeR) const { return getAndCommunicate(latticeR[0], latticeR[1], latticeR[2]); } template std::vector SuperGeometry2D::getPhysR(int iCglob, int iX, int iY) const { return this->_cuboidGeometry.getPhysR(iCglob, iX, iY); } template std::vector SuperGeometry2D::getPhysR(std::vector latticeR) const { return this->_cuboidGeometry.getPhysR(latticeR); } template void SuperGeometry2D::getPhysR(T output[2], const int latticeR[3]) const { this->_cuboidGeometry.getPhysR(output, latticeR); } template void SuperGeometry2D::getPhysR(T output[2], const int iCglob, const int iX, const int iY) const { this->_cuboidGeometry.getPhysR(output, iCglob, iX, iY); } template BlockGeometry2D& SuperGeometry2D::getExtendedBlockGeometry(int locIC) { _statistics.getStatisticsStatus() = true; return _extendedBlockGeometries[locIC]; } template BlockGeometry2D const& SuperGeometry2D::getExtendedBlockGeometry(int locIC) const { return _extendedBlockGeometries[locIC]; } template BlockGeometryView2D& SuperGeometry2D::getBlockGeometry(int locIC) { _statistics.getStatisticsStatus() = true; return _blockGeometries[locIC]; } template BlockGeometryView2D const& SuperGeometry2D::getBlockGeometry(int locIC) const { return _blockGeometries[locIC]; } template SuperGeometryStatistics2D& SuperGeometry2D::getStatistics() { if (this->_communicationNeeded) { this->communicate(); getStatisticsStatus()=true; } return _statistics; } template bool& SuperGeometry2D::getStatisticsStatus() { return _statistics.getStatisticsStatus(); } template bool const& SuperGeometry2D::getStatisticsStatus() const { return _statistics.getStatisticsStatus(); } template void SuperGeometry2D::updateStatistics(bool verbose) { if (this->_communicationNeeded) { this->communicate(verbose); getStatisticsStatus()=true; } _statistics.update(verbose); for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { _extendedBlockGeometries[iC].getStatistics().update(verbose); } } template int SuperGeometry2D::clean(bool verbose) { this->communicate(); int counter=0; for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { counter+=_extendedBlockGeometries[iC].clean(false); } #ifdef PARALLEL_MODE_MPI singleton::mpi().reduceAndBcast(counter, MPI_SUM); #endif if (verbose) { clout << "cleaned "<< counter << " outer boundary voxel(s)" << std::endl; } if (counter>0) { _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } return counter; } template int SuperGeometry2D::outerClean(bool verbose) { this->communicate(); int counter=0; for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { counter+=_extendedBlockGeometries[iC].outerClean(false); } #ifdef PARALLEL_MODE_MPI singleton::mpi().reduceAndBcast(counter, MPI_SUM); #endif if (verbose) { clout << "cleaned "<< counter << " outer fluid voxel(s)" << std::endl; } if (counter>0) { _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } return counter; } template int SuperGeometry2D::innerClean(bool verbose) { this->communicate(); int counter=0; for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { counter+=_extendedBlockGeometries[iC].innerClean(false); } #ifdef PARALLEL_MODE_MPI singleton::mpi().barrier(); singleton::mpi().reduceAndBcast(counter, MPI_SUM); #endif if (verbose) { clout << "cleaned "<< counter << " inner boundary voxel(s)" << std::endl; } if (counter>0) { _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } return counter; } template int SuperGeometry2D::innerClean(int bcType, bool verbose) { this->communicate(); int counter=0; for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { counter+=_extendedBlockGeometries[iC].innerClean(bcType,false); } #ifdef PARALLEL_MODE_MPI singleton::mpi().reduceAndBcast(counter, MPI_SUM); #endif if (verbose) { clout << "cleaned "<< counter << " inner boundary voxel(s) of Type " << bcType << std::endl; } if (counter>0) { _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } return counter; } template bool SuperGeometry2D::checkForErrors(bool verbose) { this->communicate(); bool error = false; for (unsigned iC=0; iC<_blockGeometries.size(); iC++) { if (_blockGeometries[iC].checkForErrors(false)) { error = true; } } if (verbose) { if (error) { this->clout << "error!" << std::endl; } else { this->clout << "the model is correct!" << std::endl; } } return error; } template void SuperGeometry2D::reset(IndicatorF2D& domain) { this->communicate(); for (unsigned iC = 0; iC < _extendedBlockGeometries.size(); ++iC) { _blockGeometries[iC].reset(domain); } _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } template void SuperGeometry2D::rename(int fromM, int toM) { this->communicate(); for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { _blockGeometries[iC].rename(fromM,toM); } _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } template void SuperGeometry2D::rename(int fromM, int toM, IndicatorF2D& condition) { this->communicate(); for (unsigned iC=0; iC<_extendedBlockGeometries.size(); iC++) { _extendedBlockGeometries[iC].rename(fromM,toM,condition); } _statistics.getStatisticsStatus() = true; } template void SuperGeometry2D::rename(int fromM, int toM, unsigned offsetX, unsigned offsetY) { if ( offsetX<=unsigned(this->_overlap) && offsetY<=unsigned(this->_overlap) ) { this->communicate(); for (unsigned iC=0; iC<_blockGeometries.size(); iC++) { _blockGeometries[iC].rename(fromM,toM,offsetX, offsetY); } _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } else { clout << "error rename only implemented for offset<=overlap" << std::endl; } } template void SuperGeometry2D::rename(int fromM, int toM, int testM, std::vector testDirection) { if ( testDirection[0]*testDirection[0]<=(this->_overlap)*(this->_overlap) && testDirection[1]*testDirection[1]<=(this->_overlap)*(this->_overlap) ) { this->communicate(); for (unsigned iC=0; iC<_blockGeometries.size(); iC++) { _blockGeometries[iC].rename(fromM,toM,testM,testDirection); } _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } else { clout << "error rename only implemented for |testDirection[i]|<=overlap" << std::endl; } } template void SuperGeometry2D::rename(int fromBcMat, int toBcMat, int fluidMat, IndicatorF2D& condition) { if (this->_overlap>1) { this->communicate(); rename(fromBcMat, toBcMat, condition); std::vector testDirection = this->getStatistics().computeDiscreteNormal(toBcMat); //std::cout << testDirection[0]<communicate(); for (unsigned iC=0; iC<_blockGeometries.size(); iC++) { _blockGeometries[iC].rename(fromBcMat,toBcMat,fluidMat,condition,testDirection); } _statistics.getStatisticsStatus() = true; this->_communicationNeeded = true; } else { clout << "error rename only implemented for overlap>=2" << std::endl; } } template void SuperGeometry2D::print() { this->_cuboidGeometry.print(); getStatistics().print(); } template std::unique_ptr> SuperGeometry2D::getMaterialIndicator( std::vector&& materials) { return this->getIndicator( std::forward>(materials)); } template std::unique_ptr> SuperGeometry2D::getMaterialIndicator(int material) { return this->getMaterialIndicator(std::vector { material }); } } // namespace olb #endif