/* 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 vector of 3D cuboid -- generic implementation.
*/
#ifndef CUBOID_GEOMETRY_3D_HH
#define CUBOID_GEOMETRY_3D_HH
#include
#include
#include
#include
#include
#include "geometry/cuboidGeometry3D.h"
#include "functors/analytical/indicator/indicatorF3D.h"
#include "communication/loadBalancer.h"
namespace olb {
template
CuboidGeometry3D::CuboidGeometry3D()
: _motherCuboid(0,0,0,0,0,0,0), _periodicityOn(false), clout(std::cout, "CuboidGeometry3D")
{
_cuboids.reserve(2);
add(_motherCuboid);
split(0, 1);
}
template
CuboidGeometry3D::CuboidGeometry3D(T originX, T originY, T originZ, T deltaR,
int nX, int nY, int nZ, int nC)
: _motherCuboid(originX, originY, originZ, deltaR, nX, nY, nZ),
_periodicityOn(false), clout(std::cout, "CuboidGeometry3D")
{
_cuboids.reserve(nC+2);
add(_motherCuboid);
split(0, nC);
}
template
CuboidGeometry3D::CuboidGeometry3D(std::vector origin, T deltaR,
std::vector extent, int nC)
: CuboidGeometry3D(origin[0], origin[1], origin[2], deltaR,
extent[0], extent[1], extent[2], nC)
{
_cuboids.reserve(nC+2);
}
template
CuboidGeometry3D::CuboidGeometry3D(IndicatorF3D& indicatorF, T voxelSize, int nC)
: _motherCuboid( indicatorF.getMin()[0], indicatorF.getMin()[1], indicatorF.getMin()[2], voxelSize,
(int)((indicatorF.getMax()[0] - indicatorF.getMin()[0]) / voxelSize + 1.5),
(int)((indicatorF.getMax()[1] - indicatorF.getMin()[1]) / voxelSize + 1.5),
(int)((indicatorF.getMax()[2] - indicatorF.getMin()[2]) / voxelSize + 1.5)),
_periodicityOn(false), clout(std::cout, "CuboidGeometry3D")
{
_cuboids.reserve(nC+2);
add(_motherCuboid);
split(0, nC);
shrink(indicatorF);
}
template
CuboidGeometry3D::CuboidGeometry3D(std::shared_ptr> indicator_sharedPtrF, T voxelSize, int nC)
: CuboidGeometry3D(*indicator_sharedPtrF, voxelSize, nC)
{
}
template
CuboidGeometry3D::CuboidGeometry3D(IndicatorF3D& indicatorF, T voxelSize, int nC, std::string minimizeBy)
: _motherCuboid( indicatorF.getMin()[0], indicatorF.getMin()[1], indicatorF.getMin()[2], voxelSize,
(int)((indicatorF.getMax()[0] - indicatorF.getMin()[0]) / voxelSize + 1.5),
(int)((indicatorF.getMax()[1] - indicatorF.getMin()[1]) / voxelSize + 1.5),
(int)((indicatorF.getMax()[2] - indicatorF.getMin()[2]) / voxelSize + 1.5)),
_periodicityOn(false), clout(std::cout, "CuboidGeometry3D")
{
_cuboids.reserve(nC+2);
add(_motherCuboid);
if ( minimizeBy == "volume" ) {
// Search for the largest multiplier not dividable by two
int initalNc = nC;
while ( initalNc % 2 == 0 ) {
initalNc /= 2;
}
// Split evenly in initalNc many cuboids and shrink all
split(0, initalNc);
shrink(indicatorF);
while ( getNc() < nC ) {
// clout << "Starting with " << getNc() << " Cuboids." << std::endl;
// Search for the largest child cuboid
T iCVolume[getNc()];
int maxiC = 0;
for (int iC = 0; iC < getNc(); iC++) {
iCVolume[iC] = get(iC).getLatticeVolume();
if ( iCVolume[iC] > iCVolume[maxiC] ) {
maxiC = iC;
}
// clout << "Cuboid #" << iC << " with volume " << iCVolume[iC] << " and weight " << get(iC).getWeight() << std::endl;
}
// clout << "Found maximum volume cuboid #" << maxiC << " with volume " << iCVolume[maxiC] << std::endl;
// looking for largest extend, because halfing the cuboid by its largest extend will result in the smallest surface and therfore in the least comminication cells
if ( get(maxiC).getNx() >= get(maxiC).getNy() && get(maxiC).getNx() >= get(maxiC).getNz()) {
// clout << "Cut in x direction!" << std::endl;
get(maxiC).divide(2,1,1,_cuboids);
}
else if ( get(maxiC).getNy() >= get(maxiC).getNx() && get(maxiC).getNy() >= get(maxiC).getNz()) {
// clout << "Cut in y direction!" << std::endl;
get(maxiC).divide(1,2,1,_cuboids);
}
else {
// clout << "Cut in z direction!" << std::endl;
get(maxiC).divide(1,1,2,_cuboids);
}
remove(maxiC);
// shrink the two new cuboids
shrink(_cuboids.size()-2,indicatorF);
shrink(_cuboids.size()-1,indicatorF);
}
}
else if ( minimizeBy == "weight" ) {
setWeights(indicatorF);
// conduct a prime factorisation for the number of cuboids nC
std::vector factors;
int initalNc = nC;
// iterate over the prime numbes from 0 to 100 (may have to be extended)
for ( int i : {
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71
} ) {
while ( initalNc % i == 0 ) {
initalNc /= i;
factors.push_back(i);
}
}
// recursively split the current cuboids by each prime factor
for ( int i = factors.size() - 1; i >= 0; i-- ) {
int currentNc = _cuboids.size();
for ( int iC = 0; iC < currentNc; iC++ ) {
// clout << "split cuboid number #" << iC << " in " << factors[i] << " parts" << std::endl;
splitByWeight(iC, factors[i], indicatorF);
shrink(indicatorF);
}
for ( int iC = 0; iC < currentNc; iC++ ) {
// clout << "delet cuboid number #" << iC << std::endl;
remove(0);
}
}
}
}
template
CuboidGeometry3D::CuboidGeometry3D(std::shared_ptr> indicator_sharedPtrF, T voxelSize, int nC, std::string minimizeBy)
: CuboidGeometry3D(*indicator_sharedPtrF, voxelSize, nC, minimizeBy)
{
}
template
CuboidGeometry3D::~CuboidGeometry3D() {};
template
Cuboid3D& CuboidGeometry3D::get(int iC)
{
return _cuboids[iC];
}
template
Cuboid3D const& CuboidGeometry3D::get(int iC) const
{
return _cuboids[iC];
}
template
Cuboid3D CuboidGeometry3D::getMotherCuboid()
{
return _motherCuboid;
}
template
Cuboid3D const& CuboidGeometry3D::getMotherCuboid() const
{
return _motherCuboid;
}
template
void CuboidGeometry3D::setPeriodicity(bool periodicityX, bool periodicityY, bool periodicityZ)
{
_periodicityOn[0] = periodicityX;
_periodicityOn[1] = periodicityY;
_periodicityOn[2] = periodicityZ;
}
template
int CuboidGeometry3D::get_iC(T x, T y, T z, int offset) const
{
unsigned i;
for (i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].checkPoint(x, y, z, offset)) {
return (int)i;
}
}
return (int)i;
}
template
int CuboidGeometry3D::get_iC(Vector coords, int offset) const
{
return get_iC(coords[0], coords[1], coords[2], offset);
}
template
int CuboidGeometry3D::get_iC(T x, T y, T z, int orientationX, int orientationY,
int orientationZ) const
{
unsigned i;
for (i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].checkPoint(x, y, z) &&
_cuboids[i].checkPoint(x + orientationX / _cuboids[i].getDeltaR(),
y + orientationY / _cuboids[i].getDeltaR(),
z + orientationZ / _cuboids[i].getDeltaR())) {
return (int)i;
}
}
return (int)i;
}
template
bool CuboidGeometry3D::getC(T physR[3], int& iC) const
{
const int iCtmp = get_iC(physR[0], physR[1], physR[2]);
if (iCtmp < getNc()) {
iC = iCtmp;
return true;
}
else {
return false;
}
}
template
bool CuboidGeometry3D::getC(std::vector physR, int& iC) const
{
const int iCtmp = get_iC(physR);
if (iCtmp < getNc()) {
iC = iCtmp;
return true;
}
else {
return false;
}
}
template
bool CuboidGeometry3D::getC(const Vector& physR, int& iC) const
{
const int iCtmp = get_iC(physR);
if (iCtmp < getNc()) {
iC = iCtmp;
return true;
}
else {
return false;
}
}
template
bool CuboidGeometry3D::getLatticeR(int latticeR[4], const T physR[3]) const
{
int iCtmp = get_iC(physR[0], physR[1], physR[2]);
if (iCtmp < getNc()) {
latticeR[0] = iCtmp;
latticeR[1] = (int)floor( (physR[0] - _cuboids[latticeR[0]].getOrigin()[0] ) / _cuboids[latticeR[0]].getDeltaR() + .5);
latticeR[2] = (int)floor( (physR[1] - _cuboids[latticeR[0]].getOrigin()[1] ) / _cuboids[latticeR[0]].getDeltaR() + .5);
latticeR[3] = (int)floor( (physR[2] - _cuboids[latticeR[0]].getOrigin()[2] ) / _cuboids[latticeR[0]].getDeltaR() + .5);
return true;
}
else {
return false;
}
}
template
bool CuboidGeometry3D::getFloorLatticeR(const std::vector& physR, std::vector& latticeR) const
{
int iCtmp = get_iC(physR[0], physR[1], physR[2]);
if (iCtmp < getNc()) {
latticeR[0] = iCtmp;
latticeR[1] = (int)floor( (physR[0] - _cuboids[latticeR[0]].getOrigin()[0] ) / _cuboids[latticeR[0]].getDeltaR() );
latticeR[2] = (int)floor( (physR[1] - _cuboids[latticeR[0]].getOrigin()[1] ) / _cuboids[latticeR[0]].getDeltaR() );
latticeR[3] = (int)floor( (physR[2] - _cuboids[latticeR[0]].getOrigin()[2] ) / _cuboids[latticeR[0]].getDeltaR() );
return true;
}
else {
return false;
}
}
template
bool CuboidGeometry3D::getFloorLatticeR(
const Vector& physR, Vector& latticeR) const
{
int iCtmp = get_iC(physR[0], physR[1], physR[2]);
if (iCtmp < getNc()) {
latticeR[0] = iCtmp;
latticeR[1] = (int)floor( (physR[0] - _cuboids[latticeR[0]].getOrigin()[0] ) / _cuboids[latticeR[0]].getDeltaR() );
latticeR[2] = (int)floor( (physR[1] - _cuboids[latticeR[0]].getOrigin()[1] ) / _cuboids[latticeR[0]].getDeltaR() );
latticeR[3] = (int)floor( (physR[2] - _cuboids[latticeR[0]].getOrigin()[2] ) / _cuboids[latticeR[0]].getDeltaR() );
return true;
}
else {
return false;
}
}
template
void CuboidGeometry3D::getPhysR(T physR[3], const int& iCglob, const int& iX, const int& iY, const int& iZ) const
{
_cuboids[iCglob].getPhysR(physR, iX, iY, iZ);
for (int iDim = 0; iDim < 3; iDim++) {
if (_periodicityOn[iDim]) {
//std::cout << "!!! " << iDim << _periodicityOn[iDim] <<":"<< _motherCuboid.getDeltaR()*(_motherCuboid.getExtend()[iDim]) << std::endl;
physR[iDim] = remainder( physR[iDim] - _motherCuboid.getOrigin()[iDim]
+ _motherCuboid.getDeltaR() * (_motherCuboid.getExtend()[iDim]),
_motherCuboid.getDeltaR() * (_motherCuboid.getExtend()[iDim]));
// solving the rounding error problem for double
if ( physR[iDim]*physR[iDim] < 0.001 * _motherCuboid.getDeltaR()*_motherCuboid.getDeltaR() ) {
physR[iDim] = T();
}
// make it to mod instead remainer
if ( physR[iDim] < 0 ) {
physR[iDim] += _motherCuboid.getDeltaR() *( _motherCuboid.getExtend()[iDim]);
}
// add origin
physR[iDim] += _motherCuboid.getOrigin()[iDim];
}
}
return;
}
template
void CuboidGeometry3D::getPhysR(T physR[3], const int latticeR[4]) const
{
getPhysR(physR, latticeR[0], latticeR[1], latticeR[2], latticeR[3]);
}
template
void CuboidGeometry3D::getNeighbourhood(int cuboid, std::vector& neighbours, int overlap)
{
neighbours.clear();
std::set dummy;
for (int iC = 0; iC < getNc(); iC++) {
if (cuboid == iC) {
continue;
}
T globX = get(iC).getOrigin()[0];
T globY = get(iC).getOrigin()[1];
T globZ = get(iC).getOrigin()[2];
T nX = get(iC).getNx();
T nY = get(iC).getNy();
T nZ = get(iC).getNz();
T deltaR = get(iC).getDeltaR();
if (get(cuboid).checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
//neighbours.push_back(iC);
dummy.insert(iC);
}
if (_periodicityOn[0]) {
if (get(cuboid).getOrigin()[0] + (get(cuboid).getNx() + overlap - 1)*get(cuboid).getDeltaR() > getMaxPhysR()[0]) {
Cuboid3D cub(get(cuboid).getOrigin()[0]-getMaxPhysR()[0],
get(cuboid).getOrigin()[1],
get(cuboid).getOrigin()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
if (get(cuboid).getOrigin()[0] - overlap*get(cuboid).getDeltaR() < getMinPhysR()[0]) {
Cuboid3D cub(get(cuboid).getOrigin()[0]+getMaxPhysR()[0],
get(cuboid).getOrigin()[1],
get(cuboid).getOrigin()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
}
if (_periodicityOn[1]) {
if (get(cuboid).getOrigin()[1] + (get(cuboid).getNy() + overlap - 1)*get(cuboid).getDeltaR() > getMaxPhysR()[1]) {
Cuboid3D cub(get(cuboid).getOrigin()[0],
get(cuboid).getOrigin()[1]-getMaxPhysR()[1],
get(cuboid).getOrigin()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
if (get(cuboid).getOrigin()[1] - overlap*get(cuboid).getDeltaR() < getMinPhysR()[1]) {
Cuboid3D cub(get(cuboid).getOrigin()[0],
get(cuboid).getOrigin()[1]+getMaxPhysR()[1],
get(cuboid).getOrigin()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
}
if (_periodicityOn[2]) {
if (get(cuboid).getOrigin()[2] + (get(cuboid).getNz() + overlap - 1)*get(cuboid).getDeltaR() > getMaxPhysR()[2]) {
Cuboid3D cub(get(cuboid).getOrigin()[0],
get(cuboid).getOrigin()[1],
get(cuboid).getOrigin()[2]-getMaxPhysR()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
if (get(cuboid).getOrigin()[2] - overlap*get(cuboid).getDeltaR() < getMinPhysR()[2]) {
Cuboid3D cub(get(cuboid).getOrigin()[0],
get(cuboid).getOrigin()[1],
get(cuboid).getOrigin()[2]+getMaxPhysR()[2],
get(cuboid).getDeltaR(),
get(cuboid).getNx(),
get(cuboid).getNy(),
get(cuboid).getNz());
if (cub.checkInters(globX - overlap * deltaR,
globX + (nX + overlap - 1)*deltaR,
globY - overlap * deltaR,
globY + (nY + overlap - 1)*deltaR,
globZ - overlap * deltaR,
globZ + (nZ + overlap - 1)*deltaR, overlap)) {
dummy.insert(iC);
}
}
}
}
std::set::iterator it = dummy.begin();
for (; it != dummy.end(); ++it) {
neighbours.push_back(*it);
}
}
template
int CuboidGeometry3D::getNc() const
{
return _cuboids.size();
}
template
T CuboidGeometry3D::getMinRatio() const
{
T minRatio = 1.;
for (unsigned i = 0; i < _cuboids.size(); i++) {
if ((T)_cuboids[i].getNx() / (T)_cuboids[i].getNy() < minRatio) {
minRatio = (T)_cuboids[i].getNx() / (T)_cuboids[i].getNy();
}
if ((T)_cuboids[i].getNy() / (T)_cuboids[i].getNz() < minRatio) {
minRatio = (T)_cuboids[i].getNy() / (T)_cuboids[i].getNz();
}
if ((T)_cuboids[i].getNz() / (T)_cuboids[i].getNx() < minRatio) {
minRatio = (T)_cuboids[i].getNz() / (T)_cuboids[i].getNx();
}
}
return minRatio;
}
template
T CuboidGeometry3D::getMaxRatio() const
{
T maxRatio = 1.;
for (unsigned i = 0; i < _cuboids.size(); i++) {
if ((T)_cuboids[i].getNx() / (T)_cuboids[i].getNy() > maxRatio) {
maxRatio = (T)_cuboids[i].getNx() / (T)_cuboids[i].getNy();
}
if ((T)_cuboids[i].getNy() / (T)_cuboids[i].getNz() > maxRatio) {
maxRatio = (T)_cuboids[i].getNy() / (T)_cuboids[i].getNz();
}
if ((T)_cuboids[i].getNz() / (T)_cuboids[i].getNx() > maxRatio) {
maxRatio = (T)_cuboids[i].getNz() / (T)_cuboids[i].getNx();
}
}
return maxRatio;
}
template
Vector CuboidGeometry3D::getMinPhysR() const
{
Vector output (_cuboids[0].getOrigin());
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getOrigin()[0] < output[0]) {
output[0] = _cuboids[i].getOrigin()[0];
}
if (_cuboids[i].getOrigin()[1] < output[1]) {
output[1] = _cuboids[i].getOrigin()[1];
}
if (_cuboids[i].getOrigin()[2] < output[2]) {
output[2] = _cuboids[i].getOrigin()[2];
}
}
return output;
}
template
Vector CuboidGeometry3D::getMaxPhysR() const
{
Vector output (_cuboids[0].getOrigin());
output[0] += _cuboids[0].getNx()*_cuboids[0].getDeltaR();
output[1] += _cuboids[0].getNy()*_cuboids[0].getDeltaR();
output[2] += _cuboids[0].getNz()*_cuboids[0].getDeltaR();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getOrigin()[0] + _cuboids[i].getNx()*_cuboids[i].getDeltaR() > output[0]) {
output[0] = _cuboids[i].getOrigin()[0] + _cuboids[i].getNx()*_cuboids[i].getDeltaR();
}
if (_cuboids[i].getOrigin()[1] + _cuboids[i].getNy()*_cuboids[i].getDeltaR() > output[1]) {
output[1] = _cuboids[i].getOrigin()[1] + _cuboids[i].getNy()*_cuboids[i].getDeltaR();
}
if (_cuboids[i].getOrigin()[2] + _cuboids[i].getNz()*_cuboids[i].getDeltaR() > output[2]) {
output[2] = _cuboids[i].getOrigin()[2] + _cuboids[i].getNz()*_cuboids[i].getDeltaR();
}
}
return output;
}
template
T CuboidGeometry3D::getMinPhysVolume() const
{
T minVolume = _cuboids[0].getPhysVolume();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getPhysVolume() < minVolume) {
minVolume = _cuboids[i].getPhysVolume();
}
}
return minVolume;
}
template
T CuboidGeometry3D::getMaxPhysVolume() const
{
T maxVolume = _cuboids[0].getPhysVolume();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getPhysVolume() > maxVolume) {
maxVolume = _cuboids[i].getPhysVolume();
}
}
return maxVolume;
}
template
size_t CuboidGeometry3D::getMinLatticeVolume() const
{
size_t minNodes = _cuboids[0].getLatticeVolume();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getLatticeVolume() < minNodes) {
minNodes = _cuboids[i].getLatticeVolume();
}
}
return minNodes;
}
template
size_t CuboidGeometry3D::getMaxLatticeVolume() const
{
size_t maxNodes = _cuboids[0].getLatticeVolume();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getLatticeVolume() > maxNodes) {
maxNodes = _cuboids[i].getLatticeVolume();
}
}
return maxNodes;
}
template
size_t CuboidGeometry3D::getMinLatticeWeight() const
{
size_t minNodes = _cuboids[0].getWeight();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getWeight() < minNodes) {
minNodes = _cuboids[i].getWeight();
}
}
return minNodes;
}
template
size_t CuboidGeometry3D::getMaxLatticeWeight() const
{
size_t maxNodes = _cuboids[0].getWeight();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getWeight() > maxNodes) {
maxNodes = _cuboids[i].getWeight();
}
}
return maxNodes;
}
template
T CuboidGeometry3D::getMinDeltaR() const
{
T minDelta = _cuboids[0].getDeltaR();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getDeltaR() < minDelta) {
minDelta = _cuboids[i].getDeltaR();
}
}
return minDelta;
}
template
T CuboidGeometry3D::getMaxDeltaR() const
{
T maxDelta = _cuboids[0].getDeltaR();
for (unsigned i = 0; i < _cuboids.size(); i++) {
if (_cuboids[i].getDeltaR() > maxDelta) {
maxDelta = _cuboids[i].getDeltaR();
}
}
return maxDelta;
}
template
bool CuboidGeometry3D::operator==(CuboidGeometry3D& rhs)
{
return _motherCuboid == rhs._motherCuboid
&& _periodicityOn == rhs._periodicityOn
&& _cuboids == rhs._cuboids;
}
template
void CuboidGeometry3D::add(Cuboid3D cuboid)
{
_cuboids.push_back(cuboid);
}
template
void CuboidGeometry3D::remove(int iC)
{
_cuboids.erase(_cuboids.begin() + iC);
}
template
void CuboidGeometry3D::remove(IndicatorF3D& indicatorF)
{
//IndicatorIdentity3D tmpIndicatorF(indicatorF);
std::vector allZero;
int latticeR[4];
T physR[3];
for (unsigned iC = 0; iC < _cuboids.size(); iC++) {
latticeR[0] = iC;
allZero.push_back(true);
for (int iX = 0; iX < _cuboids[iC].getNx(); iX++) {
for (int iY = 0; iY < _cuboids[iC].getNy(); iY++) {
for (int iZ = 0; iZ < _cuboids[iC].getNz(); iZ++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
bool inside[1];
indicatorF(inside,physR);
if (inside[0]) {
allZero[iC] = 0;
}
}
}
}
}
for (int iC = _cuboids.size() - 1; iC >= 0; iC--) {
if (allZero[iC] ) {
remove(iC);
}
}
}
template
void CuboidGeometry3D::shrink(int iC, IndicatorF3D& indicatorF)
{
int latticeR[4];
T physR[3];
bool inside[1];
latticeR[0] = iC;
size_t fullCells = 0;
int xN = get(iC).getNx();
int yN = get(iC).getNy();
int zN = get(iC).getNz();
int maxX = 0;
int maxY = 0;
int maxZ = 0;
int newX = xN - 1;
int newY = yN - 1;
int newZ = zN - 1;
for (int iX = 0; iX < xN; iX++) {
for (int iY = 0; iY < yN; iY++) {
for (int iZ = 0; iZ < zN; iZ++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
indicatorF(inside,physR);
if (inside[0]) {
fullCells++;
maxX = std::max(maxX, iX);
maxY = std::max(maxY, iY);
maxZ = std::max(maxZ, iZ);
newX = std::min(newX, iX);
newY = std::min(newY, iY);
newZ = std::min(newZ, iZ);
}
}
}
}
// if (maxX+2 < xN) maxX+=2; else if (maxX+1 < xN) maxX+=1;
// if (maxY+2 < yN) maxY+=2; else if (maxY+1 < yN) maxY+=1;
// if (maxZ+2 < zN) maxZ+=2; else if (maxZ+1 < zN) maxZ+=1;
//
// if (newX-2 >= 0) newX-=2; else if (newX-1 >= 0) newX-=1;
// if (newY-2 >= 0) newY-=2; else if (newY-1 >= 0) newY-=1;
// if (newZ-2 >= 0) newZ-=2; else if (newZ-1 >= 0) newZ-=1;
if (fullCells > 0) {
get(iC).setWeight(fullCells);
_cuboids[iC].resize(newX, newY, newZ, maxX - newX + 1, maxY - newY + 1, maxZ - newZ + 1);
}
else {
remove(iC);
}
}
template
void CuboidGeometry3D::shrink(IndicatorF3D& indicatorF)
{
for (int iC = getNc() - 1; iC >= 0; iC--) {
shrink(iC, indicatorF);
}
// shrink mother cuboid
Vector minPhysR = getMinPhysR();
Vector maxPhysR = getMaxPhysR();
T minDelataR = getMinDeltaR();
_motherCuboid = Cuboid3D(minPhysR[0], minPhysR[1], minPhysR[2], minDelataR,
(int)((maxPhysR[0]-minPhysR[0])/minDelataR + 0.5),
(int)((maxPhysR[1]-minPhysR[1])/minDelataR + 0.5),
(int)((maxPhysR[2]-minPhysR[2])/minDelataR + 0.5));
}
template
void CuboidGeometry3D::split(int iC, int p)
{
Cuboid3D temp(_cuboids[iC].getOrigin()[0], _cuboids[iC].getOrigin()[1],
_cuboids[iC].getOrigin()[2], _cuboids[iC].getDeltaR(),
_cuboids[iC].getNx(), _cuboids[iC].getNy(), _cuboids[iC].getNz());
temp.divide(p, _cuboids);
remove(iC);
}
template
void CuboidGeometry3D::splitByWeight(int iC, int p, IndicatorF3D& indicatorF)
{
T averageWeight = get(iC).getWeight() / (T) p;
// clout << "Mother " << get(iC).getWeight() << " " << averageWeight << std::endl;
Cuboid3D temp(_cuboids[iC].getOrigin()[0], _cuboids[iC].getOrigin()[1],
_cuboids[iC].getOrigin()[2], _cuboids[iC].getDeltaR(),
_cuboids[iC].getNx(), _cuboids[iC].getNy(), _cuboids[iC].getNz());
int latticeR[4];
T physR[3];
latticeR[0] = iC;
int xN = get(iC).getNx();
int yN = get(iC).getNy();
int zN = get(iC).getNz();
T deltaR = get(iC).getDeltaR();
int fullCells = 0;
Vector globPos_child = get(iC).getOrigin();
std::vector extend_child = {xN, yN, zN};
int localPos_child = 0;
// looking for largest extend, because halfing the cuboid by its largest extend will result in the smallest surface and therfore in the least comminication cells
if ( get(iC).getNx() >= get(iC).getNy() && get(iC).getNx() >= get(iC).getNz()) {
// clout << "Cut in x direction!" << std::endl;
// for each child cuboid search for the optimal cutting plane
for ( int iChild = 0; iChild < p - 1; iChild++) {
fullCells = 0;
int fullCells_minusOne = 0;
for (int iX = localPos_child; iX < xN; iX++) {
fullCells_minusOne = fullCells;
for (int iY = 0; iY < yN; iY++) {
for (int iZ = 0; iZ < zN; iZ++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
bool inside[1];
indicatorF(inside,physR);
if (inside[0]) {
fullCells++;
}
}
}
// the optimal cutting plane is determined, so that the child cuboid's cells inside the indicator are the closest to the total cells inside the indicator per number of children
if ( fullCells >= averageWeight ) {
if ( (fullCells - averageWeight) > (averageWeight - fullCells_minusOne) ) {
iX--;
}
// clout << "found optimal iX = " << iX << std::endl;
extend_child[0] = iX - localPos_child + 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
globPos_child[0] += extend_child[0]*deltaR;
localPos_child += extend_child[0] + 1;
// clout << "added child " << iChild << " of " << p << std::endl;
break;
}
}
}
extend_child[0] = xN - localPos_child + p - 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
// clout << "added last child of " << p << std::endl;
}
else if ( get(iC).getNy() >= get(iC).getNx() && get(iC).getNy() >= get(iC).getNz()) {
// clout << "Cut in y direction!" << std::endl;
for ( int iChild = 0; iChild < p - 1; iChild++) {
fullCells = 0;
int fullCells_minusOne = 0;
for (int iY = localPos_child; iY < yN; iY++) {
fullCells_minusOne = fullCells;
for (int iX = 0; iX < xN; iX++) {
for (int iZ = 0; iZ < zN; iZ++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
bool inside[1];
indicatorF(inside,physR);
if (inside[0]) {
fullCells++;
}
}
}
if ( fullCells >= averageWeight ) {
if ( (fullCells - averageWeight) > (averageWeight - fullCells_minusOne) ) {
iY--;
}
// clout << "found optimal iY = " << iY << std::endl;
extend_child[1] = iY - localPos_child + 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
globPos_child[1] += extend_child[1]*deltaR;
localPos_child += extend_child[1] + 1;
// clout << "added child " << iChild << " of " << p << std::endl;
break;
}
}
}
extend_child[1] = yN - localPos_child + p - 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
// clout << "added last child of " << p << std::endl;
}
else {
// clout << "Cut in z direction!" << std::endl;
for ( int iChild = 0; iChild < p - 1; iChild++) {
fullCells = 0;
int fullCells_minusOne = 0;
for (int iZ = localPos_child; iZ < zN; iZ++) {
fullCells_minusOne = fullCells;
for (int iY = 0; iY < yN; iY++) {
for (int iX = 0; iX < xN; iX++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
bool inside[1];
indicatorF(inside,physR);
if (inside[0]) {
fullCells++;
}
}
}
if ( fullCells >= averageWeight ) {
if ( (fullCells - averageWeight) > (averageWeight - fullCells_minusOne) ) {
iZ--;
}
// clout << "found optimal iZ = " << iZ << std::endl;
extend_child[2] = iZ - localPos_child + 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
globPos_child[2] += extend_child[2]*deltaR;
localPos_child += extend_child[2] + 1;
// clout << "added child " << iChild << " of " << p << std::endl;
break;
}
}
}
extend_child[2] = zN - localPos_child + p - 1;
Cuboid3D child(globPos_child[0], globPos_child[1], globPos_child[2], deltaR, extend_child[0], extend_child[1], extend_child[2]);
_cuboids.push_back(child);
// clout << "added last child of " << p << std::endl;
}
}
template
void CuboidGeometry3D::swap(CuboidGeometry3D& rhs)
{
std::swap(this->_cuboids, rhs._cuboids);
std::swap(this->_motherCuboid, rhs._motherCuboid);
std::swap(this->_periodicityOn[0], rhs._periodicityOn[0]);
std::swap(this->_periodicityOn[1], rhs._periodicityOn[1]);
std::swap(this->_periodicityOn[2], rhs._periodicityOn[2]);
std::swap(this->clout, rhs.clout);
}
template
void CuboidGeometry3D::swapCuboids(std::vector< Cuboid3D >& cuboids)
{
_cuboids.swap(cuboids);
}
template
void CuboidGeometry3D::replaceCuboids(std::vector< Cuboid3D >& cuboids)
{
this->_cuboids.clear();
for ( unsigned iC = 0; iC < cuboids.size(); iC++) {
add(cuboids[iC]);
}
}
template
void CuboidGeometry3D::setWeights(IndicatorF3D& indicatorF)
{
//IndicatorIdentity3D tmpIndicatorF(indicatorF);
int nC = getNc();
int latticeR[4];
T physR[3];
for ( int iC = nC - 1; iC >= 0; iC--) { // assemble neighbourhood information
latticeR[0] = iC;
int xN = get(iC).getNx();
int yN = get(iC).getNy();
int zN = get(iC).getNz();
size_t fullCells = 0;
for (int iX = 0; iX < xN; iX++) {
for (int iY = 0; iY < yN; iY++) {
for (int iZ = 0; iZ < zN; iZ++) {
latticeR[1] = iX;
latticeR[2] = iY;
latticeR[3] = iZ;
getPhysR(physR,latticeR);
bool inside[1];
indicatorF(inside,physR);
if (inside[0]) {
fullCells++;
}
}
}
}
if (fullCells > 0) {
get(iC).setWeight(fullCells);
}
else {
remove(iC);
}
}
}
template
size_t CuboidGeometry3D::getNblock() const
{
return 1 // _periodicityOn
+ _motherCuboid.getNblock() // _motherCuboid
+ _cuboids.size() > 0 ? 1 + _cuboids.size() * _cuboids[0].getNblock() : 0; // _cuboids;
}
template
size_t CuboidGeometry3D::getSerializableSize() const
{
return 3 * sizeof(bool) // _periodicityOn
+ _motherCuboid.getSerializableSize() // _motherCuboid
+ (_cuboids.size() > 0 ?
sizeof(size_t) + _cuboids.size() * _cuboids[0].getSerializableSize() :
0); // _cuboids;
}
template
bool* CuboidGeometry3D::getBlock(std::size_t iBlock, std::size_t& sizeBlock, bool loadingMode)
{
std::size_t currentBlock = 0;
size_t sizeBufferIndex = 0;
bool* dataPtr = nullptr;
registerVar (iBlock, sizeBlock, currentBlock, dataPtr, _periodicityOn[0], 3);
registerSerializableOfConstSize (iBlock, sizeBlock, currentBlock, dataPtr, _motherCuboid, loadingMode);
registerStdVectorOfSerializablesOfConstSize (iBlock, sizeBlock, currentBlock, sizeBufferIndex, dataPtr,
_cuboids, loadingMode);
return dataPtr;
}
template
void CuboidGeometry3D::print() const
{
clout << "---Cuboid Stucture Statistics---" << std::endl;
clout << " Number of Cuboids: " << "\t" << getNc() << std::endl;
clout << " Delta (min): " << "\t" << "\t" << getMinDeltaR() << std::endl;
clout << " (max): " << "\t" << "\t" << getMaxDeltaR() << std::endl;
clout << " Ratio (min): " << "\t" << "\t" << getMinRatio() << std::endl;
clout << " (max): " << "\t" << "\t" << getMaxRatio() << std::endl;
clout << " Nodes (min): " << "\t" << "\t" << getMinLatticeVolume() << std::endl;
clout << " (max): " << "\t" << "\t" << getMaxLatticeVolume() << std::endl;
clout << " Weight (min): " << "\t" << "\t" << getMinLatticeWeight() << std::endl;
clout << " (max): " << "\t" << "\t" << getMaxLatticeWeight() << std::endl;
clout << "--------------------------------" << std::endl;
}
template
void CuboidGeometry3D::printExtended()
{
clout << "Mothercuboid :" << std::endl;
getMotherCuboid().print();
for (int iC = 0; iC < getNc(); iC++) {
clout << "Cuboid #" << iC << ": " << std::endl;
get(iC).print();
}
}
template
void CuboidGeometry3D::writeToExistingFile(std::string completeFileName, LoadBalancer& loadBalancer)
{
std::ofstream fout;
if ( singleton::mpi().isMainProcessor() ) {
// Open File
fout.open(completeFileName.c_str(), std::ios::app);
if (!fout) {
clout << "Error: could not open " << completeFileName << std::endl;
}
// --- Preamble --- //
fout << "\n";
// TODO: Move Cuboid XML Serialization to Cuboid3D class
for (int iC = 0; iC < getNc(); ++iC) {
fout << "\n";
}
fout << "\n";
// Close File
fout.close();
}
}
template
void CuboidGeometry3D::writeToFile(std::string fileName, LoadBalancer& loadBalancer)
{
std::string fname = singleton::directories().getLogOutDir() + fileName + ".xml";
std::ofstream fout;
if (singleton::mpi().isMainProcessor()) {
fout.open(fname.c_str(), std::ios::trunc);
fout << "\n";
fout << "\n";
fout.close();
fout.clear();
}
writeToExistingFile(fname, loadBalancer);
if (singleton::mpi().isMainProcessor()) {
fout.open(fname.c_str(), std::ios::app);
fout << "\n";
fout.close();
}
}
// TODO: Move this method to Cuboid3D class
/// Helper Function to create cuboid parameters for XML tag
template
std::string CuboidGeometry3D::_cuboidParameters(Cuboid3D const& cub)
{
std::stringstream ss;
ss.flags(std::ios::scientific);
ss.precision (std::numeric_limits::digits10 + 1);
ss << " extent=\"";
for (int i = 0; i<3; i++) {
ss << cub.getExtend()[i] << " ";
}
ss << "\" origin=\"";
for (int i = 0; i<3; i++) {
ss << cub.getOrigin()[i] << " ";
}
ss << "\" deltaR=\"" << cub.getDeltaR();
ss << "\" weight=\"" << cub.getWeightValue();
ss << "\" refinementLevel=\"" << cub.getRefinementLevel() << "\"";
return ss.str();
}
} // namespace olb
#endif