/* 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