/* This file is part of the OpenLB library * * Copyright (C) 2019 Adrian Kummerländer * 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. */ #ifndef REFINEMENT_GRID_2D_HH #define REFINEMENT_GRID_2D_HH #include "grid2D.h" #include "coupler2D.hh" #include "utilities/vectorHelpers.h" #include "communication/heuristicLoadBalancer.h" namespace olb { template class DESCRIPTOR> Grid2D::Grid2D(FunctorPtr>&& domainF, RelaxationTime tau, int resolution, Characteristics characteristics): _domainF(std::move(domainF)), _characteristics(characteristics), _converter(new UnitConverterFromResolutionAndRelaxationTime( resolution, // resolution: number of voxels per charPhysL tau, // latticeRelaxationTime: relaxation time, has to be greater than 0.5! characteristics.length, // charPhysLength: reference length of simulation geometry characteristics.velocity, // charPhysVelocity: maximal/highest expected velocity during simulation in __m / s__ characteristics.viscosity, // physViscosity: physical kinematic viscosity in __m^2 / s__ characteristics.density)), // physDensity: physical density in __kg / m^3__ _cuboids(new CuboidGeometry2D( *_domainF, _converter->getConversionFactorLength(), #ifdef PARALLEL_MODE_MPI singleton::mpi().getSize() #else 1 #endif )), _balancer(new HeuristicLoadBalancer( *_cuboids)), _geometry(new SuperGeometry2D( *_cuboids, *_balancer, 2)), _lattice(new SuperLattice2D( *_geometry)) { _converter->print(); } template class DESCRIPTOR> Grid2D::Grid2D(FunctorPtr>&& domainF, LatticeVelocity latticeVelocity, int resolution, Characteristics characteristics): _domainF(std::move(domainF)), _characteristics(characteristics), _converter(new UnitConverterFromResolutionAndLatticeVelocity( resolution, // resolution: number of voxels per charPhysL latticeVelocity, // charLatticeVelocity characteristics.length, // charPhysLength: reference length of simulation geometry characteristics.velocity, // charPhysVelocity: maximal/highest expected velocity during simulation in __m / s__ characteristics.viscosity, // physViscosity: physical kinematic viscosity in __m^2 / s__ characteristics.density)), // physDensity: physical density in __kg / m^3__ _cuboids(new CuboidGeometry2D( *_domainF, _converter->getConversionFactorLength(), #ifdef PARALLEL_MODE_MPI singleton::mpi().getSize() #else 1 #endif )), _balancer(new HeuristicLoadBalancer( *_cuboids)), _geometry(new SuperGeometry2D( *_cuboids, *_balancer, 2)), _lattice(new SuperLattice2D( *_geometry)) { _converter->print(); } template class DESCRIPTOR> Grid2D::Grid2D( FunctorPtr>&& domainF, RelaxationTime tau, int resolution, int re): Grid2D(std::forward(domainF), tau, resolution, Characteristics(re)) { } template class DESCRIPTOR> Grid2D::Grid2D( FunctorPtr>&& domainF, LatticeVelocity latticeVelocity, int resolution, int re): Grid2D(std::forward(domainF), latticeVelocity, resolution, Characteristics(re)) { } template class DESCRIPTOR> Characteristics Grid2D::getCharacteristics() const { return _characteristics; } template class DESCRIPTOR> UnitConverter& Grid2D::getConverter() { return *_converter; } template class DESCRIPTOR> CuboidGeometry2D& Grid2D::getCuboidGeometry() { return *_cuboids; } template class DESCRIPTOR> LoadBalancer& Grid2D::getLoadBalancer() { return *_balancer; } template class DESCRIPTOR> SuperGeometry2D& Grid2D::getSuperGeometry() { return *_geometry; } template class DESCRIPTOR> SuperLattice2D& Grid2D::getSuperLattice() { return *_lattice; } template class DESCRIPTOR> Dynamics& Grid2D::addDynamics( std::unique_ptr>&& dynamics) { Dynamics& ref = *dynamics; _dynamics.emplace_back(std::move(dynamics)); return ref; } template class DESCRIPTOR> sOnLatticeBoundaryCondition2D& Grid2D::getOnLatticeBoundaryCondition() { _onLatticeBoundaryConditions.emplace_back( new sOnLatticeBoundaryCondition2D(getSuperLattice())); return *_onLatticeBoundaryConditions.back(); } template class DESCRIPTOR> sOffLatticeBoundaryCondition2D& Grid2D::getOffLatticeBoundaryCondition() { _offLatticeBoundaryConditions.emplace_back( new sOffLatticeBoundaryCondition2D(getSuperLattice())); return *_offLatticeBoundaryConditions.back(); } template class DESCRIPTOR> void Grid2D::collideAndStream() { for ( auto& fineCoupler : _fineCouplers ) { fineCoupler->store(); } this->getSuperLattice().collideAndStream(); for ( auto& fineGrid : _fineGrids ) { fineGrid->collideAndStream(); } for ( auto& fineCoupler : _fineCouplers ) { fineCoupler->interpolate(); fineCoupler->couple(); } for ( auto& fineGrid : _fineGrids ) { fineGrid->collideAndStream(); } for ( auto& fineCoupler : _fineCouplers ) { fineCoupler->store(); fineCoupler->couple(); } for ( auto& coarseCoupler : _coarseCouplers ) { coarseCoupler->couple(); } } template class DESCRIPTOR> FineCoupler2D& Grid2D::addFineCoupling( Grid2D& fineGrid, Vector origin, Vector extend) { _fineCouplers.emplace_back( new FineCoupler2D( *this, fineGrid, origin, extend)); return *_fineCouplers.back(); } template class DESCRIPTOR> CoarseCoupler2D& Grid2D::addCoarseCoupling( Grid2D& fineGrid, Vector origin, Vector extend) { _coarseCouplers.emplace_back( new CoarseCoupler2D( *this, fineGrid, origin, extend)); return *_coarseCouplers.back(); } template class DESCRIPTOR> Vector Grid2D::alignOriginToGrid(Vector physR) const { Vector latticeR{}; _cuboids->getLatticeR(physR, latticeR); return _cuboids->getPhysR(latticeR.toStdVector()); } template class DESCRIPTOR> Vector Grid2D::alignExtendToGrid(Vector extend) const { const T deltaX = _converter->getPhysDeltaX(); return { static_cast(std::floor(extend[0] / deltaX)) * deltaX, static_cast(std::floor(extend[1] / deltaX)) * deltaX }; } template class DESCRIPTOR> std::size_t Grid2D::getActiveVoxelN() const { std::size_t n = _geometry->getStatistics().getNvoxel(); for (const auto& grid : _fineGrids) { n += grid->getActiveVoxelN(); } return n; } template class DESCRIPTOR> RefiningGrid2D& Grid2D::refine( Vector wantedOrigin, Vector wantedExtend, bool addCouplers) { if (addCouplers) { auto& fineGrid = refine(wantedOrigin, wantedExtend, false); const Vector origin = fineGrid.getOrigin(); const Vector extend = fineGrid.getExtend(); const Vector extendX = {extend[0],0}; const Vector extendY = {0,extend[1]}; addFineCoupling(fineGrid, origin, extendY); addFineCoupling(fineGrid, origin + extendX, extendY); addFineCoupling(fineGrid, origin + extendY, extendX); addFineCoupling(fineGrid, origin, extendX); const T coarseDeltaX = getConverter().getPhysDeltaX(); const Vector innerOrigin = origin + coarseDeltaX; const Vector innerExtendX = extendX - Vector {2*coarseDeltaX,0}; const Vector innerExtendY = extendY - Vector {0,2*coarseDeltaX}; addCoarseCoupling(fineGrid, innerOrigin, innerExtendY); addCoarseCoupling(fineGrid, innerOrigin + innerExtendX, innerExtendY); addCoarseCoupling(fineGrid, innerOrigin + innerExtendY, innerExtendX); addCoarseCoupling(fineGrid, innerOrigin, innerExtendX); return fineGrid; } else { const Vector origin = alignOriginToGrid(wantedOrigin); const Vector extend = alignExtendToGrid(wantedExtend); _fineGrids.emplace_back( new RefiningGrid2D(*this, origin, extend)); return *_fineGrids.back(); } } template class DESCRIPTOR> RefiningGrid2D::RefiningGrid2D( Grid2D& parentGrid, Vector origin, Vector extend): Grid2D( std::unique_ptr>(new IndicatorCuboid2D(extend, origin)), RelaxationTime(2*parentGrid.getConverter().getLatticeRelaxationTime() - 0.5), 2*parentGrid.getConverter().getResolution(), parentGrid.getCharacteristics()), _origin(origin), _extend(extend), _parentGrid(parentGrid) { } template class DESCRIPTOR> Vector RefiningGrid2D::getOrigin() const { return _origin; } template class DESCRIPTOR> Vector RefiningGrid2D::getExtend() const { return _extend; } template class DESCRIPTOR> std::unique_ptr> RefiningGrid2D::getRefinedOverlap() const { const T coarseDeltaX = _parentGrid.getConverter().getPhysDeltaX(); return std::unique_ptr>( new IndicatorCuboid2D(_extend - 4*coarseDeltaX, _origin + 2*coarseDeltaX)); } } #endif