/* This file is part of the OpenLB library
*
* Copyright (C) 2015 Thomas Henn
* 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 PLATTICE_H_
#define PLATTICE_H_
#include "sortAlgorithms.h"
namespace olb {
template class PARTICLETYPE>
class PLattice : public ContactDetection {
public:
PLattice(ParticleSystem3D& pSys, T overlap, T spacing);
void sort();
int getMatches(int pInt,
std::vector >& matches);
private:
PLattice* generate(ParticleSystem3D& pSys);
std::vector _physPos, _physExtend;
std::vector _intExtend;
T _overlap;
T _spacing;
std::vector> > > _pLattice;
};
template class PARTICLETYPE>
PLattice* PLattice::generate(ParticleSystem3D& pSys) {
//std::cout << "calling NanoflannContact.generate()" << std::endl;
return new PLattice(pSys,_overlap, _spacing);
}
template class PARTICLETYPE>
PLattice::PLattice(ParticleSystem3D& pSys,
T overlap, T spacing)
: ContactDetection(pSys, "PLattice"),
_physPos(3, T()),
_physExtend(3, T()),
_intExtend(3, 0),
_overlap(overlap),
_spacing(spacing) {
_physPos = this->_pSys.getPhysPos();
_physExtend = this->_pSys.getPhysExtend();
int intOverlap = std::ceil(overlap / _spacing);
cout << "intOverlap: " << intOverlap << std::endl;
for (int i = 0; i < 3; i++) {
_physPos[i] -= overlap;
_intExtend[i] = std::ceil(_physExtend[i] / _spacing + 2 * intOverlap + 1);
cout << "intExtend[" << i << "]: " << _physExtend[i] << std::endl;
}
cout << "intOverlap: " << intOverlap << std::endl;
_pLattice.resize(_intExtend[0]);
for (int iX = 0; iX < _intExtend[0]; ++iX) {
_pLattice[iX].resize(_intExtend[1]);
for (int iY = 0; iY < _intExtend[1]; ++iY) {
_pLattice[iX][iY].resize(_intExtend[2]);
for (int iZ = 0; iZ < _intExtend[2]; ++iZ) {
}
}
}
// cout << "intExtend " << _intExtend[0] << " "<< _intExtend[1] << " "<< _intExtend[2] << " " << std::endl;
}
template class PARTICLETYPE>
void PLattice::sort() {
// _pLattice.clear();
for (int i = 0; i < _intExtend[0]; i++) {
for (int j = 0; j < _intExtend[1]; j++) {
for (int k = 0; k < _intExtend[2]; k++) {
_pLattice[i][j][k].clear();
}
}
}
std::vector pos(3, T());
for (unsigned int i = 0; i < this->_pSys.sizeInclShadow(); i++) {
pos = this->_pSys[i].getPos();
#if OLB_DEBUG
int aa = (pos[0] - _physPos[0]) / _spacing;
int bb = (pos[1] - _physPos[1]) / _spacing;
int cc = (pos[2] - _physPos[2]) / _spacing;
OLB_PRECONDITION( aa >= 0);
OLB_PRECONDITION( bb >= 0);
OLB_PRECONDITION( cc >= 0);
OLB_PRECONDITION( aa < _intExtend[0]);
OLB_PRECONDITION( bb < _intExtend[1]);
OLB_PRECONDITION( cc < _intExtend[2]);
#endif
_pLattice[(int) floor((pos[0] - _physPos[0]) / _spacing)][(int) floor(
(pos[1] - _physPos[1]) / _spacing)][(int) floor(
(pos[2] - _physPos[2]) / _spacing)].push_back(i);
}
int iX = 0, iY = 0, iZ = 0;
int x = 0, y = 0, z = 0;
for (unsigned int s = 0; s < this->_pSys.size(); s++) {
pos = this->_pSys[s].getPos();
iX = floor((pos[0] - _physPos[0]) / _spacing);
iY = floor((pos[1] - _physPos[1]) / _spacing);
iZ = floor((pos[2] - _physPos[2]) / _spacing);
//
if (_pLattice[iX][iY][iZ].back() != -1) {
int a = 1, b = 1, c = 1;
int d = -1, e = -1, f = -1;
if (iX <= 0)
d = 0;
if (iY <= 0)
e = 0;
if (iZ <= 0)
f = 0;
if (iX >= _intExtend[0])
a = 0;
if (iY >= _intExtend[1])
b = 0;
if (iZ >= _intExtend[2])
c = 0;
typename std::list::iterator it;
for (int i = d; i <= a; i++) {
for (int j = e; j <= b; j++) {
for (int k = f; k <= c; k++) {
if (i != 0 || j != 0 || k != 0) {
it = _pLattice[iX + i][iY + j][iZ + k].begin();
int size = _pLattice[iX + i][iY + j][iZ + k].size();
for (int lauf = 0; lauf < size; lauf++, it++) {
if (*it != -1) {
pos = this->_pSys[*it].getPos();
T rad = this->_pSys[*it].getRad();
x = floor((pos[0] - _physPos[0] - i * rad) / _spacing);
y = floor((pos[1] - _physPos[1] - j * rad) / _spacing);
z = floor((pos[2] - _physPos[2] - k * rad) / _spacing);
if (x != iX || y != iY || z != iZ) {
_pLattice[iX][iY][iZ].push_back(*it);
}
}
}
}
}
}
}
_pLattice[iX][iY][iZ].push_back(-1);
}
}
}
template class PARTICLETYPE>
int PLattice::getMatches(int pInt,
std::vector >& matches) {
matches.clear();
PARTICLETYPE& p = this->_pSys[pInt];
int iX = floor((p.getPos()[0] - _physPos[0]) / _spacing);
int iY = floor((p.getPos()[1] - _physPos[1]) / _spacing);
int iZ = floor((p.getPos()[2] - _physPos[2]) / _spacing);
typename std::list::iterator it = _pLattice[iX][iY][iZ].begin();
std::vector& pos = p.getPos();
for (; it != _pLattice[iX][iY][iZ].end(); ++it) {
if (*it != -1) {
std::vector& pos2 = this->_pSys[*it].getPos();
matches.push_back(
make_pair(
*it,
std::pow(pos[0] - pos2[0], 2) + std::pow(pos[1] - pos2[1], 2)
+ std::pow(pos[2] - pos2[2], 2)));
}
}
return matches.size();
}
} // namespace olb
#endif