/* 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 "boundary/superBoundaryCondition2D.h"
#include "boundary/superOffBoundaryCondition2D.h"
#include "communication/heuristicLoadBalancer.h"
namespace olb {
template
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
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
Grid2D::Grid2D(
FunctorPtr>&& domainF,
RelaxationTime tau,
int resolution,
int re):
Grid2D(std::forward(domainF),
tau,
resolution,
Characteristics(re))
{ }
template
Grid2D::Grid2D(
FunctorPtr>&& domainF,
LatticeVelocity latticeVelocity,
int resolution,
int re):
Grid2D(std::forward(domainF),
latticeVelocity,
resolution,
Characteristics(re))
{ }
template
Characteristics Grid2D::getCharacteristics() const
{
return _characteristics;
}
template
UnitConverter& Grid2D::getConverter()
{
return *_converter;
}
template
CuboidGeometry2D& Grid2D::getCuboidGeometry()
{
return *_cuboids;
}
template
LoadBalancer& Grid2D::getLoadBalancer()
{
return *_balancer;
}
template
SuperGeometry2D& Grid2D::getSuperGeometry()
{
return *_geometry;
}
template
SuperLattice2D& Grid2D::getSuperLattice()
{
return *_lattice;
}
template
Dynamics& Grid2D::addDynamics(
std::unique_ptr>&& dynamics)
{
Dynamics& ref = *dynamics;
_dynamics.emplace_back(std::move(dynamics));
return ref;
}
template
sOnLatticeBoundaryCondition2D& Grid2D::getOnLatticeBoundaryCondition()
{
_onLatticeBoundaryConditions.emplace_back(
new sOnLatticeBoundaryCondition2D(getSuperLattice()));
return *_onLatticeBoundaryConditions.back();
}
template
sOffLatticeBoundaryCondition2D& Grid2D::getOffLatticeBoundaryCondition()
{
_offLatticeBoundaryConditions.emplace_back(
new sOffLatticeBoundaryCondition2D(getSuperLattice()));
return *_offLatticeBoundaryConditions.back();
}
template
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
FineCoupler2D& Grid2D::addFineCoupling(
Grid2D& fineGrid, Vector origin, Vector extend)
{
_fineCouplers.emplace_back(
new FineCoupler2D(
*this, fineGrid, origin, extend));
return *_fineCouplers.back();
}
template
CoarseCoupler2D& Grid2D::addCoarseCoupling(
Grid2D& fineGrid, Vector origin, Vector extend)
{
_coarseCouplers.emplace_back(
new CoarseCoupler2D(
*this, fineGrid, origin, extend));
return *_coarseCouplers.back();
}
template
Vector Grid2D::alignOriginToGrid(Vector physR) const
{
Vector latticeR{};
_cuboids->getLatticeR(physR, latticeR);
return _cuboids->getPhysR(latticeR.toStdVector());
}
template
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
void Grid2D::forEachGrid(std::function&)>&& f)
{
f(*this);
for (auto& grid : _fineGrids) {
grid->forEachGrid(std::forward(f));
}
}
template
void Grid2D::forEachGrid(
const std::string& id,
std::function&,const std::string&)>&& f)
{
f(*this, id);
for (std::size_t i = 0; i < _fineGrids.size(); ++i) {
_fineGrids[i]->forEachGrid(id + "_" + std::to_string(i),
std::forward(f));
}
}
template
Grid2D& Grid2D::locate(Vector pos)
{
int iC;
for (auto& grid : _fineGrids) {
if (grid->getCuboidGeometry().getC(pos, iC)) {
return grid->locate(pos);
}
}
return *this;
}
template
std::size_t Grid2D::getActiveVoxelN() const
{
std::size_t n = _geometry->getStatistics().getNvoxel();
for (const auto& grid : _fineGrids) {
n += grid->getActiveVoxelN();
}
return n;
}
template
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));
RefiningGrid2D& fineGrid = *_fineGrids.back();
auto refinedOverlap = fineGrid.getRefinedOverlap();
_geometry->reset(*refinedOverlap);
return fineGrid;
}
}
template
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
Vector RefiningGrid2D::getOrigin() const
{
return _origin;
}
template
Vector RefiningGrid2D::getExtend() const
{
return _extend;
}
template
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