/* This file is part of the OpenLB library
*
* Copyright (C) 2007, 2014 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
* The description of a 3D cuboid neighbourhood -- generic implementation.
*/
#ifndef CUBOID_NEIGHBOURHOOD_3D_HH
#define CUBOID_NEIGHBOURHOOD_3D_HH
#include "communication/mpiManager.h"
#include
#include
#include "communication/cuboidNeighbourhood3D.h"
#include "geometry/cuboidGeometry3D.h"
#include "dynamics/dynamics.h"
#include "core/cell.h"
#include "communication/superStructure3D.h"
namespace olb {
//////////////// Class CuboidNeighbourhood3D //////////////////
template
CuboidNeighbourhood3D::CuboidNeighbourhood3D(
SuperStructure3D& superStructure, int iC):_superStructure(superStructure)
{
_iCglob = iC;
_nC = _superStructure.getCuboidGeometry().getNc();
_deltaC = _superStructure.getCuboidGeometry().get(iC).getDeltaR();
_nData = _superStructure.getDataSize();
_nDataType = _superStructure.getDataTypeSize();
_initInCNdone = false;
_initOutCNdone = false;
}
template
CuboidNeighbourhood3D::CuboidNeighbourhood3D (
CuboidNeighbourhood3D const& rhs ):_superStructure(rhs._superStructure)
{
_iCglob = rhs._iCglob;
_nC = rhs._nC;
_deltaC = rhs._deltaC;
_inCells = rhs._inCells;
_outCells = rhs._outCells;
_inC = rhs._inC;
_inN = rhs._inN;
_outC = rhs._outC;
_outN = rhs._outN;
_nData = rhs._nData;
_nDataType = rhs._nDataType;
_initInCNdone = false;
_initOutCNdone = false;
}
template
CuboidNeighbourhood3D CuboidNeighbourhood3D::operator= (
CuboidNeighbourhood3D rhs )
{
CuboidNeighbourhood3D tmp(rhs);
return tmp;
}
template
CuboidNeighbourhood3D::~CuboidNeighbourhood3D()
{
reset();
}
template
Cell3D const& CuboidNeighbourhood3D::get_inCell(int i) const
{
return _inCells[i];
}
template
int CuboidNeighbourhood3D::get_inCellsSize() const
{
return _inCells.size();
}
template
int const& CuboidNeighbourhood3D::get_inC(int i) const
{
return _inC[i];
}
template
int CuboidNeighbourhood3D::get_inCsize() const
{
return _inC.size();
}
template
bool** CuboidNeighbourhood3D::get_inData()
{
return _inData;
}
template
bool** CuboidNeighbourhood3D::get_outData()
{
return _outData;
}
template
void CuboidNeighbourhood3D::add_inCell(Cell3D cell)
{
_inCells.push_back(cell);
}
template
void CuboidNeighbourhood3D::add_outCell(Cell3D cell)
{
_outCells.push_back(cell);
}
template
void CuboidNeighbourhood3D::add_inCell(int iX, int iY, int iZ)
{
Cell3D found;
found.latticeR[0] = _iCglob;
found.latticeR[1] = iX;
found.latticeR[2] = iY;
found.latticeR[3] = iZ;
_superStructure.getCuboidGeometry().getPhysR(found.physR, found.latticeR);
std::vector tmp(found.physR,found.physR + 3);
if (_superStructure.getCuboidGeometry().getC(tmp, found.latticeR[0]) ) {
for (unsigned i=0; i<_inCells.size(); i++) {
if (_inCells[i]==found) {
return;
}
}
_inCells.push_back(found);
}
}
template
void CuboidNeighbourhood3D::add_inCells(int overlap)
{
int nX = _superStructure.getCuboidGeometry().get(_iCglob).getNx();
int nY = _superStructure.getCuboidGeometry().get(_iCglob).getNy();
int nZ = _superStructure.getCuboidGeometry().get(_iCglob).getNz();
for (int iX=0; iX nX + overlap - 1 ||
iY < overlap || iY > nY + overlap - 1 ||
iZ < overlap || iZ > nZ + overlap - 1 ) {
Cell3D found;
found.latticeR[0] = _iCglob;
found.latticeR[1] = iX - overlap;
found.latticeR[2] = iY - overlap;
found.latticeR[3] = iZ - overlap;
_superStructure.getCuboidGeometry().getPhysR(found.physR, found.latticeR);
std::vector tmp(found.physR,found.physR + 3);
if (_superStructure.getCuboidGeometry().getC(tmp, found.latticeR[0]) ) {
_inCells.push_back(found);
}
}
}
}
}
}
template
void CuboidNeighbourhood3D::init_inCN()
{
_inC.clear();
_inN.clear();
_inData = new bool* [_nC];
_inDataCoordinates = new T* [_nC];
_tempInCN = new int [_nC];
for (int i=0; i<_nC; i++) {
_tempInCN[i]=0;
}
for (unsigned i=0; i<_inCells.size(); i++) {
_tempInCN[_inCells[i].latticeR[0]]++;
}
for (int i=0; i<_nC; i++) {
if (_tempInCN[i]!=0) {
_inC.push_back(i);
_inN.push_back(_tempInCN[i]);
#ifdef PARALLEL_MODE_MPI
_inData[i] = new bool [_tempInCN[i]*_nData*_nDataType];
_inDataCoordinates[i] = new T [_tempInCN[i]*3];
#endif
}
#ifdef PARALLEL_MODE_MPI
else {
_inData[i] = NULL;
_inDataCoordinates[i] = NULL;
}
#endif
}
#ifdef PARALLEL_MODE_MPI
int counter=0;
for (int i=0; i<_nC; i++) {
// int dRank = _superStructure.getLoadBalancer().rank(i);
counter++;
}
_mpiNbHelper.allocate(counter);
counter=0;
for (int i=0; i<_nC; i++) {
int dRank = _superStructure.getLoadBalancer().rank(i);
singleton::mpi().iSend(&_tempInCN[i] , 1, dRank, _mpiNbHelper.get_mpiRequest(counter), _iCglob);
counter++;
}
#endif
_initInCNdone = true;
}
template
void CuboidNeighbourhood3D::init_outCN()
{
_outC.clear();
_outN.clear();
_outData = new bool* [_nC];
_outDataCoordinates = new T* [_nC];
std::vector temp(_nC,0);
for (unsigned i=0; i<_outCells.size(); i++) {
temp[_outCells[i].latticeR[0]]++;
}
for (int i=0; i<_nC; i++) {
#ifdef PARALLEL_MODE_MPI
int sRank = _superStructure.getLoadBalancer().rank(i);
singleton::mpi().receive(&temp[i], 1, sRank, i);
#endif
if (temp[i]!=0) {
_outC.push_back(i);
_outN.push_back(temp[i]);
}
_outData[i] = new bool [temp[i]*_nData*_nDataType];
_outDataCoordinates[i] = new T [temp[i]*3];
}
_initOutCNdone = true;
}
#ifdef PARALLEL_MODE_MPI
template
void CuboidNeighbourhood3D::bufSend_inCells(singleton::MpiNonBlockingHelper& helper)
{
helper.free();
std::vector temp(_nC,0);
for (unsigned i=0; i<_inCells.size(); i++) {
int iC = _inCells[i].latticeR[0];
if (singleton::mpi().getRank() != _superStructure.getLoadBalancer().rank(iC)) {
_inDataCoordinates[iC][3*temp[iC]] = _inCells[i].physR[0];
_inDataCoordinates[iC][3*temp[iC]+1] = _inCells[i].physR[1];
_inDataCoordinates[iC][3*temp[iC]+2] = _inCells[i].physR[2];
temp[iC]++;
}
}
int counter=0;
for (unsigned iC=0; iC<_inC.size(); iC++) {
//int dRank = _superStructure.get_load().rank(_inC[iC]);
//if ( singleton::mpi().getRank() != dRank )
counter++;
}
helper.allocate(counter);
counter=0;
for (unsigned iC=0; iC<_inC.size(); iC++) {
int dRank = _superStructure.getLoadBalancer().rank(_inC[iC]);
//if ( singleton::mpi().getRank() != dRank ) {
singleton::mpi().iSend( _inDataCoordinates[_inC[iC]],
_inN[iC]*3, dRank, helper.get_mpiRequest(counter), _iCglob);
counter++;
//}
}
}
#endif
template
void CuboidNeighbourhood3D::recWrite_outCells()
{
#ifdef PARALLEL_MODE_MPI
for (unsigned iC=0; iC<_outC.size(); iC++) {
int sRank = _superStructure.getLoadBalancer().rank(_outC[iC]);
singleton::mpi().receive(_outDataCoordinates[_outC[iC]], _outN[iC]*3, sRank,_outC[iC]);
if ( singleton::mpi().getRank() != sRank ) {
//singleton::mpi().receive(_outDataCoordinates[_outC[iC]], _outN[iC]*3, sRank, _outC[iC]);
Cell3D found;
for (int i=0; i<_outN[iC]; i++) {
found.physR[0] = _outDataCoordinates[_outC[iC]][3*i];
found.physR[1] = _outDataCoordinates[_outC[iC]][3*i+1];
found.physR[2] = _outDataCoordinates[_outC[iC]][3*i+2];
_superStructure.getCuboidGeometry().getLatticeR(found.latticeR, found.physR);
found.latticeR[0] = _outC[iC];
_outCells.push_back(found);
}
}
}
#endif
}
template
void CuboidNeighbourhood3D::finish_comm()
{
#ifdef PARALLEL_MODE_MPI
singleton::mpi().waitAll(_mpiNbHelper);
#endif
}
template
void CuboidNeighbourhood3D::buffer_outData()
{
std::vector temp(_nC,0);
int iCloc = _superStructure.getLoadBalancer().loc(_iCglob);
for (unsigned i=0; i<_outCells.size(); i++) {
int iC = _outCells[i].latticeR[0];
// WARNING: Here is interpolation needed if globX, globY
// are not integers. This needs to be fixed if one will
// use unstructured grids.
//for (int iData=0; iData<_nData; iData++) {
// memcpy(_outData[iC] + (temp[iC]*_nData + iData)*_nDataType, _superStructure(iCloc,iX+overlap,iY+overlap,iZ+overlap,iData), _nDataType);
//}
memcpy(_outData[iC] + temp[iC]*_nData*_nDataType, _superStructure(iCloc,_outCells[i].latticeR[1],_outCells[i].latticeR[2],_outCells[i].latticeR[3],0), _nDataType*_nData);
temp[iC]++;
}
}
template
void CuboidNeighbourhood3D::send_outData()
{
#ifdef PARALLEL_MODE_MPI
for (unsigned iC=0; iC<_outC.size(); iC++) {
int dRank = _superStructure.getLoadBalancer().rank(_outC[iC]);
singleton::mpi().iSend( _outData[_outC[iC]],
_outN[iC]*_nData*_nDataType, dRank, _mpiNbHelper.get_mpiRequest(iC), _iCglob);
}
#endif
}
template
void CuboidNeighbourhood3D::receive_inData()
{
#ifdef PARALLEL_MODE_MPI
for (unsigned iC=0; iC<_inC.size(); iC++) {
int sRank = _superStructure.getLoadBalancer().rank(_inC[iC]);
singleton::mpi().receive(_inData[_inC[iC]], _inN[iC]*_nData*_nDataType, sRank,_inC[iC]);
}
#endif
}
template
void CuboidNeighbourhood3D::write_inData()
{
int iCloc = _superStructure.getLoadBalancer().loc(_iCglob);
std::vector temp(_nC,0);
for (unsigned i=0; i<_inCells.size(); i++) {
int iC = _inCells[i].latticeR[0];
//for (int iData=0; iData<_nData; iData++) {
// memcpy(_superStructure(iCloc,iX+overlap,iY+overlap,iZ+overlap,iData), _inData[iC] + (temp[iC]*_nData + iData)*_nDataType, _nDataType);
//}
//memcpy(_superStructure(iCloc,iX+overlap,iY+overlap,iZ+overlap,0), _inData[iC] + temp[iC]*_nData*_nDataType, _nData*_nDataType);
//temp[iC]++;
memcpy(_superStructure(iCloc,_inCells[i].latticeR[1],_inCells[i].latticeR[2],_inCells[i].latticeR[3],0), _inData[iC] + temp[iC]*_nData*_nDataType, _nData*_nDataType);
temp[iC]++;
}
}
template
void CuboidNeighbourhood3D::reset()
{
if (_initInCNdone) {
#ifdef PARALLEL_MODE_MPI
for (int iC=0; iC<_nC; iC++) {
delete[] _inData[iC];
delete[] _inDataCoordinates[iC];
}
#endif
delete[] _inData;
delete[] _inDataCoordinates;
delete[] _tempInCN;
_initInCNdone = false;
}
if (_initOutCNdone) {
for (int iC=0; iC<_nC; iC++) {
delete[] _outData[iC];
delete[] _outDataCoordinates[iC];
}
delete[] _outData;
delete[] _outDataCoordinates;
#ifdef PARALLEL_MODE_MPI
_mpiNbHelper.free();
#endif
_initOutCNdone = false;
}
_inCells.clear();
_outCells.clear();
_inC.clear();
_outC.clear();
_inN.clear();
_outN.clear();
}
} // namespace olb
#endif