/* This file is part of the OpenLB library
*
* Copyright (C) 2012 Jonas Kratzke, Mathias J. Krause
* 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
* A helper for initialising 3D boundaries -- header file.
*/
#ifndef OFF_BOUNDARY_INSTANTIATOR_3D_H
#define OFF_BOUNDARY_INSTANTIATOR_3D_H
#include "offBoundaryCondition3D.h"
#include "geometry/blockGeometry3D.h"
#include "geometry/blockGeometryStatistics3D.h"
#include "core/cell.h"
#include "io/ostreamManager.h"
#include "core/util.h"
#include "io/stlReader.h"
#include "functors/lattice/indicator/blockIndicatorF3D.h"
namespace olb {
/**
* This class gets the needed processors from BoundaryManager and adds them
* to the Processor Vector of the DESCRIPTOR
*/
template
class OffBoundaryConditionInstantiator3D: public OffLatticeBoundaryCondition3D {
public:
OffBoundaryConditionInstantiator3D(BlockLatticeStructure3D& block_, T epsFraction_ = 0.0001);
~OffBoundaryConditionInstantiator3D() override;
void addOnePointZeroVelocityBoundary(int x, int y, int z, int iPop, T dist) override;
void addTwoPointZeroVelocityBoundary(int x, int y, int z, int iPop, T dist) override;
void addOnePointVelocityBoundary(int x, int y, int z, int iPop, T dist) override;
void addTwoPointVelocityBoundary(int x, int y, int z, int iPop, T dist) override;
void addOffDynamics(int x, int y, int z, T location[DESCRIPTOR::d]) override;
void addOffDynamics(int x, int y, int z, T location[DESCRIPTOR::d], T distances[DESCRIPTOR::q]) override;
void addOffDynamics(BlockIndicatorF3D& indicator) override;
void addZeroVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, int iPop, T dist) override;
void addZeroVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, T distances[DESCRIPTOR::q]);
void addZeroVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ, IndicatorF3D& geometryIndicator, BlockIndicatorF3D& bulkIndicator);
void addZeroVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ, IndicatorF3D& geometryIndicator, std::vector bulkMaterials = std::vector(1,1));
void addZeroVelocityBoundary(BlockIndicatorF3D& boundaryIndicator, BlockIndicatorF3D& bulkIndicator, IndicatorF3D& geometryIndicator) override;
void addVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, int iPop, T dist);
void addVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, T distances[DESCRIPTOR::q]);
void addVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ, IndicatorF3D& geometryIndicator, BlockIndicatorF3D& bulkIndicator);
void addVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ, IndicatorF3D& geometryIndicator, std::vector bulkMaterials = std::vector(1,1));
void addVelocityBoundary(BlockIndicatorF3D& boundaryIndicator, BlockIndicatorF3D& bulkIndicator, IndicatorF3D& geometryIndicator) override;
void setBoundaryIntersection(int iX, int iY, int iZ, int iPop, T distance);
bool getBoundaryIntersection(int iX, int iY, int iZ, int iPop, T point[DESCRIPTOR::d]);
void defineU(int iX, int iY, int iZ, int iPop, const T u[DESCRIPTOR::d]) override;
void defineU(BlockIndicatorF3D& indicator, BlockIndicatorF3D& bulkIndicator, AnalyticalF3D& u) override;
void outputOn() override;
void outputOff() override;
BlockLatticeStructure3D& getBlock() override;
BlockLatticeStructure3D const& getBlock() const override;
private:
BlockLatticeStructure3D& block;
//std::vector*> momentaVector;
std::vector*> dynamicsVector;
bool _output;
mutable OstreamManager clout;
};
///////// class OffBoundaryConditionInstantiator3D ////////////////////////
template
BlockLatticeStructure3D& OffBoundaryConditionInstantiator3D::getBlock()
{
return block;
}
template
BlockLatticeStructure3D const& OffBoundaryConditionInstantiator3D::getBlock() const
{
return block;
}
template
OffBoundaryConditionInstantiator3D::OffBoundaryConditionInstantiator3D(
BlockLatticeStructure3D& block_, T epsFraction_) :
block(block_), _output(false), clout(std::cout,"BoundaryConditionInstantiator3D")
{
this->_epsFraction = epsFraction_;
}
template
OffBoundaryConditionInstantiator3D::~OffBoundaryConditionInstantiator3D()
{
for (unsigned iDynamics = 0; iDynamics < dynamicsVector.size(); ++iDynamics) {
delete dynamicsVector[iDynamics];
}
/*
for (unsigned iMomenta = 0; iMomenta < dynamicsVector.size(); ++iMomenta) {
delete momentaVector[iMomenta];
}*/
}
template
void OffBoundaryConditionInstantiator3D::addOnePointZeroVelocityBoundary(
int x, int y, int z, int iPop, T dist)
{
PostProcessorGenerator3D* postProcessor =
BoundaryManager::getOnePointZeroVelocityBoundaryProcessor
(x, y, z, iPop, dist);
if (postProcessor) {
this->getBlock().addPostProcessor(*postProcessor);
}
}
template
void OffBoundaryConditionInstantiator3D::addTwoPointZeroVelocityBoundary(
int x, int y, int z, int iPop, T dist)
{
PostProcessorGenerator3D* postProcessor =
BoundaryManager::getTwoPointZeroVelocityBoundaryProcessor
(x, y, z, iPop, dist);
if (postProcessor) {
this->getBlock().addPostProcessor(*postProcessor);
}
}
template
void OffBoundaryConditionInstantiator3D::addOnePointVelocityBoundary(
int x, int y, int z, int iPop, T dist)
{
PostProcessorGenerator3D* postProcessor =
BoundaryManager::getOnePointVelocityBoundaryProcessor
(x, y, z, iPop, dist);
if (postProcessor) {
this->getBlock().addPostProcessor(*postProcessor);
}
}
template
void OffBoundaryConditionInstantiator3D::addTwoPointVelocityBoundary(
int x, int y, int z, int iPop, T dist)
{
PostProcessorGenerator3D* postProcessor =
BoundaryManager::getTwoPointVelocityBoundaryProcessor
(x, y, z, iPop, dist);
if (postProcessor) {
this->getBlock().addPostProcessor(*postProcessor);
}
}
template
void OffBoundaryConditionInstantiator3D::addOffDynamics(
int x, int y, int z, T location[DESCRIPTOR::d])
{
Dynamics* dynamics
= BoundaryManager::getOffDynamics(location);
this->getBlock().defineDynamics(x,x,y,y,z,z, dynamics);
dynamicsVector.push_back(dynamics);
}
template
void OffBoundaryConditionInstantiator3D::addOffDynamics(
int x, int y, int z, T location[DESCRIPTOR::d], T distances[DESCRIPTOR::q])
{
Dynamics* dynamics
= BoundaryManager::getOffDynamics(location, distances);
this->getBlock().defineDynamics(x,x,y,y,z,z, dynamics);
dynamicsVector.push_back(dynamics);
}
template
void OffBoundaryConditionInstantiator3D::addOffDynamics(
BlockIndicatorF3D& indicator)
{
if ( !indicator.isEmpty() ) {
const Vector min = indicator.getMin();
const Vector max = indicator.getMax();
for (int iX = min[0]; iX <= max[0]; ++iX) {
for (int iY = min[1]; iY <= max[1]; ++iY) {
for (int iZ = min[2]; iZ <= max[2]; ++iZ) {
if (indicator(iX,iY,iZ)) {
T location[DESCRIPTOR::d];
indicator.getBlockGeometryStructure().getPhysR(location, iX,iY,iZ);
addOffDynamics(iX, iY, iZ, location);
}
}
}
}
}
}
template
void OffBoundaryConditionInstantiator3D::addZeroVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, int iPop, T dist)
{
const Vector c = descriptors::c(iPop);
if (blockGeometryStructure.getMaterial(x-c[0], y-c[1], z-c[2]) != 1) {
addOnePointZeroVelocityBoundary(x, y, z, iPop, dist);
}
else {
addTwoPointZeroVelocityBoundary(x, y, z, iPop, dist);
}
}
template
void OffBoundaryConditionInstantiator3D::
addZeroVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, T distances[DESCRIPTOR::q])
{
typedef DESCRIPTOR L;
//T location[DESCRIPTOR::d];
//location[0] = blockGeometryStructure.physCoordX(x);
//location[1] = blockGeometryStructure.physCoordY(y);
//location[2] = blockGeometryStructure.physCoordZ(z);
//T distancesCopy[L::q];
//T spacing = blockGeometryStructure.getDeltaR();
//for (int iPop = 1; iPop < L::q ; ++iPop) {
// distancesCopy[iPop] = spacing*(1.-distances[iPop]);
// if (distances[iPop] == -1)
// distancesCopy[iPop] = -1;
//}
//addOffDynamics(x, y, z, location, distancesCopy);
for (int iPop = 1; iPop < L::q ; ++iPop) {
if ( !util::nearZero(distances[iPop]+1) ) {
const Vector c = descriptors::c(iPop);
addZeroVelocityBoundary(blockGeometryStructure, x-c[0], y-c[1], z-c[2], iPop, distances[iPop]);
}
}
}
template
void OffBoundaryConditionInstantiator3D::addZeroVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ,
IndicatorF3D& geometryIndicator, BlockIndicatorF3D& bulkIndicator)
{
T distances[DESCRIPTOR::q];
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
distances[iPop] = -1;
}
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
const Vector c = descriptors::c(iPop);
const int iXn = iX + c[0];
const int iYn = iY + c[1];
const int iZn = iZ + c[2];
if (blockGeometryStructure.isInside(iXn,iYn,iZn) && bulkIndicator(iXn,iYn,iZn)) {
T dist = -1;
T physR[3];
blockGeometryStructure.getPhysR(physR,iXn,iYn,iZn);
T voxelSize=blockGeometryStructure.getDeltaR();
Vector physC(physR);
Vector direction(-voxelSize*c[0],-voxelSize*c[1],-voxelSize*c[2]);
T cPhysNorm = voxelSize*sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]);
if (!geometryIndicator.distance(dist,physC,direction,blockGeometryStructure.getIcGlob() ) ) {
T epsX = voxelSize*c[0]*this->_epsFraction;
T epsY = voxelSize*c[1]*this->_epsFraction;
T epsZ = voxelSize*c[2]*this->_epsFraction;
Vector physC2(physC);
physC2[0] += epsX;
physC2[1] += epsY;
physC2[2] += epsZ;
Vector direction2(direction);
direction2[0] -= 2.*epsX;
direction2[1] -= 2.*epsY;
direction2[2] -= 2.*epsZ;
if ( !geometryIndicator.distance(dist,physC2,direction2,blockGeometryStructure.getIcGlob())) {
clout << "ERROR: no boundary found at (" << iXn << "," << iYn << "," << iZn <<") ~ ("
<< physR[0] << "," << physR[1] << "," << physR[2] <<"), "
<< "in direction " << util::opposite(iPop)
<< std::endl;
}
T distNew = (dist - sqrt(epsX*epsX+epsY*epsY+epsZ*epsZ))/cPhysNorm;
if (distNew < 0.5) {
dist = 0;
}
else {
dist = 0.5 * cPhysNorm;
clout << "WARNING: distance at (" << iXn << "," << iYn << "," << iZn <<") ~ ("
<< physR[0] << "," << physR[1] << "," << physR[2] <<"), "
<< "in direction " << util::opposite(iPop) << ": "
<< distNew
<< " rounded to "
<< dist/cPhysNorm
<< std::endl;
}
}
distances[util::opposite(iPop)] = dist/cPhysNorm;
} // bulkMaterials if
} // iPop loop
addZeroVelocityBoundary(blockGeometryStructure, iX, iY, iZ, distances);
}
template
void OffBoundaryConditionInstantiator3D::addZeroVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ,
IndicatorF3D& geometryIndicator, std::vector bulkMaterials)
{
BlockIndicatorMaterial3D bulkIndicator(blockGeometryStructure, bulkMaterials);
addZeroVelocityBoundary(blockGeometryStructure, iX, iY, iZ,
geometryIndicator,
bulkIndicator);
}
template
void OffBoundaryConditionInstantiator3D::addZeroVelocityBoundary(
BlockIndicatorF3D& boundaryIndicator, BlockIndicatorF3D& bulkIndicator, IndicatorF3D& geometryIndicator)
{
if ( !boundaryIndicator.isEmpty() ) {
const Vector min = boundaryIndicator.getMin();
const Vector max = boundaryIndicator.getMax();
for (int iX = min[0]; iX <= max[0]; ++iX) {
for (int iY = min[1]; iY <= max[1]; ++iY) {
for (int iZ = min[2]; iZ <= max[2]; ++iZ) {
if (boundaryIndicator(iX,iY,iZ)) {
addZeroVelocityBoundary(boundaryIndicator.getBlockGeometryStructure(), iX, iY, iZ,
geometryIndicator, bulkIndicator);
}
}
}
}
}
}
template
void OffBoundaryConditionInstantiator3D::addVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, int iPop, T dist)
{
const Vector c = descriptors::c(iPop);
if (blockGeometryStructure.getMaterial(x-c[0], y-c[1], z-c[2]) != 1) {
addOnePointVelocityBoundary(x, y, z, iPop, dist);
}
else {
addTwoPointVelocityBoundary(x, y, z, iPop, dist);
}
}
template
void OffBoundaryConditionInstantiator3D::
addVelocityBoundary(BlockGeometryStructure3D& blockGeometryStructure, int x, int y, int z, T distances[DESCRIPTOR::q])
{
T location[DESCRIPTOR::d];
blockGeometryStructure.getPhysR(location, x,y,z);
T distancesCopy[DESCRIPTOR::q];
T spacing = blockGeometryStructure.getDeltaR();
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
distancesCopy[iPop] = spacing*(1.-distances[iPop]);
if ( util::nearZero(distances[iPop]+1) ) {
distancesCopy[iPop] = -1;
}
}
addOffDynamics(x, y, z, location, distancesCopy);
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
if (!util::nearZero(distances[iPop]+1)) {
const Vector c = descriptors::c(iPop);
addVelocityBoundary(blockGeometryStructure, x-c[0], y-c[1], z-c[2], iPop, distances[iPop]);
}
}
}
template
void OffBoundaryConditionInstantiator3D::addVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ,
IndicatorF3D& geometryIndicator, BlockIndicatorF3D& bulkIndicator)
{
T distances[DESCRIPTOR::q];
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
distances[iPop] = -1;
}
for (int iPop = 1; iPop < DESCRIPTOR::q ; ++iPop) {
const Vector c = descriptors::c(iPop);
const int iXn = iX + c[0];
const int iYn = iY + c[1];
const int iZn = iZ + c[2];
if (blockGeometryStructure.isInside(iXn,iYn,iZn) && bulkIndicator(iXn,iYn,iZn)) {
T dist = -1;
T physR[3];
blockGeometryStructure.getPhysR(physR,iXn,iYn,iZn);
T voxelSize=blockGeometryStructure.getDeltaR();
Vector physC(physR);
Vector direction(-voxelSize*c[0],-voxelSize*c[1],-voxelSize*c[2]);
T cPhysNorm = voxelSize*sqrt(c[0]*c[0]+c[1]*c[1]+c[2]*c[2]);
if (!geometryIndicator.distance(dist,physC,direction,blockGeometryStructure.getIcGlob() ) ) {
T epsX = voxelSize*c[0]*this->_epsFraction;
T epsY = voxelSize*c[1]*this->_epsFraction;
T epsZ = voxelSize*c[2]*this->_epsFraction;
Vector physC2(physC);
physC2[0] += epsX;
physC2[1] += epsY;
physC2[2] += epsZ;
Vector direction2(direction);
direction2[0] -= 2.*epsX;
direction2[1] -= 2.*epsY;
direction2[2] -= 2.*epsZ;
if ( !geometryIndicator.distance(dist,physC2,direction2,blockGeometryStructure.getIcGlob())) {
clout << "ERROR: no boundary found at (" << iXn << "," << iYn << "," << iZn <<") ~ ("
<< physR[0] << "," << physR[1] << "," << physR[2] <<"), "
<< "in direction " << util::opposite(iPop)
<< std::endl;
}
T distNew = (dist - sqrt(epsX*epsX+epsY*epsY+epsZ*epsZ))/cPhysNorm;
if (distNew < 0.5) {
dist = 0;
}
else {
dist = 0.5 * cPhysNorm;
clout << "WARNING: distance at (" << iXn << "," << iYn << "," << iZn <<") ~ ("
<< physR[0] << "," << physR[1] << "," << physR[2] <<"), "
<< "in direction " << util::opposite(iPop) << ": "
<< distNew
<< " rounded to "
<< dist/cPhysNorm
<< std::endl;
}
}
distances[util::opposite(iPop)] = dist/cPhysNorm;
} // bulk indicator if
} // iPop loop
addVelocityBoundary(blockGeometryStructure, iX, iY, iZ, distances);
}
template
void OffBoundaryConditionInstantiator3D::addVelocityBoundary(
BlockGeometryStructure3D& blockGeometryStructure, int iX, int iY, int iZ,
IndicatorF3D& geometryIndicator, std::vector bulkMaterials)
{
BlockIndicatorMaterial3D bulkIndicator(blockGeometryStructure, bulkMaterials);
addVelocityBoundary(blockGeometryStructure, iX, iY, iZ,
geometryIndicator,
bulkIndicator);
}
template
void OffBoundaryConditionInstantiator3D::addVelocityBoundary(
BlockIndicatorF3D& boundaryIndicator,
BlockIndicatorF3D& bulkIndicator,
IndicatorF3D& geometryIndicator)
{
if ( !boundaryIndicator.isEmpty() ) {
const Vector min = boundaryIndicator.getMin();
const Vector max = boundaryIndicator.getMax();
for (int iX = min[0]; iX <= max[0]; ++iX) {
for (int iY = min[1]; iY <= max[1]; ++iY) {
for (int iZ = min[2]; iZ <= max[2]; ++iZ) {
if (boundaryIndicator(iX,iY,iZ)) {
addVelocityBoundary(bulkIndicator.getBlockGeometryStructure(), iX, iY, iZ,
geometryIndicator, bulkIndicator);
}
}
}
}
}
}
template
void OffBoundaryConditionInstantiator3D::
setBoundaryIntersection(int iX, int iY, int iZ, int iPop, T distance)
{
this->getBlock().getDynamics(iX, iY, iZ)->setBoundaryIntersection(iPop, distance);
if (_output) {
clout << "setBoundaryIntersection(" << iX << ", " << iY << ", " << iZ << " )" << std::endl;
}
}
template
bool OffBoundaryConditionInstantiator3D::
getBoundaryIntersection(int iX, int iY, int iZ, int iPop, T point[DESCRIPTOR::d])
{
return this->getBlock().getDynamics(iX, iY, iZ)->getBoundaryIntersection(iPop, point);
}
template
void OffBoundaryConditionInstantiator3D::
defineU(int iX, int iY, int iZ, int iPop, const T u[DESCRIPTOR::d])
{
this->getBlock().getDynamics(iX, iY, iZ)->defineU(iPop, u);
if (_output) {
clout << "defineU(" << iX << ", " << iY << ", " << iZ << " )" << std::endl;
}
}
template
void OffBoundaryConditionInstantiator3D::defineU(
BlockIndicatorF3D& indicator, BlockIndicatorF3D& bulkIndicator, AnalyticalF3D& u)
{
if ( !indicator.isEmpty() ) {
const Vector min = indicator.getMin();
const Vector max = indicator.getMax();
for (int iX = min[0]; iX <= max[0]; ++iX) {
for (int iY = min[1]; iY <= max[1]; ++iY) {
for (int iZ = min[2]; iZ <= max[2]; ++iZ) {
if (indicator(iX, iY, iZ)) {
for (int q = 1; q < DESCRIPTOR::q ; ++q) {
// Get direction
const int iXn = iX + descriptors::c(q,0);
const int iYn = iY + descriptors::c(q,1);
const int iZn = iZ + descriptors::c(q,2);
if (bulkIndicator.getBlockGeometryStructure().isInside(iXn,iYn,iZn) &&
bulkIndicator(iXn,iYn,iZn)) {
T intersection[3] = { };
const int opp = util::opposite(q);
if (this->getBoundaryIntersection(iX, iY, iZ, opp, intersection)) {
T vel[3]= { };
u(vel, intersection);
this->defineU(iX, iY, iZ, opp, vel);
}
}
}
}
}
}
}
}
}
template
void OffBoundaryConditionInstantiator3D::outputOn()
{
_output = true;
}
template
void OffBoundaryConditionInstantiator3D::outputOff()
{
_output = false;
}
}
#endif