From c917016e8566931d0d70a2fce23c5bf4a0323f20 Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Fri, 16 Oct 2020 09:06:05 +0200 Subject: [PATCH 01/83] Adaptive grid refinement for LBM and MESA-PD --- .../refinement/CurlBasedLevelDetermination.h | 178 +++++++++++++++++ src/lbm/refinement/all.h | 1 + src/lbm_mesapd_coupling/amr/BlockInfo.h | 87 ++++++++ src/lbm_mesapd_coupling/amr/InfoCollection.h | 185 ++++++++++++++++++ .../ParticlePresenceLevelDetermination.h | 101 ++++++++++ .../utility/SubCyclingManager.cpp | 93 +++++++++ .../utility/SubCyclingManager.h | 83 ++++++++ 7 files changed, 728 insertions(+) create mode 100644 src/lbm/refinement/CurlBasedLevelDetermination.h create mode 100644 src/lbm_mesapd_coupling/amr/BlockInfo.h create mode 100644 src/lbm_mesapd_coupling/amr/InfoCollection.h create mode 100644 src/lbm_mesapd_coupling/amr/level_determination/ParticlePresenceLevelDetermination.h create mode 100644 src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp create mode 100644 src/lbm_mesapd_coupling/utility/SubCyclingManager.h diff --git a/src/lbm/refinement/CurlBasedLevelDetermination.h b/src/lbm/refinement/CurlBasedLevelDetermination.h new file mode 100644 index 000000000..d384449fb --- /dev/null +++ b/src/lbm/refinement/CurlBasedLevelDetermination.h @@ -0,0 +1,178 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file VorticityBasedLevelDetermination.h +//! \ingroup lbm +//! \author Florian Schornbaum <florian.schornbaum@fau.de> +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +//! \author Lukas Werner <lks.werner@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "blockforest/BlockForest.h" +#include "core/math/Vector3.h" +#include "domain_decomposition/BlockDataID.h" +#include "field/GhostLayerField.h" + +#include <vector> + +namespace walberla { +namespace lbm { +namespace refinement { + + +/*!\brief Level determination for refinement check based on local curl + * + * If (scaled) vorticity magnitude is below lowerLimit in all cells of a block, that block could be coarsened. + * If the (scaled) vorticity value is above the upperLimit for at least one cell, that block gets marked for refinement. + * Else, the block remains on the current level. + * + * The scaling originates from neglecting the actual mesh size on the block to obtain different vorticity values for + * different mesh sizes. + * + * Parametes upperLimit corresponds to sigma_c, coarsenFactor to c, lowerLimit to c*sigma_c, lengthScaleWeight to r. + */ +template< typename Filter_T > +class CurlBasedLevelDetermination // used as a 'BlockForest::RefreshMinTargetLevelDeterminationFunction' +{ + +public: + + typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; + + CurlBasedLevelDetermination(const ConstBlockDataID & fieldID, const StructuredBlockForest & structuredBlockForest, + const Filter_T & filter, const uint_t maxLevel, + const real_t upperLimit, const real_t lowerLimit, const real_t lengthScaleWeight = real_t(2)) : + fieldID_(fieldID), structuredBlockForest_(structuredBlockForest), filter_(filter), maxLevel_(maxLevel), + upperLimitSqr_(upperLimit*upperLimit), lowerLimitSqr_(lowerLimit*lowerLimit), + lengthScaleWeight_(lengthScaleWeight) + { + WALBERLA_CHECK_FLOAT_UNEQUAL(lengthScaleWeight_, real_t(0)); // else std::pow(x, y/0) is calculated further below + } + + void operator()( std::vector< std::pair< const Block *, uint_t > > & minTargetLevels, + std::vector< const Block * > & blocksAlreadyMarkedForRefinement, + const BlockForest & forest ); + +private: + + ConstBlockDataID fieldID_; + const StructuredBlockForest & structuredBlockForest_; + + Filter_T filter_; + + uint_t maxLevel_; + + real_t upperLimitSqr_; + real_t lowerLimitSqr_; + + real_t lengthScaleWeight_; +}; + +template< typename Filter_T > +void CurlBasedLevelDetermination< Filter_T >::operator()( std::vector< std::pair< const Block *, + uint_t > > & minTargetLevels, std::vector< const Block * > &, const BlockForest & forest) { + + for(auto & minTargetLevel : minTargetLevels) { + const Block * const block = minTargetLevel.first; + const VectorField_T * u = block->template getData< VectorField_T >(fieldID_); + + if(u == nullptr) { + minTargetLevel.second = uint_t(0); + continue; + } + + WALBERLA_ASSERT_GREATER_EQUAL(u->nrOfGhostLayers(), uint_t(1)); + + CellInterval interval = u->xyzSize(); + Cell expand(cell_idx_c(-1), cell_idx_c(-1), cell_idx_c(-1)); + interval.expand(expand); + + const auto one = cell_idx_t(1); + + const real_t dx = structuredBlockForest_.dx(forest.getLevel(*block)); + const real_t dy = structuredBlockForest_.dy(forest.getLevel(*block)); + const real_t dz = structuredBlockForest_.dz(forest.getLevel(*block)); + + const auto halfInvDx = real_t(0.5) * real_t(1) / dx; + const auto halfInvDy = real_t(0.5) * real_t(1) / dy; + const auto halfInvDz = real_t(0.5) * real_t(1) / dz; + + bool refine = false; + bool coarsen = true; + + filter_(*block); + + const cell_idx_t xSize = cell_idx_c(interval.xSize()); + const cell_idx_t ySize = cell_idx_c(interval.ySize()); + const cell_idx_t zSize = cell_idx_c(interval.zSize()); + + const real_t lengthScale = std::cbrt(dx*dy*dz); + const real_t weightedLengthScale = std::pow(lengthScale, (lengthScaleWeight_+1)/lengthScaleWeight_); + const real_t weightedLengthScaleSqr = weightedLengthScale*weightedLengthScale; + + for (auto z = cell_idx_t(0); z < zSize; ++z) { + for (auto y = cell_idx_t(0); y < ySize; ++y) { + for (auto x = cell_idx_t(0); x < xSize; ++x) { + if (filter_(x,y,z) && filter_(x+one,y,z) && filter_(x-one,y,z) && filter_(x,y+one,z) && filter_(x,y-one,z) + && filter_(x,y,z+one) && filter_(x,y,z-one)) { + const Vector3< real_t > xa = u->get(x+one,y,z); + const Vector3< real_t > xb = u->get(x-one,y,z); + const Vector3< real_t > ya = u->get(x,y+one,z); + const Vector3< real_t > yb = u->get(x,y-one,z); + const Vector3< real_t > za = u->get(x,y,z+one); + const Vector3< real_t > zb = u->get(x,y,z-one); + + const real_t duzdy = halfInvDy * (ya[2] - yb[2]); + const real_t duydz = halfInvDz * (za[1] - zb[1]); + const real_t duxdz = halfInvDz * (za[0] - zb[0]); + const real_t duzdx = halfInvDx * (xa[2] - xb[2]); + const real_t duydx = halfInvDx * (xa[1] - xb[1]); + const real_t duxdy = halfInvDy * (ya[0] - yb[0]); + + const Vector3< real_t > curl( duzdy - duydz, duxdz - duzdx, duydx - duxdy ); + const auto curlSqr = curl.sqrLength(); + + const auto curlSensorSqr = curlSqr * weightedLengthScaleSqr; + + if (curlSensorSqr > lowerLimitSqr_) { + // curl is not small enough to coarsen, i.e. stay at least on the current level + coarsen = false; + if (curlSensorSqr > upperLimitSqr_) { + // curl is big enough for refinement + refine = true; + } + } + } + } + } + } + + if (refine && block->getLevel() < maxLevel_) { + WALBERLA_ASSERT(!coarsen); + minTargetLevel.second = block->getLevel() + uint_t(1); + } + if (coarsen && block->getLevel() > uint_t(0)) { + WALBERLA_ASSERT(!refine); + minTargetLevel.second = block->getLevel() - uint_t(1); + } + } +} + +} // namespace refinement +} // namespace lbm +} // namespace walberla diff --git a/src/lbm/refinement/all.h b/src/lbm/refinement/all.h index a63a1ba38..e55e8edb1 100644 --- a/src/lbm/refinement/all.h +++ b/src/lbm/refinement/all.h @@ -30,3 +30,4 @@ #include "TimeStepPdfPackInfo.h" #include "TimeTracker.h" #include "VorticityBasedLevelDetermination.h" +#include "CurlBasedLevelDetermination.h" \ No newline at end of file diff --git a/src/lbm_mesapd_coupling/amr/BlockInfo.h b/src/lbm_mesapd_coupling/amr/BlockInfo.h new file mode 100644 index 000000000..6b3e0706a --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/BlockInfo.h @@ -0,0 +1,87 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BlockInfo.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +//! \author Lukas Werner <lks.werner@fau.de> +//! // +//====================================================================================================================== + +#pragma once + +#include <core/mpi/RecvBuffer.h> +#include <core/mpi/SendBuffer.h> + +#include <ostream> + +namespace walberla { +namespace lbm_mesapd_coupling { + +struct BlockInfo { + // lbm quantities + uint_t numberOfCells; + uint_t numberOfFluidCells; + uint_t numberOfNearBoundaryCells; + // pe quantities + uint_t numberOfLocalParticles; + uint_t numberOfShadowParticles; + uint_t numberOfContacts; + // coupling quantities + uint_t numberOfMESAPDSubCycles; + + BlockInfo() + : numberOfCells(0), numberOfFluidCells(0), numberOfNearBoundaryCells(0), + numberOfLocalParticles(0), numberOfShadowParticles(0), numberOfContacts(0), numberOfMESAPDSubCycles(0) {} + + BlockInfo(const uint_t numCells, const uint_t numFluidCells, const uint_t numNearBoundaryCells, + const uint_t numLocalBodies, const uint_t numShadowParticles, const uint_t numContacts, + const uint_t numPeSubCycles) + : numberOfCells(numCells), numberOfFluidCells(numFluidCells), numberOfNearBoundaryCells(numNearBoundaryCells), + numberOfLocalParticles(numLocalBodies), numberOfShadowParticles(numShadowParticles), numberOfContacts(numContacts), numberOfMESAPDSubCycles(numPeSubCycles) {} +}; + + +inline +std::ostream& operator<<( std::ostream& os, const BlockInfo& bi ) +{ + os << bi.numberOfCells << " / " << bi.numberOfFluidCells << " / " << bi.numberOfNearBoundaryCells << " / " + << bi.numberOfLocalParticles << " / "<< bi.numberOfShadowParticles << " / " << bi.numberOfContacts << " / " + << bi.numberOfMESAPDSubCycles; + return os; +} + +template< typename T, // Element type of SendBuffer + typename G> // Growth policy of SendBuffer +mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const BlockInfo& info ) +{ + buf.addDebugMarker( "pca" ); + buf << info.numberOfCells << info.numberOfFluidCells << info.numberOfNearBoundaryCells + << info.numberOfLocalParticles << info.numberOfShadowParticles << info.numberOfContacts + << info.numberOfMESAPDSubCycles; + return buf; +} + +template< typename T> // Element type of SendBuffer +mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, BlockInfo& info ) +{ + buf.readDebugMarker( "pca" ); + buf >> info.numberOfCells >> info.numberOfFluidCells >> info.numberOfNearBoundaryCells + >> info.numberOfLocalParticles >> info.numberOfShadowParticles >> info.numberOfContacts + >> info.numberOfMESAPDSubCycles; + return buf; +} + +} // namespace lbm_mesapd_coupling +} // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/InfoCollection.h b/src/lbm_mesapd_coupling/amr/InfoCollection.h new file mode 100644 index 000000000..13f8682d5 --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/InfoCollection.h @@ -0,0 +1,185 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InfoCollection.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "BlockInfo.h" + +#include "blockforest/BlockForest.h" +#include "blockforest/BlockID.h" +#include "core/mpi/BufferSystem.h" + +#include <mesa_pd/data/ParticleStorage.h> + +#include <map> + +namespace walberla { +namespace lbm_mesapd_coupling { + +typedef std::map<blockforest::BlockID, BlockInfo> InfoCollection; +typedef std::pair<blockforest::BlockID, BlockInfo> InfoCollectionPair; + +template <typename BoundaryHandling_T, typename ParticleAccessor_T> +void createWithNeighborhood(BlockForest& bf, const BlockDataID boundaryHandlingID, + const ParticleAccessor_T& accessor, const uint_t numberOfMESAPDSubCycles, + InfoCollection& ic ) { + ic.clear(); + + mpi::BufferSystem bs( MPIManager::instance()->comm(), 856 ); + + for (auto blockIt = bf.begin(); blockIt != bf.end(); ++blockIt) + { + auto * block = static_cast<blockforest::Block*> (&(*blockIt)); + + // evaluate LBM quantities + BoundaryHandling_T * boundaryHandling = blockIt->getData< BoundaryHandling_T >( boundaryHandlingID ); + auto xyzSize = boundaryHandling->getFlagField()->xyzSize(); + const uint_t numCells = xyzSize.numCells(); + uint_t numFluidCells(0), numNearBoundaryCells(0); + for( auto cellIt = xyzSize.begin(); cellIt != xyzSize.end(); ++cellIt) + { + if( boundaryHandling->isDomain(*cellIt) ) + { + ++numFluidCells; + } + if( boundaryHandling->isNearBoundary(*cellIt)) + { + ++numNearBoundaryCells; + } + } + + // evaluate MESAPD quantities + // count block local and (possible) shadow particles here + uint_t numLocalParticles = 0, numShadowParticles = 0; + for (size_t idx = 0; idx < accessor.size(); ++idx) { + if (block->getAABB().contains(accessor.getPosition(idx))) { + // a particle within a block on the current process cannot be a ghost particle + WALBERLA_ASSERT(!mesa_pd::data::particle_flags::isSet(accessor.getFlags(idx), mesa_pd::data::particle_flags::GHOST)); + numLocalParticles++; + } else if (block->getAABB().sqDistance(accessor.getPosition(idx)) < accessor.getInteractionRadius(idx)*accessor.getInteractionRadius(idx)) { + numShadowParticles++; + } + } + + // count contacts here + const uint_t numContacts = 0; + + BlockInfo blockInfo(numCells, numFluidCells, numNearBoundaryCells, numLocalParticles, numShadowParticles, numContacts, numberOfMESAPDSubCycles); + InfoCollectionPair infoCollectionEntry(block->getId(), blockInfo); + + ic.insert( infoCollectionEntry ); + + for( auto nb = uint_t(0); nb < block->getNeighborhoodSize(); ++nb ) + { + bs.sendBuffer( block->getNeighborProcess(nb) ) << infoCollectionEntry; + } + + //note: is it necessary to add child blocks already into the info collection? + // here, we still have full geometrical information and can probably determine number of fluid and near boundary cells more easily + // however, the interesting (and most costly) blocks are never refined and thus their child infos is never needed + // see pe/amr/InfoCollection.cpp for an example + + } + + // size of buffer is unknown and changes with each send + bs.setReceiverInfoFromSendBufferState(false, true); + bs.sendAll(); + + for( auto recvIt = bs.begin(); recvIt != bs.end(); ++recvIt ) + { + while( !recvIt.buffer().isEmpty() ) + { + InfoCollectionPair val; + recvIt.buffer() >> val; + ic.insert(val); + } + } +} + +void getBlockInfoFromInfoCollection( const PhantomBlock * block, const shared_ptr<InfoCollection>& ic, + BlockInfo & blockInfo ) +{ + WALBERLA_ASSERT_NOT_NULLPTR(block); + + if (block->sourceBlockIsLarger()) + { + // block is a result of refinement -> BlockInfo object only available for the father block + // there should be no particles on the block (otherwise it would not have been refined) + // and refinement in LBM does not change the number of cells + // we assume that the number of fluid and near boundary cells also stays the same + // (ATTENTION: not true for blocks intersecting with a boundary!) + // -> we can use the information of the father block for weight assignment + + auto infoIt = ic->find( block->getId().getFatherId() ); + WALBERLA_CHECK_UNEQUAL( infoIt, ic->end(), "Father block with ID " << block->getId().getFatherId() << " not found in info collection!" ); + + // check the above mentioned assumptions + WALBERLA_ASSERT_EQUAL(infoIt->second.numberOfLocalParticles, uint_t(0)); + WALBERLA_ASSERT_EQUAL(infoIt->second.numberOfContacts, uint_t(0)); + + blockInfo = infoIt->second; + } + else if (block->sourceBlockHasTheSameSize()) + { + auto infoIt = ic->find( block->getId() ); + WALBERLA_CHECK_UNEQUAL( infoIt, ic->end(), "Block with ID " << block->getId() << " not found in info collection!" ); + blockInfo = infoIt->second; + } + else + { + // source block of block is smaller + + // block is a result of coarsening -> BlockInfo object is available on all 8 child blocks + // there should be no particles on the block (otherwise it would not have been coarsened) + // and refinement in LBM does not change the number of cells + // we assume that the number of fluid and near boundary cells will be the average of all 8 child blocks + // -> we can use the information of the child blocks for weight assignment + + blockforest::BlockID childIdForInit(block->getId(), 0); + auto childForInitIt = ic->find( childIdForInit ); + WALBERLA_CHECK_UNEQUAL( childForInitIt, ic->end(), "Child block with ID " << childIdForInit << " not found in info collection!" ); + BlockInfo combinedInfo = childForInitIt->second; + uint_t numFluidCells(0); + uint_t numNearBoundaryCells(0); + for (uint_t child = 0; child < 8; ++child) + { + blockforest::BlockID childId(block->getId(), child); + auto childIt = ic->find( childId ); + WALBERLA_CHECK_UNEQUAL( childIt, ic->end(), "Child block with ID " << childId << " not found in info collection!" ); + numFluidCells += childIt->second.numberOfFluidCells; + numNearBoundaryCells += childIt->second.numberOfNearBoundaryCells; + + // check above mentioned assumptions + WALBERLA_ASSERT_EQUAL(childIt->second.numberOfLocalParticles, uint_t(0)); + WALBERLA_ASSERT_EQUAL(childIt->second.numberOfContacts, uint_t(0)); + } + // total number of cells remains unchanged + combinedInfo.numberOfFluidCells = uint_c(numFluidCells / uint_t(8)); //average + combinedInfo.numberOfNearBoundaryCells = uint_c( numNearBoundaryCells / uint_t(8) ); //average + combinedInfo.numberOfLocalParticles = uint_t(0); + combinedInfo.numberOfContacts = uint_t(0); //sum + // number of pe sub cycles stays the same + + blockInfo = combinedInfo; + } +} + +} // namespace lbm_mesapd_coupling +} // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/level_determination/ParticlePresenceLevelDetermination.h b/src/lbm_mesapd_coupling/amr/level_determination/ParticlePresenceLevelDetermination.h new file mode 100644 index 000000000..9ad15259e --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/level_determination/ParticlePresenceLevelDetermination.h @@ -0,0 +1,101 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file ParticlePresenceLevelDetermination.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "blockforest/BlockForest.h" +#include "lbm_mesapd_coupling/amr/InfoCollection.h" + +namespace walberla { +namespace lbm_mesapd_coupling { + +/* + * Class to determine the minimum level a block can be. + * For coupled LBM-PE simulations the following rules apply: + * - a moving particle will always remain on the finest block + * - a moving particle is not allowed to extend into an area with a coarser block + * - if no moving particle is present, the level can be as coarse as possible (restricted by the 2:1 rule) + * Therefore, if a particle, local or remote (due to particles that are larger than a block), is present on any of the + * neighboring blocks of a certain block, this block's target level is the finest level. + * This, together with a refinement checking frequency that depends on the maximum translational particle velocity, + * ensures the above given requirements. + */ +class ParticlePresenceLevelDetermination +{ +public: + + ParticlePresenceLevelDetermination( const shared_ptr<lbm_mesapd_coupling::InfoCollection> & infoCollection, uint_t finestLevel) : + infoCollection_( infoCollection ), finestLevel_( finestLevel) + {} + + void operator()( std::vector< std::pair< const Block *, uint_t > > & minTargetLevels, + std::vector< const Block * > &, const BlockForest & /*forest*/ ) { + for (auto &minTargetLevel : minTargetLevels) { + uint_t currentLevelOfBlock = minTargetLevel.first->getLevel(); + + const uint_t numberOfParticlesInDirectNeighborhood = getNumberOfLocalAndShadowParticlesInNeighborhood(minTargetLevel.first); + + uint_t targetLevelOfBlock = currentLevelOfBlock; //keep everything as it is + if ( numberOfParticlesInDirectNeighborhood > uint_t(0) ) + { + // set block to finest level if there are particles nearby + targetLevelOfBlock = finestLevel_; + } + else + { + // block could coarsen since there are no particles nearby + if( currentLevelOfBlock > uint_t(0) ) + targetLevelOfBlock = currentLevelOfBlock - uint_t(1); + } + + WALBERLA_CHECK_LESS_EQUAL(std::abs(int_c(targetLevelOfBlock) - int_c(currentLevelOfBlock)), uint_t(1), "Only level difference of maximum 1 allowed!"); + minTargetLevel.second = targetLevelOfBlock; + } + } + +private: + + uint_t getNumberOfLocalAndShadowParticlesInNeighborhood(const Block * block) { + auto numParticles = uint_t(0); + + // add particles of current block + const auto infoIt = infoCollection_->find(block->getId()); + WALBERLA_CHECK_UNEQUAL(infoIt, infoCollection_->end(), "Block with ID " << block->getId() << " not found in info collection!"); + + numParticles += infoIt->second.numberOfLocalParticles + infoIt->second.numberOfShadowParticles; + + // add particles of all neighboring blocks + for(uint_t i = 0; i < block->getNeighborhoodSize(); ++i) + { + const BlockID &neighborBlockID = block->getNeighborId(i); + const auto infoItNeighbor = infoCollection_->find(neighborBlockID); + WALBERLA_CHECK_UNEQUAL(infoItNeighbor, infoCollection_->end(), "Neighbor block with ID " << neighborBlockID << " not found in info collection!"); + + numParticles += infoItNeighbor->second.numberOfLocalParticles + infoItNeighbor->second.numberOfShadowParticles; + } + return numParticles; + } + + shared_ptr<lbm_mesapd_coupling::InfoCollection> infoCollection_; + uint_t finestLevel_; +}; + +} // namespace lbm_mesapd_coupling +} // namespace walberla diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp b/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp new file mode 100644 index 000000000..ca5c531d3 --- /dev/null +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp @@ -0,0 +1,93 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SubCyclingManager.cpp +//! \author Lukas Werner <lks.werner@fau.de> +// +//====================================================================================================================== + + +#include "SubCyclingManager.h" + +namespace walberla { +namespace lbm_mesapd_coupling { + +SubCyclingManager::SubCyclingManager(size_t numberOfSubCycles, shared_ptr<WcTimingPool> timingPool) + : numberOfSubCycles_(numberOfSubCycles), timingPool_(timingPool), currentTimeStep_(0) {} + +void SubCyclingManager::operator()() { + executeBeforeFunctions(); + for (size_t s = 0; s < numberOfSubCycles_; ++s) { + executeDuringFunctions(); + } + executeAfterFunctions(); + ++currentTimeStep_; +} + +SubCyclingManager::FuncHandle +SubCyclingManager::addFuncBeforeSubCycles(const VoidVoidFunc &f, const std::string &identifier) { + IdentifiedFunc idFunc(identifier, f); + beforeFunctions_.emplace_back(idFunc); + return beforeFunctions_.size() - 1; +} + +SubCyclingManager::FuncHandle +SubCyclingManager::addFuncDuringSubCycles(const VoidVoidFunc &f, const std::string &identifier) { + IdentifiedFunc idFunc(identifier, f); + duringFunctions_.emplace_back(idFunc); + return duringFunctions_.size() - 1; +} + +SubCyclingManager::FuncHandle +SubCyclingManager::addFuncAfterSubCycles(const VoidVoidFunc &f, const std::string &identifier) { + IdentifiedFunc idFunc(identifier, f); + afterFunctions_.emplace_back(idFunc); + return afterFunctions_.size() - 1; +} + +inline void SubCyclingManager::executeBeforeFunctions() { + executeFunctions(beforeFunctions_); +} + +inline void SubCyclingManager::executeDuringFunctions() { + executeFunctions(duringFunctions_); +} + +inline void SubCyclingManager::executeAfterFunctions() { + executeFunctions(afterFunctions_); +} + +inline void SubCyclingManager::executeFunctions(std::vector<IdentifiedFunc>& functions) { + for (const auto &f: functions) { + startTiming(f.first); + f.second(); + stopTiming(f.first); + } +} + +inline void SubCyclingManager::startTiming(const std::string & name){ + if (timingPool_ != nullptr) { + (*timingPool_)[name].start(); + } +} + +inline void SubCyclingManager::stopTiming(const std::string & name){ + if (timingPool_ != nullptr) { + (*timingPool_)[name].end(); + } +} + +} +} \ No newline at end of file diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h new file mode 100644 index 000000000..cd748446b --- /dev/null +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h @@ -0,0 +1,83 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SubCyclingManager.h +//! \author Lukas Werner <lks.werner@fau.de> +// +//====================================================================================================================== + +#include "core/DataTypes.h" +#include "core/logging/Logging.h" +#include "core/timing/TimingPool.h" + +namespace walberla { +namespace lbm_mesapd_coupling { + +// loosely based on Timeloop class + +class SubCyclingManager { +public: + typedef std::function<void ()> VoidVoidFunc; + + /*! \name Construction & Destruction */ + //@{ + explicit SubCyclingManager(size_t numberOfSubCycles, shared_ptr<WcTimingPool> timingPool = nullptr); + + virtual ~SubCyclingManager() {} + //@} + + /*! \name Registration Functions */ + //@{ + typedef size_t FuncHandle; + + FuncHandle addFuncBeforeSubCycles(const VoidVoidFunc &f, const std::string &identifier = "Other"); + FuncHandle addFuncDuringSubCycles(const VoidVoidFunc &f, const std::string &identifier = "Other"); + FuncHandle addFuncAfterSubCycles(const VoidVoidFunc &f, const std::string &identifier = "Other"); + //@} + + /*! \name Execution Functions */ + //@{ + void operator()(); + //@} + + /*! \name Bookkeeping Functions */ + //@{ + uint_t getCurrentTimeStep() const { return currentTimeStep_; } + void setCurrentTimeStep(uint_t timestep) { currentTimeStep_ = timestep; } + //@} + +private: + typedef std::pair<std::string, VoidVoidFunc> IdentifiedFunc; + + inline void executeBeforeFunctions(); + inline void executeDuringFunctions(); + inline void executeAfterFunctions(); + + inline void executeFunctions(std::vector<IdentifiedFunc>& functions); + + inline void startTiming(const std::string & name); + inline void stopTiming(const std::string & name); + + size_t numberOfSubCycles_; + shared_ptr<WcTimingPool> timingPool_; + uint_t currentTimeStep_; + + std::vector<IdentifiedFunc> beforeFunctions_; + std::vector<IdentifiedFunc> duringFunctions_; + std::vector<IdentifiedFunc> afterFunctions_; +}; + +} +} \ No newline at end of file -- GitLab From 7340d92ac310afd6c03b2a43f8717d9bf96ef897 Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Tue, 27 Oct 2020 15:22:00 +0100 Subject: [PATCH 02/83] Improved description of SubCyclingManager --- src/lbm_mesapd_coupling/utility/SubCyclingManager.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h index cd748446b..d1f198916 100644 --- a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h @@ -25,7 +25,12 @@ namespace walberla { namespace lbm_mesapd_coupling { -// loosely based on Timeloop class +/*! \brief Handles the execution of subcycles in a timeloop to allow for finer grained time steps than the LBM ones. +* +* Supports registration of functions that are run before, during or after a subcycle. +* The SubCyclingManager itself has to be added to a parent (LBM) time loop, and will execute the functions registered +* for execution during the subcycling procedure numberOfSubCycles times. +*/ class SubCyclingManager { public: -- GitLab From fdb842c421a35627bcf52facdaca8b9c747b8ae3 Mon Sep 17 00:00:00 2001 From: Lukas Werner <lks.werner@fau.de> Date: Thu, 29 Oct 2020 15:22:36 +0100 Subject: [PATCH 03/83] Use std::move in constructor of SubCyclingManager --- src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp b/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp index ca5c531d3..c9e09bed4 100644 --- a/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.cpp @@ -21,11 +21,13 @@ #include "SubCyclingManager.h" +#include <utility> + namespace walberla { namespace lbm_mesapd_coupling { SubCyclingManager::SubCyclingManager(size_t numberOfSubCycles, shared_ptr<WcTimingPool> timingPool) - : numberOfSubCycles_(numberOfSubCycles), timingPool_(timingPool), currentTimeStep_(0) {} + : numberOfSubCycles_(numberOfSubCycles), timingPool_(std::move(timingPool)), currentTimeStep_(0) {} void SubCyclingManager::operator()() { executeBeforeFunctions(); -- GitLab From 4acadd45d7e499c9014e541a418e8a4c56b667fa Mon Sep 17 00:00:00 2001 From: Dominik Thoennes <dominik.thoennes@fau.de> Date: Fri, 30 Oct 2020 19:04:34 +0100 Subject: [PATCH 04/83] Add debug STL build in CI --- .gitlab-ci.yml | 31 ++++++++++++++++++++++++------ CMakeLists.txt | 1 + src/waLBerlaDefinitions.in.h | 2 ++ tests/core/CMakeLists.txt | 4 ++++ tests/core/DebugSTLTest.cpp | 37 ++++++++++++++++++++++++++++++++++++ 5 files changed, 69 insertions(+), 6 deletions(-) create mode 100644 tests/core/DebugSTLTest.cpp diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1cda00fce..5c7bc78b1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -33,7 +33,24 @@ stages: - mkdir $CI_PROJECT_DIR/build - cd $CI_PROJECT_DIR/build - if dpkg --compare-versions `ompi_info | head -2 | tail -1 | sed 's/[^0-9.]*\([0-9.]*\).*/\1/'` ge 1.10; then export MPIEXEC_PREFLAGS="--allow-run-as-root" ; fi - - cmake .. -DWALBERLA_BUFFER_DEBUG=$WALBERLA_BUFFER_DEBUG -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DMPIEXEC_PREFLAGS=$MPIEXEC_PREFLAGS -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -DWALBERLA_BUILD_WITH_METIS=$WALBERLA_BUILD_WITH_METIS -DWALBERLA_BUILD_WITH_PARMETIS=$WALBERLA_BUILD_WITH_PARMETIS -DWALBERLA_ENABLE_GUI=$WALBERLA_ENABLE_GUI -DWALBERLA_BUILD_WITH_CODEGEN=$WALBERLA_BUILD_WITH_CODEGEN + - cmake .. + -DWALBERLA_BUFFER_DEBUG=$WALBERLA_BUFFER_DEBUG + -DWALBERLA_BUILD_TESTS=ON + -DWALBERLA_BUILD_BENCHMARKS=ON + -DWALBERLA_BUILD_TUTORIALS=ON + -DWALBERLA_BUILD_TOOLS=ON + -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI + -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA + -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON + -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP + -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DMPIEXEC_PREFLAGS=$MPIEXEC_PREFLAGS + -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY + -DWARNING_ERROR=ON + -DWALBERLA_BUILD_WITH_METIS=$WALBERLA_BUILD_WITH_METIS + -DWALBERLA_BUILD_WITH_PARMETIS=$WALBERLA_BUILD_WITH_PARMETIS + -DWALBERLA_ENABLE_GUI=$WALBERLA_ENABLE_GUI + -DWALBERLA_BUILD_WITH_CODEGEN=$WALBERLA_BUILD_WITH_CODEGEN + -DWALBERLA_STL_BOUNDS_CHECKS=$WALBERLA_STL_BOUNDS_CHECKS - cmake . -LAH - make -j $NUM_BUILD_CORES -l $NUM_CORES - ctest -LE $CTEST_EXCLUDE_LABELS -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES @@ -1878,9 +1895,9 @@ gcc_8_hybrid_dbg_noboost: ## ## ############################################################################### -gcc_9_stl_debug: +gcc_10_stl_debug: extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/gcc:9 + image: i10git.cs.fau.de:5005/walberla/buildenvs/gcc-debug-stl:10 before_script: - rm -rf /opt/boost /usr/include/boost variables: @@ -1896,11 +1913,13 @@ gcc_9_stl_debug: WALBERLA_BUILD_WITH_METIS: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_PYTHON: "OFF" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS + WALBERLA_STL_BOUNDS_CHECKS: "ON" tags: - docker + stage: merge_request + when: manual + needs: [ ] + allow_failure: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 1abce0760..f14628bdb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -373,6 +373,7 @@ endif ( ) if( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL OR WALBERLA_CXX_COMPILER_IS_CLANG ) if ( WALBERLA_STL_BOUNDS_CHECKS ) add_definitions ( "-D_GLIBCXX_DEBUG" ) + add_definitions ( "-D_LIBCPP_DEBUG=1" ) endif() endif() diff --git a/src/waLBerlaDefinitions.in.h b/src/waLBerlaDefinitions.in.h index 496f223b7..21d1dd6d3 100644 --- a/src/waLBerlaDefinitions.in.h +++ b/src/waLBerlaDefinitions.in.h @@ -41,6 +41,8 @@ #cmakedefine WALBERLA_THREAD_SAFE_LOGGING +#cmakedefine WALBERLA_STL_BOUNDS_CHECKS + // Compiler #cmakedefine WALBERLA_CXX_COMPILER_IS_GNU #cmakedefine WALBERLA_CXX_COMPILER_IS_INTEL diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 72b8e4537..caf28285c 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -188,6 +188,10 @@ waLBerla_execute_test( NAME ConcatIterator ) waLBerla_compile_test( FILES DataTypesTest.cpp ) waLBerla_execute_test( NAME DataTypesTest ) +waLBerla_compile_test( FILES DebugSTLTest.cpp ) +waLBerla_execute_test( NAME DebugSTLTest ) +set_tests_properties(DebugSTLTest PROPERTIES WILL_FAIL TRUE) + waLBerla_compile_test( FILES FunctionTraitsTest.cpp ) waLBerla_execute_test( NAME FunctionTraitsTest ) diff --git a/tests/core/DebugSTLTest.cpp b/tests/core/DebugSTLTest.cpp new file mode 100644 index 000000000..173be59a1 --- /dev/null +++ b/tests/core/DebugSTLTest.cpp @@ -0,0 +1,37 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GridGeneratorTest.cpp +//! \author Dominik Thoennes <dominik.thoennes@fau.de> +// +//====================================================================================================================== + +#include <cstdlib> +#include <vector> + +#include "waLBerlaDefinitions.h" + +// this test is expected to fail +int main(int /*argc*/, char** /*argv*/) +{ + int ret = EXIT_FAILURE; +#ifdef WALBERLA_STL_BOUNDS_CHECKS + std::vector< int > a(100); + // this throws an exception if the debug STL is used + // otherwise main will return 0 and the test fails since it is expected to fail + if (a[200] != 1337) { ret = EXIT_SUCCESS; } +#endif + return ret; +} \ No newline at end of file -- GitLab From d72a331ab141cbfe1999be280b00e4022704f5f6 Mon Sep 17 00:00:00 2001 From: Dominik Thoennes <dominik.thoennes@fau.de> Date: Fri, 30 Oct 2020 21:21:28 +0100 Subject: [PATCH 05/83] fix wrong/misleading error message if pystencils/lbmpy is missing; check for jinja2 --- CMakeLists.txt | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1abce0760..7dfde4d62 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -556,14 +556,23 @@ endif ( ) ## ############################################################################################################################# if ( WALBERLA_BUILD_WITH_CODEGEN ) - find_package( PythonInterp 3 QUIET REQUIRED) + find_package( PythonInterp 3 QUIET REQUIRED) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import lbmpy" + RESULT_VARIABLE LBMPY_FOUND ) + if(NOT LBMPY_FOUND EQUAL 0) + message(FATAL_ERROR "WALBERLA_BUILD_WITH_CODEGEN activated but pystencils or lbmpy package not found. + Please install lbmpy e.g.: 'pip3 install lbmpy'") + endif() execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "from pystencils.include import get_pystencils_include_path; print(get_pystencils_include_path())" - RESULT_VARIABLE PYTHON_RET_CODE OUTPUT_VARIABLE PYSTENCILS_INCLUDE_PATH) - if(NOT PYTHON_RET_CODE EQUAL 0) - message(FATAL_ERROR "WALBERLA_BUILD_WITH_CODEGEN activated and pystencils_walberla package not found") - endif() include_directories( ${PYSTENCILS_INCLUDE_PATH} ) + + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import jinja2" + RESULT_VARIABLE JINJA2_FOUND ) + if(NOT JINJA2_FOUND EQUAL 0) + message(FATAL_ERROR "WALBERLA_BUILD_WITH_CODEGEN activated and jinja2 package not found. + Please install jinja2 e.g.: 'pip3 install jinja2'") + endif() endif() ############################################################################################################################ -- GitLab From 400d2b969b3a090cbe86d87ce7ce979e8991df5c Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Sun, 22 Nov 2020 11:48:14 +0100 Subject: [PATCH 06/83] Switch codegen MRT tests to Schiller force model --- .../PhaseFieldAllenCahn/multiphase_codegen.py | 5 +++-- .../PhaseFieldAllenCahn/CMakeLists.txt | 2 -- .../PhaseFieldAllenCahn/CPU/CMakeLists.txt | 2 +- .../CPU/multiphase_codegen.py | 19 ++++++++++--------- .../PhaseFieldAllenCahn/GPU/CMakeLists.txt | 2 +- .../GPU/multiphase_codegen.py | 5 +++-- .../tests/test_walberla_codegen.py | 2 +- tests/lbm/codegen/FluctuatingMRT.py | 2 +- 8 files changed, 20 insertions(+), 19 deletions(-) diff --git a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py index 5fd50cf57..7a00cbca6 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py +++ b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py @@ -122,8 +122,9 @@ hydro_LB_step = get_collision_assignments_hydro(lb_method=method_hydro, density=density, velocity_input=u, force=force_g, - optimization={"symbolic_field": g, - "symbolic_temporary_field": g_tmp}, + sub_iterations=1, + symbolic_fields={"symbolic_field": g, + "symbolic_temporary_field": g_tmp}, kernel_type='collide_stream_push') # streaming of the hydrodynamic distribution diff --git a/apps/showcases/PhaseFieldAllenCahn/CMakeLists.txt b/apps/showcases/PhaseFieldAllenCahn/CMakeLists.txt index ed6d22966..9084c99a8 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CMakeLists.txt +++ b/apps/showcases/PhaseFieldAllenCahn/CMakeLists.txt @@ -1,6 +1,4 @@ -if ( NOT WALBERLA_BUILD_WITH_CUDA) add_subdirectory( CPU ) -endif() if ( WALBERLA_BUILD_WITH_CUDA) add_subdirectory( GPU ) diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt b/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt index b155b2f5b..0e8f653f7 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt @@ -13,7 +13,7 @@ waLBerla_generate_target_from_python(NAME PhaseFieldCodeGenCPU stream_hydro.cpp stream_hydro.h GenDefines.h) -waLBerla_add_executable(NAME multiphase +waLBerla_add_executable(NAME multiphaseCPU FILES multiphase.cpp PythonExports.cpp InitializerFunctions.cpp contact.cpp CalculateNormals.cpp multiphase_codegen.py DEPENDS blockforest core field postprocessing lbm geometry timeloop gui PhaseFieldCodeGenCPU) diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py index 42e990dc3..497e00299 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py @@ -134,8 +134,9 @@ hydro_LB_step = get_collision_assignments_hydro(lb_method=method_hydro, density=density, velocity_input=u, force=force_g, - optimization={"symbolic_field": g, - "symbolic_temporary_field": g_tmp}, + sub_iterations=2, + symbolic_fields={"symbolic_field": g, + "symbolic_temporary_field": g_tmp}, kernel_type='collide_only') hydro_LB_step.set_sub_expressions_from_dict({**{relaxation_rate: relaxation_rate_cutoff}, @@ -163,24 +164,24 @@ with CodeGeneration() as ctx: if not ctx.optimize_for_localhost: cpu_vec = {'instruction_set': None} - generate_sweep(ctx, 'initialize_phase_field_distributions', h_updates) - generate_sweep(ctx, 'initialize_velocity_based_distributions', g_updates) + generate_sweep(ctx, 'initialize_phase_field_distributions', h_updates, target='cpu') + generate_sweep(ctx, 'initialize_velocity_based_distributions', g_updates, target='cpu') generate_sweep(ctx, 'phase_field_LB_step', phase_field_LB_step, field_swaps=[(h, h_tmp)], inner_outer_split=True, - cpu_vectorize_info=cpu_vec) - generate_boundary(ctx, 'phase_field_LB_NoSlip', NoSlip(), method_phase) + cpu_vectorize_info=cpu_vec, target='cpu') + generate_boundary(ctx, 'phase_field_LB_NoSlip', NoSlip(), method_phase, target='cpu') generate_sweep(ctx, 'hydro_LB_step', hydro_LB_step, inner_outer_split=True, - cpu_vectorize_info=cpu_vec) - generate_boundary(ctx, 'hydro_LB_NoSlip', NoSlip(), method_hydro) + cpu_vectorize_info=cpu_vec, target='cpu') + generate_boundary(ctx, 'hydro_LB_NoSlip', NoSlip(), method_hydro, target='cpu') generate_sweep(ctx, 'stream_hydro', stream_hydro, field_swaps=[(g, g_tmp)], inner_outer_split=True, - cpu_vectorize_info=cpu_vec) + cpu_vectorize_info=cpu_vec, target='cpu') ctx.write_file("GenDefines.h", info_header) diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt b/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt index e2982ff93..c65a87749 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt @@ -16,7 +16,7 @@ waLBerla_generate_target_from_python(NAME PhaseFieldCodeGenGPU PackInfo_velocity_based_distributions.cu PackInfo_velocity_based_distributions.h GenDefines.h) -waLBerla_add_executable(NAME multiphase +waLBerla_add_executable(NAME multiphaseGPU FILES multiphase.cpp PythonExports.cpp InitializerFunctions.cpp CalculateNormals.cpp contact.cu multiphase_codegen.py DEPENDS blockforest core cuda field postprocessing lbm geometry timeloop gui PhaseFieldCodeGenGPU) diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_codegen.py b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_codegen.py index 16bdcfb5a..48a19621d 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_codegen.py +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_codegen.py @@ -133,8 +133,9 @@ hydro_LB_step = get_collision_assignments_hydro(lb_method=method_hydro, density=density, velocity_input=u, force=force_g, - optimization={"symbolic_field": g, - "symbolic_temporary_field": g_tmp}, + sub_iterations=2, + symbolic_fields={"symbolic_field": g, + "symbolic_temporary_field": g_tmp}, kernel_type='collide_only') hydro_LB_step.set_sub_expressions_from_dict({**{relaxation_rate: relaxation_rate_cutoff}, diff --git a/python/lbmpy_walberla/tests/test_walberla_codegen.py b/python/lbmpy_walberla/tests/test_walberla_codegen.py index 391743468..e38880aca 100644 --- a/python/lbmpy_walberla/tests/test_walberla_codegen.py +++ b/python/lbmpy_walberla/tests/test_walberla_codegen.py @@ -85,7 +85,7 @@ class WalberlaLbmpyCodegenTest(unittest.TestCase): collision_rule = create_lb_collision_rule( stencil='D3Q19', compressible=True, fluctuating={'seed': 0, 'temperature': 1e-6}, method='mrt', relaxation_rates=[omega_shear] * 19, - force_model='guo', force=force_field.center_vector, + force_model='schiller', force=force_field.center_vector, optimization={'cse_global': False} ) generate_lattice_model(ctx, 'FluctuatingMRT', collision_rule) diff --git a/tests/lbm/codegen/FluctuatingMRT.py b/tests/lbm/codegen/FluctuatingMRT.py index 98a8812ee..71a102612 100644 --- a/tests/lbm/codegen/FluctuatingMRT.py +++ b/tests/lbm/codegen/FluctuatingMRT.py @@ -37,7 +37,7 @@ with CodeGeneration() as ctx: compressible=True, weighted=True, relaxation_rate_getter=rr_getter, - force_model=force_model_from_string('guo', force_field.center_vector) + force_model=force_model_from_string('schiller', force_field.center_vector) ) collision_rule = create_lb_collision_rule( method, -- GitLab From 89813a9df089e0d1b20a7edc515090f20aa0e89f Mon Sep 17 00:00:00 2001 From: Stephan Seitz <stephan.seitz@fau.de> Date: Tue, 3 Nov 2020 18:10:01 +0100 Subject: [PATCH 07/83] Fix typo in PhantomBlock.h (WALBELRLA_USE_STD_ANY guard) --- src/blockforest/PhantomBlock.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/blockforest/PhantomBlock.h b/src/blockforest/PhantomBlock.h index 6afe73bec..e5d95c6c9 100644 --- a/src/blockforest/PhantomBlock.h +++ b/src/blockforest/PhantomBlock.h @@ -88,7 +88,7 @@ public: T getData() const { return walberla::any_cast<T>( data_ ); } bool hasData() const { -#ifdef WALBELRLA_USE_STD_ANY +#ifdef WALBERLA_USE_STD_ANY return data_.has_value(); #else return !(data_.empty()); -- GitLab From 442630845f43282c0c20206ae543ed2a62c6abdd Mon Sep 17 00:00:00 2001 From: Stephan Seitz <stephan.seitz@fau.de> Date: Tue, 8 Dec 2020 21:08:48 +0100 Subject: [PATCH 08/83] Remove copy pasta from boundary generation --- .isort.cfg | 5 + .../codegen/03_AdvancedLBMCodegen.cpp | 4 +- doc/doxygen.in | 2 +- python/lbmpy_walberla/boundary.py | 92 +++++---------- python/pystencils_walberla/boundary.py | 106 +++++++----------- 5 files changed, 73 insertions(+), 136 deletions(-) create mode 100644 .isort.cfg diff --git a/.isort.cfg b/.isort.cfg new file mode 100644 index 000000000..bfe068484 --- /dev/null +++ b/.isort.cfg @@ -0,0 +1,5 @@ +[settings] +line_length=100 +balanced_wrapping=True +multi_line_output=4 +known_third_party=sympy diff --git a/apps/tutorials/codegen/03_AdvancedLBMCodegen.cpp b/apps/tutorials/codegen/03_AdvancedLBMCodegen.cpp index 1f24dfffe..b6ff21d73 100644 --- a/apps/tutorials/codegen/03_AdvancedLBMCodegen.cpp +++ b/apps/tutorials/codegen/03_AdvancedLBMCodegen.cpp @@ -73,7 +73,7 @@ typedef FlagField< flag_t > FlagField_T; typedef lbm::CumulantMRTNoSlip NoSlip_T; #if defined(WALBERLA_BUILD_WITH_CUDA) -typedef cuda::GPUField< double > GPUField; +typedef cuda::GPUField< real_t > GPUField; #endif ////////////////////////////////////////// @@ -247,4 +247,4 @@ int main(int argc, char** argv) } // namespace walberla -int main(int argc, char** argv) { return walberla::main(argc, argv); } \ No newline at end of file +int main(int argc, char** argv) { return walberla::main(argc, argv); } diff --git a/doc/doxygen.in b/doc/doxygen.in index a98ddcec1..ca467e074 100644 --- a/doc/doxygen.in +++ b/doc/doxygen.in @@ -2093,7 +2093,7 @@ HIDE_UNDOC_RELATIONS = YES # set to NO # The default value is: NO. -HAVE_DOT = @DOXYGEN_DOT_FOUND@ +HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed # to run in parallel. When set to 0 doxygen will base this on the number of diff --git a/python/lbmpy_walberla/boundary.py b/python/lbmpy_walberla/boundary.py index ba1d697b9..8f751f529 100644 --- a/python/lbmpy_walberla/boundary.py +++ b/python/lbmpy_walberla/boundary.py @@ -1,70 +1,28 @@ -import numpy as np -from jinja2 import Environment, PackageLoader, StrictUndefined - +import pystencils_walberla.boundary from lbmpy.boundaries.boundaryhandling import create_lattice_boltzmann_boundary_kernel -from pystencils import Field, FieldType -from pystencils.boundaries.createindexlist import numpy_data_type_for_boundary_object -from pystencils.data_types import TypedSymbol, create_type -from pystencils_walberla.boundary import struct_from_numpy_dtype -from pystencils_walberla.codegen import default_create_kernel_parameters, KernelInfo -from pystencils_walberla.jinja_filters import add_pystencils_filters_to_jinja_env - - -def generate_boundary(generation_context, class_name, boundary_object, lb_method, **create_kernel_params): - struct_name = "IndexInfo" - boundary_object.name = class_name - - create_kernel_params = default_create_kernel_parameters(generation_context, create_kernel_params) - target = create_kernel_params['target'] - - index_struct_dtype = numpy_data_type_for_boundary_object(boundary_object, lb_method.dim) - - pdf_field = Field.create_generic('pdfs', lb_method.dim, - np.float64 if generation_context.double_accuracy else np.float32, - index_dimensions=1, layout='fzyx', index_shape=[len(lb_method.stencil)]) - - index_field = Field('indexVector', FieldType.INDEXED, index_struct_dtype, layout=[0], - shape=(TypedSymbol("indexVectorSize", create_type(np.int64)), 1), strides=(1, 1)) - - kernel = create_lattice_boltzmann_boundary_kernel(pdf_field, index_field, lb_method, boundary_object, target=target, - openmp=generation_context.openmp) - kernel.function_name = "boundary_" + boundary_object.name - kernel.assumed_inner_stride_one = False - - # waLBerla is a 3D framework. Therefore, a zero for the z index has to be added if we work in 2D - if lb_method.dim == 2: - stencil = () - for d in lb_method.stencil: - d = d + (0,) - stencil = stencil + (d,) - else: - stencil = lb_method.stencil - - stencil_info = [(i, d, ", ".join([str(e) for e in d])) for i, d in enumerate(stencil)] - inv_dirs = [] - for direction in stencil: - inverse_dir = tuple([-i for i in direction]) - inv_dirs.append(stencil.index(inverse_dir)) - - context = { - 'class_name': boundary_object.name, - 'StructName': struct_name, - 'StructDeclaration': struct_from_numpy_dtype(struct_name, index_struct_dtype), - 'kernel': KernelInfo(kernel), - 'stencil_info': stencil_info, - 'inverse_directions': inv_dirs, - 'dim': lb_method.dim, - 'target': target, - 'namespace': 'lbm', - 'inner_or_boundary': boundary_object.inner_or_boundary - } - - env = Environment(loader=PackageLoader('pystencils_walberla'), undefined=StrictUndefined) - add_pystencils_filters_to_jinja_env(env) - header = env.get_template('Boundary.tmpl.h').render(**context) - source = env.get_template('Boundary.tmpl.cpp').render(**context) - source_extension = "cpp" if create_kernel_params.get("target", "cpu") == "cpu" else "cu" - generation_context.write_file("{}.h".format(class_name), header) - generation_context.write_file("{}.{}".format(class_name, source_extension), source) +def generate_boundary(generation_context, + class_name, + boundary_object, + lb_method, + field_name='pdfs', + **create_kernel_params): + + def boundary_creation_function(field, index_field, stencil, boundary_functor, target='cpu', openmp=True, **kwargs): + return create_lattice_boltzmann_boundary_kernel(field, + index_field, + lb_method, + boundary_functor, + target=target, + **kwargs) + + pystencils_walberla.boundary.generate_boundary(generation_context, + class_name, + boundary_object, + field_name=field_name, + neighbor_stencil=lb_method.stencil, + index_shape=[len(lb_method.stencil)], + kernel_creation_function=boundary_creation_function, + namespace='lbm', + **create_kernel_params) diff --git a/python/pystencils_walberla/boundary.py b/python/pystencils_walberla/boundary.py index 1984fbfc5..7c7547001 100644 --- a/python/pystencils_walberla/boundary.py +++ b/python/pystencils_walberla/boundary.py @@ -1,33 +1,52 @@ +from functools import partial + import numpy as np from jinja2 import Environment, PackageLoader, StrictUndefined - from pystencils import Field, FieldType from pystencils.boundaries.boundaryhandling import create_boundary_kernel from pystencils.boundaries.createindexlist import ( boundary_index_array_coordinate_names, direction_member_name, numpy_data_type_for_boundary_object) from pystencils.data_types import TypedSymbol, create_type -from pystencils_walberla.codegen import KernelInfo +from pystencils_walberla.codegen import KernelInfo, default_create_kernel_parameters from pystencils_walberla.jinja_filters import add_pystencils_filters_to_jinja_env -def generate_staggered_boundary(generation_context, class_name, boundary_object, - dim, neighbor_stencil, index_shape, target='cpu'): +def generate_boundary(generation_context, + class_name, + boundary_object, + field_name, + neighbor_stencil, + index_shape, + field_type=FieldType.GENERIC, + kernel_creation_function=None, + target='cpu', + namespace='pystencils', + **create_kernel_params): struct_name = "IndexInfo" boundary_object.name = class_name + dim = len(neighbor_stencil[0]) + + create_kernel_params = default_create_kernel_parameters(generation_context, create_kernel_params) + create_kernel_params["target"] = target + del create_kernel_params["cpu_vectorize_info"] + if not create_kernel_params["data_type"]: + create_kernel_params["data_type"] = 'double' if generation_context.double_accuracy else 'float32' index_struct_dtype = numpy_data_type_for_boundary_object(boundary_object, dim) - staggered_field = Field.create_generic('field', dim, - np.float64 if generation_context.double_accuracy else np.float32, - index_dimensions=len(index_shape), layout='c', index_shape=index_shape, - field_type=FieldType.STAGGERED) + field = Field.create_generic(field_name, dim, + np.float64 if generation_context.double_accuracy else np.float32, + index_dimensions=len(index_shape), layout='fzyx', index_shape=index_shape, + field_type=field_type) index_field = Field('indexVector', FieldType.INDEXED, index_struct_dtype, layout=[0], shape=(TypedSymbol("indexVectorSize", create_type(np.int64)), 1), strides=(1, 1)) - kernel = create_boundary_kernel(staggered_field, index_field, neighbor_stencil, boundary_object, target=target, - openmp=generation_context.openmp) + if not kernel_creation_function: + kernel_creation_function = create_boundary_kernel + + kernel = kernel_creation_function(field, index_field, neighbor_stencil, boundary_object, **create_kernel_params) kernel.function_name = "boundary_" + boundary_object.name kernel.assumed_inner_stride_one = False @@ -55,7 +74,7 @@ def generate_staggered_boundary(generation_context, class_name, boundary_object, 'inverse_directions': inv_dirs, 'dim': dim, 'target': target, - 'namespace': 'pystencils', + 'namespace': namespace, 'inner_or_boundary': boundary_object.inner_or_boundary } @@ -70,63 +89,18 @@ def generate_staggered_boundary(generation_context, class_name, boundary_object, generation_context.write_file("{}.{}".format(class_name, source_extension), source) -def generate_staggered_flux_boundary(generation_context, class_name, boundary_object, - dim, neighbor_stencil, index_shape, target='cpu'): - struct_name = "IndexInfo" - boundary_object.name = class_name - - index_struct_dtype = numpy_data_type_for_boundary_object(boundary_object, dim) - - staggered_field = Field.create_generic('flux', dim, - np.float64 if generation_context.double_accuracy else np.float32, - index_dimensions=len(index_shape), layout='c', index_shape=index_shape, - field_type=FieldType.STAGGERED_FLUX) - - index_field = Field('indexVector', FieldType.INDEXED, index_struct_dtype, layout=[0], - shape=(TypedSymbol("indexVectorSize", create_type(np.int64)), 1), strides=(1, 1)) - - kernel = create_boundary_kernel(staggered_field, index_field, neighbor_stencil, boundary_object, target=target, - openmp=generation_context.openmp) - kernel.function_name = "boundary_" + boundary_object.name - kernel.assumed_inner_stride_one = False - - # waLBerla is a 3D framework. Therefore, a zero for the z index has to be added if we work in 2D - if dim == 2: - stencil = () - for d in neighbor_stencil: - d = d + (0,) - stencil = stencil + (d,) - else: - stencil = neighbor_stencil - - stencil_info = [(i, d, ", ".join([str(e) for e in d])) for i, d in enumerate(stencil)] - inv_dirs = [] - for direction in stencil: - inverse_dir = tuple([-i for i in direction]) - inv_dirs.append(stencil.index(inverse_dir)) - - context = { - 'class_name': boundary_object.name, - 'StructName': struct_name, - 'StructDeclaration': struct_from_numpy_dtype(struct_name, index_struct_dtype), - 'kernel': KernelInfo(kernel), - 'stencil_info': stencil_info, - 'inverse_directions': inv_dirs, - 'dim': dim, - 'target': target, - 'namespace': 'pystencils', - 'inner_or_boundary': boundary_object.inner_or_boundary - } +def generate_staggered_boundary(generation_context, class_name, boundary_object, + dim, neighbor_stencil, index_shape, target='cpu', **kwargs): + assert dim == len(neighbor_stencil[0]) + generate_boundary(generation_context, class_name, boundary_object, 'field', neighbor_stencil, index_shape, + FieldType.STAGGERED, target=target, **kwargs) - env = Environment(loader=PackageLoader('pystencils_walberla'), undefined=StrictUndefined) - add_pystencils_filters_to_jinja_env(env) - header = env.get_template('Boundary.tmpl.h').render(**context) - source = env.get_template('Boundary.tmpl.cpp').render(**context) - - source_extension = "cpp" if target == "cpu" else "cu" - generation_context.write_file("{}.h".format(class_name), header) - generation_context.write_file("{}.{}".format(class_name, source_extension), source) +def generate_staggered_flux_boundary(generation_context, class_name, boundary_object, + dim, neighbor_stencil, index_shape, target='cpu', **kwargs): + assert dim == len(neighbor_stencil[0]) + generate_boundary(generation_context, class_name, boundary_object, 'flux', neighbor_stencil, index_shape, + FieldType.STAGGERED_FLUX, target=target, **kwargs) def struct_from_numpy_dtype(struct_name, numpy_dtype): -- GitLab From 4cb13c5446c16db216bb91afc2ea5c81138398ce Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 1 Dec 2020 13:12:06 +0100 Subject: [PATCH 09/83] reworked accuracy test of mesa_pd integrators - checking order of integrator - checking energy conservation - added semi implicit euler - improved documentation - playground for integrator analysis --- apps/benchmarks/CMakeLists.txt | 1 + .../IntegratorAccuracy/CMakeLists.txt | 4 + .../IntegratorAccuracy/IntegratorAccuracy.cpp | 274 +++++++++++++++ .../IntegratorAccuracy.ipynb | 156 +++++++++ python/mesa_pd.py | 1 + python/mesa_pd/kernel/SemiImplicitEuler.py | 34 ++ python/mesa_pd/kernel/__init__.py | 2 + .../templates/kernel/ExplicitEuler.templ.h | 17 +- .../kernel/SemiImplicitEuler.templ.h | 109 ++++++ .../templates/kernel/VelocityVerlet.templ.h | 2 + src/mesa_pd/kernel/ExplicitEuler.h | 17 +- src/mesa_pd/kernel/SemiImplicitEuler.h | 115 +++++++ src/mesa_pd/kernel/VelocityVerlet.h | 2 + tests/mesa_pd/CMakeLists.txt | 5 +- tests/mesa_pd/DropTestAnalytic.cpp | 6 +- tests/mesa_pd/DropTestGeneral.cpp | 8 +- .../kernel/CoefficientOfRestitutionLSD.cpp | 8 +- .../kernel/CoefficientOfRestitutionNLSD.cpp | 8 +- .../kernel/CoefficientOfRestitutionSD.cpp | 8 +- tests/mesa_pd/kernel/ExplicitEuler.cpp | 22 +- tests/mesa_pd/kernel/GenerateLinkedCells.cpp | 4 +- tests/mesa_pd/kernel/IntegratorAccuracy.cpp | 312 +++++++++++------- tests/mesa_pd/kernel/LinearSpringDashpot.cpp | 6 +- tests/mesa_pd/kernel/SemiImplicitEuler.cpp | 133 ++++++++ tests/mesa_pd/kernel/SpherePile.cpp | 8 +- .../SemiImplicitEulerInterfaceCheck.cpp | 90 +++++ 26 files changed, 1192 insertions(+), 160 deletions(-) create mode 100644 apps/benchmarks/IntegratorAccuracy/CMakeLists.txt create mode 100644 apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.cpp create mode 100644 apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.ipynb create mode 100644 python/mesa_pd/kernel/SemiImplicitEuler.py create mode 100644 python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h create mode 100644 src/mesa_pd/kernel/SemiImplicitEuler.h create mode 100644 tests/mesa_pd/kernel/SemiImplicitEuler.cpp create mode 100644 tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index 01d574401..aabba8b45 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -7,6 +7,7 @@ add_subdirectory( CouetteFlow ) add_subdirectory( FluidParticleCoupling ) add_subdirectory( ForcesOnSphereNearPlaneInShearFlow ) add_subdirectory( GranularGas ) +add_subdirectory( IntegratorAccuracy ) add_subdirectory( LennardJones ) add_subdirectory( NonUniformGrid ) add_subdirectory( MotionSingleHeavySphere ) diff --git a/apps/benchmarks/IntegratorAccuracy/CMakeLists.txt b/apps/benchmarks/IntegratorAccuracy/CMakeLists.txt new file mode 100644 index 000000000..8e95e831c --- /dev/null +++ b/apps/benchmarks/IntegratorAccuracy/CMakeLists.txt @@ -0,0 +1,4 @@ +waLBerla_link_files_to_builddir( "*.ipynb" ) + +waLBerla_add_executable ( NAME IntegratorAccuracy + DEPENDS core mesa_pd ) diff --git a/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.cpp b/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.cpp new file mode 100644 index 000000000..af2dc8a3a --- /dev/null +++ b/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.cpp @@ -0,0 +1,274 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file IntegratorAccuracy.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "mesa_pd/data/ParticleAccessor.h" + +#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" +#include "mesa_pd/kernel/VelocityVerlet.h" + +#include "core/Environment.h" +#include "core/math/all.h" + +#include <iostream> + +namespace walberla { + +using namespace walberla::mesa_pd; + +class SingleParticleAccessorWithShape : public data::SingleParticleAccessor +{ +public: + void setInvMass(const size_t /*p_idx*/, const real_t &val) + { invMass_ = val; } + + const auto &getInvMass(const size_t /*p_idx*/) const + { return invMass_; } + + void setInvInertiaBF(const size_t /*p_idx*/, const Mat3 &val) + { invInertiaBF_ = val; } + + const auto &getInvInertiaBF(const size_t /*p_idx*/) const + { return invInertiaBF_; } + +private: + real_t invMass_; + Mat3 invInertiaBF_; +}; + +struct Oscillator +{ + real_t amplitude = 1.5_r; + real_t k = 0.1_r; + real_t damping = 0_r; + real_t mass = 0.9_r; + real_t dt = 0.2_r; + real_t phaseFraction = 0_r; + real_t periods = 10_r; + real_t phase = phaseFraction * math::pi; + real_t dampingRatio = damping / (2_r * std::sqrt(mass * k)); + real_t omega = std::sqrt(k / mass) * std::sqrt(1_r - dampingRatio * dampingRatio); + real_t decay = std::sqrt(k / mass) * dampingRatio; + real_t durationOnePeriod = 2_r * math::pi / omega; + uint_t timeSteps = uint_c(periods * durationOnePeriod / dt); + + Oscillator(int argc, char **argv) + { + for (int i = 1; i < argc; ++i) + { + if (std::strcmp(argv[i], "--dt") == 0) + { + dt = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--amplitude") == 0) + { + amplitude = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--k") == 0) + { + k = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--damping") == 0) + { + damping = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--mass") == 0) + { + mass = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--phaseFraction") == 0) + { + phaseFraction = real_c(std::atof(argv[++i])); + continue; + } + if (std::strcmp(argv[i], "--periods") == 0) + { + periods = real_c(std::atof(argv[++i])); + continue; + } + WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); + } + + update(); + } + + void update() + { + phase = phaseFraction * math::pi; + dampingRatio = damping / (2_r * std::sqrt(mass * k)); + omega = std::sqrt(k / mass) * std::sqrt(1_r - dampingRatio * dampingRatio); + decay = std::sqrt(k / mass) * dampingRatio; + durationOnePeriod = 2_r * math::pi / omega; + timeSteps = uint_c(periods * durationOnePeriod / dt); + } + + Vec3 getForce(const Vec3 &pos, const Vec3 &vel) const + { + return -k * pos - damping * vel; + } + + real_t getEnergy(const real_t &pos, const real_t &vel) const + { + return 0.5_r * mass * vel * vel + 0.5_r * k * pos * pos; + } + + real_t analyticalPos(real_t t) const + { + return amplitude * std::exp(-decay * t) * std::cos(omega * t + phase); + } + + real_t analyticalVel(real_t t) const + { + return -decay * amplitude * std::exp(-decay * t) * std::cos(omega * t + phase) + -amplitude * std::exp(-decay * t) * omega * std::sin(omega * t + phase); + } +}; + +struct ExplicitEuler +{ + ExplicitEuler(real_t dt) : integrator(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) + { + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + integrator(0, particle); + } + kernel::ExplicitEuler integrator; +}; + +struct SemiImplicitEuler +{ + SemiImplicitEuler(real_t dt) : integrator(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) + { + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + integrator(0, particle); + } + kernel::SemiImplicitEuler integrator; +}; + +struct VelocityVerlet +{ + VelocityVerlet(real_t dt) : preVV(dt), postVV(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) + { + preVV(0, particle); + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + postVV(0, particle); + } + kernel::VelocityVerletPreForceUpdate preVV; + kernel::VelocityVerletPostForceUpdate postVV; +}; + +struct AccuracyResult +{ + real_t maxPosDeviation; + real_t maxVelDeviation; + real_t maxEneDeviation; +}; + +template <typename Integrator> +AccuracyResult checkIntegrator(const Oscillator& osc) +{ + //init data structures + SingleParticleAccessorWithShape particle; + + //first dummy argument is needed to fulfill accessor interface + particle.setPosition(0, Vec3(0, 0, osc.analyticalPos(0_r))); + particle.setLinearVelocity(0, Vec3(0, 0, osc.analyticalVel(0_r))); + particle.setInvMass(0, 1_r / osc.mass); + particle.setForce(0, osc.getForce(Vec3(0, 0, osc.analyticalPos(real_t(0))), + Vec3(0, 0, osc.analyticalVel(real_t(0))))); + particle.setOldForce(0, osc.getForce(Vec3(0, 0, osc.analyticalPos(-osc.dt)), + Vec3(0, 0, osc.analyticalVel(-osc.dt)))); + + // explicit euler + Integrator integrator(osc.dt); + + real_t maxPosDeviation = 0_r; + real_t maxVelDeviation = 0_r; + real_t maxEneDeviation = 0_r; + + for (auto i = uint_t(0); i <= osc.timeSteps; ++i) + { + real_t refPos = osc.analyticalPos(real_c(i) * osc.dt); + real_t refVel = osc.analyticalVel(real_c(i) * osc.dt); + real_t refEne = osc.getEnergy(refPos, refVel); + + maxPosDeviation = std::max(maxPosDeviation, std::abs(particle.getPosition(0)[2] - refPos)); + maxVelDeviation = std::max(maxVelDeviation, std::abs(particle.getLinearVelocity(0)[2] - refVel)); + maxEneDeviation = std::max(maxEneDeviation, std::abs(osc.getEnergy(particle.getPosition(0)[2], particle.getLinearVelocity(0)[2]) - refEne)); + + std::cout << real_t(i) * osc.dt << " " + << refPos << " " + << refVel << " " + << refEne << " " + << particle.getPosition(0)[2] << " " + << particle.getLinearVelocity(0)[2] << " " + << osc.getEnergy(particle.getPosition(0)[2], particle.getLinearVelocity(0)[2]) << " " + << maxPosDeviation << " " + << maxVelDeviation << std::endl; + + integrator(particle, osc); + } + + return {maxPosDeviation, maxVelDeviation, maxEneDeviation}; +} + +int main(int argc, char **argv) +{ + mpi::Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + Oscillator osc(argc, argv); + + AccuracyResult res; +// res = walberla::checkIntegrator<walberla::ExplicitEuler>(osc); +// res = walberla::checkIntegrator<walberla::SemiImplicitEuler>(osc); + res = walberla::checkIntegrator<walberla::VelocityVerlet>(osc); + + return EXIT_SUCCESS; +} + +} //namespace walberla + + +/* + * Simulates a harmonic oscillator to test the accuracy of the integrators. + * Playground for integrator analysis. The corresponding unit test is located at + * tests/mesa_pd/kernel/IntegratorAccuracy.cpp + */ +int main(int argc, char **argv) +{ + return walberla::main(argc, argv); +} + diff --git a/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.ipynb b/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.ipynb new file mode 100644 index 000000000..f0cc8feef --- /dev/null +++ b/apps/benchmarks/IntegratorAccuracy/IntegratorAccuracy.ipynb @@ -0,0 +1,156 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# error analysis of integration kernels" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as plt\n", + "import numpy as np" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "integrator = 'euler'\n", + "data01 = np.loadtxt(f'{integrator}01.txt').transpose()\n", + "data02 = np.loadtxt(f'{integrator}02.txt').transpose()\n", + "data04 = np.loadtxt(f'{integrator}04.txt').transpose()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(data01[0], data01[7], label='dt = 0.1')\n", + "plt.plot(data02[0], data02[7], label='dt = 0.2')\n", + "plt.plot(data04[0], data04[7], label='dt = 0.4')\n", + "plt.xlabel('time')\n", + "plt.ylabel('max pos error')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(data01[0], data01[8], label='dt = 0.1')\n", + "plt.plot(data02[0], data02[8], label='dt = 0.2')\n", + "plt.plot(data04[0], data04[8], label='dt = 0.4')\n", + "plt.xlabel('time')\n", + "plt.ylabel('max vel error')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "final_errors = np.ones(3)\n", + "final_errors[0] = np.abs(data01[7][-1])\n", + "final_errors[1] = np.abs(data02[7][-1])\n", + "final_errors[2] = np.abs(data04[7][-1])\n", + "\n", + "plt.bar(np.arange(3), final_errors)\n", + "plt.show()\n", + "\n", + "print(final_errors[2] / final_errors[1])\n", + "print(final_errors[1] / final_errors[0])" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(data01[0], data01[1], label='analytic')\n", + "plt.plot(data01[0], data01[4], label='dt = 0.1')\n", + "plt.plot(data02[0], data02[4], label='dt = 0.2')\n", + "plt.plot(data04[0], data04[4], label='dt = 0.4')\n", + "plt.xlabel('time')\n", + "plt.ylabel('pos')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(data01[0], data01[2], label='analytic')\n", + "plt.plot(data01[0], data01[5], label='dt = 0.1')\n", + "plt.plot(data02[0], data02[5], label='dt = 0.2')\n", + "plt.plot(data04[0], data04[5], label='dt = 0.4')\n", + "plt.xlabel('time')\n", + "plt.ylabel('vel')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.plot(data01[0], data01[6] / data01[3][0], label='dt = 0.1')\n", + "plt.plot(data02[0], data02[6] / data01[3][0], label='dt = 0.2')\n", + "plt.plot(data04[0], data04[6] / data01[3][0], label='dt = 0.4')\n", + "plt.xlabel('time')\n", + "plt.ylabel('relative energy')\n", + "plt.legend()\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/python/mesa_pd.py b/python/mesa_pd.py index cc8b53091..0d94b5a92 100755 --- a/python/mesa_pd.py +++ b/python/mesa_pd.py @@ -103,6 +103,7 @@ if __name__ == '__main__': mpd.add(kernel.InsertParticleIntoSparseLinkedCells()) mpd.add(kernel.LinearSpringDashpot()) mpd.add(kernel.NonLinearSpringDashpot()) + mpd.add(kernel.SemiImplicitEuler()) mpd.add(kernel.SingleCast(ps)) mpd.add(kernel.SpringDashpot()) mpd.add(kernel.SpringDashpotSpring()) diff --git a/python/mesa_pd/kernel/SemiImplicitEuler.py b/python/mesa_pd/kernel/SemiImplicitEuler.py new file mode 100644 index 000000000..f5b6632a1 --- /dev/null +++ b/python/mesa_pd/kernel/SemiImplicitEuler.py @@ -0,0 +1,34 @@ +# -*- coding: utf-8 -*- + +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +class SemiImplicitEuler: + def __init__(self, integrate_rotation=True): + self.context = {'bIntegrateRotation': integrate_rotation, + 'interface': [ + create_access("position", "walberla::mesa_pd::Vec3", access="gs"), + create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs"), + create_access("invMass", "walberla::real_t", access="g"), + create_access("force", "walberla::mesa_pd::Vec3", access="gs"), + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") + ] + } + + if integrate_rotation: + self.context['interface'].append(create_access("rotation", "walberla::mesa_pd::Rot3", access="gs")) + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("invInertiaBF", "walberla::mesa_pd::Mat3", access="g")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="gs")) + + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/SemiImplicitEuler.templ.h', ctx) + + ctx["InterfaceTestName"] = "SemiImplicitEulerInterfaceCheck" + ctx["KernelInclude"] = "kernel/SemiImplicitEuler.h" + ctx["SemiImplicitEulerInstantiation"] = \ + "template void kernel::SemiImplicitEuler::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/__init__.py b/python/mesa_pd/kernel/__init__.py index 317646d1e..4a639693b 100644 --- a/python/mesa_pd/kernel/__init__.py +++ b/python/mesa_pd/kernel/__init__.py @@ -12,6 +12,7 @@ from .InsertParticleIntoLinkedCells import InsertParticleIntoLinkedCells from .InsertParticleIntoSparseLinkedCells import InsertParticleIntoSparseLinkedCells from .LinearSpringDashpot import LinearSpringDashpot from .NonLinearSpringDashpot import NonLinearSpringDashpot +from .SemiImplicitEuler import SemiImplicitEuler from .SingleCast import SingleCast from .SpringDashpot import SpringDashpot from .SpringDashpotSpring import SpringDashpotSpring @@ -31,6 +32,7 @@ __all__ = ['DoubleCast', 'InsertParticleIntoSparseLinkedCells', 'LinearSpringDashpot', 'NonLinearSpringDashpot', + 'SemiImplicitEuler', 'SingleCast', 'SpringDashpot', 'SpringDashpotSpring', diff --git a/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h b/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h index e3916291b..79b1518b3 100644 --- a/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h +++ b/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h @@ -34,7 +34,12 @@ namespace mesa_pd { namespace kernel { /** - * Kernel which explicitly integrates all particles in time. + * Explicit Euler integration. + * Uses the 0.5at^2 extension for position integration. + * Boils down to using v_{t+0.5dt} for position integration. + * This version exhibits increased stability compared to standard explicit euler. + * + * Wachs, A. Particle-scale computational approaches to model dry and saturated granular flows of non-Brownian, non-cohesive, and non-spherical rigid bodies. Acta Mech 230, 1919–1980 (2019). https://doi.org/10.1007/s00707-019-02389-9 * * This kernel requires the following particle accessor interface * \code @@ -75,15 +80,19 @@ inline void ExplicitEuler::operator()(const size_t idx, if (!data::particle_flags::isSet( ac.getFlags(idx), data::particle_flags::FIXED)) { - ac.setPosition (idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ * dt_ + ac.getLinearVelocity(idx) * dt_ + ac.getPosition(idx)); - ac.setLinearVelocity(idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + ac.getLinearVelocity(idx)); + ac.setPosition (idx, 0.5_r * ac.getInvMass(idx) * ac.getForce(idx) * dt_ * dt_ + + ac.getLinearVelocity(idx) * dt_ + + ac.getPosition(idx)); + ac.setLinearVelocity(idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + + ac.getLinearVelocity(idx)); {%- if bIntegrateRotation %} const Vec3 wdot = math::transformMatrixRART(ac.getRotation(idx).getMatrix(), ac.getInvInertiaBF(idx)) * ac.getTorque(idx); // Calculating the rotation angle - const Vec3 phi( ac.getAngularVelocity(idx) * dt_ + wdot * dt_ * dt_); + const Vec3 phi( 0.5_r * wdot * dt_ * dt_ + + ac.getAngularVelocity(idx) * dt_ ); // Calculating the new orientation auto rotation = ac.getRotation(idx); diff --git a/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h b/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h new file mode 100644 index 000000000..7045cbfe1 --- /dev/null +++ b/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h @@ -0,0 +1,109 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SemiImplicitEuler.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +namespace walberla { +namespace mesa_pd { +namespace kernel { + +/** + * Semi-implicit Euler integration for position and velocity. + * + * This kernel requires the following particle accessor interface + * \code + {%- for prop in interface %} + {%- if 'g' in prop.access %} + * const {{prop.type}}& get{{prop.name | capFirst}}(const size_t p_idx) const; + {%- endif %} + {%- if 's' in prop.access %} + * void set{{prop.name | capFirst}}(const size_t p_idx, const {{prop.type}}& v); + {%- endif %} + {%- if 'r' in prop.access %} + * {{prop.type}}& get{{prop.name | capFirst}}Ref(const size_t p_idx); + {%- endif %} + * + {%- endfor %} + * \endcode + * + * \pre All forces and torques acting on the particles have to be set. + * \post All forces and torques are reset to 0. + * \ingroup mesa_pd_kernel + */ +class SemiImplicitEuler +{ +public: + explicit SemiImplicitEuler(const real_t dt) : dt_(dt) {} + + template <typename Accessor> + void operator()(const size_t i, Accessor& ac) const; +private: + real_t dt_ = real_t(0.0); +}; + +template <typename Accessor> +inline void SemiImplicitEuler::operator()(const size_t idx, + Accessor& ac) const +{ + static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); + + if (!data::particle_flags::isSet( ac.getFlags(idx), data::particle_flags::FIXED)) + { + ac.setLinearVelocity( idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + + ac.getLinearVelocity(idx)); + ac.setPosition ( idx, ac.getLinearVelocity(idx) * dt_ + + ac.getPosition(idx)); + + {%- if bIntegrateRotation %} + const Vec3 wdot = math::transformMatrixRART(ac.getRotation(idx).getMatrix(), + ac.getInvInertiaBF(idx)) * ac.getTorque(idx); + + ac.setAngularVelocity(idx, wdot * dt_ + + ac.getAngularVelocity(idx)); + + // Calculating the rotation angle + const Vec3 phi( ac.getAngularVelocity(idx) * dt_ ); + + // Calculating the new orientation + auto rotation = ac.getRotation(idx); + rotation.rotate( phi ); + ac.setRotation(idx, rotation); + + {%- endif %} + } + + ac.setForce (idx, Vec3(real_t(0), real_t(0), real_t(0))); + {%- if bIntegrateRotation %} + ac.setTorque(idx, Vec3(real_t(0), real_t(0), real_t(0))); + {%- endif %} +} + +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla diff --git a/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h b/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h index 148ac8c8d..98d97b628 100644 --- a/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h +++ b/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h @@ -41,6 +41,8 @@ namespace kernel { * integration is only complete when both functions are called. The integration * is symplectic. * + * Wachs, A. Particle-scale computational approaches to model dry and saturated granular flows of non-Brownian, non-cohesive, and non-spherical rigid bodies. Acta Mech 230, 1919–1980 (2019). https://doi.org/10.1007/s00707-019-02389-9 + * * This kernel requires the following particle accessor interface * \code {%- for prop in interface %} diff --git a/src/mesa_pd/kernel/ExplicitEuler.h b/src/mesa_pd/kernel/ExplicitEuler.h index 8887219b1..639e3671a 100644 --- a/src/mesa_pd/kernel/ExplicitEuler.h +++ b/src/mesa_pd/kernel/ExplicitEuler.h @@ -34,7 +34,12 @@ namespace mesa_pd { namespace kernel { /** - * Kernel which explicitly integrates all particles in time. + * Explicit Euler integration. + * Uses the 0.5at^2 extension for position integration. + * Boils down to using v_{t+0.5dt} for position integration. + * This version exhibits increased stability compared to standard explicit euler. + * + * Wachs, A. Particle-scale computational approaches to model dry and saturated granular flows of non-Brownian, non-cohesive, and non-spherical rigid bodies. Acta Mech 230, 1919–1980 (2019). https://doi.org/10.1007/s00707-019-02389-9 * * This kernel requires the following particle accessor interface * \code @@ -87,13 +92,17 @@ inline void ExplicitEuler::operator()(const size_t idx, if (!data::particle_flags::isSet( ac.getFlags(idx), data::particle_flags::FIXED)) { - ac.setPosition (idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ * dt_ + ac.getLinearVelocity(idx) * dt_ + ac.getPosition(idx)); - ac.setLinearVelocity(idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + ac.getLinearVelocity(idx)); + ac.setPosition (idx, 0.5_r * ac.getInvMass(idx) * ac.getForce(idx) * dt_ * dt_ + + ac.getLinearVelocity(idx) * dt_ + + ac.getPosition(idx)); + ac.setLinearVelocity(idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + + ac.getLinearVelocity(idx)); const Vec3 wdot = math::transformMatrixRART(ac.getRotation(idx).getMatrix(), ac.getInvInertiaBF(idx)) * ac.getTorque(idx); // Calculating the rotation angle - const Vec3 phi( ac.getAngularVelocity(idx) * dt_ + wdot * dt_ * dt_); + const Vec3 phi( 0.5_r * wdot * dt_ * dt_ + + ac.getAngularVelocity(idx) * dt_ ); // Calculating the new orientation auto rotation = ac.getRotation(idx); diff --git a/src/mesa_pd/kernel/SemiImplicitEuler.h b/src/mesa_pd/kernel/SemiImplicitEuler.h new file mode 100644 index 000000000..cf0df0734 --- /dev/null +++ b/src/mesa_pd/kernel/SemiImplicitEuler.h @@ -0,0 +1,115 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SemiImplicitEuler.h +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +namespace walberla { +namespace mesa_pd { +namespace kernel { + +/** + * Semi-implicit Euler integration for position and velocity. + * + * This kernel requires the following particle accessor interface + * \code + * const walberla::mesa_pd::Vec3& getPosition(const size_t p_idx) const; + * void setPosition(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t p_idx) const; + * void setLinearVelocity(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::real_t& getInvMass(const size_t p_idx) const; + * + * const walberla::mesa_pd::Vec3& getForce(const size_t p_idx) const; + * void setForce(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::data::particle_flags::FlagT& getFlags(const size_t p_idx) const; + * + * const walberla::mesa_pd::Rot3& getRotation(const size_t p_idx) const; + * void setRotation(const size_t p_idx, const walberla::mesa_pd::Rot3& v); + * + * const walberla::mesa_pd::Vec3& getAngularVelocity(const size_t p_idx) const; + * void setAngularVelocity(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::Mat3& getInvInertiaBF(const size_t p_idx) const; + * + * const walberla::mesa_pd::Vec3& getTorque(const size_t p_idx) const; + * void setTorque(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * \endcode + * + * \pre All forces and torques acting on the particles have to be set. + * \post All forces and torques are reset to 0. + * \ingroup mesa_pd_kernel + */ +class SemiImplicitEuler +{ +public: + explicit SemiImplicitEuler(const real_t dt) : dt_(dt) {} + + template <typename Accessor> + void operator()(const size_t i, Accessor& ac) const; +private: + real_t dt_ = real_t(0.0); +}; + +template <typename Accessor> +inline void SemiImplicitEuler::operator()(const size_t idx, + Accessor& ac) const +{ + static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); + + if (!data::particle_flags::isSet( ac.getFlags(idx), data::particle_flags::FIXED)) + { + ac.setLinearVelocity( idx, ac.getInvMass(idx) * ac.getForce(idx) * dt_ + + ac.getLinearVelocity(idx)); + ac.setPosition ( idx, ac.getLinearVelocity(idx) * dt_ + + ac.getPosition(idx)); + const Vec3 wdot = math::transformMatrixRART(ac.getRotation(idx).getMatrix(), + ac.getInvInertiaBF(idx)) * ac.getTorque(idx); + + ac.setAngularVelocity(idx, wdot * dt_ + + ac.getAngularVelocity(idx)); + + // Calculating the rotation angle + const Vec3 phi( ac.getAngularVelocity(idx) * dt_ ); + + // Calculating the new orientation + auto rotation = ac.getRotation(idx); + rotation.rotate( phi ); + ac.setRotation(idx, rotation); + } + + ac.setForce (idx, Vec3(real_t(0), real_t(0), real_t(0))); + ac.setTorque(idx, Vec3(real_t(0), real_t(0), real_t(0))); +} + +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/kernel/VelocityVerlet.h b/src/mesa_pd/kernel/VelocityVerlet.h index f029652c2..69ed50dcb 100644 --- a/src/mesa_pd/kernel/VelocityVerlet.h +++ b/src/mesa_pd/kernel/VelocityVerlet.h @@ -41,6 +41,8 @@ namespace kernel { * integration is only complete when both functions are called. The integration * is symplectic. * + * Wachs, A. Particle-scale computational approaches to model dry and saturated granular flows of non-Brownian, non-cohesive, and non-spherical rigid bodies. Acta Mech 230, 1919–1980 (2019). https://doi.org/10.1007/s00707-019-02389-9 + * * This kernel requires the following particle accessor interface * \code * const walberla::mesa_pd::Vec3& getPosition(const size_t p_idx) const; diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 3742a2ef2..caf3ba275 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -128,6 +128,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_LinearSpringDashpot ) waLBerla_compile_test( NAME MESA_PD_Kernel_LinkedCellsVsBruteForce FILES kernel/LinkedCellsVsBruteForce.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_LinkedCellsVsBruteForce PROCESSES 27 ) +waLBerla_compile_test( NAME MESA_PD_Kernel_SemiImplicitEuler FILES kernel/SemiImplicitEuler.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_SemiImplicitEuler ) + waLBerla_compile_test( NAME MESA_PD_Kernel_SingleCast FILES kernel/SingleCast.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_SingleCast ) @@ -197,4 +200,4 @@ if (WALBERLA_MESAPD_CONVEX_POLYHEDRON_AVAILABLE) waLBerla_compile_test( NAME MESA_PD_COLLISIONDETECTION_ConvexPolyhedron_GJK_EPA FILES collision_detection/ConvexPolyhedron_GJK_EPA.cpp DEPENDS core mesa_pd mesh_common ) waLBerla_execute_test( NAME MESA_PD_COLLISIONDETECTION_ConvexPolyhedron_GJK_EPA ) -endif() \ No newline at end of file +endif() diff --git a/tests/mesa_pd/DropTestAnalytic.cpp b/tests/mesa_pd/DropTestAnalytic.cpp index 7c3c89ed0..3b257e23c 100644 --- a/tests/mesa_pd/DropTestAnalytic.cpp +++ b/tests/mesa_pd/DropTestAnalytic.cpp @@ -25,7 +25,7 @@ #include <mesa_pd/data/ShapeStorage.h> #include <mesa_pd/kernel/DoubleCast.h> -#include <mesa_pd/kernel/ExplicitEuler.h> +#include <mesa_pd/kernel/SemiImplicitEuler.h> #include <mesa_pd/kernel/ParticleSelector.h> #include <mesa_pd/kernel/SpringDashpot.h> @@ -102,7 +102,7 @@ int main( int argc, char ** argv ) real_t dt = real_t(0.00001); // Init kernels - kernel::ExplicitEuler explicitEuler( dt ); + kernel::SemiImplicitEuler implEuler( dt ); kernel::SpringDashpot dem(1); auto meff = real_t(1.0) / ss->shapes[sp->getShapeID()]->getInvMass(); dem.setParametersFromCOR(0,0,real_t(0.9), dt * real_t(20), meff); @@ -152,7 +152,7 @@ int main( int argc, char ** argv ) ps->forEachParticle(false, kernel::SelectLocal(), accessor, - explicitEuler, + implEuler, accessor); // if(i%1 == 0) diff --git a/tests/mesa_pd/DropTestGeneral.cpp b/tests/mesa_pd/DropTestGeneral.cpp index 3d668694c..0ab23c4fa 100644 --- a/tests/mesa_pd/DropTestGeneral.cpp +++ b/tests/mesa_pd/DropTestGeneral.cpp @@ -25,16 +25,14 @@ #include <mesa_pd/data/ShapeStorage.h> #include <mesa_pd/kernel/DoubleCast.h> -#include <mesa_pd/kernel/ExplicitEuler.h> +#include <mesa_pd/kernel/SemiImplicitEuler.h> #include <mesa_pd/kernel/ParticleSelector.h> #include <mesa_pd/kernel/SpringDashpot.h> #include <core/Abort.h> #include <core/Environment.h> #include <core/logging/Logging.h> -#include <core/waLBerlaBuildInfo.h> -#include <functional> #include <memory> #include <string> #include <type_traits> @@ -122,7 +120,7 @@ int main( int argc, char ** argv ) real_t dt = real_t(0.00001); // Init kernels - kernel::ExplicitEuler explicitEuler( dt ); + kernel::SemiImplicitEuler implEuler( dt ); kernel::SpringDashpot dem(1); auto meff = real_t(1.0) / ss->shapes[sp->getShapeID()]->getInvMass(); dem.setParametersFromCOR(0,0,real_t(0.9), dt * real_t(20), meff); @@ -172,7 +170,7 @@ int main( int argc, char ** argv ) ps->forEachParticle(false, kernel::SelectLocal(), accessor, - explicitEuler, + implEuler, accessor); // if(i%1 == 0) diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp index 7e316264f..ac16d145e 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DEMIntegratorAccuracy.cpp +//! \file CoefficientOfRestitutionLSD.cpp //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== @@ -26,7 +26,7 @@ #include "mesa_pd/kernel/DoubleCast.h" #include "mesa_pd/kernel/VelocityVerlet.h" -#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" #include "mesa_pd/kernel/LinearSpringDashpot.h" #include "core/Environment.h" @@ -136,7 +136,7 @@ int main( int argc, char** argv ) collision_detection::AnalyticContactDetection acd; kernel::DoubleCast double_cast; - kernel::ExplicitEuler explEuler(dt); + kernel::SemiImplicitEuler implEuler(dt); kernel::VelocityVerletPreForceUpdate vvPreForce( dt ); kernel::VelocityVerletPostForceUpdate vvPostForce( dt ); @@ -160,7 +160,7 @@ int main( int argc, char** argv ) auto force = accessor->getForce(0); if(useVelocityVerlet) vvPostForce(0,*accessor); - else explEuler(0, *accessor); + else implEuler(0, *accessor); WALBERLA_LOG_INFO(steps << ": penetration = " << acd.getPenetrationDepth() << " || vel = " << accessor->getLinearVelocity(0)[2] << " || force = " << force[2]); diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp index c422a70b4..c2bfbcfdb 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DEMIntegratorAccuracy.cpp +//! \file CoefficientOfRestitutionNLSD.cpp //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== @@ -26,7 +26,7 @@ #include "mesa_pd/kernel/DoubleCast.h" #include "mesa_pd/kernel/VelocityVerlet.h" -#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" #include "mesa_pd/kernel/NonLinearSpringDashpot.h" #include "mesa_pd/mpi/ReduceContactHistory.h" @@ -137,7 +137,7 @@ int main( int argc, char** argv ) collision_detection::AnalyticContactDetection acd; kernel::DoubleCast double_cast; - kernel::ExplicitEuler explEuler(dt); + kernel::SemiImplicitEuler implEuler(dt); kernel::VelocityVerletPreForceUpdate vvPreForce( dt ); kernel::VelocityVerletPostForceUpdate vvPostForce( dt ); @@ -162,7 +162,7 @@ int main( int argc, char** argv ) auto force = accessor->getForce(0); if(useVelocityVerlet) vvPostForce(0,*accessor); - else explEuler(0, *accessor); + else implEuler(0, *accessor); WALBERLA_LOG_INFO(steps << ": penetration = " << acd.getPenetrationDepth() << " || vel = " << accessor->getLinearVelocity(0)[2] << " || force = " << force[2]); diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp index 300e0eb91..910f5da3d 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DEMIntegratorAccuracy.cpp +//! \file CoefficientOfRestitutionSD.cpp //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== @@ -26,7 +26,7 @@ #include "mesa_pd/kernel/DoubleCast.h" #include "mesa_pd/kernel/VelocityVerlet.h" -#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" #include "mesa_pd/kernel/SpringDashpot.h" #include "core/Environment.h" @@ -136,7 +136,7 @@ int main( int argc, char** argv ) collision_detection::AnalyticContactDetection acd; kernel::DoubleCast double_cast; - kernel::ExplicitEuler explEuler(dt); + kernel::SemiImplicitEuler implEuler(dt); kernel::VelocityVerletPreForceUpdate vvPreForce( dt ); kernel::VelocityVerletPostForceUpdate vvPostForce( dt ); @@ -160,7 +160,7 @@ int main( int argc, char** argv ) auto force = accessor->getForce(0); if(useVelocityVerlet) vvPostForce(0,*accessor); - else explEuler(0, *accessor); + else implEuler(0, *accessor); WALBERLA_LOG_INFO(steps << ": penetration = " << acd.getPenetrationDepth() << " || vel = " << accessor->getLinearVelocity(0)[2] << " || force = " << force[2]); diff --git a/tests/mesa_pd/kernel/ExplicitEuler.cpp b/tests/mesa_pd/kernel/ExplicitEuler.cpp index 1685ff1ae..17d55505b 100644 --- a/tests/mesa_pd/kernel/ExplicitEuler.cpp +++ b/tests/mesa_pd/kernel/ExplicitEuler.cpp @@ -66,8 +66,10 @@ int main( int argc, char ** argv ) accessor.setAngularVelocity( 0, angVel); accessor.setForce( 0, force); accessor.setTorque( 0, torque); - accessor.setInvMass( 0, real_t(1.23456)); - accessor.setInvInertiaBF( 0, Mat3(real_t(1.23456), real_t(0), real_t(0), real_t(0), real_t(1.23456), real_t(0), real_t(0), real_t(0), real_t(1.23456))); + accessor.setInvMass( 0, 1.23456_r); + accessor.setInvInertiaBF( 0, Mat3(1.23456_r, 0_r, 0_r, + 0_r, 1.23456_r, 0_r, + 0_r, 0_r, 1.23456_r )); //init kernels const real_t dt = real_t(1); @@ -83,12 +85,16 @@ int main( int argc, char ** argv ) WALBERLA_CHECK_FLOAT_EQUAL(accessor.getTorque(0), Vec3(0)); //check velocity - WALBERLA_CHECK_FLOAT_EQUAL(accessor.getLinearVelocity(0), force * accessor.getInvMass(0) * dt + linVel); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getLinearVelocity(0), force * accessor.getInvMass(0) * dt + + linVel); WALBERLA_CHECK_FLOAT_EQUAL(accessor.getAngularVelocity(0), wdot * dt + angVel); //check position - WALBERLA_CHECK_FLOAT_EQUAL(accessor.getPosition(0), linVel * dt + force * accessor.getInvMass(0) * dt * dt); - WALBERLA_CHECK_FLOAT_EQUAL(accessor.getRotation(0).getQuaternion(), Quat( (wdot * dt + angVel).getNormalized(), (wdot * dt + angVel).length() * dt )); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getPosition(0), linVel * dt + + 0.5_r * force * accessor.getInvMass(0) * dt * dt); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getRotation(0).getQuaternion(), + Quat( (wdot * dt + angVel).getNormalized(), + (0.5_r * wdot * dt + angVel).length() * dt )); accessor.setPosition( 0, Vec3(0,0,0)); accessor.setRotation( 0, Rot3(Quat())); @@ -96,8 +102,10 @@ int main( int argc, char ** argv ) accessor.setAngularVelocity( 0, angVel); accessor.setForce( 0, force); accessor.setTorque( 0, torque); - accessor.setInvMass( 0, real_t(1.23456)); - accessor.setInvInertiaBF( 0, Mat3(real_t(1.23456), real_t(0), real_t(0), real_t(0), real_t(1.23456), real_t(0), real_t(0), real_t(0), real_t(1.23456))); + accessor.setInvMass( 0, 1.23456_r); + accessor.setInvInertiaBF( 0, Mat3(1.23456_r, 0_r, 0_r, + 0_r, 1.23456_r, 0_r, + 0_r, 0_r, 1.23456_r )); data::particle_flags::set( accessor.getFlagsRef(0), data::particle_flags::FIXED ); integrator(0, accessor); diff --git a/tests/mesa_pd/kernel/GenerateLinkedCells.cpp b/tests/mesa_pd/kernel/GenerateLinkedCells.cpp index e7a60f36e..d4c2f30c6 100644 --- a/tests/mesa_pd/kernel/GenerateLinkedCells.cpp +++ b/tests/mesa_pd/kernel/GenerateLinkedCells.cpp @@ -18,7 +18,7 @@ // //====================================================================================================================== -#include <mesa_pd/kernel/ExplicitEuler.h> +#include <mesa_pd/kernel/SemiImplicitEuler.h> #include <mesa_pd/kernel/ForceLJ.h> #include <mesa_pd/kernel/InsertParticleIntoLinkedCells.h> #include <mesa_pd/kernel/ParticleSelector.h> @@ -72,7 +72,7 @@ int main( int argc, char ** argv ) //init kernels kernel::InsertParticleIntoLinkedCells ipilc; kernel::ForceLJ lj(1); - kernel::ExplicitEuler integrator( real_t(0.01) ); + kernel::SemiImplicitEuler integrator( real_t(0.01) ); //timeloop for (auto timestep = 0; timestep < 100; ++timestep) diff --git a/tests/mesa_pd/kernel/IntegratorAccuracy.cpp b/tests/mesa_pd/kernel/IntegratorAccuracy.cpp index 695bae5b9..e97c47106 100644 --- a/tests/mesa_pd/kernel/IntegratorAccuracy.cpp +++ b/tests/mesa_pd/kernel/IntegratorAccuracy.cpp @@ -15,170 +15,252 @@ // //! \file IntegratorAccuracy.cpp //! \author Christoph Rettinger <christoph.rettinger@fau.de> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== -#include "mesa_pd/data/ParticleAccessorWithShape.h" -#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/ParticleAccessor.h" -#include "mesa_pd/kernel/ParticleSelector.h" -#include "mesa_pd/kernel/VelocityVerlet.h" #include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" +#include "mesa_pd/kernel/VelocityVerlet.h" #include "core/Environment.h" -#include "core/logging/Logging.h" #include "core/math/all.h" #include <iostream> -namespace integrator_accuracy -{ - -using namespace walberla; +namespace walberla { using namespace walberla::mesa_pd; - -Vec3 getForce(const Vec3& pos, real_t k) +class SingleParticleAccessorWithShape : public data::SingleParticleAccessor { - return -k * pos; -} +public: + void setInvMass(const size_t /*p_idx*/, const real_t &val) + { invMass_ = val; } -real_t analyticalTrajectory(real_t amplitude, real_t timeStep, real_t omega, real_t phase) -{ - return amplitude * std::cos(omega * timeStep + phase); -} + const auto &getInvMass(const size_t /*p_idx*/) const + { return invMass_; } -real_t analyticalVelocity(real_t amplitude, real_t timeStep, real_t omega, real_t phase) -{ - return -amplitude * omega * std::sin(omega * timeStep + phase); -} + void setInvInertiaBF(const size_t /*p_idx*/, const Mat3 &val) + { invInertiaBF_ = val; } + const auto &getInvInertiaBF(const size_t /*p_idx*/) const + { return invInertiaBF_; } -/* - * Simulates a harmonic oscillator to test the accuracy of the integrators. - * The error of the maximum position and the maximum velocity is compared against the analytical values. - * Via command line arguments, the simulation can be adapted. - * Currently tested integrators: - * - explicit Euler (default) - * - velocity verlet (-useVV) - */ -int main( int argc, char ** argv ) -{ - mpi::Environment env(argc, argv); - WALBERLA_UNUSED(env); - mpi::MPIManager::instance()->useWorldComm(); +private: + real_t invMass_; + Mat3 invInertiaBF_; +}; - real_t amplitude = real_t(1.5); - real_t k = real_t(0.1); - real_t mass = real_t(0.9); - real_t dt = real_t(0.2); - bool useVelocityVerlet = false; - real_t phaseFraction = real_t(0); - real_t periods = real_t(1.1); +struct Oscillator +{ + real_t amplitude = 1.5_r; + real_t k = 0.1_r; + real_t damping = 0_r; + real_t mass = 0.9_r; + real_t dt = 0.2_r; + real_t phaseFraction = 0_r; + real_t periods = 10_r; + real_t phase = phaseFraction * math::pi; + real_t dampingRatio = damping / (2_r * std::sqrt(mass * k)); + real_t omega = std::sqrt(k / mass) * std::sqrt(1_r - dampingRatio * dampingRatio); + real_t decay = std::sqrt(k / mass) * dampingRatio; + real_t durationOnePeriod = 2_r * math::pi / omega; + uint_t timeSteps = uint_c(periods * durationOnePeriod / dt); - for( int i = 1; i < argc; ++i ) + void update() { - if( std::strcmp( argv[i], "--useVV" ) == 0 ) { useVelocityVerlet = true; continue; } - if( std::strcmp( argv[i], "--dt" ) == 0 ) { dt = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--amplitude" ) == 0 ) { amplitude = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--k" ) == 0 ) { k = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--mass" ) == 0 ) { mass = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--phaseFraction" ) == 0 ) { phaseFraction = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--periods" ) == 0 ) { periods = real_c(std::atof( argv[++i] )); continue; } - WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); + phase = phaseFraction * math::pi; + dampingRatio = damping / (2_r * std::sqrt(mass * k)); + omega = std::sqrt(k / mass) * std::sqrt(1_r - dampingRatio * dampingRatio); + decay = std::sqrt(k / mass) * dampingRatio; + durationOnePeriod = 2_r * math::pi / omega; + timeSteps = uint_c(periods * durationOnePeriod / dt); } + Vec3 getForce(const Vec3 &pos, const Vec3 &vel) const + { + return -k * pos - damping * vel; + } - real_t phase = phaseFraction * math::pi; - real_t omega = std::sqrt(k / mass); - real_t durationOnePeriod = real_t(2) * math::pi / omega; - uint_t timeSteps = uint_c(periods * durationOnePeriod / dt); + real_t getEnergy(const real_t &pos, const real_t &vel) const + { + return 0.5_r * mass * vel * vel + 0.5_r * k * pos * pos; + } - WALBERLA_LOG_INFO("omega = " << omega << ", T = " << real_t(2) * math::pi / omega << ", time steps = " << timeSteps << ", phase = " << phase << ", periods = " << periods); + real_t analyticalPos(real_t t) const + { + return amplitude * std::exp(-decay * t) * std::cos(omega * t + phase); + } - //initialize particle - const auto pos = Vec3(0,0,analyticalTrajectory(amplitude, real_t(0), omega, phase)); - const auto linVel = Vec3(0,0,analyticalVelocity(amplitude, real_t(0), omega, phase)); + real_t analyticalVel(real_t t) const + { + return -decay * amplitude * std::exp(-decay * t) * std::cos(omega * t + phase) + -amplitude * std::exp(-decay * t) * omega * std::sin(omega * t + phase); + } +}; - WALBERLA_LOG_INFO("Initial pos = " << pos << ", vel = " << linVel); +struct ExplicitEuler +{ + ExplicitEuler(real_t dt) : integrator(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) + { + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + integrator(0, particle); + } + kernel::ExplicitEuler integrator; +}; - //init data structures - auto ps = std::make_shared<data::ParticleStorage>(1); - auto ss = std::make_shared<data::ShapeStorage>(); - auto smallSphere = ss->create<data::Sphere>( real_t(1) ); - ss->shapes[smallSphere]->updateMassAndInertia(real_t(2707)); - data::ParticleAccessorWithShape accessor(ps, ss); - - data::Particle&& p = *ps->create(); - p.setPosition(pos); - p.setLinearVelocity(linVel); - p.setForce(getForce(pos, k)); - p.setOldForce(getForce(pos, k)); - p.setInvMass(real_t(1) / mass); - p.setShapeID(smallSphere); - - // velocity verlet - kernel::VelocityVerletPreForceUpdate preForce( dt ); - kernel::VelocityVerletPostForceUpdate postForce( dt ); +struct SemiImplicitEuler +{ + SemiImplicitEuler(real_t dt) : integrator(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) + { + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + integrator(0, particle); + } + kernel::SemiImplicitEuler integrator; +}; - // explicit euler - kernel::ExplicitEuler explEuler( dt ); - - real_t maxVel = 0.; - real_t maxRefVel = 0.; - real_t maxPos = 0.; - real_t maxRefPos = 0.; - - for (auto i = uint_t(1); i <= timeSteps; ++i) +struct VelocityVerlet +{ + VelocityVerlet(real_t dt) : preVV(dt), postVV(dt) {} + void operator()(SingleParticleAccessorWithShape& particle, + const Oscillator& osc) { + preVV(0, particle); + particle.setForce(0, osc.getForce(particle.getPosition(0), + particle.getLinearVelocity(0))); + postVV(0, particle); + } + kernel::VelocityVerletPreForceUpdate preVV; + kernel::VelocityVerletPostForceUpdate postVV; +}; - if( useVelocityVerlet ) ps->forEachParticle(false, kernel::SelectAll(), accessor, preForce, accessor); - p.setForce( getForce(p.getPosition(), k) ); - auto force = p.getForce(); +struct AccuracyResult +{ + real_t maxPosDeviation; + real_t maxVelDeviation; + real_t maxEneDeviation; +}; - if( useVelocityVerlet ) ps->forEachParticle(false, kernel::SelectAll(), accessor, postForce, accessor); - else ps->forEachParticle(false, kernel::SelectAll(), accessor, explEuler, accessor); +template <typename Integrator> +AccuracyResult checkIntegrator(const Oscillator& osc) +{ + //init data structures + SingleParticleAccessorWithShape particle; - real_t refPos = analyticalTrajectory(amplitude, real_c(i) * dt, omega, phase); - real_t refVel = analyticalVelocity(amplitude, real_c(i) * dt, omega, phase); + //first dummy argument is needed to fulfill accessor interface + particle.setPosition(0, Vec3(0, 0, osc.analyticalPos(0_r))); + particle.setLinearVelocity(0, Vec3(0, 0, osc.analyticalVel(0_r))); + particle.setInvMass(0, 1_r / osc.mass); + particle.setForce(0, osc.getForce(Vec3(0, 0, osc.analyticalPos(real_t(0))), + Vec3(0, 0, osc.analyticalVel(real_t(0))))); + particle.setOldForce(0, osc.getForce(Vec3(0, 0, osc.analyticalPos(-osc.dt)), + Vec3(0, 0, osc.analyticalVel(-osc.dt)))); - WALBERLA_LOG_INFO(i << ": pos = " << p.getPosition()[2] << " " << refPos - << " || vel = " << p.getLinearVelocity()[2] << " " << refVel - << " || force = " << force[2] ); + // explicit euler + Integrator integrator(osc.dt); - maxPos = std::max(maxPos, std::abs(p.getPosition()[2])); - maxRefPos = std::max(maxRefPos, std::abs(refPos)); + real_t maxPosDeviation = 0_r; + real_t maxVelDeviation = 0_r; + real_t maxEneDeviation = 0_r; - maxVel = std::max(maxVel, std::abs(p.getLinearVelocity()[2])); - maxRefVel = std::max(maxRefVel, std::abs(refVel)); + for (auto i = uint_t(0); i <= osc.timeSteps; ++i) + { + real_t refPos = osc.analyticalPos(real_c(i) * osc.dt); + real_t refVel = osc.analyticalVel(real_c(i) * osc.dt); + real_t refEne = osc.getEnergy(refPos, refVel); + + maxPosDeviation = std::max(maxPosDeviation, std::abs(particle.getPosition(0)[2] - refPos)); + maxVelDeviation = std::max(maxVelDeviation, std::abs(particle.getLinearVelocity(0)[2] - refVel)); + maxEneDeviation = std::max(maxEneDeviation, std::abs(osc.getEnergy(particle.getPosition(0)[2], particle.getLinearVelocity(0)[2]) - refEne)); + + integrator(particle, osc); } - real_t relativePositionError = ( maxPos - maxRefPos ) / maxRefPos; - WALBERLA_LOG_INFO("error in position = " << relativePositionError * 100. << "%"); + return {maxPosDeviation, maxVelDeviation, maxEneDeviation}; +} - real_t relativeVelocityError = ( maxVel - maxRefVel ) / maxRefVel; - WALBERLA_LOG_INFO("error in velocity = " << relativeVelocityError * 100. << "%"); +int main(int argc, char **argv) +{ + mpi::Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); - if( useVelocityVerlet ) - { - WALBERLA_CHECK_LESS(relativePositionError, real_t(0.01), "Error in position too large!"); - WALBERLA_CHECK_LESS(relativeVelocityError, real_t(0.01), "Error in velocity too large!"); - } - else + if (std::is_same<real_t, float>::value) { - WALBERLA_CHECK_LESS(relativePositionError, real_t(0.11), "Error in position too large!"); - WALBERLA_CHECK_LESS(relativeVelocityError, real_t(0.10), "Error in velocity too large!"); + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; } + Oscillator osc; + + AccuracyResult res; + osc.dt = 0.1_r; + osc.update(); + res = walberla::checkIntegrator<walberla::ExplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 1.03068993874562120e+00_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 3.33225581358688350e-01_r); + res = walberla::checkIntegrator<walberla::SemiImplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 2.92576360173544339e-02_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 1.45120298258364505e-03_r); + res = walberla::checkIntegrator<walberla::VelocityVerlet>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 4.24116598691555435e-03_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 1.45059589844465098e-03_r); + + osc.dt = 0.2_r; + osc.update(); + res = walberla::checkIntegrator<walberla::ExplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 2.76387000209972467e+00_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 8.88433661185269896e-01_r); + res = walberla::checkIntegrator<walberla::SemiImplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 6.70464626869100577e-02_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 5.81009940233766925e-03_r); + res = walberla::checkIntegrator<walberla::VelocityVerlet>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 1.69147419522671719e-02_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 5.78432113979018836e-03_r); + + osc.dt = 0.4_r; + osc.update(); + res = walberla::checkIntegrator<walberla::ExplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 1.04680753378045406e+01_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 3.34470580215144420e+00_r); + res = walberla::checkIntegrator<walberla::SemiImplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 1.68291142727994780e-01_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 2.33193930919295134e-02_r); + res = walberla::checkIntegrator<walberla::VelocityVerlet>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxPosDeviation, 6.71909796751584687e-02_r); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxVelDeviation, 2.29906986019860066e-02_r); + + //check energy conservation + osc.dt = 0.4_r; + osc.periods = 1000; + osc.update(); + //res = walberla::checkIntegrator<walberla::ExplicitEuler>(osc); + //explicit euler is not symplectic + res = walberla::checkIntegrator<walberla::SemiImplicitEuler>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxEneDeviation, 8.03571427989904774e-03_r); + res = walberla::checkIntegrator<walberla::VelocityVerlet>(osc); + WALBERLA_CHECK_FLOAT_EQUAL( res.maxEneDeviation, 4.99960610503419334e-04_r); return EXIT_SUCCESS; } -} //namespace integrator_accuracy +} //namespace walberla + -int main( int argc, char ** argv ) +/* + * Simulates a harmonic oscillator to test the accuracy of the integrators. + */ +int main(int argc, char **argv) { - return integrator_accuracy::main(argc, argv); + return walberla::main(argc, argv); } diff --git a/tests/mesa_pd/kernel/LinearSpringDashpot.cpp b/tests/mesa_pd/kernel/LinearSpringDashpot.cpp index 18beb0732..64f099e26 100644 --- a/tests/mesa_pd/kernel/LinearSpringDashpot.cpp +++ b/tests/mesa_pd/kernel/LinearSpringDashpot.cpp @@ -26,7 +26,7 @@ #include "mesa_pd/data/ShapeStorage.h" #include "mesa_pd/kernel/DoubleCast.h" -#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" #include "mesa_pd/kernel/VelocityVerlet.h" #include "mesa_pd/kernel/LinearSpringDashpot.h" #include "mesa_pd/mpi/ReduceContactHistory.h" @@ -152,7 +152,7 @@ int main( int argc, char ** argv ) kernel::VelocityVerletPostForceUpdate vvPostForce( dt ); // explicit euler - kernel::ExplicitEuler explEuler( dt ); + kernel::SemiImplicitEuler implEuler( dt ); // collision response collision_detection::AnalyticContactDetection acd; @@ -188,7 +188,7 @@ int main( int argc, char ** argv ) rch(*ps); if(useVelocityVerlet) vvPostForce(0,*accessor); - else explEuler(0, *accessor); + else implEuler(0, *accessor); ++steps; } while (double_cast(0, 1, *accessor, acd, *accessor ) || p.getLinearVelocity()[2] < 0); diff --git a/tests/mesa_pd/kernel/SemiImplicitEuler.cpp b/tests/mesa_pd/kernel/SemiImplicitEuler.cpp new file mode 100644 index 000000000..2d3a22f84 --- /dev/null +++ b/tests/mesa_pd/kernel/SemiImplicitEuler.cpp @@ -0,0 +1,133 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SemiImplicitEuler.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/ParticleAccessor.h> + +#include <mesa_pd/kernel/SemiImplicitEuler.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { + +using namespace walberla::mesa_pd; + +class SingleParticleAccessor : public data::SingleParticleAccessor +{ +public: + const walberla::real_t& getInvMass(const size_t /*p_idx*/) const {return invMass_;} + void setInvMass(const size_t /*p_idx*/, const walberla::real_t& v) { invMass_ = v;} + const walberla::mesa_pd::Mat3& getInvInertiaBF(const size_t /*p_idx*/) const {return invInertiaBF_;} + void setInvInertiaBF(const size_t /*p_idx*/, const walberla::mesa_pd::Mat3& v) { invInertiaBF_ = v;} + + walberla::real_t invMass_; + walberla::mesa_pd::Mat3 invInertiaBF_; +}; + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + //init data structures + SingleParticleAccessor accessor; + + //initialize particle + const auto linVel = Vec3(1,2,3); + const auto angVel = Vec3(1,2,3); + + const auto force = Vec3(1,2,3); + const auto torque = Vec3(1,2,3); + + accessor.setPosition( 0, Vec3(0,0,0)); + accessor.setRotation( 0, Rot3(Quat())); + accessor.setLinearVelocity( 0, linVel); + accessor.setAngularVelocity( 0, angVel); + accessor.setForce( 0, force); + accessor.setTorque( 0, torque); + accessor.setInvMass( 0, 1.23456_r); + accessor.setInvInertiaBF( 0, Mat3(1.23456_r, 0_r, 0_r, + 0_r, 1.23456_r, 0_r, + 0_r, 0_r, 1.23456_r )); + + //init kernels + const real_t dt = real_t(1); + kernel::SemiImplicitEuler integrator( dt ); + + integrator(0, accessor); + + const auto& R = accessor.getRotation(0).getMatrix(); + const auto wdot = R * accessor.getInvInertiaBF(0) * R.getTranspose() * torque; + + //check force + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getForce(0), Vec3(0)); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getTorque(0), Vec3(0)); + + //check velocity + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getLinearVelocity(0), force * accessor.getInvMass(0) * dt + + linVel); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getAngularVelocity(0), wdot * dt + angVel); + + //check position + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getPosition(0), linVel * dt + + force * accessor.getInvMass(0) * dt * dt); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getRotation(0).getQuaternion(), + Quat( (wdot * dt + angVel).getNormalized(), + (wdot * dt + angVel).length() * dt )); + + accessor.setPosition( 0, Vec3(0,0,0)); + accessor.setRotation( 0, Rot3(Quat())); + accessor.setLinearVelocity( 0, linVel); + accessor.setAngularVelocity( 0, angVel); + accessor.setForce( 0, force); + accessor.setTorque( 0, torque); + accessor.setInvMass( 0, 1.23456_r); + accessor.setInvInertiaBF( 0, Mat3(1.23456_r, 0_r, 0_r, + 0_r, 1.23456_r, 0_r, + 0_r, 0_r, 1.23456_r )); + data::particle_flags::set( accessor.getFlagsRef(0), data::particle_flags::FIXED ); + + integrator(0, accessor); + + //check force + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getForce(0), Vec3(0)); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getTorque(0), Vec3(0)); + + //check velocity + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getLinearVelocity(0), linVel); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getAngularVelocity(0), angVel); + + //check position + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getPosition(0), Vec3(0,0,0)); + WALBERLA_CHECK_FLOAT_EQUAL(accessor.getRotation(0).getQuaternion(), Quat()); + + return EXIT_SUCCESS; +} + +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::main(argc, argv); +} diff --git a/tests/mesa_pd/kernel/SpherePile.cpp b/tests/mesa_pd/kernel/SpherePile.cpp index 67e1087a7..3f71e9297 100644 --- a/tests/mesa_pd/kernel/SpherePile.cpp +++ b/tests/mesa_pd/kernel/SpherePile.cpp @@ -26,7 +26,7 @@ #include "mesa_pd/data/ShapeStorage.h" #include "mesa_pd/kernel/DoubleCast.h" -#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/SemiImplicitEuler.h" #include "mesa_pd/kernel/SpringDashpot.h" #include "mesa_pd/kernel/SpringDashpotSpring.h" #include "mesa_pd/mpi/ReduceContactHistory.h" @@ -98,7 +98,7 @@ int main(int argc, char **argv) false); // explicit euler - kernel::ExplicitEuler explEuler(dt); + kernel::SemiImplicitEuler implEuler(dt); collision_detection::AnalyticContactDetection acd; kernel::DoubleCast double_cast; kernel::SpringDashpot sd(1); @@ -147,7 +147,7 @@ int main(int argc, char **argv) ps->forEachParticle(false, kernel::SelectLocal(), *ac, - explEuler, + implEuler, *ac); } WALBERLA_LOG_DEVEL_VAR(sp->getPosition()); @@ -193,7 +193,7 @@ int main(int argc, char **argv) ps->forEachParticle(false, kernel::SelectLocal(), *ac, - explEuler, + implEuler, *ac); } WALBERLA_LOG_DEVEL_VAR(sp->getPosition()); diff --git a/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp new file mode 100644 index 000000000..ad498f1d9 --- /dev/null +++ b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp @@ -0,0 +1,90 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file SemiImplicitEulerInterfaceCheck.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include <mesa_pd/data/IAccessor.h> +#include <mesa_pd/kernel/SemiImplicitEuler.h> + +#include <core/UniqueID.h> + +#include <map> + +namespace walberla { +namespace mesa_pd { + +class Accessor : public data::IAccessor +{ +public: + virtual ~Accessor() = default; + const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} + void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} + + const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t /*p_idx*/) const {return linearVelocity_;} + void setLinearVelocity(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { linearVelocity_ = v;} + + const walberla::real_t& getInvMass(const size_t /*p_idx*/) const {return invMass_;} + + const walberla::mesa_pd::Vec3& getForce(const size_t /*p_idx*/) const {return force_;} + void setForce(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { force_ = v;} + + const walberla::mesa_pd::data::particle_flags::FlagT& getFlags(const size_t /*p_idx*/) const {return flags_;} + + const walberla::mesa_pd::Rot3& getRotation(const size_t /*p_idx*/) const {return rotation_;} + void setRotation(const size_t /*p_idx*/, const walberla::mesa_pd::Rot3& v) { rotation_ = v;} + + const walberla::mesa_pd::Vec3& getAngularVelocity(const size_t /*p_idx*/) const {return angularVelocity_;} + void setAngularVelocity(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { angularVelocity_ = v;} + + const walberla::mesa_pd::Mat3& getInvInertiaBF(const size_t /*p_idx*/) const {return invInertiaBF_;} + + const walberla::mesa_pd::Vec3& getTorque(const size_t /*p_idx*/) const {return torque_;} + void setTorque(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { torque_ = v;} + + + id_t getInvalidUid() const {return UniqueID<int>::invalidID();} + size_t getInvalidIdx() const {return std::numeric_limits<size_t>::max();} + /** + * @brief Returns the index of particle specified by uid. + * @param uid unique id of the particle to be looked up + * @return the index of the particle or std::numeric_limits<size_t>::max() if the particle is not found + */ + size_t uidToIdx(const id_t& /*uid*/) const {return 0;} + size_t size() const { return 1; } +private: + walberla::mesa_pd::Vec3 position_; + walberla::mesa_pd::Vec3 linearVelocity_; + walberla::real_t invMass_; + walberla::mesa_pd::Vec3 force_; + walberla::mesa_pd::data::particle_flags::FlagT flags_; + walberla::mesa_pd::Rot3 rotation_; + walberla::mesa_pd::Vec3 angularVelocity_; + walberla::mesa_pd::Mat3 invInertiaBF_; + walberla::mesa_pd::Vec3 torque_; +}; + + + +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file -- GitLab From 83b31025227e4c2bccbbc35abb1f68a47c926285 Mon Sep 17 00:00:00 2001 From: Christoph Schwarzmeier <christoph.schwarzmeier@fau.de> Date: Thu, 10 Dec 2020 09:48:44 +0100 Subject: [PATCH 10/83] Exclude FluctuatingMRT test when using OPTIMIZE_FOR_LOCALHOST --- tests/lbm/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/lbm/CMakeLists.txt b/tests/lbm/CMakeLists.txt index b17f65cfa..ff0f7ef48 100644 --- a/tests/lbm/CMakeLists.txt +++ b/tests/lbm/CMakeLists.txt @@ -84,9 +84,12 @@ waLBerla_generate_target_from_python(NAME LbCodeGenerationExampleGenerated LbCodeGenerationExample_UBB.cpp LbCodeGenerationExample_UBB.h ) waLBerla_compile_test( FILES codegen/LbCodeGenerationExample.cpp DEPENDS LbCodeGenerationExampleGenerated) +# FluctuatingMRT test does not work with WALBERLA_OPTIMIZE_FOR_LOCALHOST since the random number generator is not implemented with SIMD +if ( NOT WALBERLA_OPTIMIZE_FOR_LOCALHOST ) waLBerla_generate_target_from_python(NAME FluctuatingMRTGenerated FILE codegen/FluctuatingMRT.py OUT_FILES FluctuatingMRT_LatticeModel.cpp FluctuatingMRT_LatticeModel.h ) waLBerla_compile_test( FILES codegen/FluctuatingMRT.cpp DEPENDS FluctuatingMRTGenerated) +endif() waLBerla_generate_target_from_python(NAME FieldLayoutAndVectorizationTestGenerated FILE codegen/FieldLayoutAndVectorizationTest.py OUT_FILES FieldLayoutAndVectorizationTest_FZYX_Vec_LatticeModel.cpp FieldLayoutAndVectorizationTest_FZYX_Vec_LatticeModel.h @@ -95,4 +98,4 @@ waLBerla_generate_target_from_python(NAME FieldLayoutAndVectorizationTestGenerat FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.cpp FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.h ) waLBerla_compile_test( FILES codegen/FieldLayoutAndVectorizationTest.cpp DEPENDS FieldLayoutAndVectorizationTestGenerated) -endif() \ No newline at end of file +endif() -- GitLab From e562fd7979e5f41163be4faf1bea92776d58a06d Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 4 Dec 2020 16:29:26 +0100 Subject: [PATCH 11/83] [ADD] PFCDamping kernel to mesa_pd --- python/mesa_pd.py | 1 + python/mesa_pd/kernel/PFCDamping.py | 30 ++++++ python/mesa_pd/kernel/__init__.py | 2 + .../templates/kernel/PFCDamping.templ.h | 90 ++++++++++++++++++ src/mesa_pd/kernel/PFCDamping.h | 92 +++++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + tests/mesa_pd/kernel/PFCDamping.cpp | 64 +++++++++++++ .../interfaces/PFCDampingInterfaceCheck.cpp | 76 +++++++++++++++ 8 files changed, 358 insertions(+) create mode 100644 python/mesa_pd/kernel/PFCDamping.py create mode 100644 python/mesa_pd/templates/kernel/PFCDamping.templ.h create mode 100644 src/mesa_pd/kernel/PFCDamping.h create mode 100644 tests/mesa_pd/kernel/PFCDamping.cpp create mode 100644 tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp diff --git a/python/mesa_pd.py b/python/mesa_pd.py index 0d94b5a92..d3e062a4f 100755 --- a/python/mesa_pd.py +++ b/python/mesa_pd.py @@ -103,6 +103,7 @@ if __name__ == '__main__': mpd.add(kernel.InsertParticleIntoSparseLinkedCells()) mpd.add(kernel.LinearSpringDashpot()) mpd.add(kernel.NonLinearSpringDashpot()) + mpd.add(kernel.PFCDamping()) mpd.add(kernel.SemiImplicitEuler()) mpd.add(kernel.SingleCast(ps)) mpd.add(kernel.SpringDashpot()) diff --git a/python/mesa_pd/kernel/PFCDamping.py b/python/mesa_pd/kernel/PFCDamping.py new file mode 100644 index 000000000..c3faf5e98 --- /dev/null +++ b/python/mesa_pd/kernel/PFCDamping.py @@ -0,0 +1,30 @@ +# -*- coding: utf-8 -*- + +from mesa_pd.accessor import create_access +from mesa_pd.utility import generate_file + + +class PFCDamping: + def __init__(self, integrate_rotation=True): + self.context = {'bIntegrateRotation': integrate_rotation, + 'interface': [ + create_access("linearVelocity", "walberla::mesa_pd::Vec3", access="gs"), + create_access("force", "walberla::mesa_pd::Vec3", access="gs"), + create_access("flags", "walberla::mesa_pd::data::particle_flags::FlagT", access="g") + ] + } + + if integrate_rotation: + self.context['interface'].append(create_access("angularVelocity", "walberla::mesa_pd::Vec3", access="gs")) + self.context['interface'].append(create_access("torque", "walberla::mesa_pd::Vec3", access="gs")) + + def generate(self, module): + ctx = {'module': module, **self.context} + generate_file(module['module_path'], 'kernel/PFCDamping.templ.h', ctx) + + ctx["InterfaceTestName"] = "PFCDampingInterfaceCheck" + ctx["KernelInclude"] = "kernel/PFCDamping.h" + ctx["ExplicitInstantiation"] = \ + "template void kernel::PFCDamping::operator()(const size_t p_idx1, Accessor& ac) const;" + generate_file(module['test_path'], 'tests/CheckInterface.templ.cpp', ctx, + 'kernel/interfaces/PFCDampingInterfaceCheck.cpp') diff --git a/python/mesa_pd/kernel/__init__.py b/python/mesa_pd/kernel/__init__.py index 4a639693b..fda6d3c46 100644 --- a/python/mesa_pd/kernel/__init__.py +++ b/python/mesa_pd/kernel/__init__.py @@ -12,6 +12,7 @@ from .InsertParticleIntoLinkedCells import InsertParticleIntoLinkedCells from .InsertParticleIntoSparseLinkedCells import InsertParticleIntoSparseLinkedCells from .LinearSpringDashpot import LinearSpringDashpot from .NonLinearSpringDashpot import NonLinearSpringDashpot +from .PFCDamping import PFCDamping from .SemiImplicitEuler import SemiImplicitEuler from .SingleCast import SingleCast from .SpringDashpot import SpringDashpot @@ -32,6 +33,7 @@ __all__ = ['DoubleCast', 'InsertParticleIntoSparseLinkedCells', 'LinearSpringDashpot', 'NonLinearSpringDashpot', + 'PFCDamping', 'SemiImplicitEuler', 'SingleCast', 'SpringDashpot', diff --git a/python/mesa_pd/templates/kernel/PFCDamping.templ.h b/python/mesa_pd/templates/kernel/PFCDamping.templ.h new file mode 100644 index 000000000..7dfc8ae0c --- /dev/null +++ b/python/mesa_pd/templates/kernel/PFCDamping.templ.h @@ -0,0 +1,90 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PFCDamping.h +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov, <drozd013@umn.edu> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +namespace walberla { +namespace mesa_pd { +namespace kernel { + +/** + * PFC style damping + * + * This kernel requires the following particle accessor interface + * \code + {%- for prop in interface %} + {%- if 'g' in prop.access %} + * const {{prop.type}}& get{{prop.name | capFirst}}(const size_t p_idx) const; + {%- endif %} + {%- if 's' in prop.access %} + * void set{{prop.name | capFirst}}(const size_t p_idx, const {{prop.type}}& v); + {%- endif %} + {%- if 'r' in prop.access %} + * {{prop.type}}& get{{prop.name | capFirst}}Ref(const size_t p_idx); + {%- endif %} + * + {%- endfor %} + * \endcode + * + * \ingroup mesa_pd_kernel + */ +class PFCDamping +{ +public: + PFCDamping(const real_t alpha) : alpha_(alpha) {} + + template <typename Accessor> + void operator()(const size_t p_idx, Accessor& ac) const; +private: + real_t alpha_ = 0_r; +}; + +template <typename Accessor> +inline void PFCDamping::operator()(const size_t p_idx, + Accessor& ac) const +{ + static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); + + Vec3 damp_F(0,0,0); + Vec3 damp_M(0,0,0); + + for (size_t i = 0; i < 3; i++) + { + damp_F[i] = - alpha_ * std::fabs( ac.getForce(p_idx)[i] ) * math::sign( ac.getLinearVelocity(p_idx)[i] ); + damp_M[i] = - alpha_ * std::fabs( ac.getTorque(p_idx)[i] ) * math::sign( ac.getAngularVelocity(p_idx)[i] ); + } + + ac.setForce (p_idx, ac.getForce(p_idx) + damp_F); + ac.setTorque(p_idx, ac.getTorque(p_idx) + damp_M); +} + +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla diff --git a/src/mesa_pd/kernel/PFCDamping.h b/src/mesa_pd/kernel/PFCDamping.h new file mode 100644 index 000000000..386df1229 --- /dev/null +++ b/src/mesa_pd/kernel/PFCDamping.h @@ -0,0 +1,92 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PFCDamping.h +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov, <drozd013@umn.edu> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +namespace walberla { +namespace mesa_pd { +namespace kernel { + +/** + * PFC style damping + * + * This kernel requires the following particle accessor interface + * \code + * const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t p_idx) const; + * void setLinearVelocity(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::Vec3& getForce(const size_t p_idx) const; + * void setForce(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::data::particle_flags::FlagT& getFlags(const size_t p_idx) const; + * + * const walberla::mesa_pd::Vec3& getAngularVelocity(const size_t p_idx) const; + * void setAngularVelocity(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * const walberla::mesa_pd::Vec3& getTorque(const size_t p_idx) const; + * void setTorque(const size_t p_idx, const walberla::mesa_pd::Vec3& v); + * + * \endcode + * + * \ingroup mesa_pd_kernel + */ +class PFCDamping +{ +public: + PFCDamping(const real_t alpha) : alpha_(alpha) {} + + template <typename Accessor> + void operator()(const size_t p_idx, Accessor& ac) const; +private: + real_t alpha_ = 0_r; +}; + +template <typename Accessor> +inline void PFCDamping::operator()(const size_t p_idx, + Accessor& ac) const +{ + static_assert(std::is_base_of<data::IAccessor, Accessor>::value, "please provide a valid accessor"); + + Vec3 damp_F(0,0,0); + Vec3 damp_M(0,0,0); + + for (size_t i = 0; i < 3; i++) + { + damp_F[i] = - alpha_ * std::fabs( ac.getForce(p_idx)[i] ) * math::sign( ac.getLinearVelocity(p_idx)[i] ); + damp_M[i] = - alpha_ * std::fabs( ac.getTorque(p_idx)[i] ) * math::sign( ac.getAngularVelocity(p_idx)[i] ); + } + + ac.setForce (p_idx, ac.getForce(p_idx) + damp_F); + ac.setTorque(p_idx, ac.getTorque(p_idx) + damp_M); +} + +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index caf3ba275..ad034a098 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -128,6 +128,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_LinearSpringDashpot ) waLBerla_compile_test( NAME MESA_PD_Kernel_LinkedCellsVsBruteForce FILES kernel/LinkedCellsVsBruteForce.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_LinkedCellsVsBruteForce PROCESSES 27 ) +waLBerla_compile_test( NAME MESA_PD_Kernel_PFCDamping FILES kernel/PFCDamping.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_PFCDamping ) + waLBerla_compile_test( NAME MESA_PD_Kernel_SemiImplicitEuler FILES kernel/SemiImplicitEuler.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_SemiImplicitEuler ) diff --git a/tests/mesa_pd/kernel/PFCDamping.cpp b/tests/mesa_pd/kernel/PFCDamping.cpp new file mode 100644 index 000000000..0329ef911 --- /dev/null +++ b/tests/mesa_pd/kernel/PFCDamping.cpp @@ -0,0 +1,64 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PFCDamping.cpp +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +// +//====================================================================================================================== + +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/ParticleAccessor.h> + +#include <mesa_pd/kernel/PFCDamping.h> + +#include <core/Environment.h> + +namespace walberla { + +using namespace walberla::mesa_pd; + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + //init data structures + data::SingleParticleAccessor ac; + + ac.setLinearVelocity( 0, Vec3(+2_r,-2_r,+2_r) ); + ac.setForce ( 0, Vec3(+2_r,+3_r,-4_r) ); + + ac.setAngularVelocity( 0, Vec3(+2_r,-2_r,+2_r) ); + ac.setTorque ( 0, Vec3(+3_r,+5_r,-2_r) ); + + //init kernels + kernel::PFCDamping damping( 0.1_r ); + + damping(0, ac); + + WALBERLA_CHECK_FLOAT_EQUAL(ac.getForce(0), Vec3(1.8_r, 3.3_r, -4.4_r)); + WALBERLA_CHECK_FLOAT_EQUAL(ac.getTorque(0), Vec3(2.7_r, 5.5_r, -2.2_r)); + + return EXIT_SUCCESS; +} + +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::main(argc, argv); +} diff --git a/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp new file mode 100644 index 000000000..3f52ab357 --- /dev/null +++ b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp @@ -0,0 +1,76 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file PFCDampingInterfaceCheck.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#include <mesa_pd/data/IAccessor.h> +#include <mesa_pd/kernel/PFCDamping.h> + +#include <core/UniqueID.h> + +#include <map> + +namespace walberla { +namespace mesa_pd { + +class Accessor : public data::IAccessor +{ +public: + virtual ~Accessor() = default; + const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t /*p_idx*/) const {return linearVelocity_;} + void setLinearVelocity(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { linearVelocity_ = v;} + + const walberla::mesa_pd::Vec3& getForce(const size_t /*p_idx*/) const {return force_;} + void setForce(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { force_ = v;} + + const walberla::mesa_pd::data::particle_flags::FlagT& getFlags(const size_t /*p_idx*/) const {return flags_;} + + const walberla::mesa_pd::Vec3& getAngularVelocity(const size_t /*p_idx*/) const {return angularVelocity_;} + void setAngularVelocity(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { angularVelocity_ = v;} + + const walberla::mesa_pd::Vec3& getTorque(const size_t /*p_idx*/) const {return torque_;} + void setTorque(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { torque_ = v;} + + + id_t getInvalidUid() const {return UniqueID<int>::invalidID();} + size_t getInvalidIdx() const {return std::numeric_limits<size_t>::max();} + /** + * @brief Returns the index of particle specified by uid. + * @param uid unique id of the particle to be looked up + * @return the index of the particle or std::numeric_limits<size_t>::max() if the particle is not found + */ + size_t uidToIdx(const id_t& /*uid*/) const {return 0;} + size_t size() const { return 1; } +private: + walberla::mesa_pd::Vec3 linearVelocity_; + walberla::mesa_pd::Vec3 force_; + walberla::mesa_pd::data::particle_flags::FlagT flags_; + walberla::mesa_pd::Vec3 angularVelocity_; + walberla::mesa_pd::Vec3 torque_; +}; + +template void kernel::PFCDamping::operator()(const size_t p_idx1, Accessor& ac) const; + +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file -- GitLab From 103667f2f567c5cafc4853de3cd87436399e43df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20V=C3=B6gl?= <cvoegl@suse.com> Date: Thu, 10 Dec 2020 13:48:47 +0100 Subject: [PATCH 12/83] Added rotate method to MeshOperations --- src/mesh_common/MeshOperations.h | 18 ++++++++++++++++++ tests/mesh/MeshOperationsTest.cpp | 22 ++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/src/mesh_common/MeshOperations.h b/src/mesh_common/MeshOperations.h index b87081750..1694edf87 100644 --- a/src/mesh_common/MeshOperations.h +++ b/src/mesh_common/MeshOperations.h @@ -49,6 +49,9 @@ void translate( MeshType & mesh, const Vector3< typename MeshType::Scalar > & of template< typename MeshType > void scale( MeshType & mesh, const Vector3< typename MeshType::Scalar > & scaleFactors ); +template< typename MeshType > +void rotate( MeshType& mesh, Vector3<typename MeshType::Scalar > axis, typename MeshType::Scalar angle, Vector3< typename MeshType::scalar> axis_foot); + template< typename MeshType > typename MeshType::Scalar computeVolume( const MeshType & mesh ); @@ -182,6 +185,21 @@ void scale( MeshType & mesh, const Vector3< typename MeshType::Scalar > & scaleF } } +template< typename MeshType > +void rotate( MeshType& mesh, Vector3<typename MeshType::Scalar > axis, typename MeshType::Scalar angle, Vector3< typename MeshType::Scalar> axis_foot) +{ + Matrix3< typename MeshType::Scalar > mat(axis, angle); + + for( auto v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) + { + auto &p = mesh.point(*v_it); + p -= mesh::toOpenMesh(axis_foot); + p = mat*p; + p += mesh::toOpenMesh(axis_foot); + } +} + + template< typename MeshType > typename MeshType::Scalar computeVolume( const MeshType & mesh ) diff --git a/tests/mesh/MeshOperationsTest.cpp b/tests/mesh/MeshOperationsTest.cpp index 6cceae10e..a17d14c72 100644 --- a/tests/mesh/MeshOperationsTest.cpp +++ b/tests/mesh/MeshOperationsTest.cpp @@ -120,6 +120,28 @@ void testCube() WALBERLA_CHECK_FLOAT_EQUAL( inertiaTensor(0,0), aabb.volume() * ( aabb.ySize() * aabb.ySize() + aabb.zSize() * aabb.zSize() ) / real_t(12) ); WALBERLA_CHECK_FLOAT_EQUAL( inertiaTensor(1,1), aabb.volume() * ( aabb.xSize() * aabb.xSize() + aabb.zSize() * aabb.zSize() ) / real_t(12) ); WALBERLA_CHECK_FLOAT_EQUAL( inertiaTensor(2,2), aabb.volume() * ( aabb.xSize() * aabb.xSize() + aabb.ySize() * aabb.ySize() ) / real_t(12) ); + + + rotate(mesh, Vector3<Scalar>{0, 0, 1}, static_cast<Scalar>(M_PI_2), Vector3<Scalar>{-4, 0, 0}); + aabb = computeAABB( mesh ); + + WALBERLA_CHECK_FLOAT_EQUAL( aabb.xMin(), Scalar(-5.5) ); + WALBERLA_CHECK_FLOAT_EQUAL( aabb.yMin(), Scalar(3) ); + WALBERLA_CHECK_FLOAT_EQUAL( aabb.zMin(), Scalar(-0.25) ); + + WALBERLA_CHECK_FLOAT_EQUAL( aabb.xMax(), Scalar(-2.5) ); + WALBERLA_CHECK_FLOAT_EQUAL( aabb.yMax(), Scalar(5) ); + WALBERLA_CHECK_FLOAT_EQUAL( aabb.zMax(), Scalar(0.25) ); + + + WALBERLA_CHECK_FLOAT_EQUAL( computeSurfaceArea( mesh ), Scalar(2) * ( aabb.xSize() * aabb.ySize() + aabb.xSize() * aabb.zSize() + aabb.ySize() * aabb.zSize() ) ); + WALBERLA_CHECK_FLOAT_EQUAL( computeVolume( mesh ), aabb.volume() ); + centroid = computeCentroid( mesh ); + aabbCenter = aabb.center(); + WALBERLA_CHECK_FLOAT_EQUAL( centroid[0], aabbCenter[0] ); + WALBERLA_CHECK_FLOAT_EQUAL( centroid[1], aabbCenter[1] ); + WALBERLA_CHECK_FLOAT_EQUAL( centroid[2], aabbCenter[2] ); + } int main( int argc, char * argv[] ) -- GitLab From cb41496e28d523a3b0d493056b7305c2ad03325a Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 11 Dec 2020 10:39:09 +0100 Subject: [PATCH 13/83] enable clang-tidy 11 --- .clang-tidy | 7 ++++++- .gitlab-ci.yml | 4 ++-- .../NonUniformGrid/NonUniformGrid.cpp | 2 +- .../PoiseuilleChannel/PoiseuilleChannel.cpp | 4 +--- .../SchaeferTurek/SchaeferTurek.cpp | 4 ++-- .../CombinedResolvedUnresolved.cpp | 5 +---- src/blockforest/SetupBlock.cpp | 2 +- src/core/cell/CellInterval.cpp | 11 ++++------ src/core/grid_generator/HCPIterator.cpp | 9 +------- src/core/grid_generator/SCIterator.cpp | 9 +------- src/mesa_pd/collision_detection/EPA.cpp | 19 +++-------------- src/mesa_pd/domain/BlockForestDomain.cpp | 20 ++++++++---------- src/mesh/pe/rigid_body/ConvexPolyhedron.cpp | 21 ++++++++++--------- src/pe/collision/EPA.cpp | 19 +++-------------- src/pe/raytracing/Raytracer.cpp | 2 +- src/vtk/VTKOutput.cpp | 4 ++-- 16 files changed, 49 insertions(+), 93 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 935443d1e..910df6702 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -11,6 +11,7 @@ bugprone-*, misc-*, -misc-misplaced-const, +-misc-no-recursion, -misc-non-private-member-variables-in-classes, modernize-*, @@ -43,17 +44,21 @@ readability-deleted-default, readability-isolate-declaration, readability-misleading-indentation, readability-misplaced-array-index, +readability-non-const-parameter, +readability-redundant-access-specifiers, readability-redundant-control-flow, readability-redundant-declaration, readability-redundant-function-ptr-dereference, readability-redundant-preprocessor, readability-redundant-smartptr-get, readability-redundant-string-cstr, +readability-simplify-boolean-expr, readability-simplify-subscript-expr, readability-static-accessed-through-instance, readability-static-definition-in-anonymous-namespace, readability-string-compare, -readability-uniqueptr-delete-release +readability-uniqueptr-delete-release, +readability-use-anyofallof ' WarningsAsErrors: '*' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c7bc78b1..ceef61aeb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1959,7 +1959,7 @@ doc: ############################################################################### clang-tidy: - image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:10.0 + image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:11.0 script: - $CXX --version - clang-tidy -version @@ -2481,4 +2481,4 @@ benchmark_ClangBuildAnalyzer: - docker-benchmark only: variables: - - $ENABLE_NIGHTLY_BUILDS \ No newline at end of file + - $ENABLE_NIGHTLY_BUILDS diff --git a/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp b/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp index c5f1df93e..631625909 100644 --- a/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp +++ b/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp @@ -308,7 +308,7 @@ void createSetupBlockForest( blockforest::SetupBlockForest & sforest, const Conf const memory_t memoryLimit = configBlock.getParameter< memory_t >( "memoryLimit", numeric_cast< memory_t >(256) ); sforest.balanceLoad( blockforest::StaticLevelwiseCurveBalance(true), numberOfProcesses, bufferProcesses, memoryLimit, true, - (bufferProcesses != uint_t(0)) ? true : false ); + bufferProcesses != uint_t(0) ); WALBERLA_LOG_INFO_ON_ROOT( "SetupBlockForest created successfully:\n" << sforest ); } diff --git a/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp b/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp index b72efbdcb..f5695a0f5 100644 --- a/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp +++ b/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp @@ -265,9 +265,7 @@ private: { const auto d = block.getAABB().sqSignedDistance( forest.getDomain().center() ); const real_t r = setup_.radius_L + bufferDistance_; - if( d > (r * r) ) - return true; - return false; + return d > (r * r); } return false; diff --git a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp index 50c3a9244..c49dafff0 100644 --- a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp +++ b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp @@ -1318,9 +1318,9 @@ public: "cD (real area) [5], cL (real area) [6], cD (discrete area) [7], cL (discrete area) [8], " "pressure difference (in lattice units) [9], pressure difference (in Pa) [10], vortex velocity (in lattice units) [11], " "Strouhal number (real D) [12], Strouhal number (discrete D) [13]" << std::endl; - if( setup_.evaluatePressure == false ) + if( !setup_.evaluatePressure ) file << "# ATTENTION: pressure was not evaluated, pressure difference is set to zero!" << std::endl; - if( setup_.evaluateStrouhal == false ) + if( !setup_.evaluateStrouhal ) file << "# ATTENTION: vortex velocities were not evaluated, Strouhal number is set to zero!" << std::endl; file.close(); } diff --git a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp index 8b0779629..5f4336e49 100644 --- a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp +++ b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp @@ -265,10 +265,7 @@ bool selectDPMBodies(pe::BodyID bodyID) { pe::SphereID sphere = static_cast< pe::SphereID >(bodyID); real_t radius = sphere->getRadius(); - if (radius <= real_t(0.5)) - return true; - else - return false; + return radius <= real_t(0.5); } bool selectMEMBodies(pe::BodyID bodyID) { return !selectDPMBodies(bodyID); } diff --git a/src/blockforest/SetupBlock.cpp b/src/blockforest/SetupBlock.cpp index 391012997..5b822acc1 100644 --- a/src/blockforest/SetupBlock.cpp +++ b/src/blockforest/SetupBlock.cpp @@ -37,7 +37,7 @@ void SetupBlock::assembleNeighborhood() { for( uint_t n = 0; n != 26; ++n ) for( uint_t i = 0; i != neighborhoodSection_[n].size(); ++i ) - if( neighborhood.insert( neighborhoodSection_[n][i] ).second == true ) + if( neighborhood.insert( neighborhoodSection_[n][i] ).second ) neighborhood_.push_back( neighborhoodSection_[n][i] ); } diff --git a/src/core/cell/CellInterval.cpp b/src/core/cell/CellInterval.cpp index 83ab0e33d..c4df1ea31 100644 --- a/src/core/cell/CellInterval.cpp +++ b/src/core/cell/CellInterval.cpp @@ -49,13 +49,10 @@ bool CellInterval::overlaps( const CellVector& cellVector ) const if( empty() ) return false; - for( const Cell & cell : cellVector ) - { - if( this->contains( cell ) ) - return true; - } - - return false; + return std::any_of(cellVector.begin(), + cellVector.end(), + [&](const Cell & cell) + {return contains( cell );}); } diff --git a/src/core/grid_generator/HCPIterator.cpp b/src/core/grid_generator/HCPIterator.cpp index 6be206c66..7d136ef42 100644 --- a/src/core/grid_generator/HCPIterator.cpp +++ b/src/core/grid_generator/HCPIterator.cpp @@ -168,14 +168,7 @@ bool HCPIterator::operator==(const HCPIterator &rhs) const { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } // WALBERLA_ASSERT_FLOAT_EQUAL(aabb_, rhs.aabb_, "Comparing iterators for different starting configurations!"); diff --git a/src/core/grid_generator/SCIterator.cpp b/src/core/grid_generator/SCIterator.cpp index 6c4399a64..254f97214 100644 --- a/src/core/grid_generator/SCIterator.cpp +++ b/src/core/grid_generator/SCIterator.cpp @@ -115,14 +115,7 @@ bool SCIterator::operator==(const SCIterator &rhs) const { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } // WALBERLA_ASSERT_FLOAT_EQUAL(aabb_, rhs.aabb_, "Comparing iterators for different starting configurations!"); diff --git a/src/mesa_pd/collision_detection/EPA.cpp b/src/mesa_pd/collision_detection/EPA.cpp index 3fb4ced43..ef5f21780 100644 --- a/src/mesa_pd/collision_detection/EPA.cpp +++ b/src/mesa_pd/collision_detection/EPA.cpp @@ -362,11 +362,7 @@ bool EPA::doEPA( Support &geom1, penetrationDepth = -supp_dist + real_t(2.0) * margin; retNormal = -ctr; - if(penetrationDepth < contactThreshold){ - return true; - }else{ - return false; - } + return penetrationDepth < contactThreshold; } else { //Reject sphere removeSupportMargin(epaVolume, supportA, supportB); @@ -500,12 +496,7 @@ bool EPA::doEPA( Support &geom1, std::cerr << "entryHeap[0]->getSqrDist()=" << entryHeap[0]->getSqrDist() << std::endl;*/ //std::cout << "EPA penetration depth: " << penetrationDepth << std::endl; - if(penetrationDepth < contactThreshold) { - return true; - } - - //no intersection found! - return false; + return penetrationDepth < contactThreshold; } //************************************************************************************************* @@ -722,11 +713,7 @@ inline bool EPA::originInTetrahedron( const Vec3& p0, const Vec3& p1, const Vec3 return false; } Vec3 normal3T = (p0 -p3) % (p1-p3); - if( (normal3T*p3 > real_t(0.0)) == (normal3T*p2 > real_t(0.0)) ) { - return false; - } - - return true; + return (normal3T*p3 > real_t(0.0)) != (normal3T*p2 > real_t(0.0)); } //************************************************************************************************* diff --git a/src/mesa_pd/domain/BlockForestDomain.cpp b/src/mesa_pd/domain/BlockForestDomain.cpp index cf5305270..c4d15778d 100644 --- a/src/mesa_pd/domain/BlockForestDomain.cpp +++ b/src/mesa_pd/domain/BlockForestDomain.cpp @@ -127,11 +127,10 @@ bool BlockForestDomain::isContainedInProcessSubdomain(const uint_t rank, const V bool BlockForestDomain::isContainedInLocalSubdomain(const Vec3& pt, const real_t& radius) const { - for (auto& aabb : localAABBs_) - { - if (isInsideAABB(pt, radius, aabb)) return true; - } - return false; + return std::any_of(localAABBs_.begin(), + localAABBs_.end(), + [&](auto& aabb) + {return isInsideAABB(pt, radius, aabb);}); } bool BlockForestDomain::isContainedInProcessSubdomain(const Vec3& pt, const real_t& radius) const @@ -153,12 +152,11 @@ bool BlockForestDomain::isContainedInProcessSubdomain(const Vec3& pt, const real } //intersects one of the neighboring subdomains? - for (auto& subdomain : neighborSubdomains_) - { - if (sqDistancePointToAABB(pt, subdomain.aabb) < radius*radius) return false; - } - - return true; + return std::none_of(neighborSubdomains_.begin(), + neighborSubdomains_.end(), + [&](const auto &subdomain) { + return sqDistancePointToAABB(pt, subdomain.aabb) < radius * radius; + }); } int BlockForestDomain::findContainingProcessRank(const Vec3& pt) const diff --git a/src/mesh/pe/rigid_body/ConvexPolyhedron.cpp b/src/mesh/pe/rigid_body/ConvexPolyhedron.cpp index ed500565e..2b505e09b 100644 --- a/src/mesh/pe/rigid_body/ConvexPolyhedron.cpp +++ b/src/mesh/pe/rigid_body/ConvexPolyhedron.cpp @@ -297,16 +297,17 @@ bool ConvexPolyhedron::containsRelPointImpl( real_t px, real_t py, real_t pz ) c if( px * px + py * py + pz * pz > boundingSphereRadius_ * boundingSphereRadius_ ) return false; - for(auto fh : mesh_.faces()) - { - const TriangleMesh::Normal & n = mesh_.normal(fh); // Plane normal - const TriangleMesh::Point & pp = mesh_.point(mesh_.to_vertex_handle(mesh_.halfedge_handle(fh))); // Point on plane - - if( n[0] * (px - pp[0]) + n[1] * (py - pp[1]) + n[2] * (pz - pp[2]) >= real_t(0) ) - return false; - } - - return true; + return std::none_of(mesh_.faces().begin(), + mesh_.faces().end(), + [&](auto fh) + { + //check if point is on positive side of the face + const TriangleMesh::Normal &n = mesh_.normal(fh); // Plane normal + const TriangleMesh::Point &pp = mesh_.point( + mesh_.to_vertex_handle(mesh_.halfedge_handle(fh))); // Point on plane + + return (n[0] * (px - pp[0]) + n[1] * (py - pp[1]) + n[2] * (pz - pp[2]) >= real_t(0)); + }); } //************************************************************************************************* diff --git a/src/pe/collision/EPA.cpp b/src/pe/collision/EPA.cpp index 6e7eb9755..171dc8594 100644 --- a/src/pe/collision/EPA.cpp +++ b/src/pe/collision/EPA.cpp @@ -350,11 +350,7 @@ bool EPA::doEPA( GeomPrimitive &geom1, GeomPrimitive &geom2, const GJK& gjk, Vec penetrationDepth = -supp_dist + real_t(2.0) * margin; retNormal = -ctr; - if(penetrationDepth < contactThreshold){ - return true; - }else{ - return false; - } + return penetrationDepth < contactThreshold; } else { //Reject sphere removeSupportMargin(epaVolume, supportA, supportB); @@ -488,12 +484,7 @@ bool EPA::doEPA( GeomPrimitive &geom1, GeomPrimitive &geom2, const GJK& gjk, Vec std::cerr << "entryHeap[0]->getSqrDist()=" << entryHeap[0]->getSqrDist() << std::endl;*/ //std::cout << "EPA penetration depth: " << penetrationDepth << std::endl; - if(penetrationDepth < contactThreshold) { - return true; - } - - //no intersection found! - return false; + return penetrationDepth < contactThreshold; } //************************************************************************************************* @@ -705,11 +696,7 @@ inline bool EPA::originInTetrahedron( const Vec3& p0, const Vec3& p1, const Vec3 return false; } Vec3 normal3T = (p0 -p3) % (p1-p3); - if( (normal3T*p3 > real_t(0.0)) == (normal3T*p2 > real_t(0.0)) ) { - return false; - } - - return true; + return (normal3T*p3 > real_t(0.0)) != (normal3T*p2 > real_t(0.0)); } //************************************************************************************************* diff --git a/src/pe/raytracing/Raytracer.cpp b/src/pe/raytracing/Raytracer.cpp index 631a5dfd3..344b8af99 100644 --- a/src/pe/raytracing/Raytracer.cpp +++ b/src/pe/raytracing/Raytracer.cpp @@ -31,7 +31,7 @@ namespace walberla { namespace pe { namespace raytracing { -void BodyIntersectionInfo_Comparator_MPI_OP( BodyIntersectionInfo *in, BodyIntersectionInfo *inout, int *len, MPI_Datatype *dptr) { +void BodyIntersectionInfo_Comparator_MPI_OP( BodyIntersectionInfo *in, BodyIntersectionInfo *inout, const int *len, MPI_Datatype *dptr) { WALBERLA_UNUSED(dptr); for (int i = 0; i < *len; ++i) { if (in->bodySystemID != 0 && inout->bodySystemID != 0) { diff --git a/src/vtk/VTKOutput.cpp b/src/vtk/VTKOutput.cpp index 8d8cf88f1..345d4fda3 100644 --- a/src/vtk/VTKOutput.cpp +++ b/src/vtk/VTKOutput.cpp @@ -458,7 +458,7 @@ void VTKOutput::computeOutputPoints( std::vector<Vector3<real_t> > & points, std outputPoint.assign( points.size(), true ); for( uint_t i = 0; i != points.size(); ++i ) { - bool included = ( aabbInclusionFilters_.empty() ) ? true : false; + bool included = aabbInclusionFilters_.empty(); for( auto aabb = aabbInclusionFilters_.begin(); aabb != aabbInclusionFilters_.end() && !included; ++aabb ) if( aabb->contains( points[ i ][ 0 ], points[ i ][ 1 ], points[ i ][ 2 ] ) ) included = true; if( !included ) @@ -665,7 +665,7 @@ void VTKOutput::computeOutputPolylines( std::vector< std::vector< Vector3< real_ auto outputPointIt = outputPolylinePointIt->begin(); for( auto pointIt = polylineIt->begin(); pointIt != polylineIt->end(); ++pointIt, ++outputPointIt ) { - bool included = ( aabbInclusionFilters_.empty() ) ? true : false; + bool included = aabbInclusionFilters_.empty(); for( auto aabb = aabbInclusionFilters_.begin(); aabb != aabbInclusionFilters_.end() && !included; ++aabb ) if( aabb->contains( ( *pointIt )[ 0 ], ( *pointIt )[ 1 ], ( *pointIt )[ 2 ] ) ) included = true; if( !included ) -- GitLab From 696a965dc5add0ef81cf6e4df902118cf947ae97 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Thu, 17 Dec 2020 13:36:45 +0100 Subject: [PATCH 14/83] [FIX] removing potentially wrong filenames The default target of \file is the current file. --- python/mesa_pd/templates/common/ParticleFunctions.templ.h | 2 +- python/mesa_pd/templates/data/ContactAccessor.templ.h | 2 +- python/mesa_pd/templates/data/ContactHistory.templ.h | 2 +- python/mesa_pd/templates/data/ContactStorage.templ.h | 2 +- python/mesa_pd/templates/data/LinkedCells.templ.h | 2 +- python/mesa_pd/templates/data/ParticleAccessor.templ.h | 2 +- python/mesa_pd/templates/data/ParticleStorage.templ.h | 2 +- python/mesa_pd/templates/data/ShapeStorage.templ.h | 2 +- python/mesa_pd/templates/data/SparseLinkedCells.templ.h | 2 +- python/mesa_pd/templates/kernel/DetectAndStoreContacts.templ.h | 2 +- python/mesa_pd/templates/kernel/DoubleCast.templ.h | 2 +- python/mesa_pd/templates/kernel/ExplicitEuler.templ.h | 2 +- python/mesa_pd/templates/kernel/ForceLJ.templ.h | 2 +- python/mesa_pd/templates/kernel/HCSITSRelaxationStep.templ.h | 2 +- python/mesa_pd/templates/kernel/HeatConduction.templ.h | 2 +- python/mesa_pd/templates/kernel/InitContactsForHCSITS.templ.h | 2 +- python/mesa_pd/templates/kernel/InitParticlesForHCSITS.templ.h | 2 +- .../templates/kernel/InsertParticleIntoLinkedCells.templ.h | 2 +- .../kernel/InsertParticleIntoSparseLinkedCells.templ.h | 2 +- .../mesa_pd/templates/kernel/IntegrateParticlesHCSITS.templ.h | 2 +- python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h | 2 +- python/mesa_pd/templates/kernel/NonLinearSpringDashpot.templ.h | 2 +- python/mesa_pd/templates/kernel/PFCDamping.templ.h | 2 +- python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h | 2 +- python/mesa_pd/templates/kernel/SingleCast.templ.h | 2 +- python/mesa_pd/templates/kernel/SpringDashpot.templ.h | 2 +- python/mesa_pd/templates/kernel/SpringDashpotSpring.templ.h | 2 +- python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h | 2 +- python/mesa_pd/templates/kernel/VelocityVerlet.templ.h | 2 +- python/mesa_pd/templates/mpi/BroadcastProperty.templ.h | 2 +- python/mesa_pd/templates/mpi/ClearGhostOwnerSync.templ.h | 2 +- python/mesa_pd/templates/mpi/ClearNextNeighborSync.templ.h | 2 +- python/mesa_pd/templates/mpi/ReduceContactHistory.templ.h | 2 +- python/mesa_pd/templates/mpi/ReduceProperty.templ.h | 2 +- python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h | 2 +- python/mesa_pd/templates/mpi/SyncGhostOwners.templ.cpp | 2 +- python/mesa_pd/templates/mpi/SyncGhostOwners.templ.h | 2 +- python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.cpp | 2 +- python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.h | 2 +- .../mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp | 2 +- python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h | 2 +- .../mpi/notifications/ContactHistoryNotification.templ.h | 2 +- .../mpi/notifications/NewGhostParticleNotification.templ.h | 2 +- python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h | 2 +- .../mpi/notifications/ParticleCopyNotification.templ.h | 2 +- .../mpi/notifications/ParticleGhostCopyNotification.templ.h | 2 +- .../mpi/notifications/ParticleMigrationNotification.templ.h | 2 +- .../notifications/ParticleRemoteMigrationNotification.templ.h | 2 +- .../ParticleRemovalInformationNotification.templ.h | 2 +- .../mpi/notifications/ParticleRemovalNotification.templ.h | 2 +- .../mpi/notifications/ParticleUpdateNotification.templ.h | 2 +- .../templates/mpi/notifications/PropertyNotification.templ.h | 2 +- python/mesa_pd/templates/tests/CheckInterface.templ.cpp | 2 +- src/mesa_pd/collision_detection/AnalyticCollisionFunctions.h | 2 +- src/mesa_pd/collision_detection/AnalyticContactDetection.h | 2 +- src/mesa_pd/collision_detection/BroadPhase.h | 2 +- src/mesa_pd/collision_detection/EPA.cpp | 2 +- src/mesa_pd/collision_detection/EPA.h | 2 +- src/mesa_pd/collision_detection/GJK.cpp | 2 +- src/mesa_pd/collision_detection/GJK.h | 2 +- src/mesa_pd/collision_detection/GeneralContactDetection.h | 2 +- src/mesa_pd/collision_detection/Support.h | 2 +- src/mesa_pd/common/AABBConversion.h | 2 +- src/mesa_pd/common/Contains.h | 2 +- src/mesa_pd/common/ParticleFunctions.h | 2 +- src/mesa_pd/common/RayParticleIntersection.h | 2 +- src/mesa_pd/data/ContactAccessor.h | 2 +- src/mesa_pd/data/ContactHistory.h | 2 +- src/mesa_pd/data/ContactStorage.h | 2 +- src/mesa_pd/data/DataTypes.h | 2 +- src/mesa_pd/data/Flags.h | 2 +- src/mesa_pd/data/IAccessor.h | 2 +- src/mesa_pd/data/IContactAccessor.h | 2 +- src/mesa_pd/data/LinkedCells.h | 2 +- src/mesa_pd/data/ParticleAccessor.h | 2 +- src/mesa_pd/data/ParticleAccessorWithShape.h | 2 +- src/mesa_pd/data/ParticleStorage.h | 2 +- src/mesa_pd/data/STLOverloads.h | 2 +- src/mesa_pd/data/ShapeStorage.h | 2 +- src/mesa_pd/data/SparseLinkedCells.h | 2 +- src/mesa_pd/data/shape/BaseShape.h | 2 +- src/mesa_pd/data/shape/Box.h | 2 +- src/mesa_pd/data/shape/ConvexPolyhedron.h | 2 +- src/mesa_pd/data/shape/CylindricalBoundary.h | 2 +- src/mesa_pd/data/shape/Ellipsoid.h | 2 +- src/mesa_pd/data/shape/HalfSpace.h | 2 +- src/mesa_pd/data/shape/ShapeTypes.cpp | 2 +- src/mesa_pd/data/shape/Sphere.h | 2 +- src/mesa_pd/domain/BlockForestDataHandling.cpp | 2 +- src/mesa_pd/domain/BlockForestDataHandling.h | 2 +- src/mesa_pd/domain/BlockForestDomain.cpp | 2 +- src/mesa_pd/domain/BlockForestDomain.h | 2 +- src/mesa_pd/domain/IDomain.h | 2 +- src/mesa_pd/domain/InfiniteDomain.h | 2 +- src/mesa_pd/domain/InfoCollection.h | 2 +- src/mesa_pd/kernel/AssocToBlock.h | 2 +- src/mesa_pd/kernel/DetectAndStoreContacts.h | 2 +- src/mesa_pd/kernel/DoubleCast.h | 2 +- src/mesa_pd/kernel/ExplicitEuler.h | 2 +- src/mesa_pd/kernel/ExplicitEulerWithShape.h | 2 +- src/mesa_pd/kernel/ForceLJ.h | 2 +- src/mesa_pd/kernel/HCSITSRelaxationStep.h | 2 +- src/mesa_pd/kernel/HeatConduction.h | 2 +- src/mesa_pd/kernel/InitContactsForHCSITS.h | 2 +- src/mesa_pd/kernel/InitParticlesForHCSITS.h | 2 +- src/mesa_pd/kernel/InsertParticleIntoLinkedCells.h | 2 +- src/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h | 2 +- src/mesa_pd/kernel/IntegrateParticlesHCSITS.h | 2 +- src/mesa_pd/kernel/LinearSpringDashpot.h | 2 +- src/mesa_pd/kernel/NonLinearSpringDashpot.h | 2 +- src/mesa_pd/kernel/PFCDamping.h | 2 +- src/mesa_pd/kernel/ParticleSelector.h | 2 +- src/mesa_pd/kernel/SemiImplicitEuler.h | 2 +- src/mesa_pd/kernel/SingleCast.h | 2 +- src/mesa_pd/kernel/SpringDashpot.h | 2 +- src/mesa_pd/kernel/SpringDashpotSpring.h | 2 +- src/mesa_pd/kernel/TemperatureIntegration.h | 2 +- src/mesa_pd/kernel/VelocityVerlet.h | 2 +- src/mesa_pd/mpi/BroadcastProperty.h | 2 +- src/mesa_pd/mpi/ClearGhostOwnerSync.h | 2 +- src/mesa_pd/mpi/ClearNextNeighborSync.h | 2 +- src/mesa_pd/mpi/ContactFilter.h | 2 +- src/mesa_pd/mpi/ReduceContactHistory.h | 2 +- src/mesa_pd/mpi/ReduceProperty.h | 2 +- src/mesa_pd/mpi/RemoveAndNotify.cpp | 2 +- src/mesa_pd/mpi/RemoveAndNotify.h | 2 +- src/mesa_pd/mpi/ShapePackUnpack.h | 2 +- src/mesa_pd/mpi/SyncGhostOwners.cpp | 2 +- src/mesa_pd/mpi/SyncGhostOwners.h | 2 +- src/mesa_pd/mpi/SyncNextNeighbors.cpp | 2 +- src/mesa_pd/mpi/SyncNextNeighbors.h | 2 +- src/mesa_pd/mpi/SyncNextNeighborsBlockForest.cpp | 2 +- src/mesa_pd/mpi/SyncNextNeighborsBlockForest.h | 2 +- src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp | 2 +- src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h | 2 +- src/mesa_pd/mpi/notifications/ContactHistoryNotification.h | 2 +- src/mesa_pd/mpi/notifications/ForceTorqueNotification.h | 2 +- src/mesa_pd/mpi/notifications/HeatFluxNotification.h | 2 +- .../mpi/notifications/HydrodynamicForceTorqueNotification.h | 2 +- src/mesa_pd/mpi/notifications/NewGhostParticleNotification.h | 2 +- src/mesa_pd/mpi/notifications/NotificationType.h | 2 +- src/mesa_pd/mpi/notifications/PackNotification.h | 2 +- src/mesa_pd/mpi/notifications/ParseMessage.h | 2 +- src/mesa_pd/mpi/notifications/ParticleCopyNotification.h | 2 +- src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h | 2 +- src/mesa_pd/mpi/notifications/ParticleMigrationNotification.h | 2 +- .../mpi/notifications/ParticleRemoteMigrationNotification.h | 2 +- .../mpi/notifications/ParticleRemovalInformationNotification.h | 2 +- src/mesa_pd/mpi/notifications/ParticleRemovalNotification.h | 2 +- src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h | 2 +- src/mesa_pd/mpi/notifications/VelocityCorrectionNotification.h | 2 +- src/mesa_pd/mpi/notifications/VelocityUpdateNotification.h | 2 +- src/mesa_pd/mpi/notifications/reset.h | 2 +- src/mesa_pd/sorting/HilbertCompareFunctor.cpp | 2 +- src/mesa_pd/sorting/HilbertCompareFunctor.h | 2 +- src/mesa_pd/sorting/LinearizedCompareFunctor.cpp | 2 +- src/mesa_pd/sorting/LinearizedCompareFunctor.h | 2 +- src/mesa_pd/vtk/ConvexPolyhedron/MeshParticleVTKOutput.h | 2 +- .../vtk/ConvexPolyhedron/data_sources/DataSourceAdapters.h | 2 +- src/mesa_pd/vtk/ConvexPolyhedron/data_sources/FaceDataSource.h | 2 +- .../data_sources/OutputSelectorFaceDataSource.h | 2 +- .../data_sources/OutputSelectorVertexDataSource.h | 2 +- .../data_sources/SurfaceVelocityVertexDataSource.h | 2 +- .../vtk/ConvexPolyhedron/data_sources/VertexDataSource.h | 2 +- .../ConvexPolyhedron/tesselation/ConvexPolyhedronTesselation.h | 2 +- src/mesa_pd/vtk/OutputSelector.h | 2 +- src/mesa_pd/vtk/ParticleVtkOutput.cpp | 2 +- src/mesa_pd/vtk/ParticleVtkOutput.h | 2 +- src/mesa_pd/vtk/TensorGlyph.cpp | 2 +- src/mesa_pd/vtk/TensorGlyph.h | 2 +- src/mesa_pd/vtk/WriteOutput.h | 2 +- tests/mesa_pd/ContactDetection.cpp | 2 +- tests/mesa_pd/DropTestAnalytic.cpp | 2 +- tests/mesa_pd/DropTestGeneral.cpp | 2 +- tests/mesa_pd/Sorting.cpp | 2 +- .../mesa_pd/collision_detection/AnalyticCollisionFunctions.cpp | 2 +- tests/mesa_pd/collision_detection/AnalyticContactDetection.cpp | 2 +- tests/mesa_pd/collision_detection/BoxSupport.cpp | 2 +- tests/mesa_pd/collision_detection/ConvexPolyhedron_GJK_EPA.cpp | 2 +- tests/mesa_pd/collision_detection/EPA.cpp | 2 +- tests/mesa_pd/collision_detection/EllipsoidSupport.cpp | 2 +- tests/mesa_pd/collision_detection/GJK.cpp | 2 +- tests/mesa_pd/collision_detection/GJK_EPA.cpp | 2 +- tests/mesa_pd/collision_detection/GeneralContactDetection.cpp | 2 +- tests/mesa_pd/collision_detection/SphereSupport.cpp | 2 +- tests/mesa_pd/common/IntersectionRatio.cpp | 2 +- tests/mesa_pd/data/ConvexPolyhedron.cpp | 2 +- tests/mesa_pd/data/Flags.cpp | 2 +- tests/mesa_pd/data/LinkedCells.cpp | 2 +- tests/mesa_pd/data/ParticleStorage.cpp | 2 +- tests/mesa_pd/data/SparseLinkedCells.cpp | 2 +- tests/mesa_pd/domain/BlockForestDomain.cpp | 2 +- tests/mesa_pd/domain/BlockForestSync.cpp | 2 +- tests/mesa_pd/domain/BlockForestSyncPeriodic.cpp | 2 +- tests/mesa_pd/domain/DistanceCalculation.cpp | 2 +- tests/mesa_pd/domain/DynamicRefinement.cpp | 2 +- tests/mesa_pd/domain/SerializeDeserialize.cpp | 2 +- tests/mesa_pd/kernel/ClearNextNeighborSync.cpp | 2 +- tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp | 2 +- tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp | 2 +- tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp | 2 +- tests/mesa_pd/kernel/DetectAndStoreContacts.cpp | 2 +- tests/mesa_pd/kernel/DoubleCast.cpp | 2 +- tests/mesa_pd/kernel/ExplicitEuler.cpp | 2 +- tests/mesa_pd/kernel/ForceLJ.cpp | 2 +- tests/mesa_pd/kernel/GenerateAnalyticContacts.cpp | 2 +- tests/mesa_pd/kernel/GenerateLinkedCells.cpp | 2 +- tests/mesa_pd/kernel/HCSITSKernels.cpp | 2 +- tests/mesa_pd/kernel/HeatConduction.cpp | 2 +- tests/mesa_pd/kernel/IntegratorAccuracy.cpp | 2 +- tests/mesa_pd/kernel/Interfaces.cpp | 2 +- tests/mesa_pd/kernel/LinearSpringDashpot.cpp | 2 +- tests/mesa_pd/kernel/LinkedCellsVsBruteForce.cpp | 2 +- tests/mesa_pd/kernel/PFCDamping.cpp | 2 +- tests/mesa_pd/kernel/SemiImplicitEuler.cpp | 2 +- tests/mesa_pd/kernel/SingleCast.cpp | 2 +- tests/mesa_pd/kernel/SpherePile.cpp | 2 +- tests/mesa_pd/kernel/SpringDashpot.cpp | 2 +- tests/mesa_pd/kernel/SyncGhostOwners.cpp | 2 +- tests/mesa_pd/kernel/SyncGhostOwnersLarge.cpp | 2 +- tests/mesa_pd/kernel/SyncNextNeighbors.cpp | 2 +- tests/mesa_pd/kernel/SyncNextNeighborsBlockForest.cpp | 2 +- tests/mesa_pd/kernel/TemperatureIntegration.cpp | 2 +- tests/mesa_pd/kernel/VelocityVerlet.cpp | 2 +- tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp | 2 +- .../kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp | 2 +- tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp | 2 +- .../mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp | 2 +- tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp | 2 +- .../kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp | 2 +- tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp | 2 +- .../kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp | 2 +- .../mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp | 2 +- .../kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp | 2 +- tests/mesa_pd/mpi/BroadcastProperty.cpp | 2 +- tests/mesa_pd/mpi/ClearGhostOwnerSync.cpp | 2 +- tests/mesa_pd/mpi/ClearNextNeighborSync.cpp | 2 +- tests/mesa_pd/mpi/Notifications.cpp | 2 +- tests/mesa_pd/mpi/ReduceContactHistory.cpp | 2 +- tests/mesa_pd/mpi/ReduceProperty.cpp | 2 +- tests/mesa_pd/mpi/ShapePackUnpack.cpp | 2 +- tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp | 2 +- tests/mesa_pd/mpi/VelocityCorrectionNotification.cpp | 2 +- tests/mesa_pd/vtk/ConvexPolyhedronVTKOutput.cpp | 2 +- tests/mesa_pd/vtk/VTKOutputs.cpp | 2 +- 245 files changed, 245 insertions(+), 245 deletions(-) diff --git a/python/mesa_pd/templates/common/ParticleFunctions.templ.h b/python/mesa_pd/templates/common/ParticleFunctions.templ.h index 1ed2d53db..807a12919 100644 --- a/python/mesa_pd/templates/common/ParticleFunctions.templ.h +++ b/python/mesa_pd/templates/common/ParticleFunctions.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleFunctions.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ContactAccessor.templ.h b/python/mesa_pd/templates/data/ContactAccessor.templ.h index b51f5de7f..86666fcc3 100644 --- a/python/mesa_pd/templates/data/ContactAccessor.templ.h +++ b/python/mesa_pd/templates/data/ContactAccessor.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactAccessor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ContactHistory.templ.h b/python/mesa_pd/templates/data/ContactHistory.templ.h index b455a2fa9..1ab195d65 100644 --- a/python/mesa_pd/templates/data/ContactHistory.templ.h +++ b/python/mesa_pd/templates/data/ContactHistory.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactHistory.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ContactStorage.templ.h b/python/mesa_pd/templates/data/ContactStorage.templ.h index 3731188bb..a609ebb07 100644 --- a/python/mesa_pd/templates/data/ContactStorage.templ.h +++ b/python/mesa_pd/templates/data/ContactStorage.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/python/mesa_pd/templates/data/LinkedCells.templ.h b/python/mesa_pd/templates/data/LinkedCells.templ.h index 713e2d073..fdf8aa39e 100644 --- a/python/mesa_pd/templates/data/LinkedCells.templ.h +++ b/python/mesa_pd/templates/data/LinkedCells.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ParticleAccessor.templ.h b/python/mesa_pd/templates/data/ParticleAccessor.templ.h index 7372641f4..701d802d0 100644 --- a/python/mesa_pd/templates/data/ParticleAccessor.templ.h +++ b/python/mesa_pd/templates/data/ParticleAccessor.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleAccessor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ParticleStorage.templ.h b/python/mesa_pd/templates/data/ParticleStorage.templ.h index 7f8d00bb3..37cbd40ae 100644 --- a/python/mesa_pd/templates/data/ParticleStorage.templ.h +++ b/python/mesa_pd/templates/data/ParticleStorage.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/ShapeStorage.templ.h b/python/mesa_pd/templates/data/ShapeStorage.templ.h index 772628ea6..22111a7a3 100644 --- a/python/mesa_pd/templates/data/ShapeStorage.templ.h +++ b/python/mesa_pd/templates/data/ShapeStorage.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GeometryStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/data/SparseLinkedCells.templ.h b/python/mesa_pd/templates/data/SparseLinkedCells.templ.h index 139dbb0a4..145ce87c6 100644 --- a/python/mesa_pd/templates/data/SparseLinkedCells.templ.h +++ b/python/mesa_pd/templates/data/SparseLinkedCells.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SparseLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/DetectAndStoreContacts.templ.h b/python/mesa_pd/templates/kernel/DetectAndStoreContacts.templ.h index 85369e566..fa3237fb6 100644 --- a/python/mesa_pd/templates/kernel/DetectAndStoreContacts.templ.h +++ b/python/mesa_pd/templates/kernel/DetectAndStoreContacts.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DetectAndStoreContacts.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/python/mesa_pd/templates/kernel/DoubleCast.templ.h b/python/mesa_pd/templates/kernel/DoubleCast.templ.h index adc3caf3c..ab745eff7 100644 --- a/python/mesa_pd/templates/kernel/DoubleCast.templ.h +++ b/python/mesa_pd/templates/kernel/DoubleCast.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SingleCast.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h b/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h index 79b1518b3..d6893ffbe 100644 --- a/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h +++ b/python/mesa_pd/templates/kernel/ExplicitEuler.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEuler.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/ForceLJ.templ.h b/python/mesa_pd/templates/kernel/ForceLJ.templ.h index 4242a0658..fed2360e5 100644 --- a/python/mesa_pd/templates/kernel/ForceLJ.templ.h +++ b/python/mesa_pd/templates/kernel/ForceLJ.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ForceLJ.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/HCSITSRelaxationStep.templ.h b/python/mesa_pd/templates/kernel/HCSITSRelaxationStep.templ.h index 1523a57b3..e18d0df56 100644 --- a/python/mesa_pd/templates/kernel/HCSITSRelaxationStep.templ.h +++ b/python/mesa_pd/templates/kernel/HCSITSRelaxationStep.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HCSITSRelaxationStep.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/python/mesa_pd/templates/kernel/HeatConduction.templ.h b/python/mesa_pd/templates/kernel/HeatConduction.templ.h index ef12443d9..03576a7f4 100644 --- a/python/mesa_pd/templates/kernel/HeatConduction.templ.h +++ b/python/mesa_pd/templates/kernel/HeatConduction.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HeatConduction.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/InitContactsForHCSITS.templ.h b/python/mesa_pd/templates/kernel/InitContactsForHCSITS.templ.h index eb48c9a51..e78443ff6 100644 --- a/python/mesa_pd/templates/kernel/InitContactsForHCSITS.templ.h +++ b/python/mesa_pd/templates/kernel/InitContactsForHCSITS.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InitContactsForHCSITS.h +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/InitParticlesForHCSITS.templ.h b/python/mesa_pd/templates/kernel/InitParticlesForHCSITS.templ.h index 1ef8698a4..e218cb1d5 100644 --- a/python/mesa_pd/templates/kernel/InitParticlesForHCSITS.templ.h +++ b/python/mesa_pd/templates/kernel/InitParticlesForHCSITS.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InitParticlesForHCSITS.h +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/InsertParticleIntoLinkedCells.templ.h b/python/mesa_pd/templates/kernel/InsertParticleIntoLinkedCells.templ.h index d80b9cfd8..96bcd932d 100644 --- a/python/mesa_pd/templates/kernel/InsertParticleIntoLinkedCells.templ.h +++ b/python/mesa_pd/templates/kernel/InsertParticleIntoLinkedCells.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InsertParticleIntoLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/InsertParticleIntoSparseLinkedCells.templ.h b/python/mesa_pd/templates/kernel/InsertParticleIntoSparseLinkedCells.templ.h index ca9f6ba01..ff10b7b6d 100644 --- a/python/mesa_pd/templates/kernel/InsertParticleIntoSparseLinkedCells.templ.h +++ b/python/mesa_pd/templates/kernel/InsertParticleIntoSparseLinkedCells.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InsertParticleIntoSparseLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/IntegrateParticlesHCSITS.templ.h b/python/mesa_pd/templates/kernel/IntegrateParticlesHCSITS.templ.h index 068b21e14..a1a225ec9 100644 --- a/python/mesa_pd/templates/kernel/IntegrateParticlesHCSITS.templ.h +++ b/python/mesa_pd/templates/kernel/IntegrateParticlesHCSITS.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IntegrateParticlesHCSITS.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h b/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h index 2613d2414..2696e0f34 100644 --- a/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h +++ b/python/mesa_pd/templates/kernel/LinearSpringDashpot.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinearSpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Christoph Rettinger <christoph.rettinger@fau.de> // diff --git a/python/mesa_pd/templates/kernel/NonLinearSpringDashpot.templ.h b/python/mesa_pd/templates/kernel/NonLinearSpringDashpot.templ.h index 45318c780..3cc2fbd7f 100644 --- a/python/mesa_pd/templates/kernel/NonLinearSpringDashpot.templ.h +++ b/python/mesa_pd/templates/kernel/NonLinearSpringDashpot.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file NonLinearSpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Christoph Rettinger <christoph.rettinger@fau.de> // diff --git a/python/mesa_pd/templates/kernel/PFCDamping.templ.h b/python/mesa_pd/templates/kernel/PFCDamping.templ.h index 7dfc8ae0c..cab03afac 100644 --- a/python/mesa_pd/templates/kernel/PFCDamping.templ.h +++ b/python/mesa_pd/templates/kernel/PFCDamping.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PFCDamping.h +//! \file //! \author Igor Ostanin <i.ostanin@skoltech.ru> //! \author Grigorii Drozdov, <drozd013@umn.edu> // diff --git a/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h b/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h index 7045cbfe1..edc393536 100644 --- a/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h +++ b/python/mesa_pd/templates/kernel/SemiImplicitEuler.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SemiImplicitEuler.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/SingleCast.templ.h b/python/mesa_pd/templates/kernel/SingleCast.templ.h index eda737d63..878554980 100644 --- a/python/mesa_pd/templates/kernel/SingleCast.templ.h +++ b/python/mesa_pd/templates/kernel/SingleCast.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SingleCast.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/SpringDashpot.templ.h b/python/mesa_pd/templates/kernel/SpringDashpot.templ.h index 93df9f865..29c8a1076 100644 --- a/python/mesa_pd/templates/kernel/SpringDashpot.templ.h +++ b/python/mesa_pd/templates/kernel/SpringDashpot.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/SpringDashpotSpring.templ.h b/python/mesa_pd/templates/kernel/SpringDashpotSpring.templ.h index 78d3d4863..873dc7106 100644 --- a/python/mesa_pd/templates/kernel/SpringDashpotSpring.templ.h +++ b/python/mesa_pd/templates/kernel/SpringDashpotSpring.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpotSpring.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h b/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h index 2bdd7f362..f6041bf3f 100644 --- a/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h +++ b/python/mesa_pd/templates/kernel/TemperatureIntegration.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TemperatureIntegration.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h b/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h index 98d97b628..919a13b2a 100644 --- a/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h +++ b/python/mesa_pd/templates/kernel/VelocityVerlet.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityVerlet.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/BroadcastProperty.templ.h b/python/mesa_pd/templates/mpi/BroadcastProperty.templ.h index 236c0a65c..a9f3b3310 100644 --- a/python/mesa_pd/templates/mpi/BroadcastProperty.templ.h +++ b/python/mesa_pd/templates/mpi/BroadcastProperty.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BroadcastProperty.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/ClearGhostOwnerSync.templ.h b/python/mesa_pd/templates/mpi/ClearGhostOwnerSync.templ.h index 4194abe69..cd00a12a8 100644 --- a/python/mesa_pd/templates/mpi/ClearGhostOwnerSync.templ.h +++ b/python/mesa_pd/templates/mpi/ClearGhostOwnerSync.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearGhostOwnerSync.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/ClearNextNeighborSync.templ.h b/python/mesa_pd/templates/mpi/ClearNextNeighborSync.templ.h index df3505f47..c5c7d117c 100644 --- a/python/mesa_pd/templates/mpi/ClearNextNeighborSync.templ.h +++ b/python/mesa_pd/templates/mpi/ClearNextNeighborSync.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearNextNeighborSync.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/ReduceContactHistory.templ.h b/python/mesa_pd/templates/mpi/ReduceContactHistory.templ.h index 77aabba48..840e0bc1a 100644 --- a/python/mesa_pd/templates/mpi/ReduceContactHistory.templ.h +++ b/python/mesa_pd/templates/mpi/ReduceContactHistory.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ReduceContactHistory.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/ReduceProperty.templ.h b/python/mesa_pd/templates/mpi/ReduceProperty.templ.h index 60abb8985..970c0127c 100644 --- a/python/mesa_pd/templates/mpi/ReduceProperty.templ.h +++ b/python/mesa_pd/templates/mpi/ReduceProperty.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncProperty.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h b/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h index 2031f6659..6ea9d158e 100644 --- a/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h +++ b/python/mesa_pd/templates/mpi/ShapePackUnpack.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ShapePackUnpack.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.cpp b/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.cpp index 1dca2429d..7336ec1e8 100644 --- a/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.cpp +++ b/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwners.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.h b/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.h index 0be135507..179253fb0 100644 --- a/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.h +++ b/python/mesa_pd/templates/mpi/SyncGhostOwners.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwners.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.cpp b/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.cpp index f631bb0e7..3dd7ca3c4 100644 --- a/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.cpp +++ b/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighbors.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.h b/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.h index 7a9dc110b..bea705262 100644 --- a/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.h +++ b/python/mesa_pd/templates/mpi/SyncNextNeighbors.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighbors.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp index ce8c9100d..200a918d9 100644 --- a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp +++ b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsNoGhosts.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h index 8030c09e7..22fb55829 100644 --- a/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h +++ b/python/mesa_pd/templates/mpi/SyncNextNeighborsNoGhosts.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsNoGhosts.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ContactHistoryNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ContactHistoryNotification.templ.h index 2ffca67a2..0b7310f22 100644 --- a/python/mesa_pd/templates/mpi/notifications/ContactHistoryNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ContactHistoryNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactHistoryNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/NewGhostParticleNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/NewGhostParticleNotification.templ.h index 7d8a8ce43..27bc904f4 100644 --- a/python/mesa_pd/templates/mpi/notifications/NewGhostParticleNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/NewGhostParticleNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file NewGhostParticleNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h b/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h index e1dce5b88..ce4aca6e3 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParseMessage.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParseMessage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \brief Parsing of messages // diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h index e2414008e..a8c797f4c 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleCopyNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleCopyNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h index 52dd0a780..5e6b7aa4f 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleGhostCopyNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleGhostCopyNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h index f478bcc9c..26f50b3dc 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleMigrationNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleMigrationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleRemoteMigrationNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleRemoteMigrationNotification.templ.h index 3a1cbceeb..966759bdd 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleRemoteMigrationNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleRemoteMigrationNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemoteMigrationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleRemovalInformationNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleRemovalInformationNotification.templ.h index 15f10d48c..c3386d7e2 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleRemovalInformationNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleRemovalInformationNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemovalInformationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleRemovalNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleRemovalNotification.templ.h index 9b3e56b77..798f8b750 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleRemovalNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleRemovalNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemovalNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h index 507eeda47..282db85d4 100644 --- a/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/ParticleUpdateNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleUpdateNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/mpi/notifications/PropertyNotification.templ.h b/python/mesa_pd/templates/mpi/notifications/PropertyNotification.templ.h index 701f21ea9..1a759ce31 100644 --- a/python/mesa_pd/templates/mpi/notifications/PropertyNotification.templ.h +++ b/python/mesa_pd/templates/mpi/notifications/PropertyNotification.templ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file {{name}}.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/python/mesa_pd/templates/tests/CheckInterface.templ.cpp b/python/mesa_pd/templates/tests/CheckInterface.templ.cpp index 6bbd8f4f3..817001e2d 100644 --- a/python/mesa_pd/templates/tests/CheckInterface.templ.cpp +++ b/python/mesa_pd/templates/tests/CheckInterface.templ.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file {{InterfaceTestName}}.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/collision_detection/AnalyticCollisionFunctions.h b/src/mesa_pd/collision_detection/AnalyticCollisionFunctions.h index bcf3baf63..b09f646ed 100644 --- a/src/mesa_pd/collision_detection/AnalyticCollisionFunctions.h +++ b/src/mesa_pd/collision_detection/AnalyticCollisionFunctions.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AnalyticCollisionFunctions.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/collision_detection/AnalyticContactDetection.h b/src/mesa_pd/collision_detection/AnalyticContactDetection.h index 284cd1eb9..ce8149c1e 100644 --- a/src/mesa_pd/collision_detection/AnalyticContactDetection.h +++ b/src/mesa_pd/collision_detection/AnalyticContactDetection.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AnalyticContactDetection.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/collision_detection/BroadPhase.h b/src/mesa_pd/collision_detection/BroadPhase.h index 4bad17b24..a3fcb2640 100644 --- a/src/mesa_pd/collision_detection/BroadPhase.h +++ b/src/mesa_pd/collision_detection/BroadPhase.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BroadPhase.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/collision_detection/EPA.cpp b/src/mesa_pd/collision_detection/EPA.cpp index ef5f21780..defefd3a9 100644 --- a/src/mesa_pd/collision_detection/EPA.cpp +++ b/src/mesa_pd/collision_detection/EPA.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file EPA.cpp +//! \file //! \author Tobias Scharpff //! \author Tobias Leemann // diff --git a/src/mesa_pd/collision_detection/EPA.h b/src/mesa_pd/collision_detection/EPA.h index 46d59a08a..781196f62 100644 --- a/src/mesa_pd/collision_detection/EPA.h +++ b/src/mesa_pd/collision_detection/EPA.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file EPA.h +//! \file //! \author Tobias Scharpff //! \author Tobias Leemann // diff --git a/src/mesa_pd/collision_detection/GJK.cpp b/src/mesa_pd/collision_detection/GJK.cpp index d111caccd..002f3f788 100644 --- a/src/mesa_pd/collision_detection/GJK.cpp +++ b/src/mesa_pd/collision_detection/GJK.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GJK.cpp +//! \file //! \author Tobias Scharpff //! \author Tobias Leemann // diff --git a/src/mesa_pd/collision_detection/GJK.h b/src/mesa_pd/collision_detection/GJK.h index 47b424731..7ccff5128 100644 --- a/src/mesa_pd/collision_detection/GJK.h +++ b/src/mesa_pd/collision_detection/GJK.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GJK.h +//! \file //! \author Tobias Scharpff //! \author Tobias Leemann // diff --git a/src/mesa_pd/collision_detection/GeneralContactDetection.h b/src/mesa_pd/collision_detection/GeneralContactDetection.h index bf6d3fad6..69a95e508 100644 --- a/src/mesa_pd/collision_detection/GeneralContactDetection.h +++ b/src/mesa_pd/collision_detection/GeneralContactDetection.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GeneralContactDetection.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/collision_detection/Support.h b/src/mesa_pd/collision_detection/Support.h index 10e64af5e..e7ffebfd9 100644 --- a/src/mesa_pd/collision_detection/Support.h +++ b/src/mesa_pd/collision_detection/Support.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Support.h +//! \file //! \author Tobias Scharpff //! \author Tobias Leemann // diff --git a/src/mesa_pd/common/AABBConversion.h b/src/mesa_pd/common/AABBConversion.h index ade72f356..33896f25f 100644 --- a/src/mesa_pd/common/AABBConversion.h +++ b/src/mesa_pd/common/AABBConversion.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AABBConversion.h +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/common/Contains.h b/src/mesa_pd/common/Contains.h index 5bd17b840..2b13cd351 100644 --- a/src/mesa_pd/common/Contains.h +++ b/src/mesa_pd/common/Contains.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Contains.h +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/common/ParticleFunctions.h b/src/mesa_pd/common/ParticleFunctions.h index b546b36a7..bb1c89880 100644 --- a/src/mesa_pd/common/ParticleFunctions.h +++ b/src/mesa_pd/common/ParticleFunctions.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleFunctions.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/common/RayParticleIntersection.h b/src/mesa_pd/common/RayParticleIntersection.h index 097fb3848..d1c9ce912 100644 --- a/src/mesa_pd/common/RayParticleIntersection.h +++ b/src/mesa_pd/common/RayParticleIntersection.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file RayParticleIntersection.h +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ContactAccessor.h b/src/mesa_pd/data/ContactAccessor.h index 470eb0b7c..dfa293bc9 100644 --- a/src/mesa_pd/data/ContactAccessor.h +++ b/src/mesa_pd/data/ContactAccessor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactAccessor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ContactHistory.h b/src/mesa_pd/data/ContactHistory.h index 2e8712209..48bc77b53 100644 --- a/src/mesa_pd/data/ContactHistory.h +++ b/src/mesa_pd/data/ContactHistory.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactHistory.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ContactStorage.h b/src/mesa_pd/data/ContactStorage.h index 0de025bac..67f84e680 100644 --- a/src/mesa_pd/data/ContactStorage.h +++ b/src/mesa_pd/data/ContactStorage.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/src/mesa_pd/data/DataTypes.h b/src/mesa_pd/data/DataTypes.h index 49da2f963..4c38e3726 100644 --- a/src/mesa_pd/data/DataTypes.h +++ b/src/mesa_pd/data/DataTypes.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DataTypes.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/Flags.h b/src/mesa_pd/data/Flags.h index 14d1593c2..5d6f70bc5 100644 --- a/src/mesa_pd/data/Flags.h +++ b/src/mesa_pd/data/Flags.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Flags.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/IAccessor.h b/src/mesa_pd/data/IAccessor.h index 2db039769..820541f3e 100644 --- a/src/mesa_pd/data/IAccessor.h +++ b/src/mesa_pd/data/IAccessor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IAccessor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/IContactAccessor.h b/src/mesa_pd/data/IContactAccessor.h index 68382fa9b..5cd7e8957 100644 --- a/src/mesa_pd/data/IContactAccessor.h +++ b/src/mesa_pd/data/IContactAccessor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IContactAccessor.h +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/LinkedCells.h b/src/mesa_pd/data/LinkedCells.h index 3915558a9..9ba699fd0 100644 --- a/src/mesa_pd/data/LinkedCells.h +++ b/src/mesa_pd/data/LinkedCells.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ParticleAccessor.h b/src/mesa_pd/data/ParticleAccessor.h index a00eb26c3..4da6f59ee 100644 --- a/src/mesa_pd/data/ParticleAccessor.h +++ b/src/mesa_pd/data/ParticleAccessor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleAccessor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ParticleAccessorWithShape.h b/src/mesa_pd/data/ParticleAccessorWithShape.h index 3773468fa..7f3413c12 100644 --- a/src/mesa_pd/data/ParticleAccessorWithShape.h +++ b/src/mesa_pd/data/ParticleAccessorWithShape.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleAccessorWithShape.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ParticleStorage.h b/src/mesa_pd/data/ParticleStorage.h index f4f8de7e5..33def90f5 100644 --- a/src/mesa_pd/data/ParticleStorage.h +++ b/src/mesa_pd/data/ParticleStorage.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/STLOverloads.h b/src/mesa_pd/data/STLOverloads.h index 7a929e54c..b72c4b375 100644 --- a/src/mesa_pd/data/STLOverloads.h +++ b/src/mesa_pd/data/STLOverloads.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file STLOverloads.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/ShapeStorage.h b/src/mesa_pd/data/ShapeStorage.h index 7fdb72a6a..3b6ca96ef 100644 --- a/src/mesa_pd/data/ShapeStorage.h +++ b/src/mesa_pd/data/ShapeStorage.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GeometryStorage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/SparseLinkedCells.h b/src/mesa_pd/data/SparseLinkedCells.h index 7185c2988..2c184de47 100644 --- a/src/mesa_pd/data/SparseLinkedCells.h +++ b/src/mesa_pd/data/SparseLinkedCells.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SparseLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/BaseShape.h b/src/mesa_pd/data/shape/BaseShape.h index 20ab37d2e..abd1eb511 100644 --- a/src/mesa_pd/data/shape/BaseShape.h +++ b/src/mesa_pd/data/shape/BaseShape.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BaseShape.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/Box.h b/src/mesa_pd/data/shape/Box.h index cb67d2d63..08f135e86 100644 --- a/src/mesa_pd/data/shape/Box.h +++ b/src/mesa_pd/data/shape/Box.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Box.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/ConvexPolyhedron.h b/src/mesa_pd/data/shape/ConvexPolyhedron.h index cad5c6586..8bb9ec0b5 100644 --- a/src/mesa_pd/data/shape/ConvexPolyhedron.h +++ b/src/mesa_pd/data/shape/ConvexPolyhedron.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ConvexPolyhedron.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/CylindricalBoundary.h b/src/mesa_pd/data/shape/CylindricalBoundary.h index 81a04d7e4..b7bb74051 100644 --- a/src/mesa_pd/data/shape/CylindricalBoundary.h +++ b/src/mesa_pd/data/shape/CylindricalBoundary.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CylindricalBoundary.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/Ellipsoid.h b/src/mesa_pd/data/shape/Ellipsoid.h index 7101209cb..e4b08ef90 100644 --- a/src/mesa_pd/data/shape/Ellipsoid.h +++ b/src/mesa_pd/data/shape/Ellipsoid.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Ellipsoid.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/HalfSpace.h b/src/mesa_pd/data/shape/HalfSpace.h index 87b53eaf9..8145fc2c4 100644 --- a/src/mesa_pd/data/shape/HalfSpace.h +++ b/src/mesa_pd/data/shape/HalfSpace.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HalfSpace.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/ShapeTypes.cpp b/src/mesa_pd/data/shape/ShapeTypes.cpp index d33273b37..4eb52cd05 100644 --- a/src/mesa_pd/data/shape/ShapeTypes.cpp +++ b/src/mesa_pd/data/shape/ShapeTypes.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ShapeTypes.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/data/shape/Sphere.h b/src/mesa_pd/data/shape/Sphere.h index 5192c58b1..01b2ca0f7 100644 --- a/src/mesa_pd/data/shape/Sphere.h +++ b/src/mesa_pd/data/shape/Sphere.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Sphere.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/BlockForestDataHandling.cpp b/src/mesa_pd/domain/BlockForestDataHandling.cpp index 1a75c1384..29316a656 100644 --- a/src/mesa_pd/domain/BlockForestDataHandling.cpp +++ b/src/mesa_pd/domain/BlockForestDataHandling.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestDataHandling.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/BlockForestDataHandling.h b/src/mesa_pd/domain/BlockForestDataHandling.h index 338c6a649..2fae4d119 100644 --- a/src/mesa_pd/domain/BlockForestDataHandling.h +++ b/src/mesa_pd/domain/BlockForestDataHandling.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestDataHandling.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/BlockForestDomain.cpp b/src/mesa_pd/domain/BlockForestDomain.cpp index c4d15778d..2614b9d29 100644 --- a/src/mesa_pd/domain/BlockForestDomain.cpp +++ b/src/mesa_pd/domain/BlockForestDomain.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestDomain.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/BlockForestDomain.h b/src/mesa_pd/domain/BlockForestDomain.h index e4d01fbb9..7df1f9b68 100644 --- a/src/mesa_pd/domain/BlockForestDomain.h +++ b/src/mesa_pd/domain/BlockForestDomain.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestDomain.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/IDomain.h b/src/mesa_pd/domain/IDomain.h index 532a10e02..536aeb2ff 100644 --- a/src/mesa_pd/domain/IDomain.h +++ b/src/mesa_pd/domain/IDomain.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IDomain.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/InfiniteDomain.h b/src/mesa_pd/domain/InfiniteDomain.h index 3e98e8246..b9dc4f322 100644 --- a/src/mesa_pd/domain/InfiniteDomain.h +++ b/src/mesa_pd/domain/InfiniteDomain.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InfiniteDomain.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/domain/InfoCollection.h b/src/mesa_pd/domain/InfoCollection.h index 90df6dbf7..dc6047c96 100644 --- a/src/mesa_pd/domain/InfoCollection.h +++ b/src/mesa_pd/domain/InfoCollection.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InfoCollection.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/AssocToBlock.h b/src/mesa_pd/kernel/AssocToBlock.h index f25008abc..a9a77260d 100644 --- a/src/mesa_pd/kernel/AssocToBlock.h +++ b/src/mesa_pd/kernel/AssocToBlock.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AssocToBlock.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/DetectAndStoreContacts.h b/src/mesa_pd/kernel/DetectAndStoreContacts.h index 5a7900e43..7656703b9 100644 --- a/src/mesa_pd/kernel/DetectAndStoreContacts.h +++ b/src/mesa_pd/kernel/DetectAndStoreContacts.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DetectAndStoreContacts.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/src/mesa_pd/kernel/DoubleCast.h b/src/mesa_pd/kernel/DoubleCast.h index 6f7851bfe..c306c989d 100644 --- a/src/mesa_pd/kernel/DoubleCast.h +++ b/src/mesa_pd/kernel/DoubleCast.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SingleCast.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/ExplicitEuler.h b/src/mesa_pd/kernel/ExplicitEuler.h index 639e3671a..bf1bfa660 100644 --- a/src/mesa_pd/kernel/ExplicitEuler.h +++ b/src/mesa_pd/kernel/ExplicitEuler.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEuler.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/ExplicitEulerWithShape.h b/src/mesa_pd/kernel/ExplicitEulerWithShape.h index d66d9a8aa..06ed0c232 100644 --- a/src/mesa_pd/kernel/ExplicitEulerWithShape.h +++ b/src/mesa_pd/kernel/ExplicitEulerWithShape.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEuler.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/ForceLJ.h b/src/mesa_pd/kernel/ForceLJ.h index b937372b9..483e586b7 100644 --- a/src/mesa_pd/kernel/ForceLJ.h +++ b/src/mesa_pd/kernel/ForceLJ.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ForceLJ.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/HCSITSRelaxationStep.h b/src/mesa_pd/kernel/HCSITSRelaxationStep.h index 10d876999..5d9ac3a76 100644 --- a/src/mesa_pd/kernel/HCSITSRelaxationStep.h +++ b/src/mesa_pd/kernel/HCSITSRelaxationStep.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HCSITSRelaxationStep.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/src/mesa_pd/kernel/HeatConduction.h b/src/mesa_pd/kernel/HeatConduction.h index 57e60cbcc..b474db018 100644 --- a/src/mesa_pd/kernel/HeatConduction.h +++ b/src/mesa_pd/kernel/HeatConduction.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HeatConduction.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/InitContactsForHCSITS.h b/src/mesa_pd/kernel/InitContactsForHCSITS.h index e2d147952..fae1131c7 100644 --- a/src/mesa_pd/kernel/InitContactsForHCSITS.h +++ b/src/mesa_pd/kernel/InitContactsForHCSITS.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InitContactsForHCSITS.h +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/InitParticlesForHCSITS.h b/src/mesa_pd/kernel/InitParticlesForHCSITS.h index 5a72e4fad..aba85f763 100644 --- a/src/mesa_pd/kernel/InitParticlesForHCSITS.h +++ b/src/mesa_pd/kernel/InitParticlesForHCSITS.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InitParticlesForHCSITS.h +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/InsertParticleIntoLinkedCells.h b/src/mesa_pd/kernel/InsertParticleIntoLinkedCells.h index 6f693bce6..a2cbd5c57 100644 --- a/src/mesa_pd/kernel/InsertParticleIntoLinkedCells.h +++ b/src/mesa_pd/kernel/InsertParticleIntoLinkedCells.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InsertParticleIntoLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h b/src/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h index a473a6fbb..6975337c4 100644 --- a/src/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h +++ b/src/mesa_pd/kernel/InsertParticleIntoSparseLinkedCells.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file InsertParticleIntoSparseLinkedCells.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/IntegrateParticlesHCSITS.h b/src/mesa_pd/kernel/IntegrateParticlesHCSITS.h index 7cc75be73..0f00fc9a0 100644 --- a/src/mesa_pd/kernel/IntegrateParticlesHCSITS.h +++ b/src/mesa_pd/kernel/IntegrateParticlesHCSITS.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IntegrateParticlesHCSITS.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Tobias Leemann <tobias.leemann@fau.de> // diff --git a/src/mesa_pd/kernel/LinearSpringDashpot.h b/src/mesa_pd/kernel/LinearSpringDashpot.h index acf15d844..3a57f56c0 100644 --- a/src/mesa_pd/kernel/LinearSpringDashpot.h +++ b/src/mesa_pd/kernel/LinearSpringDashpot.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinearSpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Christoph Rettinger <christoph.rettinger@fau.de> // diff --git a/src/mesa_pd/kernel/NonLinearSpringDashpot.h b/src/mesa_pd/kernel/NonLinearSpringDashpot.h index 987cff4ef..6486e0ec5 100644 --- a/src/mesa_pd/kernel/NonLinearSpringDashpot.h +++ b/src/mesa_pd/kernel/NonLinearSpringDashpot.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file NonLinearSpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \author Christoph Rettinger <christoph.rettinger@fau.de> // diff --git a/src/mesa_pd/kernel/PFCDamping.h b/src/mesa_pd/kernel/PFCDamping.h index 386df1229..1442226e9 100644 --- a/src/mesa_pd/kernel/PFCDamping.h +++ b/src/mesa_pd/kernel/PFCDamping.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PFCDamping.h +//! \file //! \author Igor Ostanin <i.ostanin@skoltech.ru> //! \author Grigorii Drozdov, <drozd013@umn.edu> // diff --git a/src/mesa_pd/kernel/ParticleSelector.h b/src/mesa_pd/kernel/ParticleSelector.h index 7a09913ca..85d8b81b2 100644 --- a/src/mesa_pd/kernel/ParticleSelector.h +++ b/src/mesa_pd/kernel/ParticleSelector.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleSelector.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/SemiImplicitEuler.h b/src/mesa_pd/kernel/SemiImplicitEuler.h index cf0df0734..13963d4f5 100644 --- a/src/mesa_pd/kernel/SemiImplicitEuler.h +++ b/src/mesa_pd/kernel/SemiImplicitEuler.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SemiImplicitEuler.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/SingleCast.h b/src/mesa_pd/kernel/SingleCast.h index b8ae75717..22ab3bde4 100644 --- a/src/mesa_pd/kernel/SingleCast.h +++ b/src/mesa_pd/kernel/SingleCast.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SingleCast.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/SpringDashpot.h b/src/mesa_pd/kernel/SpringDashpot.h index 60957e0fa..1388e85c8 100644 --- a/src/mesa_pd/kernel/SpringDashpot.h +++ b/src/mesa_pd/kernel/SpringDashpot.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpot.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/SpringDashpotSpring.h b/src/mesa_pd/kernel/SpringDashpotSpring.h index f2f87671a..0fbd2e684 100644 --- a/src/mesa_pd/kernel/SpringDashpotSpring.h +++ b/src/mesa_pd/kernel/SpringDashpotSpring.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpotSpring.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/TemperatureIntegration.h b/src/mesa_pd/kernel/TemperatureIntegration.h index c90eb3ffc..8f8a771ce 100644 --- a/src/mesa_pd/kernel/TemperatureIntegration.h +++ b/src/mesa_pd/kernel/TemperatureIntegration.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TemperatureIntegration.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/kernel/VelocityVerlet.h b/src/mesa_pd/kernel/VelocityVerlet.h index 69ed50dcb..1564842e4 100644 --- a/src/mesa_pd/kernel/VelocityVerlet.h +++ b/src/mesa_pd/kernel/VelocityVerlet.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityVerlet.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/BroadcastProperty.h b/src/mesa_pd/mpi/BroadcastProperty.h index 27c4542cf..5b3313eb4 100644 --- a/src/mesa_pd/mpi/BroadcastProperty.h +++ b/src/mesa_pd/mpi/BroadcastProperty.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BroadcastProperty.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ClearGhostOwnerSync.h b/src/mesa_pd/mpi/ClearGhostOwnerSync.h index aff6b8dcc..b8713e27a 100644 --- a/src/mesa_pd/mpi/ClearGhostOwnerSync.h +++ b/src/mesa_pd/mpi/ClearGhostOwnerSync.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearGhostOwnerSync.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ClearNextNeighborSync.h b/src/mesa_pd/mpi/ClearNextNeighborSync.h index efadbe262..b091b70bb 100644 --- a/src/mesa_pd/mpi/ClearNextNeighborSync.h +++ b/src/mesa_pd/mpi/ClearNextNeighborSync.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearNextNeighborSync.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ContactFilter.h b/src/mesa_pd/mpi/ContactFilter.h index cfcada06b..3ba3bc9b5 100644 --- a/src/mesa_pd/mpi/ContactFilter.h +++ b/src/mesa_pd/mpi/ContactFilter.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactFilter.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ReduceContactHistory.h b/src/mesa_pd/mpi/ReduceContactHistory.h index 7d304f09d..efd4e9bd8 100644 --- a/src/mesa_pd/mpi/ReduceContactHistory.h +++ b/src/mesa_pd/mpi/ReduceContactHistory.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ReduceContactHistory.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ReduceProperty.h b/src/mesa_pd/mpi/ReduceProperty.h index 46736d9ed..8722179ee 100644 --- a/src/mesa_pd/mpi/ReduceProperty.h +++ b/src/mesa_pd/mpi/ReduceProperty.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncProperty.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/RemoveAndNotify.cpp b/src/mesa_pd/mpi/RemoveAndNotify.cpp index c04a40f94..d54a8c5cc 100644 --- a/src/mesa_pd/mpi/RemoveAndNotify.cpp +++ b/src/mesa_pd/mpi/RemoveAndNotify.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file RemoveAndNotify.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/RemoveAndNotify.h b/src/mesa_pd/mpi/RemoveAndNotify.h index 90cf8d3f1..753de7195 100644 --- a/src/mesa_pd/mpi/RemoveAndNotify.h +++ b/src/mesa_pd/mpi/RemoveAndNotify.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file RemoveAndNotify.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/ShapePackUnpack.h b/src/mesa_pd/mpi/ShapePackUnpack.h index dd9070355..4461369ec 100644 --- a/src/mesa_pd/mpi/ShapePackUnpack.h +++ b/src/mesa_pd/mpi/ShapePackUnpack.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ShapePackUnpack.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncGhostOwners.cpp b/src/mesa_pd/mpi/SyncGhostOwners.cpp index dd13a9fb2..e9eceaf88 100644 --- a/src/mesa_pd/mpi/SyncGhostOwners.cpp +++ b/src/mesa_pd/mpi/SyncGhostOwners.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwners.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncGhostOwners.h b/src/mesa_pd/mpi/SyncGhostOwners.h index 02089e33c..98043c6a2 100644 --- a/src/mesa_pd/mpi/SyncGhostOwners.h +++ b/src/mesa_pd/mpi/SyncGhostOwners.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwners.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighbors.cpp b/src/mesa_pd/mpi/SyncNextNeighbors.cpp index 52d922375..44f3946e7 100644 --- a/src/mesa_pd/mpi/SyncNextNeighbors.cpp +++ b/src/mesa_pd/mpi/SyncNextNeighbors.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighbors.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighbors.h b/src/mesa_pd/mpi/SyncNextNeighbors.h index 31e51f56b..e07d0c14d 100644 --- a/src/mesa_pd/mpi/SyncNextNeighbors.h +++ b/src/mesa_pd/mpi/SyncNextNeighbors.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighbors.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.cpp b/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.cpp index 34778d0e2..f4adbf79f 100644 --- a/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.cpp +++ b/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsBlockForest.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.h b/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.h index 8c04c3cee..060dfd552 100644 --- a/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.h +++ b/src/mesa_pd/mpi/SyncNextNeighborsBlockForest.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsBlockForest.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp index 145b95cd8..10e473b63 100644 --- a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp +++ b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsNoGhosts.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h index a95bc567f..d39bb8b2f 100644 --- a/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h +++ b/src/mesa_pd/mpi/SyncNextNeighborsNoGhosts.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsNoGhosts.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ContactHistoryNotification.h b/src/mesa_pd/mpi/notifications/ContactHistoryNotification.h index b177f313c..92bfe1dac 100644 --- a/src/mesa_pd/mpi/notifications/ContactHistoryNotification.h +++ b/src/mesa_pd/mpi/notifications/ContactHistoryNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactHistoryNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ForceTorqueNotification.h b/src/mesa_pd/mpi/notifications/ForceTorqueNotification.h index 2a41c9d4f..eb5c3198f 100644 --- a/src/mesa_pd/mpi/notifications/ForceTorqueNotification.h +++ b/src/mesa_pd/mpi/notifications/ForceTorqueNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ForceTorqueNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/HeatFluxNotification.h b/src/mesa_pd/mpi/notifications/HeatFluxNotification.h index a2ab05d07..5ed1d294c 100644 --- a/src/mesa_pd/mpi/notifications/HeatFluxNotification.h +++ b/src/mesa_pd/mpi/notifications/HeatFluxNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HeatFluxNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h b/src/mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h index 615535160..7d6ac1594 100644 --- a/src/mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h +++ b/src/mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HydrodynamicForceTorqueNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/NewGhostParticleNotification.h b/src/mesa_pd/mpi/notifications/NewGhostParticleNotification.h index 3c929cee4..6a36909af 100644 --- a/src/mesa_pd/mpi/notifications/NewGhostParticleNotification.h +++ b/src/mesa_pd/mpi/notifications/NewGhostParticleNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file NewGhostParticleNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/NotificationType.h b/src/mesa_pd/mpi/notifications/NotificationType.h index 66cf5bf95..1e27ec347 100644 --- a/src/mesa_pd/mpi/notifications/NotificationType.h +++ b/src/mesa_pd/mpi/notifications/NotificationType.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file NotificationType.h +//! \file //! \author Tobias Preclik //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \brief Header file for the notification types diff --git a/src/mesa_pd/mpi/notifications/PackNotification.h b/src/mesa_pd/mpi/notifications/PackNotification.h index fe3d5212b..8a0e2b9e3 100644 --- a/src/mesa_pd/mpi/notifications/PackNotification.h +++ b/src/mesa_pd/mpi/notifications/PackNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PackNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParseMessage.h b/src/mesa_pd/mpi/notifications/ParseMessage.h index caf0e0f89..32ae118a5 100644 --- a/src/mesa_pd/mpi/notifications/ParseMessage.h +++ b/src/mesa_pd/mpi/notifications/ParseMessage.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParseMessage.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> //! \brief Parsing of messages // diff --git a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h index b01a4dbeb..c17b5ec79 100644 --- a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleCopyNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h index c4e1c2417..c9e3b02ba 100644 --- a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleGhostCopyNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleMigrationNotification.h b/src/mesa_pd/mpi/notifications/ParticleMigrationNotification.h index 836fa29ee..847368ed4 100644 --- a/src/mesa_pd/mpi/notifications/ParticleMigrationNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleMigrationNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleMigrationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h b/src/mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h index dc406fa1d..6e08ba607 100644 --- a/src/mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleRemoteMigrationNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemoteMigrationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleRemovalInformationNotification.h b/src/mesa_pd/mpi/notifications/ParticleRemovalInformationNotification.h index aec2ccdfb..e0813d564 100644 --- a/src/mesa_pd/mpi/notifications/ParticleRemovalInformationNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleRemovalInformationNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemovalInformationNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleRemovalNotification.h b/src/mesa_pd/mpi/notifications/ParticleRemovalNotification.h index 8740e43fd..7b674f4d8 100644 --- a/src/mesa_pd/mpi/notifications/ParticleRemovalNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleRemovalNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleRemovalNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h index d84508200..95d0d7e37 100644 --- a/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleUpdateNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleUpdateNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/VelocityCorrectionNotification.h b/src/mesa_pd/mpi/notifications/VelocityCorrectionNotification.h index dd4ca2a89..7f9347f91 100644 --- a/src/mesa_pd/mpi/notifications/VelocityCorrectionNotification.h +++ b/src/mesa_pd/mpi/notifications/VelocityCorrectionNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityCorrectionNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/VelocityUpdateNotification.h b/src/mesa_pd/mpi/notifications/VelocityUpdateNotification.h index 7f8c1e7c7..f526d99c8 100644 --- a/src/mesa_pd/mpi/notifications/VelocityUpdateNotification.h +++ b/src/mesa_pd/mpi/notifications/VelocityUpdateNotification.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityCorrectionNotification.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/mpi/notifications/reset.h b/src/mesa_pd/mpi/notifications/reset.h index 24bab4533..ff7449e37 100644 --- a/src/mesa_pd/mpi/notifications/reset.h +++ b/src/mesa_pd/mpi/notifications/reset.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file reset.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/sorting/HilbertCompareFunctor.cpp b/src/mesa_pd/sorting/HilbertCompareFunctor.cpp index 2cf2a8466..e14de8d24 100644 --- a/src/mesa_pd/sorting/HilbertCompareFunctor.cpp +++ b/src/mesa_pd/sorting/HilbertCompareFunctor.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HilbertCompareFunctor.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/sorting/HilbertCompareFunctor.h b/src/mesa_pd/sorting/HilbertCompareFunctor.h index 70e91665f..35a7ca9c2 100644 --- a/src/mesa_pd/sorting/HilbertCompareFunctor.h +++ b/src/mesa_pd/sorting/HilbertCompareFunctor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HilbertCompareFunctor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/sorting/LinearizedCompareFunctor.cpp b/src/mesa_pd/sorting/LinearizedCompareFunctor.cpp index 7588285a4..bb9d0cb14 100644 --- a/src/mesa_pd/sorting/LinearizedCompareFunctor.cpp +++ b/src/mesa_pd/sorting/LinearizedCompareFunctor.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinearizedCompareFunctor.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/sorting/LinearizedCompareFunctor.h b/src/mesa_pd/sorting/LinearizedCompareFunctor.h index 9caf02bd0..f08b7bec0 100644 --- a/src/mesa_pd/sorting/LinearizedCompareFunctor.h +++ b/src/mesa_pd/sorting/LinearizedCompareFunctor.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinearizedCompareFunctor.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/MeshParticleVTKOutput.h b/src/mesa_pd/vtk/ConvexPolyhedron/MeshParticleVTKOutput.h index f39b7c5bc..95127646d 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/MeshParticleVTKOutput.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/MeshParticleVTKOutput.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file MeshVTKOutput.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/DataSourceAdapters.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/DataSourceAdapters.h index 8eb8a03f4..2db947f38 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/DataSourceAdapters.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/DataSourceAdapters.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DataSourceAdapters.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/FaceDataSource.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/FaceDataSource.h index 94479be44..4ab4de70f 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/FaceDataSource.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/FaceDataSource.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleFaceDataSource.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorFaceDataSource.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorFaceDataSource.h index f1442527d..02c5fec6b 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorFaceDataSource.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorFaceDataSource.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleOutputSelectorFaceDataSource.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorVertexDataSource.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorVertexDataSource.h index 1f8a7fd05..f569865a5 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorVertexDataSource.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/OutputSelectorVertexDataSource.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleOutputSelectorVertexDataSource.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/SurfaceVelocityVertexDataSource.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/SurfaceVelocityVertexDataSource.h index 03eec9d9e..2b27499a2 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/SurfaceVelocityVertexDataSource.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/SurfaceVelocityVertexDataSource.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleOutputSelectorVertexDataSource.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/VertexDataSource.h b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/VertexDataSource.h index bef238fa0..41adedfd9 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/VertexDataSource.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/data_sources/VertexDataSource.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleVertexDataSource.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ConvexPolyhedron/tesselation/ConvexPolyhedronTesselation.h b/src/mesa_pd/vtk/ConvexPolyhedron/tesselation/ConvexPolyhedronTesselation.h index 87bed413d..7aa9fa690 100644 --- a/src/mesa_pd/vtk/ConvexPolyhedron/tesselation/ConvexPolyhedronTesselation.h +++ b/src/mesa_pd/vtk/ConvexPolyhedron/tesselation/ConvexPolyhedronTesselation.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ConvexPolyhedronTesselation.h +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/OutputSelector.h b/src/mesa_pd/vtk/OutputSelector.h index 177b38f8b..32ceb5dbd 100644 --- a/src/mesa_pd/vtk/OutputSelector.h +++ b/src/mesa_pd/vtk/OutputSelector.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file OutputSelector.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ParticleVtkOutput.cpp b/src/mesa_pd/vtk/ParticleVtkOutput.cpp index 018670be9..6093eeb30 100644 --- a/src/mesa_pd/vtk/ParticleVtkOutput.cpp +++ b/src/mesa_pd/vtk/ParticleVtkOutput.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleVtkOutput.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/ParticleVtkOutput.h b/src/mesa_pd/vtk/ParticleVtkOutput.h index 5cbe88a6d..dcd90fe37 100644 --- a/src/mesa_pd/vtk/ParticleVtkOutput.h +++ b/src/mesa_pd/vtk/ParticleVtkOutput.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleVtkOutput.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/TensorGlyph.cpp b/src/mesa_pd/vtk/TensorGlyph.cpp index 4f058f667..c886731d5 100644 --- a/src/mesa_pd/vtk/TensorGlyph.cpp +++ b/src/mesa_pd/vtk/TensorGlyph.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TensorGlyph.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/TensorGlyph.h b/src/mesa_pd/vtk/TensorGlyph.h index d739f8b00..f77c19abd 100644 --- a/src/mesa_pd/vtk/TensorGlyph.h +++ b/src/mesa_pd/vtk/TensorGlyph.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TensorGlyph.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/src/mesa_pd/vtk/WriteOutput.h b/src/mesa_pd/vtk/WriteOutput.h index b6016ea79..91ef8141f 100644 --- a/src/mesa_pd/vtk/WriteOutput.h +++ b/src/mesa_pd/vtk/WriteOutput.h @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file WriteOutput.h +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/ContactDetection.cpp b/tests/mesa_pd/ContactDetection.cpp index 3b63a9a7e..41e62d75f 100644 --- a/tests/mesa_pd/ContactDetection.cpp +++ b/tests/mesa_pd/ContactDetection.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ContactDetection.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/DropTestAnalytic.cpp b/tests/mesa_pd/DropTestAnalytic.cpp index 3b257e23c..827f0951f 100644 --- a/tests/mesa_pd/DropTestAnalytic.cpp +++ b/tests/mesa_pd/DropTestAnalytic.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DropTestAnalytic.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/DropTestGeneral.cpp b/tests/mesa_pd/DropTestGeneral.cpp index 0ab23c4fa..52495a885 100644 --- a/tests/mesa_pd/DropTestGeneral.cpp +++ b/tests/mesa_pd/DropTestGeneral.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DropTestGeneral.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/Sorting.cpp b/tests/mesa_pd/Sorting.cpp index d4408cd71..178ffc2b2 100644 --- a/tests/mesa_pd/Sorting.cpp +++ b/tests/mesa_pd/Sorting.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Sorting.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/AnalyticCollisionFunctions.cpp b/tests/mesa_pd/collision_detection/AnalyticCollisionFunctions.cpp index 1dc914aae..9f171a325 100644 --- a/tests/mesa_pd/collision_detection/AnalyticCollisionFunctions.cpp +++ b/tests/mesa_pd/collision_detection/AnalyticCollisionFunctions.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AnalyticCollisionFunctions.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/AnalyticContactDetection.cpp b/tests/mesa_pd/collision_detection/AnalyticContactDetection.cpp index c191edbd6..911e7344d 100644 --- a/tests/mesa_pd/collision_detection/AnalyticContactDetection.cpp +++ b/tests/mesa_pd/collision_detection/AnalyticContactDetection.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file AnalyticContactDetection.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/BoxSupport.cpp b/tests/mesa_pd/collision_detection/BoxSupport.cpp index 08ae7bcc0..91b20ac41 100644 --- a/tests/mesa_pd/collision_detection/BoxSupport.cpp +++ b/tests/mesa_pd/collision_detection/BoxSupport.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BoxSupport.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/ConvexPolyhedron_GJK_EPA.cpp b/tests/mesa_pd/collision_detection/ConvexPolyhedron_GJK_EPA.cpp index 037073c9c..2436e8968 100644 --- a/tests/mesa_pd/collision_detection/ConvexPolyhedron_GJK_EPA.cpp +++ b/tests/mesa_pd/collision_detection/ConvexPolyhedron_GJK_EPA.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CollisionTest.cpp +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/EPA.cpp b/tests/mesa_pd/collision_detection/EPA.cpp index fa171a209..512100a26 100644 --- a/tests/mesa_pd/collision_detection/EPA.cpp +++ b/tests/mesa_pd/collision_detection/EPA.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file EPA.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/EllipsoidSupport.cpp b/tests/mesa_pd/collision_detection/EllipsoidSupport.cpp index 820d34005..03d2d86b8 100644 --- a/tests/mesa_pd/collision_detection/EllipsoidSupport.cpp +++ b/tests/mesa_pd/collision_detection/EllipsoidSupport.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file EllipsoidSupport.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/GJK.cpp b/tests/mesa_pd/collision_detection/GJK.cpp index 43f044c5d..35f4a6672 100644 --- a/tests/mesa_pd/collision_detection/GJK.cpp +++ b/tests/mesa_pd/collision_detection/GJK.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GJK.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/GJK_EPA.cpp b/tests/mesa_pd/collision_detection/GJK_EPA.cpp index 05000b339..998276419 100644 --- a/tests/mesa_pd/collision_detection/GJK_EPA.cpp +++ b/tests/mesa_pd/collision_detection/GJK_EPA.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GJK_EPA.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/GeneralContactDetection.cpp b/tests/mesa_pd/collision_detection/GeneralContactDetection.cpp index 9f3be3feb..1dcb49882 100644 --- a/tests/mesa_pd/collision_detection/GeneralContactDetection.cpp +++ b/tests/mesa_pd/collision_detection/GeneralContactDetection.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GeneralContactDetection.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/collision_detection/SphereSupport.cpp b/tests/mesa_pd/collision_detection/SphereSupport.cpp index 2c94e0fc5..359be9b70 100644 --- a/tests/mesa_pd/collision_detection/SphereSupport.cpp +++ b/tests/mesa_pd/collision_detection/SphereSupport.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SphereSupport.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/common/IntersectionRatio.cpp b/tests/mesa_pd/common/IntersectionRatio.cpp index d1184f837..71db12ae5 100644 --- a/tests/mesa_pd/common/IntersectionRatio.cpp +++ b/tests/mesa_pd/common/IntersectionRatio.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IntersectionRatio.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/data/ConvexPolyhedron.cpp b/tests/mesa_pd/data/ConvexPolyhedron.cpp index ff9f2ab76..6636e9214 100644 --- a/tests/mesa_pd/data/ConvexPolyhedron.cpp +++ b/tests/mesa_pd/data/ConvexPolyhedron.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file MeshMesapdConvexPolyhedronTest.cpp +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/tests/mesa_pd/data/Flags.cpp b/tests/mesa_pd/data/Flags.cpp index e54cdcd85..4a9ccd3a9 100644 --- a/tests/mesa_pd/data/Flags.cpp +++ b/tests/mesa_pd/data/Flags.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Flags.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/data/LinkedCells.cpp b/tests/mesa_pd/data/LinkedCells.cpp index 0653c116d..b56ac1629 100644 --- a/tests/mesa_pd/data/LinkedCells.cpp +++ b/tests/mesa_pd/data/LinkedCells.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinkedCells.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/data/ParticleStorage.cpp b/tests/mesa_pd/data/ParticleStorage.cpp index ce3579292..df2b938e0 100644 --- a/tests/mesa_pd/data/ParticleStorage.cpp +++ b/tests/mesa_pd/data/ParticleStorage.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ParticleStorage.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/data/SparseLinkedCells.cpp b/tests/mesa_pd/data/SparseLinkedCells.cpp index 090e739e2..cd4ebe519 100644 --- a/tests/mesa_pd/data/SparseLinkedCells.cpp +++ b/tests/mesa_pd/data/SparseLinkedCells.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SparseLinkedCells.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/BlockForestDomain.cpp b/tests/mesa_pd/domain/BlockForestDomain.cpp index 33d5a4f72..297cbd5fe 100644 --- a/tests/mesa_pd/domain/BlockForestDomain.cpp +++ b/tests/mesa_pd/domain/BlockForestDomain.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestDomain.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/BlockForestSync.cpp b/tests/mesa_pd/domain/BlockForestSync.cpp index b0fe8cf5d..bbb3a933a 100644 --- a/tests/mesa_pd/domain/BlockForestSync.cpp +++ b/tests/mesa_pd/domain/BlockForestSync.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestSync.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/BlockForestSyncPeriodic.cpp b/tests/mesa_pd/domain/BlockForestSyncPeriodic.cpp index 8523ec9fb..6d8af3efb 100644 --- a/tests/mesa_pd/domain/BlockForestSyncPeriodic.cpp +++ b/tests/mesa_pd/domain/BlockForestSyncPeriodic.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BlockForestSync.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/DistanceCalculation.cpp b/tests/mesa_pd/domain/DistanceCalculation.cpp index ef4fffa00..5f871333d 100644 --- a/tests/mesa_pd/domain/DistanceCalculation.cpp +++ b/tests/mesa_pd/domain/DistanceCalculation.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DistanceCalculation.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/DynamicRefinement.cpp b/tests/mesa_pd/domain/DynamicRefinement.cpp index f9378da98..5f1f83ef7 100644 --- a/tests/mesa_pd/domain/DynamicRefinement.cpp +++ b/tests/mesa_pd/domain/DynamicRefinement.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DynamicRefinement.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/domain/SerializeDeserialize.cpp b/tests/mesa_pd/domain/SerializeDeserialize.cpp index 49517852b..9b7a63781 100644 --- a/tests/mesa_pd/domain/SerializeDeserialize.cpp +++ b/tests/mesa_pd/domain/SerializeDeserialize.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DynamicRefinement.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/ClearNextNeighborSync.cpp b/tests/mesa_pd/kernel/ClearNextNeighborSync.cpp index 19154dc7b..feae33e90 100644 --- a/tests/mesa_pd/kernel/ClearNextNeighborSync.cpp +++ b/tests/mesa_pd/kernel/ClearNextNeighborSync.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearNextNeighborSync.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp index ac16d145e..a9cb84564 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionLSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CoefficientOfRestitutionLSD.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp index c2bfbcfdb..5912892af 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionNLSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CoefficientOfRestitutionNLSD.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp b/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp index 910f5da3d..00fb53052 100644 --- a/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp +++ b/tests/mesa_pd/kernel/CoefficientOfRestitutionSD.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CoefficientOfRestitutionSD.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/DetectAndStoreContacts.cpp b/tests/mesa_pd/kernel/DetectAndStoreContacts.cpp index 25b192a53..5e4c2db77 100644 --- a/tests/mesa_pd/kernel/DetectAndStoreContacts.cpp +++ b/tests/mesa_pd/kernel/DetectAndStoreContacts.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DetectAndStoreCollisions.cpp +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/DoubleCast.cpp b/tests/mesa_pd/kernel/DoubleCast.cpp index 4e2c11cdc..0d2c80d04 100644 --- a/tests/mesa_pd/kernel/DoubleCast.cpp +++ b/tests/mesa_pd/kernel/DoubleCast.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DoubleCast.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/ExplicitEuler.cpp b/tests/mesa_pd/kernel/ExplicitEuler.cpp index 17d55505b..b4673d189 100644 --- a/tests/mesa_pd/kernel/ExplicitEuler.cpp +++ b/tests/mesa_pd/kernel/ExplicitEuler.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEuler.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/ForceLJ.cpp b/tests/mesa_pd/kernel/ForceLJ.cpp index 12c49b5c7..adcb643cd 100644 --- a/tests/mesa_pd/kernel/ForceLJ.cpp +++ b/tests/mesa_pd/kernel/ForceLJ.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ForceLJ.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/GenerateAnalyticContacts.cpp b/tests/mesa_pd/kernel/GenerateAnalyticContacts.cpp index 757587beb..4762aed06 100644 --- a/tests/mesa_pd/kernel/GenerateAnalyticContacts.cpp +++ b/tests/mesa_pd/kernel/GenerateAnalyticContacts.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GenerateAnalyticContacts.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/GenerateLinkedCells.cpp b/tests/mesa_pd/kernel/GenerateLinkedCells.cpp index d4c2f30c6..3ee5183cf 100644 --- a/tests/mesa_pd/kernel/GenerateLinkedCells.cpp +++ b/tests/mesa_pd/kernel/GenerateLinkedCells.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file GenerateLinkedCells.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/HCSITSKernels.cpp b/tests/mesa_pd/kernel/HCSITSKernels.cpp index c3cb9fd6d..4f0428f38 100644 --- a/tests/mesa_pd/kernel/HCSITSKernels.cpp +++ b/tests/mesa_pd/kernel/HCSITSKernels.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HCSITSKernels.cpp +//! \file //! \author Tobias Leemann <tobias.leemann@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/HeatConduction.cpp b/tests/mesa_pd/kernel/HeatConduction.cpp index 9c8c4cd9e..06d7c3323 100644 --- a/tests/mesa_pd/kernel/HeatConduction.cpp +++ b/tests/mesa_pd/kernel/HeatConduction.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HeatConduction.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/IntegratorAccuracy.cpp b/tests/mesa_pd/kernel/IntegratorAccuracy.cpp index e97c47106..433ecb546 100644 --- a/tests/mesa_pd/kernel/IntegratorAccuracy.cpp +++ b/tests/mesa_pd/kernel/IntegratorAccuracy.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file IntegratorAccuracy.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> //! \author Sebastian Eibl <sebastian.eibl@fau.de> // diff --git a/tests/mesa_pd/kernel/Interfaces.cpp b/tests/mesa_pd/kernel/Interfaces.cpp index 25fabf624..4c8769ec3 100644 --- a/tests/mesa_pd/kernel/Interfaces.cpp +++ b/tests/mesa_pd/kernel/Interfaces.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Interfaces.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/LinearSpringDashpot.cpp b/tests/mesa_pd/kernel/LinearSpringDashpot.cpp index 64f099e26..0b749b822 100644 --- a/tests/mesa_pd/kernel/LinearSpringDashpot.cpp +++ b/tests/mesa_pd/kernel/LinearSpringDashpot.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file DEMTangentialCollision.cpp +//! \file //! \author Christoph Rettinger <christoph.rettinger@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/LinkedCellsVsBruteForce.cpp b/tests/mesa_pd/kernel/LinkedCellsVsBruteForce.cpp index ce990842f..c52e39327 100644 --- a/tests/mesa_pd/kernel/LinkedCellsVsBruteForce.cpp +++ b/tests/mesa_pd/kernel/LinkedCellsVsBruteForce.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file LinkedCellsVsBruteForce.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/PFCDamping.cpp b/tests/mesa_pd/kernel/PFCDamping.cpp index 0329ef911..42966022e 100644 --- a/tests/mesa_pd/kernel/PFCDamping.cpp +++ b/tests/mesa_pd/kernel/PFCDamping.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PFCDamping.cpp +//! \file //! \author Igor Ostanin <i.ostanin@skoltech.ru> //! \author Grigorii Drozdov <drozd013@umn.edu> // diff --git a/tests/mesa_pd/kernel/SemiImplicitEuler.cpp b/tests/mesa_pd/kernel/SemiImplicitEuler.cpp index 2d3a22f84..551d016f1 100644 --- a/tests/mesa_pd/kernel/SemiImplicitEuler.cpp +++ b/tests/mesa_pd/kernel/SemiImplicitEuler.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SemiImplicitEuler.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SingleCast.cpp b/tests/mesa_pd/kernel/SingleCast.cpp index cf137df8c..4060635f7 100644 --- a/tests/mesa_pd/kernel/SingleCast.cpp +++ b/tests/mesa_pd/kernel/SingleCast.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SingleCast.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SpherePile.cpp b/tests/mesa_pd/kernel/SpherePile.cpp index 3f71e9297..6d5184862 100644 --- a/tests/mesa_pd/kernel/SpherePile.cpp +++ b/tests/mesa_pd/kernel/SpherePile.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpherePile.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SpringDashpot.cpp b/tests/mesa_pd/kernel/SpringDashpot.cpp index b9feabe92..1e90c9dd6 100644 --- a/tests/mesa_pd/kernel/SpringDashpot.cpp +++ b/tests/mesa_pd/kernel/SpringDashpot.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpot.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SyncGhostOwners.cpp b/tests/mesa_pd/kernel/SyncGhostOwners.cpp index cf16223ee..5c742f6f8 100644 --- a/tests/mesa_pd/kernel/SyncGhostOwners.cpp +++ b/tests/mesa_pd/kernel/SyncGhostOwners.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwners.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SyncGhostOwnersLarge.cpp b/tests/mesa_pd/kernel/SyncGhostOwnersLarge.cpp index b04dd3c60..2c66a4eba 100644 --- a/tests/mesa_pd/kernel/SyncGhostOwnersLarge.cpp +++ b/tests/mesa_pd/kernel/SyncGhostOwnersLarge.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncGhostOwnersLarge.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SyncNextNeighbors.cpp b/tests/mesa_pd/kernel/SyncNextNeighbors.cpp index c6de32e05..3a4329b16 100644 --- a/tests/mesa_pd/kernel/SyncNextNeighbors.cpp +++ b/tests/mesa_pd/kernel/SyncNextNeighbors.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighbors.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/SyncNextNeighborsBlockForest.cpp b/tests/mesa_pd/kernel/SyncNextNeighborsBlockForest.cpp index 6dfde66aa..14ea54e85 100644 --- a/tests/mesa_pd/kernel/SyncNextNeighborsBlockForest.cpp +++ b/tests/mesa_pd/kernel/SyncNextNeighborsBlockForest.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsBlockForest.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/TemperatureIntegration.cpp b/tests/mesa_pd/kernel/TemperatureIntegration.cpp index b84fc9cd2..47fd92072 100644 --- a/tests/mesa_pd/kernel/TemperatureIntegration.cpp +++ b/tests/mesa_pd/kernel/TemperatureIntegration.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TemperatureIntegration.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/VelocityVerlet.cpp b/tests/mesa_pd/kernel/VelocityVerlet.cpp index 1dba566fb..d82f349c0 100644 --- a/tests/mesa_pd/kernel/VelocityVerlet.cpp +++ b/tests/mesa_pd/kernel/VelocityVerlet.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityVerlet.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp index 4d180c321..51ef473f2 100644 --- a/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEulerInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp index a56e29914..8a5b5e917 100644 --- a/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ExplicitEulerInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp index b742e0d22..53edabb32 100644 --- a/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ForceLJInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp index 4e30eba2e..c204acc86 100644 --- a/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file HeatConductionInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp index 3f52ab357..d60c39fe6 100644 --- a/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PFCDampingInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp index ad498f1d9..b73f71a3d 100644 --- a/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SemiImplicitEulerInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp index b76620428..80837e900 100644 --- a/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SpringDashpotInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp index dfc209c39..d0cdb6099 100644 --- a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file TemperatureIntegrationInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp index 06d8507c7..1f5910166 100644 --- a/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityVerletInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp index 06d8507c7..1f5910166 100644 --- a/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityVerletInterfaceCheck.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/BroadcastProperty.cpp b/tests/mesa_pd/mpi/BroadcastProperty.cpp index de7a0a2d7..6082d41e4 100644 --- a/tests/mesa_pd/mpi/BroadcastProperty.cpp +++ b/tests/mesa_pd/mpi/BroadcastProperty.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file BroadcastProperty.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/ClearGhostOwnerSync.cpp b/tests/mesa_pd/mpi/ClearGhostOwnerSync.cpp index 84bd3f1bc..6940993fb 100644 --- a/tests/mesa_pd/mpi/ClearGhostOwnerSync.cpp +++ b/tests/mesa_pd/mpi/ClearGhostOwnerSync.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearGhostOwnerSync.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/ClearNextNeighborSync.cpp b/tests/mesa_pd/mpi/ClearNextNeighborSync.cpp index 19c1ebfa6..9c8d71ee1 100644 --- a/tests/mesa_pd/mpi/ClearNextNeighborSync.cpp +++ b/tests/mesa_pd/mpi/ClearNextNeighborSync.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ClearNextNeighborSync.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/Notifications.cpp b/tests/mesa_pd/mpi/Notifications.cpp index e6eeacca6..5f432d21b 100644 --- a/tests/mesa_pd/mpi/Notifications.cpp +++ b/tests/mesa_pd/mpi/Notifications.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Notifications.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/ReduceContactHistory.cpp b/tests/mesa_pd/mpi/ReduceContactHistory.cpp index 1135e1d93..0414ed75d 100644 --- a/tests/mesa_pd/mpi/ReduceContactHistory.cpp +++ b/tests/mesa_pd/mpi/ReduceContactHistory.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ReduceContactHistory.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/ReduceProperty.cpp b/tests/mesa_pd/mpi/ReduceProperty.cpp index 3f8138ac9..0c5335cd0 100644 --- a/tests/mesa_pd/mpi/ReduceProperty.cpp +++ b/tests/mesa_pd/mpi/ReduceProperty.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file ReduceProperty.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/ShapePackUnpack.cpp b/tests/mesa_pd/mpi/ShapePackUnpack.cpp index 3efe46404..16cca30ff 100644 --- a/tests/mesa_pd/mpi/ShapePackUnpack.cpp +++ b/tests/mesa_pd/mpi/ShapePackUnpack.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file PackUnpack.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp b/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp index 1dae83425..1df6e0ae8 100644 --- a/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp +++ b/tests/mesa_pd/mpi/SyncNextNeighborsNoGhosts.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file SyncNextNeighborsNoGhosts.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/mpi/VelocityCorrectionNotification.cpp b/tests/mesa_pd/mpi/VelocityCorrectionNotification.cpp index 79cd63515..0b66e9fc0 100644 --- a/tests/mesa_pd/mpi/VelocityCorrectionNotification.cpp +++ b/tests/mesa_pd/mpi/VelocityCorrectionNotification.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VelocityCorrectionNotification.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== diff --git a/tests/mesa_pd/vtk/ConvexPolyhedronVTKOutput.cpp b/tests/mesa_pd/vtk/ConvexPolyhedronVTKOutput.cpp index 124493ca9..f734d0d0a 100644 --- a/tests/mesa_pd/vtk/ConvexPolyhedronVTKOutput.cpp +++ b/tests/mesa_pd/vtk/ConvexPolyhedronVTKOutput.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VTKOutput.cpp +//! \file //! \author Lukas Werner // //====================================================================================================================== diff --git a/tests/mesa_pd/vtk/VTKOutputs.cpp b/tests/mesa_pd/vtk/VTKOutputs.cpp index 7cd96b260..ee1a02d47 100644 --- a/tests/mesa_pd/vtk/VTKOutputs.cpp +++ b/tests/mesa_pd/vtk/VTKOutputs.cpp @@ -13,7 +13,7 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file VTKOutputs.cpp +//! \file //! \author Sebastian Eibl <sebastian.eibl@fau.de> // //====================================================================================================================== -- GitLab From fb66bdf69d0bec2be1f1fe1d302dba4f29d0b361 Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Thu, 17 Dec 2020 22:01:29 +0100 Subject: [PATCH 15/83] load pybind11 after finding python libraries also clean up some old leftovers nearby --- .gitlab-ci.yml | 262 +- .gitmodules | 3 + CHANGELOG.md | 5 + CMakeLists.txt | 127 +- apps/CMakeLists.txt | 2 - apps/benchmarks/CMakeLists.txt | 2 +- .../FieldCommunication/CMakeLists.txt | 2 +- .../FieldCommunication/FieldCommunication.cpp | 4 +- .../PhaseFieldAllenCahn/CMakeLists.txt | 2 + .../InitializerFunctions.cpp | 2 - .../InitializerFunctions.h | 3 - .../benchmark_multiphase.cpp | 2 - .../PhaseFieldAllenCahn/profiling.py | 2 - apps/benchmarks/UniformGridGPU/CMakeLists.txt | 4 +- .../UniformGridGPU_Communication.h | 2 +- .../UniformGridGenerated/CMakeLists.txt | 3 +- apps/pythonmodule/CMakeLists.txt | 43 +- apps/pythonmodule/PythonModule.cpp | 149 +- .../PythonModuleWithLbmModule.cpp | 234 -- apps/pythonmodule/setup.py | 34 +- .../PhaseFieldAllenCahn/CPU/PythonExports.cpp | 58 +- .../PhaseFieldAllenCahn/CPU/multiphase.cpp | 6 +- .../CPU/multiphase_RTI_3D.py | 14 +- .../CPU/multiphase_rising_bubble.py | 10 +- .../PhaseFieldAllenCahn/GPU/PythonExports.cpp | 58 +- .../PhaseFieldAllenCahn/GPU/multiphase.cpp | 6 +- .../GPU/multiphase_RTI_3D.py | 12 +- .../GPU/multiphase_rising_bubble.py | 10 +- cmake/FindBoost.cmake | 2213 ----------------- doc/setup.dox | 40 +- extern/pybind11 | 1 + python/pystencils_walberla/boundary.py | 2 - python/waLBerla/__init__.py | 17 +- python/waLBerla/callbacks.py | 46 +- python/waLBerla/core_extension.py | 56 +- python/waLBerla/cuda_extension.py | 20 +- python/waLBerla/field_extension.py | 87 +- python/waLBerla/geometry_setup.py | 148 -- python/waLBerla/plot.py | 171 +- python/waLBerla/timeloop_extension.py | 69 - python/waLBerla/tools/sqlitedb/insert.py | 66 +- python/waLBerla/tools/sqlitedb/merge.py | 20 +- python/waLBerla_docs/conf.py | 4 +- python/waLBerla_docs/index.rst | 41 +- .../Tutorial 01 - Basic data structures.ipynb | 310 ++- .../ipython-tutorials/Tutorial 02 - LBM.ipynb | 254 -- .../Tutorial 03 - LBM with extensions.ipynb | 272 -- python/waLBerla_docs/modules/blockforest.rst | 32 +- python/waLBerla_docs/modules/core.rst | 17 +- python/waLBerla_docs/modules/field.rst | 127 +- python/waLBerla_docs/modules/geometry.rst | 67 - python/waLBerla_docs/modules/lbm.rst | 261 -- python/waLBerla_tests/test_blockforest.py | 69 +- python/waLBerla_tests/test_core.py | 4 +- python/waLBerla_tests/test_cuda_comm.py | 25 - python/waLBerla_tests/test_field.py | 57 +- python/waLBerla_tests/test_simpleLBM.py | 198 -- .../tools/test_lbm_unitconversion.py | 8 +- python/waLBerla_tests/wing.png | Bin 1146 -> 0 bytes src/blockforest/CMakeLists.txt | 2 +- .../communication/UniformBufferedScheme.h | 7 +- .../communication/UniformDirectScheme.h | 7 +- .../python/CommunicationExport.impl.h | 235 -- src/blockforest/python/Exports.cpp | 327 --- src/blockforest/python/Exports.h | 51 - src/boundary/python/Exports.h | 39 - src/boundary/python/Exports.impl.h | 232 -- src/communication/UniformMPIDatatypeInfo.h | 8 + src/core/WeakPtrWrapper.h | 100 - src/cuda/CMakeLists.txt | 2 +- src/cuda/communication/UniformGPUScheme.h | 5 +- .../communication/UniformGPUScheme.impl.h | 2 +- src/cuda/python/Exports.impl.h | 407 --- src/field/Traits.h | 61 - src/field/python/CommunicationExport.impl.h | 260 -- src/field/python/FieldExport.h | 65 - src/field/python/FieldExport.impl.h | 1396 ----------- src/field/python/GatherExport.h | 38 - src/field/python/GatherExport.impl.h | 109 - src/geometry/python/Exports.cpp | 103 - src/geometry/python/Exports.h | 38 - src/lbm/python/ExportBasic.cpp | 244 -- src/lbm/python/ExportBasic.h | 47 - src/lbm/python/ExportBasic.impl.h | 520 ---- src/lbm/python/ExportBoundary.h | 39 - src/lbm/python/ExportBoundary.impl.h | 279 --- src/lbm/python/ExportSweeps.h | 39 - src/lbm/python/ExportSweeps.impl.h | 260 -- src/lbm/python/Exports.h | 49 - src/mesh/python/Exports.h | 41 - src/mesh/python/Exports.impl.h | 186 -- src/postprocessing/python/Exports.h | 41 - src/postprocessing/python/Exports.impl.h | 141 -- src/python_coupling/CMakeLists.txt | 8 +- src/python_coupling/CreateConfig.cpp | 314 +-- src/python_coupling/CreateConfig.h | 3 +- src/python_coupling/DictWrapper.h | 23 +- src/python_coupling/DictWrapper.impl.h | 48 +- src/python_coupling/Manager.cpp | 85 +- src/python_coupling/Manager.h | 41 +- src/python_coupling/PythonCallback.cpp | 90 +- src/python_coupling/PythonCallback.h | 5 +- src/python_coupling/PythonWrapper.h | 5 +- src/python_coupling/Shell.cpp | 247 -- src/python_coupling/Shell.h | 63 - src/python_coupling/TimeloopIntercept.cpp | 136 - src/python_coupling/TimeloopIntercept.h | 60 - src/python_coupling/all.h | 32 - .../basic_exports/BasicExports.cpp | 1238 --------- .../basic_exports/MPIExport.cpp | 266 -- src/python_coupling/export/BasicExport.cpp | 728 ++++++ .../BasicExports.h => export/BasicExport.h} | 5 +- .../export/BlockForestCommunicationExport.h} | 12 +- .../BlockForestCommunicationExport.impl.h | 242 ++ .../export/BlockForestExport.cpp | 340 +++ .../export/BlockForestExport.h | 69 + .../export/CUDAExport.h} | 13 +- src/python_coupling/export/CUDAExport.impl.h | 394 +++ .../export/FieldCommunicationExport.h} | 9 +- .../export/FieldCommunicationExport.impl.h | 249 ++ src/python_coupling/export/FieldExport.impl.h | 664 +++++ .../export/FieldExports.h} | 43 +- .../export/GatherExport.impl.h | 141 ++ src/python_coupling/export/MPIExport.cpp | 278 +++ .../{basic_exports => export}/MPIExport.h | 3 +- .../export/VTKExport.cpp} | 69 +- .../export/VTKExport.h} | 13 +- .../helper/BlockStorageExportHelpers.cpp | 13 +- .../helper/BlockStorageExportHelpers.h | 11 +- .../helper/BoostPythonHelpers.h | 106 - src/python_coupling/helper/ConfigFromDict.cpp | 77 +- src/python_coupling/helper/ConfigFromDict.h | 5 +- .../helper/ExceptionHandling.h | 71 - src/python_coupling/helper/ModuleInit.cpp | 4 +- src/python_coupling/helper/ModuleInit.h | 1 + src/python_coupling/helper/ModuleScope.h | 56 - src/python_coupling/helper/MplHelpers.h | 36 +- src/python_coupling/helper/OwningIterator.h | 74 + src/python_coupling/helper/PybindHelper.h | 65 + .../helper/PythonIterableToStdVector.h | 10 +- src/python_coupling/helper/SharedPtrDeleter.h | 65 - .../helper/SliceToCellInterval.h | 247 +- src/timeloop/python/Exports.cpp | 89 - src/timeloop/python/Exports.h | 41 - src/vtk/CMakeLists.txt | 2 +- src/walberla.h | 1 - tests/core/CMakeLists.txt | 6 +- tests/pe/SyncEquivalence.cpp | 2 - tests/python_coupling/BasicDatatypeTest.py | 26 - tests/python_coupling/CMakeLists.txt | 11 +- tests/python_coupling/CallbackTest.cpp | 21 +- tests/python_coupling/CallbackTest.py | 10 +- .../python_coupling/ConfigFromPythonTest.cpp | 57 +- tests/python_coupling/ConfigFromPythonTest.py | 42 +- tests/python_coupling/FieldExportTest.cpp | 80 +- tests/python_coupling/FieldExportTest.py | 4 +- utilities/conda/walberla/bld.bat | 1 - utilities/conda/walberla/build.sh | 2 - 158 files changed, 4871 insertions(+), 13444 deletions(-) create mode 100644 .gitmodules delete mode 100644 apps/pythonmodule/PythonModuleWithLbmModule.cpp delete mode 100644 cmake/FindBoost.cmake create mode 160000 extern/pybind11 delete mode 100644 python/waLBerla/geometry_setup.py delete mode 100644 python/waLBerla/timeloop_extension.py delete mode 100644 python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 02 - LBM.ipynb delete mode 100644 python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 03 - LBM with extensions.ipynb delete mode 100644 python/waLBerla_docs/modules/geometry.rst delete mode 100644 python/waLBerla_docs/modules/lbm.rst delete mode 100644 python/waLBerla_tests/test_cuda_comm.py delete mode 100644 python/waLBerla_tests/test_simpleLBM.py delete mode 100644 python/waLBerla_tests/wing.png delete mode 100644 src/blockforest/python/CommunicationExport.impl.h delete mode 100644 src/blockforest/python/Exports.cpp delete mode 100644 src/blockforest/python/Exports.h delete mode 100644 src/boundary/python/Exports.h delete mode 100644 src/boundary/python/Exports.impl.h delete mode 100644 src/core/WeakPtrWrapper.h delete mode 100644 src/cuda/python/Exports.impl.h delete mode 100644 src/field/Traits.h delete mode 100644 src/field/python/CommunicationExport.impl.h delete mode 100644 src/field/python/FieldExport.h delete mode 100644 src/field/python/FieldExport.impl.h delete mode 100644 src/field/python/GatherExport.h delete mode 100644 src/field/python/GatherExport.impl.h delete mode 100644 src/geometry/python/Exports.cpp delete mode 100644 src/geometry/python/Exports.h delete mode 100644 src/lbm/python/ExportBasic.cpp delete mode 100644 src/lbm/python/ExportBasic.h delete mode 100644 src/lbm/python/ExportBasic.impl.h delete mode 100644 src/lbm/python/ExportBoundary.h delete mode 100644 src/lbm/python/ExportBoundary.impl.h delete mode 100644 src/lbm/python/ExportSweeps.h delete mode 100644 src/lbm/python/ExportSweeps.impl.h delete mode 100644 src/lbm/python/Exports.h delete mode 100644 src/mesh/python/Exports.h delete mode 100644 src/mesh/python/Exports.impl.h delete mode 100644 src/postprocessing/python/Exports.h delete mode 100644 src/postprocessing/python/Exports.impl.h delete mode 100644 src/python_coupling/Shell.cpp delete mode 100644 src/python_coupling/Shell.h delete mode 100644 src/python_coupling/TimeloopIntercept.cpp delete mode 100644 src/python_coupling/TimeloopIntercept.h delete mode 100644 src/python_coupling/all.h delete mode 100644 src/python_coupling/basic_exports/BasicExports.cpp delete mode 100644 src/python_coupling/basic_exports/MPIExport.cpp create mode 100644 src/python_coupling/export/BasicExport.cpp rename src/python_coupling/{basic_exports/BasicExports.h => export/BasicExport.h} (87%) rename src/{blockforest/python/CommunicationExport.h => python_coupling/export/BlockForestCommunicationExport.h} (78%) create mode 100644 src/python_coupling/export/BlockForestCommunicationExport.impl.h create mode 100644 src/python_coupling/export/BlockForestExport.cpp create mode 100644 src/python_coupling/export/BlockForestExport.h rename src/{cuda/python/Exports.h => python_coupling/export/CUDAExport.h} (81%) create mode 100644 src/python_coupling/export/CUDAExport.impl.h rename src/{field/python/CommunicationExport.h => python_coupling/export/FieldCommunicationExport.h} (85%) create mode 100644 src/python_coupling/export/FieldCommunicationExport.impl.h create mode 100644 src/python_coupling/export/FieldExport.impl.h rename src/{field/python/Exports.h => python_coupling/export/FieldExports.h} (63%) create mode 100644 src/python_coupling/export/GatherExport.impl.h create mode 100644 src/python_coupling/export/MPIExport.cpp rename src/python_coupling/{basic_exports => export}/MPIExport.h (93%) rename src/{vtk/python/Exports.cpp => python_coupling/export/VTKExport.cpp} (53%) rename src/{vtk/python/Exports.h => python_coupling/export/VTKExport.h} (65%) delete mode 100644 src/python_coupling/helper/BoostPythonHelpers.h delete mode 100644 src/python_coupling/helper/ExceptionHandling.h delete mode 100644 src/python_coupling/helper/ModuleScope.h create mode 100644 src/python_coupling/helper/OwningIterator.h create mode 100644 src/python_coupling/helper/PybindHelper.h delete mode 100644 src/python_coupling/helper/SharedPtrDeleter.h delete mode 100644 src/timeloop/python/Exports.cpp delete mode 100644 src/timeloop/python/Exports.h delete mode 100644 tests/python_coupling/BasicDatatypeTest.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ceef61aeb..6e209960e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -51,7 +51,7 @@ stages: -DWALBERLA_ENABLE_GUI=$WALBERLA_ENABLE_GUI -DWALBERLA_BUILD_WITH_CODEGEN=$WALBERLA_BUILD_WITH_CODEGEN -DWALBERLA_STL_BOUNDS_CHECKS=$WALBERLA_STL_BOUNDS_CHECKS - - cmake . -LAH + - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - ctest -LE $CTEST_EXCLUDE_LABELS -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES tags: @@ -87,12 +87,14 @@ intel_18_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -115,10 +117,12 @@ intel_18_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -141,10 +145,12 @@ intel_18_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_ENABLE_GUI: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -163,6 +169,7 @@ intel_18_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" @@ -170,6 +177,7 @@ intel_18_serial_dbg: WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -188,11 +196,13 @@ intel_18_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -215,10 +225,12 @@ intel_18_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -259,12 +271,14 @@ intel_19_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -274,6 +288,7 @@ intel_19_serial: needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -286,10 +301,12 @@ intel_19_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -299,6 +316,7 @@ intel_19_mpionly: needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -311,14 +329,17 @@ intel_19_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -331,18 +352,21 @@ intel_19_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -355,16 +379,19 @@ intel_19_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -377,11 +404,14 @@ intel_19_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" tags: + - cuda - docker - intel @@ -389,7 +419,7 @@ intel_19_hybrid_dbg_sp: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:19 variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" @@ -399,6 +429,7 @@ intel_19_hybrid_dbg_sp: needs: [] allow_failure: false tags: + - cuda - docker - intel @@ -411,12 +442,14 @@ gcc_7_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -438,10 +471,12 @@ gcc_7_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -463,9 +498,11 @@ gcc_7_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -483,6 +520,7 @@ gcc_7_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" @@ -491,6 +529,7 @@ gcc_7_serial_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_ENABLE_GUI: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -508,11 +547,13 @@ gcc_7_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -534,10 +575,12 @@ gcc_7_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -576,12 +619,14 @@ gcc_8_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -591,6 +636,7 @@ gcc_8_serial: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_mpionly: @@ -602,10 +648,12 @@ gcc_8_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -615,6 +663,7 @@ gcc_8_mpionly: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_hybrid: @@ -626,9 +675,11 @@ gcc_8_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -638,6 +689,7 @@ gcc_8_hybrid: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_serial_dbg: @@ -649,13 +701,15 @@ gcc_8_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -665,6 +719,7 @@ gcc_8_serial_dbg: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_mpionly_dbg: @@ -676,11 +731,13 @@ gcc_8_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -690,6 +747,7 @@ gcc_8_mpionly_dbg: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_hybrid_dbg: @@ -701,10 +759,12 @@ gcc_8_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -714,13 +774,14 @@ gcc_8_hybrid_dbg: needs: [] allow_failure: false tags: + - cuda - docker gcc_8_hybrid_dbg_sp: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/gcc:8 variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" @@ -734,6 +795,7 @@ gcc_8_hybrid_dbg_sp: needs: [] allow_failure: false tags: + - cuda - docker gcc_9_serial: @@ -751,6 +813,7 @@ gcc_9_serial: WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -775,6 +838,7 @@ gcc_9_mpionly: WALBERLA_BUILD_WITH_CUDA: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -798,6 +862,7 @@ gcc_9_hybrid: variables: WALBERLA_BUILD_WITH_CUDA: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -825,6 +890,7 @@ gcc_9_serial_dbg: WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -850,6 +916,7 @@ gcc_9_mpionly_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -874,6 +941,7 @@ gcc_9_hybrid_dbg: WALBERLA_BUILD_WITH_CUDA: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -920,6 +988,7 @@ gcc_10_serial: WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -944,6 +1013,7 @@ gcc_10_mpionly: WALBERLA_BUILD_WITH_CUDA: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -968,6 +1038,7 @@ gcc_10_hybrid: variables: WALBERLA_BUILD_WITH_CUDA: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" tags: - docker @@ -987,6 +1058,7 @@ gcc_10_serial_dbg: WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" tags: - docker @@ -1004,6 +1076,7 @@ gcc_10_mpionly_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -1024,6 +1097,7 @@ gcc_10_hybrid_dbg: WALBERLA_BUILD_WITH_CUDA: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -1056,12 +1130,14 @@ clang_6.0_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1083,10 +1159,12 @@ clang_6.0_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1108,9 +1186,11 @@ clang_6.0_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1132,6 +1212,7 @@ clang_6.0_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" @@ -1139,6 +1220,7 @@ clang_6.0_serial_dbg: WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1160,11 +1242,13 @@ clang_6.0_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1186,10 +1270,12 @@ clang_6.0_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] @@ -1228,12 +1314,14 @@ clang_7.0_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1243,6 +1331,7 @@ clang_7.0_serial: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_mpionly: @@ -1254,10 +1343,12 @@ clang_7.0_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1267,6 +1358,7 @@ clang_7.0_mpionly: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_hybrid: @@ -1278,9 +1370,11 @@ clang_7.0_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1290,6 +1384,7 @@ clang_7.0_hybrid: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_serial_dbg: @@ -1301,13 +1396,15 @@ clang_7.0_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1317,6 +1414,7 @@ clang_7.0_serial_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_mpionly_dbg: @@ -1328,11 +1426,13 @@ clang_7.0_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1342,6 +1442,7 @@ clang_7.0_mpionly_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_hybrid_dbg: @@ -1353,10 +1454,12 @@ clang_7.0_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1366,13 +1469,14 @@ clang_7.0_hybrid_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_7.0_hybrid_dbg_sp: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:7.0 variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" @@ -1386,6 +1490,7 @@ clang_7.0_hybrid_dbg_sp: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_serial: @@ -1397,12 +1502,14 @@ clang_8.0_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1412,6 +1519,7 @@ clang_8.0_serial: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_mpionly: @@ -1423,10 +1531,12 @@ clang_8.0_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1436,6 +1546,7 @@ clang_8.0_mpionly: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_hybrid: @@ -1447,9 +1558,11 @@ clang_8.0_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1459,6 +1572,7 @@ clang_8.0_hybrid: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_serial_dbg: @@ -1470,13 +1584,15 @@ clang_8.0_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1486,6 +1602,7 @@ clang_8.0_serial_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_mpionly_dbg: @@ -1497,11 +1614,13 @@ clang_8.0_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1511,6 +1630,7 @@ clang_8.0_mpionly_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_hybrid_dbg: @@ -1522,10 +1642,12 @@ clang_8.0_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1535,13 +1657,14 @@ clang_8.0_hybrid_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_8.0_hybrid_dbg_sp: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:8.0 variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" @@ -1555,6 +1678,7 @@ clang_8.0_hybrid_dbg_sp: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_serial: @@ -1566,12 +1690,14 @@ clang_9.0_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1581,6 +1707,7 @@ clang_9.0_serial: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_mpionly: @@ -1592,10 +1719,12 @@ clang_9.0_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1605,6 +1734,7 @@ clang_9.0_mpionly: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_hybrid: @@ -1616,9 +1746,11 @@ clang_9.0_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1628,6 +1760,7 @@ clang_9.0_hybrid: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_serial_dbg: @@ -1639,13 +1772,15 @@ clang_9.0_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1655,6 +1790,7 @@ clang_9.0_serial_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_mpionly_dbg: @@ -1666,11 +1802,13 @@ clang_9.0_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1680,6 +1818,7 @@ clang_9.0_mpionly_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_hybrid_dbg: @@ -1691,10 +1830,12 @@ clang_9.0_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1704,13 +1845,14 @@ clang_9.0_hybrid_dbg: needs: [] allow_failure: false tags: + - cuda - docker clang_9.0_hybrid_dbg_sp: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:9.0 variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" @@ -1724,6 +1866,7 @@ clang_9.0_hybrid_dbg_sp: needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_serial: @@ -1735,12 +1878,14 @@ clang_10.0_serial: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1750,6 +1895,7 @@ clang_10.0_serial: needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_mpionly: @@ -1761,10 +1907,12 @@ clang_10.0_mpionly: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" only: variables: - $ENABLE_NIGHTLY_BUILDS @@ -1774,6 +1922,7 @@ clang_10.0_mpionly: needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_hybrid: @@ -1785,14 +1934,17 @@ clang_10.0_hybrid: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_serial_dbg: @@ -1804,18 +1956,21 @@ clang_10.0_serial_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_mpionly_dbg: @@ -1827,12 +1982,15 @@ clang_10.0_mpionly_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" tags: + - cuda - docker clang_10.0_hybrid_dbg: @@ -1844,15 +2002,18 @@ clang_10.0_hybrid_dbg: - python3 -m unittest discover pystencils_walberla/ - python3 -m unittest discover lbmpy_walberla/ - cd .. + - CC=gcc CXX=g++ pip3 install pycuda variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" + WALBERLA_BUILD_WITH_PYTHON: "ON" stage: merge_request when: manual needs: [] allow_failure: false tags: + - cuda - docker clang_10.0_hybrid_dbg_sp: @@ -1860,12 +2021,13 @@ clang_10.0_hybrid_dbg_sp: image: i10git.cs.fau.de:5005/walberla/buildenvs/clang:10.0 stage: pretest variables: - WALBERLA_BUILD_WITH_CUDA: "OFF" + WALBERLA_BUILD_WITH_CUDA: "ON" CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_METIS: "OFF" tags: + - cuda - docker @@ -1937,7 +2099,7 @@ doc: - mkdir $CI_PROJECT_DIR/build - cd $CI_PROJECT_DIR/build - cmake .. - - cmake . -LAH + - cmake . -LA - make doc stage: merge_request when: manual @@ -1967,7 +2129,7 @@ clang-tidy: - mkdir $CI_PROJECT_DIR/build - cd $CI_PROJECT_DIR/build - cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWALBERLA_BUFFER_DEBUG=ON -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=ON -DWALBERLA_BUILD_WITH_OPENMP=ON -DCMAKE_BUILD_TYPE=Debug -DWALBERLA_BUILD_WITH_METIS=ON -DWALBERLA_BUILD_WITH_PARMETIS=ON -DWALBERLA_BUILD_WITH_OPENMESH=ON -DWALBERLA_DOUBLE_ACCURACY=ON - - cmake . -LAH + - cmake . -LA - utilities/filterCompileCommands.py compile_commands.json - run-clang-tidy.py -quiet | tee clang-tidy-output.txt stage: merge_request @@ -2009,7 +2171,7 @@ coverage: - cd build - if dpkg --compare-versions `ompi_info | head -2 | tail -1 | sed 's/[^0-9.]*\([0-9.]*\).*/\1/'` ge 1.10; then export MPIEXEC_PREFLAGS="--allow-run-as-root" ; fi - cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=ON -DWALBERLA_BUILD_WITH_OPENMP=OFF -DCMAKE_BUILD_TYPE=Debug -DMPIEXEC_PREFLAGS=$MPIEXEC_PREFLAGS -DWALBERLA_BUILD_WITH_CODEGEN=OFF -DWALBERLA_BUILD_WITH_GCOV=ON - - cmake . -LAH + - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - ctest -LE longrun --output-on-failure -j $NUM_CORES --timeout 3000 - cd .. @@ -2046,7 +2208,7 @@ coverage: - cmake --version - mkdir build - cd build - - cmake -LAH -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -G "$CMAKE_GENERATOR" .. + - cmake -LA -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -G "$CMAKE_GENERATOR" .. - MSBuild.exe walberla.sln /property:Configuration=$BUILD_CONFIGURATION /verbosity:minimal /maxcpucount:4 - ctest -LE $CTEST_EXCLUDE_LABELS -C $BUILD_CONFIGURATION --output-on-failure -j 4 variables: @@ -2278,7 +2440,7 @@ msvc-14.2_mpionly: - mkdir build - cd build - cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DWARNING_ERROR=ON - - cmake . -LAH + - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - ctest -LE "$CTEST_EXCLUDE_LABELS|cuda" -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES tags: @@ -2410,7 +2572,7 @@ conda-py36-linux: - mkdir $CI_PROJECT_DIR/build - cd $CI_PROJECT_DIR/build - cmake .. -DWALBERLA_BUFFER_DEBUG=OFF -DWALBERLA_BUILD_TESTS=OFF -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=OFF -DWALBERLA_BUILD_TOOLS=OFF -DWALBERLA_BUILD_WITH_MPI=ON -DWALBERLA_BUILD_WITH_CUDA=OFF -DWALBERLA_BUILD_WITH_PYTHON=OFF -DWALBERLA_BUILD_WITH_OPENMP=OFF -DCMAKE_BUILD_TYPE=RELEASE -DMPIEXEC_PREFLAGS=$MPIEXEC_PREFLAGS -DWALBERLA_DOUBLE_ACCURACY=ON -DWARNING_ERROR=ON -DWALBERLA_BUILD_WITH_METIS=OFF -DWALBERLA_BUILD_WITH_PARMETIS=OFF -DWALBERLA_OPTIMIZE_FOR_LOCALHOST=ON -DWALBERLA_BUILD_WITH_FASTMATH=ON -DWALBERLA_BUILD_WITH_LTO=ON - - cmake . -LAH + - cmake . -LA - cd apps/benchmarks/GranularGas - make -j 20 - export PATH=$PATH:/usr/local/likwid/bin @@ -2471,7 +2633,7 @@ benchmark_ClangBuildAnalyzer: - mkdir $CI_PROJECT_DIR/build - cd $CI_PROJECT_DIR/build - cmake .. -DWALBERLA_BUFFER_DEBUG=OFF -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=OFF -DWALBERLA_BUILD_WITH_MPI=ON -DWALBERLA_BUILD_WITH_CUDA=OFF -DWALBERLA_BUILD_WITH_PYTHON=OFF -DWALBERLA_BUILD_WITH_OPENMP=OFF -DCMAKE_BUILD_TYPE=RELEASE -DMPIEXEC_PREFLAGS=$MPIEXEC_PREFLAGS -DWALBERLA_DOUBLE_ACCURACY=ON -DWARNING_ERROR=ON -DWALBERLA_BUILD_WITH_METIS=OFF -DWALBERLA_BUILD_WITH_PARMETIS=OFF -DWALBERLA_OPTIMIZE_FOR_LOCALHOST=ON -DWALBERLA_BUILD_WITH_FASTMATH=ON -DWALBERLA_BUILD_WITH_LTO=ON -DCMAKE_CXX_FLAGS=-ftime-trace -G Ninja - - cmake . -LAH + - cmake . -LA - ClangBuildAnalyzer --start . - ninja all - ClangBuildAnalyzer --stop . CBA diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..2c0cd5c01 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "extern/pybind11"] + path = extern/pybind11 + url = https://github.com/pybind/pybind11.git diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c695d2c5..bbcea2971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +- Python Coupling now build upon pybind11. Boost.Python is no longer supported + - lbm module dropped from python coupling due to deprecation for a long time + - geometry, postprocessing and timeloop dropped from python coupling due to its low usage + - PEP8-ification of Python API. This means all keyword arguments are now in snake_case and not in CamelCase as before. + ## [4.1] - 2019-04-19 ### Added - Galerkin coarsening for Multigrid diff --git a/CMakeLists.txt b/CMakeLists.txt index 3427a1eb2..d866ab63d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,8 +75,6 @@ option ( WALBERLA_BUILD_WITH_GCOV "Enables gcov" option ( WALBERLA_BUILD_WITH_LTO "Enable link time optimizations" ) option ( WALBERLA_BUILD_WITH_OPENMP "Enable OpenMP support" ) option ( WALBERLA_BUILD_WITH_PYTHON "Support for embedding Python" ) -option ( WALBERLA_BUILD_WITH_PYTHON_MODULE "Build waLBerla python module" ) -option ( WALBERLA_BUILD_WITH_PYTHON_LBM "Include LBM module into python module" OFF ) option ( WALBERLA_BUILD_WITH_CODEGEN "Enable pystencils code generation" OFF ) @@ -100,6 +98,8 @@ option ( WALBERLA_OPTIMIZE_FOR_LOCALHOST "Enable compiler optimizations spcif option ( WALBERLA_LOG_SKIPPED "Log skipped cmake targets" ON ) +option ( WALBERLA_GIT_SUBMODULE_AUTO "Check submodules during cmake run" ON ) + # Installation Directory set ( CMAKE_INSTALL_PREFIX /usr/local/waLBerla CACHE STRING "The default installation directory." ) @@ -315,7 +315,6 @@ if( WALBERLA_CXX_COMPILER_IS_IBM ) add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1586-267" ) # 1586-267 (I) Inlining of specified subprogram failed due to the presence of a C++ exception handler add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1586-266" ) # 1586-266 (I) Inlining of specified subprogram failed due to the presence of a global label add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1540-0724" ) # 1540-0724 (W) The non-type template argument "2147483648" of type "T" has wrapped [coming from boost/integer_traits.hpp] - add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1540-0095" ) # 1540-0095 (W) The friend function declaration ... [coming from boost/mpl/map/aux_/map0.hpp] add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1500-030" ) # 1500-030: (I) INFORMATION: [...] Additional optimization may be attained by recompiling and specifying MAXMEM option with a value greater than 8192. add_flag ( CMAKE_C_FLAGS "-qsuppress=1500-030" ) # 1500-030: (I) INFORMATION: [...] Additional optimization may be attained by recompiling and specifying MAXMEM option with a value greater than 8192. endif() @@ -587,53 +586,56 @@ endif() ############################################################################################################################# if ( WALBERLA_BUILD_WITH_PYTHON ) - set ( waLBerla_REQUIRED_MIN_PYTHON_VERSION "2.7") - - find_package( PythonInterp 3 QUIET) # search for Python3 first - find_package( PythonInterp QUIET) # fallback to any Python version - + find_package( PythonInterp 3.6 QUIET REQUIRED) find_package( PythonLibs QUIET REQUIRED) - if( PYTHONLIBS_VERSION_STRING VERSION_LESS ${waLBerla_REQUIRED_MIN_PYTHON_VERSION} ) - message( FATAL_ERROR "Found old python library: ${PYTHONLIBS_VERSION_STRING} need at least ${waLBerla_REQUIRED_MIN_PYTHON_VERSION}" ) - endif() - - option( WALBERLA_USE_PYTHON_DEBUG_LIBRARY "Make use of the python debug library" OFF ) - - if( WALBERLA_USE_PYTHON_DEBUG_LIBRARY ) - # you have to make sure this matches the settings you compiled boost with! - add_definitions( "-DBOOST_DEBUG_PYTHON" ) - endif() - if( NOT (PYTHON_LIBRARY AND PYTHON_INCLUDE_DIR ) ) message( FATAL_ERROR "Couldn't find any python library" ) endif() - SET( WALBERLA_BUILD_WITH_PYTHON 1 ) - include_directories( ${PYTHON_INCLUDE_DIR} ) - list ( APPEND SERVICE_LIBS ${PYTHON_LIBRARY} ) - - if( NOT WALBERLA_CXX_COMPILER_IS_MSVC ) - list ( APPEND SERVICE_LIBS -lutil ) - endif() - - if ( WALBERLA_BUILD_WITH_PYTHON_MODULE ) - # a python module is a shared library - so everything has to be compiled to position independent code - # otherwise linking the static libs into the shared lib will result in errors - if( NOT WALBERLA_CXX_COMPILER_IS_MSVC ) - add_flag ( CMAKE_CXX_FLAGS "-fPIC" ) - add_flag ( CMAKE_C_FLAGS "-fPIC" ) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import pybind11; print(pybind11._version.__version__)" + OUTPUT_VARIABLE pybind11_VERSION ERROR_QUIET RESULT_VARIABLE pybind11_VERSION_RESULT) + string(STRIP "${pybind11_VERSION}" pybind11_VERSION) + if(pybind11_VERSION_RESULT EQUAL "0" AND pybind11_VERSION VERSION_GREATER_EQUAL "2.6.0") + execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pybind11 --cmakedir + OUTPUT_VARIABLE PYBIND11_CMAKE_PATH) + string(STRIP "${PYBIND11_CMAKE_PATH}" PYBIND11_CMAKE_PATH) + find_package(pybind11 PATHS "${PYBIND11_CMAKE_PATH}" NO_DEFAULT_PATH REQUIRED) + else() + find_package(Git QUIET) + if(GIT_FOUND AND EXISTS "${PROJECT_SOURCE_DIR}/.git") + # Update submodules as needed + if(WALBERLA_GIT_SUBMODULE_AUTO) + message(STATUS "Submodule update") + execute_process(COMMAND ${GIT_EXECUTABLE} submodule update --init --recursive + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + RESULT_VARIABLE GIT_SUBMOD_RESULT) + if(NOT GIT_SUBMOD_RESULT EQUAL "0") + message(FATAL_ERROR "git submodule update --init failed with ${GIT_SUBMOD_RESULT}, please checkout submodules") + endif() + endif() endif() - endif() - if( MSVC10 ) - include(CMakeDependentOption) - CMAKE_DEPENDENT_OPTION( PYTHON_FIXED_HYPOT_REDEFINITION "fixed _hypot redefinition by python" OFF "WALBERLA_BUILD_WITH_PYTHON" OFF ) - if( NOT PYTHON_FIXED_HYPOT_REDEFINITION ) - message( WARNING "Make sure you modified your pyconfig.h that _hypot is not redefined -> see: http://connect.microsoft.com/VisualStudio/feedback/details/633988/warning-in-math-h-line-162-re-nonstandard-extensions-used" ) + if(NOT EXISTS "${PROJECT_SOURCE_DIR}/extern/pybind11/CMakeLists.txt") + if(EXISTS "${PROJECT_SOURCE_DIR}/.git") + message(FATAL_ERROR "Please update git submodules or install pybind11 via pip.") + else() + message(FATAL_ERROR "Please install pybind11 via pip or download it to ${PROJECT_SOURCE_DIR}/extern/pybind11.") + endif() endif() + + add_subdirectory(extern/pybind11) + + # if pybind11 was installed into ${PYTHON_INCLUDE_DIR} (e.g. by pip), that will have a higher priority than the Git submodule unless we reorder the search path + # introduced in 2.6.0 (https://github.com/pybind/pybind11/issues/2709), fixed in 2.6.2 (https://github.com/pybind/pybind11/pull/2716) + set_property( TARGET pybind11::pybind11 + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/extern/pybind11/include" "${PYTHON_INCLUDE_DIR}") endif() + # a python module is a shared library - so everything has to be compiled to position independent code + # otherwise linking the static libs into the shared lib will result in errors + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + if(WALBERLA_BUILD_DOC) # Sphinx documentation @@ -659,16 +661,6 @@ else() list ( APPEND waLBerla_OPTIONAL_BOOST_COMPONENTS system ) endif() -if ( WALBERLA_BUILD_WITH_PYTHON ) - if( WALBERLA_CXX_COMPILER_IS_MSVC ) - get_filename_component(PYTHON_REQUIRED_LIB ${PYTHON_LIBRARY} NAME_WE) - list( APPEND waLBerla_REQUIRED_BOOST_COMPONENTS ${PYTHON_REQUIRED_LIB} ) - elseif( WALBERLA_USE_STD_FILESYSTEM OR WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) - list( APPEND waLBerla_REQUIRED_BOOST_COMPONENTS system ) - list( REMOVE_ITEM waLBerla_OPTIONAL_BOOST_COMPONENTS system ) - endif() -endif() - # This variable is necessary, if the CMAKE version used is not aware of a more recent boost version (keep this up to date!) set ( Boost_ADDITIONAL_VERSIONS "1.45" "1.45.0" "1.46" "1.46.0" "1.46.1" "1.47" "1.47.0" "1.48" "1.48.0" "1.49" "1.49.0" @@ -727,18 +719,6 @@ if ( Boost_FOUND ) endif() add_definitions ( -DBOOST_ALL_NO_LIB ) # Disable Boost auto-linking (CMAKE does that for us...) - #fix for static lib usage: http://stackoverflow.com/questions/11812463/boost-python-link-errors-under-windows-msvc10 - if( PYTHONLIBS_FOUND AND Boost_USE_STATIC_LIBS) - add_definitions( -DBOOST_PYTHON_STATIC_LIB ) - endif() - - #fix for strange link behaviour of boost to python: boost only links to 'pyhton*.lib' and not to the absolute path - if( WIN32 AND PYTHONLIBS_FOUND ) - get_filename_component( PYTHON_LIBRARY_DIR ${PYTHON_INCLUDE_DIR} PATH ) - link_directories( ${PYTHON_LIBRARY_DIR}/libs ) - list( APPEND LINK_DIRS ${PYTHON_LIBRARY_DIR}/libs ) - endif() - set( WALBERLA_BUILD_WITH_BOOST TRUE CACHE INTERNAL "Build with Boost" ) else( Boost_FOUND ) if( (WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM OR WALBERLA_USE_STD_FILESYSTEM) AND (WALBERLA_USE_STD_EXPERIMENTAL_ANY OR WALBERLA_USE_STD_ANY) AND (WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL OR WALBERLA_USE_STD_OPTIONAL) AND NOT WALBERLA_BUILD_WITH_PYTHON) @@ -754,31 +734,6 @@ else( Boost_FOUND ) endif( Boost_FOUND ) -# Check if Python3 found and look for according boost python library -if ( WALBERLA_BUILD_WITH_PYTHON AND NOT WALBERLA_CXX_COMPILER_IS_MSVC) - SET(_boost_MULTITHREADED "") - if (Boost_USE_MULTITHREADED OR Boost_USE_MULTITHREADED_LIBRARY) - SET(_boost_MULTITHREADED "-mt") - endif() - if( PYTHON_LIBRARY MATCHES "python3" ) - string(REPLACE "." ";" VERSION_LIST ${PYTHONLIBS_VERSION_STRING}) - list(GET VERSION_LIST 0 PY_VER_MAJOR) - list(GET VERSION_LIST 1 PY_VER_MINOR) - find_library( BOOST_PYTHON_LIBRARY NAMES - boost_python${PY_VER_MAJOR}${PY_VER_MINOR}${_boost_MULTITHREADED} - boost_python-py${PY_VER_MAJOR}${PY_VER_MINOR}${_boost_MULTITHREADED} - boost_python${PY_VER_MAJOR}${_boost_MULTITHREADED} - boost_python${_boost_MULTITHREADED} - PATHS ${Boost_LIBRARY_DIRS} NO_DEFAULT_PATH ) - else() - find_library( BOOST_PYTHON_LIBRARY NAMES boost_python${_boost_MULTITHREADED} - PATHS ${Boost_LIBRARY_DIRS} NO_DEFAULT_PATH ) - endif() - message(STATUS "Using Boost Python Library ${BOOST_PYTHON_LIBRARY}" ) - list ( APPEND SERVICE_LIBS ${BOOST_PYTHON_LIBRARY} ) -endif() - - ############################################################################################################################ diff --git a/apps/CMakeLists.txt b/apps/CMakeLists.txt index 58953c4bb..178380b57 100644 --- a/apps/CMakeLists.txt +++ b/apps/CMakeLists.txt @@ -32,6 +32,4 @@ endif() # Python module if ( WALBERLA_BUILD_WITH_PYTHON ) add_subdirectory( pythonmodule ) - # no else with "EXLUDE_FROM_ALL" here, since if WALBERLA_BUILD_WITH_PYTHON_MODULE is not activated - # waLBerla was build without -fPIC , so no linking into shared library is possible endif() \ No newline at end of file diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index aabba8b45..ec223734f 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -15,7 +15,7 @@ add_subdirectory( PoiseuilleChannel ) add_subdirectory( ProbeVsExtraMessage ) add_subdirectory( SchaeferTurek ) add_subdirectory( UniformGrid ) -if ( WALBERLA_BUILD_WITH_CODEGEN ) +if ( WALBERLA_BUILD_WITH_CODEGEN AND WALBERLA_BUILD_WITH_PYTHON ) add_subdirectory( UniformGridGenerated ) add_subdirectory( PhaseFieldAllenCahn ) endif() diff --git a/apps/benchmarks/FieldCommunication/CMakeLists.txt b/apps/benchmarks/FieldCommunication/CMakeLists.txt index 35a2f698a..edb815612 100644 --- a/apps/benchmarks/FieldCommunication/CMakeLists.txt +++ b/apps/benchmarks/FieldCommunication/CMakeLists.txt @@ -4,4 +4,4 @@ waLBerla_link_files_to_builddir( "*.py" ) waLBerla_add_executable ( NAME FieldCommunication - DEPENDS blockforest core domain_decomposition field postprocessing sqlite ) + DEPENDS blockforest core domain_decomposition field postprocessing sqlite python_coupling ) diff --git a/apps/benchmarks/FieldCommunication/FieldCommunication.cpp b/apps/benchmarks/FieldCommunication/FieldCommunication.cpp index fabde23e0..c9b3cc87a 100644 --- a/apps/benchmarks/FieldCommunication/FieldCommunication.cpp +++ b/apps/benchmarks/FieldCommunication/FieldCommunication.cpp @@ -36,7 +36,7 @@ class SingleMessageBufferedScheme public: typedef Stencil_T Stencil; - SingleMessageBufferedScheme( const weak_ptr_wrapper< StructuredBlockForest > & bf, const int tag = 17953 ) + SingleMessageBufferedScheme( const weak_ptr< StructuredBlockForest > & bf, const int tag = 17953 ) : blockForest_( bf ), tag_( tag ) {} inline void addDataToCommunicate( const shared_ptr< communication::UniformPackInfo > &packInfo ) @@ -67,7 +67,7 @@ public: private: std::vector< shared_ptr< UniformBufferedScheme< Stencil>> > schemes_; - weak_ptr_wrapper< StructuredBlockForest > blockForest_; + weak_ptr< StructuredBlockForest > blockForest_; int tag_; }; diff --git a/apps/benchmarks/PhaseFieldAllenCahn/CMakeLists.txt b/apps/benchmarks/PhaseFieldAllenCahn/CMakeLists.txt index 629c9ec0a..951f04a22 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/CMakeLists.txt +++ b/apps/benchmarks/PhaseFieldAllenCahn/CMakeLists.txt @@ -16,6 +16,7 @@ if (WALBERLA_BUILD_WITH_CUDA) waLBerla_add_executable(NAME benchmark_multiphase FILES benchmark_multiphase.cpp InitializerFunctions.cpp multiphase_codegen.py DEPENDS blockforest core cuda field postprocessing lbm geometry timeloop gui BenchmarkPhaseFieldCodeGenGPU) + set_target_properties(benchmark_multiphase PROPERTIES CXX_VISIBILITY_PRESET hidden) else () waLBerla_generate_target_from_python(NAME BenchmarkPhaseFieldCodeGenCPU FILE multiphase_codegen.py @@ -31,5 +32,6 @@ else () waLBerla_add_executable(NAME benchmark_multiphase FILES benchmark_multiphase.cpp InitializerFunctions.cpp multiphase_codegen.py DEPENDS blockforest core field postprocessing lbm geometry timeloop gui BenchmarkPhaseFieldCodeGenCPU) + set_target_properties(benchmark_multiphase PROPERTIES CXX_VISIBILITY_PRESET hidden) endif (WALBERLA_BUILD_WITH_CUDA) diff --git a/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.cpp b/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.cpp index 45e91e25a..5f7e5b2f6 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.cpp +++ b/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.cpp @@ -25,8 +25,6 @@ #include "field/communication/PackInfo.h" #include "field/vtk/VTKWriter.h" -#include "python_coupling/DictWrapper.h" - namespace walberla { using PhaseField_T = GhostLayerField< real_t, 1 >; diff --git a/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.h b/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.h index 4ba7896e7..f30d41e17 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.h +++ b/apps/benchmarks/PhaseFieldAllenCahn/InitializerFunctions.h @@ -18,15 +18,12 @@ // //====================================================================================================================== -#include "core/Environment.h" -#include "core/logging/Initialization.h" #include "core/math/Constants.h" #include "field/FlagField.h" #include "field/communication/PackInfo.h" #include "field/vtk/VTKWriter.h" -#include "python_coupling/DictWrapper.h" #pragma once namespace walberla diff --git a/apps/benchmarks/PhaseFieldAllenCahn/benchmark_multiphase.cpp b/apps/benchmarks/PhaseFieldAllenCahn/benchmark_multiphase.cpp index 944ca0a0b..3513c15f2 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/benchmark_multiphase.cpp +++ b/apps/benchmarks/PhaseFieldAllenCahn/benchmark_multiphase.cpp @@ -27,8 +27,6 @@ #include "field/AddToStorage.h" #include "field/FlagField.h" -#include "field/communication/PackInfo.h" -#include "field/python/Exports.h" #include "field/vtk/VTKWriter.h" #include "geometry/InitBoundaryHandling.h" diff --git a/apps/benchmarks/PhaseFieldAllenCahn/profiling.py b/apps/benchmarks/PhaseFieldAllenCahn/profiling.py index 71cdba3f3..f8e6bed30 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/profiling.py +++ b/apps/benchmarks/PhaseFieldAllenCahn/profiling.py @@ -27,8 +27,6 @@ class Scenario: self.scenario = 1 # 1 rising bubble, 2 RTI self.config_dict = self.config() - self.csv_file = "benchmark.csv" - @wlb.member_callback def config(self): return { diff --git a/apps/benchmarks/UniformGridGPU/CMakeLists.txt b/apps/benchmarks/UniformGridGPU/CMakeLists.txt index 4a6390633..9fe54701f 100644 --- a/apps/benchmarks/UniformGridGPU/CMakeLists.txt +++ b/apps/benchmarks/UniformGridGPU/CMakeLists.txt @@ -1,6 +1,6 @@ waLBerla_link_files_to_builddir( "*.prm" ) -#waLBerla_link_files_to_builddir( "simulation_setup" ) +waLBerla_link_files_to_builddir( "simulation_setup" ) foreach (config srt trt mrt smagorinsky entropic smagorinsky_noopt entropic_kbc_n4 @@ -25,6 +25,7 @@ foreach (config srt trt mrt smagorinsky entropic smagorinsky_noopt entropic_kbc_ waLBerla_add_executable(NAME UniformGridBenchmarkGPU_${config} FILES UniformGridGPU.cpp DEPENDS blockforest boundary core cuda domain_decomposition field geometry timeloop vtk gui UniformGridGPUGenerated_${config}) + set_target_properties( UniformGridBenchmarkGPU_${config} PROPERTIES CXX_VISIBILITY_PRESET hidden) endforeach () @@ -46,4 +47,5 @@ foreach (config srt trt mrt smagorinsky entropic) waLBerla_add_executable(NAME UniformGridBenchmarkGPU_AA_${config} FILES UniformGridGPU_AA.cpp DEPENDS blockforest boundary core cuda domain_decomposition field geometry timeloop vtk gui UniformGridGPUGenerated_AA_${config}) + set_target_properties( UniformGridBenchmarkGPU_AA_${config} PROPERTIES CXX_VISIBILITY_PRESET hidden) endforeach () diff --git a/apps/benchmarks/UniformGridGPU/UniformGridGPU_Communication.h b/apps/benchmarks/UniformGridGPU/UniformGridGPU_Communication.h index db0ec86e6..aadf51331 100644 --- a/apps/benchmarks/UniformGridGPU/UniformGridGPU_Communication.h +++ b/apps/benchmarks/UniformGridGPU/UniformGridGPU_Communication.h @@ -30,7 +30,7 @@ template<typename StencilType, typename GPUFieldType > class UniformGridGPU_Communication { public: - explicit UniformGridGPU_Communication(weak_ptr_wrapper<StructuredBlockForest> bf, const BlockDataID & bdId, + explicit UniformGridGPU_Communication(weak_ptr<StructuredBlockForest> bf, const BlockDataID & bdId, CommunicationSchemeType commSchemeType, bool cudaEnabledMPI = false) : _commSchemeType(commSchemeType), _cpuCommunicationScheme(nullptr), _gpuPackInfo(nullptr), _gpuCommunicationScheme(nullptr), _directScheme(nullptr) diff --git a/apps/benchmarks/UniformGridGenerated/CMakeLists.txt b/apps/benchmarks/UniformGridGenerated/CMakeLists.txt index ee60a84f5..f964f242a 100644 --- a/apps/benchmarks/UniformGridGenerated/CMakeLists.txt +++ b/apps/benchmarks/UniformGridGenerated/CMakeLists.txt @@ -15,6 +15,7 @@ foreach(config trt smagorinsky mrt entropic_kbc_n4 cumulant ) waLBerla_add_executable ( NAME UniformGridBenchmarkGenerated_${config} FILES UniformGridGenerated.cpp DEPENDS blockforest boundary core domain_decomposition field geometry timeloop vtk gui - UniformGridGenerated_${config}) + UniformGridGenerated_${config} python_coupling) + set_target_properties(UniformGridBenchmarkGenerated_${config} PROPERTIES CXX_VISIBILITY_PRESET hidden) endforeach() diff --git a/apps/pythonmodule/CMakeLists.txt b/apps/pythonmodule/CMakeLists.txt index 820784e2b..38290ffa5 100644 --- a/apps/pythonmodule/CMakeLists.txt +++ b/apps/pythonmodule/CMakeLists.txt @@ -1,43 +1,34 @@ # waLBerla Python module -if ( WALBERLA_BUILD_WITH_PYTHON_MODULE ) - - set(PYTHON_MODULE_DEPENDENCIES blockforest boundary domain_decomposition core field geometry lbm postprocessing python_coupling timeloop vtk) - if (WALBERLA_BUILD_WITH_CUDA) - set(PYTHON_MODULE_DEPENDENCIES ${PYTHON_MODULE_DEPENDENCIES} cuda) - endif() - - if (WALBERLA_BUILD_WITH_OPENMESH) - set(PYTHON_MODULE_DEPENDENCIES ${PYTHON_MODULE_DEPENDENCIES} mesh pe) +if ( WALBERLA_BUILD_WITH_PYTHON ) + if ( WALBERLA_BUILD_WITH_CUDA ) + set(PYTHON_MODULE_DEPENDENCIES blockforest boundary domain_decomposition core field python_coupling timeloop vtk cuda) + else() + set(PYTHON_MODULE_DEPENDENCIES blockforest boundary domain_decomposition core field python_coupling timeloop vtk) endif() if( WALBERLA_CXX_COMPILER_IS_MSVC ) - set ( pythonModules ${PYTHON_MODULE_DEPENDENCIES}) + set ( pythonModules ${PYTHON_MODULE_DEPENDENCIES}) elseif( APPLE ) - set ( pythonModules "-Wl,-force_load" ${PYTHON_MODULE_DEPENDENCIES}) + set ( pythonModules "-Wl,-force_load" ${PYTHON_MODULE_DEPENDENCIES}) else() - set ( pythonModules "-Wl,-whole-archive" ${PYTHON_MODULE_DEPENDENCIES} "-Wl,-no-whole-archive" ) + set ( pythonModules "-Wl,-whole-archive" ${PYTHON_MODULE_DEPENDENCIES} "-Wl,-no-whole-archive" ) endif() - if( WALBERLA_BUILD_WITH_PYTHON_LBM ) - add_library( walberla_cpp SHARED PythonModuleWithLbmModule.cpp ) - else() - add_library( walberla_cpp SHARED PythonModule.cpp ) - endif() + add_library( walberla_cpp SHARED PythonModule.cpp ) - target_link_libraries( walberla_cpp ${WALBERLA_LINK_LIBRARIES_KEYWORD} ${pythonModules} ${SERVICE_LIBS} ) - set_target_properties( walberla_cpp PROPERTIES PREFIX "") - if ( APPLE ) - set_target_properties( walberla_cpp PROPERTIES SUFFIX ".so") - endif() + target_link_libraries( walberla_cpp ${WALBERLA_LINK_LIBRARIES_KEYWORD} ${pythonModules} ${SERVICE_LIBS} ) + + set_target_properties( + walberla_cpp PROPERTIES PREFIX "${PYTHON_MODULE_PREFIX}" + SUFFIX "${PYTHON_MODULE_EXTENSION}" + ) set_target_properties( walberla_cpp PROPERTIES MACOSX_RPATH TRUE ) + set_target_properties( walberla_cpp PROPERTIES CXX_VISIBILITY_PRESET hidden) configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/setup.py ${CMAKE_CURRENT_BINARY_DIR}/setup.py ) add_custom_target( pythonModule ALL ${PYTHON_EXECUTABLE} setup.py build DEPENDS walberla_cpp ) - add_custom_target( pythonModuleInstall ${PYTHON_EXECUTABLE} setup.py install DEPENDS walberla_cpp ) - - add_test( NAME PythonModuleTest - COMMAND ${PYTHON_EXECUTABLE} -m unittest discover -v -s ${walberla_SOURCE_DIR}/python/waLBerla_tests ) + add_custom_target( pythonModuleInstall ${PYTHON_EXECUTABLE} setup.py install --user DEPENDS walberla_cpp ) endif() diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp index 43afcff72..419b1b377 100644 --- a/apps/pythonmodule/PythonModule.cpp +++ b/apps/pythonmodule/PythonModule.cpp @@ -15,125 +15,84 @@ // //! \file PythonModule.cpp //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== -#include "python_coupling/PythonWrapper.h" -#include "waLBerlaDefinitions.h" -#include "blockforest/python/Exports.h" #include "field/GhostLayerField.h" -#include "field/python/Exports.h" -#include "mesh/python/Exports.h" -#include "geometry/python/Exports.h" -#include "postprocessing/python/Exports.h" + #include "python_coupling/Manager.h" +#include "python_coupling/export/BlockForestExport.h" +#include "python_coupling/export/FieldExports.h" +#include "python_coupling/export/VTKExport.h" #include "python_coupling/helper/ModuleInit.h" + #include "stencil/all.h" -#include "timeloop/python/Exports.h" -#include "vtk/python/Exports.h" #ifdef WALBERLA_BUILD_WITH_CUDA -#include "cuda/python/Exports.h" + #include "python_coupling/export/CUDAExport.h" #endif -#include <boost/mpl/vector.hpp> -#include <boost/mpl/insert_range.hpp> - - -namespace bmpl = boost::mpl; using namespace walberla; -typedef bmpl::vector< - Field<walberla::real_t,1>, - Field<walberla::real_t,2>, - Field<walberla::real_t,3>, - Field<walberla::real_t,4>, - Field<walberla::real_t,5>, - Field<walberla::real_t,6>, - Field<walberla::real_t,9>, - Field<walberla::real_t,15>, - Field<walberla::real_t,19>, - Field<walberla::real_t,27>, - - Field<walberla::int8_t,1>, - Field<walberla::int16_t,1>, - Field<walberla::int32_t,1>, - - Field<walberla::int64_t,1>, - Field<walberla::int64_t,2>, - Field<walberla::int64_t,3>, - Field<walberla::int64_t,4>, - - Field<walberla::uint8_t,1>, - Field<walberla::uint16_t,1>, - Field<walberla::uint32_t,1> - > FieldTypes; - -typedef bmpl::vector< - GhostLayerField<walberla::real_t,1>, - GhostLayerField<walberla::real_t,3> - > FieldTypesForMeshGeneration; - - -typedef bmpl::vector< FlagField<walberla::uint8_t>, - FlagField<walberla::uint16_t> > FlagFieldTypes; - -typedef bmpl::vector< stencil::D2Q5, - stencil::D2Q9, - stencil::D3Q7, - stencil::D3Q19, - stencil::D3Q27 > Stencils; - -typedef GhostLayerField<walberla::real_t,3> VecField_T; - - -using namespace walberla; +#define FIELD_TYPES \ + Field<walberla::real_t,1>,\ + Field<walberla::real_t,2>,\ + Field<walberla::real_t,3>,\ + Field<walberla::real_t,4>,\ + Field<walberla::real_t,5>,\ + Field<walberla::real_t,6>,\ + Field<walberla::real_t,9>,\ + Field<walberla::real_t,15>,\ + Field<walberla::real_t,19>,\ + Field<walberla::real_t,27>,\ + Field<walberla::int8_t,1>,\ + Field<walberla::int16_t,1>,\ + Field<walberla::int32_t,1>,\ + Field<walberla::int64_t,1>,\ + Field<walberla::int64_t,2>,\ + Field<walberla::int64_t,3>,\ + Field<walberla::int64_t,4>,\ + Field<walberla::uint8_t,1>,\ + Field<walberla::uint16_t,1>,\ + Field<walberla::uint32_t,1> + +#define GPU_FIELD_TYPES \ + GPUField<double>,\ + GPUField<float>,\ + GPUField<int8_t>,\ + GPUField<int16_t>,\ + GPUField<int32_t>,\ + GPUField<int64_t>,\ + GPUField<uint8_t>,\ + GPUField<uint16_t>,\ + GPUField<uint32_t>,\ + GPUField<uint64_t> struct InitObject { InitObject() { - namespace bmpl = boost::mpl; - auto pythonManager = python_coupling::Manager::instance(); - // Field - pythonManager->addExporterFunction( field::exportModuleToPython<FieldTypes> ); - pythonManager->addExporterFunction( field::exportGatherFunctions<FieldTypes> ); - pythonManager->addBlockDataConversion<FieldTypes>() ; - + pythonManager->addExporterFunction( field::exportModuleToPython<FIELD_TYPES> ); + pythonManager->addExporterFunction( field::exportGatherFunctions<FIELD_TYPES> ); + pythonManager->addBlockDataConversion<FIELD_TYPES>(); // Blockforest - pythonManager->addExporterFunction( blockforest::exportModuleToPython<Stencils> ); - - // Geometry - pythonManager->addExporterFunction( geometry::exportModuleToPython ); - + pythonManager->addExporterFunction(blockforest::exportModuleToPython<stencil::D2Q5, stencil::D2Q9, stencil::D3Q7, stencil::D3Q19, stencil::D3Q27>); // VTK pythonManager->addExporterFunction( vtk::exportModuleToPython ); - - // Postprocessing - pythonManager->addExporterFunction( postprocessing::exportModuleToPython<FieldTypesForMeshGeneration, FlagFieldTypes> ); - - // Timeloop - pythonManager->addExporterFunction( timeloop::exportModuleToPython ); - -#ifdef WALBERLA_BUILD_WITH_OPENMESH - pythonManager->addExporterFunction( mesh::exportModuleToPython<FlagFieldTypes> ); -#endif - -#ifdef WALBERLA_BUILD_WITH_CUDA - using walberla::cuda::GPUField; - typedef bmpl::vector<GPUField<double>, GPUField<float>, - GPUField<int8_t>, GPUField<int16_t>, GPUField<int32_t>, GPUField<int64_t>, - GPUField<uint8_t>, GPUField<uint16_t>, GPUField<uint32_t>,GPUField<uint64_t> > GPUFields; - - pythonManager->addExporterFunction( cuda::exportModuleToPython<GPUFields, FieldTypes> ); - pythonManager->addBlockDataConversion<GPUFields>(); -#endif - + #ifdef WALBERLA_BUILD_WITH_CUDA + using walberla::cuda::GPUField; + + pythonManager->addExporterFunction( cuda::exportModuleToPython<GPU_FIELD_TYPES> ); + pythonManager->addExporterFunction( cuda::exportCopyFunctionsToPython<FIELD_TYPES> ); + pythonManager->addBlockDataConversion<GPU_FIELD_TYPES>(); + #endif + // python_coupling::initWalberlaForPythonModule(); + } }; -InitObject globalInitObject; - +InitObject globalInitObject; \ No newline at end of file diff --git a/apps/pythonmodule/PythonModuleWithLbmModule.cpp b/apps/pythonmodule/PythonModuleWithLbmModule.cpp deleted file mode 100644 index 03301a723..000000000 --- a/apps/pythonmodule/PythonModuleWithLbmModule.cpp +++ /dev/null @@ -1,234 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonModule.cpp -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== -#include "python_coupling/PythonWrapper.h" -#include "waLBerlaDefinitions.h" -#include "blockforest/python/Exports.h" -#include "field/GhostLayerField.h" -#include "field/python/Exports.h" -#include "geometry/python/Exports.h" -#include "lbm/all.h" -#include "lbm/lattice_model/ForceModel.h" -#include "lbm/python/Exports.h" -#include "postprocessing/python/Exports.h" -#include "python_coupling/Manager.h" -#include "python_coupling/helper/ModuleInit.h" -#include "stencil/all.h" -#include "timeloop/python/Exports.h" -#include "vtk/python/Exports.h" - -#include <boost/mpl/vector.hpp> -#include <boost/mpl/insert_range.hpp> - - -namespace bmpl = boost::mpl; -using namespace walberla; - -typedef bmpl::vector< - Field<walberla::real_t,1>, - Field<walberla::real_t,2>, - Field<walberla::real_t,3>, - Field<walberla::real_t,4>, - Field<walberla::real_t,5>, - Field<walberla::real_t,9>, - Field<walberla::real_t,19>, - Field<walberla::real_t,27>, - - Field<walberla::int8_t,1>, - Field<walberla::int16_t,1>, - Field<walberla::int32_t,1>, - - Field<walberla::int64_t,1>, - Field<walberla::int64_t,2>, - Field<walberla::int64_t,3>, - Field<walberla::int64_t,4>, - Field<walberla::int64_t,5>, - - Field<walberla::uint8_t,1>, - Field<walberla::uint16_t,1>, - Field<walberla::uint32_t,1> - > FieldTypes; - - -typedef bmpl::vector< - GhostLayerField<walberla::real_t,1>, - GhostLayerField<walberla::real_t,3> - > FieldTypesForMeshGeneration; - - -typedef bmpl::vector< FlagField<walberla::uint8_t>, - FlagField<walberla::uint16_t> > FlagFieldTypes; - -typedef bmpl::vector< stencil::D2Q5, - stencil::D2Q9, - stencil::D3Q7, - stencil::D3Q19, - stencil::D3Q27 > Stencils; - -typedef lbm::collision_model::SRTField< GhostLayerField<walberla::real_t,1> > SRTField_T; - -typedef GhostLayerField<walberla::real_t,3> VecField_T; - - -// ------------------------- D2Q9 ----------------------------------------------------------------------------- - -typedef bmpl::list< lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::None, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::LuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, true, lbm::force_model::None, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, true, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::GuoField<VecField_T>, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, true, lbm::force_model::LuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::SRT, true, lbm::force_model::None, 1>, - lbm::D2Q9 < lbm::collision_model::SRT, false, lbm::force_model::None, 1> -> LM_D2Q19_SRT; - -typedef bmpl::list< lbm::D2Q9 < lbm::collision_model::TRT, false, lbm::force_model::None, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, false, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, false, lbm::force_model::LuoConstant, 2>, - - lbm::D2Q9 < lbm::collision_model::TRT, true, lbm::force_model::None, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, true, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, true, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, true, lbm::force_model::LuoConstant, 2>, - lbm::D2Q9 < lbm::collision_model::TRT, true, lbm::force_model::None, 1>, - lbm::D2Q9 < lbm::collision_model::TRT, false, lbm::force_model::None, 1> -> LM_D2Q19_TRT; - -typedef lbm::collision_model::SRTField<GhostLayerField<real_t,1> > SRTFieldCollisionModel; -typedef bmpl::list< lbm::D2Q9 < SRTFieldCollisionModel, false, lbm::force_model::None, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, false, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, false, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, false, lbm::force_model::LuoConstant, 2>, - - lbm::D2Q9 < SRTFieldCollisionModel, true, lbm::force_model::None, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, true, lbm::force_model::SimpleConstant, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, true, lbm::force_model::GuoConstant, 2>, - lbm::D2Q9 < SRTFieldCollisionModel, true, lbm::force_model::LuoConstant, 2> -> LM_D2Q9_SRTField; - -// ------------------------- D3Q19 ---------------------------------------------------------------------------- - - -typedef bmpl::list< lbm::D3Q19 < lbm::collision_model::SRT, false, lbm::force_model::None, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, false, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, false, lbm::force_model::LuoConstant, 2>, - - lbm::D3Q19 < lbm::collision_model::SRT, true, lbm::force_model::None, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, true, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < lbm::collision_model::SRT, true, lbm::force_model::LuoConstant, 2> -> LM_D3Q19_SRT; - -typedef bmpl::list< lbm::D3Q19 < lbm::collision_model::TRT, false, lbm::force_model::None, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, false, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, false, lbm::force_model::LuoConstant, 2>, - - lbm::D3Q19 < lbm::collision_model::TRT, true, lbm::force_model::None, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, true, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, true, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < lbm::collision_model::TRT, true, lbm::force_model::LuoConstant, 2> -> LM_D3Q19_TRT; - - -typedef bmpl::list<lbm::D3Q19 < lbm::collision_model::D3Q19MRT, false, lbm::force_model::None, 2>, - lbm::D3Q19 < lbm::collision_model::D3Q19MRT, false, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < lbm::collision_model::D3Q19MRT, false, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < lbm::collision_model::D3Q19MRT, false, lbm::force_model::LuoConstant, 2>, - - lbm::D3Q27 < lbm::collision_model::D3Q27Cumulant, true, lbm::force_model::None, 2> - -> LM_D3Q19_Extra; - - - -typedef lbm::collision_model::SRTField<GhostLayerField<real_t,1> > SRTFieldCollisionModel; -typedef bmpl::list< lbm::D3Q19 < SRTFieldCollisionModel, false, lbm::force_model::None, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, false, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, false, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, false, lbm::force_model::LuoConstant, 2>, - - lbm::D3Q19 < SRTFieldCollisionModel, true, lbm::force_model::None, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, true, lbm::force_model::SimpleConstant, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, true, lbm::force_model::GuoConstant, 2>, - lbm::D3Q19 < SRTFieldCollisionModel, true, lbm::force_model::LuoConstant, 2> -> LM_D3Q19_SRTField; - - -typedef bmpl::insert_range< LM_D2Q19_SRT, bmpl::end< LM_D2Q19_SRT >::type, LM_D2Q19_TRT> ::type D2Q9_SRT_TRT; -typedef bmpl::insert_range< D2Q9_SRT_TRT, bmpl::end< D2Q9_SRT_TRT >::type, LM_D2Q9_SRTField>::type LatticeModels2D; - - -typedef bmpl::insert_range< LM_D3Q19_SRT, bmpl::end< LM_D3Q19_SRT > ::type, LM_D3Q19_TRT>::type D3Q19_SRT_TRT; -typedef bmpl::insert_range< D3Q19_SRT_TRT, bmpl::end< D3Q19_SRT_TRT >::type, LM_D3Q19_Extra>::type D3Q19_SRT_TRT_MRT; -typedef bmpl::insert_range< D3Q19_SRT_TRT_MRT, bmpl::end< D3Q19_SRT_TRT_MRT >::type, LM_D3Q19_SRTField>::type LatticeModels3D; - - -typedef bmpl::insert_range< LatticeModels2D, bmpl::end< LatticeModels2D >::type, LatticeModels3D>::type LatticeModels; - -typedef typename lbm::AdaptorsFromLatticeModels<LatticeModels>::type LBMAdaptors; - - - -using namespace walberla; - -struct InitObject -{ - InitObject() - { - namespace bmpl = boost::mpl; - - auto pythonManager = python_coupling::Manager::instance(); - - // Field - pythonManager->addExporterFunction( field::exportModuleToPython<FieldTypes> ); - pythonManager->addExporterFunction( field::exportGatherFunctions<bmpl::joint_view<FieldTypes,LBMAdaptors>::type > ); - pythonManager->addBlockDataConversion< bmpl::joint_view<FieldTypes,LBMAdaptors>::type >() ; - - // Blockforest - pythonManager->addExporterFunction( blockforest::exportModuleToPython<Stencils> ); - - // Geometry - pythonManager->addExporterFunction( geometry::exportModuleToPython ); - - // VTK - pythonManager->addExporterFunction( vtk::exportModuleToPython ); - - // LBM - typedef bmpl::vector< FlagField<walberla::uint8_t> > FlagFieldTypesForLBM; - pythonManager->addExporterFunction( lbm::exportBasic<LatticeModels, FlagFieldTypesForLBM> ); - pythonManager->addExporterFunction( lbm::exportBoundary<LatticeModels, FlagFieldTypesForLBM> ); - pythonManager->addExporterFunction( lbm::exportSweeps<LatticeModels, FlagFieldTypesForLBM> ); - - // Postprocessing - pythonManager->addExporterFunction( postprocessing::exportModuleToPython<FieldTypesForMeshGeneration, FlagFieldTypes> ); - - // Timeloop - pythonManager->addExporterFunction( timeloop::exportModuleToPython ); - - python_coupling::initWalberlaForPythonModule(); - } -}; -InitObject globalInitObject; - diff --git a/apps/pythonmodule/setup.py b/apps/pythonmodule/setup.py index 5929b0fb9..066669c75 100644 --- a/apps/pythonmodule/setup.py +++ b/apps/pythonmodule/setup.py @@ -1,28 +1,30 @@ -from distutils.core import setup -import shutil -from os.path import exists, join -import platform import sys +import platform +from os.path import exists, join +import shutil + +from setuptools import setup # The following variables are configure by CMake walberla_source_dir = "${walberla_SOURCE_DIR}" walberla_binary_dir = "${CMAKE_CURRENT_BINARY_DIR}" +suffix = "${PYTHON_MODULE_EXTENSION}" +prefix = "${PYTHON_MODULE_PREFIX}" +walberla_module_file_name = prefix + "walberla_cpp" + suffix + +version = "${WALBERLA_VERSION}" if platform.system() == 'Windows': - extension = ('dll', 'pyd') configuration = 'Release' else: - extension = ('so', 'so') configuration = '' def collectFiles(): - src_shared_lib = join(walberla_binary_dir, configuration, 'walberla_cpp.' + extension[0]) - dst_shared_lib = join(walberla_binary_dir, 'waLBerla', 'walberla_cpp.' + extension[1]) + src_shared_lib = join(walberla_binary_dir, configuration, walberla_module_file_name) + dst_shared_lib = join(walberla_binary_dir, 'waLBerla', walberla_module_file_name) # copy everything inplace - print(src_shared_lib) - if not exists(src_shared_lib): print("Python Module was not built yet - run 'make walberla_cpp'") exit(1) @@ -43,17 +45,19 @@ packages = ['waLBerla', 'waLBerla.tools.report', 'waLBerla.tools.sqlitedb', 'waLBerla.tools.lbm_unitconversion', - 'waLBerla.tools.jobscripts'] + 'waLBerla.tools.jobscripts', + 'waLBerla.tools.config'] collectFiles() + setup(name='waLBerla', - version='1.0', - author='Martin Bauer', - author_email='martin.bauer@fau.de', + version=str(version), + author='Markus Holzer', + author_email='markus.holzer@fau.de', url='http://www.walberla.net', packages=packages, - package_data={'': ['walberla_cpp.' + extension[1]]} + package_data={'': [walberla_module_file_name]} ) if sys.argv[1] == 'build': diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/PythonExports.cpp b/apps/showcases/PhaseFieldAllenCahn/CPU/PythonExports.cpp index 40bb8c52b..4b73da880 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/PythonExports.cpp +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/PythonExports.cpp @@ -20,68 +20,28 @@ #include "waLBerlaDefinitions.h" #ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/Manager.h" +# include "core/math/Constants.h" -#include "core/math/Constants.h" - -#include "blockforest/python/Exports.h" - -#include "field/communication/PackInfo.h" -#include "field/python/Exports.h" - -#include "geometry/python/Exports.h" - -#include "postprocessing/python/Exports.h" - -#include "timeloop/python/Exports.h" +# include "field/communication/PackInfo.h" +# include "python_coupling/Manager.h" +# include "python_coupling/export/BlockForestExport.h" +# include "python_coupling/export/FieldExports.h" namespace walberla { using flag_t = uint8_t; // clang-format off void exportDataStructuresToPython() { - namespace bmpl = boost::mpl; - auto pythonManager = python_coupling::Manager::instance(); - typedef bmpl::vector< - Field<walberla::real_t, 1>, - Field<walberla::real_t, 3>, - Field<walberla::real_t, 9>, - Field<walberla::real_t, 19>, - Field<walberla::real_t, 27>> - FieldTypes; - - typedef bmpl::vector<stencil::D2Q9, - stencil::D3Q19, - stencil::D3Q27> - Stencils; - - typedef bmpl::vector< - GhostLayerField<real_t,1>, - GhostLayerField<real_t,3>> - RealFieldTypes; - - typedef bmpl::vector< - FlagField<flag_t>> - FlagFieldTypes; // Field - pythonManager->addExporterFunction(field::exportModuleToPython<FieldTypes>); - pythonManager->addExporterFunction(field::exportGatherFunctions<FieldTypes>); - pythonManager->addBlockDataConversion<FieldTypes>(); + pythonManager->addExporterFunction(field::exportModuleToPython<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>); + pythonManager->addExporterFunction(field::exportGatherFunctions<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>); + pythonManager->addBlockDataConversion<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>(); // Blockforest - pythonManager->addExporterFunction(blockforest::exportModuleToPython<Stencils>); - - // Timeloop - pythonManager->addExporterFunction(timeloop::exportModuleToPython); - - // Postprocessing - pythonManager->addExporterFunction( postprocessing::exportModuleToPython<RealFieldTypes, FlagFieldTypes> ); - - // Geometry - pythonManager->addExporterFunction( geometry::exportModuleToPython ); + pythonManager->addExporterFunction(blockforest::exportModuleToPython<stencil::D2Q9, stencil::D3Q19, stencil::D3Q27>); } // clang-format on } diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase.cpp b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase.cpp index cf1eff4d3..00f5fae4d 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase.cpp +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase.cpp @@ -28,13 +28,13 @@ #include "field/AddToStorage.h" #include "field/FlagField.h" #include "field/communication/PackInfo.h" -#include "field/python/Exports.h" #include "field/vtk/VTKWriter.h" #include "geometry/InitBoundaryHandling.h" #include "python_coupling/CreateConfig.h" #include "python_coupling/PythonCallback.h" +#include "python_coupling/export/FieldExports.h" #include "timeloop/SweepTimeloop.h" @@ -292,8 +292,8 @@ int main(int argc, char** argv) python_coupling::PythonCallback callback("at_end_of_time_step"); if (callback.isCallable()) { - callback.data().exposePtr("blocks", blocks); - callback.data().exposePtr("time_loop", timeLoop); + callback.data().exposeValue("blocks", blocks); + callback.data().exposeValue( "timeStep", timeLoop->getCurrentTimeStep()); callback(); } } diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_RTI_3D.py b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_RTI_3D.py index 54f656cf9..1ef86f585 100755 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_RTI_3D.py +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_RTI_3D.py @@ -13,7 +13,7 @@ class Scenario: self.dbWriteFrequency = 200 # simulation parameters - self.timesteps = 6001 + self.timesteps = 27001 self.cells = (64, 32, 64) self.blocks = (1, 8, 1) @@ -77,8 +77,8 @@ class Scenario: } @wlb.member_callback - def at_end_of_time_step(self, blocks, time_loop): - t = time_loop.getCurrentTimeStep() + def at_end_of_time_step(self, blocks, **kwargs): + t = kwargs['timeStep'] ny = self.size[1] l0 = self.size[0] if t % self.dbWriteFrequency == 0: @@ -88,22 +88,22 @@ class Scenario: mass = -100 spike_data = wlb.field.gather(blocks, 'phase', makeSlice[self.size[0] // 2, :, self.size[2] // 2]) if spike_data: - spike_field = np.asarray(spike_data.buffer()).squeeze() + spike_field = np.asarray(spike_data).squeeze() location_of_spike = (np.argmax(spike_field > 0.5) - ny // 2) / l0 bubble_data = wlb.field.gather(blocks, 'phase', makeSlice[0, :, 0]) if bubble_data: - bubble_field = np.asarray(bubble_data.buffer()).squeeze() + bubble_field = np.asarray(bubble_data).squeeze() location_of_bubble = (np.argmax(bubble_field > 0.5) - ny // 2) / l0 saddle_data = wlb.field.gather(blocks, 'phase', makeSlice[0, :, self.size[2] // 2]) if saddle_data: - saddle_field = np.asarray(saddle_data.buffer()).squeeze() + saddle_field = np.asarray(saddle_data).squeeze() location_of_saddle = (np.argmax(saddle_field > 0.5) - ny // 2) / l0 phase = wlb.field.gather(blocks, 'phase', makeSlice[:, :, :]) if phase: - phase_field = np.asarray(phase.buffer()).squeeze() + phase_field = np.asarray(phase).squeeze() mass = np.sum(phase_field) self.write_result_to_database(t, location_of_spike, location_of_bubble, location_of_saddle, mass) diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_rising_bubble.py b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_rising_bubble.py index 9a8948868..d424d7c21 100755 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_rising_bubble.py +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_rising_bubble.py @@ -91,12 +91,12 @@ class Scenario: } @wlb.member_callback - def at_end_of_time_step(self, blocks, time_loop): - t = time_loop.getCurrentTimeStep() + def at_end_of_time_step(self, blocks, **kwargs): + t = kwargs['timeStep'] if t % self.dbWriteFrequency == 0: wlb_field = wlb.field.gather(blocks, 'phase', makeSlice[:, :, self.size[2] // 2]) if wlb_field: - phase_field = np.asarray(wlb_field.buffer()).squeeze() + phase_field = np.asarray(wlb_field).squeeze() location_of_gas = np.where(phase_field < 0.5) cov = np.cov(location_of_gas) @@ -107,7 +107,9 @@ class Scenario: self.yPositions.append(center_of_mass[1]) if len(self.yPositions) > 1: speed = self.yPositions[-1] - self.yPositions[-2] - self.write_result_to_database(t, speed, axis_of_the_bubble, center_of_mass) + else: + speed = 0 + self.write_result_to_database(t, speed, axis_of_the_bubble, center_of_mass) self.counter += 1 diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/PythonExports.cpp b/apps/showcases/PhaseFieldAllenCahn/GPU/PythonExports.cpp index 40bb8c52b..4b73da880 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/PythonExports.cpp +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/PythonExports.cpp @@ -20,68 +20,28 @@ #include "waLBerlaDefinitions.h" #ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/Manager.h" +# include "core/math/Constants.h" -#include "core/math/Constants.h" - -#include "blockforest/python/Exports.h" - -#include "field/communication/PackInfo.h" -#include "field/python/Exports.h" - -#include "geometry/python/Exports.h" - -#include "postprocessing/python/Exports.h" - -#include "timeloop/python/Exports.h" +# include "field/communication/PackInfo.h" +# include "python_coupling/Manager.h" +# include "python_coupling/export/BlockForestExport.h" +# include "python_coupling/export/FieldExports.h" namespace walberla { using flag_t = uint8_t; // clang-format off void exportDataStructuresToPython() { - namespace bmpl = boost::mpl; - auto pythonManager = python_coupling::Manager::instance(); - typedef bmpl::vector< - Field<walberla::real_t, 1>, - Field<walberla::real_t, 3>, - Field<walberla::real_t, 9>, - Field<walberla::real_t, 19>, - Field<walberla::real_t, 27>> - FieldTypes; - - typedef bmpl::vector<stencil::D2Q9, - stencil::D3Q19, - stencil::D3Q27> - Stencils; - - typedef bmpl::vector< - GhostLayerField<real_t,1>, - GhostLayerField<real_t,3>> - RealFieldTypes; - - typedef bmpl::vector< - FlagField<flag_t>> - FlagFieldTypes; // Field - pythonManager->addExporterFunction(field::exportModuleToPython<FieldTypes>); - pythonManager->addExporterFunction(field::exportGatherFunctions<FieldTypes>); - pythonManager->addBlockDataConversion<FieldTypes>(); + pythonManager->addExporterFunction(field::exportModuleToPython<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>); + pythonManager->addExporterFunction(field::exportGatherFunctions<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>); + pythonManager->addBlockDataConversion<Field<walberla::real_t, 1>, Field<walberla::real_t, 3>, Field<walberla::real_t, 9>, Field<walberla::real_t, 19>, Field<walberla::real_t, 27>>(); // Blockforest - pythonManager->addExporterFunction(blockforest::exportModuleToPython<Stencils>); - - // Timeloop - pythonManager->addExporterFunction(timeloop::exportModuleToPython); - - // Postprocessing - pythonManager->addExporterFunction( postprocessing::exportModuleToPython<RealFieldTypes, FlagFieldTypes> ); - - // Geometry - pythonManager->addExporterFunction( geometry::exportModuleToPython ); + pythonManager->addExporterFunction(blockforest::exportModuleToPython<stencil::D2Q9, stencil::D3Q19, stencil::D3Q27>); } // clang-format on } diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase.cpp b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase.cpp index a0029b540..2080ce38c 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase.cpp +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase.cpp @@ -34,13 +34,13 @@ #include "field/AddToStorage.h" #include "field/FlagField.h" #include "field/communication/PackInfo.h" -#include "field/python/Exports.h" #include "field/vtk/VTKWriter.h" #include "geometry/InitBoundaryHandling.h" #include "python_coupling/CreateConfig.h" #include "python_coupling/PythonCallback.h" +#include "python_coupling/export/FieldExports.h" #include "timeloop/SweepTimeloop.h" @@ -319,8 +319,8 @@ int main(int argc, char** argv) python_coupling::PythonCallback callback("at_end_of_time_step"); if (callback.isCallable()) { - callback.data().exposePtr("blocks", blocks); - callback.data().exposePtr("time_loop", timeLoop); + callback.data().exposeValue("blocks", blocks); + callback.data().exposeValue( "timeStep", timeLoop->getCurrentTimeStep()); callback(); } } diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_RTI_3D.py b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_RTI_3D.py index d862b1a48..c9798504d 100755 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_RTI_3D.py +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_RTI_3D.py @@ -77,8 +77,8 @@ class Scenario: } @wlb.member_callback - def at_end_of_time_step(self, blocks, time_loop): - t = time_loop.getCurrentTimeStep() + def at_end_of_time_step(self, blocks, **kwargs): + t = kwargs['timeStep'] ny = self.size[1] l0 = self.size[0] if t % self.dbWriteFrequency == 0: @@ -88,22 +88,22 @@ class Scenario: mass = -100 spike_data = wlb.field.gather(blocks, 'phase', makeSlice[self.size[0] // 2, :, self.size[2] // 2]) if spike_data: - spike_field = np.asarray(spike_data.buffer()).squeeze() + spike_field = np.asarray(spike_data).squeeze() location_of_spike = (np.argmax(spike_field > 0.5) - ny // 2) / l0 bubble_data = wlb.field.gather(blocks, 'phase', makeSlice[0, :, 0]) if bubble_data: - bubble_field = np.asarray(bubble_data.buffer()).squeeze() + bubble_field = np.asarray(bubble_data).squeeze() location_of_bubble = (np.argmax(bubble_field > 0.5) - ny // 2) / l0 saddle_data = wlb.field.gather(blocks, 'phase', makeSlice[0, :, self.size[2] // 2]) if saddle_data: - saddle_field = np.asarray(saddle_data.buffer()).squeeze() + saddle_field = np.asarray(saddle_data).squeeze() location_of_saddle = (np.argmax(saddle_field > 0.5) - ny // 2) / l0 phase = wlb.field.gather(blocks, 'phase', makeSlice[:, :, :]) if phase: - phase_field = np.asarray(phase.buffer()).squeeze() + phase_field = np.asarray(phase).squeeze() mass = np.sum(phase_field) self.write_result_to_database(t, location_of_spike, location_of_bubble, location_of_saddle, mass) diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_rising_bubble.py b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_rising_bubble.py index 4294fc7b8..9f5f08323 100755 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_rising_bubble.py +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/multiphase_rising_bubble.py @@ -91,12 +91,12 @@ class Scenario: } @wlb.member_callback - def at_end_of_time_step(self, blocks, time_loop): - t = time_loop.getCurrentTimeStep() + def at_end_of_time_step(self, blocks, **kwargs): + t = kwargs['timeStep'] if t % self.dbWriteFrequency == 0: wlb_field = wlb.field.gather(blocks, 'phase', makeSlice[:, :, self.size[2] // 2]) if wlb_field: - phase_field = np.asarray(wlb_field.buffer()).squeeze() + phase_field = np.asarray(wlb_field).squeeze() location_of_gas = np.where(phase_field < 0.5) cov = np.cov(location_of_gas) @@ -107,7 +107,9 @@ class Scenario: self.yPositions.append(center_of_mass[1]) if len(self.yPositions) > 1: speed = self.yPositions[-1] - self.yPositions[-2] - self.write_result_to_database(t, speed, axis_of_the_bubble, center_of_mass) + else: + speed = 0 + self.write_result_to_database(t, speed, axis_of_the_bubble, center_of_mass) self.counter += 1 diff --git a/cmake/FindBoost.cmake b/cmake/FindBoost.cmake deleted file mode 100644 index 4b16cf672..000000000 --- a/cmake/FindBoost.cmake +++ /dev/null @@ -1,2213 +0,0 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -#[=======================================================================[.rst: -FindBoost ---------- - -Find Boost include dirs and libraries - -Use this module by invoking find_package with the form:: - - find_package(Boost - [version] [EXACT] # Minimum or EXACT version e.g. 1.67.0 - [REQUIRED] # Fail with error if Boost is not found - [COMPONENTS <libs>...] # Boost libraries by their canonical name - # e.g. "date_time" for "libboost_date_time" - [OPTIONAL_COMPONENTS <libs>...] - # Optional Boost libraries by their canonical name) - ) # e.g. "date_time" for "libboost_date_time" - -This module finds headers and requested component libraries OR a CMake -package configuration file provided by a "Boost CMake" build. For the -latter case skip to the "Boost CMake" section below. For the former -case results are reported in variables:: - - Boost_FOUND - True if headers and requested libraries were found - Boost_INCLUDE_DIRS - Boost include directories - Boost_LIBRARY_DIRS - Link directories for Boost libraries - Boost_LIBRARIES - Boost component libraries to be linked - Boost_<C>_FOUND - True if component <C> was found (<C> is upper-case) - Boost_<C>_LIBRARY - Libraries to link for component <C> (may include - target_link_libraries debug/optimized keywords) - Boost_VERSION - BOOST_VERSION value from boost/version.hpp - Boost_LIB_VERSION - Version string appended to library filenames - Boost_MAJOR_VERSION - Boost major version number (X in X.y.z) - Boost_MINOR_VERSION - Boost minor version number (Y in x.Y.z) - Boost_SUBMINOR_VERSION - Boost subminor version number (Z in x.y.Z) - Boost_VERSION_STRING - Boost version number in x.y.z format - Boost_LIB_DIAGNOSTIC_DEFINITIONS (Windows) - - Pass to add_definitions() to have diagnostic - information about Boost's automatic linking - displayed during compilation - -Note that Boost Python components require a Python version suffix -(Boost 1.67 and later), e.g. ``python36`` or ``python27`` for the -versions built against Python 3.6 and 2.7, respectively. This also -applies to additional components using Python including -``mpi_python`` and ``numpy``. Earlier Boost releases may use -distribution-specific suffixes such as ``2``, ``3`` or ``2.7``. -These may also be used as suffixes, but note that they are not -portable. - -This module reads hints about search locations from variables:: - - BOOST_ROOT - Preferred installation prefix - (or BOOSTROOT) - BOOST_INCLUDEDIR - Preferred include directory e.g. <prefix>/include - BOOST_LIBRARYDIR - Preferred library directory e.g. <prefix>/lib - Boost_NO_SYSTEM_PATHS - Set to ON to disable searching in locations not - specified by these hint variables. Default is OFF. - Boost_ADDITIONAL_VERSIONS - - List of Boost versions not known to this module - (Boost install locations may contain the version) - -and saves search results persistently in CMake cache entries:: - - Boost_INCLUDE_DIR - Directory containing Boost headers - Boost_LIBRARY_DIR_RELEASE - Directory containing release Boost libraries - Boost_LIBRARY_DIR_DEBUG - Directory containing debug Boost libraries - Boost_<C>_LIBRARY_DEBUG - Component <C> library debug variant - Boost_<C>_LIBRARY_RELEASE - Component <C> library release variant - -The following :prop_tgt:`IMPORTED` targets are also defined:: - - Boost::boost - Target for header-only dependencies - (Boost include directory) - Boost::<C> - Target for specific component dependency - (shared or static library); <C> is lower- - case - Boost::diagnostic_definitions - interface target to enable diagnostic - information about Boost's automatic linking - during compilation (adds BOOST_LIB_DIAGNOSTIC) - Boost::disable_autolinking - interface target to disable automatic - linking with MSVC (adds BOOST_ALL_NO_LIB) - Boost::dynamic_linking - interface target to enable dynamic linking - linking with MSVC (adds BOOST_ALL_DYN_LINK) - -Implicit dependencies such as Boost::filesystem requiring -Boost::system will be automatically detected and satisfied, even -if system is not specified when using find_package and if -Boost::system is not added to target_link_libraries. If using -Boost::thread, then Threads::Threads will also be added automatically. - -It is important to note that the imported targets behave differently -than variables created by this module: multiple calls to -find_package(Boost) in the same directory or sub-directories with -different options (e.g. static or shared) will not override the -values of the targets created by the first call. - -Users may set these hints or results as cache entries. Projects -should not read these entries directly but instead use the above -result variables. Note that some hint names start in upper-case -"BOOST". One may specify these as environment variables if they are -not specified as CMake variables or cache entries. - -This module first searches for the Boost header files using the above -hint variables (excluding BOOST_LIBRARYDIR) and saves the result in -Boost_INCLUDE_DIR. Then it searches for requested component libraries -using the above hints (excluding BOOST_INCLUDEDIR and -Boost_ADDITIONAL_VERSIONS), "lib" directories near Boost_INCLUDE_DIR, -and the library name configuration settings below. It saves the -library directories in Boost_LIBRARY_DIR_DEBUG and -Boost_LIBRARY_DIR_RELEASE and individual library -locations in Boost_<C>_LIBRARY_DEBUG and Boost_<C>_LIBRARY_RELEASE. -When one changes settings used by previous searches in the same build -tree (excluding environment variables) this module discards previous -search results affected by the changes and searches again. - -Boost libraries come in many variants encoded in their file name. -Users or projects may tell this module which variant to find by -setting variables:: - - Boost_USE_DEBUG_LIBS - Set to ON or OFF to specify whether to search - and use the debug libraries. Default is ON. - Boost_USE_RELEASE_LIBS - Set to ON or OFF to specify whether to search - and use the release libraries. Default is ON. - Boost_USE_MULTITHREADED - Set to OFF to use the non-multithreaded - libraries ('mt' tag). Default is ON. - Boost_USE_STATIC_LIBS - Set to ON to force the use of the static - libraries. Default is OFF. - Boost_USE_STATIC_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked statically to the C++ runtime - ('s' tag). Default is platform dependent. - Boost_USE_DEBUG_RUNTIME - Set to ON or OFF to specify whether to use - libraries linked to the MS debug C++ runtime - ('g' tag). Default is ON. - Boost_USE_DEBUG_PYTHON - Set to ON to use libraries compiled with a - debug Python build ('y' tag). Default is OFF. - Boost_USE_STLPORT - Set to ON to use libraries compiled with - STLPort ('p' tag). Default is OFF. - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - - Set to ON to use libraries compiled with - STLPort deprecated "native iostreams" - ('n' tag). Default is OFF. - Boost_COMPILER - Set to the compiler-specific library suffix - (e.g. "-gcc43"). Default is auto-computed - for the C++ compiler in use. A list may be - used if multiple compatible suffixes should - be tested for, in decreasing order of - preference. - Boost_ARCHITECTURE - Set to the architecture-specific library suffix - (e.g. "-x64"). Default is auto-computed for the - C++ compiler in use. - Boost_THREADAPI - Suffix for "thread" component library name, - such as "pthread" or "win32". Names with - and without this suffix will both be tried. - Boost_NAMESPACE - Alternate namespace used to build boost with - e.g. if set to "myboost", will search for - myboost_thread instead of boost_thread. - -Other variables one may set to control this module are:: - - Boost_DEBUG - Set to ON to enable debug output from FindBoost. - Please enable this before filing any bug report. - Boost_DETAILED_FAILURE_MSG - - Set to ON to add detailed information to the - failure message even when the REQUIRED option - is not given to the find_package call. - Boost_REALPATH - Set to ON to resolve symlinks for discovered - libraries to assist with packaging. For example, - the "system" component library may be resolved to - "/usr/lib/libboost_system.so.1.67.0" instead of - "/usr/lib/libboost_system.so". This does not - affect linking and should not be enabled unless - the user needs this information. - Boost_LIBRARY_DIR - Default value for Boost_LIBRARY_DIR_RELEASE and - Boost_LIBRARY_DIR_DEBUG. - -On Visual Studio and Borland compilers Boost headers request automatic -linking to corresponding libraries. This requires matching libraries -to be linked explicitly or available in the link library search path. -In this case setting Boost_USE_STATIC_LIBS to OFF may not achieve -dynamic linking. Boost automatic linking typically requests static -libraries with a few exceptions (such as Boost.Python). Use:: - - add_definitions(${Boost_LIB_DIAGNOSTIC_DEFINITIONS}) - -to ask Boost to report information about automatic linking requests. - -Example to find Boost headers only:: - - find_package(Boost 1.36.0) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - endif() - -Example to find Boost libraries and use imported targets:: - - find_package(Boost 1.56 REQUIRED COMPONENTS - date_time filesystem iostreams) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::date_time Boost::filesystem - Boost::iostreams) - -Example to find Boost Python 3.6 libraries and use imported targets:: - - find_package(Boost 1.67 REQUIRED COMPONENTS - python36 numpy36) - add_executable(foo foo.cc) - target_link_libraries(foo Boost::python36 Boost::numpy36) - -Example to find Boost headers and some *static* (release only) libraries:: - - set(Boost_USE_STATIC_LIBS ON) # only find static libs - set(Boost_USE_DEBUG_LIBS OFF) # ignore debug libs and - set(Boost_USE_RELEASE_LIBS ON) # only find release libs - set(Boost_USE_MULTITHREADED ON) - set(Boost_USE_STATIC_RUNTIME OFF) - find_package(Boost 1.66.0 COMPONENTS date_time filesystem system ...) - if(Boost_FOUND) - include_directories(${Boost_INCLUDE_DIRS}) - add_executable(foo foo.cc) - target_link_libraries(foo ${Boost_LIBRARIES}) - endif() - -Boost CMake -^^^^^^^^^^^ - -If Boost was built using the boost-cmake project it provides a package -configuration file for use with find_package's Config mode. This -module looks for the package configuration file called -BoostConfig.cmake or boost-config.cmake and stores the result in cache -entry "Boost_DIR". If found, the package configuration file is loaded -and this module returns with no further action. See documentation of -the Boost CMake package configuration for details on what it provides. - -Set Boost_NO_BOOST_CMAKE to ON to disable the search for boost-cmake. -#]=======================================================================] - -# Save project's policies -cmake_policy(PUSH) -cmake_policy(SET CMP0057 NEW) # if IN_LIST - -#------------------------------------------------------------------------------- -# Before we go searching, check whether boost-cmake is available, unless the -# user specifically asked NOT to search for boost-cmake. -# -# If Boost_DIR is set, this behaves as any find_package call would. If not, -# it looks at BOOST_ROOT and BOOSTROOT to find Boost. -# -if (NOT Boost_NO_BOOST_CMAKE) - # If Boost_DIR is not set, look for BOOSTROOT and BOOST_ROOT as alternatives, - # since these are more conventional for Boost. - if ("$ENV{Boost_DIR}" STREQUAL "") - if (NOT "$ENV{BOOST_ROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOST_ROOT}) - elseif (NOT "$ENV{BOOSTROOT}" STREQUAL "") - set(ENV{Boost_DIR} $ENV{BOOSTROOT}) - endif() - endif() - - # Do the same find_package call but look specifically for the CMake version. - # Note that args are passed in the Boost_FIND_xxxxx variables, so there is no - # need to delegate them to this find_package call. - find_package(Boost QUIET NO_MODULE) - mark_as_advanced(Boost_DIR) - - # If we found boost-cmake, then we're done. Print out what we found. - # Otherwise let the rest of the module try to find it. - if (Boost_FOUND) - message(STATUS "Boost ${Boost_FIND_VERSION} found.") - if (Boost_FIND_COMPONENTS) - message(STATUS "Found Boost components:\n ${Boost_FIND_COMPONENTS}") - endif() - # Restore project's policies - cmake_policy(POP) - return() - endif() -endif() - - -#------------------------------------------------------------------------------- -# FindBoost functions & macros -# - -############################################ -# -# Check the existence of the libraries. -# -############################################ -# This macro was taken directly from the FindQt4.cmake file that is included -# with the CMake distribution. This is NOT my work. All work was done by the -# original authors of the FindQt4.cmake file. Only minor modifications were -# made to remove references to Qt and make this file more generally applicable -# And ELSE/ENDIF pairs were removed for readability. -######################################################################### - -macro(_Boost_ADJUST_LIB_VARS basename) - if(Boost_INCLUDE_DIR ) - if(Boost_${basename}_LIBRARY_DEBUG AND Boost_${basename}_LIBRARY_RELEASE) - # if the generator is multi-config or if CMAKE_BUILD_TYPE is set for - # single-config generators, set optimized and debug libraries - get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) - if(_isMultiConfig OR CMAKE_BUILD_TYPE) - set(Boost_${basename}_LIBRARY optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - else() - # For single-config generators where CMAKE_BUILD_TYPE has no value, - # just use the release libraries - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - # FIXME: This probably should be set for both cases - set(Boost_${basename}_LIBRARIES optimized ${Boost_${basename}_LIBRARY_RELEASE} debug ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # if only the release version was found, set the debug variable also to the release version - if(Boost_${basename}_LIBRARY_RELEASE AND NOT Boost_${basename}_LIBRARY_DEBUG) - set(Boost_${basename}_LIBRARY_DEBUG ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE}) - endif() - - # if only the debug version was found, set the release variable also to the debug version - if(Boost_${basename}_LIBRARY_DEBUG AND NOT Boost_${basename}_LIBRARY_RELEASE) - set(Boost_${basename}_LIBRARY_RELEASE ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_DEBUG}) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_DEBUG}) - endif() - - # If the debug & release library ends up being the same, omit the keywords - if("${Boost_${basename}_LIBRARY_RELEASE}" STREQUAL "${Boost_${basename}_LIBRARY_DEBUG}") - set(Boost_${basename}_LIBRARY ${Boost_${basename}_LIBRARY_RELEASE} ) - set(Boost_${basename}_LIBRARIES ${Boost_${basename}_LIBRARY_RELEASE} ) - endif() - - if(Boost_${basename}_LIBRARY AND Boost_${basename}_HEADER) - set(Boost_${basename}_FOUND ON) - if("x${basename}" STREQUAL "xTHREAD" AND NOT TARGET Threads::Threads) - string(APPEND Boost_ERROR_REASON_THREAD " (missing dependency: Threads)") - set(Boost_THREAD_FOUND OFF) - endif() - endif() - - endif() - # Make variables changeable to the advanced user - mark_as_advanced( - Boost_${basename}_LIBRARY_RELEASE - Boost_${basename}_LIBRARY_DEBUG - ) -endmacro() - -# Detect changes in used variables. -# Compares the current variable value with the last one. -# In short form: -# v != v_LAST -> CHANGED = 1 -# v is defined, v_LAST not -> CHANGED = 1 -# v is not defined, but v_LAST is -> CHANGED = 1 -# otherwise -> CHANGED = 0 -# CHANGED is returned in variable named ${changed_var} -macro(_Boost_CHANGE_DETECT changed_var) - set(${changed_var} 0) - foreach(v ${ARGN}) - if(DEFINED _Boost_COMPONENTS_SEARCHED) - if(${v}) - if(_${v}_LAST) - string(COMPARE NOTEQUAL "${${v}}" "${_${v}_LAST}" _${v}_CHANGED) - else() - set(_${v}_CHANGED 1) - endif() - elseif(_${v}_LAST) - set(_${v}_CHANGED 1) - endif() - if(_${v}_CHANGED) - set(${changed_var} 1) - endif() - else() - set(_${v}_CHANGED 0) - endif() - endforeach() -endmacro() - -# -# Find the given library (var). -# Use 'build_type' to support different lib paths for RELEASE or DEBUG builds -# -macro(_Boost_FIND_LIBRARY var build_type) - - find_library(${var} ${ARGN}) - - if(${var}) - # If this is the first library found then save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - if(NOT Boost_LIBRARY_DIR_${build_type}) - get_filename_component(_dir "${${var}}" PATH) - set(Boost_LIBRARY_DIR_${build_type} "${_dir}" CACHE PATH "Boost library directory ${build_type}" FORCE) - endif() - elseif(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - # Try component-specific hints but do not save Boost_LIBRARY_DIR_[RELEASE,DEBUG]. - find_library(${var} HINTS ${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT} ${ARGN}) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is known then search only there. - if(Boost_LIBRARY_DIR_${build_type}) - set(_boost_LIBRARY_SEARCH_DIRS_${build_type} ${Boost_LIBRARY_DIR_${build_type}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " Boost_LIBRARY_DIR_${build_type} = ${Boost_LIBRARY_DIR_${build_type}}" - " _boost_LIBRARY_SEARCH_DIRS_${build_type} = ${_boost_LIBRARY_SEARCH_DIRS_${build_type}}") - endif() - endif() -endmacro() - -#------------------------------------------------------------------------------- - -# Convert CMAKE_CXX_COMPILER_VERSION to boost compiler suffix version. -function(_Boost_COMPILER_DUMPVERSION _OUTPUT_VERSION _OUTPUT_VERSION_MAJOR _OUTPUT_VERSION_MINOR) - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\1" - _boost_COMPILER_VERSION_MAJOR "${CMAKE_CXX_COMPILER_VERSION}") - string(REGEX REPLACE "([0-9]+)\\.([0-9]+)(\\.[0-9]+)?" "\\2" - _boost_COMPILER_VERSION_MINOR "${CMAKE_CXX_COMPILER_VERSION}") - - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}${_boost_COMPILER_VERSION_MINOR}") - - set(${_OUTPUT_VERSION} ${_boost_COMPILER_VERSION} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MAJOR} ${_boost_COMPILER_VERSION_MAJOR} PARENT_SCOPE) - set(${_OUTPUT_VERSION_MINOR} ${_boost_COMPILER_VERSION_MINOR} PARENT_SCOPE) -endfunction() - -# -# Take a list of libraries with "thread" in it -# and prepend duplicates with "thread_${Boost_THREADAPI}" -# at the front of the list -# -function(_Boost_PREPEND_LIST_WITH_THREADAPI _output) - set(_orig_libnames ${ARGN}) - string(REPLACE "thread" "thread_${Boost_THREADAPI}" _threadapi_libnames "${_orig_libnames}") - set(${_output} ${_threadapi_libnames} ${_orig_libnames} PARENT_SCOPE) -endfunction() - -# -# If a library is found, replace its cache entry with its REALPATH -# -function(_Boost_SWAP_WITH_REALPATH _library _docstring) - if(${_library}) - get_filename_component(_boost_filepathreal ${${_library}} REALPATH) - unset(${_library} CACHE) - set(${_library} ${_boost_filepathreal} CACHE FILEPATH "${_docstring}") - endif() -endfunction() - -function(_Boost_CHECK_SPELLING _var) - if(${_var}) - string(TOUPPER ${_var} _var_UC) - message(FATAL_ERROR "ERROR: ${_var} is not the correct spelling. The proper spelling is ${_var_UC}.") - endif() -endfunction() - -# Guesses Boost's compiler prefix used in built library names -# Returns the guess by setting the variable pointed to by _ret -function(_Boost_GUESS_COMPILER_PREFIX _ret) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - if(WIN32) - set (_boost_COMPILER "-iw") - else() - set (_boost_COMPILER "-il") - endif() - elseif (GHSMULTI) - set(_boost_COMPILER "-ghs") - elseif("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141) - set(_boost_COMPILER "-vc141;-vc140") - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - set(_boost_COMPILER "-vc${MSVC_TOOLSET_VERSION}") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13.10) - set(_boost_COMPILER "-vc71") - elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 13) # Good luck! - set(_boost_COMPILER "-vc7") # yes, this is correct - else() # VS 6.0 Good luck! - set(_boost_COMPILER "-vc6") # yes, this is correct - endif() - elseif (BORLAND) - set(_boost_COMPILER "-bcb") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "SunPro") - set(_boost_COMPILER "-sw") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "XL") - set(_boost_COMPILER "-xlc") - elseif (MINGW) - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-mgw") # no GCC version encoding prior to 1.34 - else() - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - set(_boost_COMPILER "-mgw${_boost_COMPILER_VERSION}") - endif() - elseif (UNIX) - _Boost_COMPILER_DUMPVERSION(_boost_COMPILER_VERSION _boost_COMPILER_VERSION_MAJOR _boost_COMPILER_VERSION_MINOR) - if(NOT Boost_VERSION VERSION_LESS 106900) - # From GCC 5 and clang 4, versioning changes and minor becomes patch. - # For those compilers, patch is exclude from compiler tag in Boost 1.69+ library naming. - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 4) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND _boost_COMPILER_VERSION_MAJOR VERSION_GREATER 3) - set(_boost_COMPILER_VERSION "${_boost_COMPILER_VERSION_MAJOR}") - endif() - endif() - - if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - if(${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION} VERSION_LESS 1.34) - set(_boost_COMPILER "-gcc") # no GCC version encoding prior to 1.34 - else() - # Determine which version of GCC we have. - if(APPLE) - if(Boost_MINOR_VERSION) - if(${Boost_MINOR_VERSION} GREATER 35) - # In Boost 1.36.0 and newer, the mangled compiler name used - # on macOS/Darwin is "xgcc". - set(_boost_COMPILER "-xgcc${_boost_COMPILER_VERSION}") - else() - # In Boost <= 1.35.0, there is no mangled compiler name for - # the macOS/Darwin version of GCC. - set(_boost_COMPILER "") - endif() - else() - # We don't know the Boost version, so assume it's - # pre-1.36.0. - set(_boost_COMPILER "") - endif() - else() - set(_boost_COMPILER "-gcc${_boost_COMPILER_VERSION}") - endif() - endif() - elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") - # TODO: Find out any Boost version constraints vs clang support. - set(_boost_COMPILER "-clang${_boost_COMPILER_VERSION}") - endif() - else() - # TODO at least Boost_DEBUG here? - set(_boost_COMPILER "") - endif() - set(${_ret} ${_boost_COMPILER} PARENT_SCOPE) -endfunction() - -# -# Get component dependencies. Requires the dependencies to have been -# defined for the Boost release version. -# -# component - the component to check -# _ret - list of library dependencies -# -function(_Boost_COMPONENT_DEPENDENCIES component _ret) - # Note: to add a new Boost release, run - # - # % cmake -DBOOST_DIR=/path/to/boost/source -P Utilities/Scripts/BoostScanDeps.cmake - # - # The output may be added in a new block below. If it's the same as - # the previous release, simply update the version range of the block - # for the previous release. Also check if any new components have - # been added, and add any new components to - # _Boost_COMPONENT_HEADERS. - # - # This information was originally generated by running - # BoostScanDeps.cmake against every boost release to date supported - # by FindBoost: - # - # % for version in /path/to/boost/sources/* - # do - # cmake -DBOOST_DIR=$version -P Utilities/Scripts/BoostScanDeps.cmake - # done - # - # The output was then updated by search and replace with these regexes: - # - # - Strip message(STATUS) prefix dashes - # s;^-- ;; - # - Indent - # s;^set(; set(;; - # - Add conditionals - # s;Scanning /path/to/boost/sources/boost_\(.*\)_\(.*\)_\(.*); elseif(NOT Boost_VERSION VERSION_LESS \10\20\3 AND Boost_VERSION VERSION_LESS xxxx); - # - # This results in the logic seen below, but will require the xxxx - # replacing with the following Boost release version (or the next - # minor version to be released, e.g. 1.59 was the latest at the time - # of writing, making 1.60 the next, so 106000 is the needed version - # number). Identical consecutive releases were then merged together - # by updating the end range of the first block and removing the - # following redundant blocks. - # - # Running the script against all historical releases should be - # required only if the BoostScanDeps.cmake script logic is changed. - # The addition of a new release should only require it to be run - # against the new release. - - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - set(_Boost_IMPORTED_TARGETS TRUE) - if(Boost_VERSION AND Boost_VERSION VERSION_LESS 103300) - message(WARNING "Imported targets and dependency information not available for Boost version ${Boost_VERSION} (all versions older than 1.33)") - set(_Boost_IMPORTED_TARGETS FALSE) - elseif(NOT Boost_VERSION VERSION_LESS 103300 AND Boost_VERSION VERSION_LESS 103500) - set(_Boost_IOSTREAMS_DEPENDENCIES regex thread) - set(_Boost_REGEX_DEPENDENCIES thread) - set(_Boost_WAVE_DEPENDENCIES filesystem thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103500 AND Boost_VERSION VERSION_LESS 103600) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103600 AND Boost_VERSION VERSION_LESS 103800) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 103800 AND Boost_VERSION VERSION_LESS 104300) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104300 AND Boost_VERSION VERSION_LESS 104400) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104400 AND Boost_VERSION VERSION_LESS 104500) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random serialization) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES serialization filesystem system thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104500 AND Boost_VERSION VERSION_LESS 104700) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104700 AND Boost_VERSION VERSION_LESS 104800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 104800 AND Boost_VERSION VERSION_LESS 105000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105000 AND Boost_VERSION VERSION_LESS 105300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105300 AND Boost_VERSION VERSION_LESS 105400) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105400 AND Boost_VERSION VERSION_LESS 105500) - set(_Boost_ATOMIC_DEPENDENCIES thread chrono system date_time) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105500 AND Boost_VERSION VERSION_LESS 105600) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l regex random) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105600 AND Boost_VERSION VERSION_LESS 105900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 105900 AND Boost_VERSION VERSION_LESS 106000) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES log_setup date_time system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106000 AND Boost_VERSION VERSION_LESS 106100) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106100 AND Boost_VERSION VERSION_LESS 106200) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106300) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106300 AND Boost_VERSION VERSION_LESS 106500) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_COROUTINE2_DEPENDENCIES context fiber thread chrono system date_time) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106500 AND Boost_VERSION VERSION_LESS 106700) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106700 AND Boost_VERSION VERSION_LESS 106800) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106800 AND Boost_VERSION VERSION_LESS 106900) - set(_Boost_CHRONO_DEPENDENCIES system) - set(_Boost_CONTEXT_DEPENDENCIES thread chrono system date_time) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono system date_time) - set(_Boost_COROUTINE_DEPENDENCIES context system) - set(_Boost_FIBER_DEPENDENCIES context thread chrono system date_time) - set(_Boost_FILESYSTEM_DEPENDENCIES system) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup system filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_RANDOM_DEPENDENCIES system) - set(_Boost_THREAD_DEPENDENCIES chrono system date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem system serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 106900 AND Boost_VERSION VERSION_LESS 107000) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono system) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 107000 AND Boost_VERSION VERSION_LESS 107200) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - elseif(NOT Boost_VERSION VERSION_LESS 107200 AND Boost_VERSION VERSION_LESS 107300) - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l chrono atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - else() - set(_Boost_CONTRACT_DEPENDENCIES thread chrono date_time) - set(_Boost_COROUTINE_DEPENDENCIES context) - set(_Boost_FIBER_DEPENDENCIES context) - set(_Boost_IOSTREAMS_DEPENDENCIES regex) - set(_Boost_LOG_DEPENDENCIES date_time log_setup filesystem thread regex chrono atomic) - set(_Boost_MATH_DEPENDENCIES math_c99 math_c99f math_c99l math_tr1 math_tr1f math_tr1l atomic) - set(_Boost_MPI_DEPENDENCIES serialization) - set(_Boost_MPI_PYTHON_DEPENDENCIES python${component_python_version} mpi serialization) - set(_Boost_NUMPY_DEPENDENCIES python${component_python_version}) - set(_Boost_THREAD_DEPENDENCIES chrono date_time atomic) - set(_Boost_TIMER_DEPENDENCIES chrono) - set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono date_time atomic) - set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION VERSION_GREATER_EQUAL 107400) - message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") - endif() - endif() - - - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_DEPS_STRING "${_Boost_${uppercomponent}_DEPENDENCIES}") - if (NOT _boost_DEPS_STRING) - set(_boost_DEPS_STRING "(none)") - endif() - # message(STATUS "Dependencies for Boost::${component}: ${_boost_DEPS_STRING}") -endfunction() - -# -# Get component headers. This is the primary header (or headers) for -# a given component, and is used to check that the headers are present -# as well as the library itself as an extra sanity check of the build -# environment. -# -# component - the component to check -# _hdrs -# -function(_Boost_COMPONENT_HEADERS component _hdrs) - # Handle Python version suffixes - if(component MATCHES "^(python|mpi_python|numpy)([0-9][0-9]?|[0-9]\\.[0-9])\$") - set(component "${CMAKE_MATCH_1}") - set(component_python_version "${CMAKE_MATCH_2}") - endif() - - # Note: new boost components will require adding here. The header - # must be present in all versions of Boost providing a library. - set(_Boost_ATOMIC_HEADERS "boost/atomic.hpp") - set(_Boost_CHRONO_HEADERS "boost/chrono.hpp") - set(_Boost_CONTAINER_HEADERS "boost/container/container_fwd.hpp") - set(_Boost_CONTRACT_HEADERS "boost/contract.hpp") - if(Boost_VERSION VERSION_LESS 106100) - set(_Boost_CONTEXT_HEADERS "boost/context/all.hpp") - else() - set(_Boost_CONTEXT_HEADERS "boost/context/detail/fcontext.hpp") - endif() - set(_Boost_COROUTINE_HEADERS "boost/coroutine/all.hpp") - set(_Boost_DATE_TIME_HEADERS "boost/date_time/date.hpp") - set(_Boost_EXCEPTION_HEADERS "boost/exception/exception.hpp") - set(_Boost_FIBER_HEADERS "boost/fiber/all.hpp") - set(_Boost_FILESYSTEM_HEADERS "boost/filesystem/path.hpp") - set(_Boost_GRAPH_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_GRAPH_PARALLEL_HEADERS "boost/graph/adjacency_list.hpp") - set(_Boost_IOSTREAMS_HEADERS "boost/iostreams/stream.hpp") - set(_Boost_LOCALE_HEADERS "boost/locale.hpp") - set(_Boost_LOG_HEADERS "boost/log/core.hpp") - set(_Boost_LOG_SETUP_HEADERS "boost/log/detail/setup_config.hpp") - set(_Boost_MATH_HEADERS "boost/math_fwd.hpp") - set(_Boost_MATH_C99_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_C99L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1F_HEADERS "boost/math/tr1.hpp") - set(_Boost_MATH_TR1L_HEADERS "boost/math/tr1.hpp") - set(_Boost_MPI_HEADERS "boost/mpi.hpp") - set(_Boost_MPI_PYTHON_HEADERS "boost/mpi/python/config.hpp") - set(_Boost_NUMPY_HEADERS "boost/python/numpy.hpp") - set(_Boost_PRG_EXEC_MONITOR_HEADERS "boost/test/prg_exec_monitor.hpp") - set(_Boost_PROGRAM_OPTIONS_HEADERS "boost/program_options.hpp") - set(_Boost_PYTHON_HEADERS "boost/python.hpp") - set(_Boost_RANDOM_HEADERS "boost/random.hpp") - set(_Boost_REGEX_HEADERS "boost/regex.hpp") - set(_Boost_SERIALIZATION_HEADERS "boost/serialization/serialization.hpp") - set(_Boost_SIGNALS_HEADERS "boost/signals.hpp") - set(_Boost_STACKTRACE_ADDR2LINE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BACKTRACE_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_BASIC_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_NOOP_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_CACHED_HEADERS "boost/stacktrace.hpp") - set(_Boost_STACKTRACE_WINDBG_HEADERS "boost/stacktrace.hpp") - set(_Boost_SYSTEM_HEADERS "boost/system/config.hpp") - set(_Boost_TEST_EXEC_MONITOR_HEADERS "boost/test/test_exec_monitor.hpp") - set(_Boost_THREAD_HEADERS "boost/thread.hpp") - set(_Boost_TIMER_HEADERS "boost/timer.hpp") - set(_Boost_TYPE_ERASURE_HEADERS "boost/type_erasure/config.hpp") - set(_Boost_UNIT_TEST_FRAMEWORK_HEADERS "boost/test/framework.hpp") - set(_Boost_WAVE_HEADERS "boost/wave.hpp") - set(_Boost_WSERIALIZATION_HEADERS "boost/archive/text_wiarchive.hpp") - if(WIN32) - set(_Boost_BZIP2_HEADERS "boost/iostreams/filter/bzip2.hpp") - set(_Boost_ZLIB_HEADERS "boost/iostreams/filter/zlib.hpp") - endif() - - string(TOUPPER ${component} uppercomponent) - set(${_hdrs} ${_Boost_${uppercomponent}_HEADERS} PARENT_SCOPE) - - string(REGEX REPLACE ";" " " _boost_HDRS_STRING "${_Boost_${uppercomponent}_HEADERS}") - if (NOT _boost_HDRS_STRING) - set(_boost_HDRS_STRING "(none)") - endif() - # message(STATUS "Headers for Boost::${component}: ${_boost_HDRS_STRING}") -endfunction() - -# -# Determine if any missing dependencies require adding to the component list. -# -# Sets _Boost_${COMPONENT}_DEPENDENCIES for each required component, -# plus _Boost_IMPORTED_TARGETS (TRUE if imported targets should be -# defined; FALSE if dependency information is unavailable). -# -# componentvar - the component list variable name -# extravar - the indirect dependency list variable name -# -# -function(_Boost_MISSING_DEPENDENCIES componentvar extravar) - # _boost_unprocessed_components - list of components requiring processing - # _boost_processed_components - components already processed (or currently being processed) - # _boost_new_components - new components discovered for future processing - # - list(APPEND _boost_unprocessed_components ${${componentvar}}) - - while(_boost_unprocessed_components) - list(APPEND _boost_processed_components ${_boost_unprocessed_components}) - foreach(component ${_boost_unprocessed_components}) - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - _Boost_COMPONENT_DEPENDENCIES("${component}" _Boost_${uppercomponent}_DEPENDENCIES) - set(_Boost_${uppercomponent}_DEPENDENCIES ${_Boost_${uppercomponent}_DEPENDENCIES} PARENT_SCOPE) - set(_Boost_IMPORTED_TARGETS ${_Boost_IMPORTED_TARGETS} PARENT_SCOPE) - foreach(componentdep ${_Boost_${uppercomponent}_DEPENDENCIES}) - if (NOT ("${componentdep}" IN_LIST _boost_processed_components OR "${componentdep}" IN_LIST _boost_new_components)) - list(APPEND _boost_new_components ${componentdep}) - endif() - endforeach() - endforeach() - set(_boost_unprocessed_components ${_boost_new_components}) - unset(_boost_new_components) - endwhile() - set(_boost_extra_components ${_boost_processed_components}) - if(_boost_extra_components AND ${componentvar}) - list(REMOVE_ITEM _boost_extra_components ${${componentvar}}) - endif() - set(${componentvar} ${_boost_processed_components} PARENT_SCOPE) - set(${extravar} ${_boost_extra_components} PARENT_SCOPE) -endfunction() - -# -# Some boost libraries may require particular set of compler features. -# The very first one was `boost::fiber` introduced in Boost 1.62. -# One can check required compiler features of it in -# `${Boost_ROOT}/libs/fiber/build/Jamfile.v2`. -# -function(_Boost_COMPILER_FEATURES component _ret) - # Boost >= 1.62 and < 1.67 - if(NOT Boost_VERSION VERSION_LESS 106200 AND Boost_VERSION VERSION_LESS 106700) - set(_Boost_FIBER_COMPILER_FEATURES - cxx_alias_templates - cxx_auto_type - cxx_constexpr - cxx_defaulted_functions - cxx_final - cxx_lambdas - cxx_noexcept - cxx_nullptr - cxx_rvalue_references - cxx_thread_local - cxx_variadic_templates - ) - endif() - string(TOUPPER ${component} uppercomponent) - set(${_ret} ${_Boost_${uppercomponent}_COMPILER_FEATURES} PARENT_SCOPE) -endfunction() - -# -# Update library search directory hint variable with paths used by prebuilt boost binaries. -# -# Prebuilt windows binaries (https://sourceforge.net/projects/boost/files/boost-binaries/) -# have library directories named using MSVC compiler version and architecture. -# This function would append corresponding directories if MSVC is a current compiler, -# so having `BOOST_ROOT` would be enough to specify to find everything. -# -function(_Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS componentlibvar basedir) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(_arch_suffix 64) - else() - set(_arch_suffix 32) - endif() - if(MSVC_TOOLSET_VERSION GREATER_EQUAL 141) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.1) - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-14.0) - elseif(MSVC_TOOLSET_VERSION GREATER_EQUAL 80) - math(EXPR _toolset_major_version "${MSVC_TOOLSET_VERSION} / 10") - list(APPEND ${componentlibvar} ${basedir}/lib${_arch_suffix}-msvc-${_toolset_major_version}.0) - endif() - set(${componentlibvar} ${${componentlibvar}} PARENT_SCOPE) - endif() -endfunction() - -# -# End functions/macros -# -#------------------------------------------------------------------------------- - -#------------------------------------------------------------------------------- -# main. -#------------------------------------------------------------------------------- - - -# If the user sets Boost_LIBRARY_DIR, use it as the default for both -# configurations. -if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_RELEASE "${Boost_LIBRARY_DIR}") -endif() -if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR) - set(Boost_LIBRARY_DIR_DEBUG "${Boost_LIBRARY_DIR}") -endif() - -if(NOT DEFINED Boost_USE_DEBUG_LIBS) - set(Boost_USE_DEBUG_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_RELEASE_LIBS) - set(Boost_USE_RELEASE_LIBS TRUE) -endif() -if(NOT DEFINED Boost_USE_MULTITHREADED) - set(Boost_USE_MULTITHREADED TRUE) -endif() -if(NOT DEFINED Boost_USE_DEBUG_RUNTIME) - set(Boost_USE_DEBUG_RUNTIME TRUE) -endif() - -# Check the version of Boost against the requested version. -if(Boost_FIND_VERSION AND NOT Boost_FIND_VERSION_MINOR) - message(SEND_ERROR "When requesting a specific version of Boost, you must provide at least the major and minor version numbers, e.g., 1.34") -endif() - -if(Boost_FIND_VERSION_EXACT) - # The version may appear in a directory with or without the patch - # level, even when the patch level is non-zero. - set(_boost_TEST_VERSIONS - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}.${Boost_FIND_VERSION_PATCH}" - "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") -else() - # The user has not requested an exact version. Among known - # versions, find those that are acceptable to the user request. - # - # Note: When adding a new Boost release, also update the dependency - # information in _Boost_COMPONENT_DEPENDENCIES and - # _Boost_COMPONENT_HEADERS. See the instructions at the top of - # _Boost_COMPONENT_DEPENDENCIES. - set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.70.0" "1.70" "1.69.0" "1.69" - "1.68.0" "1.68" "1.67.0" "1.67" "1.66.0" "1.66" "1.65.1" "1.65.0" "1.65" - "1.64.0" "1.64" "1.63.0" "1.63" "1.62.0" "1.62" "1.61.0" "1.61" "1.60.0" "1.60" - "1.59.0" "1.59" "1.58.0" "1.58" "1.57.0" "1.57" "1.56.0" "1.56" "1.55.0" "1.55" - "1.54.0" "1.54" "1.53.0" "1.53" "1.52.0" "1.52" "1.51.0" "1.51" - "1.50.0" "1.50" "1.49.0" "1.49" "1.48.0" "1.48" "1.47.0" "1.47" "1.46.1" - "1.46.0" "1.46" "1.45.0" "1.45" "1.44.0" "1.44" "1.43.0" "1.43" "1.42.0" "1.42" - "1.41.0" "1.41" "1.40.0" "1.40" "1.39.0" "1.39" "1.38.0" "1.38" "1.37.0" "1.37" - "1.36.1" "1.36.0" "1.36" "1.35.1" "1.35.0" "1.35" "1.34.1" "1.34.0" - "1.34" "1.33.1" "1.33.0" "1.33") - - set(_boost_TEST_VERSIONS) - if(Boost_FIND_VERSION) - set(_Boost_FIND_VERSION_SHORT "${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - # Select acceptable versions. - foreach(version ${_Boost_KNOWN_VERSIONS}) - if(NOT "${version}" VERSION_LESS "${Boost_FIND_VERSION}") - # This version is high enough. - list(APPEND _boost_TEST_VERSIONS "${version}") - elseif("${version}.99" VERSION_EQUAL "${_Boost_FIND_VERSION_SHORT}.99") - # This version is a short-form for the requested version with - # the patch level dropped. - list(APPEND _boost_TEST_VERSIONS "${version}") - endif() - endforeach() - else() - # Any version is acceptable. - set(_boost_TEST_VERSIONS "${_Boost_KNOWN_VERSIONS}") - endif() -endif() - -# The reason that we failed to find Boost. This will be set to a -# user-friendly message when we fail to find some necessary piece of -# Boost. -set(Boost_ERROR_REASON) - -if(Boost_DEBUG) - # Output some of their choices - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_MULTITHREADED = ${Boost_USE_MULTITHREADED}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_LIBS = ${Boost_USE_STATIC_LIBS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_USE_STATIC_RUNTIME = ${Boost_USE_STATIC_RUNTIME}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_ADDITIONAL_VERSIONS = ${Boost_ADDITIONAL_VERSIONS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NO_SYSTEM_PATHS = ${Boost_NO_SYSTEM_PATHS}") -endif() - -# Supply Boost_LIB_DIAGNOSTIC_DEFINITIONS as a convenience target. It -# will only contain any interface definitions on WIN32, but is created -# on all platforms to keep end user code free from platform dependent -# code. Also provide convenience targets to disable autolinking and -# enable dynamic linking. -if(NOT TARGET Boost::diagnostic_definitions) - add_library(Boost::diagnostic_definitions INTERFACE IMPORTED) - add_library(Boost::disable_autolinking INTERFACE IMPORTED) - add_library(Boost::dynamic_linking INTERFACE IMPORTED) - set_target_properties(Boost::dynamic_linking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_DYN_LINK") -endif() -if(WIN32) - # In windows, automatic linking is performed, so you do not have - # to specify the libraries. If you are linking to a dynamic - # runtime, then you can choose to link to either a static or a - # dynamic Boost library, the default is to do a static link. You - # can alter this for a specific library "whatever" by defining - # BOOST_WHATEVER_DYN_LINK to force Boost library "whatever" to be - # linked dynamically. Alternatively you can force all Boost - # libraries to dynamic link by defining BOOST_ALL_DYN_LINK. - - # This feature can be disabled for Boost library "whatever" by - # defining BOOST_WHATEVER_NO_LIB, or for all of Boost by defining - # BOOST_ALL_NO_LIB. - - # If you want to observe which libraries are being linked against - # then defining BOOST_LIB_DIAGNOSTIC will cause the auto-linking - # code to emit a #pragma message each time a library is selected - # for linking. - set(Boost_LIB_DIAGNOSTIC_DEFINITIONS "-DBOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::diagnostic_definitions PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_LIB_DIAGNOSTIC") - set_target_properties(Boost::disable_autolinking PROPERTIES - INTERFACE_COMPILE_DEFINITIONS "BOOST_ALL_NO_LIB") -endif() - -_Boost_CHECK_SPELLING(Boost_ROOT) -_Boost_CHECK_SPELLING(Boost_LIBRARYDIR) -_Boost_CHECK_SPELLING(Boost_INCLUDEDIR) - -# Collect environment variable inputs as hints. Do not consider changes. -foreach(v BOOSTROOT BOOST_ROOT BOOST_INCLUDEDIR BOOST_LIBRARYDIR) - set(_env $ENV{${v}}) - if(_env) - file(TO_CMAKE_PATH "${_env}" _ENV_${v}) - else() - set(_ENV_${v} "") - endif() -endforeach() -if(NOT _ENV_BOOST_ROOT AND _ENV_BOOSTROOT) - set(_ENV_BOOST_ROOT "${_ENV_BOOSTROOT}") -endif() - -# Collect inputs and cached results. Detect changes since the last run. -if(NOT BOOST_ROOT AND BOOSTROOT) - set(BOOST_ROOT "${BOOSTROOT}") -endif() -set(_Boost_VARS_DIR - BOOST_ROOT - Boost_NO_SYSTEM_PATHS - ) - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Declared as CMake or Environmental Variables:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_ROOT = ${BOOST_ROOT}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_INCLUDEDIR = ${BOOST_INCLUDEDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " BOOST_LIBRARYDIR = ${BOOST_LIBRARYDIR}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_TEST_VERSIONS = ${_boost_TEST_VERSIONS}") -endif() - -# ------------------------------------------------------------------------ -# Search for Boost include DIR -# ------------------------------------------------------------------------ - -set(_Boost_VARS_INC BOOST_INCLUDEDIR Boost_INCLUDE_DIR Boost_ADDITIONAL_VERSIONS) -_Boost_CHANGE_DETECT(_Boost_CHANGE_INCDIR ${_Boost_VARS_DIR} ${_Boost_VARS_INC}) -# Clear Boost_INCLUDE_DIR if it did not change but other input affecting the -# location did. We will find a new one based on the new inputs. -if(_Boost_CHANGE_INCDIR AND NOT _Boost_INCLUDE_DIR_CHANGED) - unset(Boost_INCLUDE_DIR CACHE) -endif() - -if(NOT Boost_INCLUDE_DIR) - set(_boost_INCLUDE_SEARCH_DIRS "") - if(BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_INCLUDEDIR}) - elseif(_ENV_BOOST_INCLUDEDIR) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_INCLUDEDIR}) - endif() - - if( BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${BOOST_ROOT}/include ${BOOST_ROOT}) - elseif( _ENV_BOOST_ROOT ) - list(APPEND _boost_INCLUDE_SEARCH_DIRS ${_ENV_BOOST_ROOT}/include ${_ENV_BOOST_ROOT}) - endif() - - if( Boost_NO_SYSTEM_PATHS) - list(APPEND _boost_INCLUDE_SEARCH_DIRS NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC") - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS "C:/local/boost_${ver}") - endforeach() - endif() - list(APPEND _boost_INCLUDE_SEARCH_DIRS PATHS - C:/boost/include - C:/boost - /sw/local/include - ) - endif() - - # Try to find Boost by stepping backwards through the Boost versions - # we know about. - # Build a list of path suffixes for each version. - set(_boost_PATH_SUFFIXES) - foreach(_boost_VER ${_boost_TEST_VERSIONS}) - # Add in a path suffix, based on the required version, ideally - # we could read this from version.hpp, but for that to work we'd - # need to know the include dir already - set(_boost_BOOSTIFIED_VERSION) - - # Transform 1.35 => 1_35 and 1.36.0 => 1_36_0 - if(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}_${CMAKE_MATCH_3}") - elseif(_boost_VER MATCHES "([0-9]+)\\.([0-9]+)") - set(_boost_BOOSTIFIED_VERSION - "${CMAKE_MATCH_1}_${CMAKE_MATCH_2}") - endif() - - list(APPEND _boost_PATH_SUFFIXES - "boost-${_boost_BOOSTIFIED_VERSION}" - "boost_${_boost_BOOSTIFIED_VERSION}" - "boost/boost-${_boost_BOOSTIFIED_VERSION}" - "boost/boost_${_boost_BOOSTIFIED_VERSION}" - ) - - endforeach() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Include debugging info:") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_INCLUDE_SEARCH_DIRS = ${_boost_INCLUDE_SEARCH_DIRS}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - " _boost_PATH_SUFFIXES = ${_boost_PATH_SUFFIXES}") - endif() - - # Look for a standard boost header file. - find_path(Boost_INCLUDE_DIR - NAMES boost/config.hpp - HINTS ${_boost_INCLUDE_SEARCH_DIRS} - PATH_SUFFIXES ${_boost_PATH_SUFFIXES} - ) -endif() - -# ------------------------------------------------------------------------ -# Extract version information from version.hpp -# ------------------------------------------------------------------------ - -# Set Boost_FOUND based only on header location and version. -# It will be updated below for component libraries. -if(Boost_INCLUDE_DIR) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "location of version.hpp: ${Boost_INCLUDE_DIR}/boost/version.hpp") - endif() - - # Extract Boost_VERSION and Boost_LIB_VERSION from version.hpp - set(Boost_VERSION 0) - set(Boost_LIB_VERSION "") - file(STRINGS "${Boost_INCLUDE_DIR}/boost/version.hpp" _boost_VERSION_HPP_CONTENTS REGEX "#define BOOST_(LIB_)?VERSION ") - set(_Boost_VERSION_REGEX "([0-9]+)") - set(_Boost_LIB_VERSION_REGEX "\"([0-9_]+)\"") - foreach(v VERSION LIB_VERSION) - if("${_boost_VERSION_HPP_CONTENTS}" MATCHES "#define BOOST_${v} ${_Boost_${v}_REGEX}") - set(Boost_${v} "${CMAKE_MATCH_1}") - endif() - endforeach() - unset(_boost_VERSION_HPP_CONTENTS) - - math(EXPR Boost_MAJOR_VERSION "${Boost_VERSION} / 100000") - math(EXPR Boost_MINOR_VERSION "${Boost_VERSION} / 100 % 1000") - math(EXPR Boost_SUBMINOR_VERSION "${Boost_VERSION} % 100") - set(Boost_VERSION_STRING "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - - string(APPEND Boost_ERROR_REASON - "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}\nBoost include path: ${Boost_INCLUDE_DIR}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "version.hpp reveals boost " - "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - endif() - - if(Boost_FIND_VERSION) - # Set Boost_FOUND based on requested version. - set(_Boost_VERSION "${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if("${_Boost_VERSION}" VERSION_LESS "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "old") - elseif(Boost_FIND_VERSION_EXACT AND - NOT "${_Boost_VERSION}" VERSION_EQUAL "${Boost_FIND_VERSION}") - set(Boost_FOUND 0) - set(_Boost_VERSION_AGE "new") - else() - set(Boost_FOUND 1) - endif() - if(NOT Boost_FOUND) - # State that we found a version of Boost that is too new or too old. - string(APPEND Boost_ERROR_REASON - "\nDetected version of Boost is too ${_Boost_VERSION_AGE}. Requested version was ${Boost_FIND_VERSION_MAJOR}.${Boost_FIND_VERSION_MINOR}") - if (Boost_FIND_VERSION_PATCH) - string(APPEND Boost_ERROR_REASON - ".${Boost_FIND_VERSION_PATCH}") - endif () - if (NOT Boost_FIND_VERSION_EXACT) - string(APPEND Boost_ERROR_REASON " (or newer)") - endif () - string(APPEND Boost_ERROR_REASON ".") - endif () - else() - # Caller will accept any Boost version. - set(Boost_FOUND 1) - endif() -else() - set(Boost_FOUND 0) - string(APPEND Boost_ERROR_REASON - "Unable to find the Boost header files. Please set BOOST_ROOT to the root directory containing Boost or BOOST_INCLUDEDIR to the directory containing Boost's headers.") -endif() - -# ------------------------------------------------------------------------ -# Prefix initialization -# ------------------------------------------------------------------------ - -set(Boost_LIB_PREFIX "") -if ( (GHSMULTI AND Boost_USE_STATIC_LIBS) OR - (WIN32 AND Boost_USE_STATIC_LIBS AND NOT CYGWIN) ) - set(Boost_LIB_PREFIX "lib") -endif() - -if ( NOT Boost_NAMESPACE ) - set(Boost_NAMESPACE "boost") -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_LIB_PREFIX = ${Boost_LIB_PREFIX}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Boost_NAMESPACE = ${Boost_NAMESPACE}") -endif() - -# ------------------------------------------------------------------------ -# Suffix initialization and compiler suffix detection. -# ------------------------------------------------------------------------ - -set(_Boost_VARS_NAME - Boost_NAMESPACE - Boost_COMPILER - Boost_THREADAPI - Boost_USE_DEBUG_PYTHON - Boost_USE_MULTITHREADED - Boost_USE_STATIC_LIBS - Boost_USE_STATIC_RUNTIME - Boost_USE_STLPORT - Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS - ) -_Boost_CHANGE_DETECT(_Boost_CHANGE_LIBNAME ${_Boost_VARS_NAME}) - -# Setting some more suffixes for the library -if (Boost_COMPILER) - set(_boost_COMPILER ${Boost_COMPILER}) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_COMPILER = ${_boost_COMPILER}") - endif() -else() - # Attempt to guess the compiler suffix - # NOTE: this is not perfect yet, if you experience any issues - # please report them and use the Boost_COMPILER variable - # to work around the problems. - _Boost_GUESS_COMPILER_PREFIX(_boost_COMPILER) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "guessed _boost_COMPILER = ${_boost_COMPILER}") - endif() -endif() - -set (_boost_MULTITHREADED "-mt") -if( NOT Boost_USE_MULTITHREADED ) - set (_boost_MULTITHREADED "") -endif() -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_MULTITHREADED = ${_boost_MULTITHREADED}") -endif() - -#====================== -# Systematically build up the Boost ABI tag for the 'tagged' and 'versioned' layouts -# http://boost.org/doc/libs/1_66_0/more/getting_started/windows.html#library-naming -# http://boost.org/doc/libs/1_66_0/boost/config/auto_link.hpp -# http://boost.org/doc/libs/1_66_0/tools/build/src/tools/common.jam -# http://boost.org/doc/libs/1_66_0/boostcpp.jam -set( _boost_RELEASE_ABI_TAG "-") -set( _boost_DEBUG_ABI_TAG "-") -# Key Use this library when: -# s linking statically to the C++ standard library and -# compiler runtime support libraries. -if(Boost_USE_STATIC_RUNTIME) - set( _boost_RELEASE_ABI_TAG "${_boost_RELEASE_ABI_TAG}s") - set( _boost_DEBUG_ABI_TAG "${_boost_DEBUG_ABI_TAG}s") -endif() -# g using debug versions of the standard and runtime -# support libraries -if(WIN32 AND Boost_USE_DEBUG_RUNTIME) - if("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xClang" - OR "x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xIntel") - string(APPEND _boost_DEBUG_ABI_TAG "g") - endif() -endif() -# y using special debug build of python -if(Boost_USE_DEBUG_PYTHON) - string(APPEND _boost_DEBUG_ABI_TAG "y") -endif() -# d using a debug version of your code -string(APPEND _boost_DEBUG_ABI_TAG "d") -# p using the STLport standard library rather than the -# default one supplied with your compiler -if(Boost_USE_STLPORT) - string(APPEND _boost_RELEASE_ABI_TAG "p") - string(APPEND _boost_DEBUG_ABI_TAG "p") -endif() -# n using the STLport deprecated "native iostreams" feature -# removed from the documentation in 1.43.0 but still present in -# boost/config/auto_link.hpp -if(Boost_USE_STLPORT_DEPRECATED_NATIVE_IOSTREAMS) - string(APPEND _boost_RELEASE_ABI_TAG "n") - string(APPEND _boost_DEBUG_ABI_TAG "n") -endif() - -# -x86 Architecture and address model tag -# First character is the architecture, then word-size, either 32 or 64 -# Only used in 'versioned' layout, added in Boost 1.66.0 -if(DEFINED Boost_ARCHITECTURE) - set(_boost_ARCHITECTURE_TAG "${Boost_ARCHITECTURE}") - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "using user-specified Boost_ARCHITECTURE = ${_boost_ARCHITECTURE_TAG}") - endif() -else() - set(_boost_ARCHITECTURE_TAG "") - # {CMAKE_CXX_COMPILER_ARCHITECTURE_ID} is not currently set for all compilers - if(NOT "x${CMAKE_CXX_COMPILER_ARCHITECTURE_ID}" STREQUAL "x" AND NOT Boost_VERSION VERSION_LESS 106600) - string(APPEND _boost_ARCHITECTURE_TAG "-") - # This needs to be kept in-sync with the section of CMakePlatformId.h.in - # inside 'defined(_WIN32) && defined(_MSC_VER)' - if(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "IA64") - string(APPEND _boost_ARCHITECTURE_TAG "i") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "X86" - OR CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "x64") - string(APPEND _boost_ARCHITECTURE_TAG "x") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID MATCHES "^ARM") - string(APPEND _boost_ARCHITECTURE_TAG "a") - elseif(CMAKE_CXX_COMPILER_ARCHITECTURE_ID STREQUAL "MIPS") - string(APPEND _boost_ARCHITECTURE_TAG "m") - endif() - - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - string(APPEND _boost_ARCHITECTURE_TAG "64") - else() - string(APPEND _boost_ARCHITECTURE_TAG "32") - endif() - endif() -endif() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_RELEASE_ABI_TAG = ${_boost_RELEASE_ABI_TAG}") - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_DEBUG_ABI_TAG = ${_boost_DEBUG_ABI_TAG}") -endif() - -# ------------------------------------------------------------------------ -# Begin finding boost libraries -# ------------------------------------------------------------------------ - -set(_Boost_VARS_LIB "") -foreach(c DEBUG RELEASE) - set(_Boost_VARS_LIB_${c} BOOST_LIBRARYDIR Boost_LIBRARY_DIR_${c}) - list(APPEND _Boost_VARS_LIB ${_Boost_VARS_LIB_${c}}) - _Boost_CHANGE_DETECT(_Boost_CHANGE_LIBDIR_${c} ${_Boost_VARS_DIR} ${_Boost_VARS_LIB_${c}} Boost_INCLUDE_DIR) - # Clear Boost_LIBRARY_DIR_${c} if it did not change but other input affecting the - # location did. We will find a new one based on the new inputs. - if(_Boost_CHANGE_LIBDIR_${c} AND NOT _Boost_LIBRARY_DIR_${c}_CHANGED) - unset(Boost_LIBRARY_DIR_${c} CACHE) - endif() - - # If Boost_LIBRARY_DIR_[RELEASE,DEBUG] is set, prefer its value. - if(Boost_LIBRARY_DIR_${c}) - set(_boost_LIBRARY_SEARCH_DIRS_${c} ${Boost_LIBRARY_DIR_${c}} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH) - else() - set(_boost_LIBRARY_SEARCH_DIRS_${c} "") - if(BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_LIBRARYDIR}) - elseif(_ENV_BOOST_LIBRARYDIR) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_LIBRARYDIR}) - endif() - - if(BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${BOOST_ROOT}/lib ${BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${BOOST_ROOT}") - elseif(_ENV_BOOST_ROOT) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} ${_ENV_BOOST_ROOT}/lib ${_ENV_BOOST_ROOT}/stage/lib) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${_ENV_BOOST_ROOT}") - endif() - - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} - ${Boost_INCLUDE_DIR}/lib - ${Boost_INCLUDE_DIR}/../lib - ${Boost_INCLUDE_DIR}/stage/lib - ) - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}/..") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "${Boost_INCLUDE_DIR}") - if( Boost_NO_SYSTEM_PATHS ) - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} NO_CMAKE_SYSTEM_PATH NO_SYSTEM_ENVIRONMENT_PATH) - else() - foreach(ver ${_boost_TEST_VERSIONS}) - string(REPLACE "." "_" ver "${ver}") - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/local/boost_${ver}") - endforeach() - _Boost_UPDATE_WINDOWS_LIBRARY_SEARCH_DIRS_WITH_PREBUILT_PATHS(_boost_LIBRARY_SEARCH_DIRS_${c} "C:/boost") - list(APPEND _boost_LIBRARY_SEARCH_DIRS_${c} PATHS - C:/boost/lib - C:/boost - /sw/local/lib - ) - endif() - endif() -endforeach() - -if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "_boost_LIBRARY_SEARCH_DIRS_RELEASE = ${_boost_LIBRARY_SEARCH_DIRS_RELEASE}" - "_boost_LIBRARY_SEARCH_DIRS_DEBUG = ${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") -endif() - -# Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES -if( Boost_USE_STATIC_LIBS ) - set( _boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES}) - if(WIN32) - list(INSERT CMAKE_FIND_LIBRARY_SUFFIXES 0 .lib .a) - else() - set(CMAKE_FIND_LIBRARY_SUFFIXES .a) - endif() -endif() - -# We want to use the tag inline below without risking double dashes -if(_boost_RELEASE_ABI_TAG) - if(${_boost_RELEASE_ABI_TAG} STREQUAL "-") - set(_boost_RELEASE_ABI_TAG "") - endif() -endif() -if(_boost_DEBUG_ABI_TAG) - if(${_boost_DEBUG_ABI_TAG} STREQUAL "-") - set(_boost_DEBUG_ABI_TAG "") - endif() -endif() - -# The previous behavior of FindBoost when Boost_USE_STATIC_LIBS was enabled -# on WIN32 was to: -# 1. Search for static libs compiled against a SHARED C++ standard runtime library (use if found) -# 2. Search for static libs compiled against a STATIC C++ standard runtime library (use if found) -# We maintain this behavior since changing it could break people's builds. -# To disable the ambiguous behavior, the user need only -# set Boost_USE_STATIC_RUNTIME either ON or OFF. -set(_boost_STATIC_RUNTIME_WORKAROUND false) -if(WIN32 AND Boost_USE_STATIC_LIBS) - if(NOT DEFINED Boost_USE_STATIC_RUNTIME) - set(_boost_STATIC_RUNTIME_WORKAROUND TRUE) - endif() -endif() - -# On versions < 1.35, remove the System library from the considered list -# since it wasn't added until 1.35. -if(Boost_VERSION AND Boost_FIND_COMPONENTS) - if(Boost_VERSION LESS 103500) - list(REMOVE_ITEM Boost_FIND_COMPONENTS system) - endif() -endif() - -# Additional components may be required via component dependencies. -# Add any missing components to the list. -_Boost_MISSING_DEPENDENCIES(Boost_FIND_COMPONENTS _Boost_EXTRA_FIND_COMPONENTS) - -# If thread is required, get the thread libs as a dependency -if("thread" IN_LIST Boost_FIND_COMPONENTS) - if(Boost_FIND_QUIETLY) - set(_Boost_find_quiet QUIET) - else() - set(_Boost_find_quiet "") - endif() - find_package(Threads ${_Boost_find_quiet}) - unset(_Boost_find_quiet) -endif() - -# If the user changed any of our control inputs flush previous results. -if(_Boost_CHANGE_LIBDIR_DEBUG OR _Boost_CHANGE_LIBDIR_RELEASE OR _Boost_CHANGE_LIBNAME) - foreach(COMPONENT ${_Boost_COMPONENTS_SEARCHED}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - foreach(c DEBUG RELEASE) - set(_var Boost_${UPPERCOMPONENT}_LIBRARY_${c}) - unset(${_var} CACHE) - set(${_var} "${_var}-NOTFOUND") - endforeach() - endforeach() - set(_Boost_COMPONENTS_SEARCHED "") -endif() - -foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - - set( _boost_docstring_release "Boost ${COMPONENT} library (release)") - set( _boost_docstring_debug "Boost ${COMPONENT} library (debug)") - - # Compute component-specific hints. - set(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT "") - if(${COMPONENT} STREQUAL "mpi" OR ${COMPONENT} STREQUAL "mpi_python" OR - ${COMPONENT} STREQUAL "graph_parallel") - foreach(lib ${MPI_CXX_LIBRARIES} ${MPI_C_LIBRARIES}) - if(IS_ABSOLUTE "${lib}") - get_filename_component(libdir "${lib}" PATH) - string(REPLACE "\\" "/" libdir "${libdir}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT ${libdir}) - endif() - endforeach() - endif() - - # Handle Python version suffixes - unset(COMPONENT_PYTHON_VERSION_MAJOR) - unset(COMPONENT_PYTHON_VERSION_MINOR) - if(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - elseif(${COMPONENT} MATCHES "^(python|mpi_python|numpy)([0-9])\\.?([0-9])\$") - set(COMPONENT_UNVERSIONED "${CMAKE_MATCH_1}") - set(COMPONENT_PYTHON_VERSION_MAJOR "${CMAKE_MATCH_2}") - set(COMPONENT_PYTHON_VERSION_MINOR "${CMAKE_MATCH_3}") - endif() - - unset(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if (COMPONENT_PYTHON_VERSION_MINOR) - # Boost >= 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Debian/Ubuntu (Some versions omit the 2 and/or 3 from the suffix) - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-py${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # Gentoo - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - # RPMs - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}-${COMPONENT_PYTHON_VERSION_MAJOR}${COMPONENT_PYTHON_VERSION_MINOR}") - endif() - if (COMPONENT_PYTHON_VERSION_MAJOR AND NOT COMPONENT_PYTHON_VERSION_MINOR) - # Boost < 1.67 - list(APPEND _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME "${COMPONENT_UNVERSIONED}${COMPONENT_PYTHON_VERSION_MAJOR}") - endif() - - # Consolidate and report component-specific hints. - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search names for ${COMPONENT_NAME}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME}") - endif() - endif() - if(_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - list(REMOVE_DUPLICATES _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT) - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Component-specific library search paths for ${COMPONENT}: " - "${_Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT}") - endif() - endif() - - # - # Find headers - # - _Boost_COMPONENT_HEADERS("${COMPONENT}" Boost_${UPPERCOMPONENT}_HEADER_NAME) - # Look for a standard boost header file. - if(Boost_${UPPERCOMPONENT}_HEADER_NAME) - if(EXISTS "${Boost_INCLUDE_DIR}/${Boost_${UPPERCOMPONENT}_HEADER_NAME}") - set(Boost_${UPPERCOMPONENT}_HEADER ON) - else() - set(Boost_${UPPERCOMPONENT}_HEADER OFF) - endif() - else() - set(Boost_${UPPERCOMPONENT}_HEADER ON) - message(WARNING "No header defined for ${COMPONENT}; skipping header check") - endif() - - # - # Find RELEASE libraries - # - unset(_boost_RELEASE_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_RELEASE_STATIC_ABI_TAG "-s${_boost_RELEASE_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_RELEASE_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_RELEASE_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_RELEASE_NAMES ${_boost_RELEASE_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_RELEASE: ${_boost_RELEASE_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_RELEASE is not defined, - # but Boost_LIBRARY_DIR_DEBUG is, look there first for RELEASE libs - if(NOT Boost_LIBRARY_DIR_RELEASE AND Boost_LIBRARY_DIR_DEBUG) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_RELEASE 0 ${Boost_LIBRARY_DIR_DEBUG}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_RELEASE}") - - if(Boost_USE_RELEASE_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE RELEASE - NAMES ${_boost_RELEASE_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_release}" - ) - endif() - - # - # Find DEBUG libraries - # - unset(_boost_DEBUG_NAMES) - foreach(component IN LISTS _Boost_FIND_LIBRARY_HINTS_FOR_COMPONENT_NAME COMPONENT) - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_ABI_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component} ) - if(_boost_STATIC_RUNTIME_WORKAROUND) - set(_boost_DEBUG_STATIC_ABI_TAG "-s${_boost_DEBUG_ABI_TAG}") - foreach(compiler IN LISTS _boost_COMPILER) - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${compiler}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endforeach() - list(APPEND _boost_DEBUG_NAMES - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG}-${Boost_LIB_VERSION} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG}${_boost_ARCHITECTURE_TAG} - ${Boost_LIB_PREFIX}${Boost_NAMESPACE}_${component}${_boost_MULTITHREADED}${_boost_DEBUG_STATIC_ABI_TAG} ) - endif() - endforeach() - if(Boost_THREADAPI AND ${COMPONENT} STREQUAL "thread") - _Boost_PREPEND_LIST_WITH_THREADAPI(_boost_DEBUG_NAMES ${_boost_DEBUG_NAMES}) - endif() - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " - "Searching for ${UPPERCOMPONENT}_LIBRARY_DEBUG: ${_boost_DEBUG_NAMES}") - endif() - - # if Boost_LIBRARY_DIR_DEBUG is not defined, - # but Boost_LIBRARY_DIR_RELEASE is, look there first for DEBUG libs - if(NOT Boost_LIBRARY_DIR_DEBUG AND Boost_LIBRARY_DIR_RELEASE) - list(INSERT _boost_LIBRARY_SEARCH_DIRS_DEBUG 0 ${Boost_LIBRARY_DIR_RELEASE}) - endif() - - # Avoid passing backslashes to _Boost_FIND_LIBRARY due to macro re-parsing. - string(REPLACE "\\" "/" _boost_LIBRARY_SEARCH_DIRS_tmp "${_boost_LIBRARY_SEARCH_DIRS_DEBUG}") - - if(Boost_USE_DEBUG_LIBS) - _Boost_FIND_LIBRARY(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG DEBUG - NAMES ${_boost_DEBUG_NAMES} - HINTS ${_boost_LIBRARY_SEARCH_DIRS_tmp} - NAMES_PER_DIR - DOC "${_boost_docstring_debug}" - ) - endif () - - if(Boost_REALPATH) - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE "${_boost_docstring_release}") - _Boost_SWAP_WITH_REALPATH(Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG "${_boost_docstring_debug}" ) - endif() - - _Boost_ADJUST_LIB_VARS(${UPPERCOMPONENT}) - - # Check if component requires some compiler features - _Boost_COMPILER_FEATURES(${COMPONENT} _Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - -endforeach() - -# Restore the original find library ordering -if( Boost_USE_STATIC_LIBS ) - set(CMAKE_FIND_LIBRARY_SUFFIXES ${_boost_ORIG_CMAKE_FIND_LIBRARY_SUFFIXES}) -endif() - -# ------------------------------------------------------------------------ -# End finding boost libraries -# ------------------------------------------------------------------------ - -set(Boost_INCLUDE_DIRS ${Boost_INCLUDE_DIR}) -set(Boost_LIBRARY_DIRS) -if(Boost_LIBRARY_DIR_RELEASE) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_RELEASE}) -endif() -if(Boost_LIBRARY_DIR_DEBUG) - list(APPEND Boost_LIBRARY_DIRS ${Boost_LIBRARY_DIR_DEBUG}) -endif() -if(Boost_LIBRARY_DIRS) - list(REMOVE_DUPLICATES Boost_LIBRARY_DIRS) -endif() - -# The above setting of Boost_FOUND was based only on the header files. -# Update it for the requested component libraries. -if(Boost_FOUND) - # The headers were found. Check for requested component libs. - set(_boost_CHECKED_COMPONENT FALSE) - set(_Boost_MISSING_COMPONENTS "") - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(_boost_CHECKED_COMPONENT TRUE) - if(NOT Boost_${UPPERCOMPONENT}_FOUND AND Boost_FIND_REQUIRED_${COMPONENT}) - list(APPEND _Boost_MISSING_COMPONENTS ${COMPONENT}) - endif() - endforeach() - if(_Boost_MISSING_COMPONENTS AND _Boost_EXTRA_FIND_COMPONENTS) - # Optional indirect dependencies are not counted as missing. - list(REMOVE_ITEM _Boost_MISSING_COMPONENTS ${_Boost_EXTRA_FIND_COMPONENTS}) - endif() - - if(Boost_DEBUG) - message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] Boost_FOUND = ${Boost_FOUND}") - endif() - - if (_Boost_MISSING_COMPONENTS) - set(Boost_FOUND 0) - # We were unable to find some libraries, so generate a sensible - # error message that lists the libraries we were unable to find. - string(APPEND Boost_ERROR_REASON - "\nCould not find the following") - if(Boost_USE_STATIC_LIBS) - string(APPEND Boost_ERROR_REASON " static") - endif() - string(APPEND Boost_ERROR_REASON - " Boost libraries:\n") - foreach(COMPONENT ${_Boost_MISSING_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - string(APPEND Boost_ERROR_REASON - " ${Boost_NAMESPACE}_${COMPONENT}${Boost_ERROR_REASON_${UPPERCOMPONENT}}\n") - endforeach() - - list(LENGTH Boost_FIND_COMPONENTS Boost_NUM_COMPONENTS_WANTED) - list(LENGTH _Boost_MISSING_COMPONENTS Boost_NUM_MISSING_COMPONENTS) - if (${Boost_NUM_COMPONENTS_WANTED} EQUAL ${Boost_NUM_MISSING_COMPONENTS}) - string(APPEND Boost_ERROR_REASON - "No Boost libraries were found. You may need to set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - else () - string(APPEND Boost_ERROR_REASON - "Some (but not all) of the required Boost libraries were found. You may need to install these additional Boost libraries. Alternatively, set BOOST_LIBRARYDIR to the directory containing Boost libraries or BOOST_ROOT to the location of Boost.") - endif () - endif () - - if( NOT Boost_LIBRARY_DIRS AND NOT _boost_CHECKED_COMPONENT ) - # Compatibility Code for backwards compatibility with CMake - # 2.4's FindBoost module. - - # Look for the boost library path. - # Note that the user may not have installed any libraries - # so it is quite possible the Boost_LIBRARY_DIRS may not exist. - set(_boost_LIB_DIR ${Boost_INCLUDE_DIR}) - - if("${_boost_LIB_DIR}" MATCHES "boost-[0-9]+") - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if("${_boost_LIB_DIR}" MATCHES "/include$") - # Strip off the trailing "/include" in the path. - get_filename_component(_boost_LIB_DIR ${_boost_LIB_DIR} PATH) - endif() - - if(EXISTS "${_boost_LIB_DIR}/lib") - string(APPEND _boost_LIB_DIR /lib) - elseif(EXISTS "${_boost_LIB_DIR}/stage/lib") - string(APPEND _boost_LIB_DIR "/stage/lib") - else() - set(_boost_LIB_DIR "") - endif() - - if(_boost_LIB_DIR AND EXISTS "${_boost_LIB_DIR}") - set(Boost_LIBRARY_DIRS ${_boost_LIB_DIR}) - endif() - - endif() -else() - # Boost headers were not found so no components were found. - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - set(Boost_${UPPERCOMPONENT}_FOUND 0) - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Add imported targets -# ------------------------------------------------------------------------ - -if(Boost_FOUND) - # For header-only libraries - if(NOT TARGET Boost::boost) - add_library(Boost::boost INTERFACE IMPORTED) - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::boost PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - endif() - - foreach(COMPONENT ${Boost_FIND_COMPONENTS}) - if(_Boost_IMPORTED_TARGETS AND NOT TARGET Boost::${COMPONENT}) - string(TOUPPER ${COMPONENT} UPPERCOMPONENT) - if(Boost_${UPPERCOMPONENT}_FOUND) - if(Boost_USE_STATIC_LIBS) - add_library(Boost::${COMPONENT} STATIC IMPORTED) - else() - # Even if Boost_USE_STATIC_LIBS is OFF, we might have static - # libraries as a result. - add_library(Boost::${COMPONENT} UNKNOWN IMPORTED) - endif() - if(Boost_INCLUDE_DIRS) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${Boost_INCLUDE_DIRS}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY}") - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES "CXX" - IMPORTED_LOCATION "${Boost_${UPPERCOMPONENT}_LIBRARY}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS RELEASE) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "CXX" - IMPORTED_LOCATION_RELEASE "${Boost_${UPPERCOMPONENT}_LIBRARY_RELEASE}") - endif() - if(EXISTS "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - set_property(TARGET Boost::${COMPONENT} APPEND PROPERTY - IMPORTED_CONFIGURATIONS DEBUG) - set_target_properties(Boost::${COMPONENT} PROPERTIES - IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "CXX" - IMPORTED_LOCATION_DEBUG "${Boost_${UPPERCOMPONENT}_LIBRARY_DEBUG}") - endif() - if(_Boost_${UPPERCOMPONENT}_DEPENDENCIES) - unset(_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES) - foreach(dep ${_Boost_${UPPERCOMPONENT}_DEPENDENCIES}) - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Boost::${dep}) - endforeach() - if(COMPONENT STREQUAL "thread") - list(APPEND _Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES Threads::Threads) - endif() - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_LINK_LIBRARIES "${_Boost_${UPPERCOMPONENT}_TARGET_DEPENDENCIES}") - endif() - if(_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES) - set_target_properties(Boost::${COMPONENT} PROPERTIES - INTERFACE_COMPILE_FEATURES "${_Boost_${UPPERCOMPONENT}_COMPILER_FEATURES}") - endif() - endif() - endif() - endforeach() -endif() - -# ------------------------------------------------------------------------ -# Notification to end user about what was found -# ------------------------------------------------------------------------ - -set(Boost_LIBRARIES "") -if(Boost_FOUND) - if(NOT Boost_FIND_QUIETLY) - message(STATUS "Boost version: ${Boost_MAJOR_VERSION}.${Boost_MINOR_VERSION}.${Boost_SUBMINOR_VERSION}") - if(Boost_FIND_COMPONENTS) - message(STATUS "Found the following Boost libraries:") - endif() - endif() - foreach( COMPONENT ${Boost_FIND_COMPONENTS} ) - string( TOUPPER ${COMPONENT} UPPERCOMPONENT ) - if( Boost_${UPPERCOMPONENT}_FOUND ) - if(NOT Boost_FIND_QUIETLY) - message (STATUS " ${COMPONENT}") - endif() - list(APPEND Boost_LIBRARIES ${Boost_${UPPERCOMPONENT}_LIBRARY}) - if(COMPONENT STREQUAL "thread") - list(APPEND Boost_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) - endif() - endif() - endforeach() -else() - if(Boost_FIND_REQUIRED) - message(SEND_ERROR "Unable to find the requested Boost libraries.\n${Boost_ERROR_REASON}") - else() - if(NOT Boost_FIND_QUIETLY) - # we opt not to automatically output Boost_ERROR_REASON here as - # it could be quite lengthy and somewhat imposing in its requests - # Since Boost is not always a required dependency we'll leave this - # up to the end-user. - if(Boost_DEBUG OR Boost_DETAILED_FAILURE_MSG) - message(STATUS "Could NOT find Boost\n${Boost_ERROR_REASON}") - else() - message(STATUS "Could NOT find Boost") - endif() - endif() - endif() -endif() - -# Configure display of cache entries in GUI. -foreach(v BOOSTROOT BOOST_ROOT ${_Boost_VARS_INC} ${_Boost_VARS_LIB}) - get_property(_type CACHE ${v} PROPERTY TYPE) - if(_type) - set_property(CACHE ${v} PROPERTY ADVANCED 1) - if("x${_type}" STREQUAL "xUNINITIALIZED") - if("x${v}" STREQUAL "xBoost_ADDITIONAL_VERSIONS") - set_property(CACHE ${v} PROPERTY TYPE STRING) - else() - set_property(CACHE ${v} PROPERTY TYPE PATH) - endif() - endif() - endif() -endforeach() - -# Record last used values of input variables so we can -# detect on the next run if the user changed them. -foreach(v - ${_Boost_VARS_INC} ${_Boost_VARS_LIB} - ${_Boost_VARS_DIR} ${_Boost_VARS_NAME} - ) - if(DEFINED ${v}) - set(_${v}_LAST "${${v}}" CACHE INTERNAL "Last used ${v} value.") - else() - unset(_${v}_LAST CACHE) - endif() -endforeach() - -# Maintain a persistent list of components requested anywhere since -# the last flush. -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}") -list(APPEND _Boost_COMPONENTS_SEARCHED ${Boost_FIND_COMPONENTS}) -list(REMOVE_DUPLICATES _Boost_COMPONENTS_SEARCHED) -list(SORT _Boost_COMPONENTS_SEARCHED) -set(_Boost_COMPONENTS_SEARCHED "${_Boost_COMPONENTS_SEARCHED}" - CACHE INTERNAL "Components requested for this build tree.") - -# Restore project's policies -cmake_policy(POP) diff --git a/doc/setup.dox b/doc/setup.dox index 5368c1e5e..e740b0e04 100644 --- a/doc/setup.dox +++ b/doc/setup.dox @@ -73,8 +73,7 @@ WALBERLA_BUILD_WITH_MPI | ON | Since one main goal of waLBerla WALBERLA_BUILD_WITH_OPENMP | OFF | Enables/Disables OpenMP support for thread-parallel computation. Can also be combined with MPI for hybrid simulations! WALBERLA_BUILD_TESTS | OFF | If enabled, all tests are built when running make in the root build folder. But you can always go to a specific directory in your test folder and manually run make. WALBERLA_BUILD_BENCHMARKS | ON | Enables/Disables the automatic build of all benchmarks located in "apps/benchmarks". -WALBERLA_BUILD_WITH_PYTHON | OFF | Enables Python Support inside waLBerla (embedded Python). Then you can use Python scripts as configuration files and start an embedded python interpreter that can access waLBerla data structures. -WALBERLA_BUILD_WITH_PYTHON_MODULE | OFF | This builds a shared library (and python module) walberla.so in "apps/pythonmodule" so that you can use walberla from python. +WALBERLA_BUILD_WITH_PYTHON | OFF | Enables Python Support inside waLBerla (embedded Python). Then you can use Python scripts as configuration files and start an embedded python interpreter that can access waLBerla data structures. This builds a shared library (and python module) walberla_cpp.so in "apps/pythonmodule" so that you can use walberla from python. For a list of all switches, see CMakeLists.txt in the root source folder. @@ -87,40 +86,13 @@ e.g. geometry setup, post-processing or steering. This mode can be enabled by th While in this first option the driving code is C++, the second option exports most of waLBerlas functionality as a Python module that can be imported from a regular Python script. Thus the application itself can be written in Python. -To build and install the waLBerla Python module enable WALBERLA_BUILD_WITH_PYTHON and WALBERLA_BUILD_WITH_PYTHON_MODULE. +To build and install the waLBerla Python module enable WALBERLA_BUILD_WITH_PYTHON. Then run 'make pythonModule' to build and 'make pythonModuleInstall' to install the module in your current environment. +The python coupling is build up on <a target="_blank" href="https://pybind11.readthedocs.io/en/stable/index.html">pybind11</a> entirely. pybind11 +provides a lightweight header only solution for that. Thus there is no need to install additional software since pybind11 +is shipped with waLBerla as a submodule. The integration happens automatically when waLBerla is build with python. -The third option is code generation using 'pystencils' and 'lbmpy' and is covered later. - -\subsection python_boost Installing Python dependencies. - -Both variants described above introduce dependencies on the Python and the boost::python library. We support building -against Python in version 3.3 and above. On Ubuntu install 'python3-dev' and 'libboost-python-dev'. Then CMake -automatically finds the right libraries. - -On clusters the setup process can be more complicated. Usually boost has to be compiled manually there. One very common -problem then is to not link boost::python against the same python lib as waLBerla is linked against. For example when boost -python is built against Python2 and waLBerla linked against Python3, linker errors occur. You can test what your -boost python was linked against with 'grep -rl "PyString_Type" libbboost_python'. If something is found, it was built -against Python2, if not, against Python3. - -To build boost correctly against a certain Python version do: -\verbatim -./bootstrap.sh --with-python=/path/to/python3 --with-python-root=/base/dir/with/lib/and/include/ --with-python-version=3.Xm -\endverbatim - -To be on the safe side then edit the project-config.jam and adapt the following line (here for example python3.6m) -by entering the location of the interpreter, include path and lib path: -\verbatim -using python : 3.6 : /path/to/python3 : /python/root/include/python3.6m/ : /python/root/lib/ ; -\endverbatim - -Then build with -\verbatim -./b2 -j $NUM_PROCS toolset=$TOOLSET install --prefix=$PREFIX -\endverbatim - -Don't forget to set BOOST_ROOT such that CMake finds your custom boost library. +The third option is code generation using <a target="_blank" href="https://pycodegen.pages.i10git.cs.fau.de/pystencils/">pystencils</a> and <a href="https://pycodegen.pages.i10git.cs.fau.de/lbmpy" target="_blank">lbmpy</a> and is covered in the tutorial section of waLBerla. \section ide_setup Setup of Integrated Development Environments diff --git a/extern/pybind11 b/extern/pybind11 new file mode 160000 index 000000000..526a7733c --- /dev/null +++ b/extern/pybind11 @@ -0,0 +1 @@ +Subproject commit 526a7733c773016f2e552777612027954d0765fd diff --git a/python/pystencils_walberla/boundary.py b/python/pystencils_walberla/boundary.py index 7c7547001..73d429ec5 100644 --- a/python/pystencils_walberla/boundary.py +++ b/python/pystencils_walberla/boundary.py @@ -1,5 +1,3 @@ -from functools import partial - import numpy as np from jinja2 import Environment, PackageLoader, StrictUndefined from pystencils import Field, FieldType diff --git a/python/waLBerla/__init__.py b/python/waLBerla/__init__.py index db838d835..6e1e3ebab 100644 --- a/python/waLBerla/__init__.py +++ b/python/waLBerla/__init__.py @@ -4,14 +4,13 @@ from .callbacks import memberCallback as member_callback # noqa:F401 import sys + try: from .walberla_cpp import * # noqa: F403 - cpp_available = True except ImportError: try: from walberla_cpp import * # noqa: F403 - cpp_available = True except ImportError: cpp_available = False @@ -41,26 +40,14 @@ if cpp_available: sys.modules[__name__ + '.field'] = field # noqa: F405 # extend the C++ module with some python functions from .field_extension import extend as extend_field - extend_field(field) # noqa: F405 + if 'cuda' in globals(): sys.modules[__name__ + '.cuda'] = cuda # noqa: F405 from .cuda_extension import extend as extend_cuda - extend_cuda(cuda) # noqa: F405 - if 'geometry' in globals(): - sys.modules[__name__ + '.geometry'] = geometry # noqa: F405 - if 'lbm' in globals(): - sys.modules[__name__ + '.lbm'] = lbm # noqa: F405 - if 'postprocessing' in globals(): - sys.modules[__name__ + 'postprocessing'] = postprocessing # noqa: F405 if 'mpi' in globals(): sys.modules[__name__ + '.mpi'] = mpi # noqa: F405 - if 'timeloop' in globals(): - sys.modules[__name__ + '.timeloop'] = timeloop # noqa: F405 - from .timeloop_extension import extend as extend_timeloop - - extend_timeloop(timeloop) # noqa: F405 else: class Dummy: pass diff --git a/python/waLBerla/callbacks.py b/python/waLBerla/callbacks.py index 8b24c6e0e..f9153ec5b 100644 --- a/python/waLBerla/callbacks.py +++ b/python/waLBerla/callbacks.py @@ -45,7 +45,6 @@ To register a certain python function as callback it has to be set as attribute """ from __future__ import print_function, absolute_import, division, unicode_literals -import os from functools import partial @@ -54,10 +53,10 @@ from functools import partial class callback: """Decorator class to mark a Python function as waLBerla callback""" - def __init__(self, callbackFunction): - if not type(callbackFunction) is str: + def __init__(self, callback_function): + if not type(callback_function) is str: raise Exception("waLBerla callback: Name of function has to be a string") - self.callbackFunction = callbackFunction + self.callbackFunction = callback_function def __call__(self, f): try: @@ -94,7 +93,6 @@ class ScenarioManager: Activation means to register the _configLoopCallback as 'config' waLBerla callback function which is called when a new scenario is expected. When config is called again the calbacks of the next scenario are activated. - """ def __init__(self): @@ -110,19 +108,19 @@ class ScenarioManager: """Activates this scenario manager instance""" try: import walberla_cpp - boundFunc = self._configLoopCallback - setattr(walberla_cpp.callbacks, "config", boundFunc) + bound_func = self._configLoopCallback + setattr(walberla_cpp.callbacks, "config", bound_func) except ImportError: pass - def restrictScenarios(self, startScenario=0): + def restrictScenarios(self, start_scenario=0): """Simulates not all scenarios registered at this manager, but skips the first startScenario-1 scenarios""" - self._startScenario = startScenario + self._startScenario = start_scenario def _configLoopCallback(self, *args, **kwargs): - def findCallbacks(classType): + def findCallbacks(class_type): res = dict() - for key, value in classType.__dict__.items(): + for key, value in class_type.__dict__.items(): if hasattr(value, "waLBerla_callback_member"): res[key] = value return res @@ -145,24 +143,14 @@ class ScenarioManager: try: import walberla_cpp - if 'WALBERLA_SCENARIO_IDX' in os.environ: - scenario_idx = int(os.environ['WALBERLA_SCENARIO_IDX']) - try: - scenario = self._scenarios[scenario_idx] - except IndexError: - walberla_cpp.log_info_on_root("Scenario does not exists - all scenarios simulated?") - exit(1) - walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (scenario_idx, len(self._scenarios))) - yield get_config_from_scenario(scenario) - else: - for idx, scenario in enumerate(self._scenarios): - if idx < self._startScenario: - continue # Skip over all scenarios with id < startScenario - cfg = None - while cfg is None: - cfg = get_config_from_scenario(scenario) - walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx, len(self._scenarios))) - yield cfg + for idx, scenario in enumerate(self._scenarios): + if idx < self._startScenario: + continue # Skip over all scenarios with id < startScenario + cfg = None + while cfg is None: + cfg = get_config_from_scenario(scenario) + # walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios))) + yield cfg except ImportError: pass diff --git a/python/waLBerla/core_extension.py b/python/waLBerla/core_extension.py index f06fefa68..be80be130 100644 --- a/python/waLBerla/core_extension.py +++ b/python/waLBerla/core_extension.py @@ -12,7 +12,7 @@ class SliceMaker(object): makeSlice = SliceMaker() -def normalizeSlice(slices, sizes): +def normalize_slice(slices, sizes): """Converts slices with floating point entries to integer slices""" assert (len(slices) == len(sizes)) @@ -29,52 +29,52 @@ def normalizeSlice(slices, sizes): assert (type(s) is slice) if s.start is None: - newStart = 0 + new_start = 0 elif type(s.start) is float: - newStart = int(s.start * size) + new_start = int(s.start * size) else: - newStart = s.start + new_start = s.start if s.stop is None: - newStop = size + new_stop = size elif type(s.stop) is float: - newStop = int(s.stop * size) + new_stop = int(s.stop * size) else: - newStop = s.stop + new_stop = s.stop - result.append(slice(newStart, newStop, s.step)) + result.append(slice(new_start, new_stop, s.step)) return tuple(result) -def sliceToCellInterval(s): - newMin = [0, 0, 0] - newMax = [0, 0, 0] +def slice_to_cell_interval(s): + new_min = [0, 0, 0] + new_max = [0, 0, 0] for i in range(3): if type(s[i]) is int: - newMin[i] = s[i] - newMax[i] = s[i] + new_min[i] = s[i] + new_max[i] = s[i] else: - newMin[i] = s[i].start - newMax[i] = s[i].stop - 1 - return walberla_cpp.CellInterval(newMin, newMax) + new_min[i] = s[i].start + new_max[i] = s[i].stop - 1 + return walberla_cpp.CellInterval(new_min[0], new_min[1], new_min[2], new_max[0], new_max[1], new_max[2]) -def cellIntervalToSlice(cellInterval, collapseExtentOne=True): - if not hasattr(collapseExtentOne, '__len__'): - collapseExtentOne = (collapseExtentOne, collapseExtentOne, collapseExtentOne) +def cell_interval_to_slice(cell_interval, collapse_extent_one=True): + if not hasattr(collapse_extent_one, '__len__'): + collapse_extent_one = (collapse_extent_one, collapse_extent_one, collapse_extent_one) slices = [] - for i, collapseInfo in enumerate(collapseExtentOne): - if collapseInfo and cellInterval.min[i] == cellInterval.max[i]: - slices.append(cellInterval.min[i]) + for i, collapseInfo in enumerate(collapse_extent_one): + if collapseInfo and cell_interval.min[i] == cell_interval.max[i]: + slices.append(cell_interval.min[i]) else: - slices.append(slice(cellInterval.min[i], cellInterval.max[i] + 1, None)) + slices.append(slice(cell_interval.min[i], cell_interval.max[i] + 1, None)) return tuple(slices) -def extend(coreModule): - coreModule.makeSlice = SliceMaker() - coreModule.normalizeSlice = normalizeSlice - coreModule.CellInterval.fromSlice = staticmethod(sliceToCellInterval) - coreModule.CellInterval.toSlice = cellIntervalToSlice +def extend(core_module): + core_module.makeSlice = SliceMaker() + core_module.normalizeSlice = normalize_slice + core_module.CellInterval.fromSlice = staticmethod(slice_to_cell_interval) + core_module.CellInterval.toSlice = cell_interval_to_slice diff --git a/python/waLBerla/cuda_extension.py b/python/waLBerla/cuda_extension.py index 0cbb96163..c7e74a528 100644 --- a/python/waLBerla/cuda_extension.py +++ b/python/waLBerla/cuda_extension.py @@ -1,26 +1,26 @@ from pycuda.gpuarray import GPUArray import numpy as np -from .field_extension import normalizeGhostlayerInfo +from .field_extension import normalize_ghostlayer_info -def toGpuArray(f, withGhostLayers=True): +def to_gpu_array(f, with_ghost_layers=True): """Converts a waLBerla GPUField to a pycuda GPUArray""" if not f: return None dtype = np.dtype(f.dtypeStr) strides = [dtype.itemsize * a for a in f.strides] res = GPUArray(f.sizeWithGhostLayers, dtype, gpudata=f.ptr, strides=strides) - if withGhostLayers is True: + if with_ghost_layers is True: return res - ghostLayers = normalizeGhostlayerInfo(f, withGhostLayers) - glCutoff = [f.nrOfGhostLayers - gl for gl in ghostLayers] - res = res[glCutoff[0]:-glCutoff[0] if glCutoff[0] > 0 else None, - glCutoff[1]:-glCutoff[1] if glCutoff[1] > 0 else None, - glCutoff[2]:-glCutoff[2] if glCutoff[2] > 0 else None, + ghost_layers = normalize_ghostlayer_info(f, with_ghost_layers) + cutoff = [f.nrOfGhostLayers - gl for gl in ghost_layers] + res = res[cutoff[0]:-cutoff[0] if cutoff[0] > 0 else None, + cutoff[1]:-cutoff[1] if cutoff[1] > 0 else None, + cutoff[2]:-cutoff[2] if cutoff[2] > 0 else None, :] return res -def extend(cppCudaModule): - cppCudaModule.toGpuArray = toGpuArray +def extend(cpp_cuda_module): + cpp_cuda_module.toGpuArray = to_gpu_array diff --git a/python/waLBerla/field_extension.py b/python/waLBerla/field_extension.py index 7e08aa730..61a14f751 100644 --- a/python/waLBerla/field_extension.py +++ b/python/waLBerla/field_extension.py @@ -8,11 +8,15 @@ import numpy # ----------------------------- Python functions to extend the C++ field module --------------------------------- -def normalizeGhostlayerInfo(field, withGhostLayers): +def normalize_ghostlayer_info(field, with_ghost_layers): """Takes one ghost layer parameter and returns an integer: - True -> all ghost layers, False->no ghost layers""" + True -> all ghost layers, False->no ghost layers + Args: + field: waLberl field object + with_ghost_layers: see numpy_array_from_walberla_field + """ - def normalizeComponent(gl): + def normalize_component(gl): if gl is False: return 0 if gl is True: @@ -21,17 +25,17 @@ def normalizeGhostlayerInfo(field, withGhostLayers): raise ValueError("Field only has %d ghost layers (requested %d)" % (field.nrOfGhostLayers, gl)) return gl - if hasattr(withGhostLayers, "__len__") and len(withGhostLayers) == 3: - ghostLayers = [normalizeComponent(gl) for gl in withGhostLayers] + if hasattr(with_ghost_layers, "__len__") and len(with_ghost_layers) == 3: + ghost_layers = [normalize_component(gl) for gl in with_ghost_layers] else: - ghostLayers = [normalizeComponent(withGhostLayers)] * 3 - return ghostLayers + ghost_layers = [normalize_component(with_ghost_layers)] * 3 + return ghost_layers -def npArrayFromWaLBerlaField(field, withGhostLayers=False): +def numpy_array_from_walberla_field(field, with_ghost_layers=False): """ Creates a numpy array view on the waLBerla field data @field: the waLBerla field - @withGhostLayers: Possible values: + @with_ghost_layers: Possible values: 1. Boolean: False: no ghost layers included True: all ghost layers included 2. Integer: number of ghost layers to include @@ -41,55 +45,58 @@ def npArrayFromWaLBerlaField(field, withGhostLayers=False): if not field: return None - ghostLayers = normalizeGhostlayerInfo(field, withGhostLayers) - - if not hasattr(field, 'buffer'): # Field adaptor -> create field with adapted values - field = field.copyToField() + if hasattr(field, 'nrOfGhostLayers'): + field_gl = field.nrOfGhostLayers + else: + field_gl = 0 + ghost_layers = normalize_ghostlayer_info(field, with_ghost_layers) - if ghostLayers[0] == 0 and ghostLayers[1] == 0 and ghostLayers[2] == 0: - return numpy.asarray(field.buffer(False)) + if ghost_layers[0] == field_gl and ghost_layers[1] == field_gl and ghost_layers[2] == field_gl: + return numpy.asarray(field) else: - result = numpy.asarray(field.buffer(True)) - glCutoff = [field.nrOfGhostLayers - gl for gl in ghostLayers] - view = result[glCutoff[0]:-glCutoff[0] if glCutoff[0] > 0 else None, - glCutoff[1]:-glCutoff[1] if glCutoff[1] > 0 else None, - glCutoff[2]:-glCutoff[2] if glCutoff[2] > 0 else None, - :] + result = numpy.asarray(field) + cutoff = [abs(gl - field.nrOfGhostLayers) for gl in ghost_layers] + if len(result.shape) == 4: + view = result[cutoff[0]:-cutoff[0] if cutoff[0] > 0 else None, + cutoff[1]:-cutoff[1] if cutoff[1] > 0 else None, + cutoff[2]:-cutoff[2] if cutoff[2] > 0 else None, + :] + else: + view = result[cutoff[0]:-cutoff[0] if cutoff[0] > 0 else None, + cutoff[1]:-cutoff[1] if cutoff[1] > 0 else None, + cutoff[2]:-cutoff[2] if cutoff[2] > 0 else None] return view -def arrayFromWaLBerlaAdaptor(field, withGhostLayers=False): - return npArrayFromWaLBerlaField(field.copyToField(), withGhostLayers) - - -def copyArrayToField(dstField, srcArray, slice=[slice(None, None, None)] * 3, withGhostLayers=False): +def copy_array_to_field(dst_field, src_array, idx=None, with_ghost_layers=False): """ Copies a numpy array into (part of) a waLBerla field Usually no copying has to take place between waLBerla fields and numpy arrays, since an array view can be constructed on a field that uses the same memory. When running certain numpy operations that cannot be done in-place,however, the data has to be copied back. - @param dstField: waLBerla field, where the data is copied to - @param srcArray: numpy array where to copy from - @param slice: the numpy array is allowed to be smaller than the field. In this case the target region + @param dst_field: waLBerla field, where the data is copied to + @param src_array: numpy array where to copy from + @param idx: the numpy array is allowed to be smaller than the field. In this case the target region has to be specified via this 3 dimensional slice - @param withGhostLayers: if true the ghost layers of the field are considered as well + @param with_ghost_layers: if true the ghost layers of the field are considered as well """ - dstAsArray = npArrayFromWaLBerlaField(dstField, withGhostLayers) - numpy.copyto(dstAsArray[slice], srcArray) + if idx is None: + idx = [slice(None, None, None)] * 3 + dst_as_array = numpy_array_from_walberla_field(dst_field, with_ghost_layers) + numpy.copyto(dst_as_array[idx], src_array) -def extend(cppFieldModule): - def gatherField(blocks, blockDataName, sliceObj, allGather=False): - field = cppFieldModule.gather(blocks, blockDataName, sliceObj, targetRank=-1 if allGather else 0) +def extend(cpp_field_module): + def gather_field(blocks, block_data_name, slice_obj, all_gather=False): + field = cpp_field_module.gather(blocks, block_data_name, slice_obj, targetRank=-1 if all_gather else 0) if field is not None: - field = npArrayFromWaLBerlaField(field) + field = numpy_array_from_walberla_field(field) field.flags.writeable = False return field else: return None - cppFieldModule.toArray = npArrayFromWaLBerlaField - cppFieldModule.adaptorToArray = arrayFromWaLBerlaAdaptor - cppFieldModule.copyArrayToField = copyArrayToField - cppFieldModule.gatherField = gatherField + cpp_field_module.toArray = numpy_array_from_walberla_field + cpp_field_module.copyArrayToField = copy_array_to_field + cpp_field_module.gatherField = gather_field diff --git a/python/waLBerla/geometry_setup.py b/python/waLBerla/geometry_setup.py deleted file mode 100644 index 32947a35b..000000000 --- a/python/waLBerla/geometry_setup.py +++ /dev/null @@ -1,148 +0,0 @@ -import numpy as np -import scipy -import scipy.ndimage - -try: - from .walberla_cpp import CellInterval, field -except ImportError: - from walberla_cpp import CellInterval, field - -from .core_extension import normalizeSlice - - -def setBoundaryFromArray(blocks, boundaryID, targetSlice, imageArr, boundaryConfig, - resizeFunc=None, extrusionCoordinate=-1): - """Initializes Boundary Handling using an image - :param blocks: the block storage - :param boundaryID: block data name of boundary handling - :param targetSlice: slice of the domain where the image should be placed. If a 2D slice is given, the image is - automatically extruded along the third coordinate. For 3D (or 1D) slices an extrusionCoordinate - has to be given. - Example: for targetSlice=[0.25:0.75, 0 , 0.25:0.75] the image is resized to half - the x-z domain size, placed in the middle of the domain and extruded in y direction. - :param imageArr: a 2D array used to set up the boundaries - :param boundaryConfig: dictionary mapping values of imageArr to boundary configurations, - used as index array in forceBoundary() - :param resizeFunc: if the given slice does not match the shape of imageArr, the image array has to be resized. - This can not be done automatically since interpolation would change the values, and the mapping - given in boundaryConfig is incorrect. Thus the resize function has to be supplied by the caller. - Here a function "resize(imgArr, newSize)" has to be passed, that returns a resized array of - shape "newSize". - :param extrusionCoordinate: only necessary if 3D or 1D slices are given for targetSlice. - See documentation of targetSlice. - """ - - if len(blocks) == 0: - return - - nrOfGhostLayers = blocks[0][boundaryID].getFlagField().nrOfGhostLayers - - imageArr = np.rot90(imageArr, 3) - - sliceWithGhostLayers = 'g' in targetSlice - targetSlice = [s for s in targetSlice if s != 'g'] - size = [s + 2 * nrOfGhostLayers if sliceWithGhostLayers else s for s in blocks.getDomainCellBB().size] - imageCellInterval = CellInterval.fromSlice(normalizeSlice(targetSlice, size)) - if sliceWithGhostLayers: - imageCellInterval.shift(-nrOfGhostLayers, -nrOfGhostLayers, -nrOfGhostLayers) - - # Automatic detection of extrusion coordinate - if extrusionCoordinate < 0 or extrusionCoordinate > 2: - possibleExtrusionCoordinate = np.array([0, 0, 0]) - for i in range(3): - if imageCellInterval.min[i] == imageCellInterval.max[i]: - possibleExtrusionCoordinate[i] = 1 - extrusionCoordinate = i - if sum(possibleExtrusionCoordinate) != 1: - raise ValueError("No valid extrusionCoordinate given - " - "and extrusion coordinate could not be found automatically") - assert (extrusionCoordinate < 3 and extrusionCoordinate >= 0) - - # Resize image - imageBounds = list(imageCellInterval.size) - del imageBounds[extrusionCoordinate] - if imageArr.shape != tuple(imageBounds): - if resizeFunc is None: - raise ValueError("The given image size does not match the target slice: " - "resizing would be necessary but no resizeFunc was given.") - imageArr = resizeFunc(imageArr, imageBounds) - - assert imageArr.shape == tuple(imageBounds) - assert imageArr.dtype.kind == 'i', "imageArr has to be of integer type" - - unusedIdx = 0 - while unusedIdx in boundaryConfig: - unusedIdx += 1 - - def make2Dfrom3DSlice(targetSlice, extrusionCoordinate): - l = list(targetSlice) - del l[extrusionCoordinate] - return l - - for block in blocks: - blockCellInterval = blocks.getBlockCellBB(block) - blockCellInterval.expand(nrOfGhostLayers) - intersectionGlobalCoord = blockCellInterval.getIntersection(imageCellInterval) - - if intersectionGlobalCoord.empty(): - continue - intersectionLocalCoord = blocks.transformGlobalToLocal(block, intersectionGlobalCoord) - - # Create a field with same size as block - blockCellBB = blocks.getBlockCellBB(block) - wlbIndexField = field.createField(list(blockCellBB.size), np.int32, ghostLayers=nrOfGhostLayers) - indexField = field.toArray(wlbIndexField, withGhostLayers=nrOfGhostLayers)[:, :, :, :] - indexField[:, :, :, :] = unusedIdx - - # Copy image into this field - targetSlice = intersectionLocalCoord.getShifted(nrOfGhostLayers, nrOfGhostLayers, nrOfGhostLayers).toSlice() - - minCoord = np.array(imageCellInterval.min) - imgTargetSlice = intersectionGlobalCoord.getShifted(*(-minCoord)).toSlice() - sliceInImage = make2Dfrom3DSlice(imgTargetSlice, extrusionCoordinate) - indexField[targetSlice + [0]] = imageArr[sliceInImage] - - block[boundaryID].forceBoundary(wlbIndexField, boundaryConfig) - - -def binaryResize(img, newSize): - """This can be used as resize function for setBoundaryFromArray for arrays with - zero and ones. After resizing the image is again binarized""" - img = scipy.misc.imresize(img, size=newSize) - img[img <= 254] = 0 - img[img > 254] = 1 - img = img.astype(np.int32) - return img - - -def setBoundaryFromBlackAndWhiteImage(blocks, boundaryID, targetSlice, imagePath, boundaryConfig, - extrusionCoordinate=-1): - """Loads array from image file and calls setBoundaryFromArray. - - :param imagePath: path to image file. - - For the other parameters see documentation of setBoundaryFromArray. - """ - imgArr = scipy.ndimage.imread(imagePath, flatten=True).astype(int) - setBoundaryFromArray(blocks, boundaryID, targetSlice, imgArr, {0: boundaryConfig}, - resizeFunc=binaryResize, extrusionCoordinate=extrusionCoordinate) - - -def setFieldUsingFlagMask(blocks, targetField, targetValue, flagField, flagNames): - """ - Sets all values of a target field to given value where a certain flag is set. - - :param blocks: the block structure - :param targetField: the field that is modified - :param targetValue: value that is written to all entries of cells where the given flag is set - :param flagField: the flag field - :param flagNames: list of flag names. If one of the flags is set, the target value is written - """ - for b in blocks: - mask = 0 - for flagName in flagNames: - mask |= b[flagField].flag(flagName) - - targetArr = field.toArray(b[targetField], True) - flagArr = field.toArray(b[flagField], True)[:, :, :, 0] - targetArr[np.bitwise_and(flagArr, mask) > 0, :] = targetValue diff --git a/python/waLBerla/plot.py b/python/waLBerla/plot.py index e4b007455..a492823aa 100644 --- a/python/waLBerla/plot.py +++ b/python/waLBerla/plot.py @@ -11,128 +11,147 @@ except ImportError: from matplotlib.pyplot import imshow, gcf, figure, plot, quiver -def fieldShow(npField, **kwargs): - npField = np.rot90(npField, 3) - imshow(npField, origin='lower', **kwargs) +def field_show(numpy_field, **kwargs): + numpy_field = np.rot90(numpy_field, 3) + imshow(numpy_field, origin='lower', **kwargs) -def scalarField(blocks, name, sliceDef, fCoord=0, targetRank=0, **kwargs): +def scalar_field(blocks, name, slice_definition, f_coordinate=0, target_rank=0, **kwargs): """Plots a 2D slice through the global domain as an image - :param blocks: the blockstorage - :param name: Name of the block data to be plotted. Has to be a scalar field - :param sliceDef: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice - :param fCoord: value of the forth field coordinate (f) - :param targetRank: rank that gathers and plots the data - :param kwargs: further keyword arguments are passed to matplotlib.pyplot.imshow + :param blocks: the blockforest + :param name: Name of the block data to be plotted. Has to be a scalar field + :param slice_definition: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice + :param f_coordinate: value of the forth field coordinate (f) + :param target_rank: rank that gathers and plots the data + :param kwargs: further keyword arguments are passed to matplotlib.pyplot.imshow """ - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) + f = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) if f: - npField = np.asarray(f.buffer())[:, :, :, fCoord].squeeze() - npField = np.swapaxes(npField, 0, 1) - imshow(npField, origin='lower', **kwargs) + numpy_field = np.asarray(f).squeeze() + numpy_field = np.swapaxes(numpy_field, 0, 1) + imshow(numpy_field, origin='lower', **kwargs) -def scalarFieldAnimation(blocks, name, sliceDef, runFunction, plotSetupFunction=lambda: None, - plotUpdateFunction=lambda: None, fCoord=0, targetRank=0, interval=30, frames=180, **kwargs): +def scalar_field_animation(blocks, name, slice_definition, run_function, plot_setup_function=lambda: None, + plot_update_function=lambda: None, f_coordinate=0, target_rank=0, + interval=30, frames=180, **kwargs): """Creates animation of 2D slices through the global domain - :param runFunction: function without arguments which is run between frames (should move simulation forward) - :param plotSetupFunction: function without arguments that is called after the plot was initially created. - Can be used to configure plot (set title etc.) - :param plotUpdateFunction: function without arguments that is called when figure is updated - :param interval: passed to matplotlib.animation.FuncAnimation: milliseconds between two frames - :param frames: passed to :class:`matplotlib.animation.FuncAnimation` number of frames + :param blocks: the blockforest + :param name: Name of the block data to be plotted. Has to be a scalar field + :param slice_definition: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice + :param run_function: function without arguments which is run between frames (should move simulation forward) + :param plot_setup_function: function without arguments that is called after the plot was initially created. + Can be used to configure plot (set title etc.) + :param plot_update_function: function without arguments that is called when figure is updated + :param f_coordinate: value of the forth field coordinate (f) + :param target_rank: rank that gathers and plots the data + :param interval: passed to matplotlib.animation.FuncAnimation: milliseconds between two frames + :param frames: passed to :class:`matplotlib.animation.FuncAnimation` number of frames for other params see :func:`scalarField` """ fig = gcf() - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) + f = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) im = None if f: - npField = np.asarray(f.buffer())[:, :, :, fCoord].squeeze() - npField = np.swapaxes(npField, 0, 1) - im = imshow(npField, origin='lower', **kwargs) - plotSetupFunction() + numpy_field = np.asarray(f).squeeze() + numpy_field = np.swapaxes(numpy_field, 0, 1) + im = imshow(numpy_field, origin='lower', **kwargs) + plot_setup_function() def updatefig(*args): - runFunction() - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) - if f: - npField = np.swapaxes(np.asarray(f.buffer()), 0, 1) - npField = npField[:, :, :, fCoord].squeeze() - im.set_array(npField) - plotUpdateFunction() + run_function() + gathered_field = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) + if gathered_field: + n_field = np.swapaxes(np.asarray(gathered_field), 0, 1) + if n_field.shape == 4: + n_field = n_field[:, :, :, f_coordinate].squeeze() + else: + n_field = n_field.squeeze() + im.set_array(n_field) + plot_update_function() return im, return animation.FuncAnimation(fig, updatefig, interval=interval, frames=frames) -def vectorField(blocks, name, sliceDef, xComponent=0, yComponent=1, targetRank=0, xStep=1, yStep=1, **kwargs): +def vector_field(blocks, name, slice_definition, x_component=0, y_component=1, target_rank=0, + x_step=1, y_step=1, **kwargs): """Plots a vector field slice using matplotlib quiver - :param blocks: the blockstorage - :param name: Name of the block data to be plotted. Has to be a scalar field - :param sliceDef: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice - :param xComponent: which component of the vector field (0,1 or 2) - to take as the horizontal value for the quiver arrows - :param yComponent: which component of the vector field (0,1 or 2) - to take as the vertical value for the quiver arrows - :param xStep: take only every xStep's cell/arrow in x direction - :param yStep: take only every yStep's cell/arrow in y direction - :param targetRank: rank that gathers and plots the data - :param kwargs: further keyword arguments are passed to matplotlib.pyplot.quiver + :param blocks: the blockforest + :param name: Name of the block data to be plotted. Has to be a scalar field + :param slice_definition: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice + :param x_component: which component of the vector field (0,1 or 2) + to take as the horizontal value for the quiver arrows + :param y_component: which component of the vector field (0,1 or 2) + to take as the vertical value for the quiver arrows + :param x_step: take only every xStep's cell/arrow in x direction + :param y_step: take only every yStep's cell/arrow in y direction + :param target_rank: rank that gathers and plots the data + :param kwargs: further keyword arguments are passed to matplotlib.pyplot.quiver """ - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) + f = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) if f: - npField = np.swapaxes(np.asarray(f.buffer()), 0, 1) - xVel = npField[::xStep, ::yStep, :, xComponent].squeeze() - yVel = npField[::xStep, ::yStep, :, yComponent].squeeze() - quiver(xVel, yVel, **kwargs) + numpy_field = np.swapaxes(np.asarray(f), 0, 1) + x_vel = numpy_field[::x_step, ::y_step, :, x_component].squeeze() + y_vel = numpy_field[::x_step, ::y_step, :, y_component].squeeze() + quiver(x_vel, y_vel, **kwargs) -def alongLine(blocks, name, sliceDef, fCoord=0, targetRank=0, **kwargs): +def along_line(blocks, name, slice_definition, f_coordinate=0, target_rank=0, **kwargs): """Plot a field value along a one dimensional slice through the domain - :param blocks: the blockstorage - :param name: Name of the block data to be plotted. Has to be a scalar field - :param sliceDef: a one dimensional slice through the domain. Can be created with :func:`waLBerla.makeSlice` - :param fCoord: value of the forth field coordinate (f) - :param targetRank: rank that gathers and plots the data - :param kwargs: further keyword arguments are passed to :func:`matplotlib.pyplot.plot` + :param blocks: the blockstorage + :param name: Name of the block data to be plotted. Has to be a scalar field + :param slice_definition: a one dimensional slice through the domain. Can be created with :func:`waLBerla.makeSlice` + :param f_coordinate: value of the forth field coordinate (f) + :param target_rank: rank that gathers and plots the data + :param kwargs: further keyword arguments are passed to :func:`matplotlib.pyplot.plot` """ - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) + f = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) if f: - npField = np.asarray(f.buffer()) - npField = npField[:, :, :, fCoord].squeeze() + npField = np.asarray(f) + npField = npField[:, :, :, f_coordinate].squeeze() plot(npField, **kwargs) -def alongLineAnimation(blocks, name, sliceDef, runFunction, plotSetupFunction=lambda: None, fCoord=0, targetRank=0, - interval=30, frames=180, **kwargs): +def along_line_animation(blocks, name, slice_definition, run_function, plot_setup_function=lambda: None, + f_coordinate=0, target_rank=0, interval=30, frames=180, **kwargs): """Animated version of :func:`alongLine` - For parameter documentation see :func:`scalarFieldAnimation` and :func:`alongLine` + :param blocks: the blockforest + :param name: Name of the block data to be plotted. Has to be a scalar field + :param slice_definition: a two dimensional slice through the domain. Can be created with waLBerla.makeSlice + :param run_function: function without arguments which is run between frames (should move simulation forward) + :param plot_setup_function: function without arguments that is called after the plot was initially created. + Can be used to configure plot (set title etc.) + :param f_coordinate: value of the forth field coordinate (f) + :param target_rank: rank that gathers and plots the data + :param interval: passed to matplotlib.animation.FuncAnimation: milliseconds between two frames + :param frames: passed to :class:`matplotlib.animation.FuncAnimation` number of frames """ fig = figure() - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) + f = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) line = None if f: - npField = np.asarray(f.buffer()) - npField = npField[:, :, :, fCoord].squeeze() - line, = plot(npField, **kwargs) - plotSetupFunction() + numpy_field = np.asarray(f) + numpy_field = numpy_field[:, :, :, f_coordinate].squeeze() + line, = plot(numpy_field, **kwargs) + plot_setup_function() def updatefig(*args): - runFunction() - f = walberla_cpp.field.gather(blocks, name, sliceDef, targetRank=targetRank) - if f: - npField = np.asarray(f.buffer()) - npField = npField[:, :, :, fCoord].squeeze() - fig.gca().set_ylim((np.min(npField), np.max(npField))) - line.set_ydata(npField) + run_function() + gathered_array = walberla_cpp.field.gather(blocks, name, slice_definition, targetRank=target_rank) + if gathered_array: + n_field = np.asarray(gathered_array) + n_field = n_field[:, :, :, f_coordinate].squeeze() + fig.gca().set_ylim((np.min(n_field), np.max(n_field))) + line.set_ydata(n_field) return line, return animation.FuncAnimation(fig, updatefig, interval=interval, frames=frames, blit=False) diff --git a/python/waLBerla/timeloop_extension.py b/python/waLBerla/timeloop_extension.py deleted file mode 100644 index 31b859ad1..000000000 --- a/python/waLBerla/timeloop_extension.py +++ /dev/null @@ -1,69 +0,0 @@ -try: - from . import walberla_cpp -except ImportError: - import walberla_cpp - - -def functorFromSweep(blocks, sweep): - """Makes a functor from a sweep, by iterating over all the blocks in the provided block storage""" - - def functor(): - for b in blocks: - sweep(b) - - return functor - - -class Timeloop(walberla_cpp.timeloop.ITimeloop): - def __init__(self, nrOfTimesteps): - super().__init__() - self._nrOfTimesteps = nrOfTimesteps - self._timestep = 0 - self._functors = [] - self._stopFlag = False - - def run(self, timesteps=None): - if not timesteps: - timesteps = self._nrOfTimesteps - for t in range(timesteps): - self.singleStep() - if self._stopFlag: - break - - def singleStep(self): - for func in self._functors: - func() - self._timestep += 1 - - def stop(self): - self._stopFlag = True - - def synchronizedStop(self, stop=True): - # syncStop = wlb.mpi.allreduceInt(int(stop), wlb.mpi.LOGICAL_OR) - self._stopFlag = True - - def setCurrentTimeStep(self, ts): - self._timestep = ts - - def getCurrentTimeStep(self): - return self._timestep - - def getNrOfTimeSteps(self): - return self._nrOfTimesteps - - def __getFunctor(self, functor, blocks): - if blocks: # assume that it is a sweep if blocks were given - return functorFromSweep(blocks, functor) - else: - return functor - - def add(self, functor, blocks=None): - self._functors.append(self.__getFunctor(functor, blocks)) - return len(self._functors) - 1 - - def replace(self, handle, functor, blocks=None): - self._functors[handle] = self.__getFunctor(functor, blocks) - - -def extend(cppTimeloopModule): - cppTimeloopModule.Timeloop = Timeloop diff --git a/python/waLBerla/tools/sqlitedb/insert.py b/python/waLBerla/tools/sqlitedb/insert.py index 29fa37c16..2e759af07 100644 --- a/python/waLBerla/tools/sqlitedb/insert.py +++ b/python/waLBerla/tools/sqlitedb/insert.py @@ -13,16 +13,16 @@ def sequenceValuesToScalars(data): This is useful when using the dictionary with storeSingle(), since each entry gets a separate column after the sequences have been separated. """ - keysToDelete = [] - newValues = {} + keys_to_delete = [] + new_values = {} for key, value in data.items(): if type(value) in [list, tuple]: - keysToDelete.append(key) + keys_to_delete.append(key) for i in range(len(value)): - newValues["%s_%d" % (key, i)] = value[i] - for k in keysToDelete: + new_values["%s_%d" % (key, i)] = value[i] + for k in keys_to_delete: del data[k] - data.update(newValues) + data.update(new_values) def storeSingle(data, tableName, dbFile="database.sqlite", runId=None): @@ -40,9 +40,9 @@ def storeSingle(data, tableName, dbFile="database.sqlite", runId=None): if runId: data['runId'] = runId - keyString = ",".join(data.keys()) - valueString = ",".join(["?" for e in data.values()]) - query = "INSERT INTO %s ( %s ) VALUES ( %s )" % (tableName, keyString, valueString) + key_string = ",".join(data.keys()) + value_string = ",".join(["?" for e in data.values()]) + query = "INSERT INTO %s ( %s ) VALUES ( %s )" % (tableName, key_string, value_string) conn = sqlite3.connect(dbFile) c = conn.cursor() @@ -76,9 +76,9 @@ def storeMultiple(data, tableName, dbFile="database.sqlite", runId=None): if runId is not None: data.update({'runId': [runId] * list_length}) - keyString = ",".join(data.keys()) - valueString = ",".join(["?" for e in data.values()]) - query = "INSERT INTO %s ( %s ) VALUES ( %s )" % (tableName, keyString, valueString) + key_string = ",".join(data.keys()) + value_string = ",".join(["?" for e in data.values()]) + query = "INSERT INTO %s ( %s ) VALUES ( %s )" % (tableName, key_string, value_string) conn = sqlite3.connect(dbFile) c = conn.cursor() @@ -93,32 +93,37 @@ def storeMultiple(data, tableName, dbFile="database.sqlite", runId=None): return lastrowid -def checkAndUpdateSchema(data, tableName, dbFile="database.sqlite", referenceRuns=False): +def checkAndUpdateSchema(data, tableName, dbFile="database.sqlite", referenceRuns=False, alter_table=False): """Alters a sqlite table in order to match the given data: * if table with given name does not exist yet, it is created * keys in the data dictionary correspond to columns - * columns are added if necessary, existing data has NULL in these new columns + * columns are added if necessary (only when alter_table is set to True), + * existing data has NULL in these new columns :param data: see :func:`storeSingle` or :func:`storeMultiple` + :param tableName name of the table which should be updated + :param dbFile name of the sql file which should be written :param referenceRuns: if False the table gets an autoincrementing integer column 'runId' if True, a normal column runId is created that points into another table with runId as primary key + :param alter_table If True the columns of the table will be altered. + Should be called if new columns should be inserted. """ def pythonToSqlType(python_type): if python_type is int: - return ("INTEGER") + return "INTEGER" elif python_type is bool: - return ("INTEGER") + return "INTEGER" elif python_type is float: - return ("DOUBLE") + return "DOUBLE" elif python_type is str: - return ("TEXT") + return "TEXT" elif python_type is list: - return (pythonToSqlType(type(value[0]))) + return pythonToSqlType(type(value[0])) elif python_type is tuple: - return (pythonToSqlType(type(value[0]))) + return pythonToSqlType(type(value[0])) if referenceRuns: names = ["runId"] @@ -131,21 +136,22 @@ def checkAndUpdateSchema(data, tableName, dbFile="database.sqlite", referenceRun names.append(key) types.append(pythonToSqlType(type(value))) - columns = [("%s %s") % e for e in zip(names, types)] + columns = ["%s %s" % e for e in zip(names, types)] - createQuery = "CREATE TABLE IF NOT EXISTS %s ( %s );" % (tableName, ",".join(columns)) - alterQueries = ["ALTER TABLE %s ADD COLUMN %s %s;" % (tableName, key, typ) for key, typ in zip(names, types)] + create_query = "CREATE TABLE IF NOT EXISTS %s ( %s );" % (tableName, ",".join(columns)) + alter_queries = ["ALTER TABLE %s ADD COLUMN %s %s;" % (tableName, key, typ) for key, typ in zip(names, types)] conn = sqlite3.connect(dbFile) c = conn.cursor() - c.execute(createQuery) - for q in alterQueries: - try: - c.execute(q) - except sqlite3.OperationalError as e: - print(e) - pass + c.execute(create_query) + if alter_table: + for q in alter_queries: + try: + c.execute(q) + except sqlite3.OperationalError as e: + print(e) + pass conn.commit() conn.close() diff --git a/python/waLBerla/tools/sqlitedb/merge.py b/python/waLBerla/tools/sqlitedb/merge.py index 5628b1f39..b853e3272 100755 --- a/python/waLBerla/tools/sqlitedb/merge.py +++ b/python/waLBerla/tools/sqlitedb/merge.py @@ -28,12 +28,12 @@ def mergeSqliteFiles(targetFile, fileToMerge): db = sqlite3.connect(targetFile) db.execute('ATTACH "' + fileToMerge + '" AS toMerge') - targetColumns = getColumnNames(db, "runs", "main") - toMergeColumns = getColumnNames(db, "runs", "toMerge") + target_columns = getColumnNames(db, "runs", "main") + to_merge_columns = getColumnNames(db, "runs", "toMerge") - columnsToCreate = [e for e in toMergeColumns if e not in targetColumns] + columns_to_create = [e for e in to_merge_columns if e not in target_columns] - for column in columnsToCreate: + for column in columns_to_create: print("Adding Column {} to run table of {} ".format(column[0], targetFile)) db.execute("ALTER TABLE main.runs ADD COLUMN %s %s" % (column[0], column[1])) @@ -41,12 +41,12 @@ def mergeSqliteFiles(targetFile, fileToMerge): # check if an entry with same date exists, if not add the run and the timing pool entries # to the targetTable c = db.cursor() - assert (toMergeColumns[0][0] == "runId") - columns = [e[0] for e in toMergeColumns] - columnString = ",".join(columns) - columnStringNoRunId = ",".join(columns[1:]) + assert (to_merge_columns[0][0] == "runId") + columns = [e[0] for e in to_merge_columns] + column_string = ",".join(columns) + column_string_no_run_id = ",".join(columns[1:]) - query = 'SELECT {} FROM toMerge.runs WHERE timestamp || " " || uuid NOT IN '.format(columnString, ) + query = 'SELECT {} FROM toMerge.runs WHERE timestamp || " " || uuid NOT IN '.format(column_string, ) query += '( SELECT timestamp || " " || uuid FROM main.runs )' # associated tables are tables that reference the runs table, having a first column of 'runId' which is a @@ -80,7 +80,7 @@ def mergeSqliteFiles(targetFile, fileToMerge): # Build up insert statement for 'runs' table questionMarkList = ['?'] * (len(run) - 1) questionMarkString = ",".join(questionMarkList) - insertStatement = "INSERT INTO main.runs (%s) VALUES (%s);" % (columnStringNoRunId, questionMarkString) + insertStatement = "INSERT INTO main.runs (%s) VALUES (%s);" % (column_string_no_run_id, questionMarkString) # Execute the insert insertCursor = db.cursor() insertCursor.execute(insertStatement, run[1:]) diff --git a/python/waLBerla_docs/conf.py b/python/waLBerla_docs/conf.py index e872f555a..b1e67ed6c 100644 --- a/python/waLBerla_docs/conf.py +++ b/python/waLBerla_docs/conf.py @@ -25,7 +25,7 @@ source_suffix = '.rst' master_doc = 'index' project = 'waLBerla' -copyright = '2016, LSS waLBerla Team' +copyright = '2020, LSS waLBerla Team' version = '' release = '' @@ -36,7 +36,7 @@ pygments_style = 'sphinx' htmlhelp_basename = 'waLBerladoc' -intersphinx_mapping = {'python': ('http://docs.python.org/3.5', None), +intersphinx_mapping = {'python': ('http://docs.python.org/3.8', None), 'numpy': ('http://docs.scipy.org/doc/numpy/', None), 'scipy': ('http://docs.scipy.org/doc/scipy/reference/', None), 'matplotlib': ('http://matplotlib.sourceforge.net/', None)} diff --git a/python/waLBerla_docs/index.rst b/python/waLBerla_docs/index.rst index 78964d95e..aa70a63de 100644 --- a/python/waLBerla_docs/index.rst +++ b/python/waLBerla_docs/index.rst @@ -4,34 +4,23 @@ Documentation of waLBerla's Python interface Quick Start / Tutorials: ------------------------ -You can quickly try out waLBerla's Python interface in a hosted IPython notebook without -having to install anything: - -http://demo.walberla.net - -This site contains interactive tutorials, illustrating how to set up a 2D lattice Boltzmann -simulation with waLBerla. - - -Installation with conda: +This is the documentation of waLBerla`s Python coupling. +It enables to use the core functionality of waLBerla from Python. A primary advantage of +the Python coupling is that it allows having a view on waLBerla`s data as +NumPy arrays. With this, it is easily possible to provide pre and postprocessing +routines using powerful packages from Python. Furthermore, it is possible to set up entire +simulations just from Python. This feature is primarily used in the code generation framework `pystencils <https://pycodegen.pages.i10git.cs.fau.de/pystencils/>`_ +within its `parallel data handling <https://pycodegen.pages.i10git.cs.fau.de/pystencils/notebooks/03_tutorial_datahandling.html>`_ which entirely builds upon waLBerla`s Python coupling. +waLBerla`s Python bindings are built with `pybind11 <https://pybind11.readthedocs.io/en/stable/#>`_, a lightweight header-only package which is shipped as a submodule. +Thus, there is no need to install any additional software. + + +Installation: ------------------------ -To run waLBerla on your own machine the simplest way to get going is the installation via -the `conda package manager <http://conda.pydata.org>`_:: - - conda install --channel lssfau walberla - - -Run in docker: --------------- - -Docker is a lightweight virtualization solution. We provide a docker image that -contains the same environment as hosted on http://demo.walberla.net. -With this image you can run and develop waLBerla simulations on your own machine without having to manually -install the dependencies. All you need is a running installation of `Docker <www.docker.com>`_. -Run the waLBerla image with the following command and navigate in your browser to http://localhost:8888 :: +To install waLberla as Python package in your path run the following command in your build folder :: - docker run -it -p 8888:8888 walberla/runenv-ubuntu-python + make pythonModuleInstall API Documentation: @@ -44,8 +33,6 @@ API Documentation: modules/blockforest modules/core modules/field - modules/geometry - modules/lbm modules/plot modules/tools diff --git a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 01 - Basic data structures.ipynb b/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 01 - Basic data structures.ipynb index df203fccd..56093faa5 100644 --- a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 01 - Basic data structures.ipynb +++ b/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 01 - Basic data structures.ipynb @@ -24,11 +24,21 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[[0 0 0 0 0]\n", + " [0 0 0 0 0]\n", + " [0 0 0 0 0]\n", + " [0 0 0 0 0]\n", + " [0 0 0 0 0]]\n" + ] + } + ], "source": [ "import numpy as np\n", "def makeGrid(shape):\n", @@ -46,10 +56,8 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, + "execution_count": 2, + "metadata": {}, "outputs": [], "source": [ "ALIVE = 1\n", @@ -86,11 +94,17 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)]\n" + ] + } + ], "source": [ "print(neighborhoodD2Q9)" ] @@ -104,11 +118,34 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Initial Setup:\n", + "[[0 0 0 0 0]\n", + " [0 0 0 0 0]\n", + " [0 1 1 1 0]\n", + " [0 0 0 0 0]\n", + " [0 0 0 0 0]]\n", + "After timestep 1: \n", + "[[0 0 0 0 0]\n", + " [0 0 1 0 0]\n", + " [0 0 1 0 0]\n", + " [0 0 1 0 0]\n", + " [0 0 0 0 0]]\n", + "After timestep 2: \n", + "[[0 0 0 0 0]\n", + " [0 0 0 0 0]\n", + " [0 1 1 1 0]\n", + " [0 0 0 0 0]\n", + " [0 0 0 0 0]]\n" + ] + } + ], "source": [ "grid = makeGrid( [5,5] )\n", "grid[2,1:4] = ALIVE\n", @@ -132,12 +169,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { - "collapsed": false, "scrolled": false }, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "<Figure size 1080x864 with 1 Axes>" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ "from material.matplotlib_setup import * # import matplotlib and configures it to play nicely with iPython notebook\n", "matplotlib.rcParams['image.cmap'] = 'Blues' # switch default colormap\n", @@ -154,11 +203,26 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<video controls width=\"80%\">\n", + " <source src=\"data:video/x-m4v;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAGlJtZGF0AAACcQYF//9t3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMSBjZGU5YTkzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTIgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTI0IGxvb2thaGVhZF90aHJlYWRzPTQgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTIgc2NlbmVjdXQ9NDAgaW50cmFfcmVmcmVzaD0wIHJjX2xvb2thaGVhZD00MCByYz1jcmYgbWJ0cmVlPTEgY3JmPTIzLjAgcWNvbXA9MC42MCBxcG1pbj0wIHFwbWF4PTY5IHFwc3RlcD00IGlwX3JhdGlvPTEuNDAgYXE9MToxLjAwAIAAAA/hZYiEBX///w9FAAE/zycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddf/4R8FoIgAMjdgACAUAAIAtTYAUERgAAgDgACACANHpYHzIq36zo0yT9Kmtra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tr/+H2CASABHf2wABANAAEAu5sAEkwy7TUENddddddddddddddddddddddddczBR2UgU0tddddddddddddddddddddddddddddddddddddddPrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666666666666/90hDUrBFwAIgviKY+if5AACAe8LwEkBxOwxHaS/8uv9s2VGGbFf+3/9RnkgFtzg0X1w09Y+FxdV/3ChZMDuhyQknln+BYf/9gk+QAD1BUAVblVKmGamQwbknqCOuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrvp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuv/EJwGGwRcABMTFOVhncstbnL/HBHoZITDETHEyPA8db72gCIf9UU9/ctKucufgACBYAAkzIHwJ/gDTACLTbCggt/jpk+GOcABBlIQhSkIc5CEOf/AAoD+BMEXbmpgyJThh/UO11111111111111111111111111111111PXXXXXXXT1111111111111111111111111309ddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXT111111111111111111111111111111111111111109ddddddddddddddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111111111111111109ddddddf//jgtBhwHAAIAYKBFMCj7Acx4GW/HAJnHOPJlra2tra2tra2tra2tra2tra2tra2tra//j4IFxeA4ABUA4LJpgCIB+CEFFVtMDO/Jgxrrrrrrrp666666666666666666666666666euuuuuuuKYNbP3QzQmQK6OA0tLS0tLS0tLS0tLS0tLS0tLS0tLS0sUwtEJy8KizVMP111111109ddddddddddddddddddddddddddPXXXXXXXMwZXqCuuuuuuuuuuuuuuuuuuuuuuunpnrrrrrrrp666666666666666666666666666euuuuuuunrrrrrrrrrrrrrrrrrrrrrrrp6euuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrr//iKM0KgggBmVM0T1e+AIwIrx64v1lFTikZUEr9943AAGgMOIQbN+djTxSn3/F+3s2Z8P/+wQf+MAAtAdYH2/Nahxq5sNQ3XXXXXXT1111111111111111111111109M9dddddddPXXXXXXXXXXXXXXXXXXXXXXXXX+QQ/4SBBAATJxDRflydFh+LRDKAAICRM5GgIOwCfiFqhGbr1Tu4YY5wcGVl9lZfUENddddddPXXXXXXXXXXXXXXXXXXXXXXXT09dddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXT111111109dddddddddddddddddddddddPT111111109ddddddddddddddddddddddddddPXXXXXXXT1111111111111111111111109PXXXXXXXT1111111111111111111111111109ddddddfD/pgDDoMOAAkjEXHWmBsKW1uCByoy4Vy+XRaLXqa2Ewmtra2tra2tra2tra2tra2tra2tra2v8PH7BcTgAN0ZGxPmOjsxUZYVyzH4ZdLqYMa6666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrri0adEV+8m7W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tanrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuv//4QQggwAHww6QDN3IroPh29kG//nCEZSkOVB1J6ghrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666666666666/ieH/CQIIAKfEjHUZXP+BAe3YIWTX4n8qAhKv+C5pBtWX6tPLDD//+w99gXUG0Xdya2zovOtDGWaghrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666666666666///4IQ5gANAB7gBIERE4lEClpCpDT1DtdddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXX2pAf/CQIoAFkXoR/K8RF76BHYxniI3skynCu8EYaCMrvAsW7g7xiD5wBKA9v4WcqalQn+DHOAAgylKUpSlKUpSlKABQH8CYIu3VTBkSnDD//qCOuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrp66666666666666666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrwoGAf6BWCLAAQjsgrFkJrWNT2mERiSxEdU+3tbW18f7CMKfgAIG4U1uI4kBghVZh+xweAA2TNoTZXVmXxYQhDOHxwgwz59noQR/TRgKwJmQ//eNAYOi58wbDc5hAbA7g9ra2tra2tr48AjT0J8ABGJziL4kgcI61ZPGOYAAIA4AAgBgDxmW/oG0RwYIbtREXYIN/EkFVxwMFo1cmt+a2tra2tra+P7UgNDOAAgThDG73kgNEK7MPmILAIHq77v/zwNwnHTLSHAeeiKgvgQc8Ula9Stis90DST1TSSMw3ynf/w/QIDLDtbW1tbW18f+AKKCheAAkJiGIwzhZlLnBVSAAmJinOwR3LNaQQv2NfGFGp1h7DruA+AEKuQW2QiZMMKa8jf8P6I1tbW1tbXx/8YoKeAAgnGKXve8DTGdeaM9AxDd+jBFUU8KU36CwBVgCn6ogELH3/rn/UA+gnwX5EMj6cjvrPQxtm1tbXC3/9h4uAAhnK471lrv3vX/hqCGuuuuuuuuuuuuuuuuuuuuuuuuuuuuvRh//w8CDwyFYT6W1RJHPOL8AEoZawSXci3vghPNWGGoIa66666+EMP/CQIPkACUxwYD3SdzDQtHnXD9g5DAChLlI7SaQdbDDqCGuuuuuvtth/wkCCAC0NYQxT3E5//9/8DYgYcoGbJJLWpNF7//vGPRCu26omdQw1BCGuuuuuv8v/w+HgAHCFTIhtNKW6OKzQ3AIwc8CTr0G2BptbVXBhqHw111111/z/+Hw9AWwTEABVareALCMqVDv//4e/IAJgMS/PaGu4gL6hh1D9ddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeAAAC9EGaOAr4ArbigScAK5/dWIBcerfSqH4mA4AEX1JmPAAi+pM/LSfbT5aDMAAi+xMwCQG//iGC4YA4ABADBQIy3wgJSkCBZF4XZfJsILydf0EgohcQuIXELiFxC5v8eMMF0AHcxMIwhhAe7vn/8BEA+F2WHkVzJoNXcB4LelxaBXHAbOudc651zrnXHsFX/mvweHfOwV5/P5/P5/P53g8O+d8/n8/n8/n87wWcSHgHAAi+xMwcACL7EzAWCmZV6IOrx4AEX2JmEDvnYfz+fz+fz+fzvB4d875/P5/P5/P53g8O+d8/n8/n8/n87weHfO+fz+fz+fz+d4ND+fz+fz+fz+fzvnfP5/P5/P5/O+d8/n8/n8/n8/BYfz+fz+fz+fz+d4g753z+fz+fz+fz8Fh/P5/P5/P5/P53iDvnfP5/P5/P5/PwWH8/n8/n8/n8/neIO+d8/n8/n8/n8/BJxIeAcACL7EzBwAIvsTPgAI01J2nu4MQeH8/n8/n8/n8/neIO+d8/n8/n8/n8/BIdh4sUEHh/P5/P5/P5/P53iDvnfP5/P5/P5/PwWH8/n8/n8/n8/neIO+d8/n8/n8/n8/BYfz+fz+fz+fz+d4g753z+fz+fz+fz8Fh/P5/P5/P5/P53zvn8/n8/n8/nfO+fz+fz+fz+fgsPLn8/n8/n8/n8753z+fz+fz+fzvnfP5/P5/P5/PwaHfO+fz+fz+fz+d4PDvnfP5/P5/P5/O8FfMCDgIX6QdU7wgd87Dufz+fz+fz+d4PDvnfP5/P5/P5/O8Hh3zvn8/n8/n8/neDw753z+fz+fz+fzvB4d8exEyKsul3NptnXOudc651zrneDw3x/9AsDgDgAFwBwJLS3wFgEwZKX4XZfjFpFELiFxC4hcQuIXMPf/6BZAASiFFcuSCrelYYcAlhV/6eA+AmzgAIbu7u7u7u7u4AFA/glGefZHBJy4Yf/8AinLAn/Jr/hDm8Cd6S0I4rwAeSTrHW5n12Qj/6qdfANlAAAAURBmkAU8AcncCJffffffffcHl99999999weX33333333B5ffffffffcHl99999999weX33333333B5ffffffffcHl99999999waX333333333333333333333333BZgBBjPfcRffffffffcFnz33EX33333333BZ899xF99999999wWfPfcRffffffffcFnz33EX33333333BZ899xF99999999wWfPfcRffffffffcFiv777777777777777777777777gtvvvvvvvvvvvvvvvvvvvvvvvuDS++++++++4PL77777777gr8wIOCF4c+J3hC++++++++4PL77777777g8vvvvvvvvuDy++++++++4PL77777777g8vvvvvvvvvuA9/EwAHRvWSlz///hmAAEh0uTMHAAJDpcmYOAASHS5MwBb0AAAE2QZpgFPAHr333333333B5ffffffffaBc8Hl99999999weX33333333B5ffffffffcHl99999999weX33333333B5ffffffffcGl999999999999999999999999wWX33333333EX33333333BZffffffffcRffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffcRffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffffffffffffffffffcFt99999999999999999999999waX33333333B5ffffffffcFh2JhC++++++++4PL77777777g8vvvvvvvvuDy++++++++4PL77777777g8vvvvvvvvuAPWgAAAATxBmoAU8AevffffffffcHl99999999weX333333333B3fffffffffcHd999999999wd3333333333B3fffffffffcHd999999999wZ3333333333333333333333333BZffffffffcRffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffcRffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffcRffffffffcFl999999999999999999999999wW33333333333333333333333BrfffffffffcHd999999999wVneEL777777777g7vvvvvvvvvuDu+++++++++4O7777777777g7vvvvvvvvvuDu++++++++4A9aAAAABMkGaoBLwB6999999999weX33333333B5ffffffffcHl99999999weX33333333B5ffffffffcHl99999999weX33333333BpffffffffffffffffffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffcRffffffffcFl99999999xF99999999wWX33333333EX33333333BZffffffffcRffffffffcFl99999999xF99999999wWX333333333333333333333333BbffffffffffffffffffffffcGt99999999weX33333333B5ffffffffcHl99999999weX33333333B5ffffffffcHl99999999oFTweX33333333AHrQAAAAxltb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAALuAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACQ3RyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAALuAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAEOAAAA2AAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAC7gAAAAAAAEAAAAAAbttZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAAEAAAADAAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFmbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABJnN0YmwAAACWc3RzZAAAAAAAAAABAAAAhmF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAEOANgAEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAAwYXZjQwFCwB7/4QAYZ0LAHtsBEBt5eEAAAAMAQAAAAwEDxYu4AQAFaMqDyyAAAAAYc3R0cwAAAAAAAAABAAAABgAAIAAAAAAUc3RzcwAAAAAAAAABAAAAAQAAABxzdHNjAAAAAAAAAAEAAAABAAAABgAAAAEAAAAsc3RzegAAAAAAAAAAAAAABgAAEloAAAL4AAABSAAAAToAAAFAAAABNgAAABRzdGNvAAAAAAAAAAEAAAAwAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1OC40NS4xMDA=\" type=\"video/mp4\">\n", + " Your browser does not support the video tag.\n", + "</video>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "ani = makeImshowAnimation(grid, gameOfLifeSweep, frames=6)\n", "displayAsHtmlVideo(ani, fps=2)" @@ -173,14 +237,29 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<video controls width=\"80%\">\n", + " <source src=\"data:video/x-m4v;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQABLEttZGF0AAACcgYF//9u3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMSBjZGU5YTkzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTIgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTI0IGxvb2thaGVhZF90aHJlYWRzPTQgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTE1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAY3GWIhA7yYoAAvBScnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJydddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddf/+E1hQMYACRjUmqjMEtyWKP6AZhHinGE/EyloXvzhBqaz1e/3yYYTojX7HTV3/GCpKBaq+eHzdW7hjD/lwAEYTuItBLDg9HnBBP4ZgAAgOAAQa1LfDAASAD1C8HUxFCbydXwwzS2gg7W1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1tbW1x84f6BYEYACICQ0GQgw8PpyrfYNzvXumGQ111111111111131zPHMcaWlpaWlpaWlpaWlpaWlpaWlpaWlpaX+If9AsBQA4BDHALlvgwACMCAS595N/mH/wWQAGUpREM/Z/AxjwwpIa+fSQkgTXuZghj47SPS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLXT11111111111111zQTXpgnrrrrrrrrrrrrrrrrrrrrr+A//hoFEACKKcZCF+sc2Cg1xABGiBLLA+lhqTV/iH/oFkBwEKaCpb4OAEUEBbBlS/Eu8AzD/0CyAAmZjrocqRoQ1DDgSAIggX4F1+K+Enr8//w0UeaPgAUUpQkc6kL//+GNqYYUkQW18tkMYuE188EwQ1LXXXXXXXXXXXXXXXXXXXXXXXXT11111111111111109ddddddddddfEP/8FYIgOAAgAwEsviCAAIAyEgAaBqcsqnL8GVLKVL8WhYrb+prnD/+wVmAArijujOVExVwYwpknhmuZSrmeE8Kh+uuuuv4D/+CsF0ARTYMxj1q+DgiQYjlgF2WFm5qTTQ8AAA/+GiwBWEqDkPA+2HdV+A/Dgiw0aX6FMs0Nmn1+AYh/6BZA4CAj2XwrDIB5HgdY5fg9bwDb/6BZACb0iJEtXv3ZgLOsKZfn3/H/2CwFIqPiAHxh46JiDomIOM+DjPXXUt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111111111111///OFQxwAELEMiuLANGu8fYDX9DoB3q0wkYaNZ7QL8MdAL8ElhWKT2RR/LphmuuuuuuuuulpfhgAf4aBA7gOAATAYPIS274YE1hgvIMVLKKl+Oy1svzqQkVWH8P7BXwAG6MS8hcx2KRgwBGcGrueSFQQ11111111111111111111111111111111111109ddddddddddddfCDBD/hIMeBoISk6VOTAaeiV+h+wCUBg2OOaUCUt+lWPQMA3zIYVM4lHcP4MP//7BFDAAaL8JZemSV48vV+DGaWoZrrrrrrrrrrrpaWlrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666euuuv//iAwXAuAAiq5og12ESGDuFbQCPD491//rDBdAAhTReYWM6qGWaa79EYd0wX11111111111111111111111111111111111111111111109ddddddddddddddPXXXXMwYUsz5PTBXU9ddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXT111109PT11111111111111111111111111111111111111111111109ddddddddddddddPXXXX+H+AWC4GAAGOrbkm1/w3YcBEA/DX3b/4Bv4LoAGRbOYVMnX+DDimZRGB3VHXbpgxrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666/gkBh/CQYgAIWIZFcWAaNd4+wGvgaCEpOlTkwGnolfmABAGgHFygE91AYcA/wH1/i7vrX7FDFRdYtRPITWAMMbu6QIpCove/9h//sPf+AA0X4Sy9Mkjx5e76hmuuulta6666666666666666666666666666666666666666666666euuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrp66666666666666666666666666666666666666666666666666666euuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666/9FlFi7DXAAaoiCHIZ3KHneGfgInAMT3QPN3tagI//3sOgG0nTViSmyacZfCYCJe8hwu3Ks+9eHphA71UPQK06oNT3+5CgBWowtwkoYvyv//8PD//YIIYADRXjWTpUs8WTq3DUN11111111111111111111111111111111111111111111111111109ddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111109ddddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXT111111111111111111111111111111111111111111111111111109ddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111/9YyFxew1wAGtGJwRi64kJNcI/ouh3GUy1vEvaj77EhHeMYKYl/iF3eEGQs9qGEvlgY7ygXKkVPvFchTRgGpGDpFkZsL17vtRrjAUkTLVgQj+/veMDaNgEvv+XHUEe2Bh7NNgpZ2IR/jnAAQmd3d2dmZmd8P/gAUHcNRGl27hZKoYYfUN11111111111111111111111111111111111111111111111111109ddddddddddddd9PXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111109ddddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXT111111111111111111111111111111111111111111111111111109ddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111//xqOFQxAATGxTFBnN5RYae8V8G2gDBLMJzRY807WBBbVhhOliKUvgD44RBZqCCTGv1YIIlHFgCaVumX/usQEDXsAWNVw8TG59h/29hPYsP4ABDVAZ0iC7+vuP/OUM11111111111111111111111111111111111111111111111111109ddddddddddddfLt/8JBbxAF1UIBtLQIlo/Kf0PyGoKGYnVZPu1hGGDzAZwexaq0E9UYuhEMPw//YehjwABACAAUAwwmdQvXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111109ddddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXT111111111111111111111111111111111111111111111111111109ddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT1111111111111//+KwqFuAAjGxTHAxD+UaCRTBT+QSsP5LCteSId4x7cxMItccwsVtVPUL11111111111111111111111111111111111111111111111111109ddddddddddddfGwvf/hIMeDbQBglmE5oseadviBP3CA/M6WyaUkT9HFQCeJk6VlxHf9Q1wgtNuXLAtGi/veZgJhhS+YX+TIZRn7YDD6eJgptq2uXzhH4QgCx/wAGD+CUVptkcPLVfDMAAPAAUBhRMgI+/lnb48AA4ADgKPywEj9e2CWCgpwLusJdYPMvT//gAwDQIJBMvYAAAhNbW1tbW1tbW1tY9QAEGUhyEMU5jGOY5/+AgfodAhtEmNwMC8UuKfDtbW1tbW1tbW1/8f6Ct/ASf5eLcAdCKs/YABQVKl2jf//0CDtcay1tbW1tbW1tbX/x/oK4SuHvEAH0Iqz9gAFBUqXaNxQ7W1tbW1tbW1tf/H90CHBH4e9wAeQyLfmAAQFVpdsy1tbW1tbW1tbX+GP4Q7JS1gAi7vXefLap76YZrrrrrrrrrrrrrr/jD6aCgWgCCDllGFNSltDYECCtQBwBFD4C7IAOBgj0uPdstQdBf9Drh7h+gn8GUYtnnnFu5hSHuDQA8AAQAwqAXD8IwxjmGKcQhJmNkMORBe1tbW1tbW1tclg4YOEumHAAO5EAECkzqXKcTv7hxIPrgNou04w/+HzEiY0gQsFE7q4AuwrxK0twnSSfgbgzAAEBAeQhZB1eAE0oAMEfewwhqn9YAwdQrCfarXujfB/yDhwrhSN47o3Tv8GHSDtLS0tLS0tLS/krN7DoKBgAB9LAAgFJnc8xTC7QNQgvH98SnjU9/6sYjOF2mRaxR//9ngZQpEfrAQJI7rK9JgBQ+XA4qLGe60fx7QcY4DeMvatDWTj/wf3APl/QT8AFyDlhLlOynajKQNwGKAAY+wY4g6v5A4KaUEK5j2xHCP8GHSDIoABG1tbW1tbW1tclNlEJOMumGgAEIS/e4E7nbESHKM+QbphteZpq4cxvBJ4Bxi8Zz4t1Ze4zAXxXqgACAOZsG1/94jbCBTzCaZZ03oahYAAgL0DULs/DL4UKCoJShdoVx88wSrguLJs1EPcWGHoyDsBimIpiFr/+3/aDYoABC1tbW1tbW1tfyRw9Q0KDHABQ/hOW+2OW4ABYfbDNjaD7mnH+94wNKEEL/IwxnRDX+EAQQKwla1namaxP3kQGxWRzAAZrkqBd9JRhhJevDBEln+8QSUYbVdKfuYOKHPDn/b+gn8M5OY7pZTYRrQ2BPAAEA4AEIocbP4CGzcVyYxsrzP4MOkGRQACFra2tra2tra1111111111111111311111111111111111111311111111131111111111311111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111114AAAAKrQZo4HeAK+P5+BLwERmGH/9ArDAw1+MVwOvlh18vxiWol+ngQQxsCDAYMgUACtizEQjNPf/AITzDxhD/DQneAKAu7Ahx4FG5/8MDpDW4NTlgT1+WZEiuAypZtabKruA22CUUB1bUOra+HVtQ6tr/TG4D/+CvAcIpDZbgZMBA0OFXjx04WMc47pf1ARFnBSdREuiXcmiO6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\" type=\"video/mp4\">\n", + " Your browser does not support the video tag.\n", + "</video>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "from scipy.misc import imread\n", - "grid = imread('material/GosperGliderGun.png',flatten=True).astype(int)\n", + "from imageio import imread\n", + "grid = imread('material/GosperGliderGun.png', as_gray=True).astype(int)\n", "grid[grid>0] = ALIVE # values are from 0 to 255 - set everything nonzero to ALIVE\n", "ani = makeImshowAnimation(grid, gameOfLifeSweep, frames=6*15)\n", "displayAsHtmlVideo(ani, fps=15)" @@ -190,65 +269,26 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Step 2: Going parallel with ipyparallel and waLBerla" + "## Step 2: Demonstration with waLBerlas python bindings" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "waLBerla is parallelized using MPI (message passing interface). That means that multiple processes are started, possibly on different machines which all execute the same program and communicate by sending messages. In a normal Python environment we would start multiple Python interpreters all executing the same script using `mpirun`. The following command would run a script using 4 processes:\n", + "waLBerla is parallelized using MPI (message passing interface). That means that multiple processes are started, possibly on different machines which all execute the same program and communicate by sending messages. In a typical Python environment, we would start multiple Python interpreters all executing the same script using `mpirun`. The following command would run a script using four processes:\n", "\n", "\n", "``` mpirun -np 4 python3 my_waLBerla_script.py```\n", "\n", - "\n", - "\n", - "To make use of multiple processes in this IPython environment we use the [ipyparallel](http://ipyparallel.readthedocs.org/en/latest/intro.html) package. \n", - "Therefore you first have to [start an ipyparallel cluster here in the IPython Cluster tab](/tree/ipython-tutorials#ipyclusters). Otherwise the following code will not work.\n", - "\n", - "Now lets test our parallel environment. After importing and initializing *ipyparallel* we only have to \n", - "prefix a code cell with the IPython magic **px** and the code cell will be executed by each process of the cluster." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ipyparallel import Client\n", - "rc = Client()\n", - "numberOfProcesses = len(rc.ids)\n", - "print(\"There are %d processes in your ipyparallel cluster\" % ( numberOfProcesses,))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "%%px\n", - "print(\"Hello parallel world\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "If above cells produce errors, go back to the IPCluster setup to make sure your cluster is running. If everything works you see the hello world message printed by each process in the cluster." + "Using multiple processes is not very convenient in an IPython environment. Thus we only demonstrate here with one process. However, this tutorial can be easily extended to multiple processes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now lets implement the *Game of Life* algorithm in parallel using waLBerla. waLBerla divides the complete domain into blocks. These blocks can then be distributed to the participating processes. We will set up here a simple example where each process gets one block. waLBerla can put multiple blocks per process. This makes sense if the computational load varies for each block, then a process receives either few expensive blocks or many cheap blocks.\n", + "Now lets implement the *Game of Life* algorithm in using waLBerla. waLBerla divides the complete domain into blocks. These blocks can then be distributed to the participating processes. We will set up here a simple example where each process gets one block. waLBerla can put multiple blocks per process. This makes sense if the computational load varies for each block, then a process receives either few expensive blocks or many cheap blocks.\n", "\n", "While blocks are the basic unit of load balancing they also act as container for distributed data. In this *Game of Life* example we have to distribute our grid to the blocks e.g. each block internally stores only part of the complete domain. \n", "The local grids are extended by one ghost layer which are a shadow copy of the outermost layer of the neighboring block.\n", @@ -261,65 +301,57 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, + "execution_count": 8, + "metadata": {}, "outputs": [], "source": [ - "from scipy.misc import imread \n", + "from imageio import imread\n", "import os\n", "\n", "# Read the initial scenario\n", - "initialConfig = np.rot90( imread('material/GosperGliderGun.png',flatten=True).astype(int), 3 )\n", - "initialConfig[initialConfig>0] = ALIVE # values are from 0 to 255 - set everything nonzero to ALIVE\n", - "\n", - "# and send it to all execution engines together with other local variables\n", - "rc[:].push( {'initialConfig' : initialConfig,\n", - " 'numberOfProcesses' : numberOfProcesses,\n", - " 'ALIVE' : ALIVE,\n", - " 'DEAD' : DEAD, \n", - " 'neighborhoodD2Q9' : neighborhoodD2Q9,\n", - " 'gameOfLifeSweep' : gameOfLifeSweep,\n", - " 'cwd' : os.getcwd() } )\n", - "pass" + "initialConfig = np.rot90( imread('material/GosperGliderGun.png',as_gray=True).astype(int), 3 )\n", + "initialConfig[initialConfig>0] = ALIVE # values are from 0 to 255 - set everything nonzero to ALIVE" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Block on rank 0: with offset (0, 0, 0)\n" + ] + } + ], "source": [ - "%%px\n", + "# %%px\n", "import sys\n", "import waLBerla as wlb\n", "import numpy as np\n", "import os\n", "\n", - "os.chdir( cwd ) # change working directory of all engines to working directory of notebook kernel\n", + "# For this tutorial we use only one process. The code can easaly run with more processes and mpirun as pyhton script\n", + "numberOfProcesses = 1\n", "\n", "domainSize = (initialConfig.shape[0], initialConfig.shape[1], 1)\n", "\n", "# We can either specify the detailed domain partitioning ...\n", - "blocks = wlb.createUniformBlockGrid(cellsPerBlock=(domainSize[0]//numberOfProcesses, domainSize[1], domainSize[2]),\n", - " blocks=(numberOfProcesses,1,1), \n", + "blocks = wlb.createUniformBlockGrid(blocks=(numberOfProcesses, 1, 1),\n", + " cellsPerBlock=(domainSize[0]//numberOfProcesses, domainSize[1], domainSize[2]),\n", " periodic=(1,1,1))\n", "\n", - "# ... or let waLBerla do it automatically - \n", - "# if the domainSize is not divisible by the block count the domain is slightly extended\n", - "blocks = wlb.createUniformBlockGrid(cells = domainSize, periodic=(1,1,1))\n", "\n", "# Now put one field (i.e. grid) on each block\n", - "wlb.field.addToStorage(blocks, name='PlayingField', type=np.int, ghostLayers=1)\n", + "wlb.field.addToStorage(blocks, name='PlayingField', dtype=np.int, ghostLayers=1)\n", "\n", "# Iterate over local blocks - in our setup we have exactly one block per process - but lets be general\n", "for block in blocks:\n", - " offsetInGlobalDomain = blocks.transformLocalToGlobal(block, (0,0,0))\n", + " offsetInGlobalDomain = blocks.transformLocalToGlobal(block, wlb.Cell(0,0,0))\n", " myRank = wlb.mpi.rank()\n", - " print(\"Block on rank %d: with offset %s\" % (myRank, offsetInGlobalDomain ))" + " print(\"Block on rank %d: with offset %s\" % (myRank, offsetInGlobalDomain[:] ))" ] }, { @@ -331,13 +363,23 @@ }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAA2cAAAJ6CAYAAACsdDqUAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4yLjIsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+WH4yJAAAZtElEQVR4nO3df6jdd53n8dd7kw6WdcA4SUtoaztIWabImjK3RXD+cNRZOu6w1T+EKYz0D6H+MQEFl6XrP6MLC/PHqPtHBqGuxbDrOhR01iLuj9JVXIehJu3U2lKHinScamiSNaL+49D63j/uEUNNvDf3npvz9p7HAy7nnO/5nnPeufkk5JnvOd9b3R0AAABW65+tegAAAADEGQAAwAjiDAAAYABxBgAAMIA4AwAAGECcAQAADHDwar7Y4cOH++abb7maLwkAADDGE088fr67j1zqvqsaZzfffEv+5rHTV/MlAQAAxrj2mvqHy93nbY0AAAADiDMAAIABxBkAAMAAW8ZZVb2qqr5eVd+oqmeq6iOL7R+uqu9V1ZOLr3fs/bgAAAD703ZOCPLTJG/t7p9U1TVJvlZV/2Nx38e7+y/2bjwAAID1sGWcdXcn+cni5jWLr97LoQAAANbNtj5zVlUHqurJJGeTPNLdjy3uOl5VT1XVg1V1aM+mBAAA2Oe2FWfd/XJ3H0tyY5I7q+oNST6R5PVJjiU5k+Sjl3psVd1XVaer6vS58+eWNDYAAMD+ckVna+zuHyb5SpK7uvvFRbT9LMknk9x5mcc80N0b3b1x5PAlfxA2AADA2tvO2RqPVNVrFtevTfL2JN+qqqMX7fauJE/vzYgAAAD733bO1ng0ycmqOpDNmHuou79YVf+lqo5l8+Qgzyd5396NCQAAsL9t52yNTyW5/RLb37MnEwEAAKyhK/rMGQAAAHtDnAEAAAwgzgAAAAbYzglBAGBfOHTH8V0/x4VTJ5YwCQD8MkfOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAxwcNUDALAeDt1xfNfPceHUiSVMAgAzOXIGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwAAHVz0AsFyH7ji+6hFy4dSJVY/ARSasiWTGupgwAwBcjiNnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAY4uOoBgF84dMfxXT/HhVMnljDJ6vleAOtmGX/v7Za/N2G1HDkDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMMDBVQ8A+8WhO47v+jkunDqxhEn2h2V8L3b7e+L3AwC4mhw5AwAAGECcAQAADCDOAAAABtgyzqrqVVX19ar6RlU9U1UfWWx/bVU9UlXPLS4P7f24AAAA+9N2jpz9NMlbu/uNSY4luauq3pTk/iSPdvetSR5d3AYAAGAHtoyz3vSTxc1rFl+d5O4kJxfbTyZ5555MCAAAsAa29ZmzqjpQVU8mOZvkke5+LMn13X0mSRaX1+3dmAAAAPvbtuKsu1/u7mNJbkxyZ1W9YbsvUFX3VdXpqjp97vy5nc4JAACwr13R2Rq7+4dJvpLkriQvVtXRJFlcnr3MYx7o7o3u3jhy+MguxwUAANiftnO2xiNV9ZrF9WuTvD3Jt5I8nOTexW73JvnCXg0JAACw3x3cxj5Hk5ysqgPZjLmHuvuLVfW3SR6qqvcm+W6Sd+/hnAAAAPvalnHW3U8luf0S2/9fkrftxVAAAADr5oo+cwYAAMDeEGcAAAADiDMAAIABxBkAAMAA2zlb4yiH7ji+6hFy4dSJVY8Aoy3jz+mEP2f75dcxYYZkxvdzwgxwOdYW4MgZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAMcXPUAwP5z4dSJVY+wFPvl1zGF7ycA/GqOnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYoLr7qr3Y7/7uRv/NY6ev2uvBr5tDdxzf9XNcOHViCZOsnu8FALAfXXtNPd7dG5e6z5EzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAMcXPUAwC9cOHVi189x6I7jS5hkd5bx61jGcwAA/Dpx5AwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAAdXPQCwXBdOnVj1CAAA7IAjZwAAAAOIMwAAgAHEGQAAwABbxllV3VRVX66qZ6vqmap6/2L7h6vqe1X15OLrHXs/LgAAwP60nROCvJTkg939RFX9ZpLHq+qRxX0f7+6/2LvxAAAA1sOWcdbdZ5KcWVz/cVU9m+SGvR4MAABgnVzRZ86q6pYktyd5bLHpeFU9VVUPVtWhJc8GAACwNrYdZ1X16iSfS/KB7v5Rkk8keX2SY9k8svbRyzzuvqo6XVWnz50/t4SRAQAA9p9txVlVXZPNMPtMd38+Sbr7xe5+ubt/luSTSe681GO7+4Hu3ujujSOHjyxrbgAAgH1lO2drrCSfSvJsd3/sou1HL9rtXUmeXv54AAAA62E7Z2t8c5L3JPlmVT252PahJPdU1bEkneT5JO/bkwkBAADWwHbO1vi1JHWJu760/HEAAADW0xWdrREAAIC9Ic4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAQ6uegB27tAdx3f1+AunTixpEgAAYLccOQMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABjg4KoHYOcunDqx6hEAAIAlceQMAABgAHEGAAAwgDgDAAAYQJwBAAAMsGWcVdVNVfXlqnq2qp6pqvcvtr+2qh6pqucWl4f2flwAAID9aTtHzl5K8sHu/p0kb0ryp1V1W5L7kzza3bcmeXRxGwAAgB3YMs66+0x3P7G4/uMkzya5IcndSU4udjuZ5J17NSQAAMB+d0WfOauqW5LcnuSxJNd395lkM+CSXLfs4QAAANbFtuOsql6d5HNJPtDdP7qCx91XVaer6vS58+d2MiMAAMC+t604q6prshlmn+nuzy82v1hVRxf3H01y9lKP7e4HunujuzeOHD6yjJkBAAD2ne2crbGSfCrJs939sYvuejjJvYvr9yb5wvLHAwAAWA8Ht7HPm5O8J8k3q+rJxbYPJfnzJA9V1XuTfDfJu/dmRAAAgP1vyzjr7q8lqcvc/bbljgMAALCeruhsjQAAAOwNcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADDAlnFWVQ9W1dmqevqibR+uqu9V1ZOLr3fs7ZgAAAD723aOnH06yV2X2P7x7j62+PrScscCAABYL1vGWXd/NckPrsIsAAAAa2s3nzk7XlVPLd72eGhpEwEAAKyhncbZJ5K8PsmxJGeSfPRyO1bVfVV1uqpOnzt/bocvBwAAsL/tKM66+8Xufrm7f5bkk0nu/BX7PtDdG929ceTwkZ3OCQAAsK/tKM6q6uhFN9+V5OnL7QsAAMDWDm61Q1V9NslbkhyuqheS/FmSt1TVsSSd5Pkk79vDGQEAAPa9LeOsu++5xOZP7cEsAAAAa2s3Z2sEAABgScQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABggC3jrKoerKqzVfX0RdteW1WPVNVzi8tDezsmAADA/radI2efTnLXK7bdn+TR7r41yaOL2wAAAOzQlnHW3V9N8oNXbL47ycnF9ZNJ3rnkuQAAANbKTj9zdn13n0mSxeV1yxsJAABg/ez5CUGq6r6qOl1Vp8+dP7fXLwcAAPBraadx9mJVHU2SxeXZy+3Y3Q9090Z3bxw5fGSHLwcAALC/7TTOHk5y7+L6vUm+sJxxAAAA1tN2TqX/2SR/m+RfVNULVfXeJH+e5A+q6rkkf7C4DQAAwA4d3GqH7r7nMne9bcmzAAAArK09PyEIAAAAWxNnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAQ7u5sFV9XySHyd5OclL3b2xjKEAAADWza7ibOH3u/v8Ep4HAABgbXlbIwAAwAC7jbNO8r+r6vGqum8ZAwEAAKyj3b6t8c3d/f2qui7JI1X1re7+6sU7LKLtviS56XWv2+XLAQAA7E+7OnLW3d9fXJ5N8tdJ7rzEPg9090Z3bxw5fGQ3LwcAALBv7TjOquqfV9Vv/vx6kn+V5OllDQYAALBOdvO2xuuT/HVV/fx5/lt3/8+lTAUAALBmdhxn3f2dJG9c4iwAAABry6n0AQAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA4gzAACAAcQZAADAAOIMAABgAHEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA4gwAAGAAcQYAADCAOAMAABhAnAEAAAwgzgAAAAYQZwAAAAOIMwAAgAHEGQAAwADiDAAAYABxBgAAMIA4AwAAGECcAQAADCDOAAAABhBnAAAAA+wqzqrqrqr6+6r6dlXdv6yhAAAA1s2O46yqDiT5yyR/mOS2JPdU1W3LGgwAAGCd7ObI2Z1Jvt3d3+nuf0ryV0nuXs5YAAAA62U3cXZDkn+86PYLi20AAABcod3EWV1iW//STlX3VdXpqjp97vy5XbwcAADA/rWbOHshyU0X3b4xyfdfuVN3P9DdG929ceTwkV28HAAAwP61mzg7leTWqvrtqvqNJH+c5OHljAUAALBeDu70gd39UlUdT/K/khxI8mB3P7O0yQAAANbIjuMsSbr7S0m+tKRZAAAA1taufgg1AAAAyyHOAAAABhBnAAAAA4gzAACAAar7l35u9N69WNW5JP/wK3Y5nOT8VRoHrpT1yVTWJpNZn0xlbbIqN3f3JX8A9FWNs61U1enu3lj1HHAp1idTWZtMZn0ylbXJRN7WCAAAMIA4AwAAGGBanD2w6gHgV7A+mcraZDLrk6msTcYZ9ZkzAACAdTXtyBkAAMBaGhNnVXVXVf19VX27qu5f9Tysr6p6sKrOVtXTF217bVU9UlXPLS4PrXJG1lNV3VRVX66qZ6vqmap6/2K79cnKVdWrqurrVfWNxfr8yGK79ckIVXWgqv6uqr64uG1tMs6IOKuqA0n+MskfJrktyT1Vddtqp2KNfTrJXa/Ydn+SR7v71iSPLm7D1fZSkg929+8keVOSP138XWl9MsFPk7y1u9+Y5FiSu6rqTbE+meP9SZ696La1yTgj4izJnUm+3d3f6e5/SvJXSe5e8Uysqe7+apIfvGLz3UlOLq6fTPLOqzoUJOnuM939xOL6j7P5j4wbYn0yQG/6yeLmNYuvjvXJAFV1Y5J/neQ/X7TZ2mScKXF2Q5J/vOj2C4ttMMX13X0m2fwHcpLrVjwPa66qbklye5LHYn0yxOJtY08mOZvkke62PpniPyX5d0l+dtE2a5NxpsRZXWKb00gCXEJVvTrJ55J8oLt/tOp54Oe6++XuPpbkxiR3VtUbVj0TVNUfJTnb3Y+vehbYypQ4eyHJTRfdvjHJ91c0C1zKi1V1NEkWl2dXPA9rqqquyWaYfaa7P7/YbH0ySnf/MMlXsvn5XeuTVXtzkn9TVc9n86Mzb62q/xprk4GmxNmpJLdW1W9X1W8k+eMkD694JrjYw0nuXVy/N8kXVjgLa6qqKsmnkjzb3R+76C7rk5WrqiNV9ZrF9WuTvD3Jt2J9smLd/e+7+8buviWb/8b8P939J7E2GWjMD6Guqndk8/3AB5I82N3/ccUjsaaq6rNJ3pLkcJIXk/xZkv+e5KEkr0vy3STv7u5XnjQE9lRV/V6S/5vkm/nF5yY+lM3PnVmfrFRV/ctsnlThQDb/8/eh7v4PVfVbsT4ZoqrekuTfdvcfWZtMNCbOAAAA1tmUtzUCAACsNXEGAAAwgDgDAAAYQJwBAAAMIM4AAAAGEGcAAAADiDMAAIABxBkAAMAA/x8Qj+b4bp1m3AAAAABJRU5ErkJggg==\n", + "text/plain": [ + "<Figure size 1080x864 with 1 Axes>" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], "source": [ - "%%px\n", "import waLBerla.plot as wlbPlt\n", "\n", "import matplotlib\n", @@ -350,35 +392,49 @@ "# Initialize our grid\n", "for block in blocks:\n", " grid = wlb.field.toArray( block['PlayingField'] ).squeeze()\n", - " offsetInGlobalDomain = blocks.transformLocalToGlobal(block, (0,0,0))\n", + " offsetInGlobalDomain = blocks.transformLocalToGlobal(block, wlb.Cell(0,0,0))\n", " blockSize = grid.shape[:2]\n", " xBegin, xEnd = offsetInGlobalDomain[0], offsetInGlobalDomain[0] + grid.shape[0]\n", " yBegin, yEnd = offsetInGlobalDomain[1], offsetInGlobalDomain[1] + grid.shape[1]\n", " grid[:,:] = initialConfig[xBegin:xEnd, yBegin:yEnd]\n", "\n", - "wlbPlt.scalarField( blocks, 'PlayingField', wlb.makeSlice[:,:,0] )" + "wlbPlt.scalar_field( blocks, 'PlayingField', wlb.makeSlice[:,:,0] )" ] }, { "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "<video controls width=\"80%\">\n", + " <source src=\"data:video/x-m4v;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQABOidtZGF0AAACcgYF//9u3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMSBjZGU5YTkzIC0gSC4yNjQvTVBFRy00IEFWQyBjb2RlYyAtIENvcHlsZWZ0IDIwMDMtMjAyMCAtIGh0dHA6Ly93d3cudmlkZW9sYW4ub3JnL3gyNjQuaHRtbCAtIG9wdGlvbnM6IGNhYmFjPTAgcmVmPTIgZGVibG9jaz0xOjA6MCBhbmFseXNlPTB4MToweDExMSBtZT1oZXggc3VibWU9NyBwc3k9MSBwc3lfcmQ9MS4wMDowLjAwIG1peGVkX3JlZj0xIG1lX3JhbmdlPTE2IGNocm9tYV9tZT0xIHRyZWxsaXM9MSA4eDhkY3Q9MCBjcW09MCBkZWFkem9uZT0yMSwxMSBmYXN0X3Bza2lwPTEgY2hyb21hX3FwX29mZnNldD0tMiB0aHJlYWRzPTI0IGxvb2thaGVhZF90aHJlYWRzPTQgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MCB3ZWlnaHRwPTAga2V5aW50PTI1MCBrZXlpbnRfbWluPTI1IHNjZW5lY3V0PTQwIGludHJhX3JlZnJlc2g9MCByY19sb29rYWhlYWQ9NDAgcmM9Y3JmIG1idHJlZT0xIGNyZj0yMy4wIHFjb21wPTAuNjAgcXBtaW49MCBxcG1heD02OSBxcHN0ZXA9NCBpcF9yYXRpbz0xLjQwIGFxPTE6MS4wMACAAAAXkGWIhAvyYoAAqcScnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJydddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddf+uFWMXsNcABGPxxRmZUtRbuGf1QkOMehppXZgvn+AgZkRHlLaR3jZ4RRp2TCS3PvqSJANmyEAo+zOC8FRE2J9mMWf9wwMxP6AspOW+L/+82Y1yM6qQR3O/GZjkhSnc/hHD/LgAJkZhOhyDCd4w8yGGYAAIAwDEkS3KhgAMBynwErJVJS7LDBTS2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra2tra4+cP+H8ABILNCIgjz6RZPwdMNhrrrrrrrrrrrrrvrpxQBvvvvvvvvvvvvvvvvvvvvvv/iH/gsBQA4RCATLfEAE0QL59/+f/4LIAQKRj6LT0//+GVQ18+rJC9yMFN9999999999999999999999999QTOmCeuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrr+A//hoFEAHeyRjRl1e95WXwJARAYjuF2WWHJq/xD/0CwgHCCoZfA8TgSKwZKX4l3gGIf+gWQA5NMMVFh+HK/uBIkBU8Gpy9xHf5//ho78AA5tJtU+v+IUw18nZc5IE3dMEdS11111111111111111111111109dddddddddddddddPXXXXXXXXXXXxD//BWCQDgIDBbL4iABIYAARQXZZOy/JpNwuhsxkxnMZMZ/9X6fchkhnnD/+wVmAArlGaIx7Rfgw5J5IQpubzwqHa6666/gP/4KwXQEKNmetXwcQok5YH0duak00PDAP/QaPAFYvDiLA+2Hf4D4FBKDCRgwlLXwde8AxD/0CyBwQZrL4EgkAojwOmcvxHeAbR/6BZADKqSSWr3/AW4xL9viHD/2CwFIOAevJ45S8HD3wcPfA4jS5DiNLieuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrp666666666/+H/BYCKABEFuIpj6J4Nmt5YdY4f/oFZgavGgUOAxLol3iOiO+IBAP/grgOCYfZb4eAONAKEdEd22+v//YKzgAzCucun/77/z154daeoI6666/gMP/DQKIATaLGrIq7X/rAkEwNHDL490mbmqZofj//BXgBrRiVle7z5EOzMdfx9PMzG56SC2np66lrrrrrrr4h//grDwADdMmCZ8hQ53FgoLDBoBIeADhKA1TwdJ25gobjjrIbQp6w//sFYRAATyOIh1IY4iUhhwLJCLgE9PZZ5ERLmBC0897KdzUM11111111111109ddddddddddddf/8FXhUMQAEYaxxR2aUtRr+m/GzwRRpuRCavFbCGGIvjySTKQf/fAIQMSyiKbpS2HzXIUDrqq7Mjld/8whDxdcBvsLD//hfYsP4ADAcp0A1dKpMbZ6WmF66666666//+HBYCbgcECC0BpcMvpW7lZocfH/QLBHAcRF6Y/6pp8Xh/LB4OIiQti3tt5mC0UBiACs/gGAf6BUCAQkhFoSTIkmcVYq/h//grFnY4DoAQx99+oZr/xw/grBVxQABALgZYIEAxvi1nLGOdGXxaD4YAZYiECqByzIOWZwdIyDpGdr4jgEP4Kw1wOECsQBkIsNZRZ21PJkl3McRS1th8B//gr8HBAikMdQ9wkObZW7mbzQp6eoJaenrqWuuuuuuuniOjjTBQ6gprrrrrrrrrrrrp6666666666666+u7//CQU+SITMCoRnKCTeCMOwxe1j2kJSxN98RQynmg7zWt8NRReTP+PgGwWFwHAAJAMHARlsILhSAhIEeDw94kO7Xx5/Dw4bAAYpShI5+QvgYMXA5WDLYgHcYuCTueCYfrrrrrp5mCrKZgpFAxAZGAANf/h/hsFWABndNoXYhAUMkhlfxBBISNNiHX00/n//YbLgBgKZ5H6f/92Kuv1BX8fAP4bBVgARVc0Qf2MUasE/AwsCDw43xzp7DTTX44BD+CsuoDgI5YdLBhQWG5RR3EHnTyxizEOivFoafI59pr4n8P4bCHACOLRRleXnEFIS0M9nMLdf4f+w0F42g9/jrSsoO7EHdj54BD9BoMcAGZV0+zfDgfoAlXof3q38FwCH6G+AA2bI3lGN2jYxTGWcImyCVODx6/Fv4BiH+gWEwHEZQSWwhJMK+iQ7xV/AM//BZwAzuimrT/8R2Rie7t9PTBbUtdddddddeEwwD/grD2AAolINGhlFtMDdgwF4OKhOBqnh3goNxw72uEv/8FYsrMAB4RoUp2IxRV78GELMwIoAS0S0LP+BOL3nv+mFa666666666666euuuuuuuuuuuuuuunm4+mYLNUwV1111109PT1+YYB/wVguwAwDJb2u7/iXNFsT3bb+3/9grE4Azu/97/f17/UFPoGAf8FYJsAEK1rvv/ngwVi6C9jPO8a4538BwCH8FfgOBGKD5YMFTQyhxfOIOHThYy0xPRfOhYhzN88Ahj48ZwAGSKJib1a5ZGPvwOFChrFAo/9HnTzDRiHRX8H//grJwAwrm3tdoB2mpl+/9sFP0wCP6Ggm4Ay+73v9/L794SmgCYnvb+AYh4dAs4DhMMPlsIL/BKnB494k78AzD/hzgAUkpMTerXf//gwYa4HkwJYQ6T/5Tb+AbQ/wWcAZ3/97/f/T++30wV1111111110tLa111111111111109ddddddddddddddf4RD/gsDGDgAFAABAFIwlBFAkFIHmFL8Gzl9r4wt/4LDYADKclD7vFK4Y1RABiUtkODbl30w7XXXXX/CP/BYCDgCgmRgEFIAo3NYS2m80PgGAfDQLBXAFE0whUAfbDlqauXW8XICnlgxxRJoul3m026YLv/D/BWDLABzjNEMNxer25BEAREIQ0FmWTMt8M2m1fn//YbE4AFcozRGaUbwYyv68kOeFMENr8cA/4KwUcHCBSIMXB1QjtBLl+bl3OiPF9v/4K/ADFe3t6vHKGiP5/zQVg4ABEL0HJ13/4h/wWAkwcCApGBVgHhXL8u/ANvh4LI8gwBBNNs5mevHaS5c8u8zBPJV111111111111111111111111109ddddddddddddddczyRrXS1111110v//DgsBFH6QAV0kzPQsq5ZYdcXEPJBycR2bTb/CIYAH9gr4DhONktiAIiEC6Lpd//4f2CsSRmAApppGTYuiqHfyQ7zMmemCeultbWuuu1ta666666666666666666666666666euuuuuuuuuuuuv//+FQtwAG0RCFcrsULL6J/iKgaYNR4badLBmyUwABADTQALoSt58umF6666666666Wl/8AwDhEPCASMQRtrh/D+wV34Atzw5IUw/XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT11111111111118ov/+Egt8kAF1KaAHgrG52w6TGEIYvxdwx69aIIZK8PcsMWvbP7//8P/+CL4ADSvEt9utmiX5swY6WoXrrrrrrrrrrrpaWlrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666euuv//iGC4FwAGPzSH5iOGsLCYwDgI9+v/9fBdABNy2KN+u78yDXbXumC+uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrp6664pgwmt7+Kdtta+mC2pa66666666666666666666666666666666666666666666euuuuuuuuuuuuuuunrrrp6YMHTBbUtddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXT111/h/gGC4FwAGbbfKfBjA6xXHerb/4Bv4LoAJPcxVk/3f8qYud1R126YL6666666666666666666666666666666666666666666666euuuuuuuuuuuuv5IrFH+EgxAAbSIRxEZiBJHD/woNr1s4TT2PrLCOgmoGbmHhNbUkEf74BI6BtbZKSxmW/xlxkAMVFHsGwplA9e9FAKvqeosc9fE44f/8Lw4YADStNRbdatNFzVlunS0wzXXXS2tddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXT11111111111111111111111111111111111111111111111111109dddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT11111111111111109dddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXT11111111111111111111111111111111111111111111111111109ddddddddddddf+uEAHsNcABJELflgChiOU4C+4CDQMZisO6wG8HaHtNk6Ww/bGgjqNyLPHLn/rb+RjSzOQfMTGDMLd2p1WF5/8/8P/+CQvgANK8S326WaJfmvG2aWoXrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrp6666666666666666666666666666666666666666666666666666euuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666666euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrr/xXgKI1hjgAMP4yDe+1KEvXZ7WgzDWWSc4k3aARMnTJtc/n14AAgDgDXduyQFWAfgA9uKJwMlP+kQx4oKMWRmI6s8bx2VyAEQVd2RzAzCVxeqzTtbP+15AiemIYxP//sEsABERmZmRkRERnh/DAAodhoJb7Vhoqfhh9LTDNdddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXfXT11111111111111111111111111111111111111111111111111109dddddddddddddddPXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXT11111111111111109dddddddddddddddddddddddddddddddddddddddddddddddddddPXXXXXXXXXXXXXXXT11111111111111111111111111111111111111111111111111109ddddddddddddf//ECghCwACZEMroIzEvSxifIzERlOdSDKetXkZiIynP2GQtfeLBk4OSI7dBJAaynw/Db4JIcMAAj+CKkoazjaj/zqWoXrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666/yL/4fCmhOoz1or6c/StcEhxRbKEP8IPXpG8PH//YIoY8AA0AHA4gmfqYVrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666766euuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuunrrrrrrrrrrrrrrrp6666666666666666666666666666666666666666666666666666euuuuuuuuuuuuuuunrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrp6666666666666///jBCEsACILcRTNkTsxGIHTwj6Sf75dMJ11111111111111111111111111111111111111111111111111109ddddddddddddf7Cn/h8LYoh2ph+Lkj+7zhj5M2wmNmw4LADkaF4roUmcROgTHOCnlPUKcrD1+hj/CAZ4YADDuEp1vlmCXpr+YAAWAHBzyZAk/Xu+PAALACg4rLUsACGUszACAL1aCCKX/wAYBwSWoAAAg4aZPvvvvvvvvhPAAQ3Z2ZndmZ2d/+zgAYylmYAQBerQRh+vvvvvvvvv/8f8EvgAJxD8/QAKESlVQj3//8EHLTRvvvvvvvvv/8f8M+AAnEPy9AAoRKlVCONU9fffffffff/4/4JfAASjF7cgAQInKqpHr77777777/4Y/hDPfAJm79v9TC9dddddddddddddf8f6QQUCnwId7iHJ/1wfAppGoDgMoTIXZABwwi/USy5XxEP3IdQ/f+gn8NxHq0sp6sU7lsDQDwAKKkFw+CIYIxRCFM7yKX//ww6QVFANra2tra2tra5LBwwcJdMNAAd0gCCtnfYhjd/cOSH/gbTcmY/+USSY0gRYc3dXAVQpwUqkxeQSoG4zAAEAYWRSCDq8APSgDCNu1MWhffrAMOgznrsq9Jvv/UMoqjG7KcNxO9/0g2KAbW1tbW1tbW1/JWD2DQUCwAGRAEDtm69yENtB8Q3m+h18i//1QyCUW6RfmP//U8G7hq20Dvis1U9k4Ax44FMkr0o4NtrQ4hQbTty+Crkn/g/uH5f0E/AF2FeJWluE7ST4DcGYAAgIDyEKIOr+QcOFcKRvHdG6d/gw6QXFANra2tra2tra5KbKASfLphoABEFecwC/OdJyKf5GaQXKNb/hnL4S4AYI+blBCSCbXgvFXgA7rh9f3eT8Q5Ll0iSJnQ0OAAIBISAuH5j8c4CQyosoN2pzL/HxRZfyVN//Bh6aPgEIjoRnp/+380g2KANra2tra2tra/kjh6hoUGOACj0EjnpDO4ABZ9IYs+A+jEl+9ph4wZ6z+/juT33ECEOxmVhtjaxfvUGiplYAZav4bPMCYI5cMRBH64hYwLL2ShHDvPd4c/7f0EygCZW5CullJjCtDYXgACAQAEdA42fwEJm0rkxS5TlfwYdIKigDa2tra2tra2tdddddddddddddddd9ddddddddd9dddddddddd9ddddddddd9dddddddddd9dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddeAAAADAkGaOBfgCKOLDXABA7/+rv7MX7nx3oQH+6jWA14rwHAXzJkHAXzJkHAXzJgKhLDMNHgkcEx4I5TvBqficBEYQQSDDLIxQ/LXy/BmllNL9PAghhBbtgQYDBgigBlSREiWr3/7gEJ7wETHC9VAECZmAQQgqtX/VcGoQQoViISGAoS6Jd00/sREyQmSxMkOteY3AYf+CskByMjy2wdBQQDG+PdLeqa6gIiJOCtT6fcmk3T+heKAwULDt4haO8V2GACP1wd/nH/BUbHCH+gVBBKvTT4tgrjsfmCAYB/wVAqEVLFWKvTT/BMfAcEUlqZg4IpLUzBwRSWpneU2P/+CohFx/vjHfj2CmSvf9cuaH/+wVhaZTp7HY5Xyvo7C+fqAiZxiwOSrkOSrkHW+DreDI3/8OCwOcAJNGZkIZ67RvvCzc5oTY4XD+g19yXgBmrSVLtI7EOhEOvpk/i4KYGwQa8n+AiAETmC3/+CsEnAGd3/vf7+dVf87BTn5TQngH+hoLuADD+9XG+/vAzYC1EO9PmwHAIfxvgCdILGKgdio9afRYchwdVWin9VXNlWyw0X+Dj9wieCeA5EyJmBBVEo/exVMpVPqNjC//QLC4AYVzbbXa8AkBcUb3l+DLkwOCDCUEAnmWJXR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\" type=\"video/mp4\">\n", + " Your browser does not support the video tag.\n", + "</video>" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ - "%%px\n", "communication = wlb.createUniformBufferedScheme( blocks, 'D2Q9')\n", "communication.addDataToCommunicate( wlb.field.createPackInfo( blocks, 'PlayingField') )\n", "\n", "def runTimestep():\n", " communication()\n", " for block in blocks:\n", - " grid = wlb.field.toArray( block['PlayingField'], withGhostLayers=True )[:,:,1,0]\n", + " grid = wlb.field.toArray( block['PlayingField'], with_ghost_layers=True )[:, :, 1]\n", " gameOfLifeSweep( grid )\n", " \n", "\n", - "ani = wlbPlt.scalarFieldAnimation( blocks, 'PlayingField', wlb.makeSlice[:,:,0], runFunction=runTimestep, frames=100 )\n", + "ani = wlbPlt.scalar_field_animation( blocks, 'PlayingField', wlb.makeSlice[:,:,0], run_function=runTimestep, frames=100 )\n", "displayAsHtmlVideo( ani, fps=30, show=(wlb.mpi.rank()==0) )" ] } @@ -399,9 +455,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.5.1" + "version": "3.8.2" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 02 - LBM.ipynb b/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 02 - LBM.ipynb deleted file mode 100644 index 1ec91a5cc..000000000 --- a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 02 - LBM.ipynb +++ /dev/null @@ -1,254 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": { - "collapsed": false - }, - "source": [ - "# waLBerla Tutorial 02: LBM Setup\n", - "\n", - "In this tutorial we set up a basic lattice Boltzmann simulation of a periodic channel.\n", - "\n", - "First we create a simple block structure, same as in the last \"Game of Life\" tutorial." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "from waLBerla import *\n", - "from material.matplotlib_setup import *\n", - "\n", - "blocks = createUniformBlockGrid( cells=(500,200,1), periodic=(1,0,1) )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "For LBM we have the choice of different lattice models. A lattice model in waLBerla consists of:\n", - "- a stencil that defines the cell neighborhoods. In this tutorial we use a two dimensional D2Q9 stencil.\n", - "- a force model to use volume forces in the domain. For our setup we need a constant volume force to drive the channel and make use of the \"SimpleConstant\" model. \n", - "- a collision model defining the LBM collision operator. Her we use SRT (BGK), however the two relaxation time (TRT) model is also supported and for the D3Q19 model a MRT implementation is available as well\n", - "\n", - "With the lattice model a pdf field is created and added to all blocks. Additionally we create optional adaptors for velocity and density. These adaptors behave similar to fields, however no memory is required for them, the values are computed on-the-fly from the pdfs.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "omega = 1.3\n", - "collisionModel =lbm.collisionModels.SRT(omega)\n", - "forceModel = lbm.forceModels.SimpleConstant( (1e-5,0,0) )\n", - "latticeModel = lbm.makeLatticeModel(\"D2Q9\", collisionModel, forceModel)\n", - "lbm.addPdfFieldToStorage(blocks, \"pdfs\", latticeModel, \n", - " velocityAdaptor=\"vel\", densityAdaptor=\"rho\", initialDensity=1.0)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To store geometry information a flag field is created and used as input to the LBM boundary handling:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "field.addFlagFieldToStorage( blocks, 'flags')\n", - "lbm.addBoundaryHandlingToStorage(blocks, 'boundary', 'pdfs', 'flags')" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we define the setup of our channel. At the northern and southern domain borders no-slip boundaries are required.\n", - "To set up the boundaries the distributed nature of the domain has to be taken into account. \n", - "When iterating over the blocks we only get the locally stored blocks. So this loop is automatically parallelized when using multiple MPI processes. For each block we first check if it is located at the border of the global domain, and if so, we set the border slice to no-slip. When defining the slice, the additional __'g'__ marker is used, to place the boundary in the ghost layer.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "def setBoundariesChannel( blocks, boundaryHandlingID ):\n", - " for block in blocks:\n", - " b = block[ boundaryHandlingID ]\n", - " if block.atDomainMinBorder[1]:\n", - " b.forceBoundary('NoSlip', makeSlice[ :, 0, :, 'g'])\n", - " if block.atDomainMaxBorder[1]:\n", - " b.forceBoundary('NoSlip', makeSlice[ :,-1, :, 'g'])\n", - " b.fillWithDomain()\n", - "setBoundariesChannel( blocks, 'boundary' )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally a LBM sweep functor is created, making use of the already created pdf and flag field." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "sweep = lbm.makeCellwiseSweep(blocks, \"pdfs\", flagFieldID='flags', flagList=['fluid'])" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Since we have set our domain to be periodic in x-direction,the east and west boundary are taken care of by the ghost layer exchange. Here the communication is set up as explained in the previous tutorial. " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "communication = createUniformBufferedScheme( blocks, 'D2Q9')\n", - "communication.addDataToCommunicate( field.createPackInfo( blocks, 'pdfs') )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "One timestep consists of ghost layer communication, boundary handling and an LBM stream-collide step" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def run( timesteps ):\n", - " for t in range(timesteps):\n", - " communication()\n", - " for block in blocks: block['boundary']()\n", - " for block in blocks: sweep.streamCollide( block )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "To get a more interesting result we place an airfoil shaped object inside our channel. This geometry is loaded from an image placed in the 'material' subfolder. You can upload different images and simulate the flow around these objects:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "from waLBerla.geometry_setup import *\n", - "setBoundaryFromBlackAndWhiteImage(blocks, \"boundary\", makeSlice[0.25:0.75, 0.3:0.6 ,0.5], \n", - " \"material/wing.png\", \"NoSlip\")" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Next we create a video of the density distribution in the channel ( which is proportional to pressure in LBM). Before creating a frame for the video we let the simulation run for 10 timesteps, then we set the density inside the object to NaN to get a better looking plot" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def setByMask( blocks, targetField, targetValue, flagField, flagNames ):\n", - " for b in blocks:\n", - " mask = 0\n", - " for flagName in flagNames:\n", - " mask |= b[flagField].flag(flagName)\n", - "\n", - " targetArr = field.toArray( b[targetField], True )\n", - " flagArr = field.toArray( b[flagField] , True )[:,:,:,0]\n", - " targetArr[ np.bitwise_and( flagArr, mask ) > 0, : ] = targetValue\n", - "\n", - "\n", - " \n", - "def visualizationStep():\n", - " run(10)\n", - " # Set pdfs to NaN in NoSlip cells to better see the obstacle in the visualization:\n", - " setFieldUsingFlagMask(blocks, 'pdfs', np.NaN, 'flags', ['NoSlip'] )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "import waLBerla.plot as wplt\n", - "\n", - "run(700) # run the simulation until flow field has stabilized - then no colormap rescaling is required\n", - "ani = wplt.scalarFieldAnimation( blocks, 'rho', makeSlice[:,:,0.5], visualizationStep, frames=300)\n", - "displayAsHtmlImage(ani)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.1" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 03 - LBM with extensions.ipynb b/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 03 - LBM with extensions.ipynb deleted file mode 100644 index e1787ea40..000000000 --- a/python/waLBerla_docs/ipython/ipython-tutorials/Tutorial 03 - LBM with extensions.ipynb +++ /dev/null @@ -1,272 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# waLBerla Tutorial 03: LBM Extensions\n", - "\n", - "\n", - "We start with the LBM simulation of an airfoil from last tutorial. In this tutorial we show how the boundary conditions can be set in a flexible way, by generating the airfoil geometry from an analytic description. Additionally we add some evaluation of force acting on the airfoil.\n", - "\n", - "## A) Programmatic Boundary setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from waLBerla import *\n", - "import waLBerla.plot as wplt\n", - "from waLBerla.geometry_setup import *\n", - "import numpy as np\n", - "import itertools\n", - "from IPython import display\n", - "from material.matplotlib_setup import *" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Instead of loading the airfoil from an image file, we use the [NACA analytical description](https://en.wikipedia.org/wiki/NACA_airfoil) to generate the geometry. The following function is just an implementation of the NACA airfoil description from Wikipedia. Additionally the airfoil can be rotated afterwards. The resulting array has value 1 in cells overlapped by the airfoil and zero otherwise." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": true - }, - "outputs": [], - "source": [ - "def makeNacaAirfoil( length, thickness=30, angle=0 ):\n", - " import scipy\n", - " import scipy.ndimage \n", - " def nacaAirfoil(x, thickness,chordLength):\n", - " xOverC = x / chordLength\n", - " y_t = 0\n", - " coeffs = [ 0.2969, -0.1260, - 0.3516, 0.2843, -0.1015 ]\n", - " for coeff, exponent in zip( coeffs, [ 0.5, 1,2,3,4 ] ):\n", - " y_t += coeff * xOverC ** exponent\n", - " y_t *= 5 * thickness/100 * chordLength\n", - " return y_t\n", - "\n", - " domain = np.zeros( (length, int(length*thickness/100) ) )\n", - " it = np.nditer( domain, flags=['multi_index'], op_flags= ['readwrite'] )\n", - " while not it.finished:\n", - " x,y = it.multi_index\n", - " y -= domain.shape[1]/2\n", - " if abs(y) < nacaAirfoil( x, thickness, domain.shape[0] ):\n", - " it[0] = 1\n", - " it.iternext()\n", - " domain = np.rot90( domain,1 )\n", - " domain = scipy.ndimage.interpolation.rotate( domain, angle=-angle)\n", - "\n", - " domain[ domain > 0.5 ] = 1\n", - " domain[ domain <= 0.5 ] = 0\n", - " domain = domain.astype( np.int32 )\n", - " return domain" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "from ipywidgets import interactive\n", - "def showAirfoil( thickness=10, angle=20 ):\n", - " wplt.style.use('ggplot')\n", - " wplt.imshow( makeNacaAirfoil(300, thickness, angle) )\n", - "widgets = interactive(showAirfoil, thickness=(5,50,1), angle=(-45,45, 1))\n", - "display.display(widgets)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "airfoilArr = makeNacaAirfoil( length=200, **widgets.kwargs )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "def setBoundariesChannel( blocks, boundaryHandlingID ):\n", - " for block in blocks:\n", - " b = block[ boundaryHandlingID ]\n", - " if block.atDomainMinBorder[1]:\n", - " b.forceBoundary( 'NoSlip', makeSlice[ :, 0, :, 'g'] )\n", - " if block.atDomainMaxBorder[1]:\n", - " b.forceBoundary( 'NoSlip', makeSlice[ :,-1, :, 'g'] )\n", - " b.fillWithDomain()\n", - "\n", - "\n", - "# Lattice Model Setup\n", - "omega = 1.7\n", - "domainSize = ( airfoilArr.shape[1]*2, airfoilArr.shape[0] * 2 )\n", - "blocks = createUniformBlockGrid( cells=(500,200,1), periodic=(1,0,1) )\n", - "collisionModel =lbm.collisionModels.SRT( omega )\n", - "forceModel = lbm.forceModels.SimpleConstant( (1e-5,0,0) )\n", - "latticeModel = lbm.makeLatticeModel( \"D2Q9\", collisionModel, forceModel )\n", - "lbm.addPdfFieldToStorage( blocks, \"pdfs\", latticeModel, velocityAdaptor=\"vel\", densityAdaptor=\"rho\", initialDensity=1.0 )\n", - "field.addFlagFieldToStorage( blocks, 'flags' )\n", - "lbm.addBoundaryHandlingToStorage( blocks, 'boundary', 'pdfs', 'flags' )\n", - "\n", - "# Boundary Setup\n", - "setBoundaryFromArray( blocks, 'boundary', makeSlice[0.3:0.7, 0.3:0.7 ,0.5], airfoilArr, { 1: 'NoSlip' }, resizeFunc=binaryResize )\n", - "setBoundariesChannel( blocks, 'boundary' )\n", - "\n", - "sweep = lbm.makeCellwiseSweep( blocks, \"pdfs\", flagFieldID='flags', flagList=['fluid'] )\n", - "\n", - "# Communication\n", - "communication = createUniformBufferedScheme( blocks, 'D3Q19')\n", - "communication.addDataToCommunicate( field.createPackInfo( blocks, 'pdfs') )\n", - "\n", - "def run( timesteps=10 ):\n", - " for t in range(timesteps):\n", - " communication()\n", - " for block in blocks: block['boundary']()\n", - " for block in blocks: sweep.streamCollide( block )" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "run(100)\n", - "setFieldUsingFlagMask(blocks, 'pdfs', np.NaN, 'flags', ['NoSlip'] )\n", - "ani = wplt.scalarFieldAnimation( blocks, 'rho', makeSlice[:,:,0.5], runFunction=run )\n", - "displayAsHtmlImage( ani )" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "## B) Evaluation" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "class ForceCalculationMasks:\n", - " @staticmethod\n", - " def addToBlock(block, blockStorage):\n", - " pdfFieldArr = field.toArray(block['pdfs'])\n", - " flagFieldArr = field.toArray(block['flags'])[:,:,:,0]\n", - " directions = block['pdfs'].latticeModel.directions\n", - " maskArr = np.zeros( pdfFieldArr.shape, dtype=bool )\n", - " pdfDirectionArr = np.zeros( list(pdfFieldArr.shape) + [3] )\n", - "\n", - " fluidFlag = block['flags'].flag(\"fluid\")\n", - " noSlipFlag = block['flags'].flag(\"NoSlip\")\n", - "\n", - " innerPartOfDomain = itertools.product( range(2, maskArr.shape[0]-2),\n", - " range(2, maskArr.shape[1]-2),\n", - " range(0, maskArr.shape[2] ) )\n", - "\n", - " for x,y,z in innerPartOfDomain:\n", - " if flagFieldArr[x,y,z] & fluidFlag:\n", - " for dirIdx, dir in enumerate(directions):\n", - " nx, ny, nz = x+dir[0], y+dir[1], z+dir[2]\n", - " if flagFieldArr[nx,ny,nz] & noSlipFlag:\n", - " maskArr[x,y,z,dirIdx ] = True\n", - " pdfDirectionArr[x,y,z,:] = dir\n", - " return ForceCalculationMasks( maskArr, pdfDirectionArr )\n", - "\n", - " def __init__(self, maskArr, pdfDirectionArr):\n", - " self._maskArr = maskArr\n", - " self._pdfDirectionArr = pdfDirectionArr\n", - "\n", - " def calculateForceOnBoundary(self, pdfField):\n", - " force = np.array([ 0.0 ] * 3)\n", - " pdfFieldArr = field.toArray( pdfField )\n", - " for i in range(3):\n", - " fArr = pdfFieldArr[ self._maskArr ] * self._pdfDirectionArr[self._maskArr,i]\n", - " force[i] += np.sum( fArr )\n", - " return force\n", - "\n", - "def calculateForceOnBoundary( blocks ):\n", - " force = np.array( [ 0.0 ] * 3 )\n", - " for block in blocks:\n", - " force += block['ForceCalculation'].calculateForceOnBoundary(block['pdfs'])\n", - " return np.array( mpi.reduceReal( force, mpi.SUM ) )\n", - "\n", - "blocks.addBlockData('ForceCalculation', ForceCalculationMasks.addToBlock)\n", - "pass" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": { - "collapsed": false - }, - "outputs": [], - "source": [ - "lifts = []\n", - "\n", - "for i in range(100):\n", - " run( 10 ) \n", - " plt.subplot(2,1,1)\n", - " wplt.scalarField( blocks, 'rho', makeSlice[:,:,0.5] )\n", - " plt.subplot(2,1,2)\n", - " f = calculateForceOnBoundary( blocks )\n", - " lifts.append( f[1] )\n", - " wplt.plot( lifts, color='b' )\n", - " wplt.ylim([0,0.15])\n", - " wplt.xlim(0 , 100 )\n", - " wplt.title(\"Lift\")\n", - " display.display( wplt.gcf() )\n", - " display.clear_output(wait=True) " - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.5.1" - } - }, - "nbformat": 4, - "nbformat_minor": 0 -} diff --git a/python/waLBerla_docs/modules/blockforest.rst b/python/waLBerla_docs/modules/blockforest.rst index f2ce559e6..ccd463bae 100644 --- a/python/waLBerla_docs/modules/blockforest.rst +++ b/python/waLBerla_docs/modules/blockforest.rst @@ -8,21 +8,23 @@ Reference ========= -.. py:function:: createUniformBlockGrid(cells, cellsPerBlock, blocks, periodic=(0,0,0), dx=1.0, oneBlockPerProcess=True) +.. py:function:: createUniformBlockGrid(blocks, cellsPerBlock, dx=1, oneBlockPerProcess=True, periodic=(0,0,0), keepGlobalBlockInformation=False) - Creates a new uniform StructuredBlockStorage. Similar to cpp function createUniformBlockGridFromConfig. - Specify either cells or (cellsPerBlock and blocks). - - :param cells: 3-tuple with total numbers of cells in x,y,z direction. The returned BlockStorage may have - more cells if the cell count in a dimension is not divisible by the number of processes. - If this parameter is set, cellsPerBlock and blocks must not be set. - :param cellsPerBlock: 3-tuple with total number of cells per block in x,y,z direction. - If this parameter is set, also blocks has to be set, but not cells - :param blocks: 3-tuple with total number of blocks in x,y,z direction. - When using this parameter you also have to pass cellsPerBlock. - :param periodic: Periodicity of the domain in x,y,z direction - :param dx: Side length of a single cell. - :param oneBlockPerProcess: If True, each process gets one block. If False, all blocks are put to one process. - The second option makes only sense for debugging or testing. + Creates a new uniform StructuredBlockForest. Similar to cpp function blockforest::createUniformBlockGrid. + Specify blocks and cellsPerBlock. + + :param blocks: 3-tuple with total number of blocks in x,y,z direction. + When using this parameter you also have to pass cellsPerBlock. + :param cellsPerBlock: 3-tuple with total number of cells per block in x,y,z direction. + If this parameter is set, also blocks has to be set, but not cells + :param dx: Side length of a single cell. + :param oneBlockPerProcess: If True, each process gets one block. If False, all blocks are put to one process. + The second option makes only sense for debugging or testing. + :param periodic: Periodicity of the domain in x,y,z direction + :param keepGlobalBlockInformation: If true, each process keeps information about remote blocks (blocks that reside + on other processes). This information includes the process rank, the state, and + the axis-aligned bounding box of any block (local or remote). [false by default] + + \ No newline at end of file diff --git a/python/waLBerla_docs/modules/core.rst b/python/waLBerla_docs/modules/core.rst index c837f3a37..c1253ba29 100644 --- a/python/waLBerla_docs/modules/core.rst +++ b/python/waLBerla_docs/modules/core.rst @@ -27,11 +27,6 @@ Block Structure Creates a CellInterval from a given Python slice e.g. ``CellInterval.fromSlice( makeSlice[0:2,0:1,0:4] )`` - .. py:method:: __init__( minCell, maxCell ) - - Construct a cell interval given the minimum and maximum coordinate (cell). - The maxCell itself is included in the interval. - .. py:method:: __init__( xMin, yMin, zMin, xMax, yMax, zMax ) Constructs a cell interval using 6 integers corresponding to begin and end of the @@ -186,13 +181,10 @@ Block Structure -.. py:class:: StructuredBlockStorage - - StructuredBlockStorage represents a collection of blocks. It is an abstract class - and can not be created directly. A concrete implementation like the blockforest can - instantiate a StructuredBlockStorage. See blockforest.createUniformBlockGrid. - +.. py:class:: StructuredBlockForest + StructuredBlockForest represents a collection of blocks. It can be created using the createUniformBlockGrid method. + .. py:method:: getNumberOfLevels() .. py:method:: getDomain() @@ -201,8 +193,7 @@ Block Structure .. py:method:: mapToPeriodicDomain( x,y,z ) .. py:method:: mapToPeriodicDomain( point ) .. py:method:: mapToPeriodicDomain( cell, level=0 ) - - + .. py:method:: getBlock( x,y,z ) .. py:method:: containsGlobalBlockInformation( ) .. py:method:: blocksOverlappedByAABB( point, aabb ) diff --git a/python/waLBerla_docs/modules/field.rst b/python/waLBerla_docs/modules/field.rst index 81a9be47e..6357f6ea0 100644 --- a/python/waLBerla_docs/modules/field.rst +++ b/python/waLBerla_docs/modules/field.rst @@ -18,7 +18,7 @@ For details have a look at the C++ documentation: :doxylink:class:`walberla::fie Fields and numpy ================ -waLBerla *fields* can be easily converted to an :py:class:`numpy.ndarray` using Python's buffer protocol. This means +waLBerla *fields* can be easily converted to an :py:class:`numpy.ndarray` using the array functionality of pybind11. This means that a *numpy* array and a *field* can share the same memory such that fields can be manipulated using all the power of *numpy*:: @@ -27,16 +27,15 @@ power of *numpy*:: >>> field = waLBerla.field.createField( [3,3,3,1], float ) >>> field[0,0,0,0] 0.0 - >>> npArr = numpy.asarray( field.buffer() ) - >>> npArr = waLBerla.field.toArray( field ) # convenience function, same as above + >>> npArr = numpy.asarray( field ) + >>> npArr = waLBerla.field.toArray( field, True ) # convenience function, same as above (True includes ghostlayers) >>> npArr[:] = 42.0 >>> field[0,0,0,0] 42.0 A new *field* is created which is by default initialized with zero. Then a *numpy* array is created which shares the same data. After modifying the *numpy* array also the field -values have changed. To view the field including ghost layers additional parameters to -:py:meth:`Field.buffer` are required. +values have changed. A common source of error is to forget that some *numpy* functions create a copy of the data. The copy is of course not shared with the field anymore:: @@ -49,8 +48,8 @@ The copy is of course not shared with the field anymore:: When during the array manipulation a copy was created the result has to be copied back into the field again. Here the function :py:func:`numpy.copyto` is helpful::: - >>> numpy.copyto( numpy.asarray( field.buffer() ), npArr ) - >>> field = waLBerla.field.fromArray( npArr ) # convenience function, equivalent to above + >>> numpy.copyto( numpy.asarray( field ), npArr ) + >>> field = waLBerla.field.toArray( field ) # convenience function, equivalent to above >>> field[0,0,0] 5.0 @@ -67,14 +66,15 @@ Classes - Exported from C++ class :doxylink:class:`walberla::field::Field` - To modify or access a field class, the most convenient way is to create a *numpy.ndarray* view on it. - .. py:method:: buffer ( withGhostLayers=False ) + .. py:method:: __array__ - The returned object implements the Python Buffer Protocol and can be used for example to + The returned object implements pybind11::array and can be used for example to create a *numpy.ndarray* that shares the same data:: - numpy.asarray( field.buffer(withGhostLayers=True) ) - - The optional parameter specifies if the ghost layers are part of the buffer. + numpy.asarray( field ) + + With this function all ghostlayers are included in the view on the array. + If the fourth dimension is one (this means only one value per cell). The returned numpy array has only 3 dimensions. .. py:method:: swapDataPointers ( otherField ) @@ -122,63 +122,6 @@ Classes .. py:attribute:: nrOfGhostLayers The number of ghostlayers at each border of the field. - - -.. py:class:: FlagField - - Subclass of :py:class:`GhostLayerField` where the value type is an unsigned integer and the - size of the f coordinate is fixed to one element. FlagFields provide additional management function - for storing multiple booleans per cell (encoded in bits). - - - FlagFields are exported from C++ class :doxylink:class:`walberla::field::FlagField` - - .. py:method:: registerFlag( flagName, bitNr = None ) - - Reserves the next free bit (if bitNr is None ) or the specified bit using the provided flag name. - Returns an integer where the reserved bit is set to one, all other bits are set to zero. - - .. py:method:: flag( flagname ) - - Returns an integer where the specified flag is set to one, all other flags are zero. - - .. py:method:: flagName( flag ) - - Maps from integer where on bit is set to the name of the flag. - - .. py:attribute:: flags - - List with registered flag names. - - - -.. py:class:: FieldAdaptor - - A field adaptor is an object that emulates a GhostLayerField but does not store data itself. - Adaptors can only be created by C++ using :doxylink:class:`walberla::field::GhostLayerFieldAdaptor`. - - When accessing a cell of an adaptor, its value is computed on the fly based on one or multiple input fields. - A VelocityAdaptor, for example, computes the macroscopic velocity in a cell based on a field of particle distribution functions (PDFs). - Since adaptor do not hold data themselves they cannot be converted directly to numpy arrays ( see :py:meth:`copyToField` ). - Since this operation is expensive consider accessing only the required adaptor values using the getitem operator. - - .. py:method:: copyToField () - - Creates a field by computing the adaptor value for every cell (potentially expensive). - Returns this temporary field. Modifications of this field - do not affect the adaptor or the adaptor base field. - - - .. py:attribute:: size - - 4-tuple with sizes of (x,y,z,f) coordinates not counting ghost layers - - .. py:attribute:: sizeWithGhostLayer - - 4-tuple with sizes of (x,y,z,f) coordinates including ghost layers - - - Free Functions -------------- @@ -187,52 +130,34 @@ Free Functions Creates a new GhostLayerField - :param size: List of length 3 or 4 specifying x,y,z,f size of the field. - If list is of length 3 f-size is assumed to be 1 + :param size: List of length 4 specifying x,y,z,f size of the field. :param type: Type of the field elements. Valid types are the python types as well as some numpy types: - Integer types: int, numpy.int[8,16,32,64] - Unsigned types: numpy.uint[8,16,32,64] - Float types : float, numpy.float32, numpy.float64 + - Bool types : numpy.bool The type mapping is done via the C++ template trait ``walberla::python_coupling::isCppEqualToPythonType`` such that custom C++ types can be exported as well. :param ghostLayers: number of ghost layers of new field - :param layout: Either array-of-structures ``field.zyxf`` or structure-of-arrays ``field.fzyx`` - - - - + :param layout: Either array-of-structures ``field.zyxf`` or structure-of-arrays ``field.fzyx`` -.. py:function:: createFlagField( size, nrOfBits=32, ghostLayers=1 ) - - Creates a new FlagField - - :param size: list of length 3 with x,y,z size of field - :param nrOfBits: how many flags can be stored per cell. Allowed values are 8,16,32,64 - :param ghostLayers: number of ghost layers of new field - -.. note:: The ValueError "Cannot create field of this (type,f-size) combination" - means that in C++ this specific choice of type and f-size was not exported to Python. - In C++ these are template parameters, so a separate field class has to be instantiated for each - combination. - - - - -.. py:function:: addToStorage( blocks, name, type, fSize=1, ghostLayers=1, layout=field.fzyx, initValue=None) +.. py:function:: addToStorage( blocks, name, dtype, fSize=1, layout=field.fzyx, ghostLayers=1, initValue=0.0, alignment=0) Adds a GhostLayerField to the given blockStorage - :param blocks: the structured blockstorage where the field should be added to - :param name: name of block data, is used to retrieve the created field later on - :param initValue: initial value for all cells, if None the types are default initialized (for most types zero) - - The remaining parameter are the same as in :py:func:`createField` - - - + :param blocks: the structured blockstorage where the field should be added to + :param name: name of block data, is used to retrieve the created field later on + :param dtype: data type of the field + :param fSize: number of values per cell + :param layout: field.fzyx (SoA) or field.zyxf(AoS) + :param ghostLayers: number of ghost layers of the field + :param initValue: initial value for all cells, if None the types are default initialized (for most types zero) + :param alignment: alignment in bytes of the field vector + + .. py:function:: gather( blocks, blockDataName, slice, targetRank=0 ) Gathers part of the complete simulation domain (which is distributed to multiple processes) diff --git a/python/waLBerla_docs/modules/geometry.rst b/python/waLBerla_docs/modules/geometry.rst deleted file mode 100644 index 0a553af04..000000000 --- a/python/waLBerla_docs/modules/geometry.rst +++ /dev/null @@ -1,67 +0,0 @@ -*************** -Geometry module -*************** - - -.. py:class:: TriangleMesh - - Corresponds to C++ class :doxylink:class:`walberla::geometry::TriangleMesh` - - .. py:attribute:: numTriangles - - Number of triangles. - - .. py:attribute:: numVertices - - Number of vertices. - - .. py:attribute:: numVertexNormals - - Number of vertex normals. - - .. py:method:: getAABB() - - Returns the axis aligned bounding box of the mesh. - - .. py:method:: volume() - - Volume of the Mesh. - - .. py:method:: scale(factor) - - Scales the complete mesh by the given factor. - - .. py:method:: scaleXYZ( factors ) - - Scales the mesh by different factors in x,y,z direction. - - :param factors: tuple or list with 3 entries corresponding to x,y,z factors - - .. py:method:: exchangeAxes( xAxisId, yAxisId, zAxisId ) - - Permutes the coordinate order of each vertex. e.g. ``m.exchangeAxes(0,2,1)`` exchanges z and y axis. - - - .. py:method:: removeDuplicateVertices( tolerance = 1e-4) - - Merges vertices with a distance smaller than tolerance - - - .. py:method:: merge( other, offset=(0,0,0 ) ) - - Merges another mesh into the current mesh. During the merging all vertices of the - other mesh are shifted by the given offset. - - - .. py:method:: save( filename ) - - Saves the mesh to a file. The mesh format is deduced using the filename extension. - Supported formats are: obj,pov,off and vtp. - - .. py:staticmethod:: load( filename, broadcast=True ) - - Loads mesh from a file. The mesh format is deduced using the filename extension. - Supported formats are obj, pov and off. - - :param broadcast: If True the mesh is read on the root system only and broadcasted - to all other processes using MPI to reduce file system load. diff --git a/python/waLBerla_docs/modules/lbm.rst b/python/waLBerla_docs/modules/lbm.rst deleted file mode 100644 index 519462ef2..000000000 --- a/python/waLBerla_docs/modules/lbm.rst +++ /dev/null @@ -1,261 +0,0 @@ -********** -LBM module -********** - -.. note:: This module is deprecated and about to be replaced by the native Python module *lbmpy* - - -Creation Functions -================== - -.. py:function:: makeLatticeModel( stencil, collisionModel, forceModel, compressible, equilibriumAccuracyOrder=2 ) - - Creates a new lattice model. A lattice model encapsulates all information about the lattice Boltzmann method. - - :param stencil: a string describing the stencil in DxQy notation e.g. 'D2Q9', 'D3Q19', 'D3Q27' - :param collisionModel: an instance of a collision model - :param forceModel: an instance of a force model - :param compressible: choose either a compressible or incompressible LBM scheme - :param equilibriumAccuracyOrder: order of the equilibrium distribution. Valid values are 1 and 2. If not sure use 2 here. - - - .. note :: - The collision model and force model object are copied into the lattice model object. Changes to - the passed force or collision model do not affect the state of the lattice model. - Similarly after a sweep was created with a lattice model, the sweep itself is not changed when the lattice model - it was created with was changed. - - - -.. py:function:: addPdfFieldToStorage( blocks, name, latticeModel, initialVelocity=(0,0,0), initialDensity=1.0, ghostlayers=1, layout=field.zyxf, densityAdaptor="", velocityAdaptor="" ) - - Adds a PDFField to the provided blockstorage and optionally a density and velocity adaptor. - - :param blocks: blockstorage where the pdf field should be added to - :param name: block data id (string) of the new pdf field - :param latticeModel: see :py:meth:`makeLatticeModel` . The lattice model is copied into the pdf field. - Later changes to the provided object do not affect the pdf field. To change parameters of - the lattice model later, one has to iterate over all blocks, get the pdf field and retrieve - a lattice model reference from it. - :param initialVelocity: lattice velocity the field is initialized with - :param initialDensity: density the field is initialized with - :param ghostlayers: number of ghost layers, has to be at least one - :param layout: memory layout of the field, ( see documentation of field module ) - :param densityAdaptor: if a nonempty string is passed a :py:class:`FieldAdaptor` for the density is created with a - blockdataID of the given name - :param velocityAdaptor: if a nonempty string is passed a :py:class:`FieldAdaptor` for the velocity is created with a - blockdataID of the given name - - - - -.. py:function:: makeCellwiseSweep( blocks, pdfFieldID, flagFieldID="", flagList=[], velocityFieldID="" ) - - Creates a new LBM sweep. - - :param blocks: block storage where pdf field ( and if used, the flag field ) are stored - :param pdfFieldID: string identifier of the pdf field - :param flagFieldID: string identifier of the flag field. If empty string is passed, the LBM sweep is executed on all cells. - :param flagList: Only necessary when a flagFieldID was specified. Pass a list of flag identifiers here, - describing the flags where the sweep should be executed - :param velocityFieldID: optional velocity field ( field of fSize=3 and type=float) where the calculated velocity is written to. - - - - -.. py:class:: PdfField( field.GhostLayerField ) - - .. py:attribute:: latticeModel: - - - .. py:method:: setDensityAndVelocity( slice, velocity, density ) - - .. py:method:: setToEquilibrium( slice, velocity, density ) - - .. py:method:: getDensity( x,y,z ) - - .. py:method:: getDensitySI ( x,y,z, rho_SI ) - - .. py:method:: getMomentumDensity ( x,y,z ) - - .. py:method:: getEquilibriumMomentumDensity ( x,y,z ) - - .. py:method:: getVelocity ( x,y,z ) - - .. py:method:: getVelocitySI ( x,y,z. dx_SI, dt_SI ) - - .. py:method:: getEquilibriumVelocity ( x,y,z ) - - .. py:method:: getPressureTensor ( x,y,z ) - - - - -Boundary Handling -================= - -.. py:class:: BoundaryHandling - - .. py:method:: isEmpty( x,y,z ) - - .. py:method:: isNearBoundary( x,y,z ) - - .. py:method:: isBoundary( x,y,z ) - - .. py:method:: isDomain( x,y,z ) - - .. py:method:: setDomain( x, y, z | slice ) - - .. py:method:: forceDomain( x, y, z | slice ) - - .. py:method:: fillWithDomain( x, y, z | slice | nrOfGhostLayersToInclude ) - - .. py:method:: setBoundary( name, x, y, z | name, slice ) - - .. py:method:: forceBoundary( name, x, y, z | name, slice ) - - .. py:method:: removeDomain( x, y, z | slice | nrOfGhostLayersToInclude ) - - .. py:method:: removeBoundary( x, y, z | slice | nrOfGhostLayersToInclude ) - - .. py:method:: clear( x, y, z | slice | nrOfGhostLayersToInclude ) - - -Collision Models -================ - -.. py:class:: collisionModels.SRT - - Single Relaxation Time (BGK) lattice model - - .. py:method:: __init__( omega, level=0 ) - - - .. py:attribute:: omega: - - Relaxation parameter ( = 1/tau ) - - .. py:attribute:: viscosity: - - .. py:attribute:: level: - - .. py:method:: reset( omega, level=0 ) - - Sets a new relaxation parameter for the given level - - -.. py:class:: collisionModels.SRTField( SRT ) - - .. py:method:: __init__( omegaFieldID, level=0 ) - - :param omegaFieldID: this blockdata has to point to a floating point field of f-size=1 where for each cell - a different omega value is stored. - - - -.. py:class:: collisionModels.TRT - - .. py:method:: __init__( lambda_e, lambda_d, level=0 ) - - .. staticmethod:: constructWithMagicNumber( omega, magicNumber=3.0/16.0 , level=0 ) - - .. py:attribute:: lambda_e: - - .. py:attribute:: lambda_d: - - .. py:attribute:: viscosity: - - .. py:attribute:: level: - - .. py:method:: reset( lambda_e, lambda_d, level=0 ) - - .. py:method:: resetWithMagicNumber( omega, magicNumber=3.0/16.0 , level=0 ) - - -.. py:class:: collisionModels.D3Q19MRT - - .. py:method:: __init__( s1, s2, s4, s9, s10, s16, level=0 ) - - .. staticmethod:: constructTRTWithMagicNumber( omega, magicNumber=3.0/16.0 , level=0 ) - - .. staticmethod:: constructTRT( lambda_e, lambda_d, level=0 ) - - .. staticmethod:: constructPanWithMagicNumber( omega, magicNumber=3.0/16.0 , level=0 ) - - .. staticmethod:: constructPan( lambda_e, lambda_d, level=0 ) - - .. py:attribute:: relaxationRates: - - .. py:attribute:: viscosity: - - .. py:attribute:: level: - - - -Force Models -============ - -.. py:class:: forceModels.NoForce - -.. py:class:: forceModels.SimpleConstant - - .. py:method:: __init__( force, level=0 ) - -.. py:class:: forceModels.EDMField - - .. py:method:: __init__( forceFieldID ) - -.. py:class:: forceModels.LuoConstant - - .. py:method:: __init__( force, level=0 ) - -.. py:class:: forceModels.LuoField - - .. py:method:: __init__( forceFieldID ) - -.. py:class:: forceModels.GuoConstant - - .. py:method:: __init__( force, level=0 ) - -.. py:class:: forceModels.Correction - - .. py:method:: __init__( previousMomentumDensityFieldID ) - - -Lattice Models -============== - -.. py:class:: LatticeModel - - Lattice models are created with the function :func:`makeLatticeModel` and encapsulate information about - stencil, collision operator and force model. - This information can be accessed through the following read-only attributes. - - .. py:attribute:: collisionModel: - - a *copy* of the collision model - - .. py:attribute:: forceModel: - - a *copy* of the force model - - .. py:attribute:: compressible: - - boolean signaling a compressible model - - .. py:attribute:: stencilName: - - a string describing the stencil in *DxQy* notation - - .. py:attribute:: communicationStencilName: - - name of stencil that should be used for communication. In most cases this is the same as stencilName - - .. py:attribute:: directions: - - a list of tuples containing the directions of the stencil. e.g. (0,0,0) for center, (1,0,0) for east etc. - For a DxQy stencil the list as y entries, the tuples are of length x. - - - - diff --git a/python/waLBerla_tests/test_blockforest.py b/python/waLBerla_tests/test_blockforest.py index 59e0057b2..09a158151 100644 --- a/python/waLBerla_tests/test_blockforest.py +++ b/python/waLBerla_tests/test_blockforest.py @@ -1,36 +1,79 @@ import unittest -from waLBerla import field, createUniformBlockGrid +import numpy as np +from waLBerla import field, createUniformBlockGrid, AABB class BlockforestModuleTest(unittest.TestCase): def testMemoryManagement1(self): """Testing correct reference counting of block data""" - blocks = createUniformBlockGrid(cells=(2, 2, 2)) - field.addToStorage(blocks, "TestField", float) - f = blocks[0]['TestField'] - stridesBefore = f.strides + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) + field.addToStorage(blocks, "TestField", np.float64) + f = blocks[0]["TestField"] + strides_before = f.strides del blocks # create another block structure - this has triggered segfault # when previous blockstructure was already freed - blocks = createUniformBlockGrid(cells=(2, 2, 2)) # noqa: F841 + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) # noqa: F841 # The first block structure must exist here, since we hold a reference to block data # if it would have been deleted already f.strides should lead to segfault or invalid values - self.assertEqual(stridesBefore, f.strides) + self.assertEqual(strides_before, f.strides) def testMemoryManagement2(self): """Testing correct reference counting of block data Holding only a numpy array pointing to a waLBerla field should still hold the blockstructure alive""" - blocks = createUniformBlockGrid(cells=(2, 2, 2)) - field.addToStorage(blocks, "TestField", float) - npf = field.toArray(blocks[0]['TestField']) - npf[:, :, :, :] = 42.0 + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) + field.addToStorage(blocks, "TestField", np.float64) + npf = field.toArray(blocks[0]["TestField"]) + npf[:, :, :] = 42.0 del blocks # create another block structure - this has triggered segfault # when previous blockstructure was already freed - blocks = createUniformBlockGrid(cells=(2, 2, 2)) # noqa: F841 - self.assertEqual(npf[0, 0, 0, 0], 42.0) + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) # noqa: F841 + self.assertEqual(npf[0, 0, 0], 42.0) + + def testMemoryManagement3(self): + """Same as testMemoryManagement2, but with iterators""" + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) + field.addToStorage(blocks, "TestField", np.float64) + for block in blocks: + for name in block.fieldNames: + if name == "TestField": + f = block[name] + npf = field.toArray(f) + npf[:, :, :] = 42.0 + del blocks, block, name, f + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) # noqa: F841 + self.assertEqual(npf[0, 0, 0], 42.0) + + def testExceptions(self): + """Check that the right exceptions are thrown when nonexistent or non-convertible fields are accessed""" + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) + with self.assertRaises(ValueError) as cm: + blocks[0]["cell bounding box"] + self.assertEqual(str(cm.exception), "This blockdata is not accessible from Python") + with self.assertRaises(IndexError) as cm: + blocks[0]["nonexistent"] + self.assertEqual(str(cm.exception), "No blockdata with the given name found") + + def testGeneralFunctionality(self): + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(2, 2, 2)) + self.assertEqual(blocks.getNumberOfLevels(), 1) + + aabb = blocks.getDomain + aabb2 = AABB(1.0, 1.0, 1.0, 1.2, 1.2, 1.2) + + self.assertEqual(aabb.min, (0.0, 0.0, 0.0)) + self.assertEqual(aabb.max, (2.0, 2.0, 2.0)) + self.assertEqual(aabb.size, (2.0, 2.0, 2.0)) + self.assertEqual(aabb.empty, False) + self.assertEqual(aabb.volume, 8.0) + self.assertEqual(aabb.center, (1.0, 1.0, 1.0)) + self.assertEqual(aabb.contains(aabb2), True) + self.assertEqual(aabb2.contains(aabb), False) + self.assertEqual(aabb2.contains((1.2, 1.2, 1.2)), False) + self.assertEqual(aabb2.contains((1.1, 1.1, 1.1)), True) if __name__ == '__main__': diff --git a/python/waLBerla_tests/test_core.py b/python/waLBerla_tests/test_core.py index 7d59da398..7a286876e 100644 --- a/python/waLBerla_tests/test_core.py +++ b/python/waLBerla_tests/test_core.py @@ -6,7 +6,7 @@ class CoreTest(unittest.TestCase): def test_CellInterval(self): ci1 = wlb.CellInterval(0, 0, 0, 5, 5, 5) - ci2 = wlb.CellInterval([0] * 3, [5] * 3) + ci2 = wlb.CellInterval(0, 0, 0, 5, 5, 5) self.assertEqual(ci1, ci2, "Equality comparison of CellIntervals failed.") self.assertFalse(ci1 != ci2, "Inequality check for CellIntervals wrong ") @@ -23,7 +23,7 @@ class CoreTest(unittest.TestCase): def test_AABB(self): aabb1 = wlb.AABB(0, 0, 0, 5, 5, 5) - aabb2 = wlb.AABB([0] * 3, [5] * 3) + aabb2 = wlb.AABB(0, 0, 0, 5, 5, 5) self.assertEqual(aabb1, aabb2) diff --git a/python/waLBerla_tests/test_cuda_comm.py b/python/waLBerla_tests/test_cuda_comm.py deleted file mode 100644 index 3ef61ee30..000000000 --- a/python/waLBerla_tests/test_cuda_comm.py +++ /dev/null @@ -1,25 +0,0 @@ -from waLBerla import field, createUniformBlockGrid, createUniformBufferedScheme, cuda -import numpy as np -import pycuda.autoinit # noqa: F401 -import pycuda.gpuarray as gpuArr -# from pycuda import * -from pystencils.field import createNumpyArrayWithLayout, getLayoutOfArray - -blocks = createUniformBlockGrid(cells=(1, 1, 1), periodic=(1, 1, 1)) -cuda.addGpuFieldToStorage(blocks, "gpuField", float, fSize=1, ghostLayers=1, layout=field.fzyx, usePitchedMem=False) - -gpuArr = cuda.toGpuArray(blocks[0]['gpuField']) # noqa: F811 - -testField = createNumpyArrayWithLayout(gpuArr.shape, getLayoutOfArray(gpuArr)) -testField[...] = 0 -testField[1, 1, 1, 0] = 1 -gpuArr.set(testField) - -scheme = createUniformBufferedScheme(blocks, "D3Q27") -scheme.addDataToCommunicate(cuda.createPackInfo(blocks, "gpuField")) - -scheme() - -gpuArr = cuda.toGpuArray(blocks[0]['gpuField']) - -assert (np.allclose(np.ones([3, 3, 3, 1]), gpuArr.get())) diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index 9f984b3e0..85957c51b 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -1,57 +1,50 @@ import unittest +import numpy as np +import waLBerla as wlb from waLBerla import field, createUniformBlockGrid class FieldModuleTest(unittest.TestCase): def testFieldAsBlockData(self): - blocks = createUniformBlockGrid(cells=(3, 2, 2), periodic=(1, 0, 0)) - field.addToStorage(blocks, 'myField', float, fSize=3, ghostLayers=0, initValue=0.0) - myField = blocks[0]['myField'] - self.assertEqual(myField[0, 0, 0, 0], 0) - myField[0, 0, 0, 0] = 42.0 - self.assertEqual(myField[0, 0, 0, 0], 42.0) + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(3, 2, 2), periodic=(True, False, False)) + field.addToStorage(blocks, 'myField', np.float64, fSize=3, ghostLayers=0, initValue=0.0) + my_field = wlb.field.toArray(blocks[0]['myField']) + self.assertEqual(my_field[0, 0, 0, 0], 0) + my_field[0, 0, 0, 0] = 42.0 + self.assertEqual(my_field[0, 0, 0, 0], 42.0) - self.assertRaises(IndexError, myField.__getitem__, (3, 0, 0)) + self.assertRaises(IndexError, my_field.__getitem__, (3, 0, 0)) def testNumpyConversionWithoutGhostLayers(self): - f1 = field.createField([1, 2, 3, 4], float, 2, field.zyxf) - f2 = field.createField([1, 2, 3, 5], float, 4, field.zyxf) - f1np = field.toArray(f1) - f2np = field.toArray(f2) - self.assertEqual(f1np[0, 0, 0, 0], 0) + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(1, 2, 3), periodic=(True, False, False)) + field.addToStorage(blocks, 'f1', np.float64, fSize=4, ghostLayers=0, initValue=2.0) + field.addToStorage(blocks, 'f2', np.float64, fSize=5, ghostLayers=0, initValue=2.0) + + f1np = field.toArray(blocks[0]['f1']) + f2np = field.toArray(blocks[0]['f2']) + self.assertEqual(f1np[0, 0, 0, 0], 2.0) self.assertEqual(f1np.shape, (1, 2, 3, 4)) self.assertEqual(f2np.shape, (1, 2, 3, 5)) - f1np[0, 0, 0, 0] = 1 - f2np[0, 0, 0, 0] = 2 - self.assertEqual(f1[0, 0, 0, 0], 1) - self.assertEqual(f2[0, 0, 0, 0], 2) - - def testNumpyConversionWithGhostLayers(self): - f = field.createField([1, 2, 3, 1], float, 2, field.zyxf) - fnp = field.toArray(f, withGhostLayers=True) - - self.assertEqual(fnp[0, 0, 0, 0], 0) - self.assertEqual(fnp.shape, (1 + 4, 2 + 4, 3 + 4, 1)) - fnp[0, 0, 0, 0] = 42 - self.assertEqual(f[-2, -2, -2, 0], 42) - def testGhostLayerExtraction(self): - size = [10, 5, 4] + size = (10, 5, 4) gl = 3 - f = field.createField(size, float, ghostLayers=gl) + blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=size, periodic=(True, False, False)) + field.addToStorage(blocks, 'f', np.float64, fSize=3, ghostLayers=gl, initValue=0.0) + + f = blocks[0]['f'] - view1 = field.toArray(f, withGhostLayers=True) + view1 = field.toArray(f, with_ghost_layers=True) self.assertEqual(view1[:, :, :, 0].shape, tuple([s + 2 * gl for s in size])) - view2 = field.toArray(f, withGhostLayers=False) + view2 = field.toArray(f, with_ghost_layers=False) self.assertEqual(view2[:, :, :, 0].shape, tuple(size)) - view3 = field.toArray(f, withGhostLayers=2) + view3 = field.toArray(f, with_ghost_layers=2) self.assertEqual(view3[:, :, :, 0].shape, tuple([s + 2 * 2 for s in size])) - view4 = field.toArray(f, withGhostLayers=[2, False, True]) + view4 = field.toArray(f, with_ghost_layers=[2, False, True]) self.assertEqual(view4[:, :, :, 0].shape, tuple([size[0] + 2 * 2, size[1] + 2 * 0, size[2] + 2 * gl])) diff --git a/python/waLBerla_tests/test_simpleLBM.py b/python/waLBerla_tests/test_simpleLBM.py deleted file mode 100644 index defe348eb..000000000 --- a/python/waLBerla_tests/test_simpleLBM.py +++ /dev/null @@ -1,198 +0,0 @@ -from waLBerla import makeSlice, field, mpi, lbm, createUniformBlockGrid, createUniformBufferedScheme -from waLBerla.geometry_setup import setBoundaryFromBlackAndWhiteImage, setFieldUsingFlagMask -import itertools - -import os -import numpy as np -import scipy - -imageFile = os.path.join(os.path.dirname(__file__), 'wing.png') - - -def setBoundariesChannel(blocks, boundaryHandlingID): - for block in blocks: - b = block[boundaryHandlingID] - if block.atDomainMinBorder[1]: - b.forceBoundary('NoSlip', makeSlice[:, 0, :, 'g']) - if block.atDomainMaxBorder[1]: - b.forceBoundary('NoSlip', makeSlice[:, -1, :, 'g']) - b.fillWithDomain() - - -class ForceCalculationMasks: - @staticmethod - def addToBlock(block, blockStorage): - pdfFieldArr = field.toArray(block['pdfs']) - flagFieldArr = field.toArray(block['flags'])[:, :, :, 0] - directions = block['pdfs'].latticeModel.directions - maskArr = np.zeros(pdfFieldArr.shape, dtype=bool) - pdfDirectionArr = np.zeros(list(pdfFieldArr.shape) + [3]) - - nearBoundaryFlag = block['flags'].flag("fluid") - noSlipFlag = block['flags'].flag("NoSlip") - - innerPartOfDomain = itertools.product(range(2, maskArr.shape[0] - 2), - range(2, maskArr.shape[1] - 2), - range(maskArr.shape[2])) - - for x, y, z in innerPartOfDomain: - if flagFieldArr[x, y, z] & nearBoundaryFlag: - for dirIdx, dir in enumerate(directions): - nx, ny, nz = x + dir[0], y + dir[1], z + dir[2] - if flagFieldArr[nx, ny, nz] & noSlipFlag: - maskArr[x, y, z, dirIdx] = True - pdfDirectionArr[x, y, z, :] = dir - return ForceCalculationMasks(maskArr, pdfDirectionArr) - - def __init__(self, maskArr, pdfDirectionArr): - self._maskArr = maskArr - self._pdfDirectionArr = pdfDirectionArr - - def calculateForceOnBoundary(self, pdfField): - force = np.array([0.0] * 3) - pdfFieldArr = field.toArray(pdfField) - for i in range(3): - fArr = pdfFieldArr[self._maskArr] * self._pdfDirectionArr[self._maskArr, i] - force[i] += np.sum(fArr) - return force - - -def calculateForceOnBoundary(blocks): - force = np.array([0.0] * 3) - for block in blocks: - force += block['ForceCalculation'].calculateForceOnBoundary(block['pdfs']) - return np.array(mpi.reduceReal(force, mpi.SUM)) - - -def makeNacaAirfoilImage(domainSize, thicknessInPercent=30, angle=0): - def nacaAirfoil(x, thicknessInPercent, chordLength): - xOverC = x / chordLength - y_t = 0 - coeffs = [0.2969, -0.1260, - 0.3516, 0.2843, -0.1015] - for coeff, exponent in zip(coeffs, [0.5, 1, 2, 3, 4]): - y_t += coeff * xOverC ** exponent - y_t *= 5 * thicknessInPercent / 100 * chordLength - return y_t - - domain = np.zeros(domainSize) - it = np.nditer(domain, flags=['multi_index'], op_flags=['readwrite']) - while not it.finished: - x, y = it.multi_index - y -= domain.shape[1] / 2 - if abs(y) < nacaAirfoil(x, thicknessInPercent, domain.shape[0]): - it[0] = 1 - it.iternext() - domain = np.rot90(domain, 1) - domain = scipy.ndimage.interpolation.rotate(domain, angle=angle) - - domain[domain > 0.5] = 1 - domain[domain <= 0.5] = 0 - domain = domain.astype(np.int32) - return domain - - -img = makeNacaAirfoilImage([300, 300], 30, angle=-30) - -omega = 1.9 -blocks = createUniformBlockGrid(cells=(500, 200, 1), periodic=(1, 0, 1)) - -collisionModel = lbm.collisionModels.SRT(omega) -forceModel = lbm.forceModels.SimpleConstant((1e-5, 0, 0)) -latticeModel = lbm.makeLatticeModel("D2Q9", collisionModel, forceModel) -lbm.addPdfFieldToStorage(blocks, "pdfs", latticeModel, velocityAdaptor="vel", densityAdaptor="rho", initialDensity=1.0) -field.addFlagFieldToStorage(blocks, 'flags') -lbm.addBoundaryHandlingToStorage(blocks, 'boundary', 'pdfs', 'flags') - -# setBoundaryFromArray( blocks, 'boundary', makeSlice[0.4:0.6, 0.4:0.55 ,0.5], img, { 1: 'NoSlip' } ) -setBoundaryFromBlackAndWhiteImage(blocks, "boundary", makeSlice[0.25:0.75, 0.3:0.6, 0.5], imageFile, "NoSlip") -setBoundariesChannel(blocks, 'boundary') - -blocks.addBlockData('ForceCalculation', ForceCalculationMasks.addToBlock) - -sweep = lbm.makeCellwiseSweep(blocks, "pdfs", flagFieldID='flags', flagList=['fluid']) - -scheme = createUniformBufferedScheme(blocks, 'D3Q19') -scheme.addDataToCommunicate(field.createPackInfo(blocks, 'pdfs')) - - -def timestep(): - scheme() - for block in blocks: - block['boundary']() - for block in blocks: - sweep.streamCollide(block) - return calculateForceOnBoundary(blocks) - - -def run(timesteps): - for t in range(timesteps): - scheme() - for block in blocks: - block['boundary']() - for block in blocks: - sweep.streamCollide(block) - - -def makeAnimation(blocks, interval=30, frames=180): - import matplotlib.pyplot as plt - import matplotlib.animation as animation - - plt.style.use('ggplot') - NR_OF_TIMESTEPS_SHOWN = 600 - lifts = [] - - fig = plt.gcf() - f = field.gather(blocks, 'rho', makeSlice[:, :, 0.5]) - im = None - - ymax = [0.05] - if f: - npField = field.toArray(f).squeeze() - npField = np.rot90(npField, 1) - - plt.subplot(2, 1, 1) - plt.title("Lattice Density") - im = plt.imshow(npField) - plt.colorbar() - - plt.subplot(2, 1, 2) - plt.title("Lift") - plt.ylim(0, ymax[0]) - plt.xlim(0, NR_OF_TIMESTEPS_SHOWN) - liftPlot, = plt.plot(lifts) - - def updatefig(*args): - force = timestep() - f = field.gather(blocks, 'rho', makeSlice[:, :, 0.5]) - if f: - npField = field.toArray(f).squeeze() - npField = np.rot90(npField, 1) - im.set_array(npField) - im.autoscale() - if lifts and max(lifts) * 1.2 > ymax[0]: - ymax[0] = max(lifts) * 1.2 - liftPlot.axes.set_ylim(0, ymax[0]) - - lifts.append(force[1]) - nrOfSamples = len(lifts) - xMin = max(0, nrOfSamples - NR_OF_TIMESTEPS_SHOWN) - liftPlot.axes.set_xlim(xMin, xMin + NR_OF_TIMESTEPS_SHOWN) - liftPlot.set_data(np.arange(nrOfSamples), lifts) - return im, liftPlot - - return animation.FuncAnimation(fig, updatefig, interval=interval, frames=frames, blit=False, repeat=False) - - -showPlots = False - -if showPlots: - import waLBerla.plot as wplt - - setFieldUsingFlagMask(blocks, 'pdfs', np.NaN, 'flags', ['NoSlip']) - run(1) - setFieldUsingFlagMask(blocks, 'pdfs', np.NaN, 'flags', ['NoSlip']) - - ani = makeAnimation(blocks, frames=6000, ) - wplt.show() -else: - run(10) diff --git a/python/waLBerla_tests/tools/test_lbm_unitconversion.py b/python/waLBerla_tests/tools/test_lbm_unitconversion.py index 72d87aa35..7631b5776 100644 --- a/python/waLBerla_tests/tools/test_lbm_unitconversion.py +++ b/python/waLBerla_tests/tools/test_lbm_unitconversion.py @@ -5,9 +5,9 @@ class UnitConversionTest(unittest.TestCase): def testExtractLatticeFactors(self): try: - import pint # noqa: F401 + import pint, sympy # noqa: F401 except ImportError: - print("Skipping unit conversion test since pint module not available") + print("Skipping unit conversion test since pint or sympy module not available") return from waLBerla.tools.lbm_unitconversion import extractLatticeFactors, computeLatticeFactors @@ -28,9 +28,9 @@ class UnitConversionTest(unittest.TestCase): def testUnitConverter(self): try: - import pint # noqa: F401 + import pint, sympy # noqa: F401 except ImportError: - print("Skipping unit conversion test since pint module not available") + print("Skipping unit conversion test since pint or sympy module not available") return from waLBerla.tools.lbm_unitconversion import PintUnitConverter diff --git a/python/waLBerla_tests/wing.png b/python/waLBerla_tests/wing.png deleted file mode 100644 index f51549c70bf0f33840c03536577b4e8591eec70a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1146 zcmeAS@N?(olHy`uVBq!ia0y~yU~*w#VA#yT#K6GtylYA;0|NtRfk$L90|Va?5N4dJ z%_q&kz`$PO>Fdh=fSH3=OMxYF&N>DL7D-PR$B>F!Z|?;9y><|A2~<1vZ@bMOW!9t9 z6xXdQ7Hbfx-j&Zb@7}HIdPav$?d}W>GZ-OAA&mi!IwTq3D2a^$h9C+dBwVdR8bWP{ zBvkGHcP|A$oQirqY5wN#-wYb}-whY*<xnlkV>Fz+LXXd~L$YgWWy1``*dX?fnI(#) z4Kr4XTd^m#RV^$~NRwjYVozF@s3D_}Ce^m5amK>L6Ve?sdm6Vj&d8L2G8NN|*gml( zElX6$QAjglyTz8YEJY!wV`dNIp|%+(B{IMoHaHfZN#SYXH4HX#xFKLH$qZ%&n7-(m z+0(c|G0lr@g;bJSas!lEY8Y%JV0J|3w~vP83aOOiJ|`JMl`YbY*j7m01Q~JlMBmIw zjH}$r&P?G6Fx`~AETv)9L|J21=8)buGc+X?G9g+Xm;3iKJUAYn9$IW%tjip8MF6bC z5M;!qipl$DGRpjJTbq@awl1}yTS^uzY;k10<iTBET0b?VFU`tJTgFk_75~&@)(lCW zHQOF;7h5l9$eiu{a1QSgo;B*N#c4;*G`j8DATUSOP}q2l^c(hcpEC#260hwl_;7?r zN3bo2e|cffnJ+xr&D(q*)pSYT;N!We#rJm0jF*ySj9XtHHIx%Iwmtme@}BfLuPhBO z8~0c}<vwmHFJx?cI3fA7#ZTd+W$80g)+jU^D5g~{i%Srk*~e*k*_fC4^@$BW9W$43 zN<?@aOZPaV;(Pc&oRP0{(y}Zjwr`Uj&Js5E6gJo}tLOHF8J@Em8sDZcTwlVkpZSXQ zDfg-}mFrjh^>W-;v$h96oU^X&yiU$CCa&<{s~^^F3sucwW2pKTblzh9D|-p9*(Ht# zgI4|EofCU)f_c8A&Z3*u4rkn4&)sI3y}a19BhumR9_0;jYeWp01GYZ26*gw@6gFm< zwA$>6y{U+C!>1*@9E~#=S47pEKf>d1>Ct4hG=@oH_l-fSe=O;gY*=#iyU!U072SR5 zNo)$4A3>T!yWh{8!RUdkMaJWn?P|p|1{v>LyoVLj80M_Jwe}N;_PJHdrIf}n$N!eE zl2RJO5p~})3_BDu=dV3^xSR1oZFT<tS%M84w{PKRJ9?I<;YakW*^&$&@0?)}FovQd zJPdGT$jksk4rdtP2(DJZ7@_tE4_qySAv0X91Cr6Wl`lAHUi{<0SCv;ryBHW47(8A5 KT-G@yGywqG?x`RE diff --git a/src/blockforest/CMakeLists.txt b/src/blockforest/CMakeLists.txt index 554388c3f..84027d327 100644 --- a/src/blockforest/CMakeLists.txt +++ b/src/blockforest/CMakeLists.txt @@ -5,4 +5,4 @@ mark_as_advanced( WALBERLA_BLOCKFOREST_PRIMITIVE_BLOCKID ) configure_file ( CMakeDefs.in.h CMakeDefs.h ) -waLBerla_add_module( DEPENDS communication core domain_decomposition python_coupling stencil ) +waLBerla_add_module( DEPENDS communication core domain_decomposition stencil ) diff --git a/src/blockforest/communication/UniformBufferedScheme.h b/src/blockforest/communication/UniformBufferedScheme.h index b9c07bbec..6ee1be18c 100644 --- a/src/blockforest/communication/UniformBufferedScheme.h +++ b/src/blockforest/communication/UniformBufferedScheme.h @@ -32,7 +32,6 @@ #include "core/Set.h" #include "core/debug/CheckFunctions.h" #include "core/debug/Debug.h" -#include "core/WeakPtrWrapper.h" #include "core/mpi/MPIManager.h" #include "core/mpi/OpenMPBufferSystem.h" #include "core/selectable/IsSetSelected.h" @@ -96,7 +95,7 @@ public: /*! \name Construction & Destruction */ //@{ - explicit UniformBufferedScheme( weak_ptr_wrapper<StructuredBlockForest> bf, + explicit UniformBufferedScheme( weak_ptr<StructuredBlockForest> bf, const int tag = 778 ) // waLBerla = 119+97+76+66+101+114+108+97 : blockForest_( bf ), localMode_( START ), @@ -111,7 +110,7 @@ public: forestModificationStamp_ = forest->getBlockForest().getModificationStamp(); } - UniformBufferedScheme( weak_ptr_wrapper<StructuredBlockForest> bf, + UniformBufferedScheme( weak_ptr<StructuredBlockForest> bf, const Set<SUID> & requiredBlockSelectors, const Set<SUID> & incompatibleBlockSelectors, const int tag = 778 ) // waLBerla = 119+97+76+66+101+114+108+97 @@ -177,7 +176,7 @@ protected: - weak_ptr_wrapper<StructuredBlockForest> blockForest_; + weak_ptr<StructuredBlockForest> blockForest_; uint_t forestModificationStamp_; std::vector< PackInfo > packInfos_; diff --git a/src/blockforest/communication/UniformDirectScheme.h b/src/blockforest/communication/UniformDirectScheme.h index bf3a73344..7dfa2d781 100644 --- a/src/blockforest/communication/UniformDirectScheme.h +++ b/src/blockforest/communication/UniformDirectScheme.h @@ -24,7 +24,6 @@ #include "blockforest/StructuredBlockForest.h" #include "core/Set.h" -#include "core/WeakPtrWrapper.h" #include "core/mpi/Datatype.h" #include "core/mpi/MPIManager.h" #include "core/mpi/MPIWrapper.h" @@ -56,7 +55,7 @@ public: //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ //@{ - explicit UniformDirectScheme( const weak_ptr_wrapper<StructuredBlockForest> & bf, + explicit UniformDirectScheme( const weak_ptr<StructuredBlockForest> & bf, const shared_ptr<UniformMPIDatatypeInfo> & dataInfo = shared_ptr<UniformMPIDatatypeInfo>(), const int tag = 778 ) // waLBerla = 119+97+76+66+101+114+108+97 : blockForest_( bf ), @@ -70,7 +69,7 @@ public: dataInfos_.push_back( dataInfo ); } - UniformDirectScheme( const weak_ptr_wrapper<StructuredBlockForest> & bf, + UniformDirectScheme( const weak_ptr<StructuredBlockForest> & bf, const Set<SUID> & requiredBlockSelectors, const Set<SUID> & incompatibleBlockSelectors, const shared_ptr<UniformMPIDatatypeInfo> & dataInfo = shared_ptr<UniformMPIDatatypeInfo>(), @@ -140,7 +139,7 @@ protected: } }; - weak_ptr_wrapper<StructuredBlockForest> blockForest_; + weak_ptr<StructuredBlockForest> blockForest_; bool setupRequired_; //< this is set in the beginning or when new communication item was added bool communicationRunning_; //< this is true between startCommunication() and wait() diff --git a/src/blockforest/python/CommunicationExport.impl.h b/src/blockforest/python/CommunicationExport.impl.h deleted file mode 100644 index 09041944f..000000000 --- a/src/blockforest/python/CommunicationExport.impl.h +++ /dev/null @@ -1,235 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file CommunicationExport.impl.h -//! \ingroup blockforest -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - - -#include "blockforest/communication/UniformBufferedScheme.h" -#include "blockforest/communication/UniformDirectScheme.h" -#include "python_coupling/helper/MplHelpers.h" - -namespace walberla { -namespace blockforest { - -namespace internal -{ - //=================================================================================================================== - // - // UniformBufferedScheme - // - //=================================================================================================================== - - /// for details see documentation in core/WeakPtrWrapper.h - /// the purpose of this class could also be solved by adding return_internal_reference to "createUniformDirectScheme" - /// however this is not easily possible since it returns not a reference but an boost::python::object - template<typename Stencil> - class UniformBufferedSchemeWrapper : public blockforest::communication::UniformBufferedScheme<Stencil> - { - public: - UniformBufferedSchemeWrapper( const shared_ptr<StructuredBlockForest> & bf, const int tag ) - : blockforest::communication::UniformBufferedScheme<Stencil>( bf, tag), - blockforest_( bf) - {} - private: - shared_ptr< StructuredBlockForest > blockforest_; - }; - - - struct UniformBufferedSchemeExporter - { - template<typename Stencil> - void operator() ( python_coupling::NonCopyableWrap<Stencil> ) - { - using namespace boost::python; - typedef UniformBufferedSchemeWrapper<Stencil> UBS; - - class_< UBS, shared_ptr<UBS>, boost::noncopyable >( "UniformBufferedScheme", no_init ) - .def( "__call__", &UBS::operator() ) - .def( "communicate", &UBS::communicate ) - .def( "startCommunication", &UBS::startCommunication ) - .def( "wait", &UBS::wait ) - .def( "addPackInfo", &UBS::addPackInfo ) - .def( "addDataToCommunicate", &UBS::addDataToCommunicate ) - .def( "localMode", &UBS::localMode ) - .def( "setLocalMode", &UBS::setLocalMode ) - ; - } - }; - - class UniformBufferedSchemeCreator - { - public: - UniformBufferedSchemeCreator( const shared_ptr<StructuredBlockForest> & bf, - const std::string & stencilName, - const int tag ) - : blockforest_( bf), stencilName_( stencilName ), tag_( tag ) - {} - - template<typename Stencil> - void operator() ( python_coupling::NonCopyableWrap<Stencil> ) - { - - using namespace boost::python; - if ( std::string(Stencil::NAME) == stencilName_ ) { - result_ = object ( make_shared< UniformBufferedSchemeWrapper<Stencil> > ( blockforest_, tag_ ) ); - } - } - - boost::python::object getResult() { return result_; } - private: - shared_ptr<StructuredBlockForest> blockforest_; - std::string stencilName_; - const int tag_; - boost::python::object result_; - }; - - - template<typename Stencils> - boost::python::object createUniformBufferedScheme( const shared_ptr<StructuredBlockForest> & bf, - const std::string & stencil, - const int tag ) - { - UniformBufferedSchemeCreator creator( bf, stencil, tag ); - python_coupling::for_each_noncopyable_type< Stencils > ( std::ref(creator) ); - - if ( creator.getResult() == boost::python::object() ) - { - PyErr_SetString( PyExc_RuntimeError, "Unknown stencil."); - throw boost::python::error_already_set(); - } - return creator.getResult(); - } - - //=================================================================================================================== - // - // UniformDirectScheme - // - //=================================================================================================================== - - template<typename Stencil> - class UniformDirectSchemeWrapper : public blockforest::communication::UniformDirectScheme<Stencil> - { - public: - UniformDirectSchemeWrapper( const shared_ptr<StructuredBlockForest> & bf, const int tag ) - : blockforest::communication::UniformDirectScheme<Stencil>( bf, shared_ptr<walberla::communication::UniformMPIDatatypeInfo>(), tag), - blockforest_( bf) - {} - private: - shared_ptr< StructuredBlockForest > blockforest_; - }; - - struct UniformDirectSchemeExporter - { - template<typename Stencil> - void operator() ( python_coupling::NonCopyableWrap<Stencil> ) - { - using namespace boost::python; - typedef UniformDirectSchemeWrapper<Stencil> UDS; - - class_< UDS, shared_ptr<UDS>, boost::noncopyable >( "UniformDirectScheme", no_init ) - .def( "__call__", &UDS::operator() ) - .def( "communicate", &UDS::communicate ) - .def( "startCommunication", &UDS::startCommunication ) - .def( "wait", &UDS::wait ) - .def( "addDataToCommunicate", &UDS::addDataToCommunicate ) - ; - } - }; - - class UniformDirectSchemeCreator - { - public: - UniformDirectSchemeCreator( const shared_ptr<StructuredBlockForest> & bf, - const std::string & stencilName, - const int tag ) - : blockforest_( bf), stencilName_( stencilName ), tag_( tag ) - {} - - template<typename Stencil> - void operator() ( python_coupling::NonCopyableWrap<Stencil> ) - { - - using namespace boost::python; - if ( std::string(Stencil::NAME) == stencilName_ ) { - result_ = object ( make_shared< UniformDirectSchemeWrapper<Stencil> > ( blockforest_, tag_ ) ); - } - } - - boost::python::object getResult() { return result_; } - private: - shared_ptr<StructuredBlockForest> blockforest_; - std::string stencilName_; - const int tag_; - boost::python::object result_; - }; - - - template<typename Stencils> - boost::python::object createUniformDirectScheme( const shared_ptr<StructuredBlockForest> & bf, - const std::string & stencil, const int tag ) - { - UniformDirectSchemeCreator creator( bf, stencil, tag ); - python_coupling::for_each_noncopyable_type< Stencils > ( std::ref(creator) ); - - if ( creator.getResult() == boost::python::object() ) - { - PyErr_SetString( PyExc_RuntimeError, "Unknown stencil."); - throw boost::python::error_already_set(); - } - return creator.getResult(); - } - -} - - -template<typename Stencils> -void exportUniformBufferedScheme() -{ - using namespace boost::python; - - enum_<LocalCommunicationMode>("LocalCommunicationMode") - .value("START", START) - .value("WAIT", WAIT) - .value("BUFFER", BUFFER) - .export_values(); - - python_coupling::for_each_noncopyable_type< Stencils > ( internal::UniformBufferedSchemeExporter() ); - - def( "createUniformBufferedScheme", &internal::createUniformBufferedScheme<Stencils>, - ( ( arg("blockForest"), arg("stencilName"), arg("tag")=778 ) ) ); - -} - -template<typename Stencils> -void exportUniformDirectScheme() -{ - using namespace boost::python; - - python_coupling::for_each_noncopyable_type< Stencils > ( internal::UniformDirectSchemeExporter() ); - - def( "createUniformDirectScheme", &internal::createUniformDirectScheme<Stencils>, - ( ( arg("blockForest"), arg("stencilName"), arg("tag")=778 ) ) ); -} - - - -} // namespace blockforest -} // namespace walberla - - diff --git a/src/blockforest/python/Exports.cpp b/src/blockforest/python/Exports.cpp deleted file mode 100644 index 08873381e..000000000 --- a/src/blockforest/python/Exports.cpp +++ /dev/null @@ -1,327 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.cpp -//! \ingroup domain_decomposition -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "blockforest/StructuredBlockForest.h" -#include "blockforest/communication/UniformBufferedScheme.h" -#include "blockforest/Initialization.h" -#include "blockforest/SetupBlock.h" -#include "blockforest/SetupBlockForest.h" -#include "blockforest/loadbalancing/StaticCurve.h" - -#include "core/logging/Logging.h" -#include "core/StringUtility.h" -#include "domain_decomposition/StructuredBlockStorage.h" -#include "python_coupling/Manager.h" -#include "python_coupling/helper/ConfigFromDict.h" - -#include "stencil/D3Q7.h" -#include "stencil/D3Q19.h" -#include "stencil/D3Q27.h" - -#include <memory> - -#include <sstream> - -#ifdef _MSC_VER -# pragma warning(push) -// disable warning boost/python/raw_function.hpp(55): warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data -# pragma warning( disable : 4267 ) -#endif //_MSC_VER -#include <boost/python/raw_function.hpp> -#ifdef _MSC_VER -# pragma warning(pop) -#endif //_MSC_VER - - -using namespace boost::python; - - -namespace walberla { -namespace blockforest { - -using walberla::blockforest::communication::UniformBufferedScheme; - -bool checkForThreeTuple( object obj ) //NOLINT -{ - if( ! extract<tuple> ( obj ).check() ) - return false; - - tuple t = extract<tuple> ( obj ); - return len(t) == 3; -} - - -object python_createUniformBlockGrid(tuple args, dict kw) //NOLINT -{ - if( len(args) > 0 ) { - PyErr_SetString( PyExc_ValueError, "This function takes only keyword arguments" ); - throw boost::python::error_already_set(); - } - - using boost::python::stl_input_iterator; - - boost::python::list keys = kw.keys(); - for( auto it = stl_input_iterator<std::string>( keys ); it != stl_input_iterator<std::string>(); ++it ) - { - if ( *it != "cells" && - *it != "cellsPerBlock" && - *it != "blocks" && - *it != "periodic" && - *it != "dx" && - *it != "oneBlockPerProcess" ) - { - PyErr_SetString( PyExc_ValueError, (std::string("Unknown Parameter: ") + (*it) ).c_str() ); - throw boost::python::error_already_set(); - } - } - - if( kw.has_key("cells ") && ! checkForThreeTuple( kw["cells"] ) ) { - PyErr_SetString( PyExc_ValueError, "Parameter 'cells' has to be tuple of length 3, indicating cells in x,y,z direction" ); - throw boost::python::error_already_set(); - } - if( kw.has_key("cellsPerBlock ") && ! checkForThreeTuple( kw["cellsPerBlock"] ) ) { - PyErr_SetString( PyExc_ValueError, "Parameter 'cellsPerBlock' has to be tuple of length 3, indicating cells in x,y,z direction" ); - throw boost::python::error_already_set(); - } - if( kw.has_key("blocks ") && ! checkForThreeTuple( kw["blocks"] ) ) { - PyErr_SetString( PyExc_ValueError, "Parameter 'blocks' has to be tuple of length 3, indicating cells in x,y,z direction" ); - throw boost::python::error_already_set(); - } - - bool keepGlobalBlockInformation = false; - if ( kw.has_key("keepGlobalBlockInformation") ) - { - if ( extract<bool>( kw["keepGlobalBlockInformation"] ).check() ) - keepGlobalBlockInformation = extract<bool>( kw["keepGlobalBlockInformation"] ); - else - { - PyErr_SetString( PyExc_ValueError, "Parameter 'keepGlobalBlockInformation' has to be a boolean" ); - throw boost::python::error_already_set(); - } - } - - shared_ptr<Config> cfg = python_coupling::configFromPythonDict( kw ); - - try { - shared_ptr< StructuredBlockForest > blocks = createUniformBlockGridFromConfig( cfg->getGlobalBlock(), nullptr, keepGlobalBlockInformation ); - return object(blocks); - } - catch( std::exception & e) - { - PyErr_SetString( PyExc_ValueError, e.what() ); - throw boost::python::error_already_set(); - } - -} - -shared_ptr<StructuredBlockForest> createStructuredBlockForest( Vector3<uint_t> blocks, - Vector3<uint_t> cellsPerBlock, - Vector3<bool> periodic, - object blockExclusionCallback = object(), - object workloadMemoryCallback = object(), - object refinementCallback = object(), - const real_t dx = 1.0, - memory_t processMemoryLimit = std::numeric_limits<memory_t>::max(), - const bool keepGlobalBlockInformation = false) -{ - using namespace blockforest; - Vector3<real_t> bbMax; - for( uint_t i=0; i < 3; ++i ) - bbMax[i] = real_c( blocks[i] * cellsPerBlock[i] ) * dx; - AABB domainAABB ( Vector3<real_t>(0), bbMax ); - - SetupBlockForest sforest; - - auto blockExclusionFunc = [&blockExclusionCallback] ( std::vector<walberla::uint8_t>& excludeBlock, const SetupBlockForest::RootBlockAABB& aabb ) -> void - { - for( uint_t i = 0; i != excludeBlock.size(); ++i ) - { - AABB bb = aabb(i); - auto pythonReturnVal = blockExclusionCallback(bb); - if( ! extract<bool>( pythonReturnVal ).check() ) { - PyErr_SetString( PyExc_ValueError, "blockExclusionCallback has to return a boolean"); - throw boost::python::error_already_set(); - } - - bool returnVal = extract<bool>(pythonReturnVal); - if ( returnVal ) - excludeBlock[i] = 1; - } - }; - - auto workloadMemoryFunc = [&workloadMemoryCallback] ( SetupBlockForest & forest )-> void - { - std::vector< SetupBlock* > blockVector; - forest.getBlocks( blockVector ); - - for( uint_t i = 0; i != blockVector.size(); ++i ) { - blockVector[i]->setMemory( memory_t(1) ); - blockVector[i]->setWorkload( workload_t(1) ); - workloadMemoryCallback( boost::python::ptr(blockVector[i]) ); - } - }; - - auto refinementFunc = [&refinementCallback] ( SetupBlockForest & forest )-> void - { - for( auto block = forest.begin(); block != forest.end(); ++block ) - { - SetupBlock * sb = &(*block); - auto pythonRes = refinementCallback( boost::python::ptr(sb) ); - if( ! extract<bool>( pythonRes ).check() ) { - PyErr_SetString( PyExc_ValueError, "refinementCallback has to return a boolean"); - throw boost::python::error_already_set(); - } - bool returnVal = extract<bool>( pythonRes ); - if( returnVal ) - block->setMarker( true ); - } - }; - - if ( blockExclusionCallback ) { - if( !PyCallable_Check( blockExclusionCallback.ptr() ) ) { - PyErr_SetString( PyExc_ValueError, "blockExclusionCallback has to be callable"); - throw boost::python::error_already_set(); - } - sforest.addRootBlockExclusionFunction( blockExclusionFunc ); - } - - if ( workloadMemoryCallback ) { - if( !PyCallable_Check( workloadMemoryCallback.ptr() ) ) { - PyErr_SetString( PyExc_ValueError, "workloadMemoryCallback has to be callable"); - throw boost::python::error_already_set(); - } - sforest.addWorkloadMemorySUIDAssignmentFunction( workloadMemoryFunc ); - } - else - sforest.addWorkloadMemorySUIDAssignmentFunction( uniformWorkloadAndMemoryAssignment ); - - if ( refinementCallback ) { - if( !PyCallable_Check( refinementCallback.ptr() ) ) { - PyErr_SetString( PyExc_ValueError, "refinementCallback has to be callable"); - throw boost::python::error_already_set(); - } - sforest.addRefinementSelectionFunction( refinementFunc ); - } - - sforest.init( domainAABB, blocks[0], blocks[1], blocks[2], periodic[0], periodic[1], periodic[2] ); - - // calculate process distribution - sforest.balanceLoad( blockforest::StaticLevelwiseCurveBalanceWeighted(), - uint_c( MPIManager::instance()->numProcesses() ), - real_t(0), processMemoryLimit ); - - if( !MPIManager::instance()->rankValid() ) - MPIManager::instance()->useWorldComm(); - - // create StructuredBlockForest (encapsulates a newly created BlockForest) - auto bf = std::make_shared< BlockForest >( uint_c( MPIManager::instance()->rank() ), sforest, keepGlobalBlockInformation ); - - auto sbf = std::make_shared< StructuredBlockForest >( bf, cellsPerBlock[0], cellsPerBlock[1], cellsPerBlock[2] ); - sbf->createCellBoundingBoxes(); - - return sbf; -} - -object createUniformNeighborScheme( const shared_ptr<StructuredBlockForest> & bf, - const std::string & stencil ) -{ - if ( string_icompare(stencil, "D3Q7") == 0 ) - return object ( make_shared< UniformBufferedScheme<stencil::D3Q7> > ( bf ) ); - if ( string_icompare(stencil, "D3Q19") == 0 ) - return object ( make_shared< UniformBufferedScheme<stencil::D3Q19> > ( bf ) ); - if ( string_icompare(stencil, "D3Q27") == 0 ) - return object ( make_shared< UniformBufferedScheme<stencil::D3Q27> > ( bf ) ); - else { - PyErr_SetString( PyExc_RuntimeError, "Unknown stencil. Allowed values 'D3Q27', 'D3Q19', 'D3Q7'"); - throw error_already_set(); - return object(); - } -} - -template<typename Stencil> -void exportUniformBufferedScheme() -{ - typedef UniformBufferedScheme<Stencil> UNS; - - class_< UNS, shared_ptr<UNS>, boost::noncopyable >( "UniformBufferedScheme", no_init ) - .def( "__call__", &UNS::operator() ) - .def( "communicate", &UNS::communicate ) - .def( "startCommunication", &UNS::startCommunication ) - .def( "wait", &UNS::wait ) - .def( "addPackInfo", &UNS::addPackInfo ) - .def( "addDataToCommunicate", &UNS::addDataToCommunicate ) - ; - -} - -std::string printSetupBlock(const SetupBlock & b ) -{ - std::stringstream out; - out << "SetupBlock at " << b.getAABB(); - return out.str(); -} - - - -void exportBlockForest() -{ - class_< StructuredBlockForest, //NOLINT - shared_ptr<StructuredBlockForest>, - bases<StructuredBlockStorage>, boost::noncopyable > ( "StructuredBlockForest", no_init ); - - class_< SetupBlock, boost::noncopyable > ( "SetupBlock", no_init ) - .add_property("level", &SetupBlock::getLevel) - .add_property("workload", &SetupBlock::getWorkload, &SetupBlock::setWorkload) - .add_property("memory", &SetupBlock::getMemory, &SetupBlock::setMemory) - .add_property("aabb", make_function(&SetupBlock::getAABB, return_value_policy<copy_const_reference>())) - .def("__repr__", &printSetupBlock) - ; - -#ifdef _MSC_VER -# pragma warning(push) -// disable warning boost/python/raw_function.hpp(55): warning C4267: 'argument' : conversion from 'size_t' to 'int', possible loss of data -# pragma warning( disable : 4267 ) -#endif //_MSC_VER - def( "createUniformBlockGrid", raw_function(python_createUniformBlockGrid) ); -#ifdef _MSC_VER -# pragma warning(pop) -#endif //_MSC_VER - - def( "createCustomBlockGrid", createStructuredBlockForest, - (arg("blocks"), arg("cellsPerBlock"), arg("periodic"), - arg("blockExclusionCallback") = object(), - arg("workloadMemoryCallback") = object(), - arg("refinementCallback") = object() , - arg("dx") = 1.0, - arg("processMemoryLimit") = std::numeric_limits<memory_t>::max(), - arg("keepGlobalBlockInformation") = false ) ); -} - -} // namespace domain_decomposition -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/blockforest/python/Exports.h b/src/blockforest/python/Exports.h deleted file mode 100644 index a910b0541..000000000 --- a/src/blockforest/python/Exports.h +++ /dev/null @@ -1,51 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.h -//! \ingroup blockforest -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" - - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "blockforest/python/CommunicationExport.h" - - -namespace walberla { -namespace blockforest { - - - void exportBlockForest(); - - - template<typename Stencils> - void exportModuleToPython() - { - exportBlockForest(); - exportUniformBufferedScheme<Stencils>(); - exportUniformDirectScheme<Stencils>(); - } - -} // namespace blockforest -} // namespace walberla - - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/boundary/python/Exports.h b/src/boundary/python/Exports.h deleted file mode 100644 index 2425f4788..000000000 --- a/src/boundary/python/Exports.h +++ /dev/null @@ -1,39 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace lbm { - - template<typename BoundaryHandlings> - void exportModuleToPython(); - -} // namespace lbm -} // namespace walberla - - -#include "Exports.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/boundary/python/Exports.impl.h b/src/boundary/python/Exports.impl.h deleted file mode 100644 index e6b5d85cb..000000000 --- a/src/boundary/python/Exports.impl.h +++ /dev/null @@ -1,232 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.impl.h -//! \ingroup boundary -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "python_coupling/Manager.h" -#include "python_coupling/helper/SliceToCellInterval.h" -#include "python_coupling/helper/ConfigFromDict.h" -#include "boundary/Boundary.h" -#include "field/FlagField.h" - - -namespace walberla { -namespace boundary { - - namespace internal - { - using python_coupling::localPythonSliceToCellInterval; - - template<typename BH> - shared_ptr<BoundaryConfiguration> boundaryConfFromDict( BH & h, const BoundaryUID & uid, boost::python::dict d ) { - shared_ptr<Config> cfg = python_coupling::configFromPythonDict( d ); - return h.createBoundaryConfiguration( uid, cfg->getGlobalBlock() ); - } - template<typename BH> - void BH_setBoundary1( BH & h, const std::string & name, cell_idx_t x, cell_idx_t y , cell_idx_t z, boost::python::dict conf ) { - h.setBoundary( name,x,y,z, *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_setBoundary2( BH & h, const std::string & name, const boost::python::tuple & index, boost::python::dict conf ) { - h.setBoundary( name, - localPythonSliceToCellInterval( *h.getFlagField() , index ), - *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_forceBoundary1( BH & h, const std::string & name, cell_idx_t x, cell_idx_t y , cell_idx_t z, boost::python::dict conf ) { - h.forceBoundary( name,x,y,z, *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_forceBoundary2( BH & h, const std::string & name, const boost::python::tuple & index, boost::python::dict conf ) { - h.forceBoundary( name, - localPythonSliceToCellInterval( *h.getFlagField() , index ), - *boundaryConfFromDict( h, name, conf) ); - } - - template<typename BH> - void BH_forceBoundary3( BH & h, const GhostLayerField<int,1> & indexField , boost::python::dict boundaryInfo ) - { - using namespace boost::python; - list keys = boundaryInfo.keys(); - - std::map<int, FlagUID > flagUIDs; - std::map<int, shared_ptr<BoundaryConfiguration> > boundaryConfigs; - - for (int i = 0; i < len( keys ); ++i) - { - int key = extract<int>( keys[i] ); - extract<std::string> extracted_str_val ( boundaryInfo[key] ); - extract<dict > extracted_dict_val ( boundaryInfo[key] ); - - if ( extracted_str_val.check() ) - { - std::string boundaryName = extracted_str_val; - flagUIDs[key] = FlagUID ( boundaryName ); - } - else if ( extracted_dict_val.check() ) - { - dict info = extracted_dict_val; - std::string boundaryName = extract<std::string>( info["name"] ); - - dict configDict = extract<dict>( info["config"] ); - - flagUIDs[key] = FlagUID ( boundaryName ); - boundaryConfigs[key] = boundaryConfFromDict( h, boundaryName, configDict); - } - else { - PyErr_SetString( PyExc_ValueError, "Invalid parameter"); - throw error_already_set(); - } - } - - if ( indexField.xyzSize() != h.getFlagField()->xyzSize() || indexField.nrOfGhostLayers() > h.getFlagField()->nrOfGhostLayers() ) { - PyErr_SetString( PyExc_ValueError, "Index field has to have same size as flag field"); - throw error_already_set(); - } - - // iterate over flag field - cell_idx_t gl = cell_idx_c( indexField.nrOfGhostLayers() ); - for( cell_idx_t z = -gl; z < cell_idx_c( indexField.zSize() ) + gl; ++z ) - for( cell_idx_t y = -gl; y < cell_idx_c( indexField.ySize() ) + gl; ++y ) - for( cell_idx_t x = -gl; x < cell_idx_c( indexField.xSize() ) + gl; ++x ) - { - int index = indexField(x,y,z); - if ( flagUIDs.find( index ) != flagUIDs.end() ) - { - if ( boundaryConfigs.find( index ) != boundaryConfigs.end() ) - h.forceBoundary( flagUIDs[index],x,y,z, * boundaryConfigs[index] ); - else - h.forceBoundary( flagUIDs[index],x,y,z ); - } - } - } - - template<typename BH> - void BH_setDomainSlice( BH & h, const boost::python::tuple & index ) { - h.setDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - template<typename BH> - void BH_forceDomainSlice( BH & h, const boost::python::tuple & index ) { - h.forceDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - template<typename BH> - void BH_fillDomainSlice( BH & h, const boost::python::tuple & index ) { - h.fillWithDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_removeDomainSlice( BH & h, const boost::python::tuple & index ) { - h.removeDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_removeBoundarySlice( BH & h, const boost::python::tuple & index ) { - h.removeBoundary( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_clearSlice( BH & h, const boost::python::tuple & index ) { - h.clear( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - - - struct BoundaryHandlingExporter - { - template< typename BH> - void operator() ( python_coupling::NonCopyableWrap<BH> ) - { - using namespace boost::python; - void ( BH::*p_exe1 )( uint_t )= &BH::operator(); - - bool ( BH::*p_isEmpty ) ( cell_idx_t, cell_idx_t, cell_idx_t ) const = &BH::isEmpty ; - bool ( BH::*p_isNearBoundary ) ( cell_idx_t, cell_idx_t, cell_idx_t ) const = &BH::isNearBoundary; - bool ( BH::*p_isBoundary ) ( cell_idx_t, cell_idx_t, cell_idx_t ) const = &BH::isBoundary ; - bool ( BH::*p_isDomain ) ( cell_idx_t, cell_idx_t, cell_idx_t ) const = &BH::isDomain ; - - void ( BH::*p_setDomain ) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::setDomain ; - void ( BH::*p_forceDomain ) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::forceDomain; - void ( BH::*p_fillWithDomain1) ( const uint_t ) = &BH::fillWithDomain; - void ( BH::*p_fillWithDomain2) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::fillWithDomain; - - void ( BH::*p_removeDomain1 ) ( const uint_t ) = &BH::removeDomain; - void ( BH::*p_removeDomain2 ) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::removeDomain; - - void ( BH::*p_removeBoundary1 ) ( const uint_t ) = &BH::removeBoundary; - void ( BH::*p_removeBoundary2 ) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::removeBoundary; - - void ( BH::*p_clear1 ) ( const uint_t ) = &BH::clear; - void ( BH::*p_clear2 ) ( cell_idx_t, cell_idx_t, cell_idx_t )= &BH::clear; - - typename BH::FlagField * ( BH::*p_getFlagField) () = &BH::getFlagField; - - typename BH::flag_t ( BH::*p_getNearBoundaryFlag ) () const = &BH::getNearBoundaryFlag; - typename BH::flag_t ( BH::*p_getBoundaryMask ) () const = &BH::getBoundaryMask; - typename BH::flag_t ( BH::*p_getDomainMask ) () const = &BH::getDomainMask; - - class_< BH, boost::noncopyable > ( "BoundaryHandling", no_init ) - .def( "__call__", p_exe1, ( arg("numberOfGhostLayersToInclude")=0 ) ) - .def( "isEmpty" , p_isEmpty, ( arg("x"), arg("y"), arg("z") ) ) - .def( "isNearBoundary", p_isNearBoundary, ( arg("x"), arg("y"), arg("z") ) ) - .def( "isBoundary" , p_isBoundary, ( arg("x"), arg("y"), arg("z") ) ) - .def( "isDomain" , p_isDomain, ( arg("x"), arg("y"), arg("z") ) ) - .def( "setDomain" , p_setDomain, ( arg("x"), arg("y"), arg("z") ) ) - .def( "setDomain" , BH_forceDomainSlice<BH>, ( arg("slice") ) ) - .def( "forceDomain" , p_forceDomain, ( arg("x"), arg("y"), arg("z") ) ) - .def( "forceDomain" , BH_forceDomainSlice<BH>, ( arg("slice") ) ) - .def( "fillWithDomain", p_fillWithDomain1, ( arg("numberOfGhostLayersToInclude")=0 ) ) - .def( "fillWithDomain", p_fillWithDomain2, ( arg("x"), arg("y"), arg("z") ) ) - .def( "fillWithDomain", BH_fillDomainSlice<BH>, ( arg("slice") ) ) - .def( "setBoundary", &BH_setBoundary1<BH>, ( arg("name"), arg("x"), arg("y"), arg("z"), arg("boundaryParams")=dict() ) ) - .def( "setBoundary", &BH_setBoundary2<BH>, ( arg("name"), arg("slice"), arg("boundaryParams")=dict() ) ) - .def( "forceBoundary", &BH_forceBoundary1<BH>, ( arg("name"), arg("x"), arg("y"), arg("z"), arg("boundaryParams")=dict() ) ) - .def( "forceBoundary", &BH_forceBoundary2<BH>, ( arg("name"), arg("slice"), arg("boundaryParams")=dict() ) ) - .def( "forceBoundary", &BH_forceBoundary3<BH>, ( arg("indexField"), arg("boundaryInfo") ) ) - .def( "removeDomain", p_removeDomain1, ( arg("numberOfGhostLayersToInclude")=0 ) ) - .def( "removeDomain", p_removeDomain2, ( arg("x"), arg("y"), arg("z") ) ) - .def( "removeDomain", BH_removeDomainSlice<BH>, ( arg("slice") ) ) - .def( "removeBoundary", p_removeBoundary1, ( arg("numberOfGhostLayersToInclude")=0 ) ) - .def( "removeBoundary", p_removeBoundary2, ( arg("x"), arg("y"), arg("z") ) ) - .def( "removeBoundary", BH_removeBoundarySlice<BH>,( arg("slice") ) ) - .def( "clear", p_clear1, ( arg("numberOfGhostLayersToInclude")=0 ) ) - .def( "clear", p_clear2, ( arg("x"), arg("y"), arg("z") ) ) - .def( "clear", BH_clearSlice<BH>, ( arg("slice") ) ) - .def( "getFlagField", p_getFlagField, return_internal_reference<>() ) - .def( "getNearBoundaryFlag", p_getNearBoundaryFlag ) - .def( "getBoundaryMask", p_getBoundaryMask ) - .def( "getDomainMask", p_getDomainMask ) - ; - } - }; - } // namespace internal - - template<typename BoundaryHandlings> - void exportModuleToPython() - { - python_coupling::for_each_noncopyable_type< BoundaryHandlings > ( internal::BoundaryHandlingExporter() ); - - auto pythonManager = python_coupling::Manager::instance(); - pythonManager->addBlockDataConversion< BoundaryHandlings> (); - - } - - -} // namespace boundary -} // namespace walberla - - diff --git a/src/communication/UniformMPIDatatypeInfo.h b/src/communication/UniformMPIDatatypeInfo.h index 33e44a873..be8689441 100644 --- a/src/communication/UniformMPIDatatypeInfo.h +++ b/src/communication/UniformMPIDatatypeInfo.h @@ -46,6 +46,14 @@ namespace communication { { public: + //**Construction & Destruction************************************************************************************ + /*! \name Construction & Destruction */ + //@{ + UniformMPIDatatypeInfo() {} + virtual ~UniformMPIDatatypeInfo() {} + //@} + //**************************************************************************************************************** + /*************************************************************************************************************//** * Return the MPI data type that should be used for sending to neighbor in specified direction *****************************************************************************************************************/ diff --git a/src/core/WeakPtrWrapper.h b/src/core/WeakPtrWrapper.h deleted file mode 100644 index 206042290..000000000 --- a/src/core/WeakPtrWrapper.h +++ /dev/null @@ -1,100 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file WeakPtrWrapper.h -//! \ingroup core -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#include "core/DataTypes.h" - - -/* - What is this good for? - - Memory Management of basic waLBerla objects: Use BlockStorage and CommunicationSchemes as example: - - a block storage is held as a shared_ptr - - create a communication scheme: internally the communication scheme - only holds a weak pointer to the block storage i.e. communication does not "own" the block storage. - If the communication would own the block storage and would internally hold a shared_ptr instead of a - weak_ptr, cycles could be created e.g. when a communication object is passed to the block storage, - which happens e.g. when registering communication functors at the block storage itself - -> weak_ptr is necessary to prevent cycles ( another way would be not to store a pointer to - block storage at all which is hardly practicable ) - - trying to communicate after a block storage was deleted leads to an error, which is reasonable - - The problem occurs when exporting this to Python: - - Due to a known and probably never fixed bug, one cannot created weak pointers from shared pointers - received from Python functions. Details here: - - http://stackoverflow.com/questions/8233252/boostpython-and-weak-ptr-stuff-disappearing - - https://svn.boost.org/trac/boost/ticket/3673 - - What works are plain old C pointers -> when compiling with Python plain C pointers should be used instead - of the checked weak pointers -> this is the reason for this wrapper class - - Special attention is necessary when exporting this construct to Python since a block forest may only be - deleted when no communication object points to it. This is ensured in this case via - UniformBufferedSchemeWrapper - */ - - - - - - - -namespace walberla { - - -#ifndef WALBERLA_BUILD_WITH_PYTHON - - - -template<typename T> -class weak_ptr_wrapper : public weak_ptr<T> -{ -public: - weak_ptr_wrapper() {} - weak_ptr_wrapper( const weak_ptr <T> & r ) : weak_ptr<T>(r) {} - weak_ptr_wrapper( const shared_ptr<T> & r ) : weak_ptr<T>(r) {} -}; - - -# else - - // Due to a bug in boost::python weak_ptr cannnot be used: - // http://stackoverflow.com/questions/8233252/boostpython-and-weak-ptr-stuff-disappearing - template<typename T> - class weak_ptr_wrapper - { - public: - weak_ptr_wrapper( const shared_ptr<T> & sp ) - : rawPtr_ ( sp.get() ) - {} - - T * lock() { return rawPtr_; } - - protected: - T * rawPtr_; - }; - - -#endif // WALBERLA_BUILD_WITH_PYTHON - -} // namespace walberla - - diff --git a/src/cuda/CMakeLists.txt b/src/cuda/CMakeLists.txt index 98aa991f0..b701f144f 100644 --- a/src/cuda/CMakeLists.txt +++ b/src/cuda/CMakeLists.txt @@ -4,7 +4,7 @@ # ################################################################################################### -waLBerla_add_module( DEPENDS blockforest core communication domain_decomposition executiontree python_coupling field stencil +waLBerla_add_module( DEPENDS blockforest core communication domain_decomposition executiontree field stencil BUILD_ONLY_IF_FOUND CUDA ) ################################################################################################### \ No newline at end of file diff --git a/src/cuda/communication/UniformGPUScheme.h b/src/cuda/communication/UniformGPUScheme.h index 0dda96a48..ba702c574 100644 --- a/src/cuda/communication/UniformGPUScheme.h +++ b/src/cuda/communication/UniformGPUScheme.h @@ -24,7 +24,6 @@ #include "blockforest/StructuredBlockForest.h" #include "core/mpi/MPIWrapper.h" #include "core/mpi/BufferSystem.h" -#include "core/WeakPtrWrapper.h" #include "domain_decomposition/IBlock.h" #include "stencil/Directions.h" @@ -45,7 +44,7 @@ namespace communication { class UniformGPUScheme { public: - explicit UniformGPUScheme( weak_ptr_wrapper<StructuredBlockForest> bf, + explicit UniformGPUScheme( weak_ptr<StructuredBlockForest> bf, bool sendDirectlyFromGPU = false, const int tag = 5432 ); @@ -60,7 +59,7 @@ namespace communication { private: void setupCommunication(); - weak_ptr_wrapper<StructuredBlockForest> blockForest_; + weak_ptr<StructuredBlockForest> blockForest_; uint_t forestModificationStamp_; bool setupBeforeNextCommunication_; diff --git a/src/cuda/communication/UniformGPUScheme.impl.h b/src/cuda/communication/UniformGPUScheme.impl.h index b39d9d054..03b65f3b5 100644 --- a/src/cuda/communication/UniformGPUScheme.impl.h +++ b/src/cuda/communication/UniformGPUScheme.impl.h @@ -27,7 +27,7 @@ namespace communication { template<typename Stencil> -UniformGPUScheme<Stencil>::UniformGPUScheme( weak_ptr_wrapper <StructuredBlockForest> bf, +UniformGPUScheme<Stencil>::UniformGPUScheme( weak_ptr <StructuredBlockForest> bf, bool sendDirectlyFromGPU, const int tag ) : blockForest_( bf ), diff --git a/src/cuda/python/Exports.impl.h b/src/cuda/python/Exports.impl.h deleted file mode 100644 index fa1352db9..000000000 --- a/src/cuda/python/Exports.impl.h +++ /dev/null @@ -1,407 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file FieldExport.cpp -//! \ingroup cuda -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#include "core/logging/Logging.h" -#include "cuda/GPUField.h" -#include "cuda/communication/GPUPackInfo.h" -#include "cuda/AddGPUFieldToStorage.h" -#include "cuda/FieldCopy.h" -#include "cuda/GPUField.h" -#include "field/communication/UniformMPIDatatypeInfo.h" -#include "field/AddToStorage.h" -#include "field/python/FieldExport.h" -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" - -#include <type_traits> -#include <iostream> - -namespace walberla { -namespace cuda { - - - -namespace internal { - - //=================================================================================================================== - // - // Field export - // - //=================================================================================================================== - - template<typename GpuField_T> - uint64_t gpufield_ptr(const GpuField_T & gpuField) - { - return reinterpret_cast<uint64_t>(gpuField.pitchedPtr().ptr); - } - - template<typename GpuField_T> - std::string gpufield_dtypeStr(const GpuField_T & ) - { - return std::string(field::internal::PythonFormatString<typename GpuField_T::value_type>::get()); - } - - struct GpuFieldExporter - { - template< typename GpuField_T> - void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) - { - using namespace boost::python; - - class_<GpuField_T, shared_ptr<GpuField_T>, boost::noncopyable>( "GpuField", no_init ) - .add_property("layout", &field::internal::field_layout < GpuField_T > ) - .add_property("size", &field::internal::field_size < GpuField_T > ) - .add_property("sizeWithGhostLayers", &field::internal::field_sizeWithGhostLayer< GpuField_T > ) - .add_property("allocSize", &field::internal::field_allocSize < GpuField_T > ) - .add_property("strides", &field::internal::field_strides < GpuField_T > ) - .add_property("offsets", &field::internal::field_offsets < GpuField_T > ) - .add_property("ptr", &gpufield_ptr < GpuField_T > ) - .add_property("dtypeStr", &gpufield_dtypeStr < GpuField_T > ) - .add_property("isPitchedMem", &GpuField_T::isPitchedMem ) - .def("swapDataPointers", &field::internal::field_swapDataPointers < GpuField_T > ) - .add_property("nrOfGhostLayers", &GpuField_T::nrOfGhostLayers ) - .def("cloneUninitialized", &GpuField_T::cloneUninitialized, return_value_policy<manage_new_object>()) - ; - - - using field::communication::PackInfo; - using communication::GPUPackInfo; - class_< GPUPackInfo<GpuField_T>, - shared_ptr< GPUPackInfo<GpuField_T> >, - bases<walberla::communication::UniformPackInfo>, - boost::noncopyable >( "GpuFieldPackInfo", no_init ); - - using field::communication::UniformMPIDatatypeInfo; - class_< UniformMPIDatatypeInfo<GpuField_T>, - shared_ptr< UniformMPIDatatypeInfo<GpuField_T> >, - bases<walberla::communication::UniformMPIDatatypeInfo>, - boost::noncopyable >( "GpuFieldMPIDataTypeInfo", no_init ); - - } - }; - - - //=================================================================================================================== - // - // createField - // - //=================================================================================================================== - - class CreateFieldExporter - { - public: - CreateFieldExporter( uint_t xs, uint_t ys, uint_t zs, uint_t fs, uint_t gl, - Layout layout, const boost::python::object & type, bool usePitchedMem, - const shared_ptr<boost::python::object> & resultPointer ) - : xs_( xs ), ys_(ys), zs_(zs), fs_(fs), gl_(gl), - layout_( layout), type_( type ), usePitchedMem_( usePitchedMem ) , resultPointer_( resultPointer ) - {} - - template< typename GpuField_T> - void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) - { - using namespace boost::python; - typedef typename GpuField_T::value_type T; - if( python_coupling::isCppEqualToPythonType<T>( (PyTypeObject *)type_.ptr() ) ) - { - *resultPointer_ = object( make_shared< GPUField<T> >( xs_,ys_,zs_, fs_, gl_, layout_, usePitchedMem_ ) ); - } - } - - private: - uint_t xs_; - uint_t ys_; - uint_t zs_; - uint_t fs_; - uint_t gl_; - Layout layout_; - boost::python::object type_; - bool usePitchedMem_; - shared_ptr<boost::python::object> resultPointer_; - }; - - template<typename GpuFields> - boost::python::object createPythonGpuField( boost::python::list size, - boost::python::object type, - uint_t ghostLayers, - Layout layout, - bool usePitchedMem) - { - using namespace boost::python; - uint_t xSize = extract<uint_t> ( size[0] ); - uint_t ySize = extract<uint_t> ( size[1] ); - uint_t zSize = extract<uint_t> ( size[2] ); - uint_t sizeLen = uint_c( len( size ) ); - uint_t fSize = 1; - if ( sizeLen == 4 ) - fSize = extract<uint_t> ( size[3] ); - - if ( ! PyType_Check( type.ptr() ) ) { - PyErr_SetString( PyExc_RuntimeError, "Invalid 'type' parameter"); - throw error_already_set(); - } - - auto result = make_shared<boost::python::object>(); - CreateFieldExporter exporter( xSize,ySize, zSize, fSize, ghostLayers, layout, type, usePitchedMem, result ); - python_coupling::for_each_noncopyable_type< GpuFields >( exporter ); - - if ( *result == object() ) - { - PyErr_SetString( PyExc_ValueError, "Cannot create field of this type"); - throw error_already_set(); - } - else { - return *result; - } - } - - - //=================================================================================================================== - // - // addToStorage - // - //=================================================================================================================== - - class AddToStorageExporter - { - public: - AddToStorageExporter( const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, uint_t fs, uint_t gl, Layout layout, - const boost::python::object & type, - bool usePitchedMem ) - : blocks_( blocks ), name_( name ), fs_( fs ), - gl_(gl),layout_( layout), type_( type ), usePitchedMem_(usePitchedMem), found_(false) - {} - - template< typename GpuField_T> - void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) - { - typedef typename GpuField_T::value_type T; - if( python_coupling::isCppEqualToPythonType<T>( (PyTypeObject *)type_.ptr() ) ) - { - WALBERLA_ASSERT(!found_); - addGPUFieldToStorage<GPUField<T> >(blocks_, name_, fs_, layout_, gl_, usePitchedMem_); - found_ = true; - } - } - - bool successful() const { return found_; } - private: - shared_ptr< StructuredBlockStorage > blocks_; - std::string name_; - uint_t fs_; - uint_t gl_; - Layout layout_; - boost::python::object type_; - bool usePitchedMem_; - bool found_; - }; - - template<typename GpuFields> - void addToStorage( const shared_ptr<StructuredBlockStorage> & blocks, const std::string & name, - boost::python::object type, uint_t fs, uint_t gl, Layout layout, bool usePitchedMem ) - { - using namespace boost::python; - - if ( ! PyType_Check( type.ptr() ) ) { - PyErr_SetString( PyExc_RuntimeError, "Invalid 'type' parameter"); - throw error_already_set(); - } - - auto result = make_shared<boost::python::object>(); - AddToStorageExporter exporter( blocks, name, fs, gl, layout, type, usePitchedMem ); - python_coupling::for_each_noncopyable_type<GpuFields>( std::ref(exporter) ); - - if ( ! exporter.successful() ) { - PyErr_SetString( PyExc_ValueError, "Adding Field failed."); - throw error_already_set(); - } - } - - - //=================================================================================================================== - // - // createPackInfo Export - // - //=================================================================================================================== - - template< typename GPUField_T > - boost::python::object createGPUPackInfoToObject( BlockDataID bdId, uint_t numberOfGhostLayers ) - { - using cuda::communication::GPUPackInfo; - if ( numberOfGhostLayers > 0 ) - return boost::python::object( make_shared< GPUPackInfo<GPUField_T> >( bdId, numberOfGhostLayers ) ); - else - return boost::python::object( make_shared< GPUPackInfo<GPUField_T> >( bdId ) ); - } - - FunctionExporterClass( createGPUPackInfoToObject, boost::python::object( BlockDataID, uint_t ) ); - - template< typename GpuFields> - boost::python::object createPackInfo( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName, uint_t numberOfGhostLayers ) - { - using cuda::communication::GPUPackInfo; - - auto bdId = python_coupling::blockDataIDFromString( *bs, blockDataName ); - if ( bs->begin() == bs->end() ) { - // if no blocks are on this field an arbitrary PackInfo can be returned - return createGPUPackInfoToObject< GPUField<real_t> > ( bdId, numberOfGhostLayers ); - } - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<GpuFields, Exporter_createGPUPackInfoToObject > dispatcher( firstBlock ); - return dispatcher( bdId )( bdId, numberOfGhostLayers ) ; - } - - - //=================================================================================================================== - // - // createMPIDatatypeInfo - // - //=================================================================================================================== - - - template< typename GpuField_T > - boost::python::object createMPIDatatypeInfoToObject( BlockDataID bdId, uint_t numberOfGhostLayers ) - { - using field::communication::UniformMPIDatatypeInfo; - if ( numberOfGhostLayers > 0 ) - return boost::python::object( make_shared< UniformMPIDatatypeInfo<GpuField_T> >( bdId, numberOfGhostLayers ) ); - else - return boost::python::object( make_shared< UniformMPIDatatypeInfo<GpuField_T> >( bdId ) ); - } - - FunctionExporterClass( createMPIDatatypeInfoToObject, boost::python::object( BlockDataID, uint_t ) ); - - template< typename GpuFields> - boost::python::object createMPIDatatypeInfo( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName, - uint_t numberOfGhostLayers) - { - auto bdId = python_coupling::blockDataIDFromString( *bs, blockDataName ); - if ( bs->begin() == bs->end() ) { - // if no blocks are on this field an arbitrary MPIDatatypeInfo can be returned - return createMPIDatatypeInfoToObject< GPUField<real_t> > ( bdId, numberOfGhostLayers ); - } - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<GpuFields, Exporter_createMPIDatatypeInfoToObject > dispatcher( firstBlock ); - return dispatcher( bdId )( bdId, numberOfGhostLayers ); - } - - - //=================================================================================================================== - // - // fieldCopy - // - //=================================================================================================================== - - template<typename Field_T> - void copyFieldToGpuDispatch(const shared_ptr<StructuredBlockStorage> & bs, - BlockDataID cpuFieldId, BlockDataID gpuFieldId, bool toGpu) - { - typedef cuda::GPUField<typename Field_T::value_type> GpuField; - if(toGpu) - cuda::fieldCpy<GpuField, Field_T>(bs, gpuFieldId, cpuFieldId); - else - cuda::fieldCpy<Field_T, GpuField>(bs, cpuFieldId, gpuFieldId); - } - FunctionExporterClass( copyFieldToGpuDispatch, - void( const shared_ptr<StructuredBlockStorage> &, BlockDataID, BlockDataID, bool ) ); - - template< typename FieldTypes > - void transferFields( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & gpuFieldId, const std::string & cpuFieldId, bool toGpu) - { - if( bs->begin() == bs->end()) { - return; - }; - - auto dstBdId = python_coupling::blockDataIDFromString( *bs, gpuFieldId ); - auto srcBdId = python_coupling::blockDataIDFromString( *bs, cpuFieldId ); - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<FieldTypes, Exporter_copyFieldToGpuDispatch> dispatcher( firstBlock ); - dispatcher( srcBdId )( bs, srcBdId, dstBdId, toGpu ); - } - - template< typename FieldTypes> - void copyFieldToGpu(const shared_ptr<StructuredBlockStorage> & bs, - const std::string & gpuFieldId, const std::string & cpuFieldId) - { - transferFields<FieldTypes>(bs, gpuFieldId, cpuFieldId, true); - } - - template< typename FieldTypes> - void copyFieldToCpu(const shared_ptr<StructuredBlockStorage> & bs, - const std::string & gpuFieldId, const std::string & cpuFieldId) - { - transferFields<FieldTypes>(bs, gpuFieldId, cpuFieldId, false); - } - -} // namespace internal - - - - -template<typename GpuFields, typename CpuFields > -void exportModuleToPython() -{ - python_coupling::ModuleScope fieldModule( "cuda" ); - - using namespace boost::python; - - python_coupling::for_each_noncopyable_type<GpuFields>( internal::GpuFieldExporter() ); - - def( "createGpuField", &internal::createPythonGpuField<GpuFields>, ( ( arg("size") ), - ( arg("type") ), - ( arg("ghostLayers") = uint_t(1) ), - ( arg("layout") = field::zyxf), - ( arg("usePitchedMem") = true ) ) ); - - - def( "addGpuFieldToStorage", &internal::addToStorage<GpuFields>, ( ( arg("blocks") ), - ( arg("name") ), - ( arg("type") ), - ( arg("fSize") = 1 ), - ( arg("ghostLayers") = uint_t(1) ), - ( arg("layout") = field::zyxf ), - ( arg("usePitchedMem") = object() ) ) ); - - def( "createMPIDatatypeInfo",&internal::createMPIDatatypeInfo<GpuFields>, ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) ); - def( "createPackInfo", &internal::createPackInfo<GpuFields>, ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) ); - - def( "copyFieldToGpu", &internal::copyFieldToGpu<CpuFields>, (arg("blocks"), ("gpuFieldId"), ("cpuFieldId"))); - def( "copyFieldToCpu", &internal::copyFieldToCpu<CpuFields>, (arg("blocks"), ("gpuFieldId"), ("cpuFieldId"))); -} - - - - - -} // namespace cuda -} // namespace walberla - - diff --git a/src/field/Traits.h b/src/field/Traits.h deleted file mode 100644 index bdde7f0c9..000000000 --- a/src/field/Traits.h +++ /dev/null @@ -1,61 +0,0 @@ - -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Traits.h -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - - -namespace walberla { -namespace field { - - - - - template<typename Pair> - struct ToField - { - typedef Field< typename Pair::first, Pair::second::value > type; - }; - - template<typename TupleList> - struct ToFieldList - { - typedef mpl::transform< TupleList, ToField<mpl::_1> >::type type; - }; - - template<typename Pair> - struct ToGhostLayerField - { - typedef GhostLayerField< typename Pair::first, Pair::second::value > type; - }; - - template<typename TupleList> - struct ToGhostLayerFieldList - { - typedef mpl::transform< TupleList, ToGhostLayerField<mpl::_1> >::type type; - }; - - -} // namespace field -} // namespace walberla - - - diff --git a/src/field/python/CommunicationExport.impl.h b/src/field/python/CommunicationExport.impl.h deleted file mode 100644 index 15066bcb0..000000000 --- a/src/field/python/CommunicationExport.impl.h +++ /dev/null @@ -1,260 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file CommunicationExport.impl.h -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "python_coupling/PythonWrapper.h" - - -#ifdef WALBERLA_BUILD_WITH_PYTHON - - -#include "field/communication/PackInfo.h" -#include "field/communication/StencilRestrictedPackInfo.h" -#include "field/communication/UniformMPIDatatypeInfo.h" - -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" -#include "python_coupling/helper/MplHelpers.h" - -#include "stencil/D2Q9.h" -#include "stencil/D3Q7.h" -#include "stencil/D3Q15.h" -#include "stencil/D3Q19.h" -#include "stencil/D3Q27.h" - - -namespace walberla { -namespace field { - - -namespace internal { - - //=================================================================================================================== - // - // createStencilRestrictedPackInfo Export - // - //=================================================================================================================== - - template< typename FieldType > - typename std::enable_if<FieldType::F_SIZE == 27, boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID bdId ) - { - typedef GhostLayerField<typename FieldType::value_type, 27> GlField_T; - using field::communication::StencilRestrictedPackInfo; - return boost::python::object( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q27> >( bdId) ); - } - - template< typename FieldType > - typename std::enable_if<FieldType::F_SIZE == 19, boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID bdId ) - { - typedef GhostLayerField<typename FieldType::value_type, 19> GlField_T; - using field::communication::StencilRestrictedPackInfo; - return boost::python::object( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q19> >( bdId) ); - } - - template< typename FieldType > - typename std::enable_if<FieldType::F_SIZE == 15, boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID bdId ) - { - typedef GhostLayerField<typename FieldType::value_type, 15> GlField_T; - using field::communication::StencilRestrictedPackInfo; - return boost::python::object( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q15> >( bdId) ); - } - - template< typename FieldType > - typename std::enable_if<FieldType::F_SIZE == 7, boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID bdId ) - { - typedef GhostLayerField<typename FieldType::value_type, 7> GlField_T; - using field::communication::StencilRestrictedPackInfo; - return boost::python::object( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q7> >( bdId) ); - } - - template< typename FieldType > - typename std::enable_if<FieldType::F_SIZE == 9, boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID bdId ) - { - typedef GhostLayerField<typename FieldType::value_type, 9> GlField_T; - using field::communication::StencilRestrictedPackInfo; - return boost::python::object( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D2Q9> >( bdId) ); - } - - template< typename FieldType > - typename std::enable_if<!(FieldType::F_SIZE == 9 || - FieldType::F_SIZE == 7 || - FieldType::F_SIZE == 15 || - FieldType::F_SIZE == 19 || - FieldType::F_SIZE == 27), boost::python::object>::type - createStencilRestrictedPackInfoObject( BlockDataID ) - { - PyErr_SetString( PyExc_ValueError, "This works only for fields with fSize in 7, 9, 15, 19 or 27" ); - throw boost::python::error_already_set(); - } - - FunctionExporterClass( createStencilRestrictedPackInfoObject, boost::python::object( BlockDataID ) ); - - template< typename FieldVector> - boost::python::object createStencilRestrictedPackInfo( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName ) - { - auto bdId = python_coupling::blockDataIDFromString( *bs, blockDataName ); - if ( bs->begin() == bs->end() ) { - // if no blocks are on this field an arbitrary PackInfo can be returned - return createStencilRestrictedPackInfoObject< GhostLayerField<real_t,1> > ( bdId ); - } - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<FieldVector, Exporter_createStencilRestrictedPackInfoObject > dispatcher( firstBlock ); - return dispatcher( bdId )( bdId ) ; - } - - //=================================================================================================================== - // - // createPackInfo Export - // - //=================================================================================================================== - - template< typename FieldType > - boost::python::object createPackInfoToObject( BlockDataID bdId, uint_t numberOfGhostLayers ) - { - typedef typename FieldType::value_type T; - const uint_t F_SIZE = FieldType::F_SIZE; - typedef GhostLayerField<T,F_SIZE> GlField_T; - if ( numberOfGhostLayers > 0 ) - return boost::python::object( make_shared< field::communication::PackInfo<GlField_T> >( bdId, numberOfGhostLayers ) ); - else - return boost::python::object( make_shared< field::communication::PackInfo<GlField_T> >( bdId ) ); - } - - FunctionExporterClass( createPackInfoToObject, boost::python::object( BlockDataID, uint_t ) ); - - template< typename FieldVector> - boost::python::object createPackInfo( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName, uint_t numberOfGhostLayers ) - { - auto bdId = python_coupling::blockDataIDFromString( *bs, blockDataName ); - if ( bs->begin() == bs->end() ) { - // if no blocks are on this field an arbitrary PackInfo can be returned - return createPackInfoToObject< GhostLayerField<real_t,1> > ( bdId, numberOfGhostLayers ); - } - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<FieldVector, Exporter_createPackInfoToObject > dispatcher( firstBlock ); - return dispatcher( bdId )( bdId, numberOfGhostLayers ) ; - } - - - //=================================================================================================================== - // - // createMPIDatatypeInfo - // - //=================================================================================================================== - - - template< typename FieldType > - boost::python::object createMPIDatatypeInfoToObject( BlockDataID bdId, uint_t numberOfGhostLayers ) - { - typedef typename FieldType::value_type T; - const uint_t F_SIZE = FieldType::F_SIZE; - typedef GhostLayerField<T,F_SIZE> GlField_T; - using field::communication::UniformMPIDatatypeInfo; - - if ( numberOfGhostLayers > 0 ) - return boost::python::object( make_shared< UniformMPIDatatypeInfo<GlField_T> >( bdId, numberOfGhostLayers ) ); - else - return boost::python::object( make_shared< UniformMPIDatatypeInfo<GlField_T> >( bdId ) ); - } - - FunctionExporterClass( createMPIDatatypeInfoToObject, boost::python::object( BlockDataID, uint_t ) ); - - template< typename FieldVector> - boost::python::object createMPIDatatypeInfo( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName, - uint_t numberOfGhostLayers) - { - auto bdId = python_coupling::blockDataIDFromString( *bs, blockDataName ); - if ( bs->begin() == bs->end() ) { - // if no blocks are on this field an arbitrary MPIDatatypeInfo can be returned - return createMPIDatatypeInfoToObject< GhostLayerField<real_t,1> > ( bdId, numberOfGhostLayers ); - } - - IBlock * firstBlock = & ( * bs->begin() ); - python_coupling::Dispatcher<FieldVector, Exporter_createMPIDatatypeInfoToObject > dispatcher( firstBlock ); - return dispatcher( bdId )( bdId, numberOfGhostLayers ); - } - - template< typename T> - void exportStencilRestrictedPackInfo() - { - using field::communication::StencilRestrictedPackInfo; - using namespace boost::python; - - { - typedef StencilRestrictedPackInfo<GhostLayerField<T, 9>, stencil::D2Q9> Pi; - class_< Pi, shared_ptr<Pi>, bases<walberla::communication::UniformPackInfo>, boost::noncopyable >( "StencilRestrictedPackInfo", no_init ); - } - { - typedef StencilRestrictedPackInfo<GhostLayerField<T, 7>, stencil::D3Q7> Pi; - class_< Pi, shared_ptr<Pi>, bases<walberla::communication::UniformPackInfo>, boost::noncopyable >( "StencilRestrictedPackInfo", no_init ); - } - { - typedef StencilRestrictedPackInfo<GhostLayerField<T, 15>, stencil::D3Q15> Pi; - class_< Pi, shared_ptr<Pi>, bases<walberla::communication::UniformPackInfo>, boost::noncopyable >( "StencilRestrictedPackInfo", no_init ); - } - { - typedef StencilRestrictedPackInfo<GhostLayerField<T, 19>, stencil::D3Q19> Pi; - class_< Pi, shared_ptr<Pi>, bases<walberla::communication::UniformPackInfo>, boost::noncopyable >( "StencilRestrictedPackInfo", no_init ); - } - { - typedef StencilRestrictedPackInfo<GhostLayerField<T, 27>, stencil::D3Q27> Pi; - class_< Pi, shared_ptr<Pi>, bases<walberla::communication::UniformPackInfo>, boost::noncopyable >( "StencilRestrictedPackInfo", no_init ); - } - - } - -} // namespace internal - - - - - -template<typename FieldTypes> -void exportCommunicationClasses() -{ - using namespace boost::python; - - internal::exportStencilRestrictedPackInfo<float>(); - internal::exportStencilRestrictedPackInfo<double>(); - - def( "createMPIDatatypeInfo",&internal::createMPIDatatypeInfo<FieldTypes>, ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) ); - def( "createPackInfo", &internal::createPackInfo<FieldTypes>, ( arg("blocks"), arg("blockDataName"), arg("numberOfGhostLayers" ) =0 ) ); - def( "createStencilRestrictedPackInfo", &internal::createStencilRestrictedPackInfo<FieldTypes>, - (arg("blocks"), arg("blockDataName") )); -} - - -} // namespace moduleName -} // namespace walberla - - - - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/field/python/FieldExport.h b/src/field/python/FieldExport.h deleted file mode 100644 index e7bdedb4f..000000000 --- a/src/field/python/FieldExport.h +++ /dev/null @@ -1,65 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file FieldExport.h -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#ifdef WALBERLA_BUILD_WITH_PYTHON - - -#include <string> - -namespace walberla { -namespace field { - - - //******************************************************************************************************************* - /*! Exports all Fields given in the Sequence - * - * Put only Fields in the sequence! The corresponding GhostLayerFields and FlagFields are exported automatically - * - * \warning Make sure that the same adaptor type is exported only once! - */ - //******************************************************************************************************************* - template<typename FieldTypes > - void exportFields(); - - - - //******************************************************************************************************************* - /*! Exports all GhostLayerFieldAdaptors given in the Sequence - * - * \warning Make sure that the same adaptor type is exported only once! - */ - //******************************************************************************************************************* - template<typename AdaptorTypes> - void exportGhostLayerFieldAdaptors(); - - template<typename AdaptorType> - void exportGhostLayerFieldAdaptor(); - - -} // namespace field -} // namespace walberla - -#include "FieldExport.impl.h" - - -#endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/field/python/FieldExport.impl.h b/src/field/python/FieldExport.impl.h deleted file mode 100644 index 83e3b4239..000000000 --- a/src/field/python/FieldExport.impl.h +++ /dev/null @@ -1,1396 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file FieldExport.cpp -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - - -#include "core/logging/Logging.h" -#include "core/VectorTrait.h" -#include "field/Field.h" -#include "field/GhostLayerField.h" -#include "field/FlagField.h" -#include "field/communication/PackInfo.h" -#include "field/communication/UniformMPIDatatypeInfo.h" - -#include "field/AddToStorage.h" -#include "field/python/GatherExport.h" -#include "field/vtk/VTKWriter.h" -#include "field/vtk/FlagFieldMapping.h" - -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" - -#include <boost/mpl/vector.hpp> - -#include <iostream> -#include <type_traits> - -namespace walberla { -namespace field { - - - -namespace internal { - - //=================================================================================================================== - // - // Buffer Protocol for Fields - // - //=================================================================================================================== - - - - /* This section implements the Python buffer protocol for walberla::Field's - * - * - Why? The buffer protocol enables other Python types to use the memory belonging to a field. - * One can for example construct a numpy.array that operates on the field data - * - How? a = numpy.asarray( myWalberlaField.buffer() ) - * creates a numpy array which uses the field data in a read-write way! no data is copied - * - Python buffer protocol: http://docs.python.org/dev/c-api/buffer.html - * - Why so complicated? - * boost::python does not yet (as in version 1.55) support the buffer protocol - * so everything has to be written in the native Python C interface. - * In order to export the Field with boost python and keep the native C interface part as - * small as possible, a new Type called FieldBuffer is introduced which is exported in the - * C interface. This type can only be created using the buffer() function of the field. - * - * - * - Lifetime issues: - * 0) f = walberla.create_field( ( 5,3,2) ) - * 1) buf = f.buffer(): - * - creates a FieldBuffer object which has as only member the Field - * - f is not deallocated as long as 'buf' exists - * 2) a = numpy.asarray( buf ) - * - calls 'fieldbuffer_get' which creates a Py_buffer, - * extracts the information, then immediately calls 'fieldbuffer_release' - * to clean up the Py_buffer. - * - buf still exists ( fieldbuffer_release only cleans up Py_buffer not - * the FieldBuffer object 'buf' ) - * 3) del f - * del b - * - the buffer object b is not deallocated since a still has a reference to it - * - since b is not deleted f is not deleted since b has still a reference to it - * i.e a -> b -> f - * 4) when a is deleted everything can be cleaned up, which means that fieldbuffer_dealloc - * is called, which decrements the reference count for f, so that f can be deallocated if - * not used otherwise - * - */ - template<class T> struct PythonFormatString { inline static char * get() { static char value [] = "B"; return value; } }; - - template<> struct PythonFormatString<double> { inline static char * get() { static char value [] = "d"; return value; } }; - template<> struct PythonFormatString<float> { inline static char * get() { static char value [] = "f"; return value; } }; - template<> struct PythonFormatString<unsigned short> { inline static char * get() { static char value [] = "H"; return value; } }; - template<> struct PythonFormatString<int> { inline static char * get() { static char value [] = "i"; return value; } }; - template<> struct PythonFormatString<unsigned int> { inline static char * get() { static char value [] = "I"; return value; } }; - template<> struct PythonFormatString<long> { inline static char * get() { static char value [] = "l"; return value; } }; - template<> struct PythonFormatString<unsigned long> { inline static char * get() { static char value [] = "L"; return value; } }; - template<> struct PythonFormatString<long long> { inline static char * get() { static char value [] = "q"; return value; } }; - template<> struct PythonFormatString<unsigned long long>{ inline static char * get() { static char value [] = "Q"; return value; } }; - - - typedef struct { - PyObject_HEAD - PyObject * field; - PyObject * fieldAlloc; - void * fieldData; - } FieldBufferPyObject; - - - template<typename T, uint_t fs> - struct FieldBufferGetDispatch - { - static int get( FieldBufferPyObject * exporter, Py_buffer * view, int flags, bool withGhostLayer ) - { - namespace bp = boost::python; - - bp::object fieldObject ( bp::handle<>(bp::borrowed( exporter->field ) ) ); - Field<T,fs> * field = bp::extract< Field<T,fs> * > ( fieldObject ); - - bp::object fieldAllocObject ( bp::handle<>(bp::borrowed( exporter->fieldAlloc ) ) ); - FieldAllocator<T> * fieldAlloc = bp::extract< FieldAllocator<T> * > ( fieldAllocObject ); - fieldAlloc->incrementReferenceCount( field->data() ); - - view->obj = (PyObject*) exporter; - Py_INCREF( view->obj ); - - uint_t size[3]; - auto glField = dynamic_cast<GhostLayerField<T,fs> * >( field ); - if ( glField && withGhostLayer ) - { - size[0] = glField->xSizeWithGhostLayer(); - size[1] = glField->ySizeWithGhostLayer(); - size[2] = glField->zSizeWithGhostLayer(); - cell_idx_t gl = cell_idx_c( glField->nrOfGhostLayers() ); - view->buf = &( field->get( -gl, -gl, -gl,0 ) ); - } - else - { - size[0] = field->xSize(); - size[1] = field->ySize(); - size[2] = field->zSize(); - view->buf = & ( field->get(0,0,0,0) ) ; - } - - - // Mandatory - view->len = Py_ssize_t( size[0] * size[1] * size[2] * fs * sizeof(T) ); - view->itemsize = sizeof( T ); - - view->ndim = 4; - - view->format = NULL; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = PythonFormatString<T>::get(); - - view->shape=NULL; - if ((flags & PyBUF_ND) == PyBUF_ND) - { - view->shape = new Py_ssize_t[4]; - view->shape[0u] = Py_ssize_t( size[0u] ); - view->shape[1u] = Py_ssize_t( size[1u] ); - view->shape[2u] = Py_ssize_t( size[2u] ); - view->shape[3u] = Py_ssize_t( field->fSize() ); - } - - view->strides = NULL; - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) - { - view->strides = new Py_ssize_t[4u]; - view->strides[0u] = Py_ssize_t( uint_c( field->xStride() ) * sizeof(T) ); - view->strides[1u] = Py_ssize_t( uint_c( field->yStride() ) * sizeof(T) ); - view->strides[2u] = Py_ssize_t( uint_c( field->zStride() ) * sizeof(T) ); - view->strides[3u] = Py_ssize_t( uint_c( field->fStride() ) * sizeof(T) ); - } - - view->suboffsets = NULL; - view->internal = NULL; - view->readonly = false; - - // We don't need the field any more. For freeing only the allocator and the field data is necessary - Py_DECREF( exporter->field ); - exporter->field = NULL; - - return 0; - } - }; - - template<typename VectorType> - struct FieldBufferGetDispatch<VectorType,1> - { - static int get( FieldBufferPyObject * exporter, Py_buffer * view, int flags, bool withGhostLayer ) - { - namespace bp = boost::python; - - typedef VectorTrait<VectorType> VecTrait; - typedef typename VecTrait::OutputType ElementType; - - static_assert( sizeof(VectorType) == VecTrait::F_SIZE*sizeof(ElementType), - "Creating Python Memory View works only for vectors types that hold their elements consecutively in memory" ); - - bp::object fieldObject ( bp::handle<>(bp::borrowed( exporter->field ) ) ); - Field<VectorType,1> * field = bp::extract< Field<VectorType,1> * > ( fieldObject ); - - bp::object fieldAllocObject ( bp::handle<>(bp::borrowed( exporter->fieldAlloc ) ) ); - FieldAllocator<VectorType> * fieldAlloc = bp::extract< FieldAllocator<VectorType> * > ( fieldAllocObject ); - fieldAlloc->incrementReferenceCount( field->data() ); - - view->obj = (PyObject*) exporter; - Py_INCREF( view->obj ); - - uint_t size[3]; - auto glField = dynamic_cast<GhostLayerField<VectorType,1> * >( field ); - if ( glField && withGhostLayer ) - { - size[0] = glField->xSizeWithGhostLayer(); - size[1] = glField->ySizeWithGhostLayer(); - size[2] = glField->zSizeWithGhostLayer(); - cell_idx_t gl = cell_idx_c( glField->nrOfGhostLayers() ); - view->buf = &( field->get( -gl, -gl, -gl,0 ) ); - } - else - { - size[0] = field->xSize(); - size[1] = field->ySize(); - size[2] = field->zSize(); - view->buf = & ( field->get(0,0,0,0) ) ; - } - - - // Mandatory - view->len = Py_ssize_t( size[0] * size[1] * size[2] * VecTrait::F_SIZE * sizeof(ElementType) ); - view->itemsize = sizeof( ElementType ); - - view->ndim = 4; - - view->format = NULL; - if ((flags & PyBUF_FORMAT) == PyBUF_FORMAT) - view->format = PythonFormatString<ElementType>::get(); - - view->shape=NULL; - if ((flags & PyBUF_ND) == PyBUF_ND) - { - view->shape = new Py_ssize_t[4]; - view->shape[0u] = Py_ssize_t( size[0u] ); - view->shape[1u] = Py_ssize_t( size[1u] ); - view->shape[2u] = Py_ssize_t( size[2u] ); - view->shape[3u] = Py_ssize_t( VecTrait::F_SIZE ); - } - - view->strides = NULL; - if ((flags & PyBUF_STRIDES) == PyBUF_STRIDES) - { - view->strides = new Py_ssize_t[4u]; - view->strides[0u] = Py_ssize_t( uint_c( field->xStride() ) * VecTrait::F_SIZE * sizeof(ElementType) ); - view->strides[1u] = Py_ssize_t( uint_c( field->yStride() ) * VecTrait::F_SIZE * sizeof(ElementType) ); - view->strides[2u] = Py_ssize_t( uint_c( field->zStride() ) * VecTrait::F_SIZE * sizeof(ElementType) ); - view->strides[3u] = Py_ssize_t( sizeof(ElementType) ); - } - - view->suboffsets = NULL; - view->internal = NULL; - view->readonly = false; - - // We don't need the field any more. For freeing only the allocator and the field data is necessary - Py_DECREF( exporter->field ); - exporter->field = NULL; - - return 0; - } - }; - - template<typename T, uint_t fs> - int fieldbuffer_get_withGl ( FieldBufferPyObject * exporter, Py_buffer * view, int flags ) - { - return FieldBufferGetDispatch<T,fs>::get( exporter, view, flags, true ); - } - - template<typename T, uint_t fs> - int fieldbuffer_get ( FieldBufferPyObject * exporter, Py_buffer * view, int flags ) - { - return FieldBufferGetDispatch<T,fs>::get( exporter, view, flags, false ); - } - - - template<typename T, uint_t fs> - int fieldbuffer_release ( PyObject * /*exporter*/, Py_buffer * view ) - { - delete [] view->strides; - delete [] view->shape; - //std::cout << "Releasing Field Buffer " << std::endl; - return 0; - } - - - template<typename T, uint_t fs> - static void fieldbuffer_dealloc( FieldBufferPyObject * exporter ) - { - namespace bp = boost::python; - bp::object fieldAllocObject ( bp::handle<>(bp::borrowed( exporter->fieldAlloc ) ) ); - FieldAllocator<T> * fieldAlloc = bp::extract< FieldAllocator<T> * > ( fieldAllocObject ); - - fieldAlloc->decrementReferenceCount( (T*) exporter->fieldData ); - - Py_DECREF( exporter->fieldAlloc ); - - - //std::cout << "Dealloc Fieldbuffer " << (void*) exporter << std::endl; - Py_TYPE(exporter)->tp_free ((PyObject*) exporter ); - } - - - template<typename T, uint_t fs> - Py_ssize_t fieldbuffer_getbuffer(FieldBufferPyObject *, Py_ssize_t , const void **) - { - WALBERLA_CHECK(false, "fieldbuffer_getbuffer is part of the old buffer interface and should never be used"); - return Py_ssize_t(0);// prevent compiler warning - } - - - template<typename T, uint_t fs> - Py_ssize_t fieldbuffer_getsegcount(FieldBufferPyObject *, Py_ssize_t *) - { - WALBERLA_CHECK(false, "fieldbuffer_getsegcount is part of the old buffer interface and should never be used"); - return Py_ssize_t(0);// prevent compiler warning - } - - - template<typename T, uint_t fs> - Py_ssize_t fieldbuffer_getbuffer_withGl(FieldBufferPyObject *, Py_ssize_t , const void **) - { - WALBERLA_CHECK(false, "fieldbuffer_getbuffer is part of the old buffer interface and should never be used"); - return Py_ssize_t(0);// prevent compiler warning - } - - - template<typename T, uint_t fs> - Py_ssize_t fieldbuffer_getsegcount_withGl(FieldBufferPyObject *, Py_ssize_t *) - { - WALBERLA_CHECK(false, "fieldbuffer_getsegcount is part of the old buffer interface and should never be used"); - return Py_ssize_t(0);// prevent compiler warning - } - - - - #ifdef WALBERLA_CXX_COMPILER_IS_GNU - #pragma GCC diagnostic push - #pragma GCC diagnostic ignored "-Wmissing-field-initializers" - #endif - - - template<typename T, uint_t fs> - struct FieldBufferType - { - static PyBufferProcs bufferProcs; - static PyTypeObject value; - }; - - template<typename T, uint_t fs> - PyBufferProcs FieldBufferType<T,fs>::bufferProcs = { -#if PY_MAJOR_VERSION < 3 - (readbufferproc) fieldbuffer_getbuffer <T,fs>, /* bf_getreadbuffer */ - (writebufferproc) fieldbuffer_getbuffer <T,fs>, /* bf_getwritebuffer */ - (segcountproc) fieldbuffer_getsegcount<T,fs>, /* bf_getsegcount */ - (charbufferproc) fieldbuffer_getbuffer <T,fs>, /* bf_getcharbuffer */ -#endif - (getbufferproc) fieldbuffer_get <T,fs>, /* bf_getbuffer */ - (releasebufferproc)fieldbuffer_release<T,fs>, /* bf_releasebuffer */ - }; - - template<typename T, uint_t fs> - PyTypeObject FieldBufferType<T,fs>::value = { - PyVarObject_HEAD_INIT(NULL, 0) - "walberla_cpp.FieldBuffer", /* tp_name */ - sizeof(FieldBufferPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)fieldbuffer_dealloc<T,fs>, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &FieldBufferType<T,fs>::bufferProcs, /* tp_as_buffer */ -#if PY_MAJOR_VERSION >= 3 - Py_TPFLAGS_DEFAULT, /* tp_flags */ -#else - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ -#endif - "FieldBuffer Objects", /* tp_doc */ - }; - - - - template<typename T, uint_t fs> - struct FieldBufferTypeGl - { - static PyBufferProcs bufferProcs; - static PyTypeObject value; - }; - - template<typename T, uint_t fs> - PyBufferProcs FieldBufferTypeGl<T,fs>::bufferProcs = { -#if PY_MAJOR_VERSION < 3 - (readbufferproc) fieldbuffer_getbuffer_withGl <T,fs>, /* bf_getreadbuffer */ - (writebufferproc) fieldbuffer_getbuffer_withGl <T,fs>, /* bf_getwritebuffer */ - (segcountproc) fieldbuffer_getsegcount_withGl<T,fs>, /* bf_getsegcount */ - (charbufferproc) fieldbuffer_getbuffer_withGl <T,fs>, /* bf_getcharbuffer */ -#endif - (getbufferproc) fieldbuffer_get_withGl<T,fs>, /* bf_getbuffer */ - (releasebufferproc)fieldbuffer_release <T,fs>, /* bf_releasebuffer */ - }; - - template<typename T, uint_t fs> - PyTypeObject FieldBufferTypeGl<T,fs>::value = { - PyVarObject_HEAD_INIT(NULL, 0) - "walberla_cpp.FieldBufferGl", /* tp_name */ - sizeof(FieldBufferPyObject), /* tp_basicsize */ - 0, /* tp_itemsize */ - (destructor)fieldbuffer_dealloc<T,fs>, /* tp_dealloc */ - 0, /* tp_print */ - 0, /* tp_getattr */ - 0, /* tp_setattr */ - 0, /* tp_reserved */ - 0, /* tp_repr */ - 0, /* tp_as_number */ - 0, /* tp_as_sequence */ - 0, /* tp_as_mapping */ - 0, /* tp_hash */ - 0, /* tp_call */ - 0, /* tp_str */ - 0, /* tp_getattro */ - 0, /* tp_setattro */ - &FieldBufferTypeGl<T,fs>::bufferProcs, /* tp_as_buffer */ -#if PY_MAJOR_VERSION >= 3 - Py_TPFLAGS_DEFAULT, /* tp_flags */ -#else - Py_TPFLAGS_DEFAULT | - Py_TPFLAGS_HAVE_NEWBUFFER, /* tp_flags */ -#endif - "FieldBufferGl Objects", /* tp_doc */ - }; - - - - #ifdef WALBERLA_CXX_COMPILER_IS_GNU - #pragma GCC diagnostic pop - #endif - - // this will become the buffer() function of the field which creates the - // FieldBuffer object, so this function is between field (exported in boost::python) and - // FieldBuffer which is exported in native Python C API - template<typename T, uint_t fs> - boost::python::object field_getBufferInterface( boost::python::object field, bool withGhostLayers ) - { - namespace bp = boost::python; - - FieldBufferPyObject *obj; - if ( withGhostLayers ) - obj = (FieldBufferPyObject*) PyObject_CallObject((PyObject *) & FieldBufferTypeGl<T,fs>::value, NULL ); - else - obj = (FieldBufferPyObject*) PyObject_CallObject((PyObject *) & FieldBufferType<T,fs>::value, NULL ); - - - Field<T,fs> * fieldPtr = bp::extract< Field<T,fs> * > ( field ); - bp::object fieldPtrObject( fieldPtr->getAllocator() ); - - obj->field = field.ptr(); - obj->fieldAlloc = fieldPtrObject.ptr(); - obj->fieldData = (void*) ( fieldPtr->data() ); - Py_INCREF( obj->field ); - Py_INCREF( obj->fieldAlloc ); - - return bp::object ( bp::handle<>( (PyObject*) obj ) ); - } - - - //=================================================================================================================== - // - // Aligned Allocation - // - //=================================================================================================================== - - template<typename T> - shared_ptr<field::FieldAllocator<T> > getAllocator(uint_t alignment) - { - if( alignment == 0 ) - return shared_ptr<field::FieldAllocator<T> >(); // leave to default - auto-detection of alignment - else if ( alignment == 16 ) - return make_shared< field::AllocateAligned<T, 16> >(); - else if ( alignment == 32 ) - return make_shared< field::AllocateAligned<T, 32> >(); - else if ( alignment == 64 ) - return make_shared< field::AllocateAligned<T, 64> >(); - else if ( alignment == 128 ) - return make_shared< field::AllocateAligned<T, 128> >(); - else { - PyErr_SetString( PyExc_ValueError, "Alignment parameter has to be one of 0, 16, 32, 64, 128." ); - throw boost::python::error_already_set(); - return shared_ptr<field::FieldAllocator<T> >(); - } - } - - template< typename GhostLayerField_T > - class GhostLayerFieldDataHandling : public field::BlockDataHandling< GhostLayerField_T > - { - public: - typedef typename GhostLayerField_T::value_type Value_T; - - GhostLayerFieldDataHandling( const weak_ptr<StructuredBlockStorage> &blocks, const uint_t nrOfGhostLayers, - const Value_T &initValue, const Layout layout, uint_t alignment = 0 ) : - blocks_( blocks ), nrOfGhostLayers_( nrOfGhostLayers ), initValue_( initValue ), layout_( layout ), - alignment_( alignment ) {} - - GhostLayerField_T * allocate( IBlock * const block ) - { - auto blocks = blocks_.lock(); - WALBERLA_CHECK_NOT_NULLPTR( blocks, "Trying to access 'AlwaysInitializeBlockDataHandling' for a block " - "storage object that doesn't exist anymore" ); - GhostLayerField_T * field = new GhostLayerField_T ( blocks->getNumberOfXCells( *block ), - blocks->getNumberOfYCells( *block ), - blocks->getNumberOfZCells( *block ), - nrOfGhostLayers_, initValue_, layout_, - getAllocator<Value_T>(alignment_) ); - return field; - } - - GhostLayerField_T * reallocate( IBlock * const block ) - { - return allocate(block); - } - - private: - weak_ptr< StructuredBlockStorage > blocks_; - - uint_t nrOfGhostLayers_; - Value_T initValue_; - Layout layout_; - uint_t alignment_; - }; - - - //=================================================================================================================== - // - // Field functions redefined for easier export - // - //=================================================================================================================== - - - static inline Cell tupleToCell( boost::python::tuple & tuple ) - { - using boost::python::extract; - return Cell ( extract<cell_idx_t>( tuple[0] ), - extract<cell_idx_t>( tuple[1] ), - extract<cell_idx_t>( tuple[2] ) ); - } - - template<typename Field_T> - void field_setCellXYZ( Field_T & field, boost::python::tuple args, const typename Field_T::value_type & value ) - { - using namespace boost::python; - - if ( len(args) < 3 || len(args) > 4 ) - { - PyErr_SetString( PyExc_RuntimeError, "3 or 4 indices required"); - throw error_already_set(); - } - - cell_idx_t f = 0; - if ( len(args) == 4 ) - f = extract<cell_idx_t> ( args[3] ); - - Cell cell = tupleToCell(args); - if ( ! field.coordinatesValid( cell[0], cell[1], cell[2], f ) ) - { - PyErr_SetString( PyExc_IndexError, "Field indices out of bounds"); - throw error_already_set(); - } - field(cell, f) = value; - } - - template<typename Field_T> - typename Field_T::value_type field_getCellXYZ( Field_T & field, boost::python::tuple args ) - { - using namespace boost::python; - if ( len(args) < 3 || len(args) > 4 ) - { - PyErr_SetString( PyExc_RuntimeError, "3 or 4 indices required"); - throw error_already_set(); - } - - cell_idx_t f = 0; - if ( len(args) == 4 ) - f = extract<cell_idx_t> ( args[3] ); - - Cell cell = tupleToCell(args); - if ( ! field.coordinatesValid( cell[0], cell[1], cell[2], f ) ) - { - PyErr_SetString( PyExc_IndexError, "Field indices out of bounds"); - throw error_already_set(); - } - - return field( cell, f ); - } - - - template<typename Field_T> - boost::python::object field_size( const Field_T & field ) { - return boost::python::make_tuple( field.xSize(), field.ySize(), field.zSize(), field.fSize() ); - } - - template<typename GlField_T> - boost::python::object field_sizeWithGhostLayer( const GlField_T & field ) { - return boost::python::make_tuple( field.xSizeWithGhostLayer(), field.ySizeWithGhostLayer(), field.zSizeWithGhostLayer(), field.fSize() ); - } - - - template<typename Field_T> - boost::python::object field_allocSize( const Field_T & field ) { - return boost::python::make_tuple( field.xAllocSize(), field.yAllocSize(), - field.zAllocSize(), field.fAllocSize() ); - } - - - template<typename Field_T> - boost::python::object field_strides( const Field_T & field ) { - return boost::python::make_tuple( field.xStride(), field.yStride(), - field.zStride(), field.fStride() ); - } - - template<typename Field_T> - boost::python::object field_offsets( const Field_T & field ) { - return boost::python::make_tuple( field.xOff(), field.yOff(), field.zOff() ); - } - - - template<typename Field_T> - boost::python::object field_layout( const Field_T & f ) { - if ( f.layout() == field::fzyx ) return boost::python::object( "fzyx" ); - if ( f.layout() == field::zyxf ) return boost::python::object( "zyxf" ); - - return boost::python::object(); - } - - - template<typename Field_T> - void field_swapDataPointers( Field_T & f1, Field_T & f2 ) - { - if ( ! f1.hasSameAllocSize(f2 ) || - ! f1.hasSameSize( f2) || - f1.layout() != f2.layout() ) - { - PyErr_SetString( PyExc_ValueError, "The data of fields with different sizes or layout cannot be swapped"); - throw boost::python::error_already_set(); - } - f1.swapDataPointers( f2 ); - } - - - template<typename T> - T FF_getFlag( const FlagField<T> & ff, const std::string & flag ) { - if ( ! ff.flagExists(flag) ) - { - PyErr_SetString( PyExc_ValueError, "No such flag"); - throw boost::python::error_already_set(); - } - return ff.getFlag( flag ); - } - - template<typename T> - boost::python::object FF_registeredFlags( const FlagField<T> & ff ) - { - std::vector<FlagUID> flags; - ff.getAllRegisteredFlags( flags ); - boost::python::list result; - - for( auto i = flags.begin(); i != flags.end(); ++i ) - result.append( i->toString() ); - boost::python::object objectResult = result; - return objectResult; - } - - - template<typename T> - boost::python::object FF_flagMap( const FlagField<T> & ff ) - { - std::vector<FlagUID> flags; - ff.getAllRegisteredFlags( flags ); - boost::python::dict result; - - for( auto i = flags.begin(); i != flags.end(); ++i ) - result[ i->toString() ] = ff.getFlag( *i ); - boost::python::object objectResult = result; - return objectResult; - } - - template<typename T> - boost::python::object FF_registerFlag( FlagField<T> & ff, const std::string & flag, boost::python::object bitNr ) - { - using namespace boost::python; - - try { - - if ( bitNr == object() ) - return object( ff.registerFlag( FlagUID(flag) ) ); - else - { - if ( extract<uint_t>(bitNr ).check() ) { - uint_t bit = extract<uint_t>(bitNr); - return object( ff.registerFlag( flag, bit ) ); - } - else { - PyErr_SetString( PyExc_ValueError, "Parameter bitNr has to be a positive integer"); - throw boost::python::error_already_set(); - } - } - } - catch ( std::runtime_error & e ) { - PyErr_SetString( PyExc_ValueError, e.what() ); - throw boost::python::error_already_set(); - } - - } - - template<typename T> - std::string FF_getFlagName( const FlagField<T> & ff, T flag ) - { - try { - return ff.getFlagUID( flag ).getIdentifier(); - } - catch ( std::runtime_error & e ) { - PyErr_SetString( PyExc_ValueError, e.what() ); - throw boost::python::error_already_set(); - } - } - - - template<typename Field_T> - boost::python::object copyAdaptorToField( const Field_T & f ) - { - typedef GhostLayerField<typename Field_T::value_type, Field_T::F_SIZE> ResField; - auto res = make_shared< ResField > ( f.xSize(), f.ySize(), f.zSize(), f.nrOfGhostLayers() ); - - auto srcIt = f.beginWithGhostLayerXYZ(); - auto dstIt = res->beginWithGhostLayerXYZ(); - while ( srcIt != f.end() ) - { - for( cell_idx_t fCoord = 0; fCoord < cell_idx_c(Field_T::F_SIZE); ++fCoord ) - dstIt.getF( fCoord ) = srcIt.getF( fCoord ); - - ++srcIt; - ++dstIt; - } - return boost::python::object( res ); - } - - - - //=================================================================================================================== - // - // Field export - // - //=================================================================================================================== - - template<typename T> - void exportFlagFieldIfUnsigned( typename std::enable_if<std::is_unsigned<T>::value >::type* = 0 ) - { - using namespace boost::python; - - class_< FlagField<T> , - shared_ptr<FlagField<T> >, - bases<GhostLayerField<T,1> >, - boost::noncopyable > ( "FlagField", no_init ) - .def ( "registerFlag", &FF_registerFlag<T> , ( arg("flagName"), arg("bitNr") = object() ) ) - .def ( "flag", &FF_getFlag<T> ) - .def ( "flagName", &FF_getFlagName<T> ) - .add_property( "flags", &FF_registeredFlags<T> ) - .add_property( "flagMap", &FF_flagMap<T> ) - ; - - } - template<typename T> - void exportFlagFieldIfUnsigned( typename std::enable_if< ! std::is_unsigned<T>::value >::type* = 0 ) {} - - - struct FieldExporter - { - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - typedef typename FieldType::value_type T; - const uint_t F_SIZE = FieldType::F_SIZE; - typedef GhostLayerField<T,F_SIZE> GlField_T; - typedef Field<T,F_SIZE> Field_T; - - using namespace boost::python; - - class_<Field_T, shared_ptr<Field_T>, boost::noncopyable>( "Field", no_init ) - .add_property("layout", &field_layout < Field_T > ) - .add_property("size", &field_size < Field_T > ) - .add_property("allocSize", &field_allocSize < Field_T > ) - .add_property("strides", &field_strides < Field_T > ) - .add_property("offsets", &field_offsets < Field_T > ) - .def("clone", &Field_T::clone , return_value_policy<manage_new_object>()) - .def("cloneUninitialized", &Field_T::cloneUninitialized, return_value_policy<manage_new_object>()) - .def("swapDataPointers", &field_swapDataPointers< Field_T > ) - .def("__getitem__", &field_getCellXYZ < Field_T > ) - .def("__setitem__", &field_setCellXYZ < Field_T > ) - .def("buffer", &field_getBufferInterface<T,F_SIZE>, ( arg("withGhostLayers") = false ) ); - ; - - class_< GlField_T , shared_ptr<GlField_T>, bases<Field_T>, boost::noncopyable > ( "GhostLayerField", no_init ) - .add_property("sizeWithGhostLayer", &field_sizeWithGhostLayer<GlField_T> ) - .add_property("nrOfGhostLayers", &GlField_T::nrOfGhostLayers ) - ; - - if ( F_SIZE == 1 ) - exportFlagFieldIfUnsigned<T>(); - - - // Field Buffer - FieldBufferType<T,F_SIZE>::value.tp_new = PyType_GenericNew; - if ( PyType_Ready(& FieldBufferType<T,F_SIZE>::value ) < 0 ) - return; - - Py_INCREF( (& FieldBufferType<T,F_SIZE>::value ) ); - PyModule_AddObject( boost::python::scope().ptr(), "FieldBuffer", (PyObject *)&FieldBufferType<T,F_SIZE>::value ); - - // Field Buffer with ghost layer - FieldBufferTypeGl<T,F_SIZE>::value.tp_new = PyType_GenericNew; - if ( PyType_Ready(& FieldBufferTypeGl<T,F_SIZE>::value ) < 0 ) - return; - - Py_INCREF( (& FieldBufferTypeGl<T,F_SIZE>::value ) ); - PyModule_AddObject( boost::python::scope().ptr(), "FieldBufferGl", (PyObject *)&FieldBufferTypeGl<T,F_SIZE>::value ); - - - // Field Buffer type - - if ( python_coupling::isTypeRegisteredInBoostPython< FieldAllocator<T> >() == false ) - { - class_< FieldAllocator<T>, shared_ptr<FieldAllocator<T> >, boost::noncopyable> ( "FieldAllocator", no_init ) - .def( "incrementReferenceCount", &FieldAllocator<T>::incrementReferenceCount ) - .def( "decrementReferenceCount", &FieldAllocator<T>::decrementReferenceCount ); - } - - using field::communication::PackInfo; - class_< PackInfo<GlField_T>, - shared_ptr< PackInfo<GlField_T> >, - bases<walberla::communication::UniformPackInfo>, - boost::noncopyable >( "FieldPackInfo", no_init ); - - - using field::communication::UniformMPIDatatypeInfo; - class_< UniformMPIDatatypeInfo<GlField_T>, - shared_ptr< UniformMPIDatatypeInfo<GlField_T> >, - bases<walberla::communication::UniformMPIDatatypeInfo>, - boost::noncopyable >( "FieldMPIDataTypeInfo", no_init ); - - } - }; - - - struct GhostLayerFieldAdaptorExporter - { - GhostLayerFieldAdaptorExporter( const std::string & name ) - : name_ ( name ) - {} - - template< typename Adaptor> - void operator()( python_coupling::NonCopyableWrap<Adaptor> ) - { - using namespace boost::python; - - class_< Adaptor, shared_ptr<Adaptor>, boost::noncopyable> ( name_.c_str(), no_init ) - .add_property("size", &field_size <Adaptor > ) - .add_property("sizeWithGhostLayer", &field_sizeWithGhostLayer<Adaptor> ) - .add_property("nrOfGhostLayers", &Adaptor::nrOfGhostLayers ) - .def("__getitem__", &field_getCellXYZ <Adaptor> ) - .def("copyToField", ©AdaptorToField <Adaptor> ); - } - - std::string name_; - }; - - //=================================================================================================================== - // - // createField - // - //=================================================================================================================== - - - class CreateFieldExporter - { - public: - CreateFieldExporter( uint_t xs, uint_t ys, uint_t zs, uint_t fs, uint_t gl, - Layout layout, const boost::python::object & type, uint_t alignment, - const shared_ptr<boost::python::object> & resultPointer ) - : xs_( xs ), ys_(ys), zs_(zs), fs_(fs), gl_(gl), - layout_( layout), type_( type ), alignment_(alignment), resultPointer_( resultPointer ) - {} - - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - using namespace boost::python; - typedef typename FieldType::value_type T; - const uint_t F_SIZE = FieldType::F_SIZE; - - if( F_SIZE != fs_ ) - return; - - if( python_coupling::isCppEqualToPythonType<T>( (PyTypeObject *)type_.ptr() ) ) - { - T initVal = T(); //extract<T> ( initValue_ ); - *resultPointer_ = object( make_shared< GhostLayerField<T,F_SIZE> >( xs_,ys_,zs_, gl_, initVal, layout_, - getAllocator<T>(alignment_))); - } - } - - private: - uint_t xs_; - uint_t ys_; - uint_t zs_; - uint_t fs_; - uint_t gl_; - Layout layout_; - boost::python::object type_; - uint_t alignment_; - shared_ptr<boost::python::object> resultPointer_; - }; - - template<typename FieldTypes> - boost::python::object createPythonField( boost::python::list size, - boost::python::object type, - uint_t ghostLayers, - Layout layout, - uint_t alignment) - { - using namespace boost::python; - uint_t xSize = extract<uint_t> ( size[0] ); - uint_t ySize = extract<uint_t> ( size[1] ); - uint_t zSize = extract<uint_t> ( size[2] ); - uint_t sizeLen = uint_c( len( size ) ); - uint_t fSize = 1; - if ( sizeLen == 4 ) - fSize = extract<uint_t> ( size[3] ); - - if ( ! PyType_Check( type.ptr() ) ) { - PyErr_SetString( PyExc_RuntimeError, "Invalid 'type' parameter"); - throw error_already_set(); - } - - auto result = make_shared<boost::python::object>(); - CreateFieldExporter exporter( xSize,ySize, zSize, fSize, ghostLayers, layout, type, alignment, result ); - python_coupling::for_each_noncopyable_type< FieldTypes > ( exporter ); - - if ( *result == object() ) - { - PyErr_SetString( PyExc_ValueError, "Cannot create field of this (type,f-size) combination"); - throw error_already_set(); - } - else { - return *result; - } - } - - //=================================================================================================================== - // - // createFlagField - // - //=================================================================================================================== - - - inline boost::python::object createPythonFlagField( boost::python::list size, uint_t nrOfBits, uint_t ghostLayers ) - { - using namespace boost::python; - - uint_t sizeLen = uint_c( len( size ) ); - if ( sizeLen != 3 ) { - PyErr_SetString( PyExc_ValueError, "Size parameter has to be a list of length 3"); - throw error_already_set(); - } - uint_t xSize = extract<uint_t> ( size[0] ); - uint_t ySize = extract<uint_t> ( size[1] ); - uint_t zSize = extract<uint_t> ( size[2] ); - - if( nrOfBits == 8 ) return object( make_shared< FlagField< uint8_t > >( xSize, ySize, zSize, ghostLayers ) ); - else if ( nrOfBits == 16 ) return object( make_shared< FlagField< uint16_t> >( xSize, ySize, zSize, ghostLayers ) ); - else if ( nrOfBits == 32 ) return object( make_shared< FlagField< uint32_t> >( xSize, ySize, zSize, ghostLayers ) ); - else if ( nrOfBits == 64 ) return object( make_shared< FlagField< uint64_t> >( xSize, ySize, zSize, ghostLayers ) ); - else - { - PyErr_SetString( PyExc_ValueError, "Allowed values for number of bits are: 8,16,32,64"); - throw error_already_set(); - } - } - - - //=================================================================================================================== - // - // addToStorage - // - //=================================================================================================================== - - class AddToStorageExporter - { - public: - AddToStorageExporter(const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, uint_t fs, uint_t gl, Layout layout, - const boost::python::object & type, - const boost::python::object & initObj, - uint_t alignment ) - : blocks_( blocks ), name_( name ), fs_( fs ), - gl_(gl),layout_( layout), type_( type ), initObj_( initObj), alignment_(alignment), found_(false) - {} - - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - using namespace boost::python; - typedef typename FieldType::value_type T; - const uint_t F_SIZE = FieldType::F_SIZE; - - if( F_SIZE != fs_ ) - return; - - if( !found_ && python_coupling::isCppEqualToPythonType<T>( (PyTypeObject *)type_.ptr() ) ) - { - typedef internal::GhostLayerFieldDataHandling< GhostLayerField<T,F_SIZE > > DataHandling; - if ( initObj_ == object() ) { - auto dataHandling = walberla::make_shared< DataHandling >( blocks_, gl_, T(), layout_, alignment_ ); - blocks_->addBlockData( dataHandling, name_ ); - } - else { - auto dataHandling = walberla::make_shared< DataHandling >( blocks_, gl_, extract<T>(initObj_), layout_, alignment_ ); - blocks_->addBlockData( dataHandling, name_ ); - } - found_ = true; - } - } - - bool successful() const { return found_; } - private: - shared_ptr< StructuredBlockStorage > blocks_; - std::string name_; - uint_t fs_; - uint_t gl_; - Layout layout_; - boost::python::object type_; - boost::python::object initObj_; - uint_t alignment_; - bool found_; - }; - - template<typename FieldTypes> - void addToStorage( const shared_ptr<StructuredBlockStorage> & blocks, const std::string & name, - boost::python::object type, uint_t fs, uint_t gl, Layout layout, boost::python::object initValue, - uint_t alignment) - { - using namespace boost::python; - - if ( ! PyType_Check( type.ptr() ) ) { - PyErr_SetString( PyExc_RuntimeError, "Invalid 'type' parameter"); - throw error_already_set(); - } - - auto result = make_shared<boost::python::object>(); - AddToStorageExporter exporter( blocks, name, fs, gl, layout, type, initValue, alignment ); - python_coupling::for_each_noncopyable_type< FieldTypes > ( std::ref(exporter) ); - - if ( ! exporter.successful() ) { - PyErr_SetString( PyExc_ValueError, "Adding Field failed."); - throw error_already_set(); - } - } - - - inline void addFlagFieldToStorage( const shared_ptr<StructuredBlockStorage> & blocks, const std::string & name, - uint_t nrOfBits, uint_t gl ) - { - if( nrOfBits == 8 ) field::addFlagFieldToStorage< FlagField<uint8_t> > ( blocks, name, gl ); - else if ( nrOfBits == 16 ) field::addFlagFieldToStorage< FlagField<uint16_t> > ( blocks, name, gl ); - else if ( nrOfBits == 32 ) field::addFlagFieldToStorage< FlagField<uint32_t> > ( blocks, name, gl ); - else if ( nrOfBits == 64 ) field::addFlagFieldToStorage< FlagField<uint64_t> > ( blocks, name, gl ); - else - { - PyErr_SetString( PyExc_ValueError, "Allowed values for number of bits are: 8,16,32,64"); - throw boost::python::error_already_set(); - } - } - - //=================================================================================================================== - // - // createVTKWriter - // - //=================================================================================================================== - - class CreateVTKWriterExporter - { - public: - CreateVTKWriterExporter( const shared_ptr<StructuredBlockStorage> & blocks, - ConstBlockDataID fieldId, const std::string & vtkName) - : blocks_( blocks ), fieldId_(fieldId), vtkName_( vtkName ) - {} - - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - using namespace boost::python; - - IBlock * firstBlock = & ( * blocks_->begin() ); - if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) - writer_ = shared_ptr<field::VTKWriter<FieldType> >( new field::VTKWriter<FieldType>(fieldId_, vtkName_)); - } - - shared_ptr< vtk::BlockCellDataWriterInterface > getCreatedWriter() { - return writer_; - } - - private: - shared_ptr< vtk::BlockCellDataWriterInterface > writer_; - shared_ptr< StructuredBlockStorage > blocks_; - ConstBlockDataID fieldId_; - std::string vtkName_; - }; - - - template<typename FieldTypes> - inline shared_ptr<vtk::BlockCellDataWriterInterface> createVTKWriter(const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, - const std::string & nameInVtkOutput = "") - { - std::string vtkName = nameInVtkOutput; - if( vtkName.size() == 0) - vtkName = name; - - if ( blocks->begin() == blocks->end() ) - return shared_ptr<vtk::BlockCellDataWriterInterface>(); - auto fieldID = python_coupling::blockDataIDFromString( *blocks, name ); - - CreateVTKWriterExporter exporter(blocks, fieldID, vtkName); - python_coupling::for_each_noncopyable_type< FieldTypes > ( std::ref(exporter) ); - if ( ! exporter.getCreatedWriter() ) { - PyErr_SetString( PyExc_ValueError, "Failed to create writer"); - throw boost::python::error_already_set(); - } - else { - return exporter.getCreatedWriter(); - } - } - - //=================================================================================================================== - // - // createFlagFieldVTKWriter - // - //=================================================================================================================== - - class CreateFlagFieldVTKWriterExporter - { - public: - CreateFlagFieldVTKWriterExporter( const shared_ptr<StructuredBlockStorage> & blocks, - ConstBlockDataID fieldId, const std::string & vtkName, - boost::python::dict flagMapping) - : blocks_( blocks ), fieldId_(fieldId), vtkName_( vtkName ), flagMapping_( flagMapping ) - {} - - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - using namespace boost::python; - - IBlock * firstBlock = & ( * blocks_->begin() ); - if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) - { - typedef typename FieldType::flag_t flag_t; - typedef field::FlagFieldMapping<FieldType, flag_t> FFMapping; - auto uncastedWriter = shared_ptr<FFMapping >( new FFMapping(fieldId_, vtkName_)); - writer_ = uncastedWriter; - auto keys = flagMapping_.keys(); - - for( int i=0; i < len(keys); ++i ) { - uncastedWriter->addMapping(FlagUID(extract<std::string>(keys[i])), - extract<flag_t>(flagMapping_[keys[i]]) ); - } - } - - } - - shared_ptr< vtk::BlockCellDataWriterInterface > getCreatedWriter() { - return writer_; - } - - private: - shared_ptr< vtk::BlockCellDataWriterInterface > writer_; - shared_ptr< StructuredBlockStorage > blocks_; - ConstBlockDataID fieldId_; - std::string vtkName_; - boost::python::dict flagMapping_; - }; - - - template<typename FieldTypes> - inline shared_ptr<vtk::BlockCellDataWriterInterface> createFlagFieldVTKWriter(const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, - boost::python::dict flagMapping, - const std::string & nameInVtkOutput = "" ) - { - std::string vtkName = nameInVtkOutput; - if( vtkName.size() == 0) - vtkName = name; - - if ( blocks->begin() == blocks->end() ) - return shared_ptr<vtk::BlockCellDataWriterInterface>(); - auto fieldID = python_coupling::blockDataIDFromString( *blocks, name ); - - CreateFlagFieldVTKWriterExporter exporter(blocks, fieldID, vtkName, flagMapping); - python_coupling::for_each_noncopyable_type< FieldTypes > ( std::ref(exporter) ); - if ( ! exporter.getCreatedWriter() ) { - PyErr_SetString( PyExc_ValueError, "Failed to create writer"); - throw boost::python::error_already_set(); - } - else { - return exporter.getCreatedWriter(); - } - } - - - //=================================================================================================================== - // - // createBinarizationFieldWriter - // - //=================================================================================================================== - - class CreateBinarizationVTKWriterExporter - { - public: - CreateBinarizationVTKWriterExporter( const shared_ptr<StructuredBlockStorage> & blocks, - ConstBlockDataID fieldId, const std::string & vtkName, uint_t mask ) - : blocks_( blocks ), fieldId_(fieldId), vtkName_( vtkName ), mask_(mask) - {} - - template< typename FieldType> - void operator() ( python_coupling::NonCopyableWrap<FieldType> ) - { - using namespace boost::python; - - IBlock * firstBlock = & ( * blocks_->begin() ); - if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) - { - typedef field::BinarizationFieldWriter<FieldType> Writer; - writer_ = shared_ptr<Writer>( new Writer(fieldId_, vtkName_, - static_cast<typename FieldType::value_type>(mask_) )); - } - } - - shared_ptr< vtk::BlockCellDataWriterInterface > getCreatedWriter() { - return writer_; - } - - private: - shared_ptr< vtk::BlockCellDataWriterInterface > writer_; - shared_ptr< StructuredBlockStorage > blocks_; - ConstBlockDataID fieldId_; - std::string vtkName_; - uint_t mask_; - }; - - - template<typename FieldTypes> - inline shared_ptr<vtk::BlockCellDataWriterInterface> createBinarizationVTKWriter(const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, - uint_t mask, - const std::string & nameInVtkOutput = "" ) - { - std::string vtkName = nameInVtkOutput; - if( vtkName.size() == 0) - vtkName = name; - - if ( blocks->begin() == blocks->end() ) - return shared_ptr<vtk::BlockCellDataWriterInterface>(); - auto fieldID = python_coupling::blockDataIDFromString( *blocks, name ); - - CreateBinarizationVTKWriterExporter exporter(blocks, fieldID, vtkName, mask); - python_coupling::for_each_noncopyable_type< FieldTypes > ( std::ref(exporter) ); - if ( ! exporter.getCreatedWriter() ) { - PyErr_SetString( PyExc_ValueError, "Failed to create writer"); - throw boost::python::error_already_set(); - } - else { - return exporter.getCreatedWriter(); - } - } - - -} // namespace internal - - - - -template<typename FieldTypes > -void exportFields() -{ - using namespace boost::python; - - enum_<Layout>("Layout") - .value("fzyx", fzyx) - .value("zyxf", zyxf) - .export_values(); - - python_coupling::for_each_noncopyable_type< FieldTypes > ( internal::FieldExporter() ); - - def( "createField", &internal::createPythonField<FieldTypes>, ( ( arg("size") ), - ( arg("type") ), - ( arg("ghostLayers") = uint_t(1) ), - ( arg("layout") = zyxf ), - ( arg("alignment") = 0 )) ); - - def( "createFlagField", &internal::createPythonFlagField, ( ( arg("size") ), - ( arg("nrOfBits") = uint_t(32) ), - ( arg("ghostLayers") = uint_t(1) ) ) ); - - def( "addToStorage", &internal::addToStorage<FieldTypes>, ( ( arg("blocks") ), - ( arg("name") ), - ( arg("type") ), - ( arg("fSize") = 1 ), - ( arg("ghostLayers") = uint_t(1) ), - ( arg("layout") = zyxf ), - ( arg("initValue") = object() ), - ( arg("alignment") = 0 ) ) ); - - def( "addFlagFieldToStorage",&internal::addFlagFieldToStorage, ( ( arg("blocks") ), - ( arg("name") ), - ( arg("nrOfBits")=8 ), - ( arg("ghostLayers") = uint_t(1) ) ) ); - - def( "createVTKWriter", &internal::createVTKWriter<FieldTypes>, ( arg("blocks"), arg("name"), arg("vtkName")="" )); - - - typedef boost::mpl::vector< - FlagField<uint8_t>, - FlagField<uint16_t>, - FlagField<uint32_t>, - FlagField<uint64_t> > FlagFields; - - def( "createFlagFieldVTKWriter", &internal::createFlagFieldVTKWriter<FlagFields>, - ( arg("blocks"), arg("name"), arg("flagMapping"), arg("vtkName")="" )); - - - typedef boost::mpl::vector< - Field<uint8_t,1 >, - Field<uint16_t, 1>, - Field<uint32_t, 1>, - Field<uint64_t, 1> > UintFields; - - def( "createBinarizationVTKWriter", &internal::createBinarizationVTKWriter<UintFields>, - ( arg("blocks"), arg("name"), arg("mask"), arg("vtkName")="" )); -} - - -template<typename AdaptorTypes> -void exportGhostLayerFieldAdaptors() -{ - python_coupling::for_each_noncopyable_type< AdaptorTypes > ( internal::GhostLayerFieldAdaptorExporter("FieldAdaptor") ); -} - -template<typename AdaptorType> -void exportGhostLayerFieldAdaptor() -{ - typedef boost::mpl::vector< AdaptorType > AdaptorTypes; - exportGhostLayerFieldAdaptors<AdaptorTypes>( ); -} - - - - -} // namespace field -} // namespace walberla - - diff --git a/src/field/python/GatherExport.h b/src/field/python/GatherExport.h deleted file mode 100644 index 1105caa00..000000000 --- a/src/field/python/GatherExport.h +++ /dev/null @@ -1,38 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file GatherExport.h -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - - -namespace walberla { -namespace field { - - -template<typename FieldTypes > -void exportGatherFunctions(); - - - -} // namespace field -} // namespace walberla - - -#include "GatherExport.impl.h" diff --git a/src/field/python/GatherExport.impl.h b/src/field/python/GatherExport.impl.h deleted file mode 100644 index 42f66565c..000000000 --- a/src/field/python/GatherExport.impl.h +++ /dev/null @@ -1,109 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file GatherExport.impl.h -//! \ingroup field -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "field/Gather.h" -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" -#include "python_coupling/helper/ModuleScope.h" -#include "python_coupling/helper/SliceToCellInterval.h" - - -namespace walberla { -namespace field { - - -namespace internal { - - //=================================================================================================================== - // - // Gather - // - //=================================================================================================================== - - - template<typename Field_T> - boost::python::object gatherToObject( const shared_ptr<StructuredBlockStorage> & blocks, BlockDataID fieldID, - CellInterval boundingBox = CellInterval(), int targetRank = 0 ) - { - typedef Field< typename Field_T::value_type, Field_T::F_SIZE > ResultField; - auto result = make_shared< ResultField > ( 0,0,0 ); - field::gather< Field_T, ResultField > ( *result, blocks, fieldID, boundingBox, targetRank, MPI_COMM_WORLD ); - - if ( MPIManager::instance()->worldRank() == targetRank ) - return boost::python::object(result); - else - return boost::python::object(); - } - - FunctionExporterClass( gatherToObject, - boost::python::object( const shared_ptr<StructuredBlockStorage> &, - BlockDataID, CellInterval,int ) ); - - template<typename FieldTypes> - static boost::python::object gatherWrapper ( const shared_ptr<StructuredBlockStorage> & blocks, const std::string & blockDataStr, - const boost::python::tuple & slice, int targetRank = 0 ) - { - using namespace boost::python; - - auto fieldID = python_coupling::blockDataIDFromString( *blocks, blockDataStr ); - CellInterval boundingBox = python_coupling::globalPythonSliceToCellInterval( blocks, slice ); - - if ( blocks->begin() == blocks->end() ) { - // if no blocks are on this process the field::gather function can be called with any type - // however we have to call it, otherwise a deadlock occurs - gatherToObject< Field<real_t,1> > ( blocks, fieldID, boundingBox, targetRank ); - return object(); - } - - IBlock * firstBlock = & ( * blocks->begin() ); - python_coupling::Dispatcher<FieldTypes, Exporter_gatherToObject > dispatcher( firstBlock ); - auto func = dispatcher( fieldID ); - if ( !func ) - { - PyErr_SetString( PyExc_RuntimeError, "This function cannot handle this type of block data."); - throw error_already_set(); - } - else - { - return func( blocks, fieldID, boundingBox, targetRank) ; - } - } - -} // namespace internal - - - -template<typename FieldTypes > -void exportGatherFunctions() -{ - using namespace boost::python; - python_coupling::ModuleScope fieldModule( "field" ); - - def( "gather", &internal::gatherWrapper<FieldTypes>, ( arg("blocks"), arg("blockDataName"), arg("slice"), arg("targetRank") = 0 ) ); -} - - - - -} // namespace moduleName -} // namespace walberla - - diff --git a/src/geometry/python/Exports.cpp b/src/geometry/python/Exports.cpp deleted file mode 100644 index aa9f32f7b..000000000 --- a/src/geometry/python/Exports.cpp +++ /dev/null @@ -1,103 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.cpp -//! \ingroup geometry -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/helper/ModuleScope.h" - -#include "core/math/AABB.h" -#include "geometry/mesh/TriangleMesh.h" -#include "geometry/mesh/TriangleMeshIO.h" - - - -using namespace boost::python; - - -namespace walberla { -namespace geometry { - -void triangleMesh_scaleReal( TriangleMesh & m, real_t scaleFactor ) { m.scale( scaleFactor ); } -void triangleMesh_scaleVec ( TriangleMesh & m, const Vector3<real_t> & scaleVec ) { m.scale( scaleVec ); } - - -shared_ptr<TriangleMesh> triangleMesh_load ( const std::string & filename, bool broadcast ) -{ - auto mesh = make_shared<TriangleMesh>(); - - try - { - if( broadcast ) - readAndBroadcastMesh( filename, *mesh ); - else - readMesh( filename, *mesh ); - } - catch( std::exception & e ) - { - PyErr_SetString( PyExc_RuntimeError, e.what() ); - throw error_already_set(); - } - return mesh; -} - -void triangleMesh_save( TriangleMesh & mesh, const std::string & filename ) -{ - try - { - writeMesh( filename, mesh ); - } - catch( std::exception & e ) - { - PyErr_SetString( PyExc_RuntimeError, e.what() ); - throw error_already_set(); - } -} - - - -void exportModuleToPython() -{ - python_coupling::ModuleScope fieldModule( "geometry" ); - - class_< TriangleMesh, shared_ptr<TriangleMesh>, boost::noncopyable > ( "TriangleMesh", no_init ) - .add_property( "numTriangles", &TriangleMesh::getNumTriangles ) - .add_property( "numVertices" , &TriangleMesh::getNumVertices ) - .add_property( "numVertexNormals", &TriangleMesh::getNumNormals ) - .def ( "volume", &TriangleMesh::volume ) - .def ( "scale", &triangleMesh_scaleReal, arg("factor") ) - .def ( "exchangeAxes", &TriangleMesh::exchangeAxes, ( arg("xAxisId"), arg("yAxisId"), arg("zAxisId") ) ) - .def ( "scaleXYZ", &triangleMesh_scaleVec, arg("factors") ) - .def ( "removeDuplicateVertices", &TriangleMesh::removeDuplicateVertices, ( arg("tolerance") = 1e-4 ) ) - .def ( "merge", &TriangleMesh::merge, ( arg("other"), arg("offset") = Vector3<real_t>(0) ) ) - .def ( "getAABB", &TriangleMesh::getAABB ) - .def ( "save", &triangleMesh_save, arg("filename") ) - .def ( "load", &triangleMesh_load, ( arg("filename"), arg("broadcast") = true) ).staticmethod( "load" ) - ; -} - - -} // namespace geometry -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/geometry/python/Exports.h b/src/geometry/python/Exports.h deleted file mode 100644 index 5b92ae1da..000000000 --- a/src/geometry/python/Exports.h +++ /dev/null @@ -1,38 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.h -//! \ingroup geometry -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace geometry { - - - void exportModuleToPython(); - - -} // namespace geometry -} // namespace walberla - - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/lbm/python/ExportBasic.cpp b/src/lbm/python/ExportBasic.cpp deleted file mode 100644 index b8af2324a..000000000 --- a/src/lbm/python/ExportBasic.cpp +++ /dev/null @@ -1,244 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.cpp -//! \ingroup domain_decomposition -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "ExportBasic.h" -#include "core/logging/Logging.h" -#include "python_coupling/Manager.h" -#include "python_coupling/helper/ModuleScope.h" - -#include "domain_decomposition/BlockDataID.h" - -#include "lbm/field/Adaptors.h" -#include "lbm/lattice_model/CollisionModel.h" -#include "lbm/lattice_model/D3Q19.h" -#include "lbm/lattice_model/ForceModel.h" - - -using namespace boost::python; - - -namespace walberla { -namespace lbm { - - -namespace internal { - - using namespace boost::python; - - - template<typename ForceModel_T> bool FM_getShiftMacVel( const ForceModel_T & ) { return ForceModel_T::shiftMacVel; } - template<typename ForceModel_T> bool FM_getShiftEquVel( const ForceModel_T & ) { return ForceModel_T::shiftEquVel; } - template<typename ForceModel_T> bool FM_getConstant ( const ForceModel_T & ) { return ForceModel_T::constant; } - - template<typename ForceModel_T> - void addForceModelDefs( class_< ForceModel_T> & c ) - { - c.add_property( "shiftMacVel", FM_getShiftMacVel<ForceModel_T> ) - .add_property( "shiftEquVel", FM_getShiftEquVel<ForceModel_T> ) - .add_property( "constant", FM_getConstant <ForceModel_T>) - .def( "setConstantBodyForceIfPossible", &ForceModel_T::setConstantBodyForceIfPossible ) - ; - } - - - list getMRTRelaxationRates( const collision_model::D3Q19MRT & l ) - { - list result; - for(uint_t i=0; i<19; ++i ) - result.append( l.s(i) ); - return result; - } - - list getCumulantRelaxationRates( const collision_model::D3Q27Cumulant & l ) - { - list result; - for(uint_t i=0; i<10; ++i ) - result.append( l.omega(i) ); - return result; - } -} - -void exportForceModels() -{ - static bool alreadyExported = false; - if( alreadyExported ) - return; - alreadyExported = true; - - using namespace internal; - using namespace force_model; - - python_coupling::ModuleScope scope("forceModels"); - - typedef GhostLayerField<Vector3<real_t>,1 > VecField; - - auto export1 = class_< None >("NoForce" ); // "None" is a Python keyword -> renamed to NoForce - addForceModelDefs( export1 ); - - auto export2 = class_< SimpleConstant >("SimpleConstant", - init<Vector3<real_t> , uint_t> ( (arg("force"), arg("level")=uint_t(0) ) ) ); - const Vector3<real_t>& (SimpleConstant::*p_SimpleConstantForce)() const = &SimpleConstant::force; - export2.def("force", p_SimpleConstantForce, return_value_policy<copy_const_reference>()); - addForceModelDefs( export2 ); - - auto export3 = class_< EDMField<VecField> > ("EDMField", - init< BlockDataID> ( (arg("forceFieldID") )) ); - addForceModelDefs( export3 ); - - auto export4 = class_< LuoConstant > ("LuoConstant", - init<Vector3<real_t> , uint_t> ( (arg("force"), arg("level")=uint_t(0) ) ) ); - const Vector3<real_t>& (LuoConstant::*p_LuoConstantForce)() const = &LuoConstant::force; - export4.def("force", p_LuoConstantForce, return_value_policy<copy_const_reference>() ); - addForceModelDefs( export4 ); - - auto export5 = class_< LuoField<VecField> > ("LuoField", - init< BlockDataID> ( (arg("forceFieldID") )) ); - addForceModelDefs( export5 ); - - auto export6 = class_< GuoConstant > ("GuoConstant", - init<Vector3<real_t> , uint_t> ( (arg("force"), arg("level")=uint_t(0) ) ) ); - const Vector3<real_t>& (GuoConstant::*p_GuoConstantForce)() const = &GuoConstant::force; - export6.def("force", p_GuoConstantForce, return_value_policy<copy_const_reference>() ); - addForceModelDefs( export6 ); - - auto export7 = class_< GuoField<VecField> > ("GuoField", - init< BlockDataID> ( (arg("forceFieldID") )) ); - addForceModelDefs( export7 ); - - auto export8 = class_< Correction<VecField> > ("Correction", - init< BlockDataID> ( (arg("previousMomentumDensityFieldID") )) ); - addForceModelDefs( export8 ); -} - - - -shared_ptr< collision_model::SRTField<GhostLayerField<real_t,1> > > createSRTFieldLatticeModel( const shared_ptr<StructuredBlockStorage> & bs, const std::string & blockDataName, uint_t level ) -{ - auto blockDataID = python_coupling::blockDataIDFromString( *bs, blockDataName ); - return make_shared< collision_model::SRTField<GhostLayerField<real_t,1> > >( blockDataID, level ); -} - -void exportCollisionModels() -{ - static bool alreadyExported = false; - if( alreadyExported ) - return; - alreadyExported = true; - - using namespace internal; - - python_coupling::ModuleScope scope("collisionModels"); - - using collision_model::SRT; - using collision_model::SRTField; - using collision_model::TRT; - using collision_model::D3Q19MRT; - using collision_model::D3Q27Cumulant; - - def( "levelDependentRelaxationParameter", collision_model::levelDependentRelaxationParameter, (arg("targetLevel"), arg("parameterLevel"), arg("level")) ); - def( "viscosityFromOmega", collision_model::viscosityFromOmega, (arg("omega") ) ); - def( "omegaFromViscosity", collision_model::omegaFromViscosity, (arg("viscosity") ) ); - - // SRT - { - real_t ( SRT::*ptr_omega )() const = &SRT::omega; - real_t ( SRT::*ptr_viscosity )() const = &SRT::viscosity; - - class_< SRT > ("SRT", init<real_t, uint_t>( ( arg("omega"), arg("level")=uint_t(0) ) ) ) - .add_property("omega", ptr_omega) - .add_property("viscosity", ptr_viscosity ) - .add_property("level", &SRT::level ) - .def("reset", &SRT::reset, (arg("omega"), arg("level")=uint_t(0) ) ) - ; - } - - // SRTField - { - typedef SRTField<GhostLayerField<real_t,1> > SRTField_T; - class_< SRTField_T >( "SRTField", no_init ) - .def( "__init__", make_constructor( &createSRTFieldLatticeModel) ) - ; - } - - // TRT - { - real_t ( TRT::*ptr_lambda_e )() const = &TRT::lambda_e; - real_t ( TRT::*ptr_lambda_d )() const = &TRT::lambda_d; - real_t ( TRT::*ptr_viscosity )() const = &TRT::viscosity; - - class_< TRT> ( "TRT", init<real_t, real_t, uint_t>( (arg("lambda_e"), arg("lambda_d"), arg("level")=uint_t(0) ) ) ) - .add_property("lambda_e", ptr_lambda_e ) - .add_property("lambda_d", ptr_lambda_d ) - .add_property("lambda_o", ptr_lambda_d ) - .add_property("viscosity", ptr_viscosity ) - .add_property("level", &TRT::level ) - .def( "reset", &TRT::reset, ( arg("lambda_e"), arg("lambda_d"), arg("level")=uint_t(0) ) ) - .def( "resetWithMagicNumber", &TRT::resetWithMagicNumber, (arg("omega"), arg("magicNumber") = TRT::threeSixteenth,arg("level")=uint_t(0) ) ) - .def( "constructWithMagicNumber", &TRT::constructWithMagicNumber, (arg("omega"), arg("magicNumber") = TRT::threeSixteenth, arg("level")=uint_t(0) ) ) - .staticmethod("constructWithMagicNumber") - ; - } - - // MRT - { - real_t ( D3Q19MRT::*ptr_viscosity )() const = &D3Q19MRT::viscosity; - - class_< D3Q19MRT >( "D3Q19MRT", init<real_t, real_t, real_t, real_t, real_t, real_t, uint_t>( - ( arg("s1"), arg("s2"), arg("s4"), arg("s9"), arg("s10"), arg("s16"), arg("level")=uint_t(0) ) )) - .add_property( "relaxationRates", getMRTRelaxationRates ) - .add_property( "viscosity", ptr_viscosity ) - .def( "constructTRT", &D3Q19MRT::constructTRT, (arg("lambda_e"), arg("lambda_d"), arg("level")=uint_t(0) ) ) - .staticmethod("constructTRT") - .def( "constructTRTWithMagicNumber", &D3Q19MRT::constructTRTWithMagicNumber, (arg("omega"), arg("magicNumber")=D3Q19MRT::threeSixteenth, arg("level")=uint_t(0) ) ) - .staticmethod("constructTRTWithMagicNumber") - .def( "constructPan", &D3Q19MRT::constructPan, (arg("lambda_e"), arg("lambda_d"), arg("level")=uint_t(0) ) ) - .staticmethod("constructPan") - .def( "constructPanWithMagicNumber", &D3Q19MRT::constructPanWithMagicNumber, (arg("omega"), arg("magicNumber")=D3Q19MRT::threeSixteenth, arg("level")=uint_t(0) ) ) - .staticmethod("constructPanWithMagicNumber") - ; - } - - // Cumulant - { - real_t ( D3Q27Cumulant::*ptr_viscosity )() const = &D3Q27Cumulant::viscosity; - - class_< D3Q27Cumulant >( "D3Q27Cumulant", init<real_t, real_t, real_t, real_t, real_t, real_t, real_t, real_t, real_t,real_t, uint_t>( - ( arg("omega1"), arg("omega2")=real_t(1), arg("omega3")=real_t(1), arg("omega4")=real_t(1), arg("omega5")=real_t(1), arg("omega6")=real_t(1), arg("omega7")=real_t(1), arg("omega8")=real_t(1), arg("omega9")=real_t(1), arg("omega10")=real_t(1), arg("level")=uint_t(0) ) )) - .add_property( "relaxationRates", getCumulantRelaxationRates ) - .add_property( "viscosity", ptr_viscosity ) - ; - - } - -} - - - -} // namespace lbm -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/lbm/python/ExportBasic.h b/src/lbm/python/ExportBasic.h deleted file mode 100644 index ba55ed144..000000000 --- a/src/lbm/python/ExportBasic.h +++ /dev/null @@ -1,47 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportBasic.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace lbm { - - void exportCollisionModels(); - void exportForceModels(); - - template< typename LatticeModels > struct VelocityAdaptorsFromLatticeModels; - template< typename LatticeModels > struct DensityAdaptorsFromLatticeModels; - template< typename LatticeModels > struct AdaptorsFromLatticeModels; - template< typename LatticeModels > struct ExtendedBoundaryHandlingsFromLatticeModels; - - template<typename LatticeModels, typename FlagFields> - void exportBasic(); - -} // namespace lbm -} // namespace walberla - - -#include "ExportBasic.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/lbm/python/ExportBasic.impl.h b/src/lbm/python/ExportBasic.impl.h deleted file mode 100644 index c0097f54e..000000000 --- a/src/lbm/python/ExportBasic.impl.h +++ /dev/null @@ -1,520 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportBasic.impl.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" -#include "python_coupling/helper/ModuleScope.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" - -#include "core/logging/Logging.h" - -#include "boundary/python/Exports.h" -#include "field/adaptors/AdaptorCreators.h" -#include "lbm/lattice_model/CollisionModel.h" -#include "lbm/lattice_model/ForceModel.h" -#include "lbm/sweeps/CellwiseSweep.h" -#include "lbm/field/AddToStorage.h" -#include "lbm/field/Adaptors.h" -#include "lbm/lattice_model/D3Q19.h" -#include "lbm/sweeps/SplitPureSweep.h" - -#include "field/python/FieldExport.h" - -#include <boost/mpl/transform.hpp> -#include <boost/mpl/copy.hpp> - - -namespace walberla { -namespace lbm { - - -namespace internal -{ - //=================================================================================================================== - // - // LatticeModel - // - //=================================================================================================================== - - class LatticeModelCreator - { - public: - LatticeModelCreator( bool compressible, uint_t eqOrder, const std::string & stencil, - boost::python::object collisionModel, boost::python::object forceModel ) - : compressible_( compressible ), equilibriumAccuracyOrder_( eqOrder ), stencil_( stencil ), - collisionModel_( collisionModel ), forceModel_( forceModel ) - {} - - template<typename LatticeModel_T> - void operator() ( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - using namespace boost::python; - using namespace collision_model; - - typedef typename LatticeModel_T::Stencil Stencil_T; - - if ( compressible_ != LatticeModel_T::compressible ) return; - if ( equilibriumAccuracyOrder_ != LatticeModel_T::equilibriumAccuracyOrder ) return; - if ( stencil_ != Stencil_T::NAME ) return; - - if ( ! extract< typename LatticeModel_T::CollisionModel>(collisionModel_).check() ) return; - if ( ! extract< typename LatticeModel_T::ForceModel >(forceModel_ ).check() ) return; - - result_ = object( LatticeModel_T( extract< typename LatticeModel_T::CollisionModel>(collisionModel_), - extract< typename LatticeModel_T::ForceModel >(forceModel_ ) ) ); - } - - boost::python::object getResult() const { return result_; } - - private: - bool compressible_; - uint_t equilibriumAccuracyOrder_; - std::string stencil_; - boost::python::object collisionModel_; - boost::python::object forceModel_; - - - boost::python::object result_; - }; - - struct LatticeModelExporter - { - template<typename LatticeModel_T> - static boost::python::list getDirections( LatticeModel_T & ) - { - using namespace boost::python; - list directionList; - const int dimension = LatticeModel_T::Stencil::D; - if( dimension < 1 || dimension > 3) { - PyErr_SetString( PyExc_ValueError, "Only stencils with dimensions 1,2,3 supported"); - throw error_already_set(); - } - for( auto it = LatticeModel_T::Stencil::begin(); it != LatticeModel_T::Stencil::end(); ++it ) - { - if(dimension == 1) { - directionList.append( make_tuple(it.cx() ) ); - } - else if( dimension == 2) { - directionList.append( make_tuple(it.cx(), it.cy()) ); - } else if (dimension == 3) { - directionList.append( make_tuple(it.cx(), it.cy(), it.cz() ) ); - } - } - return directionList; - } - template<typename LatticeModel_T> - static bool isCompressible(LatticeModel_T &) { - return LatticeModel_T::compressible; - } - template<typename LatticeModel_T> - static int equilibriumAccuracyOrder(LatticeModel_T &) { - return LatticeModel_T::equilibriumAccuracyOrder; - } - template<typename LatticeModel_T> - static boost::python::str stencilName(LatticeModel_T &) { - return boost::python::str(LatticeModel_T::Stencil::NAME); - } - template<typename LatticeModel_T> - static boost::python::str communicationStencilName(LatticeModel_T &) { - return boost::python::str(LatticeModel_T::CommunicationStencil::NAME); - } - - template<typename LatticeModel_T> - void operator()( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - using namespace boost::python; - - typename LatticeModel_T::CollisionModel& ( LatticeModel_T::*p_collisionModel) () = &LatticeModel_T::collisionModel; - typename LatticeModel_T::ForceModel & ( LatticeModel_T::*p_forceModel) () = &LatticeModel_T::forceModel; - - class_< LatticeModel_T > ( LatticeModel_T::NAME, no_init ) - .add_property( "collisionModel", make_function( p_collisionModel, return_internal_reference<>() ) ) - .add_property( "forceModel", make_function( p_forceModel , return_internal_reference<>() ) ) - .add_property( "compressible", &LatticeModelExporter::isCompressible<LatticeModel_T>) - .add_property( "equilibriumAccuracyOrder",&LatticeModelExporter::equilibriumAccuracyOrder<LatticeModel_T>) - .add_property( "stencilName", &LatticeModelExporter::stencilName<LatticeModel_T>) - .add_property( "communicationStencilName",&LatticeModelExporter::communicationStencilName<LatticeModel_T>) - .add_property( "directions", &LatticeModelExporter::getDirections<LatticeModel_T> ) - ; - } - }; - - - template<typename LatticeModels> - boost::python::object makeLatticeModel( const std::string & stencil, boost::python::object collisionModel, boost::python::object forceModel, - bool compressible, uint_t equilibriumAccuracyOrder ) - { - using namespace boost::python; - - LatticeModelCreator creator( compressible, equilibriumAccuracyOrder, stencil, collisionModel, forceModel ); - python_coupling::for_each_noncopyable_type<LatticeModels>( std::ref(creator) ); - - if ( creator.getResult() == object() ) - { - PyErr_SetString( PyExc_ValueError, "No such LatticeModel available."); - throw error_already_set(); - } - - return creator.getResult(); - } - - //=================================================================================================================== - // - // PdfField - // - //=================================================================================================================== - - template<typename LatticeModel_T> - typename PdfField<LatticeModel_T>::iterator pythonSliceToFieldIterator( PdfField<LatticeModel_T> & field, - boost::python::tuple pyIndex ) - { - using python_coupling::localPythonSliceToCellInterval; - return field.beginSliceXYZ( localPythonSliceToCellInterval(field, pyIndex) ); - } - - template<typename LatticeModel_T> - void pdfField_setDensityAndVelocity( PdfField<LatticeModel_T> & field, boost::python::tuple pyIndex, - const Vector3<real_t> & velocity, real_t rho ) - { - typename PdfField<LatticeModel_T>::iterator beginIterator = pythonSliceToFieldIterator<LatticeModel_T>( field, pyIndex ); - DensityAndVelocityRange< LatticeModel_T, typename PdfField<LatticeModel_T>::iterator >::set( beginIterator, field.end(), field.latticeModel(), velocity, rho ); - } - - template<typename LatticeModel_T> - void pdfField_setToEquilibrium( PdfField<LatticeModel_T> & field, boost::python::tuple pyIndex, - const Vector3<real_t> & velocity, real_t rho ) - { - typename PdfField<LatticeModel_T>::iterator beginIterator = pythonSliceToFieldIterator<LatticeModel_T>( field, pyIndex ); - EquilibriumRange< LatticeModel_T, typename PdfField<LatticeModel_T>::iterator >::set( beginIterator, field.end(), velocity, rho ); - } - - template<typename LatticeModel_T> - boost::python::list pdfField_getPressureTensor( PdfField<LatticeModel_T> & field, cell_idx_t x, cell_idx_t y, cell_idx_t z ) - { - using namespace boost::python; - - Matrix3<real_t> m = field.getPressureTensor( x,y,z ); - list result; - for(uint_t i=0; i<3; ++i ) - { - list row; - for(uint_t j=0; j<3; ++j) - row.append( m(i,j) ); - result.append(row); - } - return result; - } - - - struct PdfFieldExporter - { - template<typename LatticeModel_T> - void operator()( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - using namespace boost::python; - - typedef PdfField<LatticeModel_T> PdfField_T; - typedef GhostLayerField<real_t, LatticeModel_T::Stencil::Size > Base; - - - LatticeModel_T & ( PdfField_T::*ptr_latticeModel ) () = &PdfField_T::latticeModel; - - //real_t ( PdfField_T::*ptr_getShearRate )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getShearRate; - - real_t ( PdfField_T::*ptr_getDensity )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getDensity; - real_t ( PdfField_T::*ptr_getDensitySI )( cell_idx_t, cell_idx_t, cell_idx_t, real_t ) const = &PdfField_T::getDensitySI; - - Vector3<real_t> ( PdfField_T::*ptr_getMomentumDensity )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getMomentumDensity; - Vector3<real_t> ( PdfField_T::*ptr_getEquilibriumMomentumDensity )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getEquilibriumMomentumDensity; - real_t ( PdfField_T::*ptr_getShearRate )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getShearRate; - Vector3<real_t> ( PdfField_T::*ptr_getVelocity )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getVelocity; - Vector3<real_t> ( PdfField_T::*ptr_getVelocitySI )( cell_idx_t, cell_idx_t, cell_idx_t, real_t, real_t ) const = &PdfField_T::getVelocitySI; - Vector3<real_t> ( PdfField_T::*ptr_getEquilibriumVelocity )( cell_idx_t, cell_idx_t, cell_idx_t ) const = &PdfField_T::getEquilibriumVelocity; - - try - { - class_< PdfField_T, shared_ptr<PdfField_T>, bases< Base >, boost::noncopyable >("PdfField", no_init) - .add_property("latticeModel", make_function( ptr_latticeModel, return_internal_reference<>() ) ) - .def( "setDensityAndVelocity", pdfField_setDensityAndVelocity<LatticeModel_T>, ( args("slice"), args("velocity"), args("density") ) ) - .def( "setToEquilibrium", pdfField_setToEquilibrium<LatticeModel_T>, ( args("slice"), args("velocity"), args("density") ) ) - .def( "getShearRate", ptr_getShearRate , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getDensity", ptr_getDensity , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getDensitySI", ptr_getDensitySI , ( arg("x"), arg("y"), arg("z"), arg("rho_SI") ) ) - .def( "getMomentumDensity" , ptr_getMomentumDensity , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getEquilibriumMomentumDensity" , ptr_getEquilibriumMomentumDensity , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getVelocity" , ptr_getVelocity , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getVelocitySI" , ptr_getVelocitySI , ( arg("x"), arg("y"), arg("z"), arg("dx_SI"), arg("dy_SI") ) ) - .def( "getEquilibriumVelocity" , ptr_getEquilibriumVelocity , ( arg("x"), arg("y"), arg("z") ) ) - .def( "getPressureTensor", pdfField_getPressureTensor<LatticeModel_T> , ( arg("x"), arg("y"), arg("z") ) ) - ; - } - catch (...) { - WALBERLA_LOG_WARNING( "Exporting PDFField failed. Did you forget to export the corresponding GhostLayerField?" ); - } - } - }; - - class AddPdfFieldToStorageExporter - { - public: - AddPdfFieldToStorageExporter( const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, - boost::python::object latticeModel, - const Vector3<real_t> & initialVelocity, real_t initialDensity, - uint_t gl, field::Layout layout, - const std::string & densityAdaptorName, const std::string & velocityAdaptorName, - const std::string & shearRateAdaptorName ) - : blocks_( blocks ), name_( name ), latticeModel_(latticeModel), - initialVelocity_( initialVelocity ), initialDensity_( initialDensity ), - gl_(gl),layout_( layout), - densityAdaptorName_( densityAdaptorName ), velocityAdaptorName_( velocityAdaptorName ), - shearRateAdaptorName_( shearRateAdaptorName), - found_(false) - {} - - template< typename LatticeModel_T> - void operator() ( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - using namespace boost::python; - - if( ! extract<LatticeModel_T>( latticeModel_ ).check() ) - return; - - WALBERLA_ASSERT( !found_ ); - BlockDataID pdfFieldID = addPdfFieldToStorage<LatticeModel_T>( blocks_, name_, extract<LatticeModel_T>( latticeModel_ ), - initialVelocity_, initialDensity_, gl_, layout_ ); - - if ( densityAdaptorName_.size() > 0 ) { - field::addFieldAdaptor< typename lbm::Adaptor<LatticeModel_T>::Density > ( blocks_, pdfFieldID, densityAdaptorName_ ); - } - if ( velocityAdaptorName_.size() > 0 ) { - field::addFieldAdaptor< typename lbm::Adaptor<LatticeModel_T>::Velocity >( blocks_, pdfFieldID, velocityAdaptorName_ ); - } - if ( shearRateAdaptorName_.size() > 0 ) { - field::addFieldAdaptor< typename lbm::Adaptor<LatticeModel_T>::ShearRate >( blocks_, pdfFieldID, shearRateAdaptorName_ ); - } - found_ = true; - } - - bool successful() { return found_; } - - private: - shared_ptr< StructuredBlockStorage > blocks_; - std::string name_; - boost::python::object latticeModel_; - Vector3<real_t> initialVelocity_; - - real_t initialDensity_; - uint_t gl_; - field::Layout layout_; - - std::string densityAdaptorName_; - std::string velocityAdaptorName_; - std::string shearRateAdaptorName_; - - bool found_; - }; - - template<typename LatticeModels> - void addPdfFieldToStorage( const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & identifier, - boost::python::object latticeModel, - const Vector3<real_t> & initialVelocity, real_t initialDensity, - uint_t gl, field::Layout layout, - const std::string & densityAdaptor, const std::string & velocityAdaptor, - const std::string & shearRateAdaptor ) - { - using namespace boost::python; - - internal::AddPdfFieldToStorageExporter exporter( blocks, identifier, latticeModel, initialVelocity, - initialDensity, gl, layout, densityAdaptor, velocityAdaptor, shearRateAdaptor ); - python_coupling::for_each_noncopyable_type< LatticeModels > ( std::ref(exporter) ); - if ( ! exporter.successful() ) { - PyErr_SetString( PyExc_ValueError, "Adding Pdf Field failed."); - throw error_already_set(); - } - } - - struct AdaptorExporter - { - template< typename LatticeModel_T> - void operator() ( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - field::exportGhostLayerFieldAdaptor< typename Adaptor< LatticeModel_T >::Density > ( ); - field::exportGhostLayerFieldAdaptor< typename Adaptor< LatticeModel_T >::Velocity > ( ); - field::exportGhostLayerFieldAdaptor< typename Adaptor< LatticeModel_T >::ShearRate > ( ); - } - }; - - template< typename LatticeModel > - struct VelocityAdaptorFromLatticeModel - { - typedef typename lbm::Adaptor< LatticeModel>::Velocity type; - }; - - template< typename LatticeModel > - struct DensityAdaptorFromLatticeModel - { - typedef typename lbm::Adaptor< LatticeModel>::Density type; - }; - - template< typename LatticeModel > - struct ShearRateAdaptorFromLatticeModel - { - typedef typename lbm::Adaptor< LatticeModel>::ShearRate type; - }; - - class SweepWrapper - { - public: - SweepWrapper() - {} - - SweepWrapper( const std::function<void(IBlock*) > & sweepToWrap ) - : sweepToWrap_( sweepToWrap ) {} - - void operator() ( IBlock * block ) - { - if ( sweepToWrap_ ) - sweepToWrap_( block ); - } - protected: - std::function<void(IBlock*) > sweepToWrap_; - }; - - - inline shared_ptr<SweepWrapper> makeSplitPureSweep(const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & pdfFieldIDStr) - { - if ( blocks->begin() == blocks->end() ) { - PyErr_SetString( PyExc_RuntimeError, "No blocks on this process" ); - throw boost::python::error_already_set(); - } - - IBlock & firstBlock = *( blocks->begin() ); - BlockDataID pdfFieldID = python_coupling::blockDataIDFromString( firstBlock, pdfFieldIDStr ); - - typedef lbm::D3Q19< lbm::collision_model::SRT, true > LM_SRT_Compressible; - typedef lbm::D3Q19< lbm::collision_model::SRT, false > LM_SRT_Incompressible; - typedef lbm::D3Q19< lbm::collision_model::TRT, true > LM_TRT_Compressible; - typedef lbm::D3Q19< lbm::collision_model::TRT, false > LM_TRT_Incompressible; - - - if (firstBlock.isDataOfType<PdfField<LM_SRT_Compressible>>(pdfFieldID)) { - return make_shared<SweepWrapper>(SplitPureSweep<LM_SRT_Compressible>(pdfFieldID)); - } - else if (firstBlock.isDataOfType<PdfField<LM_SRT_Incompressible>>(pdfFieldID)) { - return make_shared<SweepWrapper>(SplitPureSweep<LM_SRT_Incompressible>(pdfFieldID)); - } - else if (firstBlock.isDataOfType<PdfField<LM_TRT_Compressible>>(pdfFieldID)) { - return make_shared<SweepWrapper>(SplitPureSweep<LM_TRT_Compressible>(pdfFieldID)); - } - else if (firstBlock.isDataOfType<PdfField<LM_TRT_Incompressible>>(pdfFieldID)) { - return make_shared<SweepWrapper>(SplitPureSweep<LM_TRT_Compressible>(pdfFieldID)); - } - else { - PyErr_SetString( PyExc_RuntimeError, "No split-pure sweep available for this lattice model" ); - throw boost::python::error_already_set(); - } - } -} - -template< typename LatticeModels > -struct VelocityAdaptorsFromLatticeModels -{ - typedef typename boost::mpl::transform< LatticeModels, internal::VelocityAdaptorFromLatticeModel<boost::mpl::_1 > >::type type; -}; - -template< typename LatticeModels > -struct DensityAdaptorsFromLatticeModels -{ - typedef typename boost::mpl::transform< LatticeModels, internal::DensityAdaptorFromLatticeModel<boost::mpl::_1> >::type type; -}; - -template< typename LatticeModels > -struct ShearRateAdaptorsFromLatticeModels -{ - typedef typename boost::mpl::transform< LatticeModels, internal::ShearRateAdaptorFromLatticeModel<boost::mpl::_1> >::type type; -}; - -template< typename LatticeModels > -struct AdaptorsFromLatticeModels -{ - typedef typename boost::mpl::copy< typename DensityAdaptorsFromLatticeModels<LatticeModels>::type, - boost::mpl::front_inserter< typename VelocityAdaptorsFromLatticeModels<LatticeModels>::type > > - ::type tmp1; - - typedef typename boost::mpl::copy< typename ShearRateAdaptorsFromLatticeModels<LatticeModels>::type, - boost::mpl::front_inserter< tmp1 > > - ::type type; -}; - - - -template<typename LatticeModels, typename FlagFields> -void exportBasic() -{ - using namespace boost::python; - - python_coupling::ModuleScope scope("lbm"); - - // Lattice Models - exportForceModels(); - exportCollisionModels(); - python_coupling::for_each_noncopyable_type<LatticeModels>( internal::LatticeModelExporter() ); - python_coupling::for_each_noncopyable_type<LatticeModels>( internal::AdaptorExporter() ); - - def( "makeLatticeModel", internal::makeLatticeModel<LatticeModels>, - ( arg("stencil"), arg("collisionModel"), - arg("forceModel")= force_model::None(), - arg("compressible")=false, arg("equilibriumAccuracyOrder")=2) ); - - // PdfField - python_coupling::for_each_noncopyable_type< LatticeModels > ( internal::PdfFieldExporter() ); - def( "addPdfFieldToStorage", &internal::addPdfFieldToStorage<LatticeModels>, - (( arg("blocks") ), - ( arg("name") ), - ( arg("latticeModel") ), - ( arg("initialVelocity") = Vector3<real_t>() ), - ( arg("initialDensity") = real_t(1) ), - ( arg("ghostlayers") = uint_t(1) ), - ( arg("layout") = field::zyxf ), - ( arg("densityAdaptor") = std::string() ), - ( arg("velocityAdaptor") = std::string() ), - ( arg("shearRateAdaptor")= std::string() ) - ) ); - - // Split Sweeps - def("makeSplitPureSweep", &internal::makeSplitPureSweep, (arg("blocks"), arg("pdfFieldId"))); - class_<internal::SweepWrapper, shared_ptr<internal::SweepWrapper>, boost::noncopyable>("SplitPureSweep", no_init) - .def("__call__", &internal::SweepWrapper::operator()); - - - auto pythonManager = python_coupling::Manager::instance(); - pythonManager->addBlockDataConversion< typename AdaptorsFromLatticeModels < LatticeModels >::type > (); -} - - - -} // namespace lbm -} // namespace walberla - - diff --git a/src/lbm/python/ExportBoundary.h b/src/lbm/python/ExportBoundary.h deleted file mode 100644 index a6803a374..000000000 --- a/src/lbm/python/ExportBoundary.h +++ /dev/null @@ -1,39 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportBoundary.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace lbm { - - template<typename LatticeModels, typename FlagFields> - void exportBoundary(); - -} // namespace lbm -} // namespace walberla - - -#include "ExportBoundary.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/lbm/python/ExportBoundary.impl.h b/src/lbm/python/ExportBoundary.impl.h deleted file mode 100644 index 06845e35a..000000000 --- a/src/lbm/python/ExportBoundary.impl.h +++ /dev/null @@ -1,279 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportBoundary.impl.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" -#include "python_coupling/helper/ModuleScope.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" -#include "python_coupling/helper/ConfigFromDict.h" -#include "python_coupling/helper/SliceToCellInterval.h" -#include "python_coupling/Manager.h" - -#include "core/logging/Logging.h" - -#include "boundary/python/Exports.h" - -#include "lbm/boundary/factories/ExtendedBoundaryHandlingFactory.h" - -#include "field/python/FieldExport.h" -#include "field/adaptors/AdaptorCreators.h" - -#include <boost/mpl/transform.hpp> -#include <boost/mpl/copy.hpp> - -namespace walberla { -namespace lbm { - - -namespace internal -{ - using python_coupling::localPythonSliceToCellInterval; - - - template<typename BH> - shared_ptr<BoundaryConfiguration> boundaryConfFromDict( BH & h, const BoundaryUID & uid, boost::python::dict d ) { - shared_ptr<Config> cfg = python_coupling::configFromPythonDict( d ); - return h.createBoundaryConfiguration( uid, cfg->getGlobalBlock() ); - } - template<typename BH> - void BH_setBoundary1( BH & h, const std::string & name, cell_idx_t x, cell_idx_t y , cell_idx_t z, boost::python::dict conf ) { - h.setBoundary( name,x,y,z, *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_setBoundary2( BH & h, const std::string & name, const boost::python::tuple & index, boost::python::dict conf ) { - h.setBoundary( name, - localPythonSliceToCellInterval( *h.getFlagField() , index ), - *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_forceBoundary1( BH & h, const std::string & name, cell_idx_t x, cell_idx_t y , cell_idx_t z, boost::python::dict conf ) { - h.forceBoundary( name,x,y,z, *boundaryConfFromDict( h, name, conf) ); - } - template<typename BH> - void BH_forceBoundary2( BH & h, const std::string & name, const boost::python::tuple & index, boost::python::dict conf ) { - h.forceBoundary( name, - localPythonSliceToCellInterval( *h.getFlagField() , index ), - *boundaryConfFromDict( h, name, conf) ); - } - - template<typename BH> - void BH_forceBoundary3( BH & h, const GhostLayerField<int,1> & indexField , boost::python::dict boundaryInfo ) - { - using namespace boost::python; - list keys = boundaryInfo.keys(); - - std::map<int, FlagUID > flagUIDs; - std::map<int, shared_ptr<BoundaryConfiguration> > boundaryConfigs; - - for (int i = 0; i < len( keys ); ++i) - { - int key = extract<int>( keys[i] ); - extract<std::string> extracted_str_val ( boundaryInfo[key] ); - extract<dict > extracted_dict_val ( boundaryInfo[key] ); - - if ( extracted_str_val.check() ) - { - std::string boundaryName = extracted_str_val; - flagUIDs[key] = FlagUID ( boundaryName ); - } - else if ( extracted_dict_val.check() ) - { - dict info = extracted_dict_val; - std::string boundaryName = extract<std::string>( info["name"] ); - - dict configDict = extract<dict>( info["config"] ); - - flagUIDs[key] = FlagUID ( boundaryName ); - boundaryConfigs[key] = boundaryConfFromDict( h, boundaryName, configDict); - } - else { - PyErr_SetString( PyExc_ValueError, "Invalid parameter"); - throw error_already_set(); - } - } - - // iterate over flag field - if ( indexField.xyzSize() != h.getFlagField()->xyzSize() || indexField.nrOfGhostLayers() > h.getFlagField()->nrOfGhostLayers() ) { - WALBERLA_LOG_DEVEL("indexField " << indexField.xyzSizeWithGhostLayer() ); - WALBERLA_LOG_DEVEL("flagField " << h.getFlagField()->xyzSizeWithGhostLayer() ); - PyErr_SetString( PyExc_ValueError, "Index field has to have same size as flag field"); - throw error_already_set(); - } - - - cell_idx_t gl = cell_idx_c( indexField.nrOfGhostLayers() ); - for( cell_idx_t z = -gl; z < cell_idx_c( indexField.zSizeWithGhostLayer() ); ++z ) - for( cell_idx_t y = -gl; y < cell_idx_c( indexField.ySizeWithGhostLayer() ); ++y ) - for( cell_idx_t x = -gl; x < cell_idx_c( indexField.xSizeWithGhostLayer() ); ++x ) - { - int index = indexField(x,y,z); - if ( flagUIDs.find( index ) != flagUIDs.end() ) - { - if ( boundaryConfigs.find( index ) != boundaryConfigs.end() ) - h.forceBoundary( flagUIDs[index],x,y,z, * boundaryConfigs[index] ); - else - h.forceBoundary( flagUIDs[index],x,y,z ); - } - } - } - - template<typename BH> - void BH_setDomainSlice( BH & h, const boost::python::tuple & index ) { - h.setDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - template<typename BH> - void BH_forceDomainSlice( BH & h, const boost::python::tuple & index ) { - h.forceDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - template<typename BH> - void BH_fillDomainSlice( BH & h, const boost::python::tuple & index ) { - h.fillWithDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_removeDomainSlice( BH & h, const boost::python::tuple & index ) { - h.removeDomain( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_removeBoundarySlice( BH & h, const boost::python::tuple & index ) { - h.removeBoundary( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - template<typename BH> - void BH_clearSlice( BH & h, const boost::python::tuple & index ) { - h.clear( localPythonSliceToCellInterval( *h.getFlagField() , index ) ); - } - - - - - class ExtendedBoundaryHandlingCreator - { - public: - - ExtendedBoundaryHandlingCreator( const shared_ptr<StructuredBlockStorage> & blocks, - const std::string & name, BlockDataID pdfFieldID, BlockDataID flagFieldID ) - : blocks_( blocks ), name_( name ), - pdfFieldID_( pdfFieldID ), flagFieldID_( flagFieldID ), found_ ( false ) - {} - - - template<typename LatticeModel> - void operator()( python_coupling::NonCopyableWrap<LatticeModel> ) - { - using namespace boost::python; - - IBlock & firstBlock = *( blocks_->begin() ); - if ( firstBlock.isDataClassOrSubclassOf< PdfField<LatticeModel> >( pdfFieldID_ ) ) - { - WALBERLA_ASSERT( !found_ ); - ExtendedBoundaryHandlingFactory<LatticeModel, FlagField<uint8_t> >::addBoundaryHandlingToStorage( - blocks_, name_, flagFieldID_, pdfFieldID_, FlagUID("fluid") ); - found_ = true; - } - } - - bool successful() const { return found_; } - - private: - shared_ptr<StructuredBlockStorage> blocks_; - std::string name_; - BlockDataID pdfFieldID_; - BlockDataID flagFieldID_; - - bool found_; - }; - - - template<typename LatticeModels> - void addBoundaryHandlingToStorage( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & name, - const std::string & pdfFieldStringID, - const std::string & flagFieldStringID ) - { - using namespace boost::python; - - if ( bs->begin() == bs->end() ) - return; - - - IBlock & firstBlock = *( bs->begin() ); - - BlockDataID pdfFieldID = python_coupling::blockDataIDFromString( firstBlock, pdfFieldStringID ); - BlockDataID flagFieldID = python_coupling::blockDataIDFromString( firstBlock, flagFieldStringID ); - - if ( ! firstBlock.isDataClassOrSubclassOf< FlagField<uint8_t> >( flagFieldID ) ) - { - PyErr_SetString( PyExc_ValueError, "Unknown FlagField type. Please provide a FlagField with 8 bit per cell"); - throw error_already_set(); - } - - ExtendedBoundaryHandlingCreator creator( bs, name, pdfFieldID, flagFieldID ); - python_coupling::for_each_noncopyable_type<LatticeModels>( std::ref( creator ) ); - - if ( ! creator.successful() ) - { - PyErr_SetString( PyExc_ValueError, "No Boundary Handling found for this lattice model"); - throw error_already_set(); - } - } - - template< typename LatticeModel > - struct ExtendedBoundaryHandlingFromLatticeModel - { - typedef typename ExtendedBoundaryHandlingFactory< LatticeModel, FlagField<uint8_t> >::BoundaryHandling type; - }; - } - - -template< typename LatticeModels > -struct ExtendedBoundaryHandlingsFromLatticeModels -{ - typedef typename boost::mpl::transform< LatticeModels, internal::ExtendedBoundaryHandlingFromLatticeModel<boost::mpl::_1> >::type type; -}; - - -template<typename LatticeModels, typename FlagFields> -void exportBoundary() -{ - using namespace boost::python; - - python_coupling::ModuleScope scope("lbm"); - - // Extended Boundary Handling - boundary::exportModuleToPython< typename ExtendedBoundaryHandlingsFromLatticeModels< LatticeModels >::type >(); - - def ( "addBoundaryHandlingToStorage", &internal::addBoundaryHandlingToStorage<LatticeModels>, - ( arg("blocks"), - arg("name"), - arg("pdfField"), - arg("flagField") ) ); - - auto pythonManager = python_coupling::Manager::instance(); - pythonManager->addBlockDataConversion< typename ExtendedBoundaryHandlingsFromLatticeModels< LatticeModels >::type > (); -} - - - -} // namespace lbm -} // namespace walberla - - diff --git a/src/lbm/python/ExportSweeps.h b/src/lbm/python/ExportSweeps.h deleted file mode 100644 index ba33e4803..000000000 --- a/src/lbm/python/ExportSweeps.h +++ /dev/null @@ -1,39 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportSweeps.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace lbm { - - template<typename LatticeModels, typename FlagFields> - void exportSweeps(); - -} // namespace lbm -} // namespace walberla - - -#include "ExportSweeps.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/lbm/python/ExportSweeps.impl.h b/src/lbm/python/ExportSweeps.impl.h deleted file mode 100644 index 5f9440114..000000000 --- a/src/lbm/python/ExportSweeps.impl.h +++ /dev/null @@ -1,260 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExportSweeps.impl.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BoostPythonHelpers.h" -#include "python_coupling/helper/ModuleScope.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" - -#include "python_coupling/Manager.h" - -#include "core/logging/Logging.h" - -#include "lbm/lattice_model/CollisionModel.h" -#include "lbm/sweeps/CellwiseSweep.h" - -#include "field/python/FieldExport.h" -#include "field/adaptors/AdaptorCreators.h" - -namespace walberla { -namespace lbm { - - -namespace internal -{ - template< typename LM, typename Filter, typename In, typename Out > - void addSweepMemberFunctions( boost::python::class_< CellwiseSweep<LM,Filter,In,Out>, shared_ptr<CellwiseSweep<LM,Filter,In,Out> > > & c ) - { - using namespace boost::python; - - typedef CellwiseSweep<LM,Filter,In,Out> Sweep; - c.def( "stream", &Sweep::stream, (arg("block"),arg("numberOfGhostLayersToInclude")=uint_t(0) ) ) - .def( "collide", &Sweep::collide, (arg("block"),arg("numberOfGhostLayersToInclude")=uint_t(0) ) ) - .def("streamCollide", &Sweep::streamCollide, (arg("block"),arg("numberOfGhostLayersToInclude")=uint_t(0) ) ) - .def("__call__", &Sweep::operator(), (arg("block"),arg("numberOfGhostLayersToInclude")=uint_t(0) ) ) - ; - } - - struct CellwiseSweepExporterWithoutFlagField - { - template<typename LatticeModel_T> - void operator()( python_coupling::NonCopyableWrap<LatticeModel_T> ) - { - using namespace boost::python; - - typedef GhostLayerField< real_t, 3 > VelocityField_T; - - typedef CellwiseSweep<LatticeModel_T, - field::DefaultEvaluationFilter, - DefaultDensityEquilibriumVelocityCalculation, - DefaultDensityVelocityCallback - > Sweep1; - typedef CellwiseSweep<LatticeModel_T, - field::DefaultEvaluationFilter, - DefaultDensityEquilibriumVelocityCalculation, - VelocityCallback<VelocityField_T> - > Sweep2; - - auto sweep1 = class_< Sweep1, shared_ptr<Sweep1> > ( "CellwiseSweep", no_init ); - auto sweep2 = class_< Sweep2, shared_ptr<Sweep2> > ( "CellwiseSweep", no_init ); - addSweepMemberFunctions( sweep1 ); - addSweepMemberFunctions( sweep2 ); - } - }; - - struct CellwiseSweepExporterWithFlagField - { - template<typename LatticeModel_FlagField_Pair> - void operator()( python_coupling::NonCopyableWrap<LatticeModel_FlagField_Pair> ) - { - using namespace boost::python; - - typedef typename LatticeModel_FlagField_Pair::first LatticeModel_T; - typedef typename LatticeModel_FlagField_Pair::second FlagField_T; - - typedef GhostLayerField< real_t,3> VelocityField_T; - - typedef CellwiseSweep<LatticeModel_T, - field::FlagFieldEvaluationFilter<FlagField_T>, - DefaultDensityEquilibriumVelocityCalculation, - DefaultDensityVelocityCallback - > Sweep1; - typedef CellwiseSweep<LatticeModel_T, - field::FlagFieldEvaluationFilter<FlagField_T>, - DefaultDensityEquilibriumVelocityCalculation, - VelocityCallback<VelocityField_T> - > Sweep2; - - auto sweep1 = class_< Sweep1, shared_ptr<Sweep1> > ( "CellwiseSweep", no_init ); - auto sweep2 = class_< Sweep2, shared_ptr<Sweep2> > ( "CellwiseSweep", no_init ); - addSweepMemberFunctions( sweep1 ); - addSweepMemberFunctions( sweep2 ); - } - }; - - - class CellwiseSweepCreator - { - public: - - CellwiseSweepCreator( const shared_ptr<StructuredBlockStorage> & blocks, BlockDataID pdfFieldID, - const std::string & flagFieldStringID, const std::string & velocityFieldStringID, - const Set< FlagUID > & cellsToEvaluate ) - : blocks_( blocks ), pdfFieldID_( pdfFieldID ), flagFieldStringID_( flagFieldStringID ), - velocityFieldStringID_( velocityFieldStringID ), cellsToEvaluate_( cellsToEvaluate ) - {} - - - template<typename LatticeModel_FlagField_Pair> - void operator()( python_coupling::NonCopyableWrap<LatticeModel_FlagField_Pair> ) - { - typedef GhostLayerField<real_t,3> VelocityField_T; - - using namespace boost::python; - using python_coupling::blockDataIDFromString; - - - typedef typename LatticeModel_FlagField_Pair::first LatticeModel_T; - typedef typename LatticeModel_FlagField_Pair::second FlagField_T; - - if ( blocks_->begin() == blocks_->end() ) - return; - - IBlock & firstBlock = *( blocks_->begin() ); - - if( ! firstBlock.isDataClassOrSubclassOf<PdfField<LatticeModel_T> >(pdfFieldID_) ) - return; - - if( flagFieldStringID_.size() > 0 ) - { - // Use FlagFilter - BlockDataID flagFieldID = blockDataIDFromString( firstBlock, flagFieldStringID_ ); - if ( ! firstBlock.isDataClassOrSubclassOf< FlagField_T>( flagFieldID ) ) - return; - - if ( velocityFieldStringID_.size() > 0 ) - { - BlockDataID velocityFieldID = blockDataIDFromString( firstBlock, velocityFieldStringID_ ); - result_ = object( makeCellwiseSweep<LatticeModel_T, FlagField_T, VelocityField_T >( pdfFieldID_, flagFieldID, - cellsToEvaluate_, velocityFieldID ) ); - } - else - { - result_ = object( makeCellwiseSweep<LatticeModel_T, FlagField_T>( pdfFieldID_, flagFieldID, cellsToEvaluate_ ) ); - } - } - else - { - if ( velocityFieldStringID_.size() > 0 ) - { - BlockDataID velocityFieldID = blockDataIDFromString( firstBlock, velocityFieldStringID_ ); - result_ = object ( makeCellwiseSweep<LatticeModel_T, - field::DefaultEvaluationFilter, - DefaultDensityEquilibriumVelocityCalculation, - VelocityCallback<VelocityField_T> - > - ( pdfFieldID_, field::DefaultEvaluationFilter(), - DefaultDensityEquilibriumVelocityCalculation(), - VelocityCallback<VelocityField_T>( velocityFieldID ) ) ); - } - else - { - result_ = object( makeCellwiseSweep<LatticeModel_T>( pdfFieldID_ ) ); - } - } - } - - boost::python::object getResult() const { return result_; } - - private: - shared_ptr<StructuredBlockStorage> blocks_; - BlockDataID pdfFieldID_; - std::string flagFieldStringID_; - std::string velocityFieldStringID_; - Set< FlagUID > cellsToEvaluate_; - - boost::python::object result_; - }; - - - template<typename LatticeModel_FlagField_Pairs> - boost::python::object makeCellwiseSweep( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & pdfFieldStringID, - const std::string & flagFieldStringID, boost::python::list flagList, - const std::string & velocityFieldStringID ) - { - using namespace boost::python; - - if ( bs->begin() == bs->end() ) - return object(); - IBlock & firstBlock = *( bs->begin() ); - - if( flagFieldStringID.size() > 0 || len(flagList) > 0 ) - { - if ( !( flagFieldStringID.size() > 0 && len(flagList) > 0 ) ) - { - PyErr_SetString( PyExc_ValueError, "Pass flagFieldID and flagList or none of them."); - throw error_already_set(); - } - } - - BlockDataID pdfFieldID = python_coupling::blockDataIDFromString( firstBlock, pdfFieldStringID ); - - auto flagUidSet = python_coupling::uidSetFromStringContainer< FlagUID >( flagList ); - - CellwiseSweepCreator creator( bs, pdfFieldID, flagFieldStringID, velocityFieldStringID, flagUidSet ); - python_coupling::for_each_noncopyable_type<LatticeModel_FlagField_Pairs>( std::ref( creator ) ); - - if ( creator.getResult() == object() ) - { - PyErr_SetString( PyExc_ValueError, "No Sweep available with these options."); - throw error_already_set(); - } - return creator.getResult(); - } - -} - -template<typename LatticeModels, typename FlagFields> -void exportSweeps() -{ - using namespace boost::python; - - - python_coupling::ModuleScope scope("lbm"); - - // Cellwise Sweep - typedef python_coupling::combine_vectors<LatticeModels,FlagFields> LatticeModel_FlagField_Pairs; - python_coupling::for_each_noncopyable_type<LatticeModel_FlagField_Pairs>( internal::CellwiseSweepExporterWithFlagField() ); - python_coupling::for_each_noncopyable_type<LatticeModels> ( internal::CellwiseSweepExporterWithoutFlagField() ); - def( "makeCellwiseSweep", internal::makeCellwiseSweep<LatticeModel_FlagField_Pairs>, - ( arg("blocks"), arg("pdfFieldID"), - arg("flagFieldID")=std::string(), arg("flagList")=boost::python::list(), - arg("velocityFieldID")=std::string() ) ); - -} - - - -} // namespace lbm -} // namespace walberla - - diff --git a/src/lbm/python/Exports.h b/src/lbm/python/Exports.h deleted file mode 100644 index bbf41d3b2..000000000 --- a/src/lbm/python/Exports.h +++ /dev/null @@ -1,49 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file PythonExports.h -//! \ingroup lbm -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "ExportBasic.h" -#include "ExportSweeps.h" -#include "ExportBoundary.h" - - -namespace walberla { -namespace lbm { - - - template<typename LatticeModels, typename FlagFields> - void exportModuleToPython() - { - exportBasic<LatticeModels,FlagFields>(); - exportSweeps<LatticeModels,FlagFields>(); - exportBoundary<LatticeModels,FlagFields>(); - } - - -} // namespace lbm -} // namespace walberla - - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/mesh/python/Exports.h b/src/mesh/python/Exports.h deleted file mode 100644 index 0ae7cfd3a..000000000 --- a/src/mesh/python/Exports.h +++ /dev/null @@ -1,41 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.h -//! \ingroup mesh -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace mesh { - - - template<typename FlagFields> - void exportModuleToPython(); - - -} // namespace mesh -} // namespace walberla - - -#include "Exports.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/mesh/python/Exports.impl.h b/src/mesh/python/Exports.impl.h deleted file mode 100644 index 4c68eb850..000000000 --- a/src/mesh/python/Exports.impl.h +++ /dev/null @@ -1,186 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.impl.h -//! \ingroup mesh -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" -#include "python_coupling/helper/ModuleScope.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON -#ifdef WALBERLA_BUILD_WITH_OPENMESH - -#include "python_coupling/Manager.h" -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" -#include "python_coupling/helper/PythonIterableToStdVector.h" -#include "python_coupling/helper/SharedPtrDeleter.h" - -#ifdef _MSC_VER -# pragma warning( push ) -# pragma warning( disable : 4456 4459 ) -#endif - -#include <OpenMesh/Core/IO/MeshIO.hh> -#include <OpenMesh/Core/Mesh/TriMesh_ArrayKernelT.hh> - -#ifdef _MSC_VER -# pragma warning( pop ) -#endif - -#include "mesh_common/MeshIO.h" -#include "mesh_common/distance_octree/DistanceOctree.h" -#include "mesh_common/DistanceComputations.h" -#include "mesh_common/DistanceFunction.h" -#include "mesh_common/MeshOperations.h" -#include "mesh_common/TriangleMeshes.h" -#include "mesh/boundary/BoundarySetup.h" -#include "mesh_common/vtk/VTKMeshWriter.h" - -using namespace boost::python; - - -namespace walberla { -namespace mesh { - -typedef mesh::DistanceOctree<PythonTriangleMesh> Octree; -typedef mesh::VTKMeshWriter<PythonTriangleMesh> MeshWriter; - -namespace internal -{ - void exp_readAndBroadcast(const std::string & fileName, PythonTriangleMesh & mesh ) - { - mesh::readAndBroadcast(fileName, mesh); - } - - - shared_ptr<Octree> makeDistanceOctree(object meshObj, uint_t maxDepth, uint_t minNumTriangles) - { - auto mesh = python_coupling::createSharedPtrFromPythonObject<PythonTriangleMesh>(meshObj); - auto triangleDistance = make_shared<TriangleDistance<PythonTriangleMesh> > (mesh); - return make_shared< Octree >(triangleDistance, maxDepth, minNumTriangles ); - } - - shared_ptr<MeshWriter> makeVTKMeshWriter(object meshObj, const std::string & identifier, const uint_t writeFrequency, const std::string & baseFolder) - { - shared_ptr<PythonTriangleMesh> mesh = python_coupling::createSharedPtrFromPythonObject<PythonTriangleMesh>(meshObj); - return walberla::make_shared< MeshWriter >( mesh, identifier, writeFrequency, baseFolder ); - } - - // ----------------------------------- markFlagField ---------------------------------------------------------------- - - - template<typename FlagField> - void markFlagFieldTmpl(const shared_ptr<Octree> & octree, const shared_ptr<StructuredBlockStorage> & bs, BlockDataID flagFieldID, - const std::string & flagName, uint_t ghostLayers) - { - BoundarySetup setup( bs, makeMeshDistanceFunction( octree ), ghostLayers); - setup.setFlag<FlagField>(flagFieldID, flagName, BoundarySetup::INSIDE); - } - - FunctionExporterClass( markFlagFieldTmpl, - void ( const shared_ptr<Octree> &, const shared_ptr<StructuredBlockStorage> & , - BlockDataID ,const std::string &, uint_t ) ); - - template<typename FlagFields> - void exp_markFlagField(const shared_ptr<Octree> & octree, const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataStr, const std::string & flagName, uint_t ghostLayers) - { - if ( bs->begin() == bs->end() ) - return; - IBlock * firstBlock = & ( * bs->begin() ); - - auto fieldID = python_coupling::blockDataIDFromString( *bs, blockDataStr ); - python_coupling::Dispatcher<FlagFields, Exporter_markFlagFieldTmpl > dispatcher( firstBlock ); - dispatcher( fieldID )(octree, bs, fieldID, flagName, ghostLayers); - } -} - - -bool Octree_isAABBFullyInside(const Octree & octree, const AABB & aabb) -{ - for( auto corner: aabb.corners() ) - { - const Octree::Point p ( numeric_cast<Octree::Scalar>(corner[0]), - numeric_cast<Octree::Scalar>(corner[1]), - numeric_cast<Octree::Scalar>(corner[2]) ); - if( octree.sqSignedDistance(p) > 0 ) - return false; - } - return true; -} - - -bool Octree_isAABBFullyOutside(const Octree & octree, const AABB & aabb) -{ - for( auto corner: aabb.corners() ) - { - const Octree::Point p ( numeric_cast<Octree::Scalar>(corner[0]), - numeric_cast<Octree::Scalar>(corner[1]), - numeric_cast<Octree::Scalar>(corner[2]) ); - if( octree.sqSignedDistance(p) < 0 ) - return false; - } - return true; -} - - -template<typename FlagFields> -void exportModuleToPython() -{ - python_coupling::ModuleScope fieldModule( "mesh" ); - - def( "readAndBroadcast", &internal::exp_readAndBroadcast, (arg("fileName"), arg("mesh")) ); - - def( "aabb", &mesh::computeAABB<PythonTriangleMesh>, (arg("mesh")) ); - def( "translate", &mesh::translate<PythonTriangleMesh>, (arg("mesh"), arg("translationVector")) ); - def( "scale", &mesh::scale<PythonTriangleMesh>, (arg("mesh"), arg("scaleFactors")) ); - def( "volume", &mesh::computeVolume<PythonTriangleMesh>, (arg("mesh")) ); - def( "surfaceArea", &mesh::computeSurfaceArea<PythonTriangleMesh>, (arg("mesh")) ); - - def( "markFlagField", &internal::exp_markFlagField<FlagFields> ); - - Octree::Scalar (Octree::*sqSignedDistance1)(const Octree::Point&) const= &Octree::sqSignedDistance; - Octree::Scalar (Octree::*sqDistance1)(const Octree::Point&) const= &Octree::sqDistance; - - class_<Octree, shared_ptr<Octree> >("DistanceOctree", no_init) - .def("__init__", make_constructor(internal::makeDistanceOctree, default_call_policies() ,(arg("mesh"), arg("maxDepth")=20u, arg("minNumTriangles")=25u) ) ) - .def("sqSignedDistance", sqSignedDistance1, (arg("p"))) - .def("sqDistance", sqDistance1, (arg("p"))) - .def("height", &Octree::height) - .def("writeVTKOutput", &Octree::writeVTKOutput, (arg("filestem"))) - .def("isAABBfullyOutside", &Octree_isAABBFullyOutside) - .def("isAABBfullyInside", &Octree_isAABBFullyInside) - ; - - class_<MeshWriter, shared_ptr<MeshWriter> >("VTKMeshWriter", no_init) - .def("__init__", make_constructor(internal::makeVTKMeshWriter, default_call_policies() ,(arg("mesh"), arg("identifier"), arg("writeFrequency")=1u, arg("baseFolder")="vtk_out") ) ) - .def("__call__", &MeshWriter::operator()) - ; - -} - - - -} // namespace mesh -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON -#endif //WALBERLA_BUILD_WITH_OPENMESH \ No newline at end of file diff --git a/src/postprocessing/python/Exports.h b/src/postprocessing/python/Exports.h deleted file mode 100644 index 17cd6b07a..000000000 --- a/src/postprocessing/python/Exports.h +++ /dev/null @@ -1,41 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.h -//! \ingroup postprocessing -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace postprocessing { - - - template<typename RealFields, typename FlagFields> - void exportModuleToPython(); - - -} // namespace postprocessing -} // namespace walberla - - -#include "Exports.impl.h" - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/postprocessing/python/Exports.impl.h b/src/postprocessing/python/Exports.impl.h deleted file mode 100644 index 4f67e756e..000000000 --- a/src/postprocessing/python/Exports.impl.h +++ /dev/null @@ -1,141 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.impl.h -//! \ingroup geometry -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" -#include "python_coupling/helper/ModuleScope.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/Manager.h" -#include "python_coupling/helper/MplHelpers.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" -#include "python_coupling/helper/PythonIterableToStdVector.h" - - -#include "postprocessing/FieldToSurfaceMesh.h" - -using namespace boost::python; - - -namespace walberla { -namespace postprocessing { - -FunctionExporterClass( realFieldToSurfaceMesh, - shared_ptr<geometry::TriangleMesh>( const shared_ptr<StructuredBlockStorage> &, - ConstBlockDataID, real_t, uint_t, bool, int, MPI_Comm ) ); - -template<typename FieldVector> -static shared_ptr<geometry::TriangleMesh> exp_realFieldToSurfaceMesh - ( const shared_ptr<StructuredBlockStorage> & bs, const std::string & blockDataStr, real_t threshold, - uint_t fCoord = 0, bool calcNormals = false, int targetRank = 0 ) -{ - if ( bs->begin() == bs->end() ) - return shared_ptr<geometry::TriangleMesh>(); - IBlock * firstBlock = & ( * bs->begin() ); - - auto fieldID = python_coupling::blockDataIDFromString( *bs, blockDataStr ); - - python_coupling::Dispatcher<FieldVector, Exporter_realFieldToSurfaceMesh > dispatcher( firstBlock ); - return dispatcher( fieldID )( bs, fieldID, threshold, fCoord, calcNormals, targetRank, MPI_COMM_WORLD) ; -} - - -template< typename FField> -typename FField::value_type maskFromFlagList( const shared_ptr<StructuredBlockStorage> & bs, - ConstBlockDataID flagFieldID, - const std::vector< std::string > & flagList ) -{ - if ( bs->begin() == bs->end() ) - return 0; - - IBlock & firstBlock = *( bs->begin() ); - const FField * flagField = firstBlock.getData< const FField > ( flagFieldID ); - - typedef typename FField::flag_t flag_t; - flag_t mask = 0; - for( auto it = flagList.begin(); it != flagList.end(); ++it ) - { - if ( ! flagField->flagExists( *it ) ) - throw python_coupling::BlockDataNotConvertible( "Unknown FlagID" ); - - mask = flag_t( mask | flagField->getFlag( *it ) ); - } - - return mask; -} - - -template<typename FlagField_T> -boost::python::object adaptedFlagFieldToSurfaceMesh( const shared_ptr<StructuredBlockStorage> & bs, - ConstBlockDataID fieldID, const std::vector< std::string > & flagList, - bool calcNormals = false, int targetRank = 0 ) -{ - using namespace boost::python; - - auto mask = maskFromFlagList<FlagField_T>( bs, fieldID, flagList ); - return object( flagFieldToSurfaceMesh<FlagField_T>(bs, fieldID, mask, calcNormals, targetRank ) ); -} - - -FunctionExporterClass( adaptedFlagFieldToSurfaceMesh, - boost::python::object( const shared_ptr<StructuredBlockStorage> &, ConstBlockDataID, - const std::vector< std::string > &, bool,int ) ); - - -template<typename FieldVector> -static boost::python::object exp_flagFieldToSurfaceMesh ( const shared_ptr<StructuredBlockStorage> & bs, - const std::string & blockDataName, - const boost::python::list & flagList, - bool calcNormals = false, int targetRank = 0 ) -{ - if ( bs->begin() == bs->end() ) - return boost::python::object(); //TODO check if this is correct - - IBlock * firstBlock = & ( * bs->begin() ); - - auto fieldID = python_coupling::blockDataIDFromString( *bs, blockDataName ); - - auto flagVector = python_coupling::pythonIterableToStdVector<std::string>( flagList ); - python_coupling::Dispatcher<FieldVector, Exporter_adaptedFlagFieldToSurfaceMesh > dispatcher( firstBlock ); - return dispatcher( fieldID )( bs, fieldID, flagVector, calcNormals, targetRank ); -} - - - -template<typename RealFields, typename FlagFields> -void exportModuleToPython() -{ - python_coupling::ModuleScope fieldModule( "postprocessing" ); - - def( "realFieldToMesh", &exp_realFieldToSurfaceMesh<RealFields>, - ( arg("blocks"), arg("blockDataName"), arg("fCoord")=0, arg("calcNormals") = false, arg("targetRank")=0 ) ); - - def( "flagFieldToMesh", &exp_flagFieldToSurfaceMesh<FlagFields>, - ( arg("blocks"), arg("blockDataName"), arg("flagList"), arg("calcNormals") = false, arg("targetRank")=0 ) ); -} - - - -} // namespace postprocessing -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/python_coupling/CMakeLists.txt b/src/python_coupling/CMakeLists.txt index 2b303c171..882a6d559 100644 --- a/src/python_coupling/CMakeLists.txt +++ b/src/python_coupling/CMakeLists.txt @@ -1,3 +1,5 @@ -waLBerla_add_module( DEPENDS core communication domain_decomposition stencil ) - - \ No newline at end of file +if (WALBERLA_BUILD_WITH_PYTHON) + waLBerla_add_module(DEPENDS core communication domain_decomposition stencil field blockforest vtk cuda) + target_link_libraries(python_coupling PUBLIC pybind11::embed core domain_decomposition) + set_target_properties(python_coupling PROPERTIES CXX_VISIBILITY_PRESET hidden) +endif() \ No newline at end of file diff --git a/src/python_coupling/CreateConfig.cpp b/src/python_coupling/CreateConfig.cpp index 0a4416c33..c7e3d1b24 100644 --- a/src/python_coupling/CreateConfig.cpp +++ b/src/python_coupling/CreateConfig.cpp @@ -16,248 +16,204 @@ //! \file CreateConfigFromPythonScript.cpp //! \ingroup python //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #include "CreateConfig.h" - +#include "core/StringUtility.h" #include "core/config/Config.h" #include "core/config/Create.h" #include "core/logging/Logging.h" -#include "core/StringUtility.h" - -#include <exception> - #ifdef WALBERLA_BUILD_WITH_PYTHON +# include "python_coupling/helper/ConfigFromDict.h" -#include "PythonCallback.h" -#include "PythonWrapper.h" -#include "DictWrapper.h" +# include "PythonCallback.h" +# include <pybind11/pybind11.h> -#include "python_coupling/helper/ConfigFromDict.h" -#include "helper/ExceptionHandling.h" +namespace walberla +{ +namespace python_coupling +{ +namespace py = pybind11; +shared_ptr< Config > createConfigFromPythonScript(const std::string& scriptFile, + const std::string& pythonFunctionName, + const std::vector< std::string >& argv) +{ + importModuleOrFile(scriptFile, argv); -namespace walberla { -namespace python_coupling { + PythonCallback pythonCallback(pythonFunctionName); - namespace bp = boost::python; + pythonCallback(); + using py::dict; + using py::object; - shared_ptr<Config> createConfigFromPythonScript( const std::string & scriptFile, - const std::string & pythonFunctionName, - const std::vector<std::string> & argv ) - { - importModuleOrFile( scriptFile, argv ); - - PythonCallback pythonCallback ( pythonFunctionName ); - - pythonCallback(); + object returnValue = pythonCallback.data().dict()["returnValue"]; + if (returnValue.is(object())) return shared_ptr< Config >(); - using boost::python::object; - using boost::python::dict; - using boost::python::extract; - - object returnValue = pythonCallback.data().dict()[ "returnValue" ]; - if ( returnValue == object() ) - return shared_ptr<Config>(); + bool isDict = py::isinstance< dict >(returnValue); + if (!isDict) { WALBERLA_ABORT("Python configuration did not return a dictionary object."); } + dict returnDict = dict(returnValue); + return configFromPythonDict(returnDict); +} - bool isDict = extract< dict >( returnValue ).check(); - if ( ! isDict ) { - WALBERLA_ABORT("Python configuration did not return a dictionary object."); - } - dict returnDict = extract<dict>( returnValue ); - return configFromPythonDict( returnDict ); - } - - - //=================================================================================================================== - // - // Config Generators and iterators - // - //=================================================================================================================== +//=================================================================================================================== +// +// Config Generators and iterators +// +//=================================================================================================================== +class PythonMultipleConfigGenerator : public config::ConfigGenerator +{ + public: + PythonMultipleConfigGenerator(py::list ConfigList) // NOLINT + : ConfigList_(ConfigList), counter(0) // NOLINT + {} - class PythonMultipleConfigGenerator : public config::ConfigGenerator + shared_ptr< Config > next() override { - public: - PythonMultipleConfigGenerator( bp::stl_input_iterator< bp::dict > iterator ) //NOLINT - : iter_( iterator ), firstTime_(true) //NOLINT - {} + shared_ptr< Config > config = make_shared< Config >(); - shared_ptr<Config> next() override - { - // this seemingly unnecessary complicated firstTime variable is used - // since in alternative version where (++iter_) is at the end of the function - // the python generator expression for the next time is already - // called before the current simulation finished - if ( !firstTime_ ) - ++iter_; - else - firstTime_ = false; + if ( counter == ConfigList_.size() ) + return shared_ptr<Config>(); - if ( iter_ == bp::stl_input_iterator< bp::dict >() ) - return shared_ptr<Config>(); + py::dict configDict = ConfigList_[counter]; + configFromPythonDict(config->getWritableGlobalBlock(), configDict); - shared_ptr<Config> config = make_shared<Config>(); + WALBERLA_LOG_INFO_ON_ROOT("Simulating Scenario " << counter + 1 << " of " << ConfigList_.size() << ":") - bp::dict configDict = *iter_; - configFromPythonDict( config->getWritableGlobalBlock(), configDict ); + counter++; - return config; - } - - private: - bp::stl_input_iterator< bp::dict > iter_; - bool firstTime_; - }; + return config; + } + private: + py::list ConfigList_; + uint_t counter; +}; +class PythonSingleConfigGenerator : public config::ConfigGenerator +{ + public: + PythonSingleConfigGenerator(const shared_ptr< Config >& config) : config_(config) {} - class PythonSingleConfigGenerator : public config::ConfigGenerator + shared_ptr< Config > next() override { - public: - PythonSingleConfigGenerator( const shared_ptr<Config> & config ): config_ ( config ) {} + auto res = config_; + config_.reset(); + return res; + } - shared_ptr<Config> next() override - { - auto res = config_; - config_.reset(); - return res; - } + private: + shared_ptr< Config > config_; +}; - private: - shared_ptr<Config> config_; - }; +config::Iterator createConfigIteratorFromPythonScript(const std::string& scriptFile, + const std::string& pythonFunctionName, + const std::vector< std::string >& argv) +{ + importModuleOrFile(scriptFile, argv); + PythonCallback pythonCallback(pythonFunctionName); + pythonCallback(); + py::object returnValue = pythonCallback.data().dict()["returnValue"]; + bool isDict = py::isinstance< py::dict >(returnValue); - config::Iterator createConfigIteratorFromPythonScript( const std::string & scriptFile, - const std::string & pythonFunctionName, - const std::vector<std::string> & argv ) + shared_ptr< config::ConfigGenerator > generator; + if (isDict) { - importModuleOrFile( scriptFile, argv ); - - PythonCallback pythonCallback ( pythonFunctionName ); - - pythonCallback(); - - bp::object returnValue = pythonCallback.data().dict()[ "returnValue" ]; - - bool isDict = bp::extract< bp::dict >( returnValue ).check(); - - shared_ptr< config::ConfigGenerator> generator; - if ( isDict ) + auto config = make_shared< Config >(); + py::dict extractedDict = py::cast< py::dict >(returnValue); + configFromPythonDict(config->getWritableGlobalBlock(), extractedDict); + generator = make_shared< PythonSingleConfigGenerator >(config); + } + else + { + try { - auto config = make_shared<Config>(); - bp::dict extractedDict = bp::extract<bp::dict> ( returnValue ); - configFromPythonDict( config->getWritableGlobalBlock(), extractedDict ); - generator = make_shared<PythonSingleConfigGenerator>( config ); - } - else { - - try { - generator= make_shared<PythonMultipleConfigGenerator>( returnValue ); - } - catch ( bp::error_already_set & ) { - python_coupling::terminateOnPythonException("Error while running Python config generator"); - } + generator = make_shared< PythonMultipleConfigGenerator >(returnValue); + } catch (py::error_already_set&) + { + std::string message = std::string("Error while running Python function ") + pythonFunctionName; + WALBERLA_ABORT_NO_DEBUG_INFO(message); } - - return config::Iterator( generator ); } + return config::Iterator(generator); +} } // namespace python_coupling } // namespace walberla - #else - -namespace walberla { -namespace python_coupling { - - shared_ptr<Config> createConfigFromPythonScript( const std::string &, const std::string &, const std::vector<std::string> & ) - { - WALBERLA_ABORT( "Tried to run with Python config but waLBerla was built without Python support." ); - return shared_ptr<Config>(); - } - - - config::Iterator createConfigIteratorFromPythonScript( const std::string & , const std::string &, const std::vector<std::string> & ) - { - WALBERLA_ABORT( "Tried to run with Python config but waLBerla was built without Python support." ); - return config::Iterator(); - } - +namespace walberla +{ +namespace python_coupling +{ +shared_ptr< Config > createConfigFromPythonScript(const std::string&, const std::string&, + const std::vector< std::string >&) +{ + WALBERLA_ABORT("Tried to run with Python config but waLBerla was built without Python support."); + return shared_ptr< Config >(); +} + +config::Iterator createConfigIteratorFromPythonScript(const std::string&, const std::string&, + const std::vector< std::string >&) +{ + WALBERLA_ABORT("Tried to run with Python config but waLBerla was built without Python support."); + return config::Iterator(); +} } // namespace python_coupling } // namespace walberla - #endif +namespace walberla +{ +namespace python_coupling +{ +shared_ptr< Config > createConfig(int argc, char** argv) +{ + if (argc < 2) throw std::runtime_error(config::usageString(argv[0])); + shared_ptr< Config > config; + std::string filename(argv[1]); + auto argVec = std::vector< std::string >(argv + 1, argv + argc); - - - - - - - - -namespace walberla { -namespace python_coupling { - - - - shared_ptr<Config> createConfig( int argc, char ** argv ) + if (string_ends_with(filename, ".py")) { config = createConfigFromPythonScript(filename, "config", argVec); } + else { - if(argc<2) - throw std::runtime_error( config::usageString(argv[0]) ); + config = make_shared< Config >(); + config::createFromTextFile(*config, filename); + } - shared_ptr<Config> config; - std::string filename( argv[1] ); + config::substituteCommandLineArgs(*config, argc, argv); - auto argVec = std::vector<std::string> (argv+1, argv + argc); + return config; +} - if ( string_ends_with( filename, ".py") ) { - config = createConfigFromPythonScript( filename, "config", argVec ); - } - else { - config = make_shared<Config>(); - config::createFromTextFile( *config, filename ); - } +config::Iterator configBegin(int argc, char** argv) +{ + if (argc < 2) throw std::runtime_error(config::usageString(argv[0])); - config::substituteCommandLineArgs( *config, argc, argv ); - - return config; + std::string filename(argv[1]); + if (string_ends_with(filename, ".py")) + { + auto argVec = std::vector< std::string >(argv + 1, argv + argc); + return createConfigIteratorFromPythonScript(filename, "config", argVec); } - - config::Iterator configBegin( int argc, char ** argv ) + else { - if(argc<2) - throw std::runtime_error( config::usageString(argv[0]) ); - - std::string filename( argv[1] ); - if ( string_ends_with( filename, ".py") ) { - auto argVec = std::vector<std::string> (argv+1, argv + argc); - return createConfigIteratorFromPythonScript( filename, "config", argVec ); - } - else { - return config::begin( argc, argv ); - } - + return config::begin(argc, argv); } - - - - +} } // namespace python_coupling } // namespace walberla - diff --git a/src/python_coupling/CreateConfig.h b/src/python_coupling/CreateConfig.h index 4c7dec116..f95d3586e 100644 --- a/src/python_coupling/CreateConfig.h +++ b/src/python_coupling/CreateConfig.h @@ -15,7 +15,8 @@ // //! \file CreateConfigFromPythonScript.h //! \ingroup python -//! \author martin +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> //! \brief Creates a walberla::Config object from a python script // //====================================================================================================================== diff --git a/src/python_coupling/DictWrapper.h b/src/python_coupling/DictWrapper.h index 0d2f0cab1..c3e1c2686 100644 --- a/src/python_coupling/DictWrapper.h +++ b/src/python_coupling/DictWrapper.h @@ -16,7 +16,8 @@ //! \file DictWrapper.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> -//! \brief Wrapper to store and extract values from boost::python::dict +//! \author Markus Holzer <markus.holzer@fau.de> +//! \brief Wrapper to store and extract values from pybind11 // //! \warning: if you include this header you also have to include Python.h as first header in your //! cpp file @@ -34,8 +35,6 @@ namespace walberla { namespace python_coupling { - - class DictWrapper { public: @@ -43,9 +42,9 @@ namespace python_coupling { //** Expose Data ************************************************************************************************* /*! \name Expose Data */ //@{ - template<typename T> inline void exposePtr( const std::string & name, T * var ); - template<typename T> inline void exposePtr( const std::string & name, const shared_ptr<T> & var ); - template<typename T> void exposeValue ( const std::string & name, const T & var ); + template<typename T> inline void exposePtr(const char* name, T * var ); + template<typename T> inline void exposePtr(const char* name, const shared_ptr<T> & var ); + template<typename T> void exposeValue ( const char* name, const T & var ); //@} //**************************************************************************************************************** @@ -53,19 +52,19 @@ namespace python_coupling { //** Get Data *************************************************************************************************** /*! \name Get Data */ //@{ - template<typename T> inline T get( const std::string & name ); - template<typename T> inline bool has( const std::string & name ); - template<typename T> inline bool checkedGet( const std::string & name, T output ); + template<typename T> inline T get( const char* name ); + template<typename T> inline bool has( const char* name ); + template<typename T> inline bool checkedGet( const char* name, T output ); //@} //**************************************************************************************************************** #ifdef WALBERLA_BUILD_WITH_PYTHON public: - boost::python::dict & dict() { return d_; } - const boost::python::dict & dict() const { return d_; } + pybind11::dict & dict() { return d_; } + const pybind11::dict & dict() const { return d_; } protected: - boost::python::dict d_; + pybind11::dict d_; #endif }; diff --git a/src/python_coupling/DictWrapper.impl.h b/src/python_coupling/DictWrapper.impl.h index b6ffecb9b..a2c8530c7 100644 --- a/src/python_coupling/DictWrapper.impl.h +++ b/src/python_coupling/DictWrapper.impl.h @@ -16,14 +16,18 @@ //! \file DictWrapper.impl.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #include <functional> +#include <pybind11/pybind11.h> namespace walberla { namespace python_coupling { +namespace py = pybind11; + //=================================================================================================================== // @@ -33,17 +37,17 @@ namespace python_coupling { template<typename T> -void DictWrapper::exposePtr( const std::string & name, T * var ) { - this->d_[name] = boost::python::ptr( var ); +void DictWrapper::exposePtr(const char* name, T * var ) { + this->d_[name] = var; } template<typename T> -void DictWrapper::exposePtr( const std::string & name, const shared_ptr<T> & var ) { - this->d_[name] = boost::python::ptr( var.get() ); +void DictWrapper::exposePtr(const char* name, const shared_ptr<T> & var ) { + this->d_[name] = var.get(); } template<typename T> -void DictWrapper::exposeValue( const std::string & name, const T & var ) { +void DictWrapper::exposeValue( const char* name, const T & var ) { this->d_[name] = var; } @@ -57,21 +61,21 @@ void DictWrapper::exposeValue( const std::string & name, const T & var ) { template<typename T> -T DictWrapper::get( const std::string & name ) { - return boost::python::extract<T>( d_[name] ); +T DictWrapper::get( const char* name ) { + return py::cast<T>( d_[name] ); } template<typename T> -bool DictWrapper::has( const std::string & name ) +bool DictWrapper::has( const char* name ) { - if(! d_.has_key(name) ) + if(! d_.contains(name) ) return false; - return boost::python::extract<T>( d_[name]).check(); + return py::class_<T>( d_[name]).check(); } template<typename T> -bool DictWrapper::checkedGet( const std::string & name, T output ) +bool DictWrapper::checkedGet( const char* name, T output ) { if ( ! has<T>(name) ) return false; @@ -85,20 +89,20 @@ bool DictWrapper::checkedGet( const std::string & name, T output ) template<> -inline DictWrapper DictWrapper::get( const std::string & name ) { - auto dictCopy = boost::python::extract< boost::python::dict >( d_[name] ); +inline DictWrapper DictWrapper::get( const char* name ) { + auto dictCopy = py::dict( d_[name] ); DictWrapper result; result.dict() = dictCopy; return result; } template<> -inline bool DictWrapper::has<DictWrapper >( const std::string & name ) +inline bool DictWrapper::has<DictWrapper >( const char* name ) { - if(! d_.has_key(name) ) + if(! d_.contains(name) ) return false; - return boost::python::extract< boost::python::dict >( d_[name]).check(); + return py::isinstance<py::dict>(d_[name]); } @@ -109,22 +113,22 @@ inline bool DictWrapper::has<DictWrapper >( const std::string & name ) //=================================================================================================================== // void() -inline void runPythonObject( boost::python::object obj ) { +inline void runPythonObject( py::object obj ) { obj(); } template<> -inline std::function<void()> DictWrapper::get( const std::string & name ) { - boost::python::object obj ( d_[name] ); +inline std::function<void()> DictWrapper::get( const char* name ) { + py::object obj ( d_[name] ); return std::bind( &runPythonObject, obj ); } template<> -inline bool DictWrapper::has<std::function<void()> >( const std::string & name ) +inline bool DictWrapper::has<std::function<void()> >( const char* name ) { - if(! d_.has_key(name) ) + if(! d_.contains(name) ) return false; - return PyCallable_Check( boost::python::object(d_[name]).ptr() ) != 0; + return PyCallable_Check( py::object(d_[name]).ptr() ) != 0; } diff --git a/src/python_coupling/Manager.cpp b/src/python_coupling/Manager.cpp index b7af694e8..4b22df974 100644 --- a/src/python_coupling/Manager.cpp +++ b/src/python_coupling/Manager.cpp @@ -16,6 +16,7 @@ //! \file Manager.cpp //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -26,25 +27,23 @@ #ifdef WALBERLA_BUILD_WITH_PYTHON -#include "core/waLBerlaBuildInfo.h" -#include "Manager.h" -#include "core/logging/Logging.h" -#include "python_coupling/basic_exports/BasicExports.h" +# include "core/logging/Logging.h" +# include "core/waLBerlaBuildInfo.h" -#include <cstdlib> +# include "python_coupling/export/BasicExport.h" +# include <pybind11/embed.h> -BOOST_PYTHON_MODULE( walberla_cpp ) +# include "Manager.h" + +PYBIND11_MODULE( walberla_cpp, m) { using namespace walberla::python_coupling; - auto manager =Manager::instance(); - exportBasicWalberlaDatastructures(); - manager->exportAll(); + auto manager = Manager::instance(); + exportBasicWalberlaDatastructures(m); + manager->exportAll(m); } -using namespace boost::python; - - namespace walberla { namespace python_coupling { @@ -57,7 +56,7 @@ Manager::~Manager( ) //NOLINT { // To work reliably this would have to be called at the end of the // main function. At this position this leads to a segfault in some cases - // Py_Finalize(); + // py::finalize_interpreter(); } void Manager::addEntryToPythonPath( const std::string & path ) @@ -75,15 +74,13 @@ void Manager::addPath( const std::string & path ) { WALBERLA_ASSERT( initialized_ ); - object sys = import("sys"); - list sys_path = extract<list>( sys.attr("path") ); + py::object sys = py::module::import("sys"); + py::list sys_path = py::list( sys.attr("path") ); sys_path.append(path); } void Manager::triggerInitialization() { - using namespace boost::python; - if ( initialized_ ){ return; } @@ -91,15 +88,14 @@ void Manager::triggerInitialization() try { -#if PY_MAJOR_VERSION >= 3 + // The python module is used as embedded module here. There is a pybind11 macro for that called + // PYBIND11_EMBEDDED_MODULE. However it can not be used here since we want a shared lib for the python coupling. + // With the C-Call the so is embedded here. PyImport_AppendInittab( (char*)"walberla_cpp", PyInit_walberla_cpp ); -#else - PyImport_AppendInittab( (char*)"walberla_cpp", initwalberla_cpp ); -#endif - Py_Initialize(); - import("__main__"); - import("walberla_cpp"); + py::initialize_interpreter(); + py::module::import("__main__"); + py::module::import("walberla_cpp"); // Setup python path addPath( std::string(WALBERLA_SOURCE_DIR) + "/python" ); @@ -113,54 +109,41 @@ void Manager::triggerInitialization() entriesForPythonPath_.clear(); } - catch ( boost::python::error_already_set & ) { - PyObject *type_ptr = nullptr; - - PyObject *value_ptr = nullptr; - - PyObject *traceback_ptr = nullptr; - PyErr_Fetch(&type_ptr, &value_ptr, &traceback_ptr); - - if( type_ptr ) - { - extract<std::string> type_str(( str( handle<>( type_ptr ) ) )); - if( type_str.check() ) - WALBERLA_LOG_DEVEL( type_str() ); + catch ( py::error_already_set & e ) { + if (e.matches(PyExc_ModuleNotFoundError)){ + py::print("The module walberla_cpp could not be found"); } - if(value_ptr) - { - extract<std::string> value_str(( str( handle<>( value_ptr ) ) )); - if ( value_str.check() ) - WALBERLA_LOG_DEVEL( value_str() ); + else { + py::print("Unexpected Exception"); + throw; } - WALBERLA_ABORT( "Error while initializing Python" ); } } -void Manager::exportAll() +void Manager::exportAll(py::module_ &m) { for( auto it = exporterFunctions_.begin(); it != exporterFunctions_.end(); ++it ) { - (*it)(); + (*it)(m); } } -boost::python::object Manager::pythonObjectFromBlockData( IBlock & block, BlockDataID id ) +py::object Manager::pythonObjectFromBlockData( IBlock & block, BlockDataID id ) { - if( block.isDataOfType< boost::python::object > ( id ) ) - return *block.getData< boost::python::object > ( id ); + if( block.isDataOfType< py::object > ( id ) ){ + return *block.getData< py::object > ( id );} for( auto it = blockDataToObjectFunctions_.begin(); it != blockDataToObjectFunctions_.end(); ++it ) { auto res = (*it)( block, id ); - if ( res != boost::python::object() ) - return res; + if ( !res.is(py::object()) ){ + return res;} } - return boost::python::object(); + return py::object(); } diff --git a/src/python_coupling/Manager.h b/src/python_coupling/Manager.h index ed843ff11..8f860a27a 100644 --- a/src/python_coupling/Manager.h +++ b/src/python_coupling/Manager.h @@ -16,6 +16,7 @@ //! \file Manager.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> //! \brief Singleton managing Python coupling // //====================================================================================================================== @@ -27,11 +28,13 @@ #include "python_coupling/helper/MplHelpers.h" #include "core/singleton/Singleton.h" #include "domain_decomposition/IBlock.h" +#include <pybind11/pybind11.h> void init_module_walberla_cpp(); namespace walberla { namespace python_coupling { +namespace py = pybind11; class BlockDataToObjectTester @@ -44,24 +47,24 @@ namespace python_coupling { template<typename TypeToTest> void operator() ( NonCopyableWrap<TypeToTest> ) { - using boost::python::object; - if ( result_ == object() && block_->isDataClassOrSubclassOf<TypeToTest>( blockDataID_ ) ) { - result_ = object( boost::python::ptr( block_->getData<TypeToTest>( blockDataID_ ) ) ); + using py::object; + if ( result_.is(py::object()) && block_->isDataClassOrSubclassOf<TypeToTest>( blockDataID_ ) ) { + result_ = py::cast( block_->getData<TypeToTest>( blockDataID_ ) ); } } - boost::python::object getResult() { return result_; } + py::object getResult() { return result_; } private: IBlock * block_; BlockDataID blockDataID_; - boost::python::object result_; + py::object result_; }; - template<typename TypeList> - boost::python::object testBlockData( IBlock & block, BlockDataID blockDataID ) + template<typename... Types> + py::object testBlockData( IBlock & block, BlockDataID blockDataID ) { BlockDataToObjectTester tester( &block, blockDataID ); - for_each_noncopyable_type< TypeList > ( std::ref(tester) ); + for_each_noncopyable_type< Types... > ( std::ref(tester) ); return tester.getResult(); } @@ -71,8 +74,8 @@ namespace python_coupling { public: WALBERLA_BEFRIEND_SINGLETON; - typedef std::function<void()> ExporterFunction; - typedef std::function< boost::python::object ( IBlock&, BlockDataID ) > BlockDataToObjectFunction; + typedef std::function<void(py::module_&)> ExporterFunction; + typedef std::function< py::object ( IBlock&, BlockDataID ) > BlockDataToObjectFunction; ~Manager(); @@ -82,19 +85,21 @@ namespace python_coupling { void addEntryToPythonPath( const std::string & path ); - void addExporterFunction( const ExporterFunction & f ) { exporterFunctions_.push_back( f ); } - - template<typename TypeList> - void addBlockDataConversion() { blockDataToObjectFunctions_.push_back( &testBlockData<TypeList> ); } + void addExporterFunction( const ExporterFunction & f) + { + exporterFunctions_.push_back( f ); + } + template<typename... Types> + void addBlockDataConversion() { blockDataToObjectFunctions_.push_back( &testBlockData<Types...> ); } - protected: + void exportAll(py::module_ &m); + protected: void addPath( const std::string & path ); friend void ::init_module_walberla_cpp(); - void exportAll(); - friend boost::python::object IBlock_getData( boost::python::object, const std::string & ); - boost::python::object pythonObjectFromBlockData( IBlock & block, BlockDataID id ); + friend py::object IBlock_getData( py::object, const std::string & ); + py::object pythonObjectFromBlockData( IBlock & block, BlockDataID id ); Manager(); diff --git a/src/python_coupling/PythonCallback.cpp b/src/python_coupling/PythonCallback.cpp index 507087fc9..b4d0fb6d8 100644 --- a/src/python_coupling/PythonCallback.cpp +++ b/src/python_coupling/PythonCallback.cpp @@ -16,36 +16,30 @@ //! \file PythonCallback.cpp //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #include "PythonCallback.h" -#include "PythonWrapper.h" #include "DictWrapper.h" #ifdef WALBERLA_BUILD_WITH_PYTHON #include "Manager.h" #include "core/Abort.h" -#include "core/logging/Logging.h" -#include "helper/ExceptionHandling.h" #include "core/Filesystem.h" -#if defined(__GLIBCXX__) && __GLIBCXX__ <= 20160609 -#define CURRENT_PATH_WORKAROUND -#include <unistd.h> -#include <errno.h> -#endif +#include "pybind11/eval.h" namespace walberla { namespace python_coupling { - static boost::python::object importModuleOrFileInternal( const std::string & fileOrModuleName, const std::vector< std::string > & argv ) + static py::object importModuleOrFileInternal( const std::string & fileOrModuleName, const std::vector< std::string > & argv ) { auto manager = python_coupling::Manager::instance(); manager->triggerInitialization(); - namespace bp = boost::python; + namespace py = pybind11; std::string moduleName = fileOrModuleName; @@ -57,52 +51,25 @@ namespace python_coupling { code << "] \n"; filesystem::path path ( fileOrModuleName ); -#ifdef CURRENT_PATH_WORKAROUND - // workaround for double free in filesystem::current_path in libstdc++ 5.4 and lower - size_t cwd_size = 16; - char * cwd_buf = (char*) std::malloc(cwd_size * sizeof(char)); - - while( getcwd( cwd_buf, cwd_size ) == NULL ) - { - if (errno == ERANGE) - { - cwd_size *= 2; - cwd_buf = (char*) std::realloc( cwd_buf, cwd_size * sizeof(char) ); - } - else - { - python_coupling::terminateOnPythonException( std::string("Could not determine working directory") ); - } - } - - std::string cwd(cwd_buf); - std::free(cwd_buf); - path = filesystem::absolute( path, cwd ); -#else path = filesystem::absolute( path ); -#endif + if ( path.extension() == ".py" ) { moduleName = path.stem().string(); - - - if ( ! path.parent_path().empty() ) { -#ifdef CURRENT_PATH_WORKAROUND - std::string p = filesystem::canonical(path.parent_path(), cwd).string(); -#else + if ( ! path.parent_path().empty() ) { std::string p = filesystem::canonical(path.parent_path()).string(); -#endif code << "sys.path.append( r'" << p << "')" << "\n"; } } - bp::exec( code.str().c_str(), bp::import("__main__").attr("__dict__") ); + + py::exec( code.str().c_str(), py::module::import("__main__").attr("__dict__") ); try { - return bp::import( moduleName.c_str() ); + return py::module::import( moduleName.c_str() ); } - catch ( bp::error_already_set & ) { - python_coupling::terminateOnPythonException( std::string("Python Error while loading ") + fileOrModuleName ); - return boost::python::object(); + catch ( py::error_already_set &e) { + throw py::value_error(e.what()); + return py::none(); } } @@ -116,7 +83,7 @@ namespace python_coupling { : exposedVars_( new DictWrapper() ), callbackDict_( new DictWrapper() ) { Manager::instance()->triggerInitialization(); - callbackDict_->dict() = boost::python::dict(); + callbackDict_->dict() = py::dict(); } @@ -125,13 +92,13 @@ namespace python_coupling { { Manager::instance()->triggerInitialization(); - using namespace boost::python; + namespace py = pybind11; // Add empty callbacks module importModuleOrFileInternal( fileOrModuleName, argv ); - object callbackModule = import( "walberla_cpp.callbacks"); + py::object callbackModule = py::module::import( "walberla_cpp.callbacks"); - callbackDict_->dict() = extract<dict>( callbackModule.attr( "__dict__" ) ); + callbackDict_->dict() = py::dict( callbackModule.attr( "__dict__" ) ); } @@ -140,41 +107,36 @@ namespace python_coupling { { Manager::instance()->triggerInitialization(); - using namespace boost::python; - // Add empty callbacks module - object callbackModule = import( "walberla_cpp.callbacks"); + py::object callbackModule = py::module::import( "walberla_cpp.callbacks"); - callbackDict_->dict() = extract<dict>( callbackModule.attr( "__dict__" ) ); + callbackDict_->dict() = py::dict( callbackModule.attr( "__dict__" ) ); } bool PythonCallback::isCallable() const { - return callbackDict_->dict().has_key( functionName_ ); + return callbackDict_->dict().contains( functionName_ ); } void PythonCallback::operator() () { if ( ! isCallable() ) WALBERLA_ABORT_NO_DEBUG_INFO( "Could not call python function '" << functionName_ << "'. " << - "Did you forget to set the callback function?" ); + "Did you forget to set the callback function?" ); - namespace bp = boost::python; + namespace py = pybind11; try { - if ( exposedVars_->dict().has_key("returnValue")) - bp::api::delitem( exposedVars_->dict(), "returnValue" ); - - bp::object function = callbackDict_->dict()[ functionName_ ]; + py::object function = callbackDict_->dict()[ functionName_.c_str() ]; - bp::object returnVal; - returnVal = function( *bp::tuple(), **(exposedVars_->dict() ) ); + py::object returnVal; + returnVal = function( *py::tuple(), **(exposedVars_->dict() ) ); exposedVars_->dict()["returnValue"] = returnVal; } - catch ( bp::error_already_set & ) { - python_coupling::terminateOnPythonException( std::string("Error while running Python function ") + functionName_ ); + catch ( py::error_already_set &e ) { + throw py::value_error(e.what()); } } diff --git a/src/python_coupling/PythonCallback.h b/src/python_coupling/PythonCallback.h index de7d0eaee..9eeaec650 100644 --- a/src/python_coupling/PythonCallback.h +++ b/src/python_coupling/PythonCallback.h @@ -16,6 +16,7 @@ //! \file PythonCallback.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -79,8 +80,8 @@ namespace python_coupling { PythonCallback(); PythonCallback( const std::string & functionName ); PythonCallback( const std::string & moduleOrFile, - const std::string & functionName, - const std::vector<std::string> & argv = std::vector<std::string>() ); + const std::string & functionName, + const std::vector<std::string> & argv = std::vector<std::string>() ); DictWrapper & data() { return *exposedVars_; } const DictWrapper & data() const { return *exposedVars_; } diff --git a/src/python_coupling/PythonWrapper.h b/src/python_coupling/PythonWrapper.h index 74ce9918e..7ae14bada 100644 --- a/src/python_coupling/PythonWrapper.h +++ b/src/python_coupling/PythonWrapper.h @@ -17,6 +17,7 @@ //! \ingroup core //! \author Matthias Markl <matthias.markl@fau.de> //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -36,9 +37,7 @@ #endif #endif -#include <boost/python.hpp> -#include <boost/python/stl_iterator.hpp> -#include <boost/python/suite/indexing/vector_indexing_suite.hpp> +#include "pybind11/pybind11.h" #ifdef _MSC_VER #ifdef __CREATED_HAVE_ROUND diff --git a/src/python_coupling/Shell.cpp b/src/python_coupling/Shell.cpp deleted file mode 100644 index 5749511e0..000000000 --- a/src/python_coupling/Shell.cpp +++ /dev/null @@ -1,247 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Shell.impl.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important - -#include "PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "Shell.h" -#include "DictWrapper.h" -#include "Manager.h" - -#include "core/logging/Logging.h" -#include "core/StringUtility.h" - - -namespace walberla { -namespace python_coupling { - - - Shell::Shell( const std::string & prompt ) - : exposedVars_( new DictWrapper() ) - { - Manager::instance()->triggerInitialization(); - - using namespace boost::python; - - try { - object main_module = import("__main__"); - dict globals = extract<dict>( main_module.attr( "__dict__" ) ); - - exec("import os \n" - "import code \n" - "try:\n" - " import readline \n" - " import rlcompleter \n" - " readline.parse_and_bind(\"tab: complete\") \n" - " histfile = os.path.join( os.path.expanduser('~'), '.waLBerla_history') \n" - " try:\n" - " readline.read_history_file(histfile)\n" - " except IOError:\n" - " pass\n" - "except ImportError:\n" - " pass\n" - "\n", globals ); - - - prompt1_ = prompt; - for ( uint_t i=0; i < prompt.size(); ++i ) - prompt2_ += " "; - - prompt1_ += "> "; - prompt2_ += "> "; - - exec("import sys", globals ); - exec( std::string( "sys.ps1 = '" + prompt1_ + "'" ).c_str(), globals ); - exec( std::string( "sys.ps2 = '" + prompt2_ + "'" ).c_str(), globals ); - } - catch ( error_already_set & ) { - PyErr_Print(); - WALBERLA_ABORT( "Error initializing Shell" ); - } - } - - Shell::~Shell() - { - using namespace boost::python; - - object main_module = import("__main__"); - dict globals = extract<dict>( main_module.attr( "__dict__" ) ); - exec("readline.write_history_file(histfile)", globals ); - } - - - bool Shell::isCompleteCommand ( const std::string & code ) - { - using namespace boost::python; - object main_module = import("__main__"); - dict globals = extract<dict>( main_module.attr( "__dict__" ) ); - - boost::python::dict locals; - locals["codeToTest"] = code; - object compiledCode = eval( str( "code.compile_command(codeToTest)" ), globals, locals ); - return ( compiledCode != object() ); - } - - bool Shell::getCompleteCommand( std::string & result ) - { - uint_t lineCounter = 0; - - while ( true ) - { - char* line; - - if ( lineCounter == 0 ) - line = PyOS_Readline( stdin, stdout, (char*)prompt1_.c_str() ); - else - line = PyOS_Readline( stdin, stdout, (char*)prompt2_.c_str() ); - - if ( line == nullptr || *line == '\0' ) { // interrupt or EOF - result.clear(); - return false; - } - - std::string strLine ( line ); - std::string strTrimmedLine( line ); - string_trim( strTrimmedLine ); - - PyMem_Free( line ); - - lineCounter++; - result += strLine; - - bool commandComplete = isCompleteCommand( result ); - - if ( lineCounter == 1 && commandComplete ) - return true; - if ( strTrimmedLine.empty() && isCompleteCommand(result) ) // multiline commands have to end with empty line - return true; - } - - return false; - } - - - void Shell::operator() () - { - using namespace boost::python; - - object main_module = import("__main__"); - dict globals = extract<dict>( main_module.attr( "__dict__" ) ); - - globals.update( exposedVars_->dict() ); - exec( "from waLBerla import *", globals ); - - - const int MAX_LINE_LENGTH = 1024; - const char continueMarker = 'c'; - const char stopMarker = 's'; - - WALBERLA_ROOT_SECTION() - { - std::string code; - - while ( true ) - { - code.clear(); - - try - { - if ( ! getCompleteCommand(code ) ) { - std::cout << "\n"; - code.resize( MAX_LINE_LENGTH ); - code[0] = stopMarker; - MPI_Bcast( (void*) code.c_str(), MAX_LINE_LENGTH, // send stop command - MPI_CHAR, 0, MPI_COMM_WORLD ); - break; - } - else - { - std::string codeToSend = continueMarker + code; - - if ( codeToSend.size() >= uint_c( MAX_LINE_LENGTH ) ) - { - WALBERLA_LOG_WARNING("Line length too big, only allowed " << MAX_LINE_LENGTH-1 << " characters" ); - continue; - } - codeToSend.resize( MAX_LINE_LENGTH ); - MPI_Bcast( (void*) codeToSend.c_str(), MAX_LINE_LENGTH, // send code snippet to other processes - MPI_CHAR, 0, MPI_COMM_WORLD ); - - PyRun_SimpleString( code.c_str() ); - fflush( stderr ); - WALBERLA_MPI_BARRIER(); - } - } - catch( boost::python::error_already_set & ) { - PyErr_Print(); - } - } - } - else - { - char * buffer = new char[MAX_LINE_LENGTH]; - - while ( true) - { - - MPI_Bcast( (void*) buffer, MAX_LINE_LENGTH, // send code snippet to other processes - MPI_CHAR, 0, MPI_COMM_WORLD ); - - if ( *buffer == stopMarker ) - break; - - std::string code ( buffer+1 ); - - PyRun_SimpleString( code.c_str() ); - fflush( stderr ); - WALBERLA_MPI_BARRIER(); - } - - - delete [] buffer; - } - } - - -} // namespace python_coupling -} // namespace walberla - - -#else - - -#include "Shell.h" - -namespace walberla { -namespace python_coupling { - - Shell::Shell( const std::string & ) {} - Shell::~Shell() = default; - void Shell::operator()() {} - -} // namespace python_coupling -} // namespace walberla - - -#endif diff --git a/src/python_coupling/Shell.h b/src/python_coupling/Shell.h deleted file mode 100644 index 41be5c3c8..000000000 --- a/src/python_coupling/Shell.h +++ /dev/null @@ -1,63 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ScriptRunner.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -//! \brief Runs a python script that can access waLBerla variables -// -//====================================================================================================================== - -#pragma once - -#include <string> - -#include "waLBerlaDefinitions.h" -#include "core/DataTypes.h" - - - -namespace walberla { -namespace python_coupling { - - class DictWrapper; - - class Shell - { - public: - Shell( const std::string & prompt = "waLBerla"); - ~Shell(); - - void operator() (); - - inline void run() { (*this)(); } - inline DictWrapper & data() { return *exposedVars_; } - - protected: - bool getCompleteCommand( std::string & result ); - bool isCompleteCommand ( const std::string & code ); - - shared_ptr<DictWrapper> exposedVars_; - std::string prompt1_; - std::string prompt2_; - }; - - -} // namespace python_coupling -} // namespace walberla - - - - diff --git a/src/python_coupling/TimeloopIntercept.cpp b/src/python_coupling/TimeloopIntercept.cpp deleted file mode 100644 index 17e7df788..000000000 --- a/src/python_coupling/TimeloopIntercept.cpp +++ /dev/null @@ -1,136 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file TimeloopIntercept.cpp -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#include "TimeloopIntercept.h" -#include "DictWrapper.h" -#include "PythonCallback.h" -#include "Shell.h" - -#include "core/logging/Logging.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - - - -#if defined(_MSC_VER) - -#else -# include <csignal> -#endif - - -static bool signalTriggered = false; - - -namespace walberla { -namespace python_coupling { - - -#if defined(_MSC_VER) - -void enableSignalHandler() { - -} - -#else - -void customSignalHandler( int ) { - signalTriggered = true; -} - -void enableSignalHandler() { - std::signal (SIGUSR1, customSignalHandler ); -} - -#endif - - - -TimeloopIntercept::TimeloopIntercept( const std::string & functionName, uint_t interval, bool enableSignalInterrupt ) - : callback_ ( walberla::make_shared<PythonCallback> ( functionName ) ), - timestep_ ( 0 ), - interval_ ( interval ), - enableSignalInterrupt_ ( enableSignalInterrupt ) -{ - if ( enableSignalInterrupt ) - enableSignalHandler(); -} - -TimeloopIntercept::TimeloopIntercept( const std::string & pythonFile, const std::string & functionName, - uint_t interval, bool enableSignalInterrupt ) - : callback_ ( walberla::make_shared<PythonCallback> ( pythonFile, functionName ) ), - timestep_ ( 0 ), - interval_ ( interval ), - enableSignalInterrupt_ ( enableSignalInterrupt ) -{ - if ( enableSignalInterrupt ) - enableSignalHandler(); -} - - -void TimeloopIntercept::operator() () -{ - ++timestep_; - if( interval_ > 0 && ( timestep_ % interval_ == 0 ) ) - (*callback_)(); - - if ( enableSignalInterrupt_ && signalTriggered ) - { - WALBERLA_LOG_INFO( "Interrupting Simulation at timestep " << timestep_ ); - signalTriggered = false; - Shell shell; - shell.data() = this->callback()->data(); - shell.run(); - WALBERLA_LOG_INFO( "Continue Simulation at timestep " << timestep_+1 << " ..." ); - } -} - - - -} // namespace python_coupling -} // namespace walberla - -#else - -namespace walberla { -namespace python_coupling { - -TimeloopIntercept::TimeloopIntercept( const std::string & functionName, uint_t interval, bool enableSignalInterrupt ) - : callback_ ( walberla::make_shared<PythonCallback> ( functionName ) ), - timestep_ ( 0 ), - interval_ ( interval ), - enableSignalInterrupt_ ( enableSignalInterrupt ) -{} - -TimeloopIntercept::TimeloopIntercept( const std::string & pythonFile, const std::string & functionName, - uint_t interval, bool enableSignalInterrupt ) - : callback_ ( walberla::make_shared<PythonCallback> ( pythonFile, functionName ) ), - timestep_ ( 0 ), - interval_ ( interval ), - enableSignalInterrupt_ ( enableSignalInterrupt ) -{} - -void TimeloopIntercept::operator() (){} - -} // namespace python_coupling -} // namespace walberla - -#endif diff --git a/src/python_coupling/TimeloopIntercept.h b/src/python_coupling/TimeloopIntercept.h deleted file mode 100644 index fc7f49645..000000000 --- a/src/python_coupling/TimeloopIntercept.h +++ /dev/null @@ -1,60 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ScriptRunner.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "core/DataTypes.h" - -namespace walberla { -namespace python_coupling { - - class DictWrapper; - class PythonCallback; - - - class TimeloopIntercept - { - public: - TimeloopIntercept( const std::string & functionName, - uint_t interval = 1, bool enableSignalInterrupt=true ); - - TimeloopIntercept( const std::string & pythonFile, const std::string & functionName, - uint_t interval = 1, bool enableSignalInterrupt=true ); - - inline shared_ptr<PythonCallback> callback() { return callback_; } - - void operator() (); - - protected: - shared_ptr<PythonCallback> callback_; - uint_t timestep_; - uint_t interval_; - bool enableSignalInterrupt_; - }; - - -} // namespace python_coupling -} // namespace walberla - - - - - diff --git a/src/python_coupling/all.h b/src/python_coupling/all.h deleted file mode 100644 index 9c16b51e1..000000000 --- a/src/python_coupling/all.h +++ /dev/null @@ -1,32 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file all.h -//! \ingroup python_coupling -//! \author Christian Godenschwager <christian.godenschwager@fau.de> -//! \brief Collective header file for module python_coupling -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - #include "PythonCallback.h" - #include "CreateConfig.h" - #include "Shell.h" - #include "TimeloopIntercept.h" -#endif diff --git a/src/python_coupling/basic_exports/BasicExports.cpp b/src/python_coupling/basic_exports/BasicExports.cpp deleted file mode 100644 index 2d180f58f..000000000 --- a/src/python_coupling/basic_exports/BasicExports.cpp +++ /dev/null @@ -1,1238 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file BasicExports.cpp -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "BasicExports.h" -#include "MPIExport.h" -#include "python_coupling/helper/ModuleScope.h" -#include "core/waLBerlaBuildInfo.h" -#include "core/logging/Logging.h" -#include "core/Abort.h" -#include "core/cell/CellInterval.h" -#include "core/math/AABB.h" -#include "core/mpi/MPIIO.h" -#include "core/timing/ReduceType.h" -#include "core/timing/TimingPool.h" -#include "core/timing/TimingTree.h" -#include "communication/UniformPackInfo.h" -#include "communication/UniformMPIDatatypeInfo.h" -#include "domain_decomposition/StructuredBlockStorage.h" -#include "python_coupling/Manager.h" -#include "python_coupling/helper/BlockStorageExportHelpers.h" -#include "stencil/Directions.h" - -#include <boost/version.hpp> - -#include <functional> - -using namespace boost::python; - - -namespace walberla { -namespace python_coupling { - - -template <class T> -struct NumpyIntConversion -{ - NumpyIntConversion() - { - converter::registry::push_back( &convertible, &construct, boost::python::type_id<T>() ); - } - - static void* convertible( PyObject* pyObj) - { - auto typeName = std::string( Py_TYPE(pyObj)->tp_name ); - if ( typeName.substr(0,9) == "numpy.int" ) - return pyObj; - return nullptr; - } - - static void construct( PyObject* pyObj, converter::rvalue_from_python_stage1_data* data ) - { - handle<> x(borrowed(pyObj)); - object o(x); - T value = extract<T>(o.attr("__int__")()); - void* storage =( (boost::python::converter::rvalue_from_python_storage<T>*) data)->storage.bytes; - new (storage) T(value); - data->convertible = storage; - } -}; - -template <class T> -struct NumpyFloatConversion -{ - NumpyFloatConversion() - { - converter::registry::push_back( &convertible, &construct, boost::python::type_id<T>() ); - } - - static void* convertible(PyObject* pyObj) - { - auto typeName = std::string( Py_TYPE(pyObj)->tp_name ); - if ( typeName.substr(0,11) == "numpy.float" ) - return pyObj; - return nullptr; - } - - static void construct(PyObject* pyObj, converter::rvalue_from_python_stage1_data* data) - { - handle<> x(borrowed(pyObj)); - object o(x); -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" -#endif - T value = extract<T>(o.attr("__float__")()); -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#pragma GCC diagnostic pop -#endif - void* storage =( (boost::python::converter::rvalue_from_python_storage<T>*) data)->storage.bytes; - new (storage) T(value); - data->convertible = storage; - } -}; - - -#if BOOST_VERSION < 106300 -// taken from https://github.com/boostorg/python/commit/97e4b34a15978ca9d7c296da2de89b78bba4e0d5 -template <class T> -struct exportSharedPtr -{ - exportSharedPtr() - { - converter::registry::insert( &convertible, &construct, boost::python::type_id<std::shared_ptr<T> >() -#ifndef BOOST_PYTHON_NO_PY_SIGNATURES - , &converter::expected_from_python_type_direct<T>::get_pytype -#endif - ); - } - -private: - static void* convertible( PyObject* p ) - { - if ( p == Py_None ) - return p; - - return converter::get_lvalue_from_python( p, converter::registered<T>::converters ); - } - - static void construct( PyObject* source, converter::rvalue_from_python_stage1_data* data ) - { - void* const storage = ( (converter::rvalue_from_python_storage< std::shared_ptr<T> >*) data )->storage.bytes; - // Deal with the "None" case. - if ( data->convertible == source ) - new (storage) std::shared_ptr<T>(); - else - { - std::shared_ptr<void> hold_convertible_ref_count( (void*)0, converter::shared_ptr_deleter( handle<>( borrowed( source ) ) ) ); - // use aliasing constructor - new (storage) std::shared_ptr<T>( hold_convertible_ref_count, static_cast<T*>(data->convertible) ); - } - - data->convertible = storage; - } -}; -#endif - -//====================================================================================================================== -// -// Helper Functions -// -//====================================================================================================================== - -void checkForThreeSequence( const object & o, const char * message ) -{ - // strange construct required because also the len function throws , if object has no len - try { - if ( len(o ) != 3 ) throw error_already_set(); - } - catch( error_already_set & ) { - PyErr_SetString(PyExc_RuntimeError, message); - throw error_already_set(); - } -} - -//====================================================================================================================== -// -// Vector3 -// -//====================================================================================================================== - - -template<typename T> -struct Vector3_to_PythonTuple -{ - static PyObject* convert( Vector3<T> const& v ) - { - auto resultTuple = boost::python::make_tuple(v[0], v[1], v[2] ); - return boost::python::incref ( boost::python::object ( resultTuple ).ptr () ); - } -}; - -template<typename T> -struct PythonTuple_to_Vector3 -{ - PythonTuple_to_Vector3() - { - boost::python::converter::registry::push_back( - &convertible, - &construct, - boost::python::type_id<Vector3<T> >()); - } - - static void* convertible(PyObject* obj) - { - using namespace boost::python; - - if ( ! ( PySequence_Check(obj) && PySequence_Size( obj ) == 3 )) - return nullptr; - - object element0 ( handle<>( borrowed( PySequence_GetItem(obj,0) ))); - object element1 ( handle<>( borrowed( PySequence_GetItem(obj,1) ))); - object element2 ( handle<>( borrowed( PySequence_GetItem(obj,2) ))); - - if ( extract<T>( element0 ).check() && - extract<T>( element1 ).check() && - extract<T>( element2 ).check() ) - return obj; - else - return nullptr; - } - - static void construct( PyObject* obj, boost::python::converter::rvalue_from_python_stage1_data* data ) - { - using namespace boost::python; - - object element0 ( handle<>( borrowed( PySequence_GetItem(obj,0) ))); - object element1 ( handle<>( borrowed( PySequence_GetItem(obj,1) ))); - object element2 ( handle<>( borrowed( PySequence_GetItem(obj,2) ))); - - - // Grab pointer to memory into which to construct the new Vector3 - void* storage = ( (boost::python::converter::rvalue_from_python_storage<Vector3<T> >*) data )->storage.bytes; - - new (storage) Vector3<T> ( extract<T>( element0 ), - extract<T>( element1 ), - extract<T>( element2 ) ); - - // Stash the memory chunk pointer for later use by boost.python - data->convertible = storage; - } -}; - -void exportVector3() -{ - // To Python - boost::python::to_python_converter< Vector3<bool >, Vector3_to_PythonTuple<bool > >(); - - boost::python::to_python_converter< Vector3<real_t >, Vector3_to_PythonTuple<real_t > >(); - - boost::python::to_python_converter< Vector3<uint8_t >, Vector3_to_PythonTuple<uint8_t > >(); - boost::python::to_python_converter< Vector3<uint16_t >, Vector3_to_PythonTuple<uint16_t > >(); - boost::python::to_python_converter< Vector3<uint32_t >, Vector3_to_PythonTuple<uint32_t > >(); - boost::python::to_python_converter< Vector3<uint64_t >, Vector3_to_PythonTuple<uint64_t > >(); - - boost::python::to_python_converter< Vector3<cell_idx_t>, Vector3_to_PythonTuple<cell_idx_t> >(); - - // From Python - PythonTuple_to_Vector3<bool >(); - - PythonTuple_to_Vector3<real_t >(); - - PythonTuple_to_Vector3<uint8_t >(); - PythonTuple_to_Vector3<uint16_t >(); - PythonTuple_to_Vector3<uint32_t >(); - PythonTuple_to_Vector3<uint64_t >(); - - PythonTuple_to_Vector3<cell_idx_t>(); -} - - -//====================================================================================================================== -// -// Cell -// -//====================================================================================================================== - - -struct Cell_to_PythonTuple -{ - static PyObject* convert( Cell const& c ) - { - auto resultTuple = boost::python::make_tuple(c[0], c[1], c[2] ); - return boost::python::incref ( boost::python::object ( resultTuple ).ptr () ); - } -}; - -struct PythonTuple_to_Cell -{ - PythonTuple_to_Cell() - { - boost::python::converter::registry::push_back( - &convertible, - &construct, - boost::python::type_id< Cell >()); - } - - static void* convertible( PyObject* obj ) - { - using namespace boost::python; - - if ( ! ( PySequence_Check(obj) && PySequence_Size( obj ) == 3 )) - return nullptr; - - object element0 ( handle<>( borrowed( PySequence_GetItem(obj,0) ))); - object element1 ( handle<>( borrowed( PySequence_GetItem(obj,1) ))); - object element2 ( handle<>( borrowed( PySequence_GetItem(obj,2) ))); - - if ( extract<cell_idx_t>( element0 ).check() && - extract<cell_idx_t>( element1 ).check() && - extract<cell_idx_t>( element2 ).check() ) - return obj; - else - return nullptr; - } - - static void construct( PyObject* obj, boost::python::converter::rvalue_from_python_stage1_data* data ) - { - using namespace boost::python; - - object element0 ( handle<>( borrowed( PySequence_GetItem(obj,0) ))); - object element1 ( handle<>( borrowed( PySequence_GetItem(obj,1) ))); - object element2 ( handle<>( borrowed( PySequence_GetItem(obj,2) ))); - - - // Grab pointer to memory into which to construct the new Vector3 - void* storage = ( (boost::python::converter::rvalue_from_python_storage<Cell>*) data )->storage.bytes; - - new (storage) Cell( extract<cell_idx_t>( element0 ), - extract<cell_idx_t>( element1 ), - extract<cell_idx_t>( element2 ) ); - - // Stash the memory chunk pointer for later use by boost.python - data->convertible = storage; - } -}; - -void exportCell() -{ - // To Python - boost::python::to_python_converter< Cell, Cell_to_PythonTuple >(); - // From Python - PythonTuple_to_Cell(); -} - -//====================================================================================================================== -// -// CellInterval -// -//====================================================================================================================== - - -void cellInterval_setMin( CellInterval & ci, const Cell & min ) { - ci.min() = min; -} -void cellInterval_setMax( CellInterval & ci, const Cell & max ) { - ci.max() = max; -} -void cellInterval_shift( CellInterval & ci, cell_idx_t xShift, cell_idx_t yShift, cell_idx_t zShift ) { - ci.shift( xShift, yShift, zShift ); -} - -boost::python::tuple cellInterval_size( CellInterval & ci ) { - return boost::python::make_tuple( ci.xSize(), ci.ySize(), ci.zSize() ); -} - -CellInterval cellInterval_getIntersection( CellInterval & ci1, CellInterval & ci2 ) -{ - CellInterval result ( ci1 ); - result.intersect( ci2 ); - return result; -} - -CellInterval cellInterval_getShifted( CellInterval & ci1, cell_idx_t xShift, cell_idx_t yShift, cell_idx_t zShift ) -{ - CellInterval result ( ci1 ); - result.shift( xShift, yShift, zShift ); - return result; -} - -CellInterval cellInterval_getExpanded1( CellInterval & ci1, cell_idx_t expandVal ) -{ - CellInterval result ( ci1 ); - result.expand( expandVal ); - return result; -} - -CellInterval cellInterval_getExpanded2( CellInterval & ci1, cell_idx_t xExpand, cell_idx_t yExpand, cell_idx_t zExpand ) -{ - CellInterval result ( ci1 ); - result.expand( Cell(xExpand, yExpand, zExpand) ); - return result; -} - -void exportCellInterval() -{ - const Cell & ( CellInterval::*p_getMin )( ) const = &CellInterval::min; - const Cell & ( CellInterval::*p_getMax )( ) const = &CellInterval::max; - - bool ( CellInterval::*p_contains1) ( const Cell & ) const = &CellInterval::contains; - bool ( CellInterval::*p_contains2) ( const CellInterval & ) const = &CellInterval::contains; - - void ( CellInterval::*p_expand1) ( const cell_idx_t ) = &CellInterval::expand; - void ( CellInterval::*p_expand2) ( const Cell & ) = &CellInterval::expand; - - bool ( CellInterval::*p_overlaps ) ( const CellInterval & ) const = &CellInterval::overlaps; - - class_<CellInterval>("CellInterval") - .def( init<const Cell&, const Cell&>() ) - .def( init<cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t>() ) - .add_property( "min", make_function( p_getMin, return_value_policy<copy_const_reference>() ), &cellInterval_setMin ) - .add_property( "max", make_function( p_getMax, return_value_policy<copy_const_reference>() ), &cellInterval_setMax ) - .add_property( "size", &cellInterval_size ) - .def( "empty", &CellInterval::empty ) - .def( "positiveIndicesOnly", &CellInterval::positiveIndicesOnly ) - .def( "contains", p_contains1 ) - .def( "contains", p_contains2 ) - .def( "overlaps", p_overlaps ) - .def( "shift", &cellInterval_shift ) - .def( "getShifted", &cellInterval_getShifted ) - .def( "expand", p_expand1 ) - .def( "expand", p_expand2 ) - .def( "getExpanded", &cellInterval_getExpanded1 ) - .def( "getExpanded", &cellInterval_getExpanded2 ) - .def( "intersect", &CellInterval::intersect ) - .def( "getIntersection", &cellInterval_getIntersection ) - .def("__eq__", &CellInterval::operator==) - .def("__ne__", &CellInterval::operator!=) - .add_property( "numCells", &CellInterval::numCells ) - .def( self_ns::str(self) ) - ; -} - -//====================================================================================================================== -// -// AABB -// -//====================================================================================================================== - - -tuple aabb_getMin( const AABB & domainBB ) { - return boost::python::make_tuple( domainBB.xMin(), domainBB.yMin(), domainBB.zMin() ); -} -tuple aabb_getMax( const AABB & domainBB ) { - return boost::python::make_tuple( domainBB.xMax(), domainBB.yMax(), domainBB.zMax() ); -} - -void aabb_setMin( AABB & domainBB, object min ) -{ - checkForThreeSequence(min, "Error assigning minimum of AABB - Sequence of length 3 required" ); - real_t min0 = extract<real_t>( min[0] ); - real_t min1 = extract<real_t>( min[1] ); - real_t min2 = extract<real_t>( min[2] ); - - domainBB = AABB( domainBB.max(), AABB::vector_type ( min0, min1, min2 ) ); -} - -void aabb_setMax( AABB & domainBB, object max ) -{ - checkForThreeSequence( max, "Error assigning maximum of AABB - Sequence of length 3 required" ); - - real_t max0 = extract<real_t>( max[0] ); - real_t max1 = extract<real_t>( max[1] ); - real_t max2 = extract<real_t>( max[2] ); - - domainBB = AABB( domainBB.min(), AABB::vector_type ( max0, max1, max2 ) ); -} - - -void exportAABB() -{ - bool ( AABB::*p_containsBB )( const AABB & bb ) const = &AABB::contains; - bool ( AABB::*p_containsVec )( const Vector3<real_t> & point ) const = &AABB::contains; - - - bool ( AABB::*p_containsClosedInterval1 ) ( const Vector3<real_t> & ) const = &AABB::containsClosedInterval; - bool ( AABB::*p_containsClosedInterval2 ) ( const Vector3<real_t> &, const real_t ) const = &AABB::containsClosedInterval; - - AABB ( AABB::*p_getExtended1 ) ( const real_t ) const = &AABB::getExtended; - AABB ( AABB::*p_getExtended2 ) ( const Vector3<real_t> & ) const = &AABB::getExtended; - - AABB ( AABB::*p_getScaled1 ) ( const real_t ) const = &AABB::getScaled; - AABB ( AABB::*p_getScaled2 ) ( const Vector3<real_t> & ) const = &AABB::getScaled; - - AABB ( AABB::*p_getMerged1 ) ( const Vector3<real_t> & ) const = &AABB::getMerged; - AABB ( AABB::*p_getMerged2 ) ( const AABB & ) const = &AABB::getMerged; - - bool ( AABB::*p_intersects1 )( const AABB & bb ) const = &AABB::intersects; - bool ( AABB::*p_intersects2 )( const AABB & bb, real_t dx ) const = &AABB::intersects; - - bool ( AABB::*p_intersectsClosed1 )( const AABB & bb ) const = &AABB::intersectsClosedInterval; - bool ( AABB::*p_intersectsClosed2 )( const AABB & bb, real_t dx ) const = &AABB::intersectsClosedInterval; - - void ( AABB::*p_extend1 ) ( const real_t ) = &AABB::extend; - void ( AABB::*p_extend2 ) ( const Vector3<real_t> & ) = &AABB::extend; - - void ( AABB::*p_scale1 ) ( const real_t ) = &AABB::scale; - void ( AABB::*p_scale2 ) ( const Vector3<real_t> & ) = &AABB::scale; - - void ( AABB::*p_merge1 ) ( const Vector3<real_t> & ) = &AABB::merge; - void ( AABB::*p_merge2 ) ( const AABB & ) = &AABB::merge; - - real_t ( AABB::*p_sqDistance1 ) ( const AABB & ) const = &AABB::sqDistance; - real_t ( AABB::*p_sqDistance2 ) ( const Vector3<real_t> & ) const = &AABB::sqDistance; - - real_t ( AABB::*p_sqMaxDistance1 ) ( const AABB & ) const = &AABB::sqMaxDistance; - real_t ( AABB::*p_sqMaxDistance2 ) ( const Vector3<real_t> & ) const = &AABB::sqMaxDistance; - - - class_<AABB>("AABB") - .def( init<real_t,real_t,real_t,real_t,real_t,real_t>() ) - .def( init<Vector3<real_t>,Vector3<real_t> >() ) - .def("__eq__", &walberla::math::operator==<real_t, real_t > ) - .def("__ne__", &walberla::math::operator!=<real_t, real_t > ) - .add_property( "min", &aabb_getMin, &aabb_setMin ) - .add_property( "max", &aabb_getMax, &aabb_setMax ) - .add_property( "size", &AABB::sizes ) - .def( "empty", &AABB::empty ) - .def( "volume", &AABB::volume ) - .def( "center", &AABB::center ) - .def( "contains", p_containsBB ) - .def( "contains", p_containsVec ) - .def( "containsClosedInterval", p_containsClosedInterval1 ) - .def( "containsClosedInterval", p_containsClosedInterval2 ) - .def( "getExtended", p_getExtended1 ) - .def( "getExtended", p_getExtended2 ) - .def( "getTranslated", &AABB::getTranslated ) - .def( "getScaled", p_getScaled1 ) - .def( "getScaled", p_getScaled2 ) - .def( "getMerged", p_getMerged1 ) - .def( "getMerged", p_getMerged2 ) - .def( "intersects", p_intersects1 ) - .def( "intersects", p_intersects2 ) - .def( "intersectsClosedInterval", p_intersectsClosed1 ) - .def( "intersectsClosedInterval", p_intersectsClosed2 ) - .def( "intersectionVolume", &AABB::intersectionVolume ) - .def( "getIntersection", &AABB::getIntersection ) - .def( "isIdentical", &AABB::isIdentical ) - .def( "isEqual", &AABB::isEqual ) - .def( "sqDistance", p_sqDistance1 ) - .def( "sqDistance", p_sqDistance2 ) - .def( "sqMaxDistance", p_sqMaxDistance1 ) - .def( "sqMaxDistance", p_sqMaxDistance2 ) - .def( "sqSignedDistance", &AABB::sqSignedDistance) - .def( "distance" , &AABB::distance) - .def( "signedDistance" , &AABB::signedDistance) - .def( "maxDistance" , &AABB::maxDistance) - .def( "extend", p_extend1 ) - .def( "extend", p_extend2 ) - .def( "translate", &AABB::translate ) - .def( "scale", p_scale1 ) - .def( "scale", p_scale2 ) - .def( "merge", p_merge1 ) - .def( "merge", p_merge2 ) - .def( "intersect", &AABB::intersect ) - .def( self_ns::str(self) ) - ; -} - -//====================================================================================================================== -// -// Timing -// -//====================================================================================================================== - -dict buildDictFromTimingNode(const WcTimingNode & tn) -{ - dict result; - - result["all"] = tn.timer_; - for ( auto it = tn.tree_.begin(); it != tn.tree_.end(); ++it) - { - if (it->second.tree_.empty()) - { - result[it->first] = it->second.timer_; - } else - { - result[it->first] = buildDictFromTimingNode(it->second); - } - } - - return result; -} - -dict buildDictFromTimingTree(const WcTimingTree & tt) -{ - return buildDictFromTimingNode( tt.getRawData() ); -} - -void timingTreeStopWrapper(WcTimingTree & tt, const std::string& name) -{ - if (!tt.isTimerRunning(name)) - { - PyErr_SetString( PyExc_ValueError, ("Timer '" + name + "' is currently not running!").c_str() ); - throw error_already_set(); - } - tt.stop(name); -} - -void exportTiming() -{ - class_<WcTimer> ("Timer") - .def( init<>() ) - .def( "start", &WcTimer::start ) - .def( "stop", &WcTimer::end ) - .def( "reset", &WcTimer::reset ) - .def( "merge", &WcTimer::merge ) - .add_property( "counter", &WcTimer::getCounter ) - .add_property( "total", &WcTimer::total ) - .add_property( "sumOfSquares", &WcTimer::sumOfSquares ) - .add_property( "average", &WcTimer::average ) - .add_property( "variance", &WcTimer::variance ) - .add_property( "min", &WcTimer::min ) - .add_property( "max", &WcTimer::max ) - .add_property( "last", &WcTimer::last ) - ; - - - WcTimer & ( WcTimingPool::*pGetItem ) ( const std::string & ) = &WcTimingPool::operator[]; - - { - scope classScope = - class_<WcTimingPool, shared_ptr<WcTimingPool> > ("TimingPool") - .def( init<>() ) - .def( self_ns::str(self) ) - .def( "__getitem__", pGetItem, return_internal_reference<1>() ) - .def( "__contains__", &WcTimingPool::timerExists ) - .def( "getReduced", &WcTimingPool::getReduced, ( arg("targetRank") = 0) ) - .def( "merge", &WcTimingPool::merge, ( arg("mergeDuplicates") = true) ) - .def( "clear", &WcTimingPool::clear ) - .def( "unifyRegisteredTimersAcrossProcesses", &WcTimingPool::unifyRegisteredTimersAcrossProcesses ) - .def( "logResultOnRoot", &WcTimingPool::logResultOnRoot, (arg("unifyRegisteredTimers") = false) ) - .def( self_ns::str(self) ) - ; - - enum_<timing::ReduceType>("ReduceType") - .value("min" , timing::REDUCE_MIN) - .value("avg" , timing::REDUCE_AVG) - .value("max" , timing::REDUCE_MAX) - .value("total", timing::REDUCE_TOTAL) - .export_values() - ; - } - - const WcTimer & ( WcTimingTree::*pTimingTreeGet ) ( const std::string & ) const = &WcTimingTree::operator[]; - class_<WcTimingTree, shared_ptr<WcTimingTree> > ("TimingTree") - .def( init<>() ) - .def( "__getitem__", pTimingTreeGet, return_internal_reference<1>() ) - .def( "start", &WcTimingTree::start ) - .def( "stop", &timingTreeStopWrapper ) - .def( "getReduced", &WcTimingTree::getReduced ) - .def( "toDict", &buildDictFromTimingTree ) - .def( self_ns::str(self) ) - ; - -#if BOOST_VERSION < 106300 - exportSharedPtr<WcTimingTree>(); -#endif - -} - - - - -//====================================================================================================================== -// -// IBlock -// -//====================================================================================================================== - -boost::python::object IBlock_getData( boost::python::object iblockObject, const std::string & stringID ) //NOLINT -{ - IBlock * block = boost::python::extract<IBlock*>( iblockObject ); - - //typedef std::pair< IBlock *, std::string > BlockStringPair; - //static std::map< BlockStringPair, object > cache; - - //auto blockStringPair = std::make_pair( &block, stringID ); - //auto it = cache.find( blockStringPair ); - //if ( it != cache.end() ) - // return it->second; - - BlockDataID id = blockDataIDFromString( *block, stringID ); - - auto manager = python_coupling::Manager::instance(); - boost::python::object res = manager->pythonObjectFromBlockData( *block, id ); - - if ( res == boost::python::object() ) - throw BlockDataNotConvertible(); - - boost::python::objects::make_nurse_and_patient( res.ptr(), iblockObject.ptr() ); - - // write result to cache - //cache[blockStringPair] = res; - //TODO cache has bugs when cache is destroyed, probably since objects are freed after py_finalize is called - //move cache to Manager? - - return res; -} - - -boost::python::list IBlock_blockDataList( boost::python::object iblockObject ) //NOLINT -{ - IBlock * block = boost::python::extract<IBlock*>( iblockObject ); - - const std::vector<std::string> & stringIds = block->getBlockStorage().getBlockDataIdentifiers(); - - boost::python::list resultList; - - for( auto it = stringIds.begin(); it != stringIds.end(); ++it ) { - try { - resultList.append( boost::python::make_tuple( *it, IBlock_getData( iblockObject, *it) ) ); - } - catch( BlockDataNotConvertible & /*e*/ ) { - } - } - - return resultList; -} - -boost::python::object IBlock_iter( boost::python::object iblockObject ) -{ - boost::python::list resultList = IBlock_blockDataList( iblockObject ); //NOLINT - return resultList.attr("__iter__"); -} - -boost::python::tuple IBlock_atDomainMinBorder( IBlock & block ) -{ - return boost::python::make_tuple( block.getBlockStorage().atDomainXMinBorder(block), - block.getBlockStorage().atDomainYMinBorder(block), - block.getBlockStorage().atDomainZMinBorder(block) ); -} - -boost::python::tuple IBlock_atDomainMaxBorder( IBlock & block ) -{ - return boost::python::make_tuple( block.getBlockStorage().atDomainXMaxBorder(block), - block.getBlockStorage().atDomainYMaxBorder(block), - block.getBlockStorage().atDomainZMaxBorder(block) ); -} - -IBlockID::IDType IBlock_getIntegerID( IBlock & block ) -{ - return block.getId().getID(); -} - -bool IBlock_equals( IBlock & block1, IBlock & block2 ) -{ - return block1.getId() == block2.getId(); -} - -std::string IBlock_str( IBlock & b ) { - std::stringstream out; - out << "Block at " << b.getAABB(); - return out.str(); - -} - -void exportIBlock() -{ - register_exception_translator<NoSuchBlockData>( & NoSuchBlockData::translate ); - register_exception_translator<BlockDataNotConvertible>( & BlockDataNotConvertible::translate ); - - class_<IBlock, boost::noncopyable> ("Block", no_init) - .def ( "__getitem__", &IBlock_getData ) - .add_property( "atDomainMinBorder", &IBlock_atDomainMinBorder ) - .add_property( "atDomainMaxBorder", &IBlock_atDomainMaxBorder ) - .add_property( "items", &IBlock_blockDataList) - .add_property( "id", &IBlock_getIntegerID) - .def ( "__hash__", &IBlock_getIntegerID) - .def ( "__eq__", &IBlock_equals) - .def ( "__repr__", &IBlock_str ) - .add_property( "__iter__", &IBlock_iter ) - .add_property("aabb", make_function(&IBlock::getAABB, return_value_policy<copy_const_reference>())) - ; - -} - -//====================================================================================================================== -// -// Logging & Abort -// -//====================================================================================================================== - - -static void wlb_log_devel ( const std::string & msg ) { WALBERLA_LOG_DEVEL ( msg ); } -static void wlb_log_devel_on_root ( const std::string & msg ) { WALBERLA_LOG_DEVEL_ON_ROOT ( msg ); } - -static void wlb_log_result ( const std::string & msg ) { WALBERLA_LOG_RESULT ( msg ); } -static void wlb_log_result_on_root ( const std::string & msg ) { WALBERLA_LOG_RESULT_ON_ROOT ( msg ); } - -static void wlb_log_warning ( const std::string & msg ) { WALBERLA_LOG_WARNING ( msg ); } -static void wlb_log_warning_on_root ( const std::string & msg ) { WALBERLA_LOG_WARNING_ON_ROOT ( msg ); } - -#ifdef WALBERLA_LOGLEVEL_INFO -static void wlb_log_info ( const std::string & msg ) { WALBERLA_LOG_INFO ( msg ); } -static void wlb_log_info_on_root ( const std::string & msg ) { WALBERLA_LOG_INFO_ON_ROOT ( msg ); } -#else -static void wlb_log_info ( const std::string & ) {} -static void wlb_log_info_on_root ( const std::string & ) {} -#endif - -#ifdef WALBERLA_LOGLEVEL_PROGRESS -static void wlb_log_progress ( const std::string & msg ) { WALBERLA_LOG_PROGRESS ( msg ); } -static void wlb_log_progress_on_root ( const std::string & msg ) { WALBERLA_LOG_PROGRESS_ON_ROOT( msg ); } -#else -static void wlb_log_progress ( const std::string & ) {} -static void wlb_log_progress_on_root ( const std::string & ) {} -#endif - -#ifdef WALBERLA_LOGLEVEL_DETAIL -static void wlb_log_detail ( const std::string & msg ) { WALBERLA_LOG_DETAIL ( msg ); } -static void wlb_log_detail_on_root ( const std::string & msg ) { WALBERLA_LOG_DETAIL_ON_ROOT ( msg ); } -#else -static void wlb_log_detail ( const std::string & ) {} -static void wlb_log_detail_on_root ( const std::string & ) {} -#endif - -static void wlb_abort ( const std::string & msg ) { WALBERLA_ABORT_NO_DEBUG_INFO ( msg ); } - -void exportLogging() -{ - def ( "log_devel" , wlb_log_devel ); - def ( "log_devel_on_root" , wlb_log_devel_on_root ); - def ( "log_result", wlb_log_result ); - def ( "log_result_on_root", wlb_log_result_on_root ); - def ( "log_warning", wlb_log_warning ); - def ( "log_warning_on_root", wlb_log_warning_on_root ); - def ( "log_info", wlb_log_info ); - def ( "log_info_on_root", wlb_log_info_on_root ); - def ( "log_progress", wlb_log_progress ); - def ( "log_progress_on_root",wlb_log_progress_on_root); - def ( "log_detail", wlb_log_detail ); - def ( "log_detail_on_root", wlb_log_detail_on_root ); - - def ( "abort", wlb_abort ); -} - - - - -//====================================================================================================================== -// -// StructuredBlockStorage -// -//====================================================================================================================== - - -object * blockDataCreationHelper( IBlock * block, StructuredBlockStorage * bs, object callable ) //NOLINT -{ - object * res = new object( callable( ptr(block), ptr(bs) ) ); - return res; -} - -uint_t StructuredBlockStorage_addBlockData( StructuredBlockStorage & s, const std::string & name, object functionPtr ) //NOLINT -{ - BlockDataID res = s.addStructuredBlockData(name) - << StructuredBlockDataCreator<object>( std::bind( &blockDataCreationHelper, std::placeholders::_1, std::placeholders::_2, functionPtr ) ); - //TODO extend this for moving block data ( packing und unpacking with pickle ) - return res; -} - -// Helper function for iteration over StructuredBlockStorage -// boost::python comes with iteration helpers but non of this worked: -// .def("__iter__" range(&StructuredBlockStorage::begin, &StructuredBlockStorage::end)) -// .def("__iter__", range<return_value_policy<copy_non_const_reference> >( beginPtr, endPtr) ) -boost::python::object StructuredBlockStorage_iter( boost::python::object structuredBlockStorage ) //NOLINT -{ - shared_ptr<StructuredBlockStorage> s = extract< shared_ptr<StructuredBlockStorage> > ( structuredBlockStorage ); - - std::vector< const IBlock* > blocks; - s->getBlocks( blocks ); - boost::python::list resultList; - - for( auto it = blocks.begin(); it != blocks.end(); ++it ) { - boost::python::object theObject( ptr( *it ) ); - // Prevent blockstorage from being destroyed when references to blocks exist - boost::python::objects::make_nurse_and_patient( theObject.ptr(), structuredBlockStorage.ptr() ); - resultList.append( theObject ); - } - - return resultList.attr("__iter__"); -} - - -boost::python::object StructuredBlockStorage_getItem( boost::python::object structuredBlockStorage, uint_t i ) //NOLINT -{ - shared_ptr<StructuredBlockStorage> s = extract< shared_ptr<StructuredBlockStorage> > ( structuredBlockStorage ); - - if ( i >= s->size() ) - { - PyErr_SetString( PyExc_RuntimeError, "Index out of bounds"); - throw error_already_set(); - } - - std::vector< const IBlock* > blocks; - s->getBlocks( blocks ); - - boost::python::object theObject( ptr( blocks[i] ) ); - boost::python::objects::make_nurse_and_patient( theObject.ptr(), structuredBlockStorage.ptr() ); - return theObject; -} - -boost::python::list StructuredBlockStorage_blocksOverlappedByAABB( StructuredBlockStorage & s, const AABB & aabb ) { - std::vector< IBlock*> blocks; - s.getBlocksOverlappedByAABB( blocks, aabb ); - - boost::python::list resultList; - for( auto it = blocks.begin(); it != blocks.end(); ++it ) - resultList.append( ptr( *it ) ); - return resultList; -} - - -boost::python::list StructuredBlockStorage_blocksContainedWithinAABB( StructuredBlockStorage & s, const AABB & aabb ) { - std::vector< IBlock*> blocks; - s.getBlocksContainedWithinAABB( blocks, aabb ); - - boost::python::list resultList; - for( auto it = blocks.begin(); it != blocks.end(); ++it ) - resultList.append( ptr( *it ) ); - return resultList; -} - - -object SbS_transformGlobalToLocal ( StructuredBlockStorage & s, IBlock & block, const object & global ) -{ - if ( extract<CellInterval>( global ).check() ) - { - CellInterval ret; - s.transformGlobalToBlockLocalCellInterval( ret, block, extract<CellInterval>( global ) ); - return object( ret ); - } - else if ( extract<Cell>( global ).check() ) - { - Cell ret; - s.transformGlobalToBlockLocalCell( ret, block, extract<Cell>( global ) ); - return object( ret ); - } - - PyErr_SetString(PyExc_RuntimeError, "Only CellIntervals and cells can be transformed" ); - throw error_already_set(); -} - - -object SbS_transformLocalToGlobal ( StructuredBlockStorage & s, IBlock & block, const object & local ) -{ - if ( extract<CellInterval>( local ).check() ) - { - CellInterval ret; - s.transformBlockLocalToGlobalCellInterval( ret, block, extract<CellInterval>( local ) ); - return object( ret ); - } - else if ( extract<Cell>( local ).check() ) - { - Cell ret; - s.transformBlockLocalToGlobalCell( ret, block, extract<Cell>( local ) ); - return object( ret ); - } - PyErr_SetString(PyExc_RuntimeError, "Only CellIntervals and cells can be transformed" ); - throw error_already_set(); -} - -void SbS_writeBlockData( StructuredBlockStorage & s,const std::string & blockDataId, const std::string & file ) -{ - mpi::SendBuffer buffer; - s.serializeBlockData( blockDataIDFromString(s, blockDataId), buffer); - mpi::writeMPIIO(file, buffer); -} - -void SbS_readBlockData( StructuredBlockStorage & s,const std::string & blockDataId, const std::string & file ) -{ - mpi::RecvBuffer buffer; - mpi::readMPIIO(file, buffer); - - s.deserializeBlockData( blockDataIDFromString(s, blockDataId), buffer ); - if ( ! buffer.isEmpty() ) { - PyErr_SetString(PyExc_RuntimeError, "Reading failed - file does not contain matching data for this type." ); - throw error_already_set(); - } -} - -CellInterval SbS_getBlockCellBB( StructuredBlockStorage & s, const IBlock * block ) -{ - return s.getBlockCellBB( *block ); -} - - -Vector3<real_t> SbS_mapToPeriodicDomain1 ( StructuredBlockStorage & s, real_t x, real_t y, real_t z ) -{ - Vector3<real_t> res ( x,y,z ); - s.mapToPeriodicDomain( res ); - return res; -} -Vector3<real_t> SbS_mapToPeriodicDomain2 ( StructuredBlockStorage & s, Vector3<real_t> in ) -{ - s.mapToPeriodicDomain( in ); - return in; -} -Cell SbS_mapToPeriodicDomain3 ( StructuredBlockStorage & s, Cell in, uint_t level = 0 ) -{ - s.mapToPeriodicDomain( in, level ); - return in; -} - -object SbS_getBlock1 ( StructuredBlockStorage & s, const real_t x , const real_t y , const real_t z ) { - return object( ptr( s.getBlock( x,y,z ) ) ); - -} - -object SbS_getBlock2 ( StructuredBlockStorage & s, const Vector3<real_t> & v ) { - return object( ptr( s.getBlock( v ) ) ); -} - - -tuple SbS_periodic( StructuredBlockStorage & s ) -{ - return make_tuple( s.isXPeriodic(), s.isYPeriodic(), s.isZPeriodic() ); -} - -bool SbS_atDomainXMinBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainXMinBorder( *b ); } -bool SbS_atDomainXMaxBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainXMaxBorder( *b ); } -bool SbS_atDomainYMinBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainYMinBorder( *b ); } -bool SbS_atDomainYMaxBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainYMaxBorder( *b ); } -bool SbS_atDomainZMinBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainZMinBorder( *b ); } -bool SbS_atDomainZMaxBorder( StructuredBlockStorage & s, const IBlock * b ) { return s.atDomainZMaxBorder( *b ); } - -void exportStructuredBlockStorage() -{ - bool ( StructuredBlockStorage::*p_blockExists1 ) ( const Vector3< real_t > & ) const = &StructuredBlockStorage::blockExists; - bool ( StructuredBlockStorage::*p_blockExistsLocally1 ) ( const Vector3< real_t > & ) const = &StructuredBlockStorage::blockExistsLocally; - bool ( StructuredBlockStorage::*p_blockExistsRemotely1 ) ( const Vector3< real_t > & ) const = &StructuredBlockStorage::blockExistsRemotely; - - bool ( StructuredBlockStorage::*p_blockExists2 ) ( const real_t, const real_t, const real_t ) const = &StructuredBlockStorage::blockExists; - bool ( StructuredBlockStorage::*p_blockExistsLocally2 ) ( const real_t, const real_t, const real_t ) const = &StructuredBlockStorage::blockExistsLocally; - bool ( StructuredBlockStorage::*p_blockExistsRemotely2 ) ( const real_t, const real_t, const real_t ) const = &StructuredBlockStorage::blockExistsRemotely; - - class_<StructuredBlockStorage, shared_ptr<StructuredBlockStorage>, boost::noncopyable>("StructuredBlockStorage", no_init ) - .def( "getNumberOfLevels", &StructuredBlockStorage::getNumberOfLevels ) - .def( "getDomain", &StructuredBlockStorage::getDomain, return_internal_reference<1>() ) - .def( "mapToPeriodicDomain", &SbS_mapToPeriodicDomain1 ) - .def( "mapToPeriodicDomain", &SbS_mapToPeriodicDomain2 ) - .def( "mapToPeriodicDomain", &SbS_mapToPeriodicDomain3, (arg("level") = 0 ) ) - .def( "addBlockData", &StructuredBlockStorage_addBlockData ) - .def( "__getitem__", &StructuredBlockStorage_getItem ) - .def( "__len__", &StructuredBlockStorage::size ) - .def( "getBlock", SbS_getBlock1 ) - .def( "getBlock", SbS_getBlock2 ) - .def( "containsGlobalBlockInformation", &StructuredBlockStorage::containsGlobalBlockInformation ) - .def( "blocksOverlappedByAABB" , &StructuredBlockStorage_blocksOverlappedByAABB ) - .def( "blocksContainedWithinAABB", &StructuredBlockStorage_blocksContainedWithinAABB ) - .def( "blockExists", p_blockExists1 ) - .def( "blockExists", p_blockExists2 ) - .def( "blockExistsLocally", p_blockExistsLocally1 ) - .def( "blockExistsLocally", p_blockExistsLocally2 ) - .def( "blockExistsRemotely", p_blockExistsRemotely1 ) - .def( "blockExistsRemotely", p_blockExistsRemotely2 ) - .def( "atDomainXMinBorder", &SbS_atDomainXMinBorder ) - .def( "atDomainXMaxBorder", &SbS_atDomainXMaxBorder ) - .def( "atDomainYMinBorder", &SbS_atDomainYMinBorder ) - .def( "atDomainYMaxBorder", &SbS_atDomainYMaxBorder ) - .def( "atDomainZMinBorder", &SbS_atDomainZMinBorder ) - .def( "atDomainZMaxBorder", &SbS_atDomainZMaxBorder ) - .def( "dx", &StructuredBlockStorage::dx, ( args("level")=0 ) ) - .def( "dy", &StructuredBlockStorage::dy, ( args("level")=0 ) ) - .def( "dz", &StructuredBlockStorage::dz, ( args("level")=0 ) ) - .def( "getDomainCellBB", &StructuredBlockStorage::getDomainCellBB, return_value_policy<copy_const_reference>(), ( args( "level") = 0 ) ) - .def( "getBlockCellBB", &SbS_getBlockCellBB ) - .def( "transformGlobalToLocal", &SbS_transformGlobalToLocal ) - .def( "transformLocalToGlobal", &SbS_transformLocalToGlobal ) - .def( "writeBlockData", &SbS_writeBlockData ) - .def( "readBlockData", &SbS_readBlockData ) - .add_property("__iter__", &StructuredBlockStorage_iter ) - .add_property( "containsGlobalBlockInformation", &StructuredBlockStorage::containsGlobalBlockInformation ) - .add_property( "periodic", &SbS_periodic ) - ; - -#if BOOST_VERSION < 106300 - exportSharedPtr<StructuredBlockStorage>(); -#endif -} - -//====================================================================================================================== -// -// Communication -// -//====================================================================================================================== - -void exportCommunication() -{ - using communication::UniformPackInfo; - class_< UniformPackInfo, shared_ptr<UniformPackInfo>, boost::noncopyable> //NOLINT - ( "UniformPackInfo", no_init ); - - using communication::UniformMPIDatatypeInfo; - class_< UniformMPIDatatypeInfo, shared_ptr<UniformMPIDatatypeInfo>, boost::noncopyable> - ( "UniformMPIDatatypeInfo", no_init ); - -#if BOOST_VERSION < 106300 - exportSharedPtr<UniformPackInfo>(); - exportSharedPtr<UniformMPIDatatypeInfo>(); -#endif -} - -//====================================================================================================================== -// -// Stencil Directions -// -//====================================================================================================================== - -void exportStencilDirections() -{ - ModuleScope build_info( "stencil"); - - enum_<stencil::Direction>("Direction") - .value("C" , stencil::C ) - .value("N" , stencil::N ) - .value("S" , stencil::S ) - .value("W" , stencil::W ) - .value("E" , stencil::E ) - .value("T" , stencil::T ) - .value("B" , stencil::B ) - .value("NW" , stencil::NW ) - .value("NE" , stencil::NE ) - .value("SW" , stencil::SW ) - .value("SE" , stencil::SE ) - .value("TN" , stencil::TN ) - .value("TS" , stencil::TS ) - .value("TW" , stencil::TW ) - .value("TE" , stencil::TE ) - .value("BN" , stencil::BN ) - .value("BS" , stencil::BS ) - .value("BW" , stencil::BW ) - .value("BE" , stencil::BE ) - .value("TNE", stencil::TNE) - .value("TNW", stencil::TNW) - .value("TSE", stencil::TSE) - .value("TSW", stencil::TSW) - .value("BNE", stencil::BNE) - .value("BNW", stencil::BNW) - .value("BSE", stencil::BSE) - .value("BSW", stencil::BSW) - .export_values() - ; - boost::python::list cx; - - boost::python::list cy; - - boost::python::list cz; - - boost::python::list dirStrings; - for( uint_t i=0; i < stencil::NR_OF_DIRECTIONS; ++i ) - { - cx.append( stencil::cx[i] ); - cy.append( stencil::cy[i] ); - cz.append( stencil::cz[i] ); - dirStrings.append( stencil::dirToString[i] ); - } - boost::python::list c; - c.append( cx ); - c.append( cy ); - c.append( cz ); - - using boost::python::scope; - scope().attr("cx") = cx; - scope().attr("cy") = cy; - scope().attr("cz") = cz; - scope().attr("c") = c; - scope().attr("dirStrings") = dirStrings; -} - - -//====================================================================================================================== -// -// Build Info -// -//====================================================================================================================== - - -void exportBuildInfo() -{ - ModuleScope build_info( "build_info"); - using boost::python::scope; - scope().attr("version") = WALBERLA_GIT_SHA1; - scope().attr("type" ) = WALBERLA_BUILD_TYPE; - scope().attr("compiler_flags" ) = WALBERLA_COMPILER_FLAGS; - scope().attr("build_machine" ) = WALBERLA_BUILD_MACHINE; - scope().attr("source_dir") = WALBERLA_SOURCE_DIR; - scope().attr("build_dir") = WALBERLA_BUILD_DIR; -} - - - - -void exportBasicWalberlaDatastructures() -{ - - NumpyIntConversion<uint8_t>(); - NumpyIntConversion<int32_t>(); - NumpyIntConversion<int64_t>(); - NumpyIntConversion<uint32_t>(); - NumpyIntConversion<uint64_t>(); - NumpyIntConversion<size_t>(); - NumpyIntConversion<bool>(); - NumpyFloatConversion<float>(); - NumpyFloatConversion<double>(); - NumpyFloatConversion<long double>(); - - - exportMPI(); - - exportBuildInfo(); - exportVector3(); - exportCell(); - exportCellInterval(); - exportAABB(); - - exportTiming(); - - exportIBlock(); - exportStructuredBlockStorage(); - exportCommunication(); - - exportLogging(); - exportStencilDirections(); - - // Add empty callbacks module - object callbackModule( handle<>( borrowed(PyImport_AddModule("walberla_cpp.callbacks")))); - scope().attr("callbacks") = callbackModule; - -} - -} // namespace python_coupling -} // namespace walberla - -#endif - diff --git a/src/python_coupling/basic_exports/MPIExport.cpp b/src/python_coupling/basic_exports/MPIExport.cpp deleted file mode 100644 index 5811cbab5..000000000 --- a/src/python_coupling/basic_exports/MPIExport.cpp +++ /dev/null @@ -1,266 +0,0 @@ -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "python_coupling/helper/PythonIterableToStdVector.h" - -#include "core/mpi/MPIManager.h" -#include "core/mpi/Reduce.h" -#include "core/mpi/Gather.h" -#include "core/mpi/Broadcast.h" - -#include <vector> - -using namespace boost::python; - - - - -namespace walberla { -namespace python_coupling { - - typedef std::vector<int64_t> IntStdVector; - typedef std::vector<real_t> RealStdVector; - typedef std::vector<std::string> StringStdVector; - - - //=================================================================================================================== - // - // MPIManager - // - //=================================================================================================================== - - - static int rank() { return MPIManager::instance()->rank(); } - static int worldRank() { return MPIManager::instance()->worldRank(); } - static int numProcesses() { return MPIManager::instance()->numProcesses(); } - static bool hasCartesianSetup() { return MPIManager::instance()->hasCartesianSetup(); } - static bool rankValid() { return MPIManager::instance()->rankValid(); } - - - - //=================================================================================================================== - // - // Broadcast - // - //=================================================================================================================== - - static object broadcast_string( object value, int sendRank ) //NOLINT - { - if ( extract<std::string>(value).check() ) - { - std::string extractedValue = extract< std::string >(value); - mpi::broadcastObject( extractedValue , sendRank ); - return object( extractedValue ); - } - StringStdVector extractedValue = pythonIterableToStdVector< StringStdVector::value_type >( value ); - mpi::broadcastObject( extractedValue, sendRank ); - return object( extractedValue ); - } - - static object broadcast_int( object value, int sendRank ) //NOLINT - { - if ( extract<int64_t>(value).check() ) - { - int64_t extractedValue = extract< int64_t >(value); - mpi::broadcastObject( extractedValue , sendRank ); - return object( extractedValue ); - } - IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); - mpi::broadcastObject( extractedValue, sendRank ); - return object( extractedValue ); - } - - static object broadcast_real( object value, int sendRank ) //NOLINT - { - if ( extract<real_t>(value).check() ) - { - real_t extractedValue = extract< real_t >(value); - mpi::broadcastObject( extractedValue , sendRank); - return object( extractedValue ); - } - RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); - mpi::broadcastObject( extractedValue , sendRank); - return object( extractedValue ); - } - - - //=================================================================================================================== - // - // Reduce - // - //=================================================================================================================== - - - static object reduce_int( object value, mpi::Operation op, int recvRank ) //NOLINT - { - if ( extract<int64_t>(value).check() ) - { - int64_t extractedValue = extract< int64_t >(value); - mpi::reduceInplace( extractedValue , op, recvRank ); - return object( extractedValue ); - } - IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); - mpi::reduceInplace( extractedValue, op, recvRank ); - return object( extractedValue ); - } - - static object reduce_real( object value, mpi::Operation op, int recvRank ) //NOLINT - { - if ( extract<real_t>(value).check() ) - { - real_t extractedValue = extract< real_t >(value); - mpi::reduceInplace( extractedValue , op, recvRank); - return object( extractedValue ); - } - RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); - mpi::reduceInplace( extractedValue , op, recvRank); - return object( extractedValue ); - } - - - static object allreduce_int( object value, mpi::Operation op ) //NOLINT - { - if ( extract<int64_t>(value).check() ) - { - int64_t extractedValue = extract< int64_t >(value); - mpi::allReduceInplace( extractedValue , op ); - return object( extractedValue ); - } - IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); - mpi::allReduceInplace( extractedValue, op ); - return object( extractedValue ); - } - - static object allreduce_real( object value, mpi::Operation op ) //NOLINT - { - if ( extract<real_t>(value).check() ) - { - real_t extractedValue = extract< real_t >(value); - mpi::allReduceInplace( extractedValue , op ); - return object( extractedValue ); - } - RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); - mpi::allReduceInplace( extractedValue , op ); - return object( extractedValue ); - } - - - //=================================================================================================================== - // - // Gather - // - //=================================================================================================================== - - static IntStdVector gather_int( object value, int recvRank ) //NOLINT - { - if ( ! extract<int64_t>(value).check() ) - { - PyErr_SetString( PyExc_RuntimeError, "Could not gather the given value - unknown type"); - throw error_already_set(); - } - int64_t extractedValue = extract< int64_t >(value); - return mpi::gather( extractedValue , recvRank ); - } - - static RealStdVector gather_real( object value, int recvRank ) //NOLINT - { - if ( ! extract<real_t>(value).check() ) - { - PyErr_SetString( PyExc_RuntimeError, "Could not gather the given value - unknown type"); - throw error_already_set(); - } - real_t extractedValue = extract< real_t >(value); - return mpi::gather( extractedValue , recvRank); - } - - - static IntStdVector allgather_int( object value ) //NOLINT - { - if ( ! extract<int64_t>(value).check() ) - { - PyErr_SetString( PyExc_RuntimeError, "Could not gather the given value - unknown type"); - throw error_already_set(); - } - int64_t extractedValue = extract< int64_t >(value); - return mpi::allGather( extractedValue ); - } - - static RealStdVector allgather_real( object value ) //NOLINT - { - if ( ! extract<real_t>(value).check() ) - { - PyErr_SetString( PyExc_RuntimeError, "Could not gather the given value - unknown type"); - throw error_already_set(); - } - real_t extractedValue = extract< real_t >(value); - return mpi::allGather( extractedValue ); - } - - - - //=================================================================================================================== - // - // Export - // - //=================================================================================================================== - - static void worldBarrier() - { - WALBERLA_MPI_WORLD_BARRIER(); - } - - - void exportMPI() - { - object mpiModule( handle<>( borrowed(PyImport_AddModule("walberla_cpp.mpi")))); - scope().attr("mpi") = mpiModule; - scope mpiScope = mpiModule; - - def( "rank" , &rank ); - def( "worldRank" , &worldRank ); - def( "numProcesses" , &numProcesses ); - def( "hasCartesianSetup", &hasCartesianSetup); - def( "rankValid" , &rankValid ); - def( "worldBarrier" , &worldBarrier ); - - enum_<mpi::Operation>("Operation") - .value("MIN" , mpi::MIN ) - .value("MAX" , mpi::MAX ) - .value("SUM" , mpi::SUM ) - .value("PRODUCT", mpi::PRODUCT ) - .value("LOGICAL_AND", mpi::LOGICAL_AND ) - .value("BITWISE_AND", mpi::BITWISE_AND ) - .value("LOGICAL_OR", mpi::LOGICAL_OR ) - .value("BITWISE_OR", mpi::BITWISE_OR ) - .value("LOGICAL_XOR", mpi::LOGICAL_XOR ) - .value("BITWISE_XOR", mpi::BITWISE_XOR ) - .export_values(); - - def( "broadcastInt", &broadcast_int, ( arg("sendRank") = 0) ); - def( "broadcastReal", &broadcast_real, ( arg("sendRank") = 0) ); - def( "broadcastString",&broadcast_string, ( arg("sendRank") = 0) ); - - def( "reduceInt", &reduce_int, ( arg("recvRank") = 0 ) ); - def( "reduceReal", &reduce_real, ( arg("recvRank") = 0 ) ); - def( "allreduceInt", &allreduce_int ); - def( "allreduceReal", &allreduce_real ); - - - class_< IntStdVector> ("IntStdVector") .def(vector_indexing_suite<IntStdVector>() ); - class_< RealStdVector> ("RealStdVector").def(vector_indexing_suite<RealStdVector>() ); - class_< StringStdVector>("StringStdVector").def(vector_indexing_suite<StringStdVector>() ); - - def( "gatherInt", &gather_int , ( arg("recvRank") = 0 ) ); - def( "gatherReal", &gather_real, ( arg("recvRank") = 0 ) ); - def( "allgatherInt", &allgather_int ); - def( "allgatherReal", &allgather_real ); - } - - - -} // namespace python_coupling -} // namespace walberla - - -#endif diff --git a/src/python_coupling/export/BasicExport.cpp b/src/python_coupling/export/BasicExport.cpp new file mode 100644 index 000000000..279e304e5 --- /dev/null +++ b/src/python_coupling/export/BasicExport.cpp @@ -0,0 +1,728 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file BasicExports.cpp +//! \ingroup python_coupling +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +// Do not reorder includes - the include order is important +#include "python_coupling/PythonWrapper.h" + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +# include "communication/UniformMPIDatatypeInfo.h" +# include "communication/UniformPackInfo.h" + +# include "core/Abort.h" +# include "core/cell/CellInterval.h" +# include "core/logging/Logging.h" +# include "core/math/AABB.h" +# include "core/mpi/MPIIO.h" +# include "core/timing/ReduceType.h" +# include "core/timing/TimingPool.h" +# include "core/timing/TimingTree.h" +# include "core/waLBerlaBuildInfo.h" + +# include "domain_decomposition/StructuredBlockStorage.h" + +# include "field/GhostLayerField.h" + +# include "python_coupling/Manager.h" +# include "python_coupling/helper/BlockStorageExportHelpers.h" +# include "python_coupling/helper/OwningIterator.h" + +# include "stencil/Directions.h" + +# include <functional> + +# include "BasicExport.h" +# include "MPIExport.h" + +# include <pybind11/stl.h> + +// specialize operator== since == is deprecated in pybind11 +template<> +bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==( + const BlockData::DataBase& rhs) const +{ + const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs); + return (rhsData == &rhs) && (data_->is(*(rhsData->data_))); +} + +namespace py = pybind11; +namespace walberla { +namespace python_coupling { + +//====================================================================================================================== +// +// Cell +// +//====================================================================================================================== + +void exportCell(py::module_ &m) +{ + py::class_<Cell>(m, "Cell") + .def( py::init<cell_idx_t, cell_idx_t, cell_idx_t>()) + .def("__getitem__", + [](const Cell & cell, py::object & idx){ + return py::make_tuple(cell.x(), cell.y(), cell.z()).attr("__getitem__")(idx); + }); +} + +//====================================================================================================================== +// +// CellInterval +// +//====================================================================================================================== + + +void cellInterval_setMin( CellInterval & ci, const Cell & min ) { + ci.min() = min; +} +void cellInterval_setMax( CellInterval & ci, const Cell & max ) { + ci.max() = max; +} +void cellInterval_shift( CellInterval & ci, cell_idx_t xShift, cell_idx_t yShift, cell_idx_t zShift ) { + ci.shift( xShift, yShift, zShift ); +} + +py::tuple cellInterval_size( CellInterval & ci ) { + return py::make_tuple( ci.xSize(), ci.ySize(), ci.zSize() ); +} + +py::tuple cellInterval_min( CellInterval & ci ) { + return py::make_tuple( ci.xMin(), ci.yMin(), ci.zMin() ); +} + +py::tuple cellInterval_max( CellInterval & ci ) { + return py::make_tuple( ci.xMax(), ci.yMax(), ci.zMax() ); +} + +CellInterval cellInterval_getIntersection( CellInterval & ci1, CellInterval & ci2 ) +{ + CellInterval result ( ci1 ); + result.intersect( ci2 ); + return result; +} + +CellInterval cellInterval_getShifted( CellInterval & ci1, cell_idx_t xShift, cell_idx_t yShift, cell_idx_t zShift ) +{ + CellInterval result ( ci1 ); + result.shift( xShift, yShift, zShift ); + return result; +} + +CellInterval cellInterval_getExpanded1( CellInterval & ci1, cell_idx_t expandVal ) +{ + CellInterval result ( ci1 ); + result.expand( expandVal ); + return result; +} + +CellInterval cellInterval_getExpanded2( CellInterval & ci1, cell_idx_t xExpand, cell_idx_t yExpand, cell_idx_t zExpand ) +{ + CellInterval result ( ci1 ); + result.expand( Cell(xExpand, yExpand, zExpand) ); + return result; +} + +void exportCellInterval(py::module_ &m) +{ + using namespace pybind11::literals; + bool ( CellInterval::*p_contains1) ( const Cell & ) const = &CellInterval::contains; + bool ( CellInterval::*p_contains2) ( const CellInterval & ) const = &CellInterval::contains; + + void ( CellInterval::*p_expand1) ( const cell_idx_t ) = &CellInterval::expand; + void ( CellInterval::*p_expand2) ( const Cell & ) = &CellInterval::expand; + + bool ( CellInterval::*p_overlaps ) ( const CellInterval & ) const = &CellInterval::overlaps; + + py::class_<CellInterval>(m, "CellInterval") + .def( py::init<cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t>()) + .def_property( "min", &cellInterval_min, &cellInterval_setMin ) + .def_property( "max", &cellInterval_max, &cellInterval_setMax ) + .def_property_readonly( "size", &cellInterval_size ) + .def( "empty", &CellInterval::empty ) + .def( "positiveIndicesOnly", &CellInterval::positiveIndicesOnly ) + .def( "contains", p_contains1 ) + .def( "contains", p_contains2 ) + .def( "overlaps", p_overlaps ) + .def( "shift", &cellInterval_shift ) + .def( "getShifted", &cellInterval_getShifted ) + .def( "expand", p_expand1 ) + .def( "expand", p_expand2 ) + .def( "getExpanded", &cellInterval_getExpanded1 ) + .def( "getExpanded", &cellInterval_getExpanded2 ) + .def( "intersect", &CellInterval::intersect ) + .def( "getIntersection", &cellInterval_getIntersection ) + .def("__eq__", &CellInterval::operator==) + .def("__ne__", &CellInterval::operator!=) + .def_property_readonly( "numCells", &CellInterval::numCells ) + ; +} + +//====================================================================================================================== +// +// AABB +// +//====================================================================================================================== + + +py::tuple aabb_getMin( const AABB & domainBB ) { + return py::make_tuple( domainBB.xMin(), domainBB.yMin(), domainBB.zMin() ); +} + +py::tuple aabb_getMax( const AABB & domainBB ) { + return py::make_tuple( domainBB.xMax(), domainBB.yMax(), domainBB.zMax() ); +} + +py::tuple aabb_getSize( const AABB & domainBB ) { + return py::make_tuple( domainBB.sizes()[0], domainBB.sizes()[1], domainBB.sizes()[2] ); +} + +py::tuple aabb_getCenter( const AABB & domainBB ) { + return py::make_tuple( domainBB.center()[0], domainBB.center()[1], domainBB.center()[2] ); +} + +bool p_containsVec( const AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.contains(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +bool p_containsClosedInterval1( const AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.containsClosedInterval(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +bool p_containsClosedInterval2( const AABB & domainBB, std::array< real_t , 3 > Point, real_t dx ) { + return domainBB.containsClosedInterval(Vector3<real_t>(Point[0], Point[1], Point[2]), dx); +} + +AABB p_getExtended2( const AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.getExtended(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +AABB p_getScaled2( const AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.getScaled(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +AABB p_getMerged2( const AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.getMerged(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +void p_extend2( AABB & domainBB, std::array< real_t , 3 > Point ) { + domainBB.extend(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +void p_scale2( AABB & domainBB, std::array< real_t , 3 > Point ) { + domainBB.scale(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +void p_merge2( AABB & domainBB, std::array< real_t , 3 > Point ) { + domainBB.merge(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +real_t p_distance( AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.distance(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +real_t p_signedDistance( AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.signedDistance(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +real_t p_maxDistance( AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.distance(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +real_t p_sqDistance2( AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.sqDistance(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +real_t p_sqMaxDistance2( AABB & domainBB, std::array< real_t , 3 > Point ) { + return domainBB.sqMaxDistance(Vector3<real_t>(Point[0], Point[1], Point[2])); +} + +void aabb_setMin( AABB & domainBB, const std::array< real_t , 3 >& min ) +{ + domainBB = AABB( domainBB.max(), AABB::vector_type ( min[0], min[1], min[2] ) ); +} + +void aabb_setMax( AABB & domainBB, const std::array< real_t , 3 >& max ) +{ + domainBB = AABB( domainBB.min(), AABB::vector_type ( max[0], max[1], max[2] ) ); +} + + +void exportAABB(py::module_ &m) +{ + bool ( AABB::*p_containsBB )( const AABB & bb ) const = &AABB::contains; + + AABB ( AABB::*p_getExtended1 ) ( const real_t ) const = &AABB::getExtended; + + AABB ( AABB::*p_getScaled1 ) ( const real_t ) const = &AABB::getScaled; + + AABB ( AABB::*p_getMerged1 ) ( const AABB & ) const = &AABB::getMerged; + + bool ( AABB::*p_intersects1 )( const AABB & bb ) const = &AABB::intersects; + bool ( AABB::*p_intersects2 )( const AABB & bb, real_t dx ) const = &AABB::intersects; + + bool ( AABB::*p_intersectsClosed1 )( const AABB & bb ) const = &AABB::intersectsClosedInterval; + bool ( AABB::*p_intersectsClosed2 )( const AABB & bb, real_t dx ) const = &AABB::intersectsClosedInterval; + + void ( AABB::*p_extend1 ) ( const real_t ) = &AABB::extend; + + void ( AABB::*p_scale1 ) ( const real_t ) = &AABB::scale; + + void ( AABB::*p_merge1 ) ( const AABB & ) = &AABB::merge; + + real_t ( AABB::*p_sqDistance1 ) ( const AABB & ) const = &AABB::sqDistance; + + real_t ( AABB::*p_sqMaxDistance1 ) ( const AABB & ) const = &AABB::sqMaxDistance; + + + py::class_<AABB>(m, "AABB") + .def( py::init<real_t,real_t,real_t,real_t,real_t,real_t>() ) + .def("__eq__", &walberla::math::operator==<real_t, real_t > ) + .def("__ne__", &walberla::math::operator!=<real_t, real_t > ) + .def_property( "min", &aabb_getMin, &aabb_setMin ) + .def_property( "max", &aabb_getMax, &aabb_setMax ) + .def_property_readonly( "size", &aabb_getSize ) + .def_property_readonly( "empty", &AABB::empty ) + .def_property_readonly( "volume", &AABB::volume ) + .def_property_readonly( "center", &aabb_getCenter ) + .def( "contains", p_containsBB ) + .def( "contains", &p_containsVec ) + .def( "containsClosedInterval", &p_containsClosedInterval1 ) + .def( "containsClosedInterval", &p_containsClosedInterval2 ) + .def( "getExtended", p_getExtended1 ) + .def( "getExtended", &p_getExtended2 ) + .def( "getTranslated", &AABB::getTranslated ) + .def( "getScaled", p_getScaled1 ) + .def( "getScaled", &p_getScaled2 ) + .def( "getMerged", p_getMerged1 ) + .def( "getMerged", &p_getMerged2 ) + .def( "intersects", p_intersects1 ) + .def( "intersects", p_intersects2 ) + .def( "intersectsClosedInterval", p_intersectsClosed1 ) + .def( "intersectsClosedInterval", p_intersectsClosed2 ) + .def( "intersectionVolume", &AABB::intersectionVolume ) + .def( "getIntersection", &AABB::getIntersection ) + .def( "isIdentical", &AABB::isIdentical ) + .def( "isEqual", &AABB::isEqual ) + .def( "sqDistance", p_sqDistance1 ) + .def( "sqDistance", &p_sqDistance2 ) + .def( "sqMaxDistance", p_sqMaxDistance1 ) + .def( "sqMaxDistance", &p_sqMaxDistance2 ) + .def( "sqSignedDistance", &AABB::sqSignedDistance) + .def( "distance" , &p_distance) + .def( "signedDistance" , &p_signedDistance) + .def( "maxDistance" , &p_maxDistance) + .def( "extend", p_extend1 ) + .def( "extend", &p_extend2 ) + .def( "translate", &AABB::translate ) + .def( "scale", p_scale1 ) + .def( "scale", &p_scale2 ) + .def( "merge", p_merge1 ) + .def( "merge", &p_merge2 ) + .def( "intersect", &AABB::intersect ) + ; +} + +//====================================================================================================================== +// +// Timing +// +//====================================================================================================================== + +py::dict buildDictFromTimingNode(const WcTimingNode & tn) +{ + py::dict result; + + result["all"] = tn.timer_; + for ( auto it = tn.tree_.begin(); it != tn.tree_.end(); ++it) + { + std::string key = it->first; + if (it->second.tree_.empty()) + { + result[key.c_str()] = it->second.timer_; + } else + { + result[key.c_str()] = buildDictFromTimingNode(it->second); + } + } + + return result; +} + +py::dict buildDictFromTimingTree(const WcTimingTree & tt) +{ + return buildDictFromTimingNode( tt.getRawData() ); +} + +void timingTreeStopWrapper(WcTimingTree & tt, const std::string& name) +{ + if (!tt.isTimerRunning(name)) + { + throw py::value_error(("Timer '" + name + "' is currently not running!").c_str()); + } + tt.stop(name); +} + +void exportTiming(py::module_ &m) +{ + py::class_<WcTimer> (m, "Timer") + .def( py::init<>() ) + .def( "start", &WcTimer::start ) + .def( "stop", &WcTimer::end ) + .def( "reset", &WcTimer::reset ) + .def( "merge", &WcTimer::merge ) + .def_property_readonly( "counter", &WcTimer::getCounter ) + .def_property_readonly( "total", &WcTimer::total ) + .def_property_readonly( "sumOfSquares", &WcTimer::sumOfSquares ) + .def_property_readonly( "average", &WcTimer::average ) + .def_property_readonly( "variance", &WcTimer::variance ) + .def_property_readonly( "min", &WcTimer::min ) + .def_property_readonly( "max", &WcTimer::max ) + .def_property_readonly( "last", &WcTimer::last ) + ; + + + WcTimer & ( WcTimingPool::*pGetItem ) ( const std::string & ) = &WcTimingPool::operator[]; + + { + py::scope classScope = + py::class_<WcTimingPool, shared_ptr<WcTimingPool> > (m, "TimingPool") + .def( py::init<>() ) + .def_property_readonly( "__getitem__", pGetItem) + .def( "__contains__", &WcTimingPool::timerExists ) + .def( "getReduced", &WcTimingPool::getReduced) + .def( "merge", &WcTimingPool::merge) + .def( "clear", &WcTimingPool::clear ) + .def( "unifyRegisteredTimersAcrossProcesses", &WcTimingPool::unifyRegisteredTimersAcrossProcesses ) + .def( "logResultOnRoot", &WcTimingPool::logResultOnRoot) + ; + WALBERLA_UNUSED( classScope ); + + py::enum_<timing::ReduceType>(m, "ReduceType") + .value("min" , timing::REDUCE_MIN) + .value("avg" , timing::REDUCE_AVG) + .value("max" , timing::REDUCE_MAX) + .value("total", timing::REDUCE_TOTAL) + .export_values() + ; + } + + const WcTimer & ( WcTimingTree::*pTimingTreeGet ) ( const std::string & ) const = &WcTimingTree::operator[]; + py::class_<WcTimingTree, shared_ptr<WcTimingTree> > (m, "TimingTree") + .def( py::init<>() ) + .def_property_readonly( "__getitem__", pTimingTreeGet ) + .def( "start", &WcTimingTree::start ) + .def( "stop", &timingTreeStopWrapper ) + .def( "getReduced", &WcTimingTree::getReduced ) + .def( "toDict", &buildDictFromTimingTree ) + ; +} + + + + +//====================================================================================================================== +// +// IBlock +// +//====================================================================================================================== + +py::object IBlock_getData( py::object iblockObject, const std::string & stringID ) //NOLINT +{ + IBlock * block = py::cast<IBlock*>( iblockObject ); + + BlockDataID id = blockDataIDFromString( *block, stringID ); + + auto manager = python_coupling::Manager::instance(); + py::object res = manager->pythonObjectFromBlockData( *block, id ); + + if ( res.is(py::object()) ) + throw BlockDataNotConvertible(); + + return manager->pythonObjectFromBlockData( *block, id ); +} + + +std::vector<std::string> IBlock_fieldNames( py::object iblockObject ) //NOLINT +{ + IBlock * block = py::cast<IBlock*>( iblockObject ); + + return block->getBlockStorage().getBlockDataIdentifiers(); +} + +py::tuple IBlock_atDomainMinBorder( IBlock & block ) +{ + return py::make_tuple( block.getBlockStorage().atDomainXMinBorder(block), + block.getBlockStorage().atDomainYMinBorder(block), + block.getBlockStorage().atDomainZMinBorder(block) ); +} + +py::tuple IBlock_atDomainMaxBorder( IBlock & block ) +{ + return py::make_tuple( block.getBlockStorage().atDomainXMaxBorder(block), + block.getBlockStorage().atDomainYMaxBorder(block), + block.getBlockStorage().atDomainZMaxBorder(block) ); +} + +IBlockID::IDType IBlock_getIntegerID( IBlock & block ) +{ + return block.getId().getID(); +} + +bool IBlock_equals( IBlock & block1, IBlock & block2 ) +{ + return block1.getId() == block2.getId(); +} + +std::string IBlock_str( IBlock & b ) { + std::stringstream out; + out << "Block at " << b.getAABB(); + return out.str(); + +} + +void exportIBlock(py::module_ &m) +{ + static py::exception<NoSuchBlockData> ex(m, "NoSuchBlockData"); + py::register_exception_translator([](std::exception_ptr p) { + try { + if (p) std::rethrow_exception(p); + } catch (const NoSuchBlockData &e) { + // Set NoSuchBlockData as the active python error + throw std::out_of_range(e.what()); + } + }); + static py::exception<BlockDataNotConvertible> ex2(m, "BlockDataNotConvertible"); + py::register_exception_translator([](std::exception_ptr p) { + try { + if (p) std::rethrow_exception(p); + } catch (const BlockDataNotConvertible &e) { + // Set BlockDataNotConvertible as the active python error + throw std::invalid_argument(e.what()); + } + }); + + py::class_<IBlock, std::unique_ptr<IBlock, py::nodelete>> (m, "Block") + .def ( "__getitem__", &IBlock_getData, py::keep_alive<0, 1>() ) + .def_property_readonly( "atDomainMinBorder", &IBlock_atDomainMinBorder ) + .def_property_readonly( "atDomainMaxBorder", &IBlock_atDomainMaxBorder ) + .def_property_readonly( "fieldNames", &IBlock_fieldNames ) + .def_property_readonly( "id", &IBlock_getIntegerID ) + .def ( "__hash__", &IBlock_getIntegerID ) + .def ( "__eq__", &IBlock_equals ) + .def ( "__repr__", &IBlock_str ) + .def_property_readonly("aabb", &IBlock::getAABB ) + ; + +} + +//====================================================================================================================== +// +// Logging & Abort +// +//====================================================================================================================== + + +static void wlb_log_devel ( const std::string & msg ) { WALBERLA_LOG_DEVEL ( msg ); } +static void wlb_log_devel_on_root ( const std::string & msg ) { WALBERLA_LOG_DEVEL_ON_ROOT ( msg ); } + +static void wlb_log_result ( const std::string & msg ) { WALBERLA_LOG_RESULT ( msg ); } +static void wlb_log_result_on_root ( const std::string & msg ) { WALBERLA_LOG_RESULT_ON_ROOT ( msg ); } + +static void wlb_log_warning ( const std::string & msg ) { WALBERLA_LOG_WARNING ( msg ); } +static void wlb_log_warning_on_root ( const std::string & msg ) { WALBERLA_LOG_WARNING_ON_ROOT ( msg ); } + +#ifdef WALBERLA_LOGLEVEL_INFO +static void wlb_log_info ( const std::string & msg ) { WALBERLA_LOG_INFO ( msg ); } +static void wlb_log_info_on_root ( const std::string & msg ) { WALBERLA_LOG_INFO_ON_ROOT ( msg ); } +#else +static void wlb_log_info ( const std::string & ) {} +static void wlb_log_info_on_root ( const std::string & ) {} +#endif + +#ifdef WALBERLA_LOGLEVEL_PROGRESS +static void wlb_log_progress ( const std::string & msg ) { WALBERLA_LOG_PROGRESS ( msg ); } +static void wlb_log_progress_on_root ( const std::string & msg ) { WALBERLA_LOG_PROGRESS_ON_ROOT( msg ); } +#else +static void wlb_log_progress ( const std::string & ) {} +static void wlb_log_progress_on_root ( const std::string & ) {} +#endif + +#ifdef WALBERLA_LOGLEVEL_DETAIL +static void wlb_log_detail ( const std::string & msg ) { WALBERLA_LOG_DETAIL ( msg ); } +static void wlb_log_detail_on_root ( const std::string & msg ) { WALBERLA_LOG_DETAIL_ON_ROOT ( msg ); } +#else +static void wlb_log_detail ( const std::string & ) {} +static void wlb_log_detail_on_root ( const std::string & ) {} +#endif + +static void wlb_abort ( const std::string & msg ) { WALBERLA_ABORT_NO_DEBUG_INFO ( msg ); } + +void exportLogging(py::module_ &m) +{ + m.def ( "log_devel" , wlb_log_devel ); + m.def ( "log_devel_on_root" , wlb_log_devel_on_root ); + m.def ( "log_result", wlb_log_result ); + m.def ( "log_result_on_root", wlb_log_result_on_root ); + m.def ( "log_warning", wlb_log_warning ); + m.def ( "log_warning_on_root", wlb_log_warning_on_root ); + m.def ( "log_info", wlb_log_info ); + m.def ( "log_info_on_root", wlb_log_info_on_root ); + m.def ( "log_progress", wlb_log_progress ); + m.def ( "log_progress_on_root",wlb_log_progress_on_root); + m.def ( "log_detail", wlb_log_detail ); + m.def ( "log_detail_on_root", wlb_log_detail_on_root ); + + m.def ( "abort", wlb_abort ); +} + +//====================================================================================================================== +// +// Communication +// +//====================================================================================================================== + +void exportCommunication(py::module_ &m) +{ + using communication::UniformPackInfo; + py::class_< UniformPackInfo, shared_ptr<UniformPackInfo>> //NOLINT + (m, "UniformPackInfo" ); + + using communication::UniformMPIDatatypeInfo; + py::class_< UniformMPIDatatypeInfo, shared_ptr<UniformMPIDatatypeInfo>> + (m, "UniformMPIDatatypeInfo" ); + +} + +//====================================================================================================================== +// +// Stencil Directions +// +//====================================================================================================================== + +void exportStencilDirections(py::module_ &m) +{ + + py::module_ m2 = m.def_submodule("stencil", "Stencil Extension of the waLBerla python bindings"); + py::enum_< stencil::Direction >(m2, "Direction") + .value("C", stencil::C) + .value("N", stencil::N) + .value("S", stencil::S) + .value("W", stencil::W) + .value("E", stencil::E) + .value("T", stencil::T) + .value("B", stencil::B) + .value("NW", stencil::NW) + .value("NE", stencil::NE) + .value("SW", stencil::SW) + .value("SE", stencil::SE) + .value("TN", stencil::TN) + .value("TS", stencil::TS) + .value("TW", stencil::TW) + .value("TE", stencil::TE) + .value("BN", stencil::BN) + .value("BS", stencil::BS) + .value("BW", stencil::BW) + .value("BE", stencil::BE) + .value("TNE", stencil::TNE) + .value("TNW", stencil::TNW) + .value("TSE", stencil::TSE) + .value("TSW", stencil::TSW) + .value("BNE", stencil::BNE) + .value("BNW", stencil::BNW) + .value("BSE", stencil::BSE) + .value("BSW", stencil::BSW) + .export_values(); + py::list cx; + + py::list cy; + + py::list cz; + + py::list dirStrings; + for (uint_t i = 0; i < stencil::NR_OF_DIRECTIONS; ++i) + { + cx.append(stencil::cx[i]); + cy.append(stencil::cy[i]); + cz.append(stencil::cz[i]); + dirStrings.append(stencil::dirToString[i]); + } + py::list c; + c.append(cx); + c.append(cy); + c.append(cz); + + m2.attr("cx") = cx; + m2.attr("cy") = cy; + m2.attr("cz") = cz; + m2.attr("c") = c; + m2.attr("dirStrings") = dirStrings; +} + + +//====================================================================================================================== +// +// Build Info +// +//====================================================================================================================== + + +void exportBuildInfo(py::module_ &m) +{ + py::module_ m2 = m.def_submodule("build_info", "Get waLBerla Build Information"); + m2.attr("version") = WALBERLA_GIT_SHA1; + m2.attr("type" ) = WALBERLA_BUILD_TYPE; + m2.attr("compiler_flags" ) = WALBERLA_COMPILER_FLAGS; + m2.attr("build_machine" ) = WALBERLA_BUILD_MACHINE; + m2.attr("source_dir") = WALBERLA_SOURCE_DIR; + m2.attr("build_dir") = WALBERLA_BUILD_DIR; +} + + + + +void exportBasicWalberlaDatastructures(py::module_ &m) +{ + exportMPI(m); + + exportBuildInfo(m); + exportCell(m); + exportCellInterval(m); + exportAABB(m); + + exportTiming(m); + + exportIBlock(m); + exportCommunication(m); + + exportLogging(m); + exportStencilDirections(m); + + // Add empty callbacks module + m.def_submodule("callbacks", "Empty callbacks module. Needed for the Szenario manager"); + +} + +} // namespace python_coupling +} // namespace walberla + +#endif + diff --git a/src/python_coupling/basic_exports/BasicExports.h b/src/python_coupling/export/BasicExport.h similarity index 87% rename from src/python_coupling/basic_exports/BasicExports.h rename to src/python_coupling/export/BasicExport.h index 27421cd1f..ba9bb2b07 100644 --- a/src/python_coupling/basic_exports/BasicExports.h +++ b/src/python_coupling/export/BasicExport.h @@ -16,18 +16,21 @@ //! \file BasicExports.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #pragma once +#include <pybind11/pybind11.h> namespace walberla { namespace python_coupling { +namespace py = pybind11; - void exportBasicWalberlaDatastructures(); + void exportBasicWalberlaDatastructures(py::module_ &m); diff --git a/src/blockforest/python/CommunicationExport.h b/src/python_coupling/export/BlockForestCommunicationExport.h similarity index 78% rename from src/blockforest/python/CommunicationExport.h rename to src/python_coupling/export/BlockForestCommunicationExport.h index f47406da0..f74ff2fa3 100644 --- a/src/blockforest/python/CommunicationExport.h +++ b/src/python_coupling/export/BlockForestCommunicationExport.h @@ -16,10 +16,12 @@ //! \file CommunicationExport.h //! \ingroup blockforest //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #pragma once +#include <pybind11/pybind11.h> @@ -27,15 +29,15 @@ namespace walberla { namespace blockforest { - template<typename Stencils> - void exportUniformBufferedScheme(); + template<typename... Stencils> + void exportUniformBufferedScheme(pybind11::module_& m); - template<typename Stencils> - void exportUniformDirectScheme(); + template<typename... Stencils> + void exportUniformDirectScheme(pybind11::module_& m); } // namespace blockforest } // namespace walberla -#include "CommunicationExport.impl.h" +#include "BlockForestCommunicationExport.impl.h" diff --git a/src/python_coupling/export/BlockForestCommunicationExport.impl.h b/src/python_coupling/export/BlockForestCommunicationExport.impl.h new file mode 100644 index 000000000..a45abe4ff --- /dev/null +++ b/src/python_coupling/export/BlockForestCommunicationExport.impl.h @@ -0,0 +1,242 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CommunicationExport.impl.h +//! \ingroup blockforest +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "blockforest/communication/UniformBufferedScheme.h" +#include "blockforest/communication/UniformDirectScheme.h" + +#include "python_coupling/helper/MplHelpers.h" + +#include <pybind11/pybind11.h> + +namespace walberla +{ +namespace blockforest +{ +namespace py = pybind11; +namespace internal +{ +//=================================================================================================================== +// +// UniformBufferedScheme +// +//=================================================================================================================== + +/// the purpose of this class could also be solved by adding return_internal_reference to "createUniformDirectScheme" +/// however this is not easily possible since it returns not a reference but an py::object +template< typename Stencil > +class UniformBufferedSchemeWrapper : public blockforest::communication::UniformBufferedScheme< Stencil > +{ + public: + UniformBufferedSchemeWrapper(const shared_ptr< StructuredBlockForest >& bf, const int tag) + : blockforest::communication::UniformBufferedScheme< Stencil >(bf, tag), blockforest_(bf) + {} + + private: + shared_ptr< StructuredBlockForest > blockforest_; +}; + +struct UniformBufferedSchemeExporter +{ + UniformBufferedSchemeExporter(py::module_& m) : m_(m) {} + template< typename Stencil > + void operator()(python_coupling::NonCopyableWrap< Stencil >) const + { + typedef UniformBufferedSchemeWrapper< Stencil > UBS; + std::string class_name = "UniformBufferedScheme" + std::string(Stencil::NAME); + + py::class_< UBS, shared_ptr< UBS > >(m_, class_name.c_str()) + .def("__call__", &UBS::operator()) + .def("communicate", &UBS::communicate) + .def("startCommunication", &UBS::startCommunication) + .def("wait", &UBS::wait) + .def("addPackInfo", &UBS::addPackInfo) + .def("addDataToCommunicate", &UBS::addDataToCommunicate) + .def("localMode", &UBS::localMode) + .def("setLocalMode", &UBS::setLocalMode); + } + const py::module_& m_; +}; + +class UniformBufferedSchemeCreator +{ + public: + UniformBufferedSchemeCreator( const shared_ptr<StructuredBlockForest> & bf, + const std::string & stencilName, + const int tag ) + : blockforest_( bf), stencilName_( stencilName ), tag_( tag ) + {} + + template<typename Stencil> + void operator() ( python_coupling::NonCopyableWrap<Stencil> ) + { + + if ( std::string(Stencil::NAME) == stencilName_ ) { + result_ = py::cast( make_shared< UniformBufferedSchemeWrapper<Stencil> > ( blockforest_, tag_ ) ); + } + } + + py::object getResult() { return result_; } + private: + py::object result_; + shared_ptr<StructuredBlockForest> blockforest_; + std::string stencilName_; + const int tag_; +}; + + +template<typename... Stencils> +py::object createUniformBufferedScheme( const shared_ptr<StructuredBlockForest> & bf, + const std::string & stencil, const int tag ) +{ + UniformBufferedSchemeCreator creator( bf, stencil, tag ); + python_coupling::for_each_noncopyable_type< Stencils... > ( std::ref(creator) ); + + if ( !creator.getResult() ) + { + throw py::value_error("Unknown stencil."); + } + return creator.getResult(); +} + +//=================================================================================================================== +// +// UniformDirectScheme +// +//=================================================================================================================== + +template< typename Stencil > +class UniformDirectSchemeWrapper : public blockforest::communication::UniformDirectScheme< Stencil > +{ + public: + UniformDirectSchemeWrapper(const shared_ptr< StructuredBlockForest >& bf, const int tag) + : blockforest::communication::UniformDirectScheme< Stencil >( + bf, shared_ptr< walberla::communication::UniformMPIDatatypeInfo >(), tag), + blockforest_(bf) + {} + + private: + shared_ptr< StructuredBlockForest > blockforest_; +}; + +struct UniformDirectSchemeExporter +{ + UniformDirectSchemeExporter(py::module_& m) : m_(m) {} + template< typename Stencil > + void operator()(python_coupling::NonCopyableWrap< Stencil >) const + { + typedef UniformDirectSchemeWrapper< Stencil > UDS; + std::string class_name = "UniformDirectScheme_" + std::string(Stencil::NAME); + + py::class_< UDS, shared_ptr<UDS> >(m_, class_name.c_str() ) + .def("__call__", &UDS::operator()) + .def("communicate", &UDS::communicate) + .def("startCommunication", &UDS::startCommunication) + .def("wait", &UDS::wait) + .def("addDataToCommunicate", &UDS::addDataToCommunicate); + } + const py::module_ m_; +}; + +class UniformDirectSchemeCreator +{ + public: + UniformDirectSchemeCreator( const shared_ptr<StructuredBlockForest> & bf, + const std::string & stencilName, + const int tag ) + : blockforest_( bf), stencilName_( stencilName ), tag_( tag ) + {} + + template<typename Stencil> + void operator() ( python_coupling::NonCopyableWrap<Stencil> ) + { + + if ( std::string(Stencil::NAME) == stencilName_ ) { + result_ = py::cast( make_shared< UniformDirectSchemeWrapper<Stencil> > ( blockforest_, tag_ ) ); + } + } + + py::object getResult() { return result_; } + private: + py::object result_; + shared_ptr<StructuredBlockForest> blockforest_; + std::string stencilName_; + const int tag_; +}; + + +template<typename... Stencils> +py::object createUniformDirectScheme( const shared_ptr<StructuredBlockForest> & bf, + const std::string & stencil, const int tag ) +{ + UniformDirectSchemeCreator creator( bf, stencil, tag ); + python_coupling::for_each_noncopyable_type< Stencils... > ( std::ref(creator) ); + + if ( !creator.getResult() ) + { + throw py::value_error("Unknown stencil."); + } + return creator.getResult(); +} + + + + +} // namespace internal + +template< typename... Stencils > +void exportUniformDirectScheme(py::module_& m) +{ + using namespace py; + + python_coupling::for_each_noncopyable_type< Stencils... >(internal::UniformDirectSchemeExporter(m)); + m.def( "createUniformDirectScheme", + [](const shared_ptr<StructuredBlockForest> & blocks, const std::string & stencil, const int tag) + { + return internal::createUniformDirectScheme< Stencils... >(blocks, stencil, tag); + }, + "blocks"_a, "stencil"_a, "tag"_a=778 ); + + +} + +template< typename... Stencils > +void exportUniformBufferedScheme(py::module_& m) +{ + using namespace py; + + py::enum_< LocalCommunicationMode >(m, "LocalCommunicationMode") + .value("START", START) + .value("WAIT", WAIT) + .value("BUFFER", BUFFER) + .export_values(); + + python_coupling::for_each_noncopyable_type< Stencils... >(internal::UniformBufferedSchemeExporter(m)); + m.def( "createUniformBufferedScheme", + [](const shared_ptr<StructuredBlockForest> & blocks, const std::string & stencil, const int tag) + { + return internal::createUniformBufferedScheme< Stencils... >(blocks, stencil, tag); + }, + "blocks"_a, "stencil"_a, "tag"_a=778 ); +} + +} // namespace blockforest +} // namespace walberla \ No newline at end of file diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp new file mode 100644 index 000000000..14232baae --- /dev/null +++ b/src/python_coupling/export/BlockForestExport.cpp @@ -0,0 +1,340 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Exports.cpp +//! \ingroup blockforest +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +// Do not reorder includes - the include order is important +#include "python_coupling/PythonWrapper.h" + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +# include "blockforest/Initialization.h" +# include "blockforest/SetupBlock.h" +# include "blockforest/SetupBlockForest.h" +# include "blockforest/StructuredBlockForest.h" + +# include "core/StringUtility.h" +# include "core/mpi/MPIIO.h" + +# include "stencil/D3Q19.h" + +# include <memory> +# include <pybind11/stl.h> +# include <sstream> + +# include "BlockForestExport.h" +# include "python_coupling/helper/OwningIterator.h" + +namespace walberla +{ +namespace blockforest +{ +std::string printSetupBlock(const SetupBlock& b) +{ + std::stringstream out; + out << "SetupBlock at " << b.getAABB(); + return out.str(); +} + +namespace py = pybind11; + +//====================================================================================================================== +// +// StructuredBlockForest +// +//====================================================================================================================== + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +void NoSuchBlockData::translate( const NoSuchBlockData & e ) { + throw py::cast_error(e.what()); +} + +void BlockDataNotConvertible::translate( const BlockDataNotConvertible & e ) { + throw py::cast_error(e.what()); +} +#else + +void NoSuchBlockData::translate( const NoSuchBlockData & ) {} + +void BlockDataNotConvertible::translate( const BlockDataNotConvertible & ) {} + +#endif + +BlockDataID blockDataIDFromString(BlockStorage& bs, const std::string& stringID) +{ + auto ids = bs.getBlockDataIdentifiers(); + + for (uint_t i = 0; i < ids.size(); ++i) + if (ids[i] == stringID) return BlockDataID(i); + + throw NoSuchBlockData(); +} + +BlockDataID blockDataIDFromString(IBlock& block, const std::string& stringID) +{ + return blockDataIDFromString(block.getBlockStorage(), stringID); +} + +BlockDataID blockDataIDFromString(StructuredBlockForest& bs, const std::string& stringID) +{ + return blockDataIDFromString(bs.getBlockStorage(), stringID); +} + +py::iterator StructuredBlockForest_iter(const shared_ptr< StructuredBlockForest >& bf) // NOLINT +{ + // shared_ptr<StructuredBlockForest> s = py::cast< shared_ptr<StructuredBlockForest> > ( StructuredBlockForest ); + + std::vector< const IBlock* > blocks; + bf->getBlocks(blocks); + std::vector<py::object> resultList; + resultList.reserve(blocks.size()); + + for (auto it = blocks.begin(); it != blocks.end(); ++it) + { + py::object theObject = py::cast(*it); + resultList.push_back(theObject); + } + + return python_coupling::make_owning_iterator(resultList); +} + +py::object StructuredBlockForest_getItem(const shared_ptr< StructuredBlockForest >& bf, uint_t i) // NOLINT +{ + if (i >= bf->size()) { throw py::value_error("Index out of bounds"); } + + std::vector< const IBlock* > blocks; + bf->getBlocks(blocks); + + py::object theObject = py::cast(blocks[i]); + return theObject; +} + +std::vector<py::object> StructuredBlockForest_blocksOverlappedByAABB(StructuredBlockForest& s, const AABB& aabb) +{ + std::vector< IBlock* > blocks; + s.getBlocksOverlappedByAABB(blocks, aabb); + + std::vector<py::object> resultList; + for (auto it = blocks.begin(); it != blocks.end(); ++it) + resultList.push_back(py::cast(*it)); + return resultList; +} + +std::vector<py::object> StructuredBlockForest_blocksContainedWithinAABB(StructuredBlockForest& s, const AABB& aabb) +{ + std::vector< IBlock* > blocks; + s.getBlocksContainedWithinAABB(blocks, aabb); + + std::vector<py::object> resultList; + for (auto it = blocks.begin(); it != blocks.end(); ++it) + resultList.push_back(py::cast(*it)); + return resultList; +} + +py::object SbF_transformGlobalToLocal(StructuredBlockForest& s, IBlock& block, const py::object& global) +{ + if (py::isinstance< CellInterval >(global)) + { + CellInterval ret; + s.transformGlobalToBlockLocalCellInterval(ret, block, py::cast< CellInterval >(global)); + return py::cast(ret); + } + else if (py::isinstance< Cell >(global)) + { + Cell ret; + s.transformGlobalToBlockLocalCell(ret, block, py::cast< Cell >(global)); + return py::cast(ret); + } + + throw py::value_error("Only CellIntervals and cells can be transformed"); +} + +py::object SbF_transformLocalToGlobal(StructuredBlockForest& s, IBlock& block, const py::object& local) +{ + if (py::isinstance< CellInterval >(local)) + { + CellInterval ret; + s.transformBlockLocalToGlobalCellInterval(ret, block, py::cast< CellInterval >(local)); + return py::cast(ret); + } + else if (py::isinstance< Cell >(local)) + { + Cell ret; + s.transformBlockLocalToGlobalCell(ret, block, py::cast< Cell >(local)); + return py::cast(ret); + } + throw py::value_error("Only CellIntervals and cells can be transformed"); +} + +void SbF_writeBlockData(StructuredBlockForest& s, const std::string& blockDataId, const std::string& file) +{ + mpi::SendBuffer buffer; + s.serializeBlockData(blockDataIDFromString(s, blockDataId), buffer); + mpi::writeMPIIO(file, buffer); +} + +void SbF_readBlockData(StructuredBlockForest& s, const std::string& blockDataId, const std::string& file) +{ + mpi::RecvBuffer buffer; + mpi::readMPIIO(file, buffer); + + s.deserializeBlockData(blockDataIDFromString(s, blockDataId), buffer); + if (!buffer.isEmpty()) + { throw py::cast_error("Reading failed - file does not contain matching data for this type."); } +} + +CellInterval SbF_getBlockCellBB(StructuredBlockForest& s, const IBlock* block) { return s.getBlockCellBB(*block); } + +std::array<real_t , 3> SbF_mapToPeriodicDomain1(StructuredBlockForest& s, real_t x, real_t y, real_t z) +{ + Vector3< real_t > res(x, y, z); + s.mapToPeriodicDomain(res); + return std::array< real_t, 3 >{ res[0], res[1], res[2] }; +} + +std::array<real_t , 3> SbF_mapToPeriodicDomain2(StructuredBlockForest& s, const std::array<real_t, 3>& in) +{ + Vector3< real_t > tmp(in[0], in[1], in[2]); + s.mapToPeriodicDomain(tmp); + return std::array< real_t, 3 >{ tmp[0], tmp[1], tmp[2] }; +} + +Cell SbF_mapToPeriodicDomain3(StructuredBlockForest& s, Cell in, uint_t level = 0) +{ + s.mapToPeriodicDomain(in, level); + return in; +} + +py::object SbF_getBlock1(StructuredBlockForest& s, const real_t x, const real_t y, const real_t z) +{ + return py::cast(s.getBlock(x, y, z)); +} + +py::object SbF_getBlock2(StructuredBlockForest& s, const std::array<real_t, 3>& v) +{ + return py::cast(s.getBlock(Vector3<real_t>(v[0], v[1], v[2]))); + +} + +py::tuple SbF_periodic(StructuredBlockForest& s) +{ + return py::make_tuple(s.isXPeriodic(), s.isYPeriodic(), s.isZPeriodic()); +} + +bool p_blockExists1(StructuredBlockForest& s, const std::array<real_t, 3>& v) +{ + return s.blockExists(Vector3<real_t>(v[0], v[1], v[2])); + +} + +bool p_blockExistsLocally1(StructuredBlockForest& s, const std::array<real_t, 3>& v) +{ + return s.blockExistsLocally(Vector3<real_t>(v[0], v[1], v[2])); + +} + +bool p_blockExistsRemotely1(StructuredBlockForest& s, const std::array<real_t, 3>& v) +{ + return s.blockExistsRemotely(Vector3<real_t>(v[0], v[1], v[2])); + +} + +bool SbF_atDomainXMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMinBorder(*b); } +bool SbF_atDomainXMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMaxBorder(*b); } +bool SbF_atDomainYMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainYMinBorder(*b); } +bool SbF_atDomainYMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainYMaxBorder(*b); } +bool SbF_atDomainZMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainZMinBorder(*b); } +bool SbF_atDomainZMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainZMaxBorder(*b); } + +void exportBlockForest(py::module_& m) +{ + using namespace pybind11::literals; + + bool (StructuredBlockForest::*p_blockExists2)(const real_t, const real_t, const real_t) const = + &StructuredBlockForest::blockExists; + bool (StructuredBlockForest::*p_blockExistsLocally2)(const real_t, const real_t, const real_t) const = + &StructuredBlockForest::blockExistsLocally; + bool (StructuredBlockForest::*p_blockExistsRemotely2)(const real_t, const real_t, const real_t) const = + &StructuredBlockForest::blockExistsRemotely; + + py::class_< StructuredBlockForest, std::shared_ptr< StructuredBlockForest > >(m, "StructuredBlockForest") + .def("getNumberOfLevels", &StructuredBlockForest::getNumberOfLevels) + .def_property_readonly("getDomain", &StructuredBlockForest::getDomain) + .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain1) + .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain2) + .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain3) + .def("__getitem__", &StructuredBlockForest_getItem, py::keep_alive< 0, 1 >()) + .def("__len__", &StructuredBlockForest::size) + .def("getBlock", SbF_getBlock1, py::keep_alive< 0, 1 >()) + .def("getBlock", SbF_getBlock2, py::keep_alive< 0, 1 >()) + .def("containsGlobalBlockInformation", &StructuredBlockForest::containsGlobalBlockInformation) + .def("blocksOverlappedByAABB", &StructuredBlockForest_blocksOverlappedByAABB, py::keep_alive< 0, 1 >()) + .def("blocksContainedWithinAABB", &StructuredBlockForest_blocksContainedWithinAABB, py::keep_alive< 0, 1 >()) + .def("blockExists", &p_blockExists1) + .def("blockExists", p_blockExists2) + .def("blockExistsLocally", &p_blockExistsLocally1) + .def("blockExistsLocally", p_blockExistsLocally2) + .def("blockExistsRemotely", &p_blockExistsRemotely1) + .def("blockExistsRemotely", p_blockExistsRemotely2) + .def("atDomainXMinBorder", &SbF_atDomainXMinBorder) + .def("atDomainXMaxBorder", &SbF_atDomainXMaxBorder) + .def("atDomainYMinBorder", &SbF_atDomainYMinBorder) + .def("atDomainYMaxBorder", &SbF_atDomainYMaxBorder) + .def("atDomainZMinBorder", &SbF_atDomainZMinBorder) + .def("atDomainZMaxBorder", &SbF_atDomainZMaxBorder) + .def("dx", &StructuredBlockForest::dx) + .def("dy", &StructuredBlockForest::dy) + .def("dz", &StructuredBlockForest::dz) + .def("getDomainCellBB", &StructuredBlockForest::getDomainCellBB, "level"_a=0) + .def("getBlockCellBB", &SbF_getBlockCellBB) + .def("transformGlobalToLocal", &SbF_transformGlobalToLocal) + .def("transformLocalToGlobal", &SbF_transformLocalToGlobal) + .def("writeBlockData", &SbF_writeBlockData) + .def("readBlockData", &SbF_readBlockData) + .def("__iter__", &StructuredBlockForest_iter, py::keep_alive< 0, 1 >()) + .def_property_readonly("containsGlobalBlockInformation", &StructuredBlockForest::containsGlobalBlockInformation) + .def_property_readonly("periodic", &SbF_periodic); + + py::class_< SetupBlock, shared_ptr< SetupBlock > >(m, "SetupBlock") + .def("get_level", &SetupBlock::getLevel) + .def("set_workload", &SetupBlock::setWorkload) + .def("get_workload", &SetupBlock::getWorkload) + .def("set_memory", &SetupBlock::setMemory) + .def("get_memory", &SetupBlock::getMemory) + .def("get_aabb", &SetupBlock::getAABB) + .def("__repr__", &printSetupBlock); + + m.def( + "createUniformBlockGrid", + [](std::array< uint_t, 3 > blocks, std::array< uint_t, 3 > cellsPerBlock, real_t dx, + bool oneBlockPerProcess, std::array< bool, 3 > periodic, bool keepGlobalBlockInformation) { + return blockforest::createUniformBlockGrid(blocks[0], blocks[1], blocks[2], cellsPerBlock[0], cellsPerBlock[1], + cellsPerBlock[2], dx, oneBlockPerProcess, periodic[0], periodic[1], periodic[2], + keepGlobalBlockInformation); + }, + "blocks"_a, "cellsPerBlock"_a, "dx"_a = real_t(1), "oneBlockPerProcess"_a = true, + "periodic"_a = std::array< bool, 3 >{ false, false, false }, "keepGlobalBlockInformation"_a = false); +} + +} // namespace blockforest +} // namespace walberla + +#endif // WALBERLA_BUILD_WITH_PYTHON \ No newline at end of file diff --git a/src/python_coupling/export/BlockForestExport.h b/src/python_coupling/export/BlockForestExport.h new file mode 100644 index 000000000..1c5ddaae4 --- /dev/null +++ b/src/python_coupling/export/BlockForestExport.h @@ -0,0 +1,69 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file Exports.h +//! \ingroup blockforest +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "waLBerlaDefinitions.h" + + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +# include <pybind11/pybind11.h> + +# include "BlockForestCommunicationExport.h" + +namespace walberla { +namespace blockforest { + + struct NoSuchBlockData : public std::out_of_range { + explicit NoSuchBlockData ( ) : std::out_of_range( "No blockdata with the given name found" ) {} + explicit NoSuchBlockData ( const std::string & w ) : std::out_of_range(w) {} + static void translate( const NoSuchBlockData & e ); + }; + struct BlockDataNotConvertible : public std::runtime_error { + explicit BlockDataNotConvertible ( ) : std::runtime_error( "This blockdata is not accessible from Python" ) {} + explicit BlockDataNotConvertible ( const std::string & w ) : std::runtime_error(w) {} + static void translate( const BlockDataNotConvertible & e ); + }; + + BlockDataID blockDataIDFromString( IBlock & block, const std::string & stringID ); + BlockDataID blockDataIDFromString( BlockStorage & bs, const std::string & stringID ); + BlockDataID blockDataIDFromString( StructuredBlockStorage & bs, const std::string & stringID ); + + namespace py = pybind11; + + void exportBlockForest(py::module_ &m); + + + template<typename... Stencils> + void exportModuleToPython(py::module_ &m) + { + exportBlockForest(m); + exportUniformBufferedScheme<Stencils...>(m); + exportUniformDirectScheme<Stencils...>(m); + } + +} // namespace blockforest +} // namespace walberla + + +#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/cuda/python/Exports.h b/src/python_coupling/export/CUDAExport.h similarity index 81% rename from src/cuda/python/Exports.h rename to src/python_coupling/export/CUDAExport.h index 5e5b00090..505aa3368 100644 --- a/src/cuda/python/Exports.h +++ b/src/python_coupling/export/CUDAExport.h @@ -13,9 +13,10 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file FieldExport.h +//! \file CUDAExport.h //! \ingroup cuda //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -28,14 +29,16 @@ namespace walberla { namespace cuda { - template<typename GpuFields, typename CpuFields> - void exportModuleToPython(); + template<typename... GpuFields> + void exportModuleToPython(py::module_ &m); + + template<typename... CpuFields> + void exportCopyFunctionsToPython(py::module_ &m); } // namespace cuda } // namespace walberla -#include "Exports.impl.h" - +#include "CUDAExport.impl.h" #endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/python_coupling/export/CUDAExport.impl.h b/src/python_coupling/export/CUDAExport.impl.h new file mode 100644 index 000000000..eb60759cb --- /dev/null +++ b/src/python_coupling/export/CUDAExport.impl.h @@ -0,0 +1,394 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CUDAExport.impl.h +//! \ingroup cuda +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +// Do not reorder includes - the include order is important +#include "core/logging/Logging.h" + +#include "cuda/AddGPUFieldToStorage.h" +#include "cuda/FieldCopy.h" +#include "cuda/GPUField.h" +#include "cuda/communication/GPUPackInfo.h" + +#include "field/AddToStorage.h" +#include "field/communication/UniformMPIDatatypeInfo.h" + +#include "python_coupling/PythonWrapper.h" +#include "python_coupling/helper/MplHelpers.h" + +namespace walberla { +namespace cuda { + + + +namespace internal { +using namespace pybind11::literals; + //=================================================================================================================== + // + // Field export + // + //=================================================================================================================== + + template<typename GpuField_T> + uint64_t gpufield_ptr(const GpuField_T & gpuField) + { + return reinterpret_cast<uint64_t>(gpuField.pitchedPtr().ptr); + // return gpuField.pitchedPtr(); + } + + template<typename GpuField_T> + std::string gpufield_dtypeStr(const GpuField_T & ) + { + return std::string(field::internal::PythonFormatString<typename GpuField_T::value_type>::get()); + } + + struct GpuFieldExporter + { + GpuFieldExporter(py::module_& m) : m_(m) {} + template< typename GpuField_T> + void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) const + { + + typedef typename GpuField_T::value_type T; + std::string data_type_name = field::internal::PythonFormatString<T>::get(); + + std::string class_name = "GpuField_" + data_type_name; + py::class_<GpuField_T, shared_ptr<GpuField_T>>(m_, class_name.c_str() ) + .def_property_readonly("layout", &field::internal::field_layout < GpuField_T > ) + .def_property_readonly("size", &field::internal::field_size < GpuField_T > ) + .def_property_readonly("sizeWithGhostLayers", &field::internal::field_sizeWithGhostLayer< GpuField_T > ) + .def_property_readonly("allocSize", &field::internal::field_allocSize < GpuField_T > ) + .def_property_readonly("strides", &field::internal::field_strides < GpuField_T > ) + .def_property_readonly("offsets", &field::internal::field_offsets < GpuField_T > ) + .def_property_readonly("ptr", &gpufield_ptr < GpuField_T > ) + .def_property_readonly("dtypeStr", &gpufield_dtypeStr < GpuField_T > ) + .def_property_readonly("isPitchedMem", &GpuField_T::isPitchedMem ) + .def("swapDataPointers", &field::internal::field_swapDataPointers < GpuField_T > ) + .def_property_readonly("nrOfGhostLayers", &GpuField_T::nrOfGhostLayers ) + .def("cloneUninitialized", &GpuField_T::cloneUninitialized, py::return_value_policy::copy) + ; + + + using field::communication::PackInfo; + using communication::GPUPackInfo; + std::string GpuFieldPackInfoName = "GpuFieldPackInfo_" + data_type_name; + py::class_< GPUPackInfo<GpuField_T>, shared_ptr< GPUPackInfo<GpuField_T> >, walberla::communication::UniformPackInfo>(m_, GpuFieldPackInfoName.c_str() ); + + using field::communication::UniformMPIDatatypeInfo; + std::string GpuFieldMPIDataTypeInfoName = "GpuFieldMPIDataTypeInfo_" + data_type_name; + py::class_< UniformMPIDatatypeInfo<GpuField_T>, shared_ptr< UniformMPIDatatypeInfo<GpuField_T> >, walberla::communication::UniformMPIDatatypeInfo>(m_, GpuFieldMPIDataTypeInfoName.c_str() ); + + } + const py::module_& m_; + }; + + + //=================================================================================================================== + // + // addToStorage + // + //=================================================================================================================== + + class AddToStorageExporter + { + public: + AddToStorageExporter( const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, + py::object &dtype, uint_t fs, uint_t gl, Layout layout, + bool usePitchedMem ) + : blocks_( blocks ), name_( name ), dtype_(dtype), fs_( fs ), + gl_(gl),layout_( layout), usePitchedMem_(usePitchedMem), found_(true) + {} + + template< typename GpuField_T> + void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) + { + typedef typename GpuField_T::value_type T; + + if(python_coupling::isCppEqualToPythonType<T>(py::cast<std::string>(dtype_.attr("__name__")))) + { + addGPUFieldToStorage< GPUField< T > >(blocks_, name_, fs_, layout_, gl_, usePitchedMem_); + } + } + + bool successful() const { return found_; } + private: + shared_ptr< StructuredBlockForest > blocks_; + std::string name_; + py::object dtype_; + uint_t fs_; + uint_t gl_; + Layout layout_; + bool usePitchedMem_; + bool found_; + }; + + template<typename... GpuFields> + void addToStorage( const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, py::object &dtype, + uint_t fs, uint_t gl, Layout layout, bool usePitchedMem ) + { + namespace py = pybind11; + auto result = make_shared<py::object>(); + AddToStorageExporter exporter( blocks, name, dtype, fs, gl, layout, usePitchedMem ); + python_coupling::for_each_noncopyable_type<GpuFields...>( std::ref(exporter) ); + } + + + //=================================================================================================================== + // + // createPackInfo Export + // + //=================================================================================================================== + + class PackInfoExporter + { + public: + PackInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId, uint_t numberOfGhostLayers) + : blocks_(blocks), fieldId_(fieldId), numberOfGhostLayers_( numberOfGhostLayers ) + {} + + template< typename GpuField_T> + void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) + { + using cuda::communication::GPUPackInfo; + + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<GpuField_T>(fieldId_) ) + { + if ( numberOfGhostLayers_ > 0 ) + { + resultPackInfo_ = py::cast(make_shared< GPUPackInfo< GpuField_T > >(fieldId_, numberOfGhostLayers_)); + } + else + { + resultPackInfo_ = py::cast(make_shared< GPUPackInfo< GpuField_T > >(fieldId_)); + } + } + } + py::object getResultPackInfo() + { + return resultPackInfo_; + } + + private: + py::object resultPackInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; + uint_t numberOfGhostLayers_; + }; + + + template<typename... GpuField_T> + static py::object PackInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & name, uint_t numberOfGhostLayers ) + { + using cuda::communication::GPUPackInfo; + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< GPUPackInfo<GPUField<int8_t>> >( fieldID, numberOfGhostLayers ) ); + } + + PackInfoExporter exporter(blocks, fieldID, numberOfGhostLayers); + python_coupling::for_each_noncopyable_type< GpuField_T... > ( std::ref(exporter) ); + if ( ! exporter.getResultPackInfo() ) { + throw py::value_error("Failed to create GPU PackInfo"); + } + else { + return exporter.getResultPackInfo(); + } + } + + //=================================================================================================================== + // + // createMPIDatatypeInfo + // + //=================================================================================================================== + + class UniformMPIDatatypeInfoExporter + { + public: + UniformMPIDatatypeInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId, uint_t numberOfGhostLayers) + : blocks_(blocks), fieldId_(fieldId), numberOfGhostLayers_( numberOfGhostLayers ) + {} + + template< typename GpuField_T> + void operator() ( python_coupling::NonCopyableWrap<GpuField_T> ) + { + using field::communication::UniformMPIDatatypeInfo; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<GpuField_T>(fieldId_) ) + { + if ( numberOfGhostLayers_ > 0 ) + resultMPIDatatypeInfo_ = py::cast( make_shared< UniformMPIDatatypeInfo<GpuField_T> >( fieldId_, numberOfGhostLayers_ ) ); + else + resultMPIDatatypeInfo_ = py::cast( make_shared< UniformMPIDatatypeInfo<GpuField_T> >( fieldId_ ) ); + + } + } + py::object getResultUniformMPIDatatype() + { + return resultMPIDatatypeInfo_; + } + + private: + py::object resultMPIDatatypeInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; + uint_t numberOfGhostLayers_; + }; + + + template<typename... GpuField_T> + static py::object UniformMPIDatatypeInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & name, uint_t numberOfGhostLayers ) + { + using field::communication::UniformMPIDatatypeInfo; + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< UniformMPIDatatypeInfo<GPUField<int8_t>> >( fieldID, numberOfGhostLayers ) ); + } + + UniformMPIDatatypeInfoExporter exporter(blocks, fieldID, numberOfGhostLayers); + python_coupling::for_each_noncopyable_type< GpuField_T... > ( std::ref(exporter) ); + if ( ! exporter.getResultUniformMPIDatatype() ) { + throw py::value_error("Failed to create GPU UniformMPIDatatype"); + } + else { + return exporter.getResultUniformMPIDatatype(); + } + } + + //=================================================================================================================== + // + // fieldCopy + // + //=================================================================================================================== + +class copyFieldToGpuDispatchExporter +{ + public: + copyFieldToGpuDispatchExporter( const shared_ptr<StructuredBlockForest> & blocks, + BlockDataID gpuFieldId, BlockDataID cpuFieldId, bool toGPU) + : blocks_( blocks ), gpuFieldId_( gpuFieldId ), cpuFieldId_(cpuFieldId), toGPU_( toGPU ) + {} + + template< typename CpuField_T> + void operator() ( python_coupling::NonCopyableWrap<CpuField_T> ) + { + typedef cuda::GPUField<typename CpuField_T::value_type> GpuField_T; + IBlock * firstBlock = & ( * blocks_->begin() ); + + if(firstBlock->isDataClassOrSubclassOf< CpuField_T > ( cpuFieldId_ ) ) + { + if(toGPU_) + cuda::fieldCpy<GpuField_T, CpuField_T>(blocks_, gpuFieldId_, cpuFieldId_); + else + cuda::fieldCpy<CpuField_T, GpuField_T>(blocks_, cpuFieldId_, gpuFieldId_); + } + } + private: + shared_ptr< StructuredBlockForest > blocks_; + BlockDataID gpuFieldId_; + BlockDataID cpuFieldId_; + bool toGPU_; +}; + +template<typename... CpuFields> +void copyFieldToGPU(const shared_ptr< StructuredBlockForest > & blocks, const std::string & gpuFieldName, + const std::string & cpuFieldName, bool toGPU ) +{ + namespace py = pybind11; + auto result = make_shared<py::object>(); + + BlockDataID gpuFieldId = python_coupling::blockDataIDFromString( *blocks, gpuFieldName ); + BlockDataID cpuFieldId = python_coupling::blockDataIDFromString( *blocks, cpuFieldName ); + + copyFieldToGpuDispatchExporter exporter( blocks, gpuFieldId, cpuFieldId, toGPU ); + python_coupling::for_each_noncopyable_type<CpuFields...>( std::ref(exporter) ); +} +} // namespace internal + + +using namespace pybind11::literals; + +template<typename... GpuFields> +void exportModuleToPython(py::module_ &m) +{ + py::module_ m2 = m.def_submodule("cuda", "Cuda Extension of the waLBerla python bindings"); + + python_coupling::for_each_noncopyable_type<GpuFields...>( internal::GpuFieldExporter(m2) ); + + m2.def( + "addGpuFieldToStorage", + [](const shared_ptr< StructuredBlockForest > & blocks, const std::string & name, py::object &dtype, uint_t fSize, + bool usePitchedMem, uint_t ghostLayers, Layout layout) { + return internal::addToStorage<GpuFields...>(blocks, name, dtype, fSize, ghostLayers, layout, usePitchedMem); + }, + "blocks"_a, "name"_a, "dtype"_a, "fSize"_a=1, "usePitchedMem"_a=false, "ghostLayers"_a=uint(1), "layout"_a=zyxf); + + m2.def( + "createPackInfo", + [](const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName, uint_t numberOfGhostLayers ) { + return internal::PackInfoWrapper< GpuFields... >(blocks, blockDataName, numberOfGhostLayers); + }, + "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); + + m2.def( + "createMPIDatatypeInfo", + [](const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName, uint_t numberOfGhostLayers ) { + return internal::UniformMPIDatatypeInfoWrapper< GpuFields... >(blocks, blockDataName, numberOfGhostLayers); + }, + "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); + +} + +template<typename... CpuFields > +void exportCopyFunctionsToPython(py::module_ &m) +{ + py::module_ m2 = m.def_submodule("cuda", "Cuda Extension of the waLBerla python bindings"); + + m2.def( + "copyFieldToGpu", + [](const shared_ptr< StructuredBlockForest > & blocks, const std::string & gpuFieldName, const std::string & cpuFieldName) { + return internal::copyFieldToGPU<CpuFields...>(blocks, gpuFieldName, cpuFieldName, true); + }, + "blocks"_a, "gpuFieldName"_a, "cpuFieldName"_a); + + m2.def( + "copyFieldToCpu", + [](const shared_ptr< StructuredBlockForest > & blocks, const std::string & gpuFieldName, const std::string & cpuFieldName) { + return internal::copyFieldToGPU<CpuFields...>(blocks, gpuFieldName, cpuFieldName, false); + }, + "blocks"_a, "gpuFieldName"_a, "cpuFieldName"_a); +} + + + + +} // namespace cuda +} // namespace walberla + + diff --git a/src/field/python/CommunicationExport.h b/src/python_coupling/export/FieldCommunicationExport.h similarity index 85% rename from src/field/python/CommunicationExport.h rename to src/python_coupling/export/FieldCommunicationExport.h index 8b76146a6..ccbe61496 100644 --- a/src/field/python/CommunicationExport.h +++ b/src/python_coupling/export/FieldCommunicationExport.h @@ -16,6 +16,7 @@ //! \file CommunicationExport.h //! \ingroup field //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -26,17 +27,17 @@ namespace walberla { namespace field { +namespace py = pybind11; - template<typename FieldTypes> - void exportCommunicationClasses(); + template<typename... FieldTypes> + void exportCommunicationClasses(py::module_ &m); } // namespace field } // namespace walberla -#include "CommunicationExport.impl.h" - +#include "FieldCommunicationExport.impl.h" #endif //WALBERLA_BUILD_WITH_PYTHON diff --git a/src/python_coupling/export/FieldCommunicationExport.impl.h b/src/python_coupling/export/FieldCommunicationExport.impl.h new file mode 100644 index 000000000..0793b26a5 --- /dev/null +++ b/src/python_coupling/export/FieldCommunicationExport.impl.h @@ -0,0 +1,249 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CommunicationExport.impl.h +//! \ingroup field +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "python_coupling/PythonWrapper.h" + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +# include "blockforest/StructuredBlockForest.h" +# include "python_coupling/helper/BlockStorageExportHelpers.h" + +# include "field/communication/PackInfo.h" +# include "field/communication/StencilRestrictedPackInfo.h" +# include "field/communication/UniformMPIDatatypeInfo.h" + +# include "python_coupling/helper/MplHelpers.h" + +# include "stencil/D2Q9.h" +# include "stencil/D3Q15.h" +# include "stencil/D3Q19.h" +# include "stencil/D3Q27.h" +# include "stencil/D3Q7.h" + +# include <typeinfo> + +# include "pybind11/pybind11.h" + +namespace walberla +{ +namespace field +{ +namespace internal +{ +namespace py = pybind11; + +//=================================================================================================================== +// +// createPackInfo Export +// +//=================================================================================================================== + +class PackInfoExporter +{ + public: + PackInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId, uint_t numberOfGhostLayers) + : blocks_(blocks), fieldId_(fieldId), numberOfGhostLayers_( numberOfGhostLayers ) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + typedef GhostLayerField<T, F_SIZE> GlField_T; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + { + if ( numberOfGhostLayers_ > 0 ) + { + resultPackInfo_ = py::cast(make_shared< field::communication::PackInfo< GlField_T > >(fieldId_, numberOfGhostLayers_)); + } + else + { + resultPackInfo_ = py::cast(make_shared< field::communication::PackInfo< GlField_T > >(fieldId_)); + } + } + } + py::object getResultPackInfo() + { + return resultPackInfo_; + } + + private: + py::object resultPackInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; + uint_t numberOfGhostLayers_; +}; + + +template<typename... FieldTypes> +static py::object PackInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & name, uint_t numberOfGhostLayers ) +{ + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< field::communication::PackInfo<GhostLayerField<real_t,1>> >( fieldID, numberOfGhostLayers ) ); + } + + PackInfoExporter exporter(blocks, fieldID, numberOfGhostLayers); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getResultPackInfo() ) { + throw py::value_error("Failed to create PackInfo"); + } + else { + return exporter.getResultPackInfo(); + } +} + +//=================================================================================================================== +// +// createMPIDatatypeInfo +// +//=================================================================================================================== + +class UniformMPIDatatypeInfoExporter +{ + public: + UniformMPIDatatypeInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId, uint_t numberOfGhostLayers) + : blocks_(blocks), fieldId_(fieldId), numberOfGhostLayers_( numberOfGhostLayers ) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + typedef GhostLayerField<T, F_SIZE> GlField_T; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + { + if ( numberOfGhostLayers_ > 0 ) + resultMPIDatatypeInfo_ = py::cast( make_shared< field::communication::UniformMPIDatatypeInfo<GlField_T> >( fieldId_, numberOfGhostLayers_ ) ); + else + resultMPIDatatypeInfo_ = py::cast( make_shared< field::communication::UniformMPIDatatypeInfo<GlField_T> >( fieldId_ ) ); + + } + } + py::object getResultUniformMPIDatatype() + { + return resultMPIDatatypeInfo_; + } + + private: + py::object resultMPIDatatypeInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; + uint_t numberOfGhostLayers_; +}; + + +template<typename... FieldTypes> +static py::object UniformMPIDatatypeInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & name, uint_t numberOfGhostLayers ) +{ + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< field::communication::UniformMPIDatatypeInfo<GhostLayerField<real_t,1>> >( fieldID, numberOfGhostLayers ) ); + } + + UniformMPIDatatypeInfoExporter exporter(blocks, fieldID, numberOfGhostLayers); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getResultUniformMPIDatatype() ) { + throw py::value_error("Failed to create UniformMPIDatatype"); + } + else { + return exporter.getResultUniformMPIDatatype(); + } +} + +//=================================================================================================================== +// +// exportStencilRestrictedPackInfo +// +//=================================================================================================================== + +template< typename T > +void exportStencilRestrictedPackInfo(py::module_& m) +{ + using field::communication::StencilRestrictedPackInfo; + { + typedef StencilRestrictedPackInfo< GhostLayerField< T, 9 >, stencil::D2Q9 > Pi; + py::class_< Pi, shared_ptr< Pi >, walberla::communication::UniformPackInfo >(m, "StencilRestrictedPackInfo_D2Q9"); + } + { + typedef StencilRestrictedPackInfo< GhostLayerField< T, 7 >, stencil::D3Q7 > Pi; + py::class_< Pi, shared_ptr< Pi >, walberla::communication::UniformPackInfo >(m, "StencilRestrictedPackInfo_D3Q7"); + } + { + typedef StencilRestrictedPackInfo< GhostLayerField< T, 15 >, stencil::D3Q15 > Pi; + py::class_< Pi, shared_ptr< Pi >, walberla::communication::UniformPackInfo >(m, + "StencilRestrictedPackInfo_D3Q15"); + } + { + typedef StencilRestrictedPackInfo< GhostLayerField< T, 19 >, stencil::D3Q19 > Pi; + py::class_< Pi, shared_ptr< Pi >, walberla::communication::UniformPackInfo >(m, + "StencilRestrictedPackInfo_D3Q19"); + } + { + typedef StencilRestrictedPackInfo< GhostLayerField< T, 27 >, stencil::D3Q27 > Pi; + py::class_< Pi, shared_ptr< Pi >, walberla::communication::UniformPackInfo >(m, + "StencilRestrictedPackInfo_D3Q27"); + } +} + +} // namespace internal + +namespace py = pybind11; +using namespace pybind11::literals; + +template< typename... FieldTypes > +void exportCommunicationClasses(py::module_& m) +{ + py::module_ m2 = m.def_submodule("field", "Field Extension of the waLBerla python bindings"); + internal::exportStencilRestrictedPackInfo< real_t >(m2); + + m2.def( + "createPackInfo", + [](const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName, uint_t numberOfGhostLayers ) { + return internal::PackInfoWrapper< FieldTypes... >(blocks, blockDataName, numberOfGhostLayers); + }, + "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); + + m2.def( + "createMPIDatatypeInfo", + [](const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName, uint_t numberOfGhostLayers ) { + return internal::UniformMPIDatatypeInfoWrapper< FieldTypes... >(blocks, blockDataName, numberOfGhostLayers); + }, + "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); +} + +} // namespace field +} // namespace walberla + +#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/python_coupling/export/FieldExport.impl.h b/src/python_coupling/export/FieldExport.impl.h new file mode 100644 index 000000000..ad9449849 --- /dev/null +++ b/src/python_coupling/export/FieldExport.impl.h @@ -0,0 +1,664 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file FieldExport.impl.h +//! \ingroup field +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== +#include "core/VectorTrait.h" +#include "core/logging/Logging.h" + +#include "field/AddToStorage.h" +#include "field/Field.h" +#include "field/FlagField.h" +#include "field/GhostLayerField.h" +#include "field/communication/PackInfo.h" +#include "field/communication/UniformMPIDatatypeInfo.h" +#include "field/vtk/FlagFieldMapping.h" +#include "field/vtk/VTKWriter.h" + +#include "python_coupling/PythonWrapper.h" +#include "python_coupling/helper/MplHelpers.h" +#include "python_coupling/helper/PybindHelper.h" + +#include <iostream> +#include <type_traits> + +#include "GatherExport.impl.h" +#include "pybind11/numpy.h" +#include <pybind11/stl.h> + +namespace walberla +{ +namespace field +{ + +//******************************************************************************************************************* +/*! Exports all Fields given in the Sequence +* +* Put only Fields in the sequence! The corresponding GhostLayerFields are exported automatically +* +* \warning Make sure that the same adaptor type is exported only once! +*/ +//******************************************************************************************************************* +template<typename... FieldTypes > +void exportFields(); + + + +//******************************************************************************************************************* +/*! Exports all GhostLayerFieldAdaptors given in the Sequence +* +* \warning Make sure that the same adaptor type is exported only once! +*/ +//******************************************************************************************************************* +template<typename... AdaptorTypes> +void exportGhostLayerFieldAdaptors(); + +template<typename AdaptorType> +void exportGhostLayerFieldAdaptor(); + +namespace internal +{ +namespace py = pybind11; + +template<class T> struct PythonFormatString { inline static char * get() { static char value [] = "B"; return value; } }; + +template<> struct PythonFormatString<double> { inline static char * get() { static char value [] = "d"; return value; } }; +template<> struct PythonFormatString<float> { inline static char * get() { static char value [] = "f"; return value; } }; +template<> struct PythonFormatString<unsigned short> { inline static char * get() { static char value [] = "H"; return value; } }; +template<> struct PythonFormatString<int> { inline static char * get() { static char value [] = "i"; return value; } }; +template<> struct PythonFormatString<unsigned int> { inline static char * get() { static char value [] = "I"; return value; } }; +template<> struct PythonFormatString<long> { inline static char * get() { static char value [] = "l"; return value; } }; +template<> struct PythonFormatString<unsigned long> { inline static char * get() { static char value [] = "L"; return value; } }; +template<> struct PythonFormatString<long long> { inline static char * get() { static char value [] = "q"; return value; } }; +template<> struct PythonFormatString<unsigned long long>{ inline static char * get() { static char value [] = "Q"; return value; } }; +template<> struct PythonFormatString<int8_t> { inline static char * get() { static char value [] = "c"; return value; } }; +template<> struct PythonFormatString<int16_t> { inline static char * get() { static char value [] = "h"; return value; } }; +template<> struct PythonFormatString<uint8_t> { inline static char * get() { static char value [] = "C"; return value; } }; + +//=================================================================================================================== +// +// Aligned Allocation +// +//=================================================================================================================== + +template< typename T > +shared_ptr< field::FieldAllocator< T > > getAllocator(uint_t alignment) +{ + if (alignment == 0) + return shared_ptr< field::FieldAllocator< T > >(); // leave to default - auto-detection of alignment + else if (alignment == 16) + return make_shared< field::AllocateAligned< T, 16 > >(); + else if (alignment == 32) + return make_shared< field::AllocateAligned< T, 32 > >(); + else if (alignment == 64) + return make_shared< field::AllocateAligned< T, 64 > >(); + else if (alignment == 128) + return make_shared< field::AllocateAligned< T, 128 > >(); + else + { + throw py::value_error("Alignment parameter has to be one of 0, 16, 32, 64, 128."); + return shared_ptr< field::FieldAllocator< T > >(); + } +} + +template< typename GhostLayerField_T > +class GhostLayerFieldDataHandling : public field::BlockDataHandling< GhostLayerField_T > +{ + public: + typedef typename GhostLayerField_T::value_type Value_T; + + GhostLayerFieldDataHandling(const weak_ptr< StructuredBlockStorage >& blocks, const uint_t nrOfGhostLayers, + const Value_T& initValue, const Layout layout, uint_t alignment = 0) + : blocks_(blocks), nrOfGhostLayers_(nrOfGhostLayers), initValue_(initValue), layout_(layout), + alignment_(alignment) + {} + + GhostLayerField_T* allocate(IBlock* const block) + { + auto blocks = blocks_.lock(); + WALBERLA_CHECK_NOT_NULLPTR(blocks, "Trying to access 'AlwaysInitializeBlockDataHandling' for a block " + "storage object that doesn't exist anymore"); + GhostLayerField_T* field = new GhostLayerField_T( + blocks->getNumberOfXCells(*block), blocks->getNumberOfYCells(*block), blocks->getNumberOfZCells(*block), + nrOfGhostLayers_, initValue_, layout_, getAllocator< Value_T >(alignment_)); + return field; + } + + GhostLayerField_T* reallocate(IBlock* const block) { return allocate(block); } + + private: + weak_ptr< StructuredBlockStorage > blocks_; + + uint_t nrOfGhostLayers_; + Value_T initValue_; + Layout layout_; + uint_t alignment_; +}; + +//=================================================================================================================== +// +// Field functions redefined for easier export +// +//=================================================================================================================== + +template< typename Field_T > +py::object field_size(const Field_T& field) +{ + return py::make_tuple(field.xSize(), field.ySize(), field.zSize(), field.fSize()); +} + +template< typename GlField_T > +py::tuple field_sizeWithGhostLayer(const GlField_T& field) +{ + return py::make_tuple(field.xSizeWithGhostLayer(), field.ySizeWithGhostLayer(), field.zSizeWithGhostLayer(), + field.fSize()); +} + +template< typename Field_T > +py::tuple field_allocSize(const Field_T& field) +{ + return py::make_tuple(field.xAllocSize(), field.yAllocSize(), field.zAllocSize(), field.fAllocSize()); +} + +template< typename Field_T > +py::tuple field_strides(const Field_T& field) +{ + return py::make_tuple(field.xStride(), field.yStride(), field.zStride(), field.fStride()); +} + +template< typename Field_T > +py::tuple field_offsets(const Field_T& field) +{ + return py::make_tuple(field.xOff(), field.yOff(), field.zOff()); +} + +template< typename Field_T > +py::object field_layout(const Field_T& f) +{ + return py::cast(f.layout()); +} + +template< typename Field_T > +void field_swapDataPointers(Field_T& f1, Field_T& f2) +{ + if (!f1.hasSameAllocSize(f2) || !f1.hasSameSize(f2) || f1.layout() != f2.layout()) + { + throw py::value_error("The data of fields with different sizes or layout cannot be swapped"); + } + f1.swapDataPointers(f2); +} + +template< typename Field_T > +py::object copyAdaptorToField(const Field_T& f) +{ + typedef GhostLayerField< typename Field_T::value_type, Field_T::F_SIZE > ResField; + auto res = make_shared< ResField >(f.xSize(), f.ySize(), f.zSize(), f.nrOfGhostLayers()); + + auto srcIt = f.beginWithGhostLayerXYZ(); + auto dstIt = res->beginWithGhostLayerXYZ(); + while (srcIt != f.end()) + { + for (cell_idx_t fCoord = 0; fCoord < cell_idx_c(Field_T::F_SIZE); ++fCoord) + dstIt.getF(fCoord) = srcIt.getF(fCoord); + + ++srcIt; + ++dstIt; + } + return py::cast(res); +} + +//=================================================================================================================== +// +// Field export +// +//=================================================================================================================== +template< typename Field_T > +py::array_t< typename Field_T::value_type > toNumpyArray(const Field_T& field) +{ + using T = typename Field_T::value_type; + const T* ptr = field.dataAt(0, 0, 0, 0); + + if (field.fSize() == 1) + { + return pybind11::array_t< T, 0 >({ field.xSize(), field.ySize(), field.zSize() }, + { static_cast< size_t >(field.xStride()) * sizeof(T), + static_cast< size_t >(field.yStride()) * sizeof(T), + static_cast< size_t >(field.zStride()) * sizeof(T) }, + ptr, py::cast(field)); + } + else + { + return pybind11::array_t< T, 0 >( + { field.xSize(), field.ySize(), field.zSize(), field.fSize() }, + { static_cast< size_t >(field.xStride()) * sizeof(T), static_cast< size_t >(field.yStride()) * sizeof(T), + static_cast< size_t >(field.zStride()) * sizeof(T), static_cast< size_t >(field.fStride()) * sizeof(T) }, + ptr, py::cast(field)); + } +} + +template< typename GlField_T > +py::array_t< typename GlField_T::value_type > toNumpyArrayWithGhostLayers(const GlField_T& field) +{ + using T = typename GlField_T::value_type; + const T* ptr = field.dataAt(-static_cast< cell_idx_t >(field.nrOfGhostLayers()), + -static_cast< cell_idx_t >(field.nrOfGhostLayers()), + -static_cast< cell_idx_t >(field.nrOfGhostLayers()), 0); + + + if (field.fSize() == 1) + { + return pybind11::array_t< T, 0 >({ field.xSizeWithGhostLayer(), field.ySizeWithGhostLayer(), field.zSizeWithGhostLayer() }, + { static_cast< size_t >(field.xStride()) * sizeof(T), + static_cast< size_t >(field.yStride()) * sizeof(T), + static_cast< size_t >(field.zStride()) * sizeof(T) }, + ptr, py::cast(field)); + } + else + { + return pybind11::array_t< T, 0 >( + { field.xSizeWithGhostLayer(), field.ySizeWithGhostLayer(), field.zSizeWithGhostLayer(), field.fSize() }, + { static_cast< size_t >(field.xStride()) * sizeof(T), static_cast< size_t >(field.yStride()) * sizeof(T), + static_cast< size_t >(field.zStride()) * sizeof(T), static_cast< size_t >(field.fStride()) * sizeof(T) }, + ptr, py::cast(field)); + } +} + + +struct FieldExporter +{ + FieldExporter(py::module_& m) : m_(m) {} + template< typename FieldType > + void operator()(python_coupling::NonCopyableWrap< FieldType >) const + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + typedef GhostLayerField< T, F_SIZE > GlField_T; + typedef Field< T, F_SIZE > Field_T; + + std::string data_type_name = PythonFormatString<T>::get(); + + std::string class_name = "Field_" + data_type_name + "_" + std::to_string(FieldType::F_SIZE); + + py::class_< Field_T, shared_ptr< Field_T > >(m_, class_name.c_str()) + .def_property_readonly("layout", &field_layout< Field_T >) + .def_property_readonly("size", &field_size< Field_T >) + .def_property_readonly("allocSize", &field_allocSize< Field_T >) + .def_property_readonly("strides", &field_strides< Field_T >) + .def_property_readonly("offsets", &field_offsets< Field_T >) + .def("clone", &Field_T::clone, py::return_value_policy::copy) + .def("cloneUninitialized", &Field_T::cloneUninitialized, py::return_value_policy::copy) + .def("swapDataPointers", &field_swapDataPointers< Field_T >) + .def("__getitem__", [](const Field_T& self, const py::object& index) { + return py::cast(self).attr("__array__")().attr("__getitem__")(index); + } ) + .def("__setitem__", [](const Field_T& self, const py::object& index, + const typename Field_T::value_type& value) { + py::cast(self).attr("__array__")().attr("__setitem__")(index, value); + } ) + .def("__array__", &toNumpyArray< Field_T >); + + std::string class_nameGL = + "GhostLayerField_" + data_type_name + "_" + std::to_string(FieldType::F_SIZE); + + py::class_< GlField_T, shared_ptr< GlField_T >, Field_T >(m_, class_nameGL.c_str()) + .def_property_readonly("sizeWithGhostLayer", &GlField_T::xSizeWithGhostLayer) + .def_property_readonly("nrOfGhostLayers", &GlField_T::nrOfGhostLayers) + .def("__array__", &toNumpyArrayWithGhostLayers< GlField_T >); + + using field::communication::PackInfo; + std::string FieldPackInfo_name = "FieldPackInfo_" + data_type_name + "_" + std::to_string(FieldType::F_SIZE); + py::class_< PackInfo< GlField_T >, shared_ptr< PackInfo< GlField_T > >, walberla::communication::UniformPackInfo >(m_, FieldPackInfo_name.c_str()); + + using field::communication::UniformMPIDatatypeInfo; + std::string FieldMPIDataTypeInfo_name = "FieldMPIDataTypeInfo_" + data_type_name + "_" + std::to_string(FieldType::F_SIZE); + py::class_< UniformMPIDatatypeInfo< GlField_T >, shared_ptr< UniformMPIDatatypeInfo< GlField_T > >, walberla::communication::UniformMPIDatatypeInfo >( + m_, FieldMPIDataTypeInfo_name.c_str()); + } + const py::module_& m_; +}; + + +struct FieldAllocatorExporter +{ + FieldAllocatorExporter(py::module_& m) : m_(m) {} + template< typename T > + void operator()(python_coupling::NonCopyableWrap< T >) const + { + std::string data_type_name = PythonFormatString<T>::get(); + std::string class_nameFieldAllocator = "FieldAllocator_" + data_type_name; + py::class_< FieldAllocator< T >, shared_ptr< FieldAllocator< T > > >(m_, class_nameFieldAllocator.c_str()) + .def("incrementReferenceCount", &FieldAllocator< T >::incrementReferenceCount) + .def("decrementReferenceCount", &FieldAllocator< T >::decrementReferenceCount); + } + const py::module_& m_; +}; + +//=================================================================================================================== +// +// addToStorage +// +//=================================================================================================================== + +class AddToStorageExporter +{ + public: + AddToStorageExporter(const shared_ptr< StructuredBlockForest >& blocks, const std::string& name, py::object& dtype, uint_t fs, + uint_t gl, Layout layout, real_t initValue, uint_t alignment) + : blocks_(blocks), name_(name), dtype_(dtype), fs_(fs), gl_(gl), layout_(layout), initValue_(initValue), alignment_(alignment), found_(false) + {} + + template< typename FieldType > + void operator()(python_coupling::NonCopyableWrap<FieldType>) const + { + using namespace py; + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + + if (F_SIZE != fs_) return; + if(python_coupling::isCppEqualToPythonType<T>(py::cast<std::string>(dtype_.attr("__name__")))) + { + typedef internal::GhostLayerFieldDataHandling< GhostLayerField< T, F_SIZE > > DataHandling; + auto dataHandling = walberla::make_shared< DataHandling >(blocks_, gl_, initValue_, layout_, alignment_); + blocks_->addBlockData(dataHandling, name_); + } + found_ = true; + } + + bool successful() const { return found_; } + + private: + shared_ptr< StructuredBlockStorage > blocks_; + std::string name_; + py::object dtype_; + uint_t fs_; + uint_t gl_; + Layout layout_; + real_t initValue_; + uint_t alignment_; + mutable bool found_; +}; + +template< typename... FieldTypes > +void addToStorage(const shared_ptr< StructuredBlockForest >& blocks, const std::string& name, py::object& dtype, + uint_t fs, uint_t gl, Layout layout, real_t initValue, uint_t alignment) +{ + using namespace py; + + auto result = make_shared< py::object >(); + AddToStorageExporter exporter(blocks, name, dtype, fs, gl, layout, initValue, alignment); + python_coupling::for_each_noncopyable_type< FieldTypes... >(exporter); + + if (!exporter.successful()) + { + throw py::value_error("Adding GhostLayerField failed. Maybe the data type and/or the fsize is not exported to python yet"); + } +} + +inline void addFlagFieldToStorage(const shared_ptr< StructuredBlockStorage >& blocks, const std::string& name, + uint_t nrOfBits, uint_t gl) +{ + if (nrOfBits == 8) + field::addFlagFieldToStorage< FlagField< uint8_t > >(blocks, name, gl); + else if (nrOfBits == 16) + field::addFlagFieldToStorage< FlagField< uint16_t > >(blocks, name, gl); + else if (nrOfBits == 32) + field::addFlagFieldToStorage< FlagField< uint32_t > >(blocks, name, gl); + else if (nrOfBits == 64) + field::addFlagFieldToStorage< FlagField< uint64_t > >(blocks, name, gl); + else + { + throw py::value_error("Allowed values for number of bits are: 8,16,32,64"); + } +} + +//=================================================================================================================== +// +// createField +// +//=================================================================================================================== + +class CreateFieldExporter +{ + public: + CreateFieldExporter( uint_t xs, uint_t ys, uint_t zs, uint_t fs, uint_t gl, + Layout layout, const py::object & dtype, uint_t alignment, + const shared_ptr<py::object> & resultPointer ) + : xs_( xs ), ys_(ys), zs_(zs), fs_(fs), gl_(gl), + layout_( layout), dtype_( dtype ), alignment_(alignment), resultPointer_( resultPointer ) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) const + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + + if( F_SIZE != fs_ ) + return; + + if(python_coupling::isCppEqualToPythonType<T>(py::cast<std::string>(dtype_.attr("__name__")))) + { + T initVal = T(); + *resultPointer_ = py::cast( make_shared< GhostLayerField<T, F_SIZE> >( xs_,ys_,zs_, gl_, initVal, layout_, + getAllocator<T>(alignment_))); + } + } + + private: + uint_t xs_; + uint_t ys_; + uint_t zs_; + uint_t fs_; + uint_t gl_; + Layout layout_; + py::object dtype_; + uint_t alignment_; + shared_ptr<py::object> resultPointer_; +}; + +template<typename... FieldTypes> +py::object createPythonField( std::array< uint_t, 4 > size, + py::object & dtype, + uint_t ghostLayers, + Layout layout, + uint_t alignment) +{ + uint_t xSize = size[0]; + uint_t ySize = size[1]; + uint_t zSize = size[2]; + uint_t fSize = size[3]; + + auto result = make_shared<py::none>(); + CreateFieldExporter exporter( xSize,ySize, zSize, fSize, ghostLayers, layout, dtype, alignment, result ); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( exporter ); + + return *result; +} + +//=================================================================================================================== +// +// createVTKWriter +// +//=================================================================================================================== + +class CreateVTKWriterExporter +{ + public: + CreateVTKWriterExporter( const shared_ptr<StructuredBlockForest> & blocks, + ConstBlockDataID fieldId, const std::string & vtkName) + : blocks_( blocks ), fieldId_(fieldId), vtkName_( vtkName ) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + writer_ = shared_ptr<field::VTKWriter<FieldType> >( new field::VTKWriter<FieldType>(fieldId_, vtkName_)); + } + + shared_ptr< vtk::BlockCellDataWriterInterface > getCreatedWriter() { + return writer_; + } + + private: + shared_ptr< vtk::BlockCellDataWriterInterface > writer_; + shared_ptr< StructuredBlockStorage > blocks_; + ConstBlockDataID fieldId_; + std::string vtkName_; +}; + + +template<typename... FieldTypes> +inline shared_ptr<vtk::BlockCellDataWriterInterface> createVTKWriter(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & name, + const std::string & nameInVtkOutput = "") +{ + std::string vtkName = nameInVtkOutput; + if( vtkName.empty()) + vtkName = name; + + if ( blocks->begin() == blocks->end() ) + return shared_ptr<vtk::BlockCellDataWriterInterface>(); + auto fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + CreateVTKWriterExporter exporter(blocks, fieldID, vtkName); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getCreatedWriter() ) { + throw py::value_error("Failed to create VTK writer"); + } + else { + return exporter.getCreatedWriter(); + } +} + + +//=================================================================================================================== +// +// createBinarizationFieldWriter +// +//=================================================================================================================== + +class CreateBinarizationVTKWriterExporter +{ + public: + CreateBinarizationVTKWriterExporter( const shared_ptr<StructuredBlockStorage> & blocks, + ConstBlockDataID fieldId, const std::string & vtkName, uint_t mask) + : blocks_( blocks ), fieldId_(fieldId), vtkName_( vtkName ), mask_(mask) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + { + typedef field::BinarizationFieldWriter< FieldType > Writer; + writer_ = shared_ptr< Writer >(new Writer(fieldId_, vtkName_, static_cast< typename FieldType::value_type >(mask_))); + } + } + + shared_ptr< vtk::BlockCellDataWriterInterface > getCreatedWriter() { + return writer_; + } + + private: + shared_ptr< vtk::BlockCellDataWriterInterface > writer_; + shared_ptr< StructuredBlockStorage > blocks_; + ConstBlockDataID fieldId_; + std::string vtkName_; + uint_t mask_; +}; + + +template<typename... FieldTypes> +inline shared_ptr<vtk::BlockCellDataWriterInterface> createBinarizationVTKWriter(const shared_ptr<StructuredBlockStorage> & blocks, + const std::string & name, + uint_t mask, + const std::string & nameInVtkOutput = "") +{ + std::string vtkName = nameInVtkOutput; + if( vtkName.empty()) + vtkName = name; + + if ( blocks->begin() == blocks->end() ) + return shared_ptr<vtk::BlockCellDataWriterInterface>(); + auto fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + + CreateBinarizationVTKWriterExporter exporter(blocks, fieldID, vtkName, mask); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getCreatedWriter() ) { + throw py::value_error("Failed to create binarization field writer"); + } + else { + return exporter.getCreatedWriter(); + } +} + +} // namespace internal + +namespace py = pybind11; +template< typename... FieldTypes > +void exportFields(py::module_& m) +{ + using namespace py; + + py::module_ m2 = m.def_submodule("field", "Field Extension of the waLBerla python bindings"); + + py::enum_< Layout >(m2, "Layout").value("fzyx", fzyx).value("zyxf", zyxf).export_values(); + + python_coupling::for_each_noncopyable_type< FieldTypes... >(internal::FieldExporter(m2)); + python_coupling::for_each_noncopyable_type< real_t, int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t >(internal::FieldAllocatorExporter(m2)); + + m2.def( + "createField", + [](std::array< uint_t, 4 > size, py::object & dtype, uint_t ghostLayers, Layout layout, uint_t alignment) { + return internal::createPythonField< FieldTypes... >(size, dtype, ghostLayers, layout, alignment); + }, + "size"_a, "dtype"_a, "ghostLayers"_a = uint_t(1), "layout"_a = zyxf, "alignment"_a = 0); + + m2.def( + "addToStorage", + [](const shared_ptr< StructuredBlockForest > & blocks, const std::string & name, py::object &dtype, uint_t fSize, + Layout layout, uint_t ghostLayers, real_t initValue, uint_t alignment) { + return internal::addToStorage< FieldTypes... >(blocks, name, dtype, fSize, ghostLayers, layout, initValue, alignment); + }, + "blocks"_a, "name"_a, "dtype"_a, "fSize"_a = 1, "layout"_a = zyxf, "ghostLayers"_a = uint_t(1), "initValue"_a = 0.0, "alignment"_a = 0); + + m2.def( "createVTKWriter", + [](const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, + const std::string & nameInVtkOutput = ""){ + return internal::createVTKWriter< FieldTypes... >(blocks, name, nameInVtkOutput); + }, + "blocks"_a, "name"_a, "nameInVtkOutput"_a="" ); + + + #define UintFields Field<uint8_t,1 >, Field<uint16_t, 1>, Field<uint32_t, 1>, Field<uint64_t, 1> + m2.def( "createBinarizationVTKWriter", + [](const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, + uint_t mask, const std::string & nameInVtkOutput = ""){ + return internal::createBinarizationVTKWriter< UintFields >(blocks, name, mask, nameInVtkOutput); + }, + "blocks"_a, "name"_a, "mask"_a, "nameInVtkOutput"_a="" ); + + +} + +} // namespace field +} // namespace walberla diff --git a/src/field/python/Exports.h b/src/python_coupling/export/FieldExports.h similarity index 63% rename from src/field/python/Exports.h rename to src/python_coupling/export/FieldExports.h index c07bad868..385ad4fe7 100644 --- a/src/field/python/Exports.h +++ b/src/python_coupling/export/FieldExports.h @@ -13,9 +13,10 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file Exports.h +//! \file FieldExports.h //! \ingroup field //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -26,10 +27,10 @@ #ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/helper/ModuleScope.h" -#include "FieldExport.h" -#include "GatherExport.h" -#include "CommunicationExport.h" +# include "python_coupling/PythonWrapper.h" + +# include "FieldCommunicationExport.h" +# include "FieldExport.impl.h" namespace walberla { namespace field { @@ -38,26 +39,17 @@ namespace field { //******************************************************************************************************************* /*! Exports the field types and corresponding function given in the type sequence to python * - * Automatically exports the Field, GhostLayerField and (if possible) the FlagField version, - * so it is enough to add the basic Field<> types to the sequence - * For fields that store and unsigned integer type and have an fSize of one, the FlagField is also exported + * Automatically exports the Field and GhostLayerField * - * Example: - \code - typedef boost::mpl::vector< Field<real_t,1>, - Field<uint16_t, 1> - Field<Vector3<real_t>, 1 > FieldVector; - \endcode - - * This exports the following types: + * For example, with the template arguments Field<real_t,1> and Field<uint16_t, 1>, + * this exports the following types: * - Field<real_t,1>, GhostLayerField<real_t,1> - * - Field<uint16_t,1>, GhostLayerField<uint16_t,1>, FlagField<uint16_t> - * - Field< Vector3<real_t>, 1 > , GhostLayerField< Vector3<real_t>, 1 > + * - Field<uint16_t,1>, GhostLayerField<uint16_t,1> * * Additionally the following free functions are exported - * - field.createField - * - field.createFlagField * - field.addToStorage + * - field.createVTKWriter + * - field.createBinarizationVTKWriter * - field.createPackInfo * - field.createMPIDatatypeInfo * @@ -66,14 +58,11 @@ namespace field { * \warning Make sure that the same field type is exported only once! */ //******************************************************************************************************************* - template<typename FieldTypes> - void exportModuleToPython() + template<typename... FieldTypes> + void exportModuleToPython(py::module_ &m) { - python_coupling::ModuleScope fieldModule( "field" ); - - exportFields<FieldTypes>(); - - exportCommunicationClasses<FieldTypes>(); + exportFields<FieldTypes...>(m); + exportCommunicationClasses<FieldTypes...>(m); } diff --git a/src/python_coupling/export/GatherExport.impl.h b/src/python_coupling/export/GatherExport.impl.h new file mode 100644 index 000000000..6d567f075 --- /dev/null +++ b/src/python_coupling/export/GatherExport.impl.h @@ -0,0 +1,141 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GatherExport.impl.h +//! \ingroup field +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "field/Gather.h" +#include "python_coupling/helper/MplHelpers.h" +#include "python_coupling/helper/BlockStorageExportHelpers.h" +#include "python_coupling/helper/SliceToCellInterval.h" + + +namespace walberla { +namespace field { + +//******************************************************************************************************************* +/*! Exports the gather functionality of waLberla +* +* With field.gather a corresponding field will the gathered to the specified process. This field can be viewed as a +* numpy array with field.toArrayOn all other porcesses an empty pybind11::object will be returned. +* +* \hint For large scale simulations it is also possible to provide a slice to keep the gathered data low! +*/ +//******************************************************************************************************************* +namespace py = pybind11; +template<typename... FieldTypes > +void exportGatherFunctions(py::module_ &m); + +namespace internal { +namespace py = pybind11; + //=================================================================================================================== + // + // Gather + // + //=================================================================================================================== + +class GatherExporter +{ + public: + GatherExporter(const shared_ptr<StructuredBlockForest> & blocks, ConstBlockDataID fieldId, + CellInterval boundingBox = CellInterval(), int targetRank = 0 ) + : blocks_( blocks ), fieldId_(fieldId), boundingBox_( boundingBox ), targetRank_(targetRank) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + typedef Field< typename FieldType::value_type, FieldType::F_SIZE > ResultField; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + { + auto result = make_shared< ResultField > ( 0,0,0 ); + field::gather< FieldType, ResultField > ( *result, blocks_, fieldId_, boundingBox_, targetRank_, MPI_COMM_WORLD ); + + if ( MPIManager::instance()->worldRank() == targetRank_ ) + resultField_ = py::cast(result); + else + resultField_ = py::none(); + + } + } + py::object getResultField() + { + return resultField_; + } + + private: + py::object resultField_; + shared_ptr< StructuredBlockStorage > blocks_; + ConstBlockDataID fieldId_; + std::string vtkName_; + CellInterval boundingBox_; + int targetRank_ ; +}; + + +template<typename... FieldTypes> +static py::object gatherWrapper(const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, + const py::tuple & slice, int targetRank = 0 ) +{ + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, name ); + CellInterval boundingBox = python_coupling::globalPythonSliceToCellInterval( blocks, slice ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this process the field::gather function can be called with any type + // however we have to call it, otherwise a deadlock occurs + auto result = make_shared< Field<real_t, 1> > ( 0,0,0 ); + field::gather< Field<real_t, 1>, Field<real_t, 1> > ( *result, blocks, fieldID, boundingBox, targetRank, MPI_COMM_WORLD ); + return py::none(); + } + + GatherExporter exporter(blocks, fieldID, boundingBox, targetRank); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + + if ( ! exporter.getResultField() ) { + throw py::value_error("Failed to gather Field"); + } + else { + return exporter.getResultField(); + } +} + +} // namespace internal + + +namespace py = pybind11; +using namespace pybind11::literals; +template<typename... FieldTypes > +void exportGatherFunctions(py::module_ &m) +{ + py::module_ m2 = m.def_submodule("field", "Field Extension of the waLBerla python bindings"); + + m2.def( + "gather", + [](const shared_ptr<StructuredBlockForest> & blocks, const std::string & name, + const py::tuple & slice, int targetRank = 0 ) { + return internal::gatherWrapper< FieldTypes... >(blocks, name, slice, targetRank); + }, + "blocks"_a, "name"_a, "slice"_a, "targetRank"_a = uint_t(0)); +} + +} // namespace moduleName +} // namespace walberla + + diff --git a/src/python_coupling/export/MPIExport.cpp b/src/python_coupling/export/MPIExport.cpp new file mode 100644 index 000000000..00e13dfdf --- /dev/null +++ b/src/python_coupling/export/MPIExport.cpp @@ -0,0 +1,278 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file MPIExports.cpp +//! \ingroup python_coupling +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#include "python_coupling/PythonWrapper.h" + +#ifdef WALBERLA_BUILD_WITH_PYTHON + +#include "python_coupling/helper/PythonIterableToStdVector.h" + +#include "core/mpi/MPIManager.h" +#include "core/mpi/Reduce.h" +#include "core/mpi/Gather.h" +#include "core/mpi/Broadcast.h" + +#include <vector> +#include "pybind11/stl.h" + +namespace py = pybind11; + + + + +namespace walberla { +namespace python_coupling { + + typedef std::vector<int64_t> IntStdVector; + typedef std::vector<real_t> RealStdVector; + typedef std::vector<std::string> StringStdVector; + + + //=================================================================================================================== + // + // MPIManager + // + //=================================================================================================================== + + + static int rank() { return MPIManager::instance()->rank(); } + static int worldRank() { return MPIManager::instance()->worldRank(); } + static int numProcesses() { return MPIManager::instance()->numProcesses(); } + static bool hasCartesianSetup() { return MPIManager::instance()->hasCartesianSetup(); } + static bool rankValid() { return MPIManager::instance()->rankValid(); } + + + + //=================================================================================================================== + // + // Broadcast + // + //=================================================================================================================== + + static py::object broadcast_string( py::object value, int sendRank ) //NOLINT + { + if ( py::isinstance<std::string>(value) ) + { + std::string extractedValue = py::cast< std::string >(value); + mpi::broadcastObject( extractedValue , sendRank ); + return py::cast( extractedValue ); + } + StringStdVector extractedValue = pythonIterableToStdVector< StringStdVector::value_type >( value ); + mpi::broadcastObject( extractedValue, sendRank ); + return py::cast( extractedValue ); + } + + static py::object broadcast_int( py::object value, int sendRank ) //NOLINT + { + if ( py::isinstance<int64_t>(value) ) + { + int64_t extractedValue = py::cast< int64_t >(value); + mpi::broadcastObject( extractedValue , sendRank ); + return py::cast( extractedValue ); + } + IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); + mpi::broadcastObject( extractedValue, sendRank ); + return py::cast( extractedValue ); + } + + static py::object broadcast_real( py::object value, int sendRank ) //NOLINT + { + if ( py::isinstance<real_t>(value) ) + { + real_t extractedValue = py::cast< real_t >(value); + mpi::broadcastObject( extractedValue , sendRank); + return py::cast( extractedValue ); + } + RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); + mpi::broadcastObject( extractedValue , sendRank); + return py::cast( extractedValue ); + } + + + //=================================================================================================================== + // + // Reduce + // + //=================================================================================================================== + + + static py::object reduce_int( py::object value, mpi::Operation op, int recvRank ) //NOLINT + { + if ( py::isinstance<int64_t>(value) ) + { + int64_t extractedValue = py::cast< int64_t >(value); + mpi::reduceInplace( extractedValue , op, recvRank ); + return py::cast( extractedValue ); + } + IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); + mpi::reduceInplace( extractedValue, op, recvRank ); + return py::cast( extractedValue ); + } + + static py::object reduce_real( py::object value, mpi::Operation op, int recvRank ) //NOLINT + { + if ( py::isinstance<real_t>(value) ) + { + real_t extractedValue = py::cast< real_t >(value); + mpi::reduceInplace( extractedValue , op, recvRank); + return py::cast( extractedValue ); + } + RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); + mpi::reduceInplace( extractedValue , op, recvRank); + return py::cast( extractedValue ); + } + + + static py::object allreduce_int( py::object value, mpi::Operation op ) //NOLINT + { + if ( py::isinstance<int64_t>(value) ) + { + int64_t extractedValue = py::cast< int64_t >(value); + mpi::allReduceInplace( extractedValue , op ); + return py::cast( extractedValue ); + } + IntStdVector extractedValue = pythonIterableToStdVector< IntStdVector::value_type >( value ); + mpi::allReduceInplace( extractedValue, op ); + return py::cast( extractedValue ); + } + + static py::object allreduce_real( py::object value, mpi::Operation op ) //NOLINT + { + if ( py::isinstance<real_t>(value) ) + { + real_t extractedValue = py::cast< real_t >(value); + mpi::allReduceInplace( extractedValue , op ); + return py::cast( extractedValue ); + } + RealStdVector extractedValue = pythonIterableToStdVector< RealStdVector::value_type >( value ); + mpi::allReduceInplace( extractedValue , op ); + return py::cast( extractedValue ); + } + + + //=================================================================================================================== + // + // Gather + // + //=================================================================================================================== + + static IntStdVector gather_int( py::object value, int recvRank ) //NOLINT + { + if ( ! py::isinstance<int64_t>(value) ) + { + throw py::cast_error("Could not gather the given value - unknown type"); + } + int64_t extractedValue = py::cast< int64_t >(value); + return mpi::gather( extractedValue , recvRank ); + } + + static RealStdVector gather_real( py::object value, int recvRank ) //NOLINT + { + if ( ! py::isinstance<real_t>(value) ) + { + throw py::cast_error("Could not gather the given value - unknown type"); + } + real_t extractedValue = py::cast< real_t >(value); + return mpi::gather( extractedValue , recvRank); + } + + + static IntStdVector allgather_int( py::object value ) //NOLINT + { + if ( ! py::isinstance<int64_t>(value) ) + { + throw py::cast_error("Could not gather the given value - unknown type"); + } + int64_t extractedValue = py::cast< int64_t >(value); + return mpi::allGather( extractedValue ); + } + + static RealStdVector allgather_real( py::object value ) //NOLINT + { + if ( ! py::isinstance<real_t>(value) ) + { + throw py::cast_error("Could not gather the given value - unknown type"); + } + real_t extractedValue = py::cast< real_t >(value); + return mpi::allGather( extractedValue ); + } + + + + //=================================================================================================================== + // + // Export + // + //=================================================================================================================== + + static void worldBarrier() + { + WALBERLA_MPI_WORLD_BARRIER(); + } + + + void exportMPI(py::module_ &m) + { + py::module_ m2 = m.def_submodule("mpi", "MPI Extension of the waLBerla python bindings"); + + m2.def( "rank" , &rank ); + m2.def( "worldRank" , &worldRank ); + m2.def( "numProcesses" , &numProcesses ); + m2.def( "hasCartesianSetup", &hasCartesianSetup); + m2.def( "rankValid" , &rankValid ); + m2.def( "worldBarrier" , &worldBarrier ); + + py::enum_<mpi::Operation>(m2, "Operation") + .value("MIN" , mpi::MIN ) + .value("MAX" , mpi::MAX ) + .value("SUM" , mpi::SUM ) + .value("PRODUCT", mpi::PRODUCT ) + .value("LOGICAL_AND", mpi::LOGICAL_AND ) + .value("BITWISE_AND", mpi::BITWISE_AND ) + .value("LOGICAL_OR", mpi::LOGICAL_OR ) + .value("BITWISE_OR", mpi::BITWISE_OR ) + .value("LOGICAL_XOR", mpi::LOGICAL_XOR ) + .value("BITWISE_XOR", mpi::BITWISE_XOR ) + .export_values(); + + m2.def( "broadcastInt", &broadcast_int); + m2.def( "broadcastReal", &broadcast_real); + m2.def( "broadcastString",&broadcast_string); + + m2.def( "reduceInt", &reduce_int); + m2.def( "reduceReal", &reduce_real); + m2.def( "allreduceInt", &allreduce_int ); + m2.def( "allreduceReal", &allreduce_real ); + + m2.def( "gatherInt", &gather_int); + m2.def( "gatherReal", &gather_real); + m2.def( "allgatherInt", &allgather_int ); + m2.def( "allgatherReal", &allgather_real ); + } + + + +} // namespace python_coupling +} // namespace walberla + + +#endif diff --git a/src/python_coupling/basic_exports/MPIExport.h b/src/python_coupling/export/MPIExport.h similarity index 93% rename from src/python_coupling/basic_exports/MPIExport.h rename to src/python_coupling/export/MPIExport.h index 8e15eb1e7..d1653a734 100644 --- a/src/python_coupling/basic_exports/MPIExport.h +++ b/src/python_coupling/export/MPIExport.h @@ -16,6 +16,7 @@ //! \file MPIExports.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -27,7 +28,7 @@ namespace python_coupling { - void exportMPI(); + void exportMPI(py::module_ &m); diff --git a/src/vtk/python/Exports.cpp b/src/python_coupling/export/VTKExport.cpp similarity index 53% rename from src/vtk/python/Exports.cpp rename to src/python_coupling/export/VTKExport.cpp index 719a6baeb..a8ab00e57 100644 --- a/src/vtk/python/Exports.cpp +++ b/src/python_coupling/export/VTKExport.cpp @@ -14,7 +14,7 @@ // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // //! \file Exports.cpp -//! \ingroup timeloop +//! \ingroup vtk //! \author Martin Bauer <martin.bauer@fau.de> // //====================================================================================================================== @@ -24,68 +24,59 @@ #ifdef WALBERLA_BUILD_WITH_PYTHON -#include "python_coupling/Manager.h" -#include "python_coupling/helper/ModuleScope.h" - +#include "blockforest/StructuredBlockForest.h" #include "vtk/VTKOutput.h" -using namespace boost::python; - - namespace walberla { namespace vtk { namespace internal { +namespace py = pybind11; - shared_ptr<VTKOutput> VTKOutput_create(const shared_ptr<StructuredBlockStorage> & sbs, const std::string & identifier, - const std::string & baseFolder, const std::string & executionFolder, - const bool binary, const bool littleEndian, const bool useMPIIO, - uint_t ghostLayers=0) - { - return createVTKOutput_BlockData(*sbs, identifier, 1, ghostLayers, false, baseFolder, executionFolder, - true, binary, littleEndian, useMPIIO, 0); - } - - void VTKOutput_write(const shared_ptr<VTKOutput> &vtkOut, int step) - { - if (step < 0) - { - PyErr_SetString(PyExc_ValueError, "Step parameter has to be positive"); - throw boost::python::error_already_set(); - } - vtkOut->forceWrite(uint_c(step)); - } +void VTKOutput_write(const shared_ptr<VTKOutput> &vtkOut, int step) +{ + if (step < 0) + { + throw py::value_error("Step parameter has to be positive"); + } + vtkOut->forceWrite(uint_c(step)); +} } // namespace internal - -void exportModuleToPython() +namespace py = pybind11; +using namespace pybind11::literals; +void exportModuleToPython(py::module_& m) { - python_coupling::ModuleScope timeloopModule( "vtk" ); + py::module_ m2 = m.def_submodule("vtk", "VTK Extension of the waLBerla python bindings"); void ( VTKOutput::*p_setSamplingResolution1) ( const real_t ) = &VTKOutput::setSamplingResolution; void ( VTKOutput::*p_setSamplingResolution2) ( const real_t, const real_t, const real_t ) = &VTKOutput::setSamplingResolution; - class_<BlockCellDataWriterInterface, //NOLINT - boost::noncopyable, - shared_ptr<BlockCellDataWriterInterface> > ("BlockCellDataWriterInterface", no_init) - ; + py::class_<BlockCellDataWriterInterface, shared_ptr<BlockCellDataWriterInterface> > (m2, "BlockCellDataWriterInterface"); + + m2.def( + "makeOutput", + [](const shared_ptr<StructuredBlockForest> & sbf, const std::string & identifier, + const std::string & baseFolder, const std::string & executionFolder, + const bool binary, const bool littleEndian, const bool useMPIIO, uint_t ghostLayers=0) + { + return createVTKOutput_BlockData(*sbf, identifier, 1, ghostLayers, false, baseFolder, executionFolder, + true, binary, littleEndian, useMPIIO, 0); + }, + "blocks"_a, "name"_a, "baseFolder"_a=".", "executionFolder"_a="vtk", "binary"_a=true, + "littleEndian"_a=true, "useMPIIO"_a=true, "ghostLayers"_a=0); - def("makeOutput", internal::VTKOutput_create, (arg("blocks"), arg("name"), arg("baseFolder")=".", - arg("executionFolder")="vtk", arg("binary")=true, - arg("littleEndian")=true, arg("useMPIIO")=true, - arg("ghostLayers")=0)); - class_<VTKOutput, shared_ptr<VTKOutput>, boost::noncopyable > ("VTKOutput", no_init) + py::class_<VTKOutput, shared_ptr<VTKOutput> > (m2, "VTKOutput") .def( "addCellDataWriter" , &VTKOutput::addCellDataWriter ) .def( "write" , &internal::VTKOutput_write ) .def( "__call__" , &internal::VTKOutput_write ) .def( "addAABBInclusionFilter", &VTKOutput::addAABBInclusionFilter ) .def( "addAABBExclusionFilter", &VTKOutput::addAABBExclusionFilter ) .def( "setSamplingResolution" , p_setSamplingResolution1 ) - .def( "setSamplingResolution" , p_setSamplingResolution2 ) - ; + .def( "setSamplingResolution" , p_setSamplingResolution2 ); } diff --git a/src/vtk/python/Exports.h b/src/python_coupling/export/VTKExport.h similarity index 65% rename from src/vtk/python/Exports.h rename to src/python_coupling/export/VTKExport.h index a14e864cd..d2f955cd7 100644 --- a/src/vtk/python/Exports.h +++ b/src/python_coupling/export/VTKExport.h @@ -16,6 +16,7 @@ //! \file Exports.h //! \ingroup vtk //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -25,11 +26,21 @@ #ifdef WALBERLA_BUILD_WITH_PYTHON +#include <pybind11/pybind11.h> namespace walberla { namespace vtk { +namespace py = pybind11; - void exportModuleToPython(); + //******************************************************************************************************************* + /*! Exports the vtk functionality of waLBerla + * + * With vtk.makeOutput a instance of VTKOutput will be provided for python. I can be used together with + * field.createVTKWriter and field.createBinarizationVTKWriter to get the VTK output + */ + //******************************************************************************************************************* + + void exportModuleToPython(py::module_ &m); } // namespace vtk } // namespace walberla diff --git a/src/python_coupling/helper/BlockStorageExportHelpers.cpp b/src/python_coupling/helper/BlockStorageExportHelpers.cpp index 4555f0e7d..016416d11 100644 --- a/src/python_coupling/helper/BlockStorageExportHelpers.cpp +++ b/src/python_coupling/helper/BlockStorageExportHelpers.cpp @@ -16,6 +16,7 @@ //! \file BlockStorageExportHelpers.cpp //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -25,24 +26,22 @@ namespace walberla { namespace python_coupling { - +namespace py = pybind11; #ifdef WALBERLA_BUILD_WITH_PYTHON void NoSuchBlockData::translate( const NoSuchBlockData & e ) { - PyErr_SetString(PyExc_RuntimeError, e.what() ); + throw py::cast_error(e.what()); } void BlockDataNotConvertible::translate( const BlockDataNotConvertible & e ) { - PyErr_SetString(PyExc_RuntimeError, e.what() ); + throw py::cast_error(e.what()); } #else -void NoSuchBlockData::translate( const NoSuchBlockData & ) { -} +void NoSuchBlockData::translate( const NoSuchBlockData & ) {} -void BlockDataNotConvertible::translate( const BlockDataNotConvertible & ) { -} +void BlockDataNotConvertible::translate( const BlockDataNotConvertible & ) {} #endif diff --git a/src/python_coupling/helper/BlockStorageExportHelpers.h b/src/python_coupling/helper/BlockStorageExportHelpers.h index 227b45474..0b41dd498 100644 --- a/src/python_coupling/helper/BlockStorageExportHelpers.h +++ b/src/python_coupling/helper/BlockStorageExportHelpers.h @@ -16,6 +16,7 @@ //! \file ExportHelpers.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -56,16 +57,6 @@ namespace python_coupling { #ifdef WALBERLA_BUILD_WITH_PYTHON - - template<typename UID, typename StringContainer> - Set< UID > uidSetFromStringContainer( const StringContainer & stringContainer ) - { - Set< UID > result; - result.insert( boost::python::stl_input_iterator< std::string >( stringContainer ), - boost::python::stl_input_iterator< std::string >( ) ); - return result; - } - template< typename FField> typename FField::value_type maskFromFlagList( const shared_ptr<StructuredBlockStorage> & bs, ConstBlockDataID flagFieldID, diff --git a/src/python_coupling/helper/BoostPythonHelpers.h b/src/python_coupling/helper/BoostPythonHelpers.h deleted file mode 100644 index 88c4fec8c..000000000 --- a/src/python_coupling/helper/BoostPythonHelpers.h +++ /dev/null @@ -1,106 +0,0 @@ - -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file CppPythonTypeEquality.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "core/DataTypes.h" -#include "python_coupling/PythonWrapper.h" - -#include <boost/python/converter/registry.hpp> - - -namespace walberla { -namespace python_coupling { - -#ifdef WALBERLA_CXX_COMPILER_IS_CLANG -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" -#endif - - // fallback - check boost python registry - template<typename T> - inline static bool isCppEqualToPythonType( PyTypeObject * obj) - { - boost::python::type_info info = boost::python::type_id<T>(); - const boost::python::converter::registration* reg = boost::python::converter::registry::query(info); - if (reg == NULL) - return false; - - try - { - reg->get_class_object(); - return ( reg->get_class_object() == obj ); - } - catch ( ... ) { - return false; - } - } - - // native data types - template<> inline bool isCppEqualToPythonType<bool> ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.bool_" - || n =="bool" ); } - - - template<> inline bool isCppEqualToPythonType<float> ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.float32" ); } - template<> bool inline isCppEqualToPythonType<double>( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.float64" - || n == "numpy.float_" - || n =="float"); } - - - template<> inline bool isCppEqualToPythonType<uint8_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.uint8" ); } - template<> inline bool isCppEqualToPythonType<uint16_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.uint16" ); } - template<> inline bool isCppEqualToPythonType<uint32_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.uint32" ); } - template<> inline bool isCppEqualToPythonType<uint64_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.uint64" ); } - - - template<> inline bool isCppEqualToPythonType<int8_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.int8" ); } - template<> inline bool isCppEqualToPythonType<int16_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.int16" ); } - template<> inline bool isCppEqualToPythonType<int32_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.int32" ); } - template<> inline bool isCppEqualToPythonType<int64_t > ( PyTypeObject * o) { std::string n( o->tp_name ); return ( n == "numpy.int64" - || n == "int" ); } - -#ifdef WALBERLA_CXX_COMPILER_IS_CLANG -#pragma clang diagnostic pop -#endif - - - template< typename T > - bool isTypeRegisteredInBoostPython( ) - { - boost::python::type_info info = boost::python::type_id<T>(); - const boost::python::converter::registration* reg = boost::python::converter::registry::query(info); - - try { - reg->get_class_object(); - } - catch( ... ) { - PyErr_Clear(); - return false; - } - PyErr_Clear(); - return (reg != NULL); - } - -} // namespace python_coupling -} // namespace walberla - - diff --git a/src/python_coupling/helper/ConfigFromDict.cpp b/src/python_coupling/helper/ConfigFromDict.cpp index 5755373ea..e35ca0fd5 100644 --- a/src/python_coupling/helper/ConfigFromDict.cpp +++ b/src/python_coupling/helper/ConfigFromDict.cpp @@ -16,6 +16,7 @@ //! \file ConfigFromDict.cpp //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -37,59 +38,55 @@ void handlePythonBooleans( std::string & value) { if ( value=="False") value="0"; } -void configFromPythonDict( config::Config::Block & block, boost::python::dict & pythonDict ) -{ - using namespace boost::python; - - boost::python::list keys = pythonDict.keys(); - keys.sort(); +namespace py = pybind11; - for (int i = 0; i < boost::python::len( keys ); ++i) +void configFromPythonDict( config::Config::Block & block, py::dict & pythonDict ) +{ + for (auto item : pythonDict) { - // Extract key - boost::python::extract<std::string> extracted_key( keys[i] ); - if( !extracted_key.check() ) { + // py::print(item); + if( py::isinstance<std::string>(item.first) ) { WALBERLA_LOG_WARNING( "Detected non-string key in waLBerla configuration" ); continue; } - std::string key = extracted_key; - // Extract value - extract<std::string> extracted_str_val ( pythonDict[key] ); - extract<dict> extracted_dict_val ( pythonDict[key] ); - extract<list> extracted_list_val ( pythonDict[key] ); - extract<tuple> extracted_tuple_val ( pythonDict[key] ); + std::string key = py::str(item.first); try { - if( extracted_str_val.check() ){ - std::string value = extracted_str_val; + if( py::isinstance<std::string>(item.second) ){ + std::string value = py::str(item.second); handlePythonBooleans( value ); block.addParameter( key, value ); } - else if ( extracted_dict_val.check() ) + else if ( py::isinstance<py::dict>(item.second) ) { walberla::config::Config::Block & childBlock = block.createBlock( key ); - dict childDict = extracted_dict_val; - configFromPythonDict( childBlock, childDict ); + py::dict childDict = py::dict(pythonDict[key.c_str()]); + configFromPythonDict( childBlock, childDict); } - else if ( extracted_list_val.check() ) + else if ( py::isinstance<py::list>(item.second) ) { - list childList = extracted_list_val; - for( int l=0; l < len( childList ); ++l ) { + py::list childList = py::list(pythonDict[key.c_str()]); + for(py::size_t i = 0; i < childList.size(); ++i){ walberla::config::Config::Block & childBlock = block.createBlock( key ); - dict d = extract<dict>( childList[l] ); + py::dict d = py::dict(childList[i]); configFromPythonDict( childBlock, d ); } } - else if ( extracted_tuple_val.check() ) + else if ( py::isinstance<py::tuple>(item.second) ) { std::stringstream ss; - tuple childTuple = extracted_tuple_val; + py::tuple childTuple = py::tuple(pythonDict[key.c_str()]); + + WALBERLA_ASSERT(len(childTuple) == 2 || len(childTuple) == 3, + "Config problem: " << key << ": Python tuples are mapped to walberla::Vector2 or Vector3. \n" << + "So only tuples of size 2 or 3 are supported! Option " << key << " is ignored ") + if ( len(childTuple) == 2 ) { - std::string e0 = extract<std::string>( childTuple[0].attr("__str__" )() ); - std::string e1 = extract<std::string>( childTuple[1].attr("__str__" )() ); + std::string e0 = py::str( childTuple[0].attr("__str__" )() ); + std::string e1 = py::str( childTuple[1].attr("__str__" )() ); handlePythonBooleans( e0 ); handlePythonBooleans( e1 ); ss << "< " << e0 << " , " << e1 << " > "; @@ -97,40 +94,32 @@ void configFromPythonDict( config::Config::Block & block, boost::python::dict & } else if ( len(childTuple) == 3) { - std::string e0 = extract<std::string>( childTuple[0].attr("__str__" )() ); - std::string e1 = extract<std::string>( childTuple[1].attr("__str__" )() ); - std::string e2 = extract<std::string>( childTuple[2].attr("__str__" )() ); + std::string e0 = py::str( childTuple[0].attr("__str__" )() ); + std::string e1 = py::str( childTuple[1].attr("__str__" )() ); + std::string e2 = py::str( childTuple[2].attr("__str__" )() ); handlePythonBooleans( e0 ); handlePythonBooleans( e1 ); handlePythonBooleans( e2 ); - ss << "< " << e0 << " , " << e1 << ", " << e2 << " > "; + ss << "< " << e0 << ", " << e1 << ", " << e2 << " > "; block.addParameter( key, ss.str() ); } - else - { - WALBERLA_LOG_WARNING( "Config problem: " << key << ": Python tuples are mapped to walberla::Vector2 or Vector3. \n" << - "So only tuples of size 2 or 3 are supported! Option " << key << " is ignored "); - - } } else { // if value is not a string try to convert it - std::string value = extract<std::string>( pythonDict[key].attr("__str__" )() ); + std::string value = py::str( pythonDict[key.c_str()].attr("__str__" )() ); block.addParameter ( key, value ); } } - catch ( error_already_set & ) { + catch ( py::error_already_set & ) { WALBERLA_LOG_WARNING ( "Error when reading configuration option " << key << ". Could not be converted to string."); } } } -shared_ptr<Config> configFromPythonDict( boost::python::dict & pythonDict ) +shared_ptr<Config> configFromPythonDict( py::dict & pythonDict ) { - using namespace boost::python; - shared_ptr<Config> config = make_shared<Config>(); configFromPythonDict( config->getWritableGlobalBlock(), pythonDict ); return config; diff --git a/src/python_coupling/helper/ConfigFromDict.h b/src/python_coupling/helper/ConfigFromDict.h index e1bef7f27..146ebf0fc 100644 --- a/src/python_coupling/helper/ConfigFromDict.h +++ b/src/python_coupling/helper/ConfigFromDict.h @@ -16,6 +16,7 @@ //! \file ConfigFromDict.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -37,7 +38,7 @@ namespace python_coupling { /*! Converts a python dictionary to a config::Block (recursively) */ //******************************************************************************************************************* - void configFromPythonDict( config::Config::Block & result, boost::python::dict & pythonDict ); + void configFromPythonDict( config::Config::Block & result, py::dict & pythonDict ); @@ -45,7 +46,7 @@ namespace python_coupling { /*! Converts a python dictionary to a waLBerla config object */ //******************************************************************************************************************* - shared_ptr<Config> configFromPythonDict( boost::python::dict & pythonDict ); + shared_ptr<Config> configFromPythonDict( py::dict & pythonDict ); diff --git a/src/python_coupling/helper/ExceptionHandling.h b/src/python_coupling/helper/ExceptionHandling.h deleted file mode 100644 index e17ebdfd0..000000000 --- a/src/python_coupling/helper/ExceptionHandling.h +++ /dev/null @@ -1,71 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ExceptionDecode.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include <string> - - -namespace walberla { -namespace python_coupling { - - // Call this function when a boost::python::already_set exception was caught - // returns formatted error string with traceback - inline std::string decodeException() - { - namespace bp = boost::python; - - PyObject *exc,*val,*tb; - - bp::object formatted_list, formatted; - PyErr_Fetch(&exc,&val,&tb); - PyErr_NormalizeException(&exc, &val, &tb); - bp::handle<> hexc( exc ); - bp::handle<> hval( bp::allow_null(val) ); - bp::handle<> htb ( bp::allow_null(tb) ); - bp::object traceback( bp::import("traceback")); - - if (!tb) { - bp::object format_exception_only( traceback.attr("format_exception_only")); - formatted_list = format_exception_only(hexc,hval); - } else { - bp::object format_exception(traceback.attr("format_exception")); - formatted_list = format_exception(hexc,hval,htb); - } - formatted = bp::str("").join(formatted_list); - return bp::extract<std::string>(formatted); - } - - - inline void terminateOnPythonException( const std::string message ) - { - if (PyErr_Occurred()) { - std::string decodedException = decodeException(); - WALBERLA_ABORT_NO_DEBUG_INFO( message << "\n\n" << decodedException ); - } - WALBERLA_ABORT_NO_DEBUG_INFO( message << " (unable to decode Python exception) " ); - } - - -} // namespace python_coupling -} // namespace walberla - - diff --git a/src/python_coupling/helper/ModuleInit.cpp b/src/python_coupling/helper/ModuleInit.cpp index e917ff50b..3198acfc3 100644 --- a/src/python_coupling/helper/ModuleInit.cpp +++ b/src/python_coupling/helper/ModuleInit.cpp @@ -16,14 +16,14 @@ //! \file ModuleInit.cpp //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #include "ModuleInit.h" -#include "waLBerlaDefinitions.h" +#include "core/debug/CheckFunctions.h" #include "core/mpi/MPIManager.h" #include "core/Abort.h" -#include "core/debug/CheckFunctions.h" // Workaround for OpenMPI library: it dynamically loads plugins which causes trouble when walberla itself is a shared lib #if defined(OPEN_MPI) && !defined(_WIN32) && OMPI_MAJOR_VERSION < 3 diff --git a/src/python_coupling/helper/ModuleInit.h b/src/python_coupling/helper/ModuleInit.h index e771bb86c..e85c45d6c 100644 --- a/src/python_coupling/helper/ModuleInit.h +++ b/src/python_coupling/helper/ModuleInit.h @@ -16,6 +16,7 @@ //! \file ModuleInit.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== diff --git a/src/python_coupling/helper/ModuleScope.h b/src/python_coupling/helper/ModuleScope.h deleted file mode 100644 index 09a619781..000000000 --- a/src/python_coupling/helper/ModuleScope.h +++ /dev/null @@ -1,56 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file ModuleScope.h -//! \ingroup python_coupling -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "python_coupling/PythonWrapper.h" - -#include <string> - -namespace walberla { -namespace python_coupling { - - - class ModuleScope : public boost::python::scope - { - public: - ModuleScope( const std::string & name) - : boost::python::scope ( ModuleScope::createNew( name ) ) - {} - - private: - static boost::python::object createNew ( const std::string & name ) - { - using namespace boost::python; - object module( handle<>( borrowed(PyImport_AddModule( name.c_str() ) ) ) ); - scope().attr( name.c_str() ) = module; - return module; - } - - }; - - - - -} // namespace python_coupling -} // namespace walberla - - diff --git a/src/python_coupling/helper/MplHelpers.h b/src/python_coupling/helper/MplHelpers.h index d9b008664..0a5a1d9bd 100644 --- a/src/python_coupling/helper/MplHelpers.h +++ b/src/python_coupling/helper/MplHelpers.h @@ -16,6 +16,7 @@ //! \file MplHelpers.h //! \ingroup python_export //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== @@ -23,11 +24,6 @@ #include "domain_decomposition/IBlock.h" -#include <boost/mpl/for_each.hpp> -#include <boost/mpl/lambda.hpp> -#include <boost/mpl/pair.hpp> -#include <boost/mpl/transform.hpp> - #include <functional> #include <map> @@ -37,23 +33,6 @@ namespace walberla { namespace python_coupling { -template <typename V, typename T, typename Result> -struct list_of_pairs - : boost::mpl::fold<V, Result, - boost::mpl::push_back<boost::mpl::_1, boost::mpl::pair<T, boost::mpl::_2> > > -{}; - -template<typename V1, typename V2> -struct combine_vectors -: boost::mpl::fold< - V1, - boost::mpl::vector<>, - boost::mpl::lambda<list_of_pairs<V2,boost::mpl::_2, boost::mpl::_1> > ->::type -{}; - - - template <typename T> struct NonCopyableWrap {}; @@ -78,15 +57,20 @@ struct NonCopyableWrap {}; -template< typename Sequence, typename F > +template< typename F > +void for_each_noncopyable_type( const F & ) +{} + +template< typename Type, typename... Types, typename F > void for_each_noncopyable_type( const F & f) { - boost::mpl::for_each< Sequence, NonCopyableWrap< boost::mpl::placeholders::_1> > ( f ); + f(NonCopyableWrap<Type>()); + for_each_noncopyable_type<Types...>(f); } -template<typename FieldTypeList, typename Exporter> +template<typename Exporter, typename... FieldTypes> class Dispatcher { public: @@ -102,7 +86,7 @@ public: return map_[ blockDataID ]; Exporter exporter( block_, blockDataID ); - for_each_noncopyable_type< FieldTypeList> ( std::ref(exporter) ); + for_each_noncopyable_type< FieldTypes...> ( std::ref(exporter) ); map_[ blockDataID ] = exporter.result; return exporter.result; } diff --git a/src/python_coupling/helper/OwningIterator.h b/src/python_coupling/helper/OwningIterator.h new file mode 100644 index 000000000..f384acca4 --- /dev/null +++ b/src/python_coupling/helper/OwningIterator.h @@ -0,0 +1,74 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file OwningIterator.h +//! \ingroup python_coupling +//! \author Michael Kuron <mkuron@icp.uni-stuttgart.de> +// +//====================================================================================================================== + +#pragma once + +#include <mutex> +#include <pybind11/pybind11.h> + +namespace walberla { +namespace python_coupling { + +namespace py = pybind11; + +namespace detail { + +template <typename T, py::return_value_policy Policy> +struct owning_iterator_state { + owning_iterator_state(T _obj) + : obj(_obj), it(obj.begin()), first_or_done(true) {} + T obj; + typename T::iterator it; + bool first_or_done; + static std::once_flag registered; +}; + +template <typename T, py::return_value_policy Policy> +std::once_flag owning_iterator_state<T, Policy>::registered; + +} // namespace detail + +template <py::return_value_policy Policy = py::return_value_policy::reference_internal, + typename T> +py::iterator make_owning_iterator(T obj) { + using state = detail::owning_iterator_state<T, Policy>; + + std::call_once(state::registered, []() { + py::class_<state>(py::handle(), "owning_iterator", py::module_local()) + .def("__iter__", [](state &s) -> state& { return s; }) + .def("__next__", [](state &s) -> typename T::value_type { + if (!s.first_or_done) + ++s.it; + else + s.first_or_done = false; + if (s.it == s.obj.end()) { + s.first_or_done = true; + throw py::stop_iteration(); + } + return *s.it; + }, py::keep_alive< 0, 1 >(), Policy); + }); + + return cast(state(obj)); +} + +} // namespace python_coupling +} // namespace walberla diff --git a/src/python_coupling/helper/PybindHelper.h b/src/python_coupling/helper/PybindHelper.h new file mode 100644 index 000000000..d43c560cc --- /dev/null +++ b/src/python_coupling/helper/PybindHelper.h @@ -0,0 +1,65 @@ + +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file CppPythonTypeEquality.h +//! \ingroup python_coupling +//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "core/DataTypes.h" +#include "python_coupling/PythonWrapper.h" + +namespace walberla { +namespace python_coupling { + +#ifdef WALBERLA_CXX_COMPILER_IS_CLANG +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" +#endif + +// fallback - check for bool +template<typename T> +inline static bool isCppEqualToPythonType( std::string n ) +{ + return ( n == "numpy.bool_" || n =="bool" ); +} + +// native data types +template<> inline bool isCppEqualToPythonType<float> ( std::string n) {return ( n == "numpy.float32" || n =="float32" );} +template<> inline bool isCppEqualToPythonType<double>( std::string n) {return ( n == "numpy.float64" || n == "numpy.float_" || n =="float64" || n=="float");} + + +template<> inline bool isCppEqualToPythonType<uint8_t > ( std::string n) {return ( n == "numpy.uint8" || n =="uint8" );} +template<> inline bool isCppEqualToPythonType<uint16_t > ( std::string n) {return ( n == "numpy.uint16"|| n =="uint16" );} +template<> inline bool isCppEqualToPythonType<uint32_t > ( std::string n) {return ( n == "numpy.uint32"|| n =="uint32" );} +template<> inline bool isCppEqualToPythonType<uint64_t > ( std::string n) {return ( n == "numpy.uint64"|| n =="uint64" );} + + +template<> inline bool isCppEqualToPythonType<int8_t > ( std::string n) {return ( n == "numpy.int8" || n =="int8");} +template<> inline bool isCppEqualToPythonType<int16_t > ( std::string n) {return ( n == "numpy.int16" || n =="int16");} +template<> inline bool isCppEqualToPythonType<int32_t > ( std::string n) {return ( n == "numpy.int32" || n =="int32");} +template<> inline bool isCppEqualToPythonType<int64_t > ( std::string n) {return ( n == "numpy.int64" || n =="int64" || n == "int" );} + +#ifdef WALBERLA_CXX_COMPILER_IS_CLANG +#pragma clang diagnostic pop +#endif + +} // namespace python_coupling +} // namespace walberla diff --git a/src/python_coupling/helper/PythonIterableToStdVector.h b/src/python_coupling/helper/PythonIterableToStdVector.h index 5a759aedf..71583ec21 100644 --- a/src/python_coupling/helper/PythonIterableToStdVector.h +++ b/src/python_coupling/helper/PythonIterableToStdVector.h @@ -16,26 +16,30 @@ //! \file PythonIterableToStdVector.h.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #pragma once #include <vector> +#include "pybind11/numpy.h" namespace walberla { namespace python_coupling { +namespace py = pybind11; template< typename T > + inline -std::vector< T > pythonIterableToStdVector( const boost::python::object& iterable ) +std::vector< T > pythonIterableToStdVector( const py::object& iterable ) { - return std::vector< T >( boost::python::stl_input_iterator< T >( iterable ), - boost::python::stl_input_iterator< T >( ) ); + return py::cast<std::vector<T>>(py::array(iterable)); } + } // namespace python_coupling } // namespace walberla diff --git a/src/python_coupling/helper/SharedPtrDeleter.h b/src/python_coupling/helper/SharedPtrDeleter.h deleted file mode 100644 index a946cc038..000000000 --- a/src/python_coupling/helper/SharedPtrDeleter.h +++ /dev/null @@ -1,65 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file SharedPtrDeleter.h -//! \ingroup python_export -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "python_coupling/PythonWrapper.h" - -namespace walberla { -namespace python_coupling { - - -namespace internal -{ - -template<typename T> -class SharedPtrDeleterTiedToPythonObject -{ -public: - SharedPtrDeleterTiedToPythonObject( PyObject *object ) : object_( object ) - { - } - - void operator()( T * ) - { - Py_DECREF( object_ ); - } - -private: - PyObject *object_; -}; - -} // namespace internal - - -template<typename T> -shared_ptr<T> createSharedPtrFromPythonObject(boost::python::object pythonObject) { - T * ptr = boost::python::extract<T*>( pythonObject); - auto deleter = internal::SharedPtrDeleterTiedToPythonObject<T>(pythonObject.ptr()); - Py_INCREF(pythonObject.ptr()); - return shared_ptr<T>(ptr, deleter); -} - - -} // namespace python_coupling -} // namespace walberla - - diff --git a/src/python_coupling/helper/SliceToCellInterval.h b/src/python_coupling/helper/SliceToCellInterval.h index d8ce96829..d988c1c74 100644 --- a/src/python_coupling/helper/SliceToCellInterval.h +++ b/src/python_coupling/helper/SliceToCellInterval.h @@ -16,205 +16,94 @@ //! \file SliceToCellInterval.h //! \ingroup python_coupling //! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #pragma once -#include "python_coupling/PythonWrapper.h" #include "core/cell/CellInterval.h" -#include "domain_decomposition/StructuredBlockStorage.h" -#include <boost/python/slice.hpp> - -namespace walberla { -namespace python_coupling { - - - namespace internal - { - inline cell_idx_t normalizeIdx( boost::python::object pyIndex, uint_t coordinateSize ) - { - using namespace boost::python; - cell_idx_t index; - if ( extract<cell_idx_t>( pyIndex ).check() ) - index = extract<cell_idx_t> ( pyIndex ); - else if ( extract<double>( pyIndex ).check() ) - index = cell_idx_c( double ( extract<double>( pyIndex ) ) * double( coordinateSize) ); - else { - PyErr_SetString( PyExc_IndexError, "Incompatible index data type" ); - throw error_already_set(); - } - - if ( index < 0 ) - return cell_idx_c(coordinateSize) + 1 + index; - else - return index; - } - - } // namespace internal +#include "domain_decomposition/StructuredBlockStorage.h" +#include "python_coupling/PythonWrapper.h" +namespace py = pybind11; +namespace walberla +{ +namespace python_coupling +{ +namespace internal +{ +inline cell_idx_t normalizeIdx(py::object pyIndex, uint_t coordinateSize) +{ + cell_idx_t index; + + try { + index = py::cast< cell_idx_t >(pyIndex); + } + catch (py::error_already_set & ){ + throw py::cast_error("Incompatible index data type"); + } - //******************************************************************************************************************* - /*! Creates a CellInterval as subset from the complete domain-cell-bounding-box based on a Python slice - * - * Example: Python Slice: [ :, 3, -1 ] and a domain size of ( 3,4,5 ) - * - x coordinate is the complete valid x-range indicated by the semicolon: i.e. [0,3) - * - y coordinate is just a normal index i.e. the range from [3,4) - * - z coordiante is the first valid coordinate from the back [4,5) - * - * Python slices are tuples with slice classes as entry. Each slice has start, stop and step. - * Steps are not supported since they can not be encoded in a CellInterval - */ - //******************************************************************************************************************* - inline CellInterval globalPythonSliceToCellInterval( const shared_ptr<StructuredBlockStorage> & blocks, - boost::python::tuple indexTuple ) + if (index < 0) + return cell_idx_c(coordinateSize) + 1 + index; + else + return index; +} + +} // namespace internal + +//******************************************************************************************************************* +/*! Creates a CellInterval as subset from the complete domain-cell-bounding-box based on a Python slice + * + * Example: Python Slice: [ :, 3, -1 ] and a domain size of ( 3,4,5 ) + * - x coordinate is the complete valid x-range indicated by the semicolon: i.e. [0,3) + * - y coordinate is just a normal index i.e. the range from [3,4) + * - z coordiante is the first valid coordinate from the back [4,5) + * + * Python slices are tuples with slice classes as entry. Each slice has start, stop and step. + * Steps are not supported since they can not be encoded in a CellInterval + */ +//******************************************************************************************************************* +inline CellInterval globalPythonSliceToCellInterval(const shared_ptr< StructuredBlockStorage >& blocks, + py::tuple indexTuple) +{ + using internal::normalizeIdx; + + CellInterval bounds = blocks->getDomainCellBB(); + + if (len(indexTuple) != 3) { - using namespace boost::python; - using internal::normalizeIdx; - - CellInterval bounds = blocks->getDomainCellBB(); - - if ( len(indexTuple) != 3 ) - { - PyErr_SetString( PyExc_IndexError, "Slice needs three components" ); - throw error_already_set(); - } - - CellInterval interval; - for( uint_t i=0; i<3; ++i ) - { - if( ! extract< slice >(indexTuple[i]).check() ) - { - cell_idx_t idx = normalizeIdx( indexTuple[i], uint_c( bounds.max()[i] ) ); - interval.min()[i] = idx; - interval.max()[i] = idx; - } - else if ( extract< slice >(indexTuple[i]).check() ) - { - slice s = extract< slice >(indexTuple[i]); - - // Min - if ( s.start() == object() ) - interval.min()[i] = bounds.min()[i]; - else - interval.min()[i] = normalizeIdx( s.start(), uint_c( bounds.max()[i] ) ); - - // Max - if ( s.stop() == object() ) - interval.max()[i] = bounds.max()[i]; - else - interval.max()[i] = normalizeIdx( s.stop(), uint_c( bounds.max()[i] ) ); - - if ( s.step() != object() ) { - PyErr_SetString( PyExc_IndexError, "Steps in slice not supported." ); - throw error_already_set(); - } - } - } - return interval; + throw py::index_error("Slice needs three components"); } - - - //******************************************************************************************************************* - /*! Creates a CellInterval based on a Python Slice as subset of a field - * - * Similar to globalPythonSliceToCellInterval() with the following additional features: - * - slice may have a forth component: [ :, 3, -1, 'g' ] with the only valid entry 'g' for ghost layers - * - if this ghost layer marker is present, coordinate 0 addresses the outermost ghost layer, otherwise the - * first inner cell is addressed - */ - //******************************************************************************************************************* - template<typename Field_T> - CellInterval localPythonSliceToCellInterval( const Field_T & field, - boost::python::tuple indexTuple ) + CellInterval interval; + for (uint_t i = 0; i < 3; ++i) { - using namespace boost::python; - using internal::normalizeIdx; - - bool withGhostLayer=false; - - if ( len(indexTuple) != 3 ) - { - if ( len(indexTuple) == 4 ) - { - std::string marker = extract<std::string>( indexTuple[3]); - if ( marker == std::string("g") ) - withGhostLayer = true; - else - { - PyErr_SetString( PyExc_IndexError, "Unknown marker in slice" ); - throw error_already_set(); - } - } - else - { - PyErr_SetString( PyExc_IndexError, "Slice needs three components ( + optional ghost layer marker )" ); - throw error_already_set(); - } - } - - cell_idx_t gl = cell_idx_c( field.nrOfGhostLayers() ); - - CellInterval bounds;; - if ( withGhostLayer ) + if (!py::isinstance< py::slice >(indexTuple[i])) { - bounds = field.xyzSizeWithGhostLayer(); - bounds.shift( gl,gl,gl ); + cell_idx_t idx = normalizeIdx(indexTuple[i], uint_c(bounds.max()[i])); + interval.min()[i] = idx; + interval.max()[i] = idx; } - else - bounds = field.xyzSize(); - - - CellInterval interval; - - for( uint_t i=0; i<3; ++i ) + else if (py::isinstance< py::slice >(indexTuple[i])) { - if( ! extract< slice >(indexTuple[i]).check() ) - { - interval.min()[i] = normalizeIdx( indexTuple[i], uint_c(bounds.max()[i]) ); - interval.max()[i] = normalizeIdx( indexTuple[i], uint_c(bounds.max()[i]) ); - } + py::slice s = py::cast< py::slice >(indexTuple[i]); + // Min + if ( py::isinstance< py::none >(s.attr("start")) ) + interval.min()[i] = bounds.min()[i]; else - { - slice s = extract< slice >(indexTuple[i]); + interval.min()[i] = normalizeIdx( s.attr("start"), uint_c( bounds.min()[i] ) ); - // Min - if ( s.start() == object() ) - interval.min()[i] = bounds.min()[i]; - else - interval.min()[i] = normalizeIdx( s.start(), uint_c(bounds.max()[i]) ); - - // Max - if ( s.stop() == object() ) - interval.max()[i] = bounds.max()[i]; - else - interval.max()[i] = normalizeIdx( s.stop(), uint_c(bounds.max()[i]) ); - - if ( s.step() != object() ) { - PyErr_SetString( PyExc_IndexError, "Steps in slice not supported." ); - throw error_already_set(); - } - } - } - - if ( withGhostLayer ) - interval.shift( -gl,-gl,-gl ); - - // Range check - if ( ! field.xyzAllocSize().contains( interval ) ) { - PyErr_SetString( PyExc_IndexError, "Index out of bounds." ); - throw error_already_set(); + // Max + if ( py::isinstance< py::none >(s.attr("stop")) ) + interval.max()[i] = bounds.max()[i]; + else + interval.max()[i] = normalizeIdx( s.attr("stop"), uint_c( bounds.max()[i] ) ); } - - return interval; } - - - + return interval; +} } // namespace python_coupling } // namespace walberla - - diff --git a/src/timeloop/python/Exports.cpp b/src/timeloop/python/Exports.cpp deleted file mode 100644 index 3411e7f29..000000000 --- a/src/timeloop/python/Exports.cpp +++ /dev/null @@ -1,89 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.cpp -//! \ingroup timeloop -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -// Do not reorder includes - the include order is important -#include "python_coupling/PythonWrapper.h" - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -#include "python_coupling/Manager.h" -#include "python_coupling/helper/ModuleScope.h" - -#include "timeloop/Timeloop.h" -#include "timeloop/SweepTimeloop.h" - -using namespace boost::python; - - -namespace walberla { -namespace timeloop { - -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wconversion" -#endif -struct ITimeloopWrap : public ITimeloop, public wrapper<ITimeloop> -{ - void run() override { this->get_override( "run" )(); } - void singleStep() override { this->get_override( "singleStep" )(); } - void stop() override { this->get_override( "stop" )(); } - void synchronizedStop( bool s ) override { this->get_override( "synchronizedStop" )(s); } - void setCurrentTimeStep( uint_t ts) override { this->get_override( "setCurrentTimeStep" )(ts); } - uint_t getCurrentTimeStep() const override { return this->get_override( "getCurrentTimeStep" )(); } - uint_t getNrOfTimeSteps() const override { return this->get_override( "getNrOfTimeSteps" )(); } -}; - -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#pragma GCC diagnostic pop -#endif - -void exportModuleToPython() -{ - python_coupling::ModuleScope timeloopModule( "timeloop" ); - - void ( Timeloop::*p_run1) ( const bool ) = &Timeloop::run; - void ( Timeloop::*p_run2) ( WcTimingPool & , const bool ) = &Timeloop::run; - - class_<ITimeloopWrap, boost::noncopyable > ("ITimeloop" ) - .def( "getCurrentTimeStep", pure_virtual( &ITimeloop::getCurrentTimeStep ) ) - .def( "getNrOfTimeSteps", pure_virtual( &ITimeloop::getNrOfTimeSteps ) ) - .def( "stop", pure_virtual( &ITimeloop::stop ) ) - .def( "synchronizedStop", pure_virtual( &ITimeloop::synchronizedStop ) ) - .def( "run", pure_virtual( &ITimeloop::run ) ) - ; - - class_<Timeloop, bases<ITimeloop>, boost::noncopyable>( "CppTimeloop", no_init ) - .def( "run", p_run1, args("logTimeStep") = true ) - .def( "run", p_run2, ( args("timingPool"), args("logTimeStep") = true ) ) - ; - class_< SweepTimeloop , bases<Timeloop>, boost::noncopyable > ( "CppSweepTimeloop", no_init ) - .def( init< const shared_ptr<StructuredBlockStorage> & , uint_t > () ) - ; - -} - - -} // namespace timeloop -} // namespace walberla - - -#endif //WALBERLA_BUILD_WITH_PYTHON - diff --git a/src/timeloop/python/Exports.h b/src/timeloop/python/Exports.h deleted file mode 100644 index 4126ed455..000000000 --- a/src/timeloop/python/Exports.h +++ /dev/null @@ -1,41 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Exports.h -//! \ingroup timeloop -//! \author Martin Bauer <martin.bauer@fau.de> -// -//====================================================================================================================== - -#pragma once - -#include "waLBerlaDefinitions.h" - - -#ifdef WALBERLA_BUILD_WITH_PYTHON - -namespace walberla { -namespace timeloop { - - - - void exportModuleToPython(); - - -} // namespace timeloop -} // namespace walberla - - -#endif // WALBERLA_BUILD_WITH_PYTHON diff --git a/src/vtk/CMakeLists.txt b/src/vtk/CMakeLists.txt index a3b6bf30e..6a12fce9b 100644 --- a/src/vtk/CMakeLists.txt +++ b/src/vtk/CMakeLists.txt @@ -4,6 +4,6 @@ # ################################################################################################### -waLBerla_add_module( DEPENDS core domain_decomposition python_coupling ) +waLBerla_add_module( DEPENDS core blockforest domain_decomposition python_coupling ) ################################################################################################### diff --git a/src/walberla.h b/src/walberla.h index c6e9858ed..7136333e4 100644 --- a/src/walberla.h +++ b/src/walberla.h @@ -34,7 +34,6 @@ #include "pde/all.h" #include "pe_coupling/all.h" #include "postprocessing/all.h" -#include "python_coupling/all.h" #include "stencil/all.h" #include "timeloop/all.h" #include "vtk/all.h" diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index caf28285c..89583aadb 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -179,7 +179,11 @@ waLBerla_execute_test( NAME SweepTimeloopTimerReduction PROCESSES 9 ) # core # ######## -waLBerla_compile_test( FILES AllHeaderTest.cpp DEPENDS blockforest field geometry pe pe_coupling python_coupling ) +if ( WALBERLA_BUILD_WITH_PYTHON ) + waLBerla_compile_test( FILES AllHeaderTest.cpp DEPENDS blockforest field geometry pe pe_coupling python_coupling ) +else() + waLBerla_compile_test( FILES AllHeaderTest.cpp DEPENDS blockforest field geometry pe pe_coupling ) +endif() waLBerla_execute_test( NAME AllHeaderTest ) waLBerla_compile_test( FILES ConcatIterator.cpp ) diff --git a/tests/pe/SyncEquivalence.cpp b/tests/pe/SyncEquivalence.cpp index d17e2f0f1..6c0318018 100644 --- a/tests/pe/SyncEquivalence.cpp +++ b/tests/pe/SyncEquivalence.cpp @@ -18,8 +18,6 @@ // //====================================================================================================================== -#include "python_coupling/DictWrapper.h" - #include "blockforest/all.h" #include "core/all.h" #include "domain_decomposition/all.h" diff --git a/tests/python_coupling/BasicDatatypeTest.py b/tests/python_coupling/BasicDatatypeTest.py deleted file mode 100644 index bd5deff65..000000000 --- a/tests/python_coupling/BasicDatatypeTest.py +++ /dev/null @@ -1,26 +0,0 @@ -import unittest -import waLBerla as wlb - - -class BasicDatatypesTest(unittest.TestCase): - - def test_CellInterval(self): - ci1 = wlb.CellInterval(0, 0, 0, 5, 5, 5) - ci2 = wlb.CellInterval([0] * 3, [5] * 3) - self.assertEqual(ci1, ci2, "Equality comparison of CellIntervals failed.") - self.assertFalse(ci1 != ci2, "Inequality check for CellIntervals wrong ") - - self.assertEqual(ci1.min, (0, 0, 0), "CellInterval min wrong") - self.assertEqual(ci1.max, (5, 5, 5), "CellInterval max wrong") - - self.assertFalse(ci1.empty()) - - ci1.intersect(ci2) - self.assertTrue(ci1.contains(ci2)) - - ci2.expand(1) - self.assertFalse(ci1.contains(ci2)) - - def test_AABB(self): - aabb1 = wlb.AABB(0, 0, 0, 5, 5, 5) # noqa: F841 - aabb2 = wlb.AABB([0] * 3, [5] * 3) # noqa: F841 diff --git a/tests/python_coupling/CMakeLists.txt b/tests/python_coupling/CMakeLists.txt index 8e7c48fc9..462c2b8f2 100644 --- a/tests/python_coupling/CMakeLists.txt +++ b/tests/python_coupling/CMakeLists.txt @@ -1,6 +1,6 @@ ################################################################################################### # -# Tests for timeloop module +# Tests for python coupling # ################################################################################################### @@ -13,9 +13,16 @@ if (WALBERLA_BUILD_WITH_PYTHON) waLBerla_compile_test( FILES CallbackTest.cpp DEPENDS blockforest field ) waLBerla_execute_test( NAME CallbackTest - COMMAND $<TARGET_FILE:CallbackTest> ${CMAKE_CURRENT_SOURCE_DIR}/CallbackTest.py ) + COMMAND $<TARGET_FILE:CallbackTest> ${CMAKE_CURRENT_SOURCE_DIR}/CallbackTest.py ) + set_target_properties(CallbackTest PROPERTIES CXX_VISIBILITY_PRESET hidden) waLBerla_compile_test( FILES FieldExportTest.cpp DEPENDS blockforest field ) waLBerla_execute_test( NAME FieldExportTest COMMAND $<TARGET_FILE:FieldExportTest> ${CMAKE_CURRENT_SOURCE_DIR}/FieldExportTest.py ) + set_target_properties(FieldExportTest PROPERTIES CXX_VISIBILITY_PRESET hidden) + + add_test( NAME PythonWalberlaTest + COMMAND python3 -m unittest discover waLBerla_tests/ WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/python/) + SET_TESTS_PROPERTIES(PythonWalberlaTest + PROPERTIES ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/apps/pythonmodule:$PYTHONPATH") endif() diff --git a/tests/python_coupling/CallbackTest.cpp b/tests/python_coupling/CallbackTest.cpp index 95d210b76..08790f31f 100644 --- a/tests/python_coupling/CallbackTest.cpp +++ b/tests/python_coupling/CallbackTest.cpp @@ -13,33 +13,30 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file CallbackTest.h -//! \author Martin Bauer <martin.bauer@fau.de> -// +//! \file CallbackTest.cpp +//! \author Markus Holzer <markus.holzer@fau.de> +//! //====================================================================================================================== -#include "python_coupling/PythonWrapper.h" +#include "blockforest/Initialization.h" -#include "core/debug/TestSubsystem.h" #include "core/Environment.h" +#include "core/debug/TestSubsystem.h" #include "field/Field.h" -#include "field/python/Exports.h" -#include "blockforest/Initialization.h" -#include "blockforest/python/Exports.h" -#include "python_coupling/PythonCallback.h" -#include "python_coupling/Shell.h" + #include "python_coupling/DictWrapper.h" #include "python_coupling/Manager.h" +#include "python_coupling/PythonCallback.h" +#include "python_coupling/export/FieldExports.h" using namespace walberla; int main( int argc, char ** argv ) { - typedef boost::mpl::vector< Field<int,1> > Fields; auto pythonManager = python_coupling::Manager::instance(); - pythonManager->addExporterFunction( field::exportModuleToPython<Fields> ); + pythonManager->addExporterFunction( field::exportModuleToPython<Field<int,1>> ); if ( argc != 2 ) { WALBERLA_ABORT_NO_DEBUG_INFO("Wrong parameter count: \nUsage: \n ./CallbackTest CallbackTest.py"); diff --git a/tests/python_coupling/CallbackTest.py b/tests/python_coupling/CallbackTest.py index e6aa0a7b3..95381f415 100644 --- a/tests/python_coupling/CallbackTest.py +++ b/tests/python_coupling/CallbackTest.py @@ -9,9 +9,9 @@ def someCallback(input1, input2): @waLBerla.callback("cb2") def fieldCallback(field): - npArray = waLBerla.field.toArray(field) - npArray[0, 0, 0] = 42 + numpy_array = waLBerla.field.toArray(field) + numpy_array[0, 0, 0] = 42 - npArrayGl = waLBerla.field.toArray(field, withGhostLayers=True) - print(npArrayGl.shape) - npArrayGl[0, 0, 0] = 5 + numpy_array_with_gl = waLBerla.field.toArray(field, with_ghost_layers=True) + print(numpy_array_with_gl.shape) + numpy_array_with_gl[0, 0, 0] = 5 diff --git a/tests/python_coupling/ConfigFromPythonTest.cpp b/tests/python_coupling/ConfigFromPythonTest.cpp index 527cc3e55..7b3437463 100644 --- a/tests/python_coupling/ConfigFromPythonTest.cpp +++ b/tests/python_coupling/ConfigFromPythonTest.cpp @@ -1,52 +1,65 @@ //====================================================================================================================== // -// This file is part of waLBerla. waLBerla is free software: you can +// This file is part of waLBerla. waLBerla 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 3 of +// License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. -// -// waLBerla 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 +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // //! \file ConfigFromPythonTest.cpp //! \ingroup core -//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== #include "core/Abort.h" #include "core/debug/TestSubsystem.h" -#include "core/mpi/MPIManager.h" +#include "core/logging/Logging.h" +#include "core/math/Vector3.h" #include "core/mpi/Environment.h" + #include "python_coupling/CreateConfig.h" using namespace walberla; - -int main( int argc, char** argv ) +int main(int argc, char** argv) { debug::enterTestMode(); - mpi::Environment env( argc, argv ); + mpi::Environment env(argc, argv); - auto config = python_coupling::createConfigFromPythonScript( argv[1] ); + int counter = 0; + for (auto cfg = python_coupling::configBegin(argc, argv); cfg != python_coupling::configEnd(); ++cfg) + { + auto config = *cfg; + auto parameters = config->getOneBlock("DomainSetup"); + const int test_int = parameters.getParameter< int >("testInt"); + const std::string testString = parameters.getParameter< std::string >("testString"); + const real_t testDouble = parameters.getParameter< real_t >("testDouble"); + Vector3< real_t > testVector = parameters.getParameter< Vector3< real_t > >("testVector"); + const bool testBool = parameters.getParameter< bool >("testBool"); - WALBERLA_CHECK_EQUAL( argc, 2 ); + if (counter == 0) + WALBERLA_CHECK(test_int == 4) + else + WALBERLA_CHECK(test_int == 5) - config->listParameters(); - WALBERLA_CHECK_EQUAL ( int ( config->getParameter<int> ("testInt") ), 4 ); - WALBERLA_CHECK_EQUAL ( std::string( config->getParameter<std::string>("testString")), "someString" ); - WALBERLA_CHECK_FLOAT_EQUAL( double ( config->getParameter<real_t> ("testDouble")), real_t(42.42)); + counter++; + WALBERLA_CHECK(testString == "someString") + WALBERLA_CHECK(testDouble > 42 && testDouble < 43) + WALBERLA_CHECK(testVector == Vector3< real_t >(0.5, 0.5, 0.7)) + WALBERLA_CHECK(testBool == false) - auto subBlock = config->getBlock("subBlock"); - WALBERLA_CHECK_EQUAL ( std::string( subBlock.getParameter<std::string>("subKey1") ), std::string("abc") ); - WALBERLA_CHECK_EQUAL ( std::string( subBlock.getParameter<std::string>("subKey2") ), std::string("def") ); + WALBERLA_LOG_INFO_ON_ROOT(test_int) + } - return 0; + return EXIT_SUCCESS; } diff --git a/tests/python_coupling/ConfigFromPythonTest.py b/tests/python_coupling/ConfigFromPythonTest.py index 9c4a4f45a..d319203af 100644 --- a/tests/python_coupling/ConfigFromPythonTest.py +++ b/tests/python_coupling/ConfigFromPythonTest.py @@ -1,15 +1,27 @@ -import waLBerla - - -@waLBerla.callback("config") -def waLBerlaConfig(): - conf = { - 'testInt': 4, - 'testString': "someString", - 'testDouble': 42.42, - '44242': 'ohoh_IntegerKey', - 'subBlock': {'subKey1': 'abc', - 'subKey2': 'def' - } - } - return conf +import waLBerla as wlb + + +class Scenario: + def __init__(self, number): + self.testInt = number + self.testString = "someString" + self.testDouble = 42.42 + self.testVector = (0.5, 0.5, 0.7) + self.testBool = False + + @wlb.member_callback + def config(self): + return { + 'DomainSetup': { + 'testInt': self.testInt, + 'testDouble': self.testDouble, + 'testString': self.testString, + 'testVector': self.testVector, + 'testBool': self.testBool + } + } + + +scenarios = wlb.ScenarioManager() +scenarios.add(Scenario(4)) +scenarios.add(Scenario(5)) diff --git a/tests/python_coupling/FieldExportTest.cpp b/tests/python_coupling/FieldExportTest.cpp index 05997b58a..b78bc3682 100644 --- a/tests/python_coupling/FieldExportTest.cpp +++ b/tests/python_coupling/FieldExportTest.cpp @@ -13,28 +13,27 @@ // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // -//! \file FieldExportTest.h -//! \author Martin Bauer <martin.bauer@fau.de> +//! \file FieldExportTest.cpp +//! //! \author Markus Holzer <markus.holzer@fau.de> // //====================================================================================================================== -#include "python_coupling/PythonWrapper.h" +#include "blockforest/Initialization.h" #include "core/Environment.h" #include "core/debug/TestSubsystem.h" +#include "core/math/Random.h" #include "core/math/Vector2.h" #include "core/math/Vector3.h" -#include "core/math/Random.h" -#include "blockforest/Initialization.h" -#include "blockforest/python/Exports.h" -#include "field/python/Exports.h" +#include "python_coupling/DictWrapper.h" #include "python_coupling/Manager.h" #include "python_coupling/PythonCallback.h" -#include "python_coupling/DictWrapper.h" -#include "stencil/D2Q9.h" +#include "python_coupling/PythonWrapper.h" +#include "python_coupling/export/BlockForestExport.h" +#include "python_coupling/export/FieldExports.h" -#include <boost/mpl/vector.hpp> +#include "stencil/D2Q9.h" using namespace walberla; @@ -46,36 +45,29 @@ int main( int argc, char ** argv ) mpi::Environment mpiEnv( argc, argv ); auto pythonManager = python_coupling::Manager::instance(); - typedef boost::mpl::vector< - Field<Vector2<int>,1>, - Field<Vector3<int>,1>, - Field<int,2>, - Field<int,3> > FieldTypes; - - typedef boost::mpl::vector< stencil::D2Q9> Stencils; - pythonManager->addExporterFunction( field::exportModuleToPython<FieldTypes> ); - pythonManager->addBlockDataConversion< FieldTypes >() ; - pythonManager->addExporterFunction( blockforest::exportModuleToPython<Stencils> ); + pythonManager->addExporterFunction( field::exportModuleToPython<Field<int, 3>, Field<real_t, 3>> ); + pythonManager->addBlockDataConversion< Field<int, 3>, Field<real_t, 3> >() ; + pythonManager->addExporterFunction( blockforest::exportModuleToPython<stencil::D2Q9> ); shared_ptr< StructuredBlockForest > blocks = blockforest::createUniformBlockGrid( 1,1,1, 20,20,1, real_t(1.0), false, true,true,true ); - auto sca2FieldID = field::addToStorage< GhostLayerField<int,2> >( blocks, "sca2Field", int(0), field::fzyx, 1 ); - auto sca3FieldID = field::addToStorage< GhostLayerField<int,3> >( blocks, "sca3Field", int(0), field::fzyx, 1 ); + auto srcIntFieldID = field::addToStorage< GhostLayerField<int, 3> >( blocks, "srcIntFieldID", int(0), field::fzyx, 1 ); + auto dstIntFieldID = field::addToStorage< GhostLayerField<int, 3> >( blocks, "dstIntFieldID", int(0), field::fzyx, 1 ); - auto vec2FieldID = field::addToStorage< GhostLayerField<Vector2<int>,1> >( blocks, "vec2Field", Vector2<int>(), field::zyxf, 1 ); - auto vec3FieldID = field::addToStorage< GhostLayerField<Vector3<int>,1> >( blocks, "vec3Field", Vector3<int>(), field::zyxf, 1 ); + auto srcDoubleFieldID = field::addToStorage< GhostLayerField<real_t, 3> >( blocks, "srcDoubleFieldID", real_t(0.0), field::fzyx, 1 ); + auto dstDoubleFieldID = field::addToStorage< GhostLayerField<real_t, 3> >( blocks, "dstDoubleFieldID", real_t(0.0), field::fzyx, 1 ); // random init for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) { - auto sca2Field = blockIt->getData<GhostLayerField<int,2> >( sca2FieldID ); - auto sca3Field = blockIt->getData<GhostLayerField<int,3> >( sca3FieldID ); - for( auto cellIt = sca2Field->begin(); cellIt != sca2Field->end(); ++cellIt ) - *cellIt = math::intRandom( int(0), int(42) ); - for( auto cellIt = sca3Field->begin(); cellIt != sca3Field->end(); ++cellIt ) + auto srcIntField = blockIt->getData<GhostLayerField<int, 3> >( srcIntFieldID ); + auto srcDoubleField = blockIt->getData<GhostLayerField<real_t, 3> >( srcDoubleFieldID ); + for( auto cellIt = srcIntField->begin(); cellIt != srcIntField->end(); ++cellIt ) *cellIt = math::intRandom( int(0), int(42) ); + for( auto cellIt = srcDoubleField->begin(); cellIt != srcDoubleField->end(); ++cellIt ) + *cellIt = math::realRandom( real_t(0.0), real_t(42.0) ); } // call python function which should copy over the values to the Vector fields @@ -89,26 +81,26 @@ int main( int argc, char ** argv ) // check for equivalence for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) { - auto sca2Field = blockIt->getData<GhostLayerField<int,2> >( sca2FieldID ); - auto sca3Field = blockIt->getData<GhostLayerField<int,3> >( sca3FieldID ); - auto vec2Field = blockIt->getData<GhostLayerField<Vector2<int>,1 > >( vec2FieldID ); - auto vec3Field = blockIt->getData<GhostLayerField<Vector3<int>,1 > >( vec3FieldID ); + auto srcIntField = blockIt->getData<GhostLayerField<int, 3> >( srcIntFieldID ); + auto dstIntField = blockIt->getData<GhostLayerField<int, 3> >( dstIntFieldID ); + auto srcDoubleField = blockIt->getData<GhostLayerField<real_t, 3> >( srcDoubleFieldID ); + auto dstDoubleField = blockIt->getData<GhostLayerField<real_t, 3> >( dstDoubleFieldID ); { - for(cell_idx_t z = 0; z < cell_idx_c(sca2Field->zSize()); ++z) - for(cell_idx_t y = 0; y < cell_idx_c(sca2Field->zSize()); ++y) - for(cell_idx_t x = 0; x < cell_idx_c(sca2Field->zSize()); ++x) + for(cell_idx_t z = 0; z < cell_idx_c(srcIntField->zSize()); ++z) + for(cell_idx_t y = 0; y < cell_idx_c(srcIntField->zSize()); ++y) + for(cell_idx_t x = 0; x < cell_idx_c(srcIntField->zSize()); ++x) { - WALBERLA_CHECK_EQUAL( sca2Field->get(x,y,z, 0), vec2Field->get(x,y,z)[0] ); - WALBERLA_CHECK_EQUAL( sca2Field->get(x,y,z, 1), vec2Field->get(x,y,z)[1] ); + WALBERLA_CHECK_EQUAL( srcIntField->get(x,y,z, 0), dstIntField->get(x,y,z, 0) ); + WALBERLA_CHECK_EQUAL( srcIntField->get(x,y,z, 1), dstIntField->get(x,y,z, 1) ); } - for(cell_idx_t z = 0; z < cell_idx_c(sca3Field->zSize()); ++z) - for(cell_idx_t y = 0; y < cell_idx_c(sca3Field->zSize()); ++y) - for(cell_idx_t x = 0; x < cell_idx_c(sca3Field->zSize()); ++x) + for(cell_idx_t z = 0; z < cell_idx_c(srcDoubleField->zSize()); ++z) + for(cell_idx_t y = 0; y < cell_idx_c(srcDoubleField->zSize()); ++y) + for(cell_idx_t x = 0; x < cell_idx_c(srcDoubleField->zSize()); ++x) { - WALBERLA_CHECK_EQUAL( sca3Field->get(x,y,z, 0), vec3Field->get(x,y,z)[0] ); - WALBERLA_CHECK_EQUAL( sca3Field->get(x,y,z, 1), vec3Field->get(x,y,z)[1] ); - WALBERLA_CHECK_EQUAL( sca3Field->get(x,y,z, 2), vec3Field->get(x,y,z)[2] ); + WALBERLA_CHECK_FLOAT_EQUAL( srcDoubleField->get(x,y,z, 0), dstDoubleField->get(x,y,z, 0) ); + WALBERLA_CHECK_FLOAT_EQUAL( srcDoubleField->get(x,y,z, 1), dstDoubleField->get(x,y,z, 1) ); + WALBERLA_CHECK_FLOAT_EQUAL( srcDoubleField->get(x,y,z, 2), dstDoubleField->get(x,y,z, 2) ); } } } diff --git a/tests/python_coupling/FieldExportTest.py b/tests/python_coupling/FieldExportTest.py index 7790e9d2c..98da1c797 100644 --- a/tests/python_coupling/FieldExportTest.py +++ b/tests/python_coupling/FieldExportTest.py @@ -6,5 +6,5 @@ import numpy as np @waLBerla.callback("theCallback") def theCallback(blocks): for block in blocks: - np.copyto(toArray(block['vec2Field']), toArray(block['sca2Field'])) - np.copyto(toArray(block['vec3Field']), toArray(block['sca3Field'])) + np.copyto(toArray(block['srcIntFieldID']), toArray(block['dstIntFieldID'])) + np.copyto(toArray(block['srcDoubleFieldID']), toArray(block['dstDoubleFieldID'])) diff --git a/utilities/conda/walberla/bld.bat b/utilities/conda/walberla/bld.bat index ead78eca7..2b90c35b5 100644 --- a/utilities/conda/walberla/bld.bat +++ b/utilities/conda/walberla/bld.bat @@ -4,7 +4,6 @@ cd build set BOOST_ROOT=%PREFIX% cmake -LAH -G"Visual Studio 15 2017 Win64" ^ -DWALBERLA_BUILD_WITH_PYTHON=ON ^ - -DWALBERLA_BUILD_WITH_PYTHON_MODULE=ON ^ -DWALBERLA_BUILD_WITH_MPI=OFF ^ -DWALBERLA_BUILD_WITH_OPENMP=ON ^ -DPYTHON_EXECUTABLE="%PYTHON%" ^ diff --git a/utilities/conda/walberla/build.sh b/utilities/conda/walberla/build.sh index ac6ff0002..97256607b 100644 --- a/utilities/conda/walberla/build.sh +++ b/utilities/conda/walberla/build.sh @@ -5,8 +5,6 @@ cmake \ -DCMAKE_FIND_ROOT_PATH=${PREFIX} \ -DCMAKE_INSTALL_PREFIX=${PREFIX} \ -DWALBERLA_BUILD_WITH_PYTHON=ON \ - -DWALBERLA_BUILD_WITH_PYTHON_MODULE=ON \ - -DWALBERLA_BUILD_WITH_PYTHON_LBM=OFF \ .. make -j ${CPU_COUNT} pythonModuleInstall -- GitLab From d5a966d705285b925373cab5d62009b74740d789 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 16:49:31 +0100 Subject: [PATCH 16/83] [ADD] necessary particle properties for VBond model --- python/mesa_pd.py | 4 ++ src/mesa_pd/data/ParticleAccessor.h | 18 ++++++ src/mesa_pd/data/ParticleStorage.h | 58 +++++++++++++++++++ .../notifications/ParticleCopyNotification.h | 8 +++ .../ParticleGhostCopyNotification.h | 8 +++ 5 files changed, 96 insertions(+) diff --git a/python/mesa_pd.py b/python/mesa_pd.py index d3e062a4f..16d089cee 100755 --- a/python/mesa_pd.py +++ b/python/mesa_pd.py @@ -63,6 +63,10 @@ if __name__ == '__main__': ps.add_property("oldHydrodynamicTorque", "walberla::mesa_pd::Vec3", defValue="real_t(0)", syncMode="ON_OWNERSHIP_CHANGE") + # properties for VBond model + ps.add_property("clusterID", "int64_t", defValue="-1", syncMode="ON_GHOST_CREATION") + ps.add_property("segmentID", "int64_t", defValue="-1", syncMode="ON_GHOST_CREATION") + ch = mpd.add(data.ContactHistory()) ch.add_property("tangentialSpringDisplacement", "walberla::mesa_pd::Vec3", defValue="real_t(0)") ch.add_property("isSticking", "bool", defValue="false") diff --git a/src/mesa_pd/data/ParticleAccessor.h b/src/mesa_pd/data/ParticleAccessor.h index a00eb26c3..c6d978ac6 100644 --- a/src/mesa_pd/data/ParticleAccessor.h +++ b/src/mesa_pd/data/ParticleAccessor.h @@ -164,6 +164,14 @@ public: walberla::mesa_pd::Vec3& getOldHydrodynamicTorqueRef(const size_t p_idx) {return ps_->getOldHydrodynamicTorqueRef(p_idx);} void setOldHydrodynamicTorque(const size_t p_idx, walberla::mesa_pd::Vec3 const & v) { ps_->setOldHydrodynamicTorque(p_idx, v);} + int64_t const & getClusterID(const size_t p_idx) const {return ps_->getClusterID(p_idx);} + int64_t& getClusterIDRef(const size_t p_idx) {return ps_->getClusterIDRef(p_idx);} + void setClusterID(const size_t p_idx, int64_t const & v) { ps_->setClusterID(p_idx, v);} + + int64_t const & getSegmentID(const size_t p_idx) const {return ps_->getSegmentID(p_idx);} + int64_t& getSegmentIDRef(const size_t p_idx) {return ps_->getSegmentIDRef(p_idx);} + void setSegmentID(const size_t p_idx, int64_t const & v) { ps_->setSegmentID(p_idx, v);} + std::unordered_set<walberla::mpi::MPIRank> const & getNeighborState(const size_t p_idx) const {return ps_->getNeighborState(p_idx);} std::unordered_set<walberla::mpi::MPIRank>& getNeighborStateRef(const size_t p_idx) {return ps_->getNeighborStateRef(p_idx);} void setNeighborState(const size_t p_idx, std::unordered_set<walberla::mpi::MPIRank> const & v) { ps_->setNeighborState(p_idx, v);} @@ -329,6 +337,14 @@ public: void setOldHydrodynamicTorque(const size_t /*p_idx*/, walberla::mesa_pd::Vec3 const & v) { oldHydrodynamicTorque_ = v;} walberla::mesa_pd::Vec3& getOldHydrodynamicTorqueRef(const size_t /*p_idx*/) {return oldHydrodynamicTorque_;} + int64_t const & getClusterID(const size_t /*p_idx*/) const {return clusterID_;} + void setClusterID(const size_t /*p_idx*/, int64_t const & v) { clusterID_ = v;} + int64_t& getClusterIDRef(const size_t /*p_idx*/) {return clusterID_;} + + int64_t const & getSegmentID(const size_t /*p_idx*/) const {return segmentID_;} + void setSegmentID(const size_t /*p_idx*/, int64_t const & v) { segmentID_ = v;} + int64_t& getSegmentIDRef(const size_t /*p_idx*/) {return segmentID_;} + std::unordered_set<walberla::mpi::MPIRank> const & getNeighborState(const size_t /*p_idx*/) const {return neighborState_;} void setNeighborState(const size_t /*p_idx*/, std::unordered_set<walberla::mpi::MPIRank> const & v) { neighborState_ = v;} std::unordered_set<walberla::mpi::MPIRank>& getNeighborStateRef(const size_t /*p_idx*/) {return neighborState_;} @@ -373,6 +389,8 @@ private: walberla::mesa_pd::Vec3 hydrodynamicTorque_; walberla::mesa_pd::Vec3 oldHydrodynamicForce_; walberla::mesa_pd::Vec3 oldHydrodynamicTorque_; + int64_t clusterID_; + int64_t segmentID_; std::unordered_set<walberla::mpi::MPIRank> neighborState_; }; diff --git a/src/mesa_pd/data/ParticleStorage.h b/src/mesa_pd/data/ParticleStorage.h index f4f8de7e5..7e928eb64 100644 --- a/src/mesa_pd/data/ParticleStorage.h +++ b/src/mesa_pd/data/ParticleStorage.h @@ -100,6 +100,8 @@ public: using hydrodynamicTorque_type = walberla::mesa_pd::Vec3; using oldHydrodynamicForce_type = walberla::mesa_pd::Vec3; using oldHydrodynamicTorque_type = walberla::mesa_pd::Vec3; + using clusterID_type = int64_t; + using segmentID_type = int64_t; using neighborState_type = std::unordered_set<walberla::mpi::MPIRank>; @@ -219,6 +221,14 @@ public: oldHydrodynamicTorque_type& getOldHydrodynamicTorqueRef() {return storage_.getOldHydrodynamicTorqueRef(i_);} void setOldHydrodynamicTorque(oldHydrodynamicTorque_type const & v) { storage_.setOldHydrodynamicTorque(i_, v);} + clusterID_type const & getClusterID() const {return storage_.getClusterID(i_);} + clusterID_type& getClusterIDRef() {return storage_.getClusterIDRef(i_);} + void setClusterID(clusterID_type const & v) { storage_.setClusterID(i_, v);} + + segmentID_type const & getSegmentID() const {return storage_.getSegmentID(i_);} + segmentID_type& getSegmentIDRef() {return storage_.getSegmentIDRef(i_);} + void setSegmentID(segmentID_type const & v) { storage_.setSegmentID(i_, v);} + neighborState_type const & getNeighborState() const {return storage_.getNeighborState(i_);} neighborState_type& getNeighborStateRef() {return storage_.getNeighborStateRef(i_);} void setNeighborState(neighborState_type const & v) { storage_.setNeighborState(i_, v);} @@ -312,6 +322,8 @@ public: using hydrodynamicTorque_type = walberla::mesa_pd::Vec3; using oldHydrodynamicForce_type = walberla::mesa_pd::Vec3; using oldHydrodynamicTorque_type = walberla::mesa_pd::Vec3; + using clusterID_type = int64_t; + using segmentID_type = int64_t; using neighborState_type = std::unordered_set<walberla::mpi::MPIRank>; @@ -431,6 +443,14 @@ public: oldHydrodynamicTorque_type& getOldHydrodynamicTorqueRef(const size_t idx) {return oldHydrodynamicTorque_[idx];} void setOldHydrodynamicTorque(const size_t idx, oldHydrodynamicTorque_type const & v) { oldHydrodynamicTorque_[idx] = v; } + clusterID_type const & getClusterID(const size_t idx) const {return clusterID_[idx];} + clusterID_type& getClusterIDRef(const size_t idx) {return clusterID_[idx];} + void setClusterID(const size_t idx, clusterID_type const & v) { clusterID_[idx] = v; } + + segmentID_type const & getSegmentID(const size_t idx) const {return segmentID_[idx];} + segmentID_type& getSegmentIDRef(const size_t idx) {return segmentID_[idx];} + void setSegmentID(const size_t idx, segmentID_type const & v) { segmentID_[idx] = v; } + neighborState_type const & getNeighborState(const size_t idx) const {return neighborState_[idx];} neighborState_type& getNeighborStateRef(const size_t idx) {return neighborState_[idx];} void setNeighborState(const size_t idx, neighborState_type const & v) { neighborState_[idx] = v; } @@ -555,6 +575,8 @@ public: std::vector<hydrodynamicTorque_type> hydrodynamicTorque_ {}; std::vector<oldHydrodynamicForce_type> oldHydrodynamicForce_ {}; std::vector<oldHydrodynamicTorque_type> oldHydrodynamicTorque_ {}; + std::vector<clusterID_type> clusterID_ {}; + std::vector<segmentID_type> segmentID_ {}; std::vector<neighborState_type> neighborState_ {}; std::unordered_map<uid_type, size_t> uidToIdx_; static_assert(std::is_same<uid_type, id_t>::value, @@ -594,6 +616,8 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(const ParticleSt getHydrodynamicTorqueRef() = rhs.getHydrodynamicTorque(); getOldHydrodynamicForceRef() = rhs.getOldHydrodynamicForce(); getOldHydrodynamicTorqueRef() = rhs.getOldHydrodynamicTorque(); + getClusterIDRef() = rhs.getClusterID(); + getSegmentIDRef() = rhs.getSegmentID(); getNeighborStateRef() = rhs.getNeighborState(); return *this; } @@ -630,6 +654,8 @@ ParticleStorage::Particle& ParticleStorage::Particle::operator=(ParticleStorage: getHydrodynamicTorqueRef() = std::move(rhs.getHydrodynamicTorqueRef()); getOldHydrodynamicForceRef() = std::move(rhs.getOldHydrodynamicForceRef()); getOldHydrodynamicTorqueRef() = std::move(rhs.getOldHydrodynamicTorqueRef()); + getClusterIDRef() = std::move(rhs.getClusterIDRef()); + getSegmentIDRef() = std::move(rhs.getSegmentIDRef()); getNeighborStateRef() = std::move(rhs.getNeighborStateRef()); return *this; } @@ -667,6 +693,8 @@ void swap(ParticleStorage::Particle lhs, ParticleStorage::Particle rhs) std::swap(lhs.getHydrodynamicTorqueRef(), rhs.getHydrodynamicTorqueRef()); std::swap(lhs.getOldHydrodynamicForceRef(), rhs.getOldHydrodynamicForceRef()); std::swap(lhs.getOldHydrodynamicTorqueRef(), rhs.getOldHydrodynamicTorqueRef()); + std::swap(lhs.getClusterIDRef(), rhs.getClusterIDRef()); + std::swap(lhs.getSegmentIDRef(), rhs.getSegmentIDRef()); std::swap(lhs.getNeighborStateRef(), rhs.getNeighborStateRef()); } @@ -704,6 +732,8 @@ std::ostream& operator<<( std::ostream& os, const ParticleStorage::Particle& p ) "hydrodynamicTorque : " << p.getHydrodynamicTorque() << "\n" << "oldHydrodynamicForce: " << p.getOldHydrodynamicForce() << "\n" << "oldHydrodynamicTorque: " << p.getOldHydrodynamicTorque() << "\n" << + "clusterID : " << p.getClusterID() << "\n" << + "segmentID : " << p.getSegmentID() << "\n" << "neighborState : " << p.getNeighborState() << "\n" << "================================" << std::endl; return os; @@ -811,6 +841,8 @@ inline ParticleStorage::iterator ParticleStorage::create(const id_t& uid) hydrodynamicTorque_.emplace_back(real_t(0)); oldHydrodynamicForce_.emplace_back(real_t(0)); oldHydrodynamicTorque_.emplace_back(real_t(0)); + clusterID_.emplace_back(-1); + segmentID_.emplace_back(-1); neighborState_.emplace_back(); uid_.back() = uid; uidToIdx_[uid] = uid_.size() - 1; @@ -873,6 +905,8 @@ inline ParticleStorage::iterator ParticleStorage::erase(iterator& it) hydrodynamicTorque_.pop_back(); oldHydrodynamicForce_.pop_back(); oldHydrodynamicTorque_.pop_back(); + clusterID_.pop_back(); + segmentID_.pop_back(); neighborState_.pop_back(); return it; } @@ -922,6 +956,8 @@ inline void ParticleStorage::reserve(const size_t size) hydrodynamicTorque_.reserve(size); oldHydrodynamicForce_.reserve(size); oldHydrodynamicTorque_.reserve(size); + clusterID_.reserve(size); + segmentID_.reserve(size); neighborState_.reserve(size); } @@ -956,6 +992,8 @@ inline void ParticleStorage::clear() hydrodynamicTorque_.clear(); oldHydrodynamicForce_.clear(); oldHydrodynamicTorque_.clear(); + clusterID_.clear(); + segmentID_.clear(); neighborState_.clear(); uidToIdx_.clear(); } @@ -991,6 +1029,8 @@ inline size_t ParticleStorage::size() const //WALBERLA_ASSERT_EQUAL( uid_.size(), hydrodynamicTorque.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), oldHydrodynamicForce.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), oldHydrodynamicTorque.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), clusterID.size() ); + //WALBERLA_ASSERT_EQUAL( uid_.size(), segmentID.size() ); //WALBERLA_ASSERT_EQUAL( uid_.size(), neighborState.size() ); return uid_.size(); } @@ -1419,6 +1459,24 @@ public: walberla::mesa_pd::Vec3 const & operator()(const data::Particle& p) const {return p.getOldHydrodynamicTorque();} }; ///Predicate that selects a certain property from a Particle +class SelectParticleClusterID +{ +public: + using return_type = int64_t; + int64_t& operator()(data::Particle& p) const {return p.getClusterIDRef();} + int64_t& operator()(data::Particle&& p) const {return p.getClusterIDRef();} + int64_t const & operator()(const data::Particle& p) const {return p.getClusterID();} +}; +///Predicate that selects a certain property from a Particle +class SelectParticleSegmentID +{ +public: + using return_type = int64_t; + int64_t& operator()(data::Particle& p) const {return p.getSegmentIDRef();} + int64_t& operator()(data::Particle&& p) const {return p.getSegmentIDRef();} + int64_t const & operator()(const data::Particle& p) const {return p.getSegmentID();} +}; +///Predicate that selects a certain property from a Particle class SelectParticleNeighborState { public: diff --git a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h index b01a4dbeb..3881f2db6 100644 --- a/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleCopyNotification.h @@ -69,6 +69,8 @@ public: walberla::mesa_pd::Vec3 hydrodynamicTorque {real_t(0)}; walberla::mesa_pd::Vec3 oldHydrodynamicForce {real_t(0)}; walberla::mesa_pd::Vec3 oldHydrodynamicTorque {real_t(0)}; + int64_t clusterID {-1}; + int64_t segmentID {-1}; }; inline explicit ParticleCopyNotification( const data::Particle& particle ) : particle_(particle) {} @@ -101,6 +103,8 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setHydrodynamicTorque(data.hydrodynamicTorque); pIt->setOldHydrodynamicForce(data.oldHydrodynamicForce); pIt->setOldHydrodynamicTorque(data.oldHydrodynamicTorque); + pIt->setClusterID(data.clusterID); + pIt->setSegmentID(data.segmentID); return pIt; } @@ -148,6 +152,8 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getHydrodynamicTorque(); buf << obj.particle_.getOldHydrodynamicForce(); buf << obj.particle_.getOldHydrodynamicTorque(); + buf << obj.particle_.getClusterID(); + buf << obj.particle_.getSegmentID(); return buf; } @@ -176,6 +182,8 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.hydrodynamicTorque; buf >> objparam.oldHydrodynamicForce; buf >> objparam.oldHydrodynamicTorque; + buf >> objparam.clusterID; + buf >> objparam.segmentID; return buf; } diff --git a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h index c4e1c2417..77e8aed26 100644 --- a/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h +++ b/src/mesa_pd/mpi/notifications/ParticleGhostCopyNotification.h @@ -62,6 +62,8 @@ public: uint_t type {0}; std::map<walberla::id_t, walberla::mesa_pd::data::ContactHistory> oldContactHistory {}; walberla::real_t temperature {real_t(0)}; + int64_t clusterID {-1}; + int64_t segmentID {-1}; }; inline explicit ParticleGhostCopyNotification( const data::Particle& particle ) : particle_(particle) {} @@ -87,6 +89,8 @@ inline data::ParticleStorage::iterator createNewParticle(data::ParticleStorage& pIt->setType(data.type); pIt->setOldContactHistory(data.oldContactHistory); pIt->setTemperature(data.temperature); + pIt->setClusterID(data.clusterID); + pIt->setSegmentID(data.segmentID); return pIt; } @@ -127,6 +131,8 @@ mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, cons buf << obj.particle_.getType(); buf << obj.particle_.getOldContactHistory(); buf << obj.particle_.getTemperature(); + buf << obj.particle_.getClusterID(); + buf << obj.particle_.getSegmentID(); return buf; } @@ -148,6 +154,8 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, mesa_pd: buf >> objparam.type; buf >> objparam.oldContactHistory; buf >> objparam.temperature; + buf >> objparam.clusterID; + buf >> objparam.segmentID; return buf; } -- GitLab From a57c015ef65ec74a48a90107fb851a96730b28df Mon Sep 17 00:00:00 2001 From: Dominik Thoennes <dominik.thoennes@fau.de> Date: Fri, 18 Dec 2020 21:19:41 +0100 Subject: [PATCH 17/83] remove merge request stage since it causes nighlty jobs to be manual as well --- .gitlab-ci.yml | 387 ++----------------------------------------------- 1 file changed, 16 insertions(+), 371 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6e209960e..150f2086e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,6 @@ stages: - pretest - test - - merge_request - deploy - benchmark @@ -99,10 +98,6 @@ intel_18_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -127,10 +122,6 @@ intel_18_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -151,10 +142,10 @@ intel_18_hybrid: WALBERLA_ENABLE_GUI: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false + only: + variables: + - $ENABLE_NIGHTLY_BUILDS + tags: - cuda - docker @@ -178,10 +169,10 @@ intel_18_serial_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false + only: + variables: + - $ENABLE_NIGHTLY_BUILDS + tags: - cuda - docker @@ -207,10 +198,6 @@ intel_18_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -231,10 +218,6 @@ intel_18_hybrid_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -253,10 +236,6 @@ intel_18_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -283,10 +262,6 @@ intel_19_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -311,10 +286,6 @@ intel_19_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -334,10 +305,6 @@ intel_19_hybrid: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -361,10 +328,6 @@ intel_19_serial_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -386,10 +349,6 @@ intel_19_mpionly_dbg: WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -424,10 +383,6 @@ intel_19_hybrid_dbg_sp: WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_METIS: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -454,10 +409,6 @@ gcc_7_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -481,10 +432,6 @@ gcc_7_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -503,10 +450,10 @@ gcc_7_hybrid: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false + only: + variables: + - $ENABLE_NIGHTLY_BUILDS + tags: - cuda - docker @@ -530,10 +477,10 @@ gcc_7_serial_dbg: WALBERLA_ENABLE_GUI: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false + only: + variables: + - $ENABLE_NIGHTLY_BUILDS + tags: - cuda - docker @@ -558,10 +505,6 @@ gcc_7_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -581,10 +524,6 @@ gcc_7_hybrid_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -602,10 +541,6 @@ gcc_7_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -631,10 +566,6 @@ gcc_8_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -658,10 +589,6 @@ gcc_8_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -684,10 +611,6 @@ gcc_8_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -714,10 +637,6 @@ gcc_8_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -742,10 +661,6 @@ gcc_8_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -769,10 +684,6 @@ gcc_8_hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -790,10 +701,6 @@ gcc_8_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -818,10 +725,6 @@ gcc_9_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -843,10 +746,6 @@ gcc_9_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -867,10 +766,6 @@ gcc_9_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -895,10 +790,6 @@ gcc_9_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -921,10 +812,6 @@ gcc_9_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -946,10 +833,6 @@ gcc_9_hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -966,10 +849,6 @@ gcc_9_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -993,10 +872,6 @@ gcc_10_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -1018,10 +893,6 @@ gcc_10_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -1077,10 +948,6 @@ gcc_10_mpionly_dbg: WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -1098,10 +965,6 @@ gcc_10_hybrid_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -1114,10 +977,6 @@ gcc_10_hybrid_dbg_sp: WALBERLA_DOUBLE_ACCURACY: "OFF" WALBERLA_BUILD_WITH_PARMETIS: "OFF" WALBERLA_BUILD_WITH_METIS: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker @@ -1142,10 +1001,6 @@ clang_6.0_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1169,10 +1024,6 @@ clang_6.0_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1195,10 +1046,6 @@ clang_6.0_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1225,10 +1072,6 @@ clang_6.0_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1253,10 +1096,6 @@ clang_6.0_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1276,10 +1115,6 @@ clang_6.0_hybrid_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1297,10 +1132,6 @@ clang_6.0_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1326,10 +1157,6 @@ clang_7.0_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1353,10 +1180,6 @@ clang_7.0_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1379,10 +1202,6 @@ clang_7.0_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1409,10 +1228,6 @@ clang_7.0_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1437,10 +1252,6 @@ clang_7.0_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1464,10 +1275,6 @@ clang_7.0_hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1485,10 +1292,6 @@ clang_7.0_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1514,10 +1317,6 @@ clang_8.0_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1541,10 +1340,6 @@ clang_8.0_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1567,10 +1362,6 @@ clang_8.0_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1597,10 +1388,6 @@ clang_8.0_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1625,10 +1412,6 @@ clang_8.0_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1652,10 +1435,6 @@ clang_8.0_hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1673,10 +1452,6 @@ clang_8.0_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1702,10 +1477,6 @@ clang_9.0_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1729,10 +1500,6 @@ clang_9.0_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1755,10 +1522,6 @@ clang_9.0_hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1785,10 +1548,6 @@ clang_9.0_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1813,10 +1572,6 @@ clang_9.0_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1840,10 +1595,6 @@ clang_9.0_hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1861,10 +1612,6 @@ clang_9.0_hybrid_dbg_sp: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1890,10 +1637,6 @@ clang_10.0_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1917,10 +1660,6 @@ clang_10.0_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1939,10 +1678,6 @@ clang_10.0_hybrid: WALBERLA_BUILD_WITH_CUDA: "ON" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -1965,10 +1700,6 @@ clang_10.0_serial_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -2008,10 +1739,6 @@ clang_10.0_hybrid_dbg: CMAKE_BUILD_TYPE: "DebugOptimized" WALBERLA_BUILD_WITH_CODEGEN: "ON" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - cuda - docker @@ -2044,10 +1771,6 @@ gcc_8_hybrid_dbg_noboost: WALBERLA_BUILD_WITH_PYTHON: "OFF" tags: - docker - stage: merge_request - when: manual - needs: [] - allow_failure: false @@ -2078,10 +1801,6 @@ gcc_10_stl_debug: WALBERLA_STL_BOUNDS_CHECKS: "ON" tags: - docker - stage: merge_request - when: manual - needs: [ ] - allow_failure: false @@ -2101,10 +1820,6 @@ doc: - cmake .. - cmake . -LA - make doc - stage: merge_request - when: manual - needs: [] - allow_failure: false tags: - docker artifacts: @@ -2132,10 +1847,6 @@ clang-tidy: - cmake . -LA - utilities/filterCompileCommands.py compile_commands.json - run-clang-tidy.py -quiet | tee clang-tidy-output.txt - stage: merge_request - when: manual - needs: [] - allow_failure: false artifacts: paths: - $CI_PROJECT_DIR/build/clang-tidy-output.txt @@ -2231,10 +1942,6 @@ msvc-14.1_Hybrid_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_Hybrid_sp_dbg: @@ -2248,10 +1955,6 @@ msvc-14.1_Hybrid_sp_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_Hybrid: @@ -2263,10 +1966,6 @@ msvc-14.1_Hybrid: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_serial_dbg: @@ -2281,10 +1980,6 @@ msvc-14.1_serial_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_serial: @@ -2298,10 +1993,6 @@ msvc-14.1_serial: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_mpionly_dbg: @@ -2315,10 +2006,6 @@ msvc-14.1_mpionly_dbg: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.1_mpionly: @@ -2331,10 +2018,6 @@ msvc-14.1_mpionly: variables: - $ENABLE_NIGHTLY_BUILDS - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_Hybrid_dbg: @@ -2352,10 +2035,6 @@ msvc-14.2_Hybrid_sp_dbg: CMAKE_GENERATOR: "Visual Studio 16 2019" BUILD_CONFIGURATION: "DebugOptimized" WALBERLA_DOUBLE_ACCURACY: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_Hybrid: @@ -2363,10 +2042,6 @@ msvc-14.2_Hybrid: variables: WALBERLA_BUILD_WITH_CUDA: "OFF" CMAKE_GENERATOR: "Visual Studio 16 2019" - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_serial_dbg: @@ -2377,10 +2052,6 @@ msvc-14.2_serial_dbg: WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" BUILD_CONFIGURATION: "DebugOptimized" - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_serial: @@ -2390,10 +2061,6 @@ msvc-14.2_serial: CMAKE_GENERATOR: "Visual Studio 16 2019" WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_mpionly_dbg: @@ -2403,10 +2070,6 @@ msvc-14.2_mpionly_dbg: CMAKE_GENERATOR: "Visual Studio 16 2019" BUILD_CONFIGURATION: "DebugOptimized" WALBERLA_BUILD_WITH_OPENMP: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false msvc-14.2_mpionly: @@ -2415,10 +2078,6 @@ msvc-14.2_mpionly: WALBERLA_BUILD_WITH_CUDA: "OFF" CMAKE_GENERATOR: "Visual Studio 16 2019" WALBERLA_BUILD_WITH_OPENMP: "OFF" - stage: merge_request - when: manual - needs: [] - allow_failure: false @@ -2454,10 +2113,6 @@ mac_Serial_Dbg: WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false mac_Serial: <<: *mac_build_definition @@ -2467,10 +2122,6 @@ mac_Serial: WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" - stage: merge_request - when: manual - needs: [] - allow_failure: false mac_MpiOnly_Dbg: <<: *mac_build_definition @@ -2491,10 +2142,6 @@ mac_MpiOnly: WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" OMPI_MCA_btl: "self,tcp" - stage: merge_request - when: manual - needs: [] - allow_failure: false ############################################################################### ## ## @@ -2513,8 +2160,6 @@ mac_MpiOnly: - anaconda logout dependencies: [] when: manual - needs: [] - allow_failure: false only: - master@walberla/walberla - tags@walberla/walberla -- GitLab From bd9e7b0fbf6e725fadd6febc55c9d601aa46c9a7 Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Fri, 18 Dec 2020 21:43:05 +0100 Subject: [PATCH 18/83] Python coupling patch --- python/waLBerla_docs/modules/blockforest.rst | 15 ++++++++++ python/waLBerla_tests/test_field.py | 30 +++++++++++++++++++ .../export/BlockForestExport.cpp | 19 ++++++++++++ .../helper/SliceToCellInterval.h | 14 ++++++--- 4 files changed, 74 insertions(+), 4 deletions(-) diff --git a/python/waLBerla_docs/modules/blockforest.rst b/python/waLBerla_docs/modules/blockforest.rst index ccd463bae..a9ef1d001 100644 --- a/python/waLBerla_docs/modules/blockforest.rst +++ b/python/waLBerla_docs/modules/blockforest.rst @@ -25,6 +25,21 @@ Reference on other processes). This information includes the process rank, the state, and the axis-aligned bounding box of any block (local or remote). [false by default] +.. py:function:: createUniformBlockGrid(cells, dx=1, oneBlockPerProcess=True, periodic=(0,0,0), keepGlobalBlockInformation=False) + + Creates a new uniform StructuredBlockForest. Similar to cpp function blockforest::createUniformBlockGrid. + Specify only number of cells. The distribution on the processes is then calculated automatically. + + :param cells : 3-tuple with total number of cells in x,y,z direction. + + :param dx: Side length of a single cell. + :param oneBlockPerProcess: If True, each process gets one block. If False, all blocks are put to one process. + The second option makes only sense for debugging or testing. + :param periodic: Periodicity of the domain in x,y,z direction + :param keepGlobalBlockInformation: If true, each process keeps information about remote blocks (blocks that reside + on other processes). This information includes the process rank, the state, and + the axis-aligned bounding box of any block (local or remote). [false by default] + \ No newline at end of file diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index 85957c51b..3ab25c418 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -47,6 +47,36 @@ class FieldModuleTest(unittest.TestCase): view4 = field.toArray(f, with_ghost_layers=[2, False, True]) self.assertEqual(view4[:, :, :, 0].shape, tuple([size[0] + 2 * 2, size[1] + 2 * 0, size[2] + 2 * gl])) + def test_gather(self): + blocks = createUniformBlockGrid(blocks=(10, 4, 3), cellsPerBlock=(2, 2, 2), + periodic=(True, True, True), oneBlockPerProcess=False) + wlb.field.addToStorage(blocks, "test", dtype=np.int, fSize=3) + + for block in blocks: + offset_in_global_domain = blocks.transformLocalToGlobal(block, wlb.Cell(0, 0, 0))[:] + f = wlb.field.toArray(block["test"]) + s = f.shape + for i in range(0, s[0]): + for j in range(0, s[1]): + for k in range(0, s[2]): + f[i, j, k, 0] = i + offset_in_global_domain[0] + f[i, j, k, 1] = j + offset_in_global_domain[1] + f[i, j, k, 2] = k + offset_in_global_domain[2] + + tp = tuple([slice(5, 15), slice(None, None), 0.5]) + f = wlb.field.gather(blocks, "test", tp) + + nparray = wlb.field.toArray(f) + self.assertEqual(nparray.shape, (11, 8, 1, 3)) + + s = nparray.shape + for i in range(0, s[0]): + for j in range(0, s[1]): + for k in range(0, s[2]): + assert(nparray[i, j, k, 0] == i + 5) + assert(nparray[i, j, k, 1] == j) + assert(nparray[i, j, k, 2] == 2) + if __name__ == '__main__': unittest.main() diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp index 14232baae..7d2c9d764 100644 --- a/src/python_coupling/export/BlockForestExport.cpp +++ b/src/python_coupling/export/BlockForestExport.cpp @@ -332,6 +332,25 @@ void exportBlockForest(py::module_& m) }, "blocks"_a, "cellsPerBlock"_a, "dx"_a = real_t(1), "oneBlockPerProcess"_a = true, "periodic"_a = std::array< bool, 3 >{ false, false, false }, "keepGlobalBlockInformation"_a = false); + + m.def( + "createUniformBlockGrid", + [](std::array< uint_t, 3 > cells, real_t dx, + bool oneBlockPerProcess, std::array< bool, 3 > periodic, bool keepGlobalBlockInformation) { + Vector3<uint_t> cellsVec(cells[0], cells[1], cells[2]); + Vector3<uint_t> cellsPerBlock; + Vector3<uint_t> blocks; + uint_t nrOfProcesses = uint_c( MPIManager::instance()->numProcesses() ); + + calculateCellDistribution( cellsVec, nrOfProcesses, blocks, cellsPerBlock ); + + + return blockforest::createUniformBlockGrid(blocks[0], blocks[1], blocks[2], cellsPerBlock[0], cellsPerBlock[1], + cellsPerBlock[2], dx, oneBlockPerProcess, periodic[0], periodic[1], periodic[2], + keepGlobalBlockInformation); + }, + "cells"_a,"dx"_a = real_t(1), "oneBlockPerProcess"_a = true, + "periodic"_a = std::array< bool, 3 >{ false, false, false }, "keepGlobalBlockInformation"_a = false); } } // namespace blockforest diff --git a/src/python_coupling/helper/SliceToCellInterval.h b/src/python_coupling/helper/SliceToCellInterval.h index d988c1c74..fd0a7ecdc 100644 --- a/src/python_coupling/helper/SliceToCellInterval.h +++ b/src/python_coupling/helper/SliceToCellInterval.h @@ -38,11 +38,17 @@ inline cell_idx_t normalizeIdx(py::object pyIndex, uint_t coordinateSize) { cell_idx_t index; - try { - index = py::cast< cell_idx_t >(pyIndex); + try{ + index = pyIndex.cast<cell_idx_t>(); } - catch (py::error_already_set & ){ - throw py::cast_error("Incompatible index data type"); + catch (std::exception &){ + try { + auto test = pyIndex.cast<real_t>(); + index = cell_idx_c( test * real_t( coordinateSize) ); + } + catch (std::exception &) { + throw py::cast_error("Incompatible index data type"); + } } if (index < 0) -- GitLab From c2f79f23c3d7e5b75a25ea7cda51baa96e6141dd Mon Sep 17 00:00:00 2001 From: Stephan Seitz <stephan.seitz@fau.de> Date: Fri, 9 Oct 2020 11:33:14 +0200 Subject: [PATCH 19/83] Silence warnings in mpi.h for (mpich and clang12) --- src/core/mpi/MPIWrapper.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/core/mpi/MPIWrapper.h b/src/core/mpi/MPIWrapper.h index 3cdc7d546..14e72cc5d 100644 --- a/src/core/mpi/MPIWrapper.h +++ b/src/core/mpi/MPIWrapper.h @@ -61,7 +61,14 @@ namespace mpistubs { #pragma warning ( push, 1 ) #endif +#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wsign-conversion" +#endif #include <mpi.h> +#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) +# pragma GCC diagnostic pop +#endif #ifdef _MSC_VER #pragma warning ( pop ) @@ -284,8 +291,8 @@ using namespace mpistubs; namespace walberla { namespace mpi { - typedef int MPIRank; - typedef int MPISize; + using MPIRank = int; + using MPISize = int; const MPIRank INVALID_RANK = -1; const MPISize INVALID_SIZE = -1; } // namespace MPI -- GitLab From 5c825e803bf9db7775313b6f4fe0aafbc5fd4069 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 27 Nov 2020 09:58:28 +0100 Subject: [PATCH 20/83] removed mpi-type-mismatch from clang-tidy This check seems to be buggy and often crashes clang-tidy. --- .clang-tidy | 1 + 1 file changed, 1 insertion(+) diff --git a/.clang-tidy b/.clang-tidy index 910df6702..ddebeb835 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -28,6 +28,7 @@ modernize-*, -modernize-avoid-c-arrays, mpi-*, +-mpi-type-mismatch, openmp-*, -openmp-exception-escape, -- GitLab From 310948cd2b5eb5915fb331cb49d98fdc2cd960a8 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Tue, 22 Dec 2020 11:34:46 +0100 Subject: [PATCH 21/83] Align to __BIGGEST_ALIGNMENT__ (GCC, Clang, Intel) or to 512 bits for AVX512 compatibility via pystencils Intel always sets __BIGGEST_ALIGNMENT__ to 64, irrespective of what instruction set is enabled --- src/field/Field.impl.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/field/Field.impl.h b/src/field/Field.impl.h index 2ae44c77f..e1515cb75 100644 --- a/src/field/Field.impl.h +++ b/src/field/Field.impl.h @@ -316,14 +316,18 @@ namespace field { // Automatically select allocator if none was given if ( alloc == 0 ) { - const uint_t alignment = 32; +#ifdef __BIGGEST_ALIGNMENT__ + const uint_t alignment = __BIGGEST_ALIGNMENT__; +#else + const uint_t alignment = 64; +#endif // aligned allocator only used (by default) if ... if ( l == fzyx && // ... we use a structure of arrays layout _xSize * sizeof(T) > alignment && // ... the inner coordinate is sufficiently large sizeof(T) < alignment && // ... the stored data type is smaller than the alignment alignment % sizeof(T) == 0 ) // ... there is an integer number of elements fitting in one aligned line - alloc = make_shared<AllocateAligned<T,32> >(); + alloc = make_shared<AllocateAligned<T,alignment> >(); else alloc = make_shared<StdFieldAlloc<T> > (); } -- GitLab From c3b6da1d18eabadb42bda3a52dfd0130ec7bac3a Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Mon, 28 Dec 2020 18:53:07 +0100 Subject: [PATCH 22/83] Remove Boost and switch to C++17 Some optional components use Boost MultiArray and PropertyTree, so we still include the headers if available. We also still search std::experimental for any, filesystem and optional because some otherwise C++17-compliant compilers did not support them in std until recently. --- .clang-tidy | 2 + .gitlab-ci.yml | 168 +------------------- CMakeLists.txt | 138 +++++----------- README.md | 4 +- cmake/TestStdAny.cpp | 17 -- cmake/TestStdOptional.cpp | 19 --- cmake/TestStdVariant.cpp | 7 - cmake/waLBerlaFunctions.cmake | 4 +- doc/setup.dox | 6 - extern/pybind11 | 2 +- src/blockforest/PhantomBlock.h | 2 +- src/core/Any.h | 14 +- src/core/ConcatIterator.h | 8 +- src/core/Environment.cpp | 2 +- src/core/Filesystem.h | 13 +- src/core/Optional.h | 16 +- src/core/Variant.h | 20 --- src/core/grid_generator/HCPIterator.h | 8 +- src/core/grid_generator/SCIterator.h | 8 +- src/core/mpi/BufferDataTypeExtensions.h | 4 + src/domain_decomposition/BlockStorage.h | 7 +- src/field/iterators/FieldIterator.h | 9 +- src/gather/CellGatherPackInfo.h | 2 +- src/gather/CurveGatherPackInfo.h | 2 +- src/mesa_pd/data/shape/ShapeTypes.cpp | 39 ----- src/pe/rigidbody/BodyIterators.h | 24 ++- src/vtk/Initialization.cpp | 6 +- src/waLBerlaDefinitions.in.h | 5 - tests/core/CMakeLists.txt | 2 +- tests/core/VariantTest.cpp | 13 +- tests/timeloop/TimeloopAndSweepRegister.cpp | 1 - utilities/conda/walberla/bld.bat | 4 +- utilities/conda/walberla/meta.yaml | 2 - 33 files changed, 131 insertions(+), 447 deletions(-) delete mode 100644 cmake/TestStdAny.cpp delete mode 100644 cmake/TestStdOptional.cpp delete mode 100644 cmake/TestStdVariant.cpp delete mode 100644 src/mesa_pd/data/shape/ShapeTypes.cpp diff --git a/.clang-tidy b/.clang-tidy index ddebeb835..00ffd56f0 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -26,6 +26,8 @@ modernize-*, -modernize-redundant-void-arg, -modernize-use-trailing-return-type, -modernize-avoid-c-arrays, +-modernize-concat-nested-namespaces, +-modernize-use-nodiscard, mpi-*, -mpi-type-mismatch, diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 150f2086e..2248c4cdd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -77,170 +77,6 @@ stages: -intel_18_serial: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - WALBERLA_BUILD_WITH_MPI: "OFF" - WALBERLA_BUILD_WITH_OPENMP: "OFF" - WALBERLA_BUILD_WITH_PARMETIS: "OFF" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - -intel_18_mpionly: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - WALBERLA_BUILD_WITH_OPENMP: "OFF" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - -intel_18_hybrid: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - WALBERLA_ENABLE_GUI: "ON" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - -intel_18_serial_dbg: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - WALBERLA_BUILD_WITH_MPI: "OFF" - WALBERLA_BUILD_WITH_OPENMP: "OFF" - WALBERLA_BUILD_WITH_PARMETIS: "OFF" - CMAKE_BUILD_TYPE: "DebugOptimized" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - -intel_18_mpionly_dbg: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - CMAKE_BUILD_TYPE: "DebugOptimized" - WALBERLA_BUILD_WITH_OPENMP: "OFF" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - -intel_18_hybrid_dbg: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - before_script: - - pip3 install lbmpy jinja2 - - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ - - cd .. - - CC=gcc CXX=g++ pip3 install pycuda - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - CMAKE_BUILD_TYPE: "DebugOptimized" - WALBERLA_BUILD_WITH_CODEGEN: "ON" - WALBERLA_BUILD_WITH_PYTHON: "ON" - tags: - - cuda - - docker - - intel - -intel_18_hybrid_dbg_sp: - extends: .build_template - image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:18 - variables: - WALBERLA_BUILD_WITH_CUDA: "ON" - CMAKE_BUILD_TYPE: "DebugOptimized" - WALBERLA_DOUBLE_ACCURACY: "OFF" - WALBERLA_BUILD_WITH_PARMETIS: "OFF" - WALBERLA_BUILD_WITH_METIS: "OFF" - only: - variables: - - $ENABLE_NIGHTLY_BUILDS - - tags: - - cuda - - docker - - intel - intel_19_serial: extends: .build_template image: i10git.cs.fau.de:5005/walberla/buildenvs/intel:19 @@ -1858,7 +1694,7 @@ cppcheck: image: i10git.cs.fau.de:5005/walberla/buildenvs/cppcheck script: - cppcheck --version - - cppcheck . --max-configs=10 --enable=warning --enable=style --enable=performance --enable=portability -i src/gui/extern -i src/geometry/structured/extern -i sqlite3.c -i StackWalker.cpp -I src/ -I tests/ -I apps/ -D WALBERLA_BUILD_WITH_MPI -D WALBERLA_BUILD_WITH_METIS -D WALBERLA_BUILD_WITH_BOOST_THREAD -D WALBERLA_BUILD_WITH_PYTHON --xml 2> report.xml + - cppcheck . --max-configs=10 --enable=warning --enable=style --enable=performance --enable=portability -i src/gui/extern -i src/geometry/structured/extern -i sqlite3.c -i StackWalker.cpp -I src/ -I tests/ -I apps/ -D WALBERLA_BUILD_WITH_MPI -D WALBERLA_BUILD_WITH_METIS -D WALBERLA_BUILD_WITH_PYTHON --xml 2> report.xml - cppcheck-htmlreport --file=report.xml --report-dir=html_report --source-dir=. artifacts: untracked: true @@ -1919,7 +1755,7 @@ coverage: - cmake --version - mkdir build - cd build - - cmake -LA -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -G "$CMAKE_GENERATOR" .. + - cmake -LA -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -G "$CMAKE_GENERATOR" -DCMAKE_DISABLE_FIND_PACKAGE_Boost=TRUE .. - MSBuild.exe walberla.sln /property:Configuration=$BUILD_CONFIGURATION /verbosity:minimal /maxcpucount:4 - ctest -LE $CTEST_EXCLUDE_LABELS -C $BUILD_CONFIGURATION --output-on-failure -j 4 variables: diff --git a/CMakeLists.txt b/CMakeLists.txt index d866ab63d..c62caabc3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ ## Contents: ## - definition of build options ## - compiler variables ( c++ standard, warnings etc. ) -## - Finding of service libraries. Required: boost, Optional: MPI, PE, METIS +## - Finding of service libraries. Required: none, Optional: Boost, MPI, FFTW3, METIS, OpenMesh, Python ## the include paths are set, and the libraries are added to variable SERVICE_LIBS ## - Subdirectory cmake lists are called ## -> src/ this folder contains all modules, each module (that contains c or cpp files) is linked to a @@ -136,7 +136,7 @@ endif() ############################################################################################################################ -set( CMAKE_CXX_STANDARD 14 ) +set( CMAKE_CXX_STANDARD 17 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_CXX_EXTENSIONS OFF ) @@ -170,10 +170,16 @@ if( CMAKE_CXX_COMPILER MATCHES "icpc" OR CMAKE_CXX_COMPILER_ARG1 MATCHES "icpc" SET(CMAKE_LINKER "${XILD}") ENDIF(XILD) MARK_AS_ADVANCED(XILD) - if( CMAKE_VERSION VERSION_LESS 3.6.0 ) - set( CMAKE_CXX14_STANDARD_COMPILE_OPTION "-std=c++14" ) + + if( CMAKE_VERSION VERSION_LESS 3.11.0 ) + set( CMAKE_CXX17_STANDARD_COMPILE_OPTION "-std=c++17" ) + set( CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_CXX17_STANDARD_COMPILE_OPTION ) add_flag ( CMAKE_CXX_FLAGS ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) endif() + if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS "19.0.5" ) + # std::filesystem uses ABI tags, which don't work 19.0.2 but do in 19.0.5 + add_flag ( CMAKE_CXX_FLAGS "-D_GLIBCXX_USE_CXX11_ABI=0" ) + endif() else() option ( WALBERLA_CXX_COMPILER_IS_INTEL "Use Intel compiler" OFF ) endif() @@ -285,7 +291,8 @@ endif() # C++ language features for NEC compiler if( WALBERLA_CXX_COMPILER_IS_NEC ) - set( CMAKE_CXX14_STANDARD_COMPILE_OPTION "-Kcpp14" ) + set( CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION "-Kcpp${CMAKE_CXX_STANDARD}" ) + set( CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION ) add_flag ( CMAKE_CXX_FLAGS "${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} -Krtti -Kexceptions -size_t64 -Kgcc" ) add_flag ( CMAKE_CXX_FLAGS "-D__BIG_ENDIAN -D__BYTE_ORDER=__BIG_ENDIAN" ) add_flag ( CMAKE_CXX_FLAGS "-Tnoauto,used" ) @@ -314,7 +321,6 @@ endif() if( WALBERLA_CXX_COMPILER_IS_IBM ) add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1586-267" ) # 1586-267 (I) Inlining of specified subprogram failed due to the presence of a C++ exception handler add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1586-266" ) # 1586-266 (I) Inlining of specified subprogram failed due to the presence of a global label - add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1540-0724" ) # 1540-0724 (W) The non-type template argument "2147483648" of type "T" has wrapped [coming from boost/integer_traits.hpp] add_flag ( CMAKE_CXX_FLAGS "-qsuppress=1500-030" ) # 1500-030: (I) INFORMATION: [...] Additional optimization may be attained by recompiling and specifying MAXMEM option with a value greater than 8192. add_flag ( CMAKE_C_FLAGS "-qsuppress=1500-030" ) # 1500-030: (I) INFORMATION: [...] Additional optimization may be attained by recompiling and specifying MAXMEM option with a value greater than 8192. endif() @@ -366,7 +372,6 @@ endif() if ( WALBERLA_CXX_COMPILER_IS_CLANG ) add_flag ( CMAKE_CXX_FLAGS "-Wall -Wconversion -Wshadow -Wno-c++11-extensions -Qunused-arguments" ) - add_flag ( CMAKE_CXX_FLAGS "-D'_LIBCPP_EXTERN_TEMPLATE(...)='") endif ( ) if( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL OR WALBERLA_CXX_COMPILER_IS_CLANG ) @@ -433,25 +438,24 @@ endif() ############################################################################################################################ ## -## Find optional C++ libraries +## Find newer C++ libraries, which may only be available in std::experimental on some compilers ## ############################################################################################################################ try_compile( WALBERLA_USE_STD_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) + COMPILE_DEFINITIONS -DWALBERLA_USE_STD_FILESYSTEM ) if( WALBERLA_USE_STD_FILESYSTEM ) message( STATUS "Found std::filesystem") else() try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) + COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) message( STATUS "Found std::experimental::filesystem") endif() if( NOT WALBERLA_CXX_COMPILER_IS_MSVC AND NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) unset( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM CACHE ) try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} - LINK_LIBRARIES stdc++fs ) + COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM LINK_LIBRARIES stdc++fs ) if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) message( STATUS "Found std::experimental::filesystem in libstdc++fs") list ( APPEND SERVICE_LIBS -lstdc++fs ) @@ -460,47 +464,23 @@ else() if( NOT WALBERLA_CXX_COMPILER_IS_MSVC AND NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) unset( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM CACHE ) try_compile( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdFilesystem.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} - LINK_LIBRARIES c++experimental ) + COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM LINK_LIBRARIES c++experimental ) if( WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) message( STATUS "Found std::experimental::filesystem in libc++experimental") list ( APPEND SERVICE_LIBS -lc++experimental ) endif() endif() -endif() - -try_compile( WALBERLA_USE_STD_ANY "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdAny.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_ANY ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) -if( WALBERLA_USE_STD_ANY ) - message( STATUS "Found std::any") -else() - try_compile( WALBERLA_USE_STD_EXPERIMENTAL_ANY "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdAny.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_ANY ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) - if( WALBERLA_USE_STD_EXPERIMENTAL_ANY ) - message( STATUS "Found std::experimental::any") - endif() -endif() - -try_compile( WALBERLA_USE_STD_OPTIONAL "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdOptional.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_OPTIONAL ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) -if( WALBERLA_USE_STD_OPTIONAL ) - message( STATUS "Found std::optional") -else() - try_compile( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdOptional.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) - if( WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL ) - message( STATUS "Found std::experimental::optional") + if( NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM AND NOT WALBERLA_USE_STD_FILESYSTEM) + message(FATAL_ERROR "Neither std::filesystem nor std::experimental::filesystem are available") endif() endif() -try_compile( WALBERLA_USE_STD_VARIANT "${CMAKE_CURRENT_BINARY_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/cmake/TestStdVariant.cpp" - COMPILE_DEFINITIONS -DWALBERLA_USE_STD_VARIANT ${CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION} ) -if( WALBERLA_USE_STD_VARIANT ) - message( STATUS "Found std::variant") +if (WALBERLA_BUILD_WITH_CUDA AND CUDA_VERSION VERSION_LESS "11.0") + # CUDA < 11 does not support C++17. std::experimental::any works with C++14, unlike std::any. + set(WALBERLA_USE_STD_EXPERIMENTAL_ANY 1) endif() - ############################################################################################################################ ## ## Visual Studio Setup @@ -593,10 +573,17 @@ if ( WALBERLA_BUILD_WITH_PYTHON ) message( FATAL_ERROR "Couldn't find any python library" ) endif() + if(WALBERLA_CXX_COMPILER_IS_INTEL) + # Intel C++17 support introduced in 2.6.2 (https://github.com/pybind/pybind11/pull/2729) + set(PYBIND11_MINIMUM_VERSION "2.6.2") + else() + set(PYBIND11_MINIMUM_VERSION "2.6.0") + endif() + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import pybind11; print(pybind11._version.__version__)" OUTPUT_VARIABLE pybind11_VERSION ERROR_QUIET RESULT_VARIABLE pybind11_VERSION_RESULT) string(STRIP "${pybind11_VERSION}" pybind11_VERSION) - if(pybind11_VERSION_RESULT EQUAL "0" AND pybind11_VERSION VERSION_GREATER_EQUAL "2.6.0") + if(pybind11_VERSION_RESULT EQUAL "0" AND pybind11_VERSION VERSION_GREATER_EQUAL "${PYBIND11_MINIMUM_VERSION}") execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pybind11 --cmakedir OUTPUT_VARIABLE PYBIND11_CMAKE_PATH) string(STRIP "${PYBIND11_CMAKE_PATH}" PYBIND11_CMAKE_PATH) @@ -626,10 +613,12 @@ if ( WALBERLA_BUILD_WITH_PYTHON ) add_subdirectory(extern/pybind11) - # if pybind11 was installed into ${PYTHON_INCLUDE_DIR} (e.g. by pip), that will have a higher priority than the Git submodule unless we reorder the search path - # introduced in 2.6.0 (https://github.com/pybind/pybind11/issues/2709), fixed in 2.6.2 (https://github.com/pybind/pybind11/pull/2716) - set_property( TARGET pybind11::pybind11 - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/extern/pybind11/include" "${PYTHON_INCLUDE_DIR}") + if(pybind11_VERSION VERSION_LESS "2.6.2") + # if pybind11 was installed into ${PYTHON_INCLUDE_DIR} (e.g. by pip), that will have a higher priority than the Git submodule unless we reorder the search path + # introduced in 2.6.0 (https://github.com/pybind/pybind11/issues/2709), fixed in 2.6.2 (https://github.com/pybind/pybind11/pull/2716) + set_property( TARGET pybind11::pybind11 + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${PROJECT_SOURCE_DIR}/extern/pybind11/include" "${PYTHON_INCLUDE_DIR}") + endif() endif() # a python module is a shared library - so everything has to be compiled to position independent code @@ -652,25 +641,14 @@ endif() ## BOOST Libraries ## ############################################################################################################################# -set ( waLBerla_REQUIRED_MIN_BOOST_VERSION "1.48") set ( Boost_NO_BOOST_CMAKE ON) -if ( NOT WALBERLA_USE_STD_FILESYSTEM AND NOT WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM ) - list ( APPEND waLBerla_REQUIRED_BOOST_COMPONENTS filesystem system ) -else() - list ( APPEND waLBerla_OPTIONAL_BOOST_COMPONENTS system ) -endif() - # This variable is necessary, if the CMAKE version used is not aware of a more recent boost version (keep this up to date!) set ( Boost_ADDITIONAL_VERSIONS "1.45" "1.45.0" "1.46" "1.46.0" "1.46.1" "1.47" "1.47.0" "1.48" "1.48.0" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52" "1.52.0" "1.53" "1.53.0" "1.54" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" "1.59" "1.59.0" "1.60" "1.60.0" "1.61" "1.61.0" "1.62" "1.62.0" "1.63" "1.63.0" - "1.64.0" "1.65.0" "1.65.1" "1.66.0" "1.67.0" "1.68.0" "1.69.0" "1.70.0" "1.71.0" "1.72.0" "1.73.0") - -set ( Boost_USE_STATIC_LIBS OFF CACHE BOOL "Use boost static libraries" ) -set ( Boost_USE_MULTITHREADED OFF CACHE BOOL "Use boost multithreaded libraries" ) -set ( Boost_USE_STATIC_RUNTIME OFF CACHE BOOL "Use boost libraries statically linked to runtime libs" ) + "1.64.0" "1.65.0" "1.65.1" "1.66.0" "1.67.0" "1.68.0" "1.69.0" "1.70.0" "1.71.0" "1.72.0" "1.73.0" "1.74.0") # if you defined BOOST_ROOT or BOOST_BASE in your environment use it here to find boost too if ( NOT BOOST_ROOT ) @@ -683,28 +661,7 @@ if ( NOT BOOST_ROOT ) endforeach ( ) endif ( ) -find_package ( Boost ${waLBerla_REQUIRED_MIN_BOOST_VERSION} COMPONENTS ${waLBerla_REQUIRED_BOOST_COMPONENTS} OPTIONAL_COMPONENTS ${waLBerla_OPTIONAL_BOOST_COMPONENTS} QUIET ) - -if( NOT Boost_FOUND ) - message ( WARNING - "The specified configuration of the BOOST libraries was not found on your system! Now trying some other configuration..." ) - foreach ( Boost_USE_STATIC_LIBS ON OFF ) - foreach ( Boost_USE_MULTITHREADED ON OFF ) - find_package ( Boost ${waLBerla_REQUIRED_MIN_BOOST_VERSION} COMPONENTS ${waLBerla_REQUIRED_BOOST_COMPONENTS} OPTIONAL_COMPONENTS ${waLBerla_OPTIONAL_BOOST_COMPONENTS} QUIET ) - if ( Boost_FOUND ) - set ( Boost_USE_STATIC_LIBS ${Boost_USE_STATIC_LIBS} CACHE BOOL "Use boost static libraries" FORCE ) - set ( Boost_USE_MULTITHREADED ${Boost_USE_MULTITHREADED} CACHE BOOL "Use boost multithreaded libraries" FORCE ) - set ( Boost_USE_MULTITHREADED_LIBRARY ${Boost_USE_MULTITHREADED} ) - message ( STATUS "Working configuration of the BOOST libraries was found :o)!" ) - message ( STATUS "Boost_USE_STATIC_LIBS and Boost_USE_MULTITHREADED was adapted accordingly." ) - BREAK ( ) - endif ( Boost_FOUND ) - endforeach ( Boost_USE_MULTITHREADED ) - if ( Boost_FOUND ) - BREAK ( ) - endif ( Boost_FOUND ) - endforeach ( Boost_USE_STATIC_LIBS ) -endif ( NOT Boost_FOUND ) +find_package ( Boost ) if ( Boost_FOUND ) if(CMAKE_GENERATOR STREQUAL "Xcode") @@ -713,24 +670,11 @@ if ( Boost_FOUND ) else() include_directories ( SYSTEM ${Boost_INCLUDE_DIRS} ) endif() - if( waLBerla_REQUIRED_BOOST_COMPONENTS ) - link_directories ( ${Boost_LIBRARY_DIRS} ) - list ( APPEND SERVICE_LIBS ${Boost_LIBRARIES} ) - endif() add_definitions ( -DBOOST_ALL_NO_LIB ) # Disable Boost auto-linking (CMAKE does that for us...) set( WALBERLA_BUILD_WITH_BOOST TRUE CACHE INTERNAL "Build with Boost" ) else( Boost_FOUND ) - if( (WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM OR WALBERLA_USE_STD_FILESYSTEM) AND (WALBERLA_USE_STD_EXPERIMENTAL_ANY OR WALBERLA_USE_STD_ANY) AND (WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL OR WALBERLA_USE_STD_OPTIONAL) AND NOT WALBERLA_BUILD_WITH_PYTHON) - # we don't really need Boost - set( WALBERLA_BUILD_WITH_BOOST FALSE CACHE INTERNAL "Build with Boost" ) - else() - # Search again, this time with the REQUIRED option. This will give a CMAKE error and a detailed error message for the user - find_package ( Boost ${waLBerla_REQUIRED_MIN_BOOST_VERSION} REQUIRED ${waLBerla_REQUIRED_BOOST_COMPONENTS} OPTIONAL_COMPONENTS ${waLBerla_OPTIONAL_BOOST_COMPONENTS} ) - if( (WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM OR WALBERLA_USE_STD_FILESYSTEM) AND (WALBERLA_USE_STD_EXPERIMENTAL_ANY OR WALBERLA_USE_STD_ANY) AND (WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL OR WALBERLA_USE_STD_OPTIONAL) ) - message(WARNING "If you set WALBERLA_BUILD_WITH_PYTHON=OFF, you can build without the Boost library.") - endif() - endif() + set( WALBERLA_BUILD_WITH_BOOST FALSE CACHE INTERNAL "Build with Boost" ) endif( Boost_FOUND ) @@ -864,10 +808,6 @@ if ( WALBERLA_ENABLE_GUI ) INCLUDE( ${QT_USE_FILE} ) list ( APPEND SERVICE_LIBS ${OPENGL_LIBRARIES} ${QT_LIBRARIES} ) - # Workaround for Qt4 moc and newer boost versions - moc cannot parse BOOST_JOIN - # so additional defines are passed to the moc compiler that prevent the problematic header to be parsed - set( QT_MOC_EXECUTABLE ${QT_MOC_EXECUTABLE} -DBOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -DBOOST_TT_HAS_OPERATOR_HPP_INCLUDED ) - endif(WALBERLA_ENABLE_GUI) ############################################################################################################################ diff --git a/README.md b/README.md index 40e176fb8..9d87364cf 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,8 @@ is documented in [Sphinx](http://walberla.net/sphinx/index.html). ## Getting started -The minimum requirements are a C++14-compliant compiler (e.g. GCC or Clang), -the [Boost](http://www.boost.org) library and the [CMake](http://www.cmake.org) +The minimum requirements are a C++17-compliant compiler (e.g. GCC or Clang) +and the [CMake](http://www.cmake.org) build system. Furthermore, you need an MPI library (like [Open MPI](http://www.open-mpi.org)) if you want to make use of parallel processing capabilities. All of these dependencies are typically available in diff --git a/cmake/TestStdAny.cpp b/cmake/TestStdAny.cpp deleted file mode 100644 index 6bcc880a6..000000000 --- a/cmake/TestStdAny.cpp +++ /dev/null @@ -1,17 +0,0 @@ -#include <iostream> -#if defined(WALBERLA_USE_STD_ANY) -#include <any> -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY) -#include <experimental/any> -#endif - -int main() { -#if defined(WALBERLA_USE_STD_ANY) - auto a = std::any(42); - std::cout << std::any_cast<int>(a) << std::endl; -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY) - auto a = std::experimental::any(42); - std::cout << std::experimental::any_cast<int>(a) << std::endl; -#endif - return 0; -} diff --git a/cmake/TestStdOptional.cpp b/cmake/TestStdOptional.cpp deleted file mode 100644 index fc3a148c1..000000000 --- a/cmake/TestStdOptional.cpp +++ /dev/null @@ -1,19 +0,0 @@ -#include <iostream> -#if defined(WALBERLA_USE_STD_OPTIONAL) -#include <optional> -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL) -#include <experimental/optional> -#endif - -int main() { -#if defined(WALBERLA_USE_STD_OPTIONAL) - auto a = std::optional<int>(); - auto b = std::optional<int>(42); -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL) - auto a = std::experimental::optional<int>(); - auto b = std::experimental::optional<int>(42); -#endif - if (b) - std::cout << a.value_or(b.value()) << std::endl; - return 0; -} diff --git a/cmake/TestStdVariant.cpp b/cmake/TestStdVariant.cpp deleted file mode 100644 index be98d121f..000000000 --- a/cmake/TestStdVariant.cpp +++ /dev/null @@ -1,7 +0,0 @@ -#include <iostream> -#include <variant> - -int main() { - std::variant<int,float> a; - return 0; -} diff --git a/cmake/waLBerlaFunctions.cmake b/cmake/waLBerlaFunctions.cmake index a5822aa84..f4c4b1f68 100644 --- a/cmake/waLBerlaFunctions.cmake +++ b/cmake/waLBerlaFunctions.cmake @@ -99,7 +99,7 @@ function ( waLBerla_add_module ) waLBerla_register_dependency ( ${moduleName} ${ARG_DEPENDS} ) - set_property( TARGET ${moduleName} PROPERTY CXX_STANDARD 14 ) + set_property( TARGET ${moduleName} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} ) # This property is needed for visual studio to group modules together if( WALBERLA_GROUP_PROJECTS ) @@ -204,7 +204,7 @@ function ( waLBerla_add_executable ) target_link_modules ( ${ARG_NAME} ${ARG_DEPENDS} ) target_link_libraries( ${ARG_NAME} ${WALBERLA_LINK_LIBRARIES_KEYWORD} ${SERVICE_LIBS} ) - set_property( TARGET ${ARG_NAME} PROPERTY CXX_STANDARD 14 ) + set_property( TARGET ${ARG_NAME} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} ) if( WALBERLA_GROUP_PROJECTS ) if( NOT ARG_GROUP ) diff --git a/doc/setup.dox b/doc/setup.dox index e740b0e04..ab9ba0588 100644 --- a/doc/setup.dox +++ b/doc/setup.dox @@ -22,12 +22,6 @@ If you are not familiar with the git version control system, this To compile waLBerla with all modules and features a few third-party libraries are required. -\subsubsection libs_boost Boost -The boost library is the only required third-party library. It is installed on -most Linux system by default and should be detected by cmake. -If boost resides at a non-standard location, you have to set the environment variable -`BOOST_ROOT` in order to have it detected by cmake. - \subsubsection libs_mpi MPI (optional) The message passing interface (MPI) library is required if you want to run waLBerla with distributed memory parallelization. If MPI is not installed on your system, diff --git a/extern/pybind11 b/extern/pybind11 index 526a7733c..687c69625 160000 --- a/extern/pybind11 +++ b/extern/pybind11 @@ -1 +1 @@ -Subproject commit 526a7733c773016f2e552777612027954d0765fd +Subproject commit 687c69625bd2b96ac0596d1a9cc0ab2101485d70 diff --git a/src/blockforest/PhantomBlock.h b/src/blockforest/PhantomBlock.h index e5d95c6c9..0df698690 100644 --- a/src/blockforest/PhantomBlock.h +++ b/src/blockforest/PhantomBlock.h @@ -88,7 +88,7 @@ public: T getData() const { return walberla::any_cast<T>( data_ ); } bool hasData() const { -#ifdef WALBERLA_USE_STD_ANY +#ifndef WALBERLA_USE_STD_EXPERIMENTAL_ANY return data_.has_value(); #else return !(data_.empty()); diff --git a/src/core/Any.h b/src/core/Any.h index ac2f9dbb3..a7bdfaea4 100644 --- a/src/core/Any.h +++ b/src/core/Any.h @@ -21,29 +21,25 @@ #pragma once +#include "waLBerlaDefinitions.h" -#if defined(WALBERLA_USE_STD_ANY) +#ifndef WALBERLA_USE_STD_EXPERIMENTAL_ANY #include <any> -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY) +#else #undef _LIBCPP_WARN_ON_DEPRECATED_EXPERIMENTAL_HEADER #include <experimental/any> -#else -#include <boost/any.hpp> #endif namespace walberla { -#if defined(WALBERLA_USE_STD_ANY) +#ifndef WALBERLA_USE_STD_EXPERIMENTAL_ANY using std::any; using std::any_cast; -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_ANY) +#else using std::experimental::any; using std::experimental::any_cast; -#else -using boost::any; -using boost::any_cast; #endif } diff --git a/src/core/ConcatIterator.h b/src/core/ConcatIterator.h index b21ce3705..f76c79f62 100644 --- a/src/core/ConcatIterator.h +++ b/src/core/ConcatIterator.h @@ -27,9 +27,15 @@ namespace walberla { template< typename T > -class ConcatIterator : public std::iterator< std::input_iterator_tag, typename T::value_type, typename T::difference_type, typename T::pointer, typename T::reference > +class ConcatIterator { public: + using iterator_category = std::input_iterator_tag; + using value_type = typename T::value_type; + using difference_type = typename T::difference_type; + using pointer = typename T::pointer; + using reference = typename T::reference; + /// default constructed iterator points to end() ConcatIterator( ) : ended_( true ) diff --git a/src/core/Environment.cpp b/src/core/Environment.cpp index 015687ce3..684f6f8e2 100644 --- a/src/core/Environment.cpp +++ b/src/core/Environment.cpp @@ -82,7 +82,7 @@ void configureGlobalState( const shared_ptr<Config> & config ) { std::string suids = config->getParameter< std::string >( "GlobalState" ); std::vector< std::string > states = string_split( suids, ", \t" ); - states.erase( std::remove_if( states.begin(), states.end(), std::bind( &std::string::empty, std::placeholders::_1 ) ), states.end() ); + states.erase( std::remove_if( states.begin(), states.end(), [](auto &s){ return s.empty(); } ), states.end() ); Set<SUID> state; for( auto it = states.begin(); it != states.end(); ++it ) diff --git a/src/core/Filesystem.h b/src/core/Filesystem.h index 24e14a868..beaf77ad0 100644 --- a/src/core/Filesystem.h +++ b/src/core/Filesystem.h @@ -21,14 +21,13 @@ #pragma once +#include "waLBerlaDefinitions.h" -#if defined(WALBERLA_USE_STD_FILESYSTEM) +#ifndef WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM #include <filesystem> -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM) +#else #define _LIBCPP_NO_EXPERIMENTAL_DEPRECATION_WARNING_FILESYSTEM #include <experimental/filesystem> -#else -#include <boost/filesystem.hpp> #endif @@ -36,12 +35,10 @@ namespace walberla { namespace filesystem { -#if defined(WALBERLA_USE_STD_FILESYSTEM) +#ifndef WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM using namespace std::filesystem; -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM) -using namespace std::experimental::filesystem; #else -using namespace boost::filesystem; +using namespace std::experimental::filesystem; #endif } diff --git a/src/core/Optional.h b/src/core/Optional.h index 60883fd3d..5c31a1ec0 100644 --- a/src/core/Optional.h +++ b/src/core/Optional.h @@ -21,29 +21,15 @@ #pragma once +#include "waLBerlaDefinitions.h" -#if defined(WALBERLA_USE_STD_OPTIONAL) #include <optional> -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL) -#undef _LIBCPP_WARN_ON_DEPRECATED_EXPERIMENTAL_HEADER -#include <experimental/optional> -#else -#include <boost/optional.hpp> -#endif namespace walberla { -#if defined(WALBERLA_USE_STD_OPTIONAL) using std::optional; using std::nullopt; -#elif defined(WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL) -using std::experimental::optional; -using std::experimental::nullopt; -#else -using boost::optional; -const boost::none_t nullopt = boost::none; -#endif } diff --git a/src/core/Variant.h b/src/core/Variant.h index 7fe6d195a..2be3f0a6c 100644 --- a/src/core/Variant.h +++ b/src/core/Variant.h @@ -22,37 +22,17 @@ #pragma once -#if defined(WALBERLA_USE_STD_VARIANT) #include <variant> -#else -#include <boost/variant.hpp> -#endif namespace walberla { -#if defined(WALBERLA_USE_STD_VARIANT) using std::variant; using std::visit; using std::get; using std::holds_alternative; using std::bad_variant_access; -#else -using boost::variant; -using boost::get; -template <class T, class... Types> -constexpr bool holds_alternative( const boost::variant<Types...>& v ) noexcept -{ - return v.type() == typeid( T ); -} -using bad_variant_access = boost::bad_get; -template<typename Visitor, typename... Variant> -decltype( auto ) visit( Visitor&& visitor, Variant&& ... variant ) -{ - return boost::apply_visitor( visitor, variant... ); -} -#endif } diff --git a/src/core/grid_generator/HCPIterator.h b/src/core/grid_generator/HCPIterator.h index dc84a29c6..dfc806d11 100644 --- a/src/core/grid_generator/HCPIterator.h +++ b/src/core/grid_generator/HCPIterator.h @@ -33,9 +33,15 @@ namespace grid_generator { /// /// Usage: /// \code for (auto it = HCPIterator::begin(...); it != HCPIterator::end(); ++it) \endcode -class HCPIterator : public std::iterator< std::forward_iterator_tag, Vector3<real_t> > +class HCPIterator { public: + using iterator_category = std::forward_iterator_tag; + using value_type = Vector3<real_t>; + using difference_type = std::ptrdiff_t; + using pointer = Vector3<real_t>*; + using reference = Vector3<real_t>&; + /** * @brief begin iterator * @param domain volume were lattice points will be returned diff --git a/src/core/grid_generator/SCIterator.h b/src/core/grid_generator/SCIterator.h index 4946f8dbd..7068bd3de 100644 --- a/src/core/grid_generator/SCIterator.h +++ b/src/core/grid_generator/SCIterator.h @@ -46,9 +46,15 @@ namespace grid_generator { /// \endcode /// Usage: /// \code for (auto it = SCIterator::begin(...); it != SCIterator::end(); ++it) \endcode -class SCIterator : public std::iterator< std::forward_iterator_tag, Vector3<real_t> > +class SCIterator { public: + using iterator_category = std::forward_iterator_tag; + using value_type = Vector3<real_t>; + using difference_type = std::ptrdiff_t; + using pointer = Vector3<real_t>*; + using reference = Vector3<real_t>&; + /** * @brief begin iterator * @param domain volume were lattice points will be returned diff --git a/src/core/mpi/BufferDataTypeExtensions.h b/src/core/mpi/BufferDataTypeExtensions.h index 9685d6ac2..3196b5362 100644 --- a/src/core/mpi/BufferDataTypeExtensions.h +++ b/src/core/mpi/BufferDataTypeExtensions.h @@ -28,7 +28,9 @@ #include "core/Conversion.h" #include "core/DataTypes.h" #include "core/math/Uint.h" +#if __cplusplus >= 201703L || defined(_MSC_VER) #include "core/Optional.h" +#endif #include "core/RandomUUID.h" #include <array> @@ -564,6 +566,7 @@ template<typename T, typename K, typename C, typename A> struct BufferSizeTrait< std::multimap<K,T,C,A> > { static const bool constantSize = false; }; +#if __cplusplus >= 201703L || defined(_MSC_VER) // --------------------------------------------------------------------------------------------------------------------- // ------------------------------------------- optional Support -------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------- @@ -614,6 +617,7 @@ GenericRecvBuffer<T>& operator>>( GenericRecvBuffer<T> & buf, walberla::optional return buf; } +#endif // --------------------------------------------------------------------------------------------------------------------- // --------------------------------------- RandomUUID Support ---------------------------------------------------------- diff --git a/src/domain_decomposition/BlockStorage.h b/src/domain_decomposition/BlockStorage.h index 34789a47b..e00f3ee86 100644 --- a/src/domain_decomposition/BlockStorage.h +++ b/src/domain_decomposition/BlockStorage.h @@ -77,10 +77,15 @@ public: class const_iterator; - class iterator : public std::iterator <std::forward_iterator_tag, IBlock > { + class iterator { friend class const_iterator; friend class BlockStorage; public: + using iterator_category = std::forward_iterator_tag; + using value_type = IBlock; + using difference_type = std::ptrdiff_t; + using pointer = IBlock*; + using reference = IBlock&; iterator( const iterator & it ) : it_( it.it_ ), end_( it.end_ ), requiredSelectors_( it.requiredSelectors_ ), incompatibleSelectors_( it.incompatibleSelectors_ ) {} diff --git a/src/field/iterators/FieldIterator.h b/src/field/iterators/FieldIterator.h index 0136ce727..faecf9822 100644 --- a/src/field/iterators/FieldIterator.h +++ b/src/field/iterators/FieldIterator.h @@ -66,11 +66,16 @@ namespace field { */ //******************************************************************************************************************* template <typename T, uint_t fieldFSize> - class FieldIterator : public std::iterator <std::forward_iterator_tag,T> + class FieldIterator { public: + using iterator_category = std::forward_iterator_tag; + using value_type = T; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using reference = T&; + typedef Field<typename std::remove_const<T>::type, fieldFSize> FieldType; - typedef T value_type; static const uint_t F_SIZE = fieldFSize; diff --git a/src/gather/CellGatherPackInfo.h b/src/gather/CellGatherPackInfo.h index d4cee6c5d..0055a2ba0 100644 --- a/src/gather/CellGatherPackInfo.h +++ b/src/gather/CellGatherPackInfo.h @@ -124,7 +124,7 @@ protected: shared_ptr<DataProcessor> dataProcessor_; /// Helper class for sorting the receivedData array according to t-value - struct Compare : public std::binary_function<std::vector<real_t> , std::vector<real_t> ,bool> + struct Compare : public std::function<bool(std::vector<real_t> , std::vector<real_t>)> { inline bool operator()(const std::vector<real_t> & v1, const std::vector<real_t> & v2) const { return v1[0] < v2[0]; diff --git a/src/gather/CurveGatherPackInfo.h b/src/gather/CurveGatherPackInfo.h index f23b18ae6..112f018b3 100644 --- a/src/gather/CurveGatherPackInfo.h +++ b/src/gather/CurveGatherPackInfo.h @@ -193,7 +193,7 @@ class CurveGatherPackInfo : public GatherPackInfo /// Helper class for sorting the receivedData array according to t-value - struct Compare : public std::binary_function<std::vector<real_t> , std::vector<real_t> ,bool> + struct Compare : public std::function<bool(std::vector<real_t> , std::vector<real_t>)> { inline bool operator()(const std::vector<real_t> & v1, const std::vector<real_t> & v2) const { return v1[0] < v2[0]; diff --git a/src/mesa_pd/data/shape/ShapeTypes.cpp b/src/mesa_pd/data/shape/ShapeTypes.cpp deleted file mode 100644 index 4eb52cd05..000000000 --- a/src/mesa_pd/data/shape/ShapeTypes.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file -//! \author Sebastian Eibl <sebastian.eibl@fau.de> -// -//====================================================================================================================== - -#include <mesa_pd/data/shape/Box.h> -#include <mesa_pd/data/shape/CylindricalBoundary.h> -#include <mesa_pd/data/shape/HalfSpace.h> -#include <mesa_pd/data/shape/Ellipsoid.h> -#include <mesa_pd/data/shape/Sphere.h> - -namespace walberla { -namespace mesa_pd { -namespace data { - -const int Box::SHAPE_TYPE ; -const int CylindricalBoundary::SHAPE_TYPE; -const int HalfSpace::SHAPE_TYPE ; -const int Ellipsoid::SHAPE_TYPE ; -const int Sphere::SHAPE_TYPE ; - -} //namespace data -} //namespace mesa_pd -} //namespace walberla diff --git a/src/pe/rigidbody/BodyIterators.h b/src/pe/rigidbody/BodyIterators.h index 5f4ef40fc..903a1195b 100644 --- a/src/pe/rigidbody/BodyIterators.h +++ b/src/pe/rigidbody/BodyIterators.h @@ -34,10 +34,16 @@ class BodyIterator public: template< typename T > - class iterator : public std::iterator< std::input_iterator_tag, typename T::value_type, typename T::difference_type, typename T::pointer, typename T::reference > + class iterator { friend class BodyIterator; public: + using iterator_category = std::input_iterator_tag; + using value_type = typename T::value_type; + using difference_type = typename T::difference_type; + using pointer = typename T::pointer; + using reference = typename T::reference; + iterator & operator++() { ++it_; checkStateAndAdapt(); return *this; } // prefix ++X iterator operator++(int) { iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -146,10 +152,16 @@ class LocalBodyIterator public: template< typename T > - class iterator : public std::iterator< std::input_iterator_tag, typename T::value_type, typename T::difference_type, typename T::pointer, typename T::reference > + class iterator { friend class LocalBodyIterator; public: + using iterator_category = std::input_iterator_tag; + using value_type = typename T::value_type; + using difference_type = typename T::difference_type; + using pointer = typename T::pointer; + using reference = typename T::reference; + iterator & operator++() { ++it_; checkStateAndAdapt(); return *this; } // prefix ++X iterator operator++(int) { iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -236,10 +248,16 @@ class ShadowBodyIterator public: template< typename T > - class iterator : public std::iterator< std::input_iterator_tag, typename T::value_type, typename T::difference_type, typename T::pointer, typename T::reference > + class iterator { friend class ShadowBodyIterator; public: + using iterator_category = std::input_iterator_tag; + using value_type = typename T::value_type; + using difference_type = typename T::difference_type; + using pointer = typename T::pointer; + using reference = typename T::reference; + iterator & operator++() { ++it_; checkStateAndAdapt(); return *this; } // prefix ++X iterator operator++(int) { iterator it( *this ); operator++(); return it; }; // postfix X++ diff --git a/src/vtk/Initialization.cpp b/src/vtk/Initialization.cpp index 0b4fa4567..4d88f1b21 100644 --- a/src/vtk/Initialization.cpp +++ b/src/vtk/Initialization.cpp @@ -42,7 +42,7 @@ static void splitVector( T& x, T& y, T& z, const Config::BlockHandle& bb, const std::string vector = bb.getParameter< std::string >( vertex ); coordinates = string_split( vector, "<,> \t" ); - coordinates.erase( std::remove_if( coordinates.begin(), coordinates.end(), std::bind( &std::string::empty, std::placeholders::_1 ) ), coordinates.end() ); + coordinates.erase( std::remove_if( coordinates.begin(), coordinates.end(), [](auto &s){ return s.empty(); } ), coordinates.end() ); if( coordinates.size() != 3 ) WALBERLA_ABORT( errorMsg ); @@ -59,7 +59,7 @@ static std::vector< std::string > splitList( const std::string& string ) std::vector< std::string > list; list = string_split( string, ", \t" ); - list.erase( std::remove_if( list.begin(), list.end(), std::bind( &std::string::empty, std::placeholders::_1 ) ), list.end() ); + list.erase( std::remove_if( list.begin(), list.end(), [](auto &s){ return s.empty(); } ), list.end() ); return list; } @@ -70,7 +70,7 @@ static void addStates( Set<SUID>& set, const std::string& string ) { std::vector< std::string > states; states = string_split( string, ", \t" ); - states.erase( std::remove_if( states.begin(), states.end(), std::bind( &std::string::empty, std::placeholders::_1 ) ), states.end() ); + states.erase( std::remove_if( states.begin(), states.end(), [](auto &s){ return s.empty(); } ), states.end() ); for( auto it = states.begin(); it != states.end(); ++it ) set += SUID( *it ); diff --git a/src/waLBerlaDefinitions.in.h b/src/waLBerlaDefinitions.in.h index 21d1dd6d3..c729cd2af 100644 --- a/src/waLBerlaDefinitions.in.h +++ b/src/waLBerlaDefinitions.in.h @@ -51,12 +51,7 @@ #cmakedefine WALBERLA_CXX_COMPILER_IS_CLANG #cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_FILESYSTEM -#cmakedefine WALBERLA_USE_STD_FILESYSTEM #cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_ANY -#cmakedefine WALBERLA_USE_STD_ANY -#cmakedefine WALBERLA_USE_STD_EXPERIMENTAL_OPTIONAL -#cmakedefine WALBERLA_USE_STD_OPTIONAL -#cmakedefine WALBERLA_USE_STD_VARIANT #cmakedefine WALBERLA_BUILD_WITH_BACKTRACE #ifdef WALBERLA_BUILD_WITH_BACKTRACE #define WALBERLA_BACKTRACE_HEADER "${Backtrace_HEADER}" diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index 89583aadb..df07f5c8f 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -220,7 +220,7 @@ waLBerla_execute_test( NAME UNIQUEID PROCESSES 4) waLBerla_compile_test( FILES VersionTest.cpp ) waLBerla_execute_test( NAME VersionTest ) -if( WALBERLA_BUILD_WITH_BOOST OR WALBERLA_USE_STD_VARIANT ) +if ( WALBERLA_CXX_COMPILER_IS_INTEL AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS "20.0" ) waLBerla_compile_test( FILES VariantTest ) waLBerla_execute_test( NAME VariantTest ) endif() diff --git a/tests/core/VariantTest.cpp b/tests/core/VariantTest.cpp index a879b5b98..89eaf99ea 100644 --- a/tests/core/VariantTest.cpp +++ b/tests/core/VariantTest.cpp @@ -41,36 +41,31 @@ int main( int /*argc*/, char** /*argv*/ ) walberla::variant<int, float> v, w; v = 12; // v contains int int i = walberla::get<int>( v ); -#ifdef WALBERLA_USE_STD_VARIANT - WALBERLA_CHECK( i == 12 ); // boost::variant cannot use == with variant and type -#endif WALBERLA_CHECK( 0 == 12 - i ); w = walberla::get<int>( v ); w = v; -#ifdef WALBERLA_USE_STD_VARIANT - WALBERLA_CHECK( w == 12 ); // boost::variant cannot use == with variant and type -#endif WALBERLA_CHECK( 0 == 12 - i ); // walberla::get<double>(v); // error: no double in [int, float] // walberla::get<3>(v); // error: valid index values are 0 and 1 try { - walberla::get<float>( w ); // w contains int, not float: will throw + float f = walberla::get<float>( w ); // w contains int, not float: will throw + std::cout << f << std::endl; } catch ( const walberla::bad_variant_access& ) {} walberla::variant<std::string> x( "abc" ); // converting constructors work when unambiguous x = "def"; // converting assignment also works when unambiguous std::cout << "hallo" << std::endl; - walberla::variant<std::string, bool> y( "abc" ); // casts to bool when passed a char const * + walberla::variant<std::string, bool> y( true ); std::cout << "eoo" << std::endl; WALBERLA_CHECK( walberla::holds_alternative<bool>( y ) ); // succeeds y = "xyz"s; WALBERLA_CHECK( walberla::holds_alternative<std::string>( y ) ); //succeeds std::cout << "bye" << std::endl; - std::vector<var_t> vec {10, 15l, 1.5, "hello"}; + std::vector<var_t> vec = {10, 15l, 1.5, "hello"}; for ( auto& z : vec ) { // 1. void visitor, only called for side-effects (here, for I/O) diff --git a/tests/timeloop/TimeloopAndSweepRegister.cpp b/tests/timeloop/TimeloopAndSweepRegister.cpp index 9e0a2d39b..028e5fad7 100644 --- a/tests/timeloop/TimeloopAndSweepRegister.cpp +++ b/tests/timeloop/TimeloopAndSweepRegister.cpp @@ -30,7 +30,6 @@ using namespace std; -using namespace boost; using namespace walberla; diff --git a/utilities/conda/walberla/bld.bat b/utilities/conda/walberla/bld.bat index 2b90c35b5..64c851061 100644 --- a/utilities/conda/walberla/bld.bat +++ b/utilities/conda/walberla/bld.bat @@ -6,9 +6,7 @@ cmake -LAH -G"Visual Studio 15 2017 Win64" ^ -DWALBERLA_BUILD_WITH_PYTHON=ON ^ -DWALBERLA_BUILD_WITH_MPI=OFF ^ -DWALBERLA_BUILD_WITH_OPENMP=ON ^ - -DPYTHON_EXECUTABLE="%PYTHON%" ^ - -DBoost_USE_STATIC_LIBS=OFF ^ - -DBoost_USE_MULTITHREADED=ON .. + -DPYTHON_EXECUTABLE="%PYTHON%" .. if errorlevel 1 exit 1 cmake --build . --config Release --target pythonModuleInstall diff --git a/utilities/conda/walberla/meta.yaml b/utilities/conda/walberla/meta.yaml index 2148479bb..80a1cefc0 100644 --- a/utilities/conda/walberla/meta.yaml +++ b/utilities/conda/walberla/meta.yaml @@ -14,12 +14,10 @@ requirements: - make host: - python - - boost - mpich [linux] - openmesh run: - python - - boost - numpy - mpich [linux] - openmesh -- GitLab From e21cd0ea590e2fa83708327080030954d357289c Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Tue, 29 Dec 2020 10:13:24 +0100 Subject: [PATCH 23/83] Add block data --- apps/pythonmodule/PythonModule.cpp | 12 +- python/waLBerla/callbacks.py | 2 +- python/waLBerla_docs/modules/core.rst | 4 + python/waLBerla_tests/test_field.py | 8 +- src/python_coupling/CreateConfig.cpp | 27 ++-- src/python_coupling/export/BasicExport.cpp | 8 -- .../export/BlockForestExport.cpp | 23 ++++ .../export/FieldCommunicationExport.impl.h | 121 ++++++++++++++++++ 8 files changed, 166 insertions(+), 39 deletions(-) diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp index 419b1b377..b32f103dd 100644 --- a/apps/pythonmodule/PythonModule.cpp +++ b/apps/pythonmodule/PythonModule.cpp @@ -40,34 +40,24 @@ using namespace walberla; Field<walberla::real_t,1>,\ Field<walberla::real_t,2>,\ Field<walberla::real_t,3>,\ - Field<walberla::real_t,4>,\ - Field<walberla::real_t,5>,\ - Field<walberla::real_t,6>,\ Field<walberla::real_t,9>,\ Field<walberla::real_t,15>,\ Field<walberla::real_t,19>,\ Field<walberla::real_t,27>,\ Field<walberla::int8_t,1>,\ - Field<walberla::int16_t,1>,\ - Field<walberla::int32_t,1>,\ Field<walberla::int64_t,1>,\ Field<walberla::int64_t,2>,\ Field<walberla::int64_t,3>,\ - Field<walberla::int64_t,4>,\ Field<walberla::uint8_t,1>,\ Field<walberla::uint16_t,1>,\ Field<walberla::uint32_t,1> #define GPU_FIELD_TYPES \ - GPUField<double>,\ - GPUField<float>,\ + GPUField<real_t>,\ GPUField<int8_t>,\ - GPUField<int16_t>,\ GPUField<int32_t>,\ GPUField<int64_t>,\ GPUField<uint8_t>,\ - GPUField<uint16_t>,\ - GPUField<uint32_t>,\ GPUField<uint64_t> struct InitObject diff --git a/python/waLBerla/callbacks.py b/python/waLBerla/callbacks.py index f9153ec5b..07f2ebc0f 100644 --- a/python/waLBerla/callbacks.py +++ b/python/waLBerla/callbacks.py @@ -149,7 +149,7 @@ class ScenarioManager: cfg = None while cfg is None: cfg = get_config_from_scenario(scenario) - # walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios))) + walberla_cpp.log_info_on_root("Simulating Scenario %d of %d :" % (idx + 1, len(self._scenarios))) yield cfg except ImportError: diff --git a/python/waLBerla_docs/modules/core.rst b/python/waLBerla_docs/modules/core.rst index c1253ba29..ee8d985a3 100644 --- a/python/waLBerla_docs/modules/core.rst +++ b/python/waLBerla_docs/modules/core.rst @@ -198,6 +198,10 @@ Block Structure .. py:method:: containsGlobalBlockInformation( ) .. py:method:: blocksOverlappedByAABB( point, aabb ) .. py:method:: blocksContainedWithinAABB( point, aabb ) + + .. py:method:: addBlockData( name, blockdata) + + Adds custom data to the blockforest. This can be a Python Class for example which is then callable on all blocks .. py:method:: blockExists( point ) .. py:method:: blockExistsLocally( point ) diff --git a/python/waLBerla_tests/test_field.py b/python/waLBerla_tests/test_field.py index 3ab25c418..04ab5afb4 100644 --- a/python/waLBerla_tests/test_field.py +++ b/python/waLBerla_tests/test_field.py @@ -18,14 +18,14 @@ class FieldModuleTest(unittest.TestCase): def testNumpyConversionWithoutGhostLayers(self): blocks = createUniformBlockGrid(blocks=(1, 1, 1), cellsPerBlock=(1, 2, 3), periodic=(True, False, False)) - field.addToStorage(blocks, 'f1', np.float64, fSize=4, ghostLayers=0, initValue=2.0) - field.addToStorage(blocks, 'f2', np.float64, fSize=5, ghostLayers=0, initValue=2.0) + field.addToStorage(blocks, 'f1', np.float64, fSize=2, ghostLayers=0, initValue=2.0) + field.addToStorage(blocks, 'f2', np.float64, fSize=3, ghostLayers=0, initValue=2.0) f1np = field.toArray(blocks[0]['f1']) f2np = field.toArray(blocks[0]['f2']) self.assertEqual(f1np[0, 0, 0, 0], 2.0) - self.assertEqual(f1np.shape, (1, 2, 3, 4)) - self.assertEqual(f2np.shape, (1, 2, 3, 5)) + self.assertEqual(f1np.shape, (1, 2, 3, 2)) + self.assertEqual(f2np.shape, (1, 2, 3, 3)) def testGhostLayerExtraction(self): size = (10, 5, 4) diff --git a/src/python_coupling/CreateConfig.cpp b/src/python_coupling/CreateConfig.cpp index c7e3d1b24..5f8f9615c 100644 --- a/src/python_coupling/CreateConfig.cpp +++ b/src/python_coupling/CreateConfig.cpp @@ -70,30 +70,27 @@ shared_ptr< Config > createConfigFromPythonScript(const std::string& scriptFile, class PythonMultipleConfigGenerator : public config::ConfigGenerator { public: - PythonMultipleConfigGenerator(py::list ConfigList) // NOLINT - : ConfigList_(ConfigList), counter(0) // NOLINT + PythonMultipleConfigGenerator(py::object ScenarioConfigGenerator) // NOLINT + : ScenarioConfigGenerator_(ScenarioConfigGenerator) // NOLINT {} shared_ptr< Config > next() override { shared_ptr< Config > config = make_shared< Config >(); - - if ( counter == ConfigList_.size() ) + try + { + py::dict configDict = ScenarioConfigGenerator_.attr("__next__")(); + configFromPythonDict(config->getWritableGlobalBlock(), configDict); + return config; + } + catch (py::error_already_set&) + { return shared_ptr<Config>(); - - py::dict configDict = ConfigList_[counter]; - configFromPythonDict(config->getWritableGlobalBlock(), configDict); - - WALBERLA_LOG_INFO_ON_ROOT("Simulating Scenario " << counter + 1 << " of " << ConfigList_.size() << ":") - - counter++; - - return config; + } } private: - py::list ConfigList_; - uint_t counter; + py::object ScenarioConfigGenerator_; }; class PythonSingleConfigGenerator : public config::ConfigGenerator diff --git a/src/python_coupling/export/BasicExport.cpp b/src/python_coupling/export/BasicExport.cpp index 279e304e5..c4fad8eb6 100644 --- a/src/python_coupling/export/BasicExport.cpp +++ b/src/python_coupling/export/BasicExport.cpp @@ -55,14 +55,6 @@ # include <pybind11/stl.h> -// specialize operator== since == is deprecated in pybind11 -template<> -bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==( - const BlockData::DataBase& rhs) const -{ - const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs); - return (rhsData == &rhs) && (data_->is(*(rhsData->data_))); -} namespace py = pybind11; namespace walberla { diff --git a/src/python_coupling/export/BlockForestExport.cpp b/src/python_coupling/export/BlockForestExport.cpp index 7d2c9d764..e4aae6226 100644 --- a/src/python_coupling/export/BlockForestExport.cpp +++ b/src/python_coupling/export/BlockForestExport.cpp @@ -42,6 +42,15 @@ # include "BlockForestExport.h" # include "python_coupling/helper/OwningIterator.h" +// specialize operator== since == is deprecated in pybind11 +template<> +bool walberla::domain_decomposition::internal::BlockData::Data< pybind11::object >::operator==( + const BlockData::DataBase& rhs) const +{ + const Data< pybind11::object >* rhsData = dynamic_cast< const Data< pybind11::object >* >(&rhs); + return (rhsData == &rhs) && (data_->is(*(rhsData->data_))); +} + namespace walberla { namespace blockforest @@ -257,6 +266,19 @@ bool p_blockExistsRemotely1(StructuredBlockForest& s, const std::array<real_t, 3 } +py::object * blockDataCreationHelper( IBlock * block, py::object callable ) //NOLINT +{ + py::object * res = new py::object( callable( block )); + return res; +} + +uint_t StructuredBlockForest_addBlockData( StructuredBlockForest & s, const std::string & name, py::object functionPtr ) //NOLINT +{ + BlockDataID res = s.addBlockData(name) + << BlockDataCreator<py::object>( std::bind( &blockDataCreationHelper, std::placeholders::_1, functionPtr ) ); + return res; +} + bool SbF_atDomainXMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMinBorder(*b); } bool SbF_atDomainXMaxBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainXMaxBorder(*b); } bool SbF_atDomainYMinBorder(StructuredBlockForest& s, const IBlock* b) { return s.atDomainYMinBorder(*b); } @@ -278,6 +300,7 @@ void exportBlockForest(py::module_& m) py::class_< StructuredBlockForest, std::shared_ptr< StructuredBlockForest > >(m, "StructuredBlockForest") .def("getNumberOfLevels", &StructuredBlockForest::getNumberOfLevels) .def_property_readonly("getDomain", &StructuredBlockForest::getDomain) + .def( "addBlockData", &StructuredBlockForest_addBlockData) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain1) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain2) .def("mapToPeriodicDomain", &SbF_mapToPeriodicDomain3) diff --git a/src/python_coupling/export/FieldCommunicationExport.impl.h b/src/python_coupling/export/FieldCommunicationExport.impl.h index 0793b26a5..57289631d 100644 --- a/src/python_coupling/export/FieldCommunicationExport.impl.h +++ b/src/python_coupling/export/FieldCommunicationExport.impl.h @@ -51,6 +51,119 @@ namespace internal { namespace py = pybind11; +//=================================================================================================================== +// +// createStencilRestrictedPackInfo Export +// +//=================================================================================================================== + +template< typename FieldType > +typename std::enable_if<FieldType::F_SIZE == 27, py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField<typename FieldType::value_type, 27> GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q27> >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if<FieldType::F_SIZE == 19, py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField<typename FieldType::value_type, 19> GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q19> >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if<FieldType::F_SIZE == 15, py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField<typename FieldType::value_type, 15> GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q15> >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if<FieldType::F_SIZE == 7, py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField<typename FieldType::value_type, 7> GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D3Q7> >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if<FieldType::F_SIZE == 9, py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID bdId ) +{ + typedef GhostLayerField<typename FieldType::value_type, 9> GlField_T; + using field::communication::StencilRestrictedPackInfo; + return py::cast( make_shared< StencilRestrictedPackInfo<GlField_T, stencil::D2Q9> >( bdId) ); +} + +template< typename FieldType > +typename std::enable_if<!(FieldType::F_SIZE == 9 || + FieldType::F_SIZE == 7 || + FieldType::F_SIZE == 15 || + FieldType::F_SIZE == 19 || + FieldType::F_SIZE == 27), py::object>::type +createStencilRestrictedPackInfoObject( BlockDataID ) +{ + throw py::value_error("This works only for fields with fSize in 7, 9, 15, 19 or 27"); +} + +class StencilRestrictedPackInfoExporter +{ + public: + StencilRestrictedPackInfoExporter(const shared_ptr<StructuredBlockForest> & blocks, BlockDataID fieldId) + : blocks_(blocks), fieldId_(fieldId) + {} + + template< typename FieldType> + void operator() ( python_coupling::NonCopyableWrap<FieldType> ) + { + typedef typename FieldType::value_type T; + const uint_t F_SIZE = FieldType::F_SIZE; + typedef GhostLayerField<T, F_SIZE> GlField_T; + IBlock * firstBlock = & ( * blocks_->begin() ); + if( firstBlock->isDataClassOrSubclassOf<FieldType>(fieldId_) ) + { + resultStencilRestrictedPackInfo_ = createStencilRestrictedPackInfoObject<GlField_T>(fieldId_); + } + } + py::object getResultStencilRestrictedPackInfo() + { + return resultStencilRestrictedPackInfo_; + } + + private: + py::object resultStencilRestrictedPackInfo_; + shared_ptr< StructuredBlockStorage > blocks_; + BlockDataID fieldId_; +}; + +template<typename... FieldTypes> +static py::object StencilRestrictedPackInfoWrapper(const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName ) +{ + BlockDataID fieldID = python_coupling::blockDataIDFromString( *blocks, blockDataName ); + + if ( blocks->begin() == blocks->end() ) { + // if no blocks are on this field an arbitrary PackInfo can be returned + return py::cast( make_shared< field::communication::StencilRestrictedPackInfo<GhostLayerField<real_t, 9>, stencil::D2Q9> >( fieldID ) ); + } + + StencilRestrictedPackInfoExporter exporter(blocks, fieldID); + python_coupling::for_each_noncopyable_type< FieldTypes... > ( std::ref(exporter) ); + if ( ! exporter.getResultStencilRestrictedPackInfo() ) { + throw py::value_error("Failed to create Stencil Restricted PackInfo"); + } + else { + return exporter.getResultStencilRestrictedPackInfo(); + } +} + //=================================================================================================================== // // createPackInfo Export @@ -241,6 +354,14 @@ void exportCommunicationClasses(py::module_& m) return internal::UniformMPIDatatypeInfoWrapper< FieldTypes... >(blocks, blockDataName, numberOfGhostLayers); }, "blocks"_a, "blockDataName"_a, "numberOfGhostLayers"_a = uint_t(0)); + + m2.def( + "createStencilRestrictedPackInfo", + [](const shared_ptr<StructuredBlockForest> & blocks, + const std::string & blockDataName) { + return internal::StencilRestrictedPackInfoWrapper< FieldTypes... >(blocks, blockDataName); + }, + "blocks"_a, "blockDataName"_a); } } // namespace field -- GitLab From ad457d814e25b032b06d1e279ecce549b0deb5e6 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Wed, 30 Dec 2020 16:19:47 +0100 Subject: [PATCH 24/83] Restore MSVC 14.1 compatibility MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - OpenMP pragma parser bug - std::string doesn’t like to be aligned to more than 256 bits --- src/boundary/BoundaryHandling.h | 2 +- src/field/Field.impl.h | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/boundary/BoundaryHandling.h b/src/boundary/BoundaryHandling.h index 96f93c991..cf724cdc1 100644 --- a/src/boundary/BoundaryHandling.h +++ b/src/boundary/BoundaryHandling.h @@ -2230,7 +2230,7 @@ inline void BoundaryHandling< FlagField_T, Stencil, Boundaries... >::operator()( WALBERLA_ASSERT( checkConsistency( localCells ) ); - #ifdef _OPENMP + #if defined(_OPENMP) && !(defined(_MSC_VER) && _MSC_VER < 1925) const int zMin = int_c( localCells.zMin() ); const int zMax = int_c( localCells.zMax() ); #pragma omp parallel for schedule(static) if(threadSafeBCs_) diff --git a/src/field/Field.impl.h b/src/field/Field.impl.h index e1515cb75..4856de7ee 100644 --- a/src/field/Field.impl.h +++ b/src/field/Field.impl.h @@ -318,6 +318,12 @@ namespace field { { #ifdef __BIGGEST_ALIGNMENT__ const uint_t alignment = __BIGGEST_ALIGNMENT__; +#elif defined(__AVX512F__) + const uint_t alignment = 64; +#elif defined(__AVX__) + const uint_t alignment = 32; +#elif defined(__SSE__) || defined(_MSC_VER) + const uint_t alignment = 16; #else const uint_t alignment = 64; #endif -- GitLab From 659c76d321db23343c15baa0f9fc4ee9e2f04728 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Thu, 31 Dec 2020 16:06:10 +0100 Subject: [PATCH 25/83] eliminate some warnings about range-based for loops incorrectly using references --- tests/core/GridGeneratorTest.cpp | 2 +- tests/geometry/BinaryRawFileTest.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/core/GridGeneratorTest.cpp b/tests/core/GridGeneratorTest.cpp index 7971b5f07..670279459 100644 --- a/tests/core/GridGeneratorTest.cpp +++ b/tests/core/GridGeneratorTest.cpp @@ -98,7 +98,7 @@ void rangeBasedTest() auto dx = Vector3<real_t>( Grid::iterator::getUnitCellX(spacing), Grid::iterator::getUnitCellY(spacing), Grid::iterator::getUnitCellZ(spacing) ); auto lowerIt = typename Grid::iterator(domain, Vector3<real_t>(5,5,5) - dx * 30, spacing); auto endIt = typename Grid::iterator(); - for ( const auto& pt : Grid(domain, Vector3<real_t>(5,5,5) - dx * 30, spacing) ) + for ( const auto pt : Grid(domain, Vector3<real_t>(5,5,5) - dx * 30, spacing) ) { WALBERLA_CHECK( lowerIt != endIt ); WALBERLA_CHECK_FLOAT_EQUAL( *lowerIt, pt); diff --git a/tests/geometry/BinaryRawFileTest.cpp b/tests/geometry/BinaryRawFileTest.cpp index cc219ea1b..22ce402d9 100644 --- a/tests/geometry/BinaryRawFileTest.cpp +++ b/tests/geometry/BinaryRawFileTest.cpp @@ -59,7 +59,7 @@ void test( const std::string & filename, const Vector3<uint_t> & size, const std CellInterval ci( 0, 0, 0, cell_idx_c( size[0] ) - 1, cell_idx_c( size[1] ) - 1, cell_idx_c( size[2] ) - 1 ); - for (const Cell & c : ci) + for (const Cell c : ci) { field->get( c ) = brf.get( uint_c( c[0] ), uint_c( c[1] ), uint_c( c[2] ) ); } @@ -100,7 +100,7 @@ void testScaled( const std::string & filename, const Vector3<uint_t> & size, con CellInterval ci( 0, 0, 0, cell_idx_c( scaledSize[0] ) - 1, cell_idx_c( scaledSize[1] ) - 1, cell_idx_c( scaledSize[2] ) - 1 ); - for (const Cell & c : ci) + for (const Cell c : ci) { auto pos = blocks->getBlockLocalCellCenter( block, c ); field->get( c ) = brfi.get( pos ); -- GitLab From f4124ee192b9b7505d55a1c224e51c1b55b1e809 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Thu, 31 Dec 2020 16:09:08 +0100 Subject: [PATCH 26/83] eliminate most compiler-specific workarounds --- CMakeLists.txt | 44 +++---------- .../PhaseFieldAllenCahn/CPU/contact.cpp | 8 +-- .../PhaseFieldAllenCahn/CPU/contact.h | 8 --- .../PhaseFieldAllenCahn/GPU/contact.cu | 20 +++--- .../PhaseFieldAllenCahn/GPU/contact.h | 8 --- src/blockforest/BlockForest.cpp | 2 +- src/blockforest/BlockID.cpp | 8 +-- src/core/NonCreateable.h | 30 +-------- src/core/Sanitizer.h | 7 +- src/core/Sleep.cpp | 31 ++------- src/core/Template.h | 65 ------------------- src/core/math/Constants.h | 6 -- src/core/math/Parser.cpp | 4 +- src/core/math/Uint.cpp | 6 -- src/core/math/Uint.h | 13 ++-- src/core/mpi/BufferDataTypeExtensions.h | 13 ---- src/field/iterators/IteratorMacros.h | 4 +- .../initializer/ExprSystemInitFunction.cpp | 4 +- src/pe/rigidbody/Owner.cpp | 0 src/python_coupling/PythonWrapper.h | 17 ----- src/simd/SIMD.h | 4 +- src/stencil/Directions.h | 1 - tests/simd/CMakeLists.txt | 8 +-- 23 files changed, 51 insertions(+), 260 deletions(-) delete mode 100644 src/core/Template.h delete mode 100644 src/pe/rigidbody/Owner.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c62caabc3..174015bc7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,9 +227,6 @@ mark_as_advanced ( WALBERLA_CXX_COMPILER_IS_CLANG ) if( CMAKE_CXX_COMPILER_ID MATCHES Cray ) option ( WALBERLA_CXX_COMPILER_IS_CRAY "Use Cray compiler" ON ) - if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 8.4) - message( FATAL_ERROR "Insufficient Cray Compiler Environment version" ) - endif() else() option ( WALBERLA_CXX_COMPILER_IS_CRAY "Use Cray compiler" OFF ) endif() @@ -690,8 +687,14 @@ endif( Boost_FOUND ) ## ############################################################################################################################ -if ( NOT WIN32 ) - add_flag( CMAKE_CXX_FLAGS "-pthread" ) +set( THREADS_PREFER_PTHREAD_FLAG TRUE ) +find_package(Threads) +if ( Threads_FOUND ) + if( CMAKE_USE_PTHREADS_INIT ) + add_flag( CMAKE_CXX_FLAGS "-pthread" ) + else() + add_flag( CMAKE_CXX_FLAGS "${CMAKE_THREAD_LIBS_INIT}" ) + endif() endif() @@ -975,10 +978,7 @@ endif() option ( WALBERLA_THREAD_SAFE_LOGGING "Enables/Disables thread-safe logging" ON ) if ( WALBERLA_BUILD_WITH_OPENMP ) - if ( WALBERLA_CXX_COMPILER_IS_INTEL AND "${CMAKE_CXX_COMPILER_VERSION}" VERSION_LESS "16.0.3" ) - add_flag ( CMAKE_C_FLAGS "-openmp" ) - add_flag ( CMAKE_CXX_FLAGS "-openmp" ) - elseif ( WALBERLA_CXX_COMPILER_IS_NEC ) + if ( WALBERLA_CXX_COMPILER_IS_NEC ) add_flag ( CMAKE_C_FLAGS "-Popenmp" ) add_flag ( CMAKE_CXX_FLAGS "-Popenmp" ) else() @@ -1089,31 +1089,7 @@ endif() ## ############################################################################################################################ if ( WALBERLA_BUILD_WITH_LTO ) - - if( WALBERLA_CXX_COMPILER_IS_INTEL ) - add_flag( CMAKE_CXX_FLAGS_RELEASE "-ip -ipo3" ) - add_flag( CMAKE_C_FLAGS_RELEASE "-ip -ipo3" ) - endif() - - if ( CMAKE_COMPILER_IS_GNUCXX ) - add_flag ( CMAKE_C_FLAGS_RELEASE "-flto=3" ) - add_flag ( CMAKE_CXX_FLAGS_RELEASE "-flto=3" ) - add_flag ( CMAKE_EXE_LINKER_FLAGS "-fuse-linker-plugin" ) - endif ( ) - - if( WALBERLA_CXX_COMPILER_IS_MSVC ) - add_flag ( CMAKE_CXX_FLAGS_RELEASE "/GL" ) - add_flag ( CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG" ) - add_flag ( CMAKE_SHARED_LINKER_FLAGS_RELEASE "/LTCG" ) - add_flag ( CMAKE_MODULE_LINKER_FLAGS_RELEASE "/LTCG" ) - endif ( ) - - if( WALBERLA_CXX_COMPILER_IS_IBM ) - add_flag ( CMAKE_C_FLAGS_RELEASE "-qipa" ) - add_flag ( CMAKE_CXX_FLAGS_RELEASE "-qipa" ) - add_flag ( CMAKE_EXE_LINKER_FLAGS "-qipa" ) - endif( ) - + set( CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE ) endif ( ) ############################################################################################################################ diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/contact.cpp b/apps/showcases/PhaseFieldAllenCahn/CPU/contact.cpp index 4e87ab28f..8253e1d4c 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/contact.cpp +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/contact.cpp @@ -36,7 +36,7 @@ namespace lbm namespace internal_boundary_contact { -static FUNC_PREFIX void contact_angle_treatment(uint8_t* RESTRICT const _data_indexVector, double* RESTRICT _data_phase, +static FUNC_PREFIX void contact_angle_treatment(uint8_t* WALBERLA_RESTRICT const _data_indexVector, double* WALBERLA_RESTRICT _data_phase, int64_t const _stride_phase_0, int64_t const _stride_phase_1, int64_t const _stride_phase_2, int64_t indexVectorSize, double alpha) { @@ -58,8 +58,8 @@ static FUNC_PREFIX void contact_angle_treatment(uint8_t* RESTRICT const _data_in const double a = cos(alpha); const double W = 5; - double* RESTRICT _phase_wall = _data_phase + _stride_phase_1 * y + _stride_phase_2 * z; - double* RESTRICT _phase_interior = _data_phase + _stride_phase_1 * y1 + _stride_phase_2 * z1; + double* WALBERLA_RESTRICT _phase_wall = _data_phase + _stride_phase_1 * y + _stride_phase_2 * z; + double* WALBERLA_RESTRICT _phase_interior = _data_phase + _stride_phase_1 * y1 + _stride_phase_2 * z1; if (h < 0.001) { _phase_wall[_stride_phase_0 * x] = 1.0; } else if (a > 1e-8 || a < -1e-8) { @@ -98,7 +98,7 @@ void contact::run(IBlock* block, IndexVectors::Type type) auto& alpha = this->alpha_; WALBERLA_ASSERT_GREATER_EQUAL(0, -int_c(phaseField->nrOfGhostLayers())) - double* RESTRICT _data_phase = phaseField->dataAt(0, 0, 0, 0); + double* WALBERLA_RESTRICT _data_phase = phaseField->dataAt(0, 0, 0, 0); const auto _stride_pdfs_0 = int64_t(phaseField->xStride()); const auto _stride_pdfs_1 = int64_t(phaseField->yStride()); const auto _stride_pdfs_2 = int64_t(phaseField->zStride()); diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/contact.h b/apps/showcases/PhaseFieldAllenCahn/CPU/contact.h index c53419516..dbaf4a560 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/contact.h +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/contact.h @@ -31,14 +31,6 @@ #include <set> #include <vector> -#ifdef __GNUC__ -# define RESTRICT __restrict__ -#elif _MSC_VER -# define RESTRICT __restrict -#else -# define RESTRICT -#endif - namespace walberla { namespace lbm diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/contact.cu b/apps/showcases/PhaseFieldAllenCahn/GPU/contact.cu index 6a42483ba..48d26d1c5 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/contact.cu +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/contact.cu @@ -41,25 +41,25 @@ namespace lbm namespace internal_boundary_contact { -static FUNC_PREFIX void contact_angle_treatment(uint8_t* RESTRICT const _data_indexVector, double* RESTRICT _data_phase, +static FUNC_PREFIX void contact_angle_treatment(uint8_t* WALBERLA_RESTRICT const _data_indexVector, double* WALBERLA_RESTRICT _data_phase, int64_t const _stride_phase_0, int64_t const _stride_phase_1, int64_t const _stride_phase_2, int64_t indexVectorSize, double alpha) { if (blockDim.x * blockIdx.x + threadIdx.x < indexVectorSize) { - uint8_t* RESTRICT _data_indexVector_10 = _data_indexVector; + uint8_t* WALBERLA_RESTRICT _data_indexVector_10 = _data_indexVector; const int32_t x = *((int32_t*) (&_data_indexVector_10[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); - uint8_t* RESTRICT _data_indexVector_14 = _data_indexVector + 4; + uint8_t* WALBERLA_RESTRICT _data_indexVector_14 = _data_indexVector + 4; const int32_t y = *((int32_t*) (&_data_indexVector_14[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); - uint8_t* RESTRICT _data_indexVector_18 = _data_indexVector + 8; + uint8_t* WALBERLA_RESTRICT _data_indexVector_18 = _data_indexVector + 8; const int32_t z = *((int32_t*) (&_data_indexVector_18[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); - uint8_t* RESTRICT _data_indexVector_112 = _data_indexVector + 12; + uint8_t* WALBERLA_RESTRICT _data_indexVector_112 = _data_indexVector + 12; const int32_t nx = *((int32_t*) (&_data_indexVector_112[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); const int32_t x1 = x + nx; - uint8_t* RESTRICT _data_indexVector_116 = _data_indexVector + 16; + uint8_t* WALBERLA_RESTRICT _data_indexVector_116 = _data_indexVector + 16; const int32_t ny = *((int32_t*) (&_data_indexVector_116[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); const int32_t y1 = y + ny; - uint8_t* RESTRICT _data_indexVector_200 = _data_indexVector + 20; + uint8_t* WALBERLA_RESTRICT _data_indexVector_200 = _data_indexVector + 20; const int32_t nz = *((int32_t*) (&_data_indexVector_200[24 * blockDim.x * blockIdx.x + 24 * threadIdx.x])); const int32_t z1 = z + nz; @@ -67,8 +67,8 @@ static FUNC_PREFIX void contact_angle_treatment(uint8_t* RESTRICT const _data_in const double a = cos(alpha); const double W = 5; - double* RESTRICT _phase_wall = _data_phase + _stride_phase_1 * y + _stride_phase_2 * z; - double* RESTRICT _phase_interior = _data_phase + _stride_phase_1 * y1 + _stride_phase_2 * z1; + double* WALBERLA_RESTRICT _phase_wall = _data_phase + _stride_phase_1 * y + _stride_phase_2 * z; + double* WALBERLA_RESTRICT _phase_interior = _data_phase + _stride_phase_1 * y1 + _stride_phase_2 * z1; if (h < 0.001) { _phase_wall[_stride_phase_0 * x] = 1.0; } else if (a > 1e-8 || a < -1e-8) { @@ -107,7 +107,7 @@ void contact::run(IBlock* block, IndexVectors::Type type, cudaStream_t stream) auto& alpha = this->alpha_; WALBERLA_ASSERT_GREATER_EQUAL(0, -int_c(phaseField->nrOfGhostLayers())) - double* RESTRICT _data_phase = phaseField->dataAt(0, 0, 0, 0); + double* WALBERLA_RESTRICT _data_phase = phaseField->dataAt(0, 0, 0, 0); const auto _stride_pdfs_0 = int64_t(phaseField->xStride()); const auto _stride_pdfs_1 = int64_t(phaseField->yStride()); const auto _stride_pdfs_2 = int64_t(phaseField->zStride()); diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/contact.h b/apps/showcases/PhaseFieldAllenCahn/GPU/contact.h index 2ce5deefb..f2cd84cd0 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/contact.h +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/contact.h @@ -32,14 +32,6 @@ #include <set> #include <vector> -#ifdef __GNUC__ -# define RESTRICT __restrict__ -#elif _MSC_VER -# define RESTRICT __restrict -#else -# define RESTRICT -#endif - namespace walberla { namespace lbm diff --git a/src/blockforest/BlockForest.cpp b/src/blockforest/BlockForest.cpp index 62affa837..70b1fdaf4 100644 --- a/src/blockforest/BlockForest.cpp +++ b/src/blockforest/BlockForest.cpp @@ -1661,7 +1661,7 @@ bool BlockForest::determineBlockTargetLevels( bool & additionalRefreshCycleRequi minTargetLevels[id] = minTargetLevel; } } -#ifndef NDEBUF +#ifndef NDEBUG else { WALBERLA_ASSERT_LESS_EQUAL( minTargetLevel, level + uint_t(1) ); diff --git a/src/blockforest/BlockID.cpp b/src/blockforest/BlockID.cpp index 886567ed9..865cfcb2e 100644 --- a/src/blockforest/BlockID.cpp +++ b/src/blockforest/BlockID.cpp @@ -135,11 +135,9 @@ void BlockID::toByteArray( std::vector< uint8_t >& array, const uint_t offset, c #else -#ifdef WALBERLA_CXX_COMPILER_IS_MSVC -namespace { char dummy; } // disable MSVC warning LNK4221: This object file does not define any previously - // undefined public symbols, so it will not be used by any link operation that - // consumes this library -#endif +namespace internal { +char dummy; // silence linker warning about object file with no symbols +} #endif diff --git a/src/core/NonCreateable.h b/src/core/NonCreateable.h index 42dc0057b..fb291a3a9 100644 --- a/src/core/NonCreateable.h +++ b/src/core/NonCreateable.h @@ -35,34 +35,8 @@ namespace walberla{ class NonCreateable { -#ifndef _MSC_VER - - // non-MSVC-Build - -private: - - NonCreateable(); - ~NonCreateable(); - - NonCreateable(const NonCreateable&); - NonCreateable& operator=(const NonCreateable&); - -#else - - // MSVC-Build (eliminating warning C4624) - -private: - - NonCreateable(); - NonCreateable(const NonCreateable&); - - NonCreateable& operator=(const NonCreateable&); - -protected: - - ~NonCreateable(); - -#endif +public: + NonCreateable() = delete; }; diff --git a/src/core/Sanitizer.h b/src/core/Sanitizer.h index 8ccb5f7b8..86ff57516 100644 --- a/src/core/Sanitizer.h +++ b/src/core/Sanitizer.h @@ -21,16 +21,15 @@ #pragma once -#if (( defined WALBERLA_CXX_COMPILER_IS_CLANG ) && ( __clang_major__ >=4 ) ) \ - || (( defined WALBERLA_CXX_COMPILER_IS_GNU ) && ( __GNUC__ >= 5 ) ) +#if defined(WALBERLA_CXX_COMPILER_IS_CLANG) || defined(WALBERLA_CXX_COMPILER_IS_GNU) # define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) #else # define ATTRIBUTE_NO_SANITIZE_ADDRESS #endif -#if ( ( defined WALBERLA_CXX_COMPILER_IS_GNU ) && ( __GNUC__ >= 5 ) ) +#if defined(WALBERLA_CXX_COMPILER_IS_GNU) # define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize_undefined)) -#elif (( defined WALBERLA_CXX_COMPILER_IS_CLANG ) && ( __clang_major__ >= 4 ) ) +#elif defined(WALBERLA_CXX_COMPILER_IS_CLANG) # define ATTRIBUTE_NO_SANITIZE_UNDEFINED __attribute__((no_sanitize("undefined"))) #else # define ATTRIBUTE_NO_SANITIZE_UNDEFINED diff --git a/src/core/Sleep.cpp b/src/core/Sleep.cpp index ae26ea9cf..8706a72ec 100644 --- a/src/core/Sleep.cpp +++ b/src/core/Sleep.cpp @@ -22,36 +22,13 @@ #include "Sleep.h" #include "waLBerlaDefinitions.h" -#ifdef WALBERLA_CXX_COMPILER_IS_MSVC - -#include <windows.h> +#include <thread> namespace walberla { - void sleep( uint_t seconds ) - { - ::Sleep( static_cast<DWORD>( uint_t(1000) * seconds ) ); - } - +void sleep( uint_t seconds ) +{ + std::this_thread::sleep_for(std::chrono::seconds(static_cast<int>(seconds))); } -#else - -#ifdef WALBERLA_CXX_COMPILER_IS_IBM -#ifndef _POSIX_SOURCE -#define _POSIX_SOURCE -#endif -#endif - -#include <unistd.h> - -namespace walberla { - - void sleep( uint_t seconds ) - { - ::sleep( static_cast<unsigned int>(seconds) ); - } - } - -#endif \ No newline at end of file diff --git a/src/core/Template.h b/src/core/Template.h deleted file mode 100644 index 861c7bebd..000000000 --- a/src/core/Template.h +++ /dev/null @@ -1,65 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \file Template.h -//! \ingroup core -//! \author Klaus Iglberger -//! \author Sebastian Eibl <sebastian.eibl@fau.de> -// -//====================================================================================================================== - -#pragma once - - -//************************************************************************************************* -/*! \cond internal */ -/*!\brief Compiler specific patch for nested template disambiguation. - * \ingroup util - * - * The WALBERLA_TEMPLATE is a patch for the Microsoft Visual C++ compiler that does not correctly - * parse definitions of nested templates of the following form: - - \code - template< typename T > - class Alloc { - public: - ... - template< typename Other > - class rebind { - public: - typedef Alloc<Other> other; - }; - ... - }; - - typedef Alloc<int> AI; - typedef AI::template rebind<double>::other Other; // Compilation error with Visual C++ - \endcode - - * In order to circumvent this compilation error, the WALBERLA_TEMPLATE macro should be used instead - * the \a template keyword: - - \code - ... - typedef AI::WALBERLA_TEMPLATE rebind<double>::other Other; // No compilation errors - \endcode - */ -#if defined(_MSC_VER) -# define WALBERLA_TEMPLATE -#else -# define WALBERLA_TEMPLATE template -#endif -/*! \endcond */ -//************************************************************************************************* diff --git a/src/core/math/Constants.h b/src/core/math/Constants.h index 79e97e97e..92e49678d 100644 --- a/src/core/math/Constants.h +++ b/src/core/math/Constants.h @@ -30,12 +30,6 @@ #include <cmath> #include <core/DataTypes.h> -// Disable false warnings in GCC 5 -#if (defined __GNUC__) && (__GNUC__ == 5) && (__GNUC_MINOR__ == 1) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-variable" -#endif - namespace walberla { namespace math diff --git a/src/core/math/Parser.cpp b/src/core/math/Parser.cpp index b3a457567..7c39e5e9d 100644 --- a/src/core/math/Parser.cpp +++ b/src/core/math/Parser.cpp @@ -31,9 +31,7 @@ # pragma warning( disable : 4706 ) #elif ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) # pragma GCC diagnostic push -# if !( ( __clang_major__ == 3 ) && ( __clang_minor__ <= 4 ) ) -# pragma GCC diagnostic ignored "-Wpragmas" -# endif +# pragma GCC diagnostic ignored "-Wpragmas" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wshorten-64-to-32" diff --git a/src/core/math/Uint.cpp b/src/core/math/Uint.cpp index 38f8003e7..347f639b8 100644 --- a/src/core/math/Uint.cpp +++ b/src/core/math/Uint.cpp @@ -49,11 +49,5 @@ template<> uint_t uintMSBPosition< uint64_t >( uint64_t value ) { // for the doc return ( i != 0 ) ? (8 + msbLookupTable[i]) : msbLookupTable[value]; } -#ifndef WALBERLA_CXX_COMPILER_IS_MSVC - -const uint_t int_ld<1>::exp; - -#endif - } // namespace math } // namespace walberla diff --git a/src/core/math/Uint.h b/src/core/math/Uint.h index 5a76bc8fa..3b0ab1721 100644 --- a/src/core/math/Uint.h +++ b/src/core/math/Uint.h @@ -222,8 +222,8 @@ struct leastUnsignedInteger }; /// \cond internal -static const uint_t UINT_BITS = static_cast< uint_t >( std::numeric_limits< uint_t >::digits ); -static const uint_t UINT_BYTES = static_cast< uint_t >( std::numeric_limits< uint_t >::digits ) >> 3; +static constexpr uint_t UINT_BITS = static_cast< uint_t >( std::numeric_limits< uint_t >::digits ); +static constexpr uint_t UINT_BYTES = static_cast< uint_t >( std::numeric_limits< uint_t >::digits ) >> 3; static_assert( !(UINT_BITS & (UINT_BITS - 1)), "Type \"uint_t\" must consist of 2^x Bits!" ); // power of two @@ -231,18 +231,17 @@ template< int N > struct int_ld { static_assert( N >= 1 && !(N & (N - 1)), "Calculating log_2(N) -> \"N\" must be a power of two!" ); - static const uint_t exp = 1 + int_ld< (N >> 1) >::exp; + static constexpr uint_t exp = 1 + int_ld< (N >> 1) >::exp; + static_assert( exp > 0 ); }; -template< int N > const uint_t int_ld<N>::exp; - template<> struct int_ld<1> { - static const uint_t exp = 0; + static constexpr uint_t exp = 0; }; -static const uint_t UINT_BITS_LD = int_ld< std::numeric_limits< uint_t >::digits >::exp; +static constexpr uint_t UINT_BITS_LD = int_ld< std::numeric_limits< uint_t >::digits >::exp; /// \endcond } // namespace math diff --git a/src/core/mpi/BufferDataTypeExtensions.h b/src/core/mpi/BufferDataTypeExtensions.h index 3196b5362..69f3e52e9 100644 --- a/src/core/mpi/BufferDataTypeExtensions.h +++ b/src/core/mpi/BufferDataTypeExtensions.h @@ -143,13 +143,6 @@ void sendContainer( GenericSendBuffer<T,G> & buf, const Cont & container ) } -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#if __GNUC__ == 4 && __GNUC_MINOR__ == 9 || __GNUC__ == 6 -#pragma GCC push_options -#pragma GCC optimize(2) -#endif -#endif - template< typename T, // Element type of RecvBuffer typename Cont> // Container void recvContainer( GenericRecvBuffer<T> & buf, Cont & container ) @@ -162,12 +155,6 @@ void recvContainer( GenericRecvBuffer<T> & buf, Cont & container ) buf >> *it; } -#ifdef WALBERLA_CXX_COMPILER_IS_GNU -#if __GNUC__ == 4 && __GNUC_MINOR__ == 9 || __GNUC__ == 6 -#pragma GCC pop_options -#endif -#endif - template< typename T, // Element type of SendBuffer diff --git a/src/field/iterators/IteratorMacros.h b/src/field/iterators/IteratorMacros.h index 08e8d5d97..ed5b98711 100644 --- a/src/field/iterators/IteratorMacros.h +++ b/src/field/iterators/IteratorMacros.h @@ -149,7 +149,7 @@ #ifdef _OPENMP -#ifdef WALBERLA_CXX_COMPILER_IS_MSVC +#if (defined(_MSC_VER) && _MSC_VER < 1926) #define WALBERLA_FOR_ALL_CELLS_XYZ_OMP( field, omp, CODE ) \ { WALBERLA_ASSERT_NOT_NULLPTR_1( (field) ); \ @@ -875,7 +875,7 @@ } \ } } -#else // == not WALBERLA_CXX_COMPILER_IS_MSVC +#else // == MSVC >= 2019 16.6 or not MSVC #define WALBERLA_FOR_ALL_CELLS_XYZ_OMP( field, omp, CODE ) \ { WALBERLA_ASSERT_NOT_NULLPTR_1( (field) ); \ diff --git a/src/lbm/field/initializer/ExprSystemInitFunction.cpp b/src/lbm/field/initializer/ExprSystemInitFunction.cpp index abb2f028c..bb3f5ebcd 100644 --- a/src/lbm/field/initializer/ExprSystemInitFunction.cpp +++ b/src/lbm/field/initializer/ExprSystemInitFunction.cpp @@ -27,9 +27,7 @@ # pragma warning( disable : 4706 ) #elif ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) # pragma GCC diagnostic push -# if !( ( __clang_major__ == 3 ) && ( __clang_minor__ <= 4 ) ) -# pragma GCC diagnostic ignored "-Wpragmas" -# endif +# pragma GCC diagnostic ignored "-Wpragmas" # pragma GCC diagnostic ignored "-Wsign-conversion" # pragma GCC diagnostic ignored "-Wconversion" # pragma GCC diagnostic ignored "-Wshorten-64-to-32" diff --git a/src/pe/rigidbody/Owner.cpp b/src/pe/rigidbody/Owner.cpp deleted file mode 100644 index e69de29bb..000000000 diff --git a/src/python_coupling/PythonWrapper.h b/src/python_coupling/PythonWrapper.h index 7ae14bada..3909af052 100644 --- a/src/python_coupling/PythonWrapper.h +++ b/src/python_coupling/PythonWrapper.h @@ -28,23 +28,6 @@ #ifdef WALBERLA_BUILD_WITH_PYTHON // macro defined in waLBerlaDefinitions.h -#ifdef _MSC_VER -#pragma warning ( push, 3 ) -#pragma warning ( disable: 4244 4275 4800 4251 4267 ) -#ifndef HAVE_ROUND -#define HAVE_ROUND 1 -#define __CREATED_HAVE_ROUND -#endif -#endif - #include "pybind11/pybind11.h" -#ifdef _MSC_VER -#ifdef __CREATED_HAVE_ROUND -#undef HAVE_ROUND -#undef __CREATED_HAVE_ROUND -#endif -#pragma warning ( pop ) -#endif - #endif diff --git a/src/simd/SIMD.h b/src/simd/SIMD.h index d0feb81e7..2998cef34 100644 --- a/src/simd/SIMD.h +++ b/src/simd/SIMD.h @@ -127,7 +127,7 @@ namespace simd { template<typename T> struct is_vector4_type { static const bool value = false; }; -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) && ( __GNUC__ >= 6 ) +#ifdef WALBERLA_CXX_COMPILER_IS_GNU # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wignored-attributes" #endif @@ -168,7 +168,7 @@ template<typename T> struct is_vector4_type { static const bool value = false; #endif -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) && ( __GNUC__ >= 6 ) +#ifdef WALBERLA_CXX_COMPILER_IS_GNU # pragma GCC diagnostic pop #endif diff --git a/src/stencil/Directions.h b/src/stencil/Directions.h index 4d42e24cd..cc3cfa29b 100644 --- a/src/stencil/Directions.h +++ b/src/stencil/Directions.h @@ -10,7 +10,6 @@ // core includes #include "core/DataTypes.h" -#include "core/NonCreateable.h" #include "core/cell/Cell.h" #include "core/debug/Debug.h" diff --git a/tests/simd/CMakeLists.txt b/tests/simd/CMakeLists.txt index 060dd5b61..6fa07c3c5 100644 --- a/tests/simd/CMakeLists.txt +++ b/tests/simd/CMakeLists.txt @@ -8,12 +8,8 @@ # builds the test -if ( CMAKE_COMPILER_IS_GNUCXX ) - if( CMAKE_CXX_COMPILER_VERSION VERSION_LESS "4.7.0" ) - set( MarchNativeString "" ) - else() - set( MarchNativeString "-march=native" ) - endif() +if ( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_CLANG ) + set( MarchNativeString "-march=native" ) endif() waLBerla_compile_test( NAME AVX2_AVX_Equivalence FILES SIMD_Equivalence.cpp ) -- GitLab From 72ca3f72bd6658453ebb7ce824778296638f9e52 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Fri, 1 Jan 2021 18:55:28 +0100 Subject: [PATCH 27/83] Disable some warnings on PGI compiler --- CMakeLists.txt | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 174015bc7..bc0d8638d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -225,6 +225,7 @@ else() endif() mark_as_advanced ( WALBERLA_CXX_COMPILER_IS_CLANG ) +# Check for Cray compiler if( CMAKE_CXX_COMPILER_ID MATCHES Cray ) option ( WALBERLA_CXX_COMPILER_IS_CRAY "Use Cray compiler" ON ) else() @@ -232,6 +233,13 @@ else() endif() mark_as_advanced ( WALBERLA_CXX_COMPILER_IS_CRAY ) +if( CMAKE_CXX_COMPILER MATCHES "pgc\\+\\+" OR CMAKE_CXX_COMPILER_ARG1 MATCHES "pgc\\+\\+" ) + option ( WALBERLA_CXX_COMPILER_IS_PGI "Use PGI compiler" ON ) +else() + option ( WALBERLA_CXX_COMPILER_IS_PGI "Use PGI compiler" OFF ) +endif() +mark_as_advanced ( WALBERLA_CXX_COMPILER_IS_PGI ) + # Check for MPI wrapper get_filename_component( CXX_COMPILER_WITHOUT_PATH ${CMAKE_CXX_COMPILER} NAME ) if( CXX_COMPILER_WITHOUT_PATH MATCHES "mpi" OR CMAKE_CXX_COMPILER_ARG1 MATCHES "mpi" ) @@ -330,6 +338,21 @@ if( WALBERLA_CXX_COMPILER_IS_CRAY ) add_flag ( CMAKE_CXX_FLAGS "-DSQLITE_HAVE_ISNAN" ) # SQLite will not work correctly with the -ffast-math option of GCC. endif() +# Silences compiler and linker warnings and information with the PGI compiler +if( WALBERLA_CXX_COMPILER_IS_PGI ) + add_flag ( CMAKE_CXX_FLAGS "--display_error_number" ) + add_flag ( CMAKE_C_FLAGS "--display_error_number" ) + if( CMAKE_VERSION VERSION_LESS "3.19" ) + # https://github.com/Kitware/CMake/commit/52eee1938919deb59cc2b51d44f365f0d9a418e5 + set( CMAKE_CXX${CMAKE_CXX_STANDARD}_STANDARD_COMPILE_OPTION "--c++${CMAKE_CXX_STANDARD}" ) + endif() + add_flag ( CMAKE_CXX_FLAGS "--diag_suppress=1" ) # last line of file ends without a newline + add_flag ( CMAKE_CXX_FLAGS "--diag_suppress=111" ) # statement is unreachable + add_flag ( CMAKE_C_FLAGS "--diag_suppress=111" ) # statement is unreachable + add_flag ( CMAKE_C_FLAGS "--diag_suppress=550" ) # variable [...] was set but never used + add_flag ( CMAKE_C_FLAGS "--diag_suppress=191" ) # type qualifier is meaningless on cast type +endif() + # architecture optimization if( WALBERLA_OPTIMIZE_FOR_LOCALHOST ) if( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_INTEL OR WALBERLA_CXX_COMPILER_IS_CLANG ) -- GitLab From 9d781038639470fd3c5d4c1fb9066684fc1c6e53 Mon Sep 17 00:00:00 2001 From: markus holzer <markus.holzer@fau.de> Date: Tue, 5 Jan 2021 15:29:27 +0100 Subject: [PATCH 28/83] Added ifs in CMake --- apps/benchmarks/CMakeLists.txt | 23 +++++++++++++------ apps/benchmarks/UniformGridGPU/CMakeLists.txt | 1 + apps/showcases/CMakeLists.txt | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index ec223734f..d16b4255d 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -1,7 +1,6 @@ add_subdirectory( AdaptiveMeshRefinementFluidParticleCoupling ) add_subdirectory( ComplexGeometry ) add_subdirectory( DEM ) -add_subdirectory( FieldCommunication ) add_subdirectory( MeshDistance ) add_subdirectory( CouetteFlow ) add_subdirectory( FluidParticleCoupling ) @@ -15,10 +14,20 @@ add_subdirectory( PoiseuilleChannel ) add_subdirectory( ProbeVsExtraMessage ) add_subdirectory( SchaeferTurek ) add_subdirectory( UniformGrid ) -if ( WALBERLA_BUILD_WITH_CODEGEN AND WALBERLA_BUILD_WITH_PYTHON ) -add_subdirectory( UniformGridGenerated ) -add_subdirectory( PhaseFieldAllenCahn ) -endif() -if ( WALBERLA_BUILD_WITH_CODEGEN AND WALBERLA_BUILD_WITH_CUDA ) -add_subdirectory( UniformGridGPU ) + +if ( WALBERLA_BUILD_WITH_PYTHON ) + add_subdirectory( FieldCommunication ) + + if ( WALBERLA_BUILD_WITH_CODEGEN ) + add_subdirectory( UniformGridGenerated ) + add_subdirectory( PhaseFieldAllenCahn ) + endif() + + if ( WALBERLA_BUILD_WITH_CODEGEN AND WALBERLA_BUILD_WITH_CUDA ) + add_subdirectory( UniformGridGPU ) + endif() + endif() + + + diff --git a/apps/benchmarks/UniformGridGPU/CMakeLists.txt b/apps/benchmarks/UniformGridGPU/CMakeLists.txt index 9fe54701f..29755644d 100644 --- a/apps/benchmarks/UniformGridGPU/CMakeLists.txt +++ b/apps/benchmarks/UniformGridGPU/CMakeLists.txt @@ -1,5 +1,6 @@ waLBerla_link_files_to_builddir( "*.prm" ) +waLBerla_link_files_to_builddir( "*.py" ) waLBerla_link_files_to_builddir( "simulation_setup" ) diff --git a/apps/showcases/CMakeLists.txt b/apps/showcases/CMakeLists.txt index cfdbf9591..30592ee71 100644 --- a/apps/showcases/CMakeLists.txt +++ b/apps/showcases/CMakeLists.txt @@ -3,6 +3,6 @@ add_subdirectory( CombinedResolvedUnresolved ) add_subdirectory( HeatConduction ) add_subdirectory( Mixer ) add_subdirectory( PegIntoSphereBed ) -if ( WALBERLA_BUILD_WITH_CODEGEN) +if ( WALBERLA_BUILD_WITH_CODEGEN AND WALBERLA_BUILD_WITH_PYTHON ) add_subdirectory( PhaseFieldAllenCahn ) endif() -- GitLab From 3c9c1f5937f03a0535686d5be7d16401e97a8ed8 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 22 Dec 2020 13:56:16 +0100 Subject: [PATCH 29/83] [UPDATE] readme and contributors --- AUTHORS.txt | 2 ++ README.md | 32 +++++++++++++++++++++++--------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/AUTHORS.txt b/AUTHORS.txt index fd6d6505b..b0dba6103 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -13,7 +13,9 @@ Dominik Bartuschat Ehsan Fattahi Felix Winterhalter Florian Schornbaum +Grigorii Drozdov Helen Schottenhamml +Igor Ostanin Jan Götz Jan Hönig João Victor Tozatti Risso diff --git a/README.md b/README.md index 9d87364cf..2fe23457a 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,29 @@ Many thanks go to waLBerla's [contributors](AUTHORS.txt) If you use waLBerla in a publication, please cite the following articles: -- C. Godenschwager, F. Schornbaum, M. Bauer, H. Köstler, and U. Rüde. A -framework for hybrid parallel flow simulations with a trillion cells in complex -geometries. In: Proceedings of the International Conference on High Performance -Computing, Networking, Storage and Analysis, page 35. ACM, 2013. -- M. Bauer, S. Eibl, C. Godenschwager, N. Kohl, M. Kuron, C. Rettinger, -F. Schornbaum, C. Schwarzmeier, D. Thönnes, H. Köstler, and U. Rüde. waLBerla: -A block-structured high-performance framework for multiphysics simulations. In: -Computers & Mathematics with Applications, doi:10.1016/j.camwa.2020.01.007. -Elsevier, 2020. +Overview: + - M. Bauer et al, *waLBerla: A block-structured high-performance framework for + multiphysics simulations*. Computers & Mathematics with Applications, 2020, + https://doi.org/10.1016/j.camwa.2020.01.007. + +Grid Refinement: + - F. Schornbaum and U. Rüde, *Massively parallel algorithms for the lattice boltzmann + method on nonuniform grids*. SIAM Journal on Scientific Computing, 2016. + https://doi.org/10.1137/15M1035240 + +LBM - Particles Coupling: + - C. Rettinger and U. Rüde, *Dynamic load balancing techniques for particulate flow simulations*. + Computation, 2019. https://doi.org/10.3390/computation7010009 + +MESA-PD: + - S. Eibl and U. Rüde, *A Modular and Extensible Software Architecture for Particle Dynamics*. + Proceedings Of The 8Th International Conference On Discrete Element Methods. + https://mercurylab.co.uk/dem8/full-papers/#page-content + +Carbon Nanotubes: + - G. Drozdov et al, *Densification of single-walled carbon nanotube films: + Mesoscopic distinct element method simulations and experimental validation*. + Journal of Applied Physics, 2020. https://doi.org/10.1063/5.0025505 ## License -- GitLab From 95b421fce009aee6687bfc508e5fc6826f06d83d Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 16:41:28 +0100 Subject: [PATCH 30/83] [ADD] radians <-> degree conversion functions --- src/core/math/Angles.h | 34 +++++++++++++++++++++++++++++ tests/core/Angles.test.cpp | 44 ++++++++++++++++++++++++++++++++++++++ tests/core/CMakeLists.txt | 3 +++ 3 files changed, 81 insertions(+) create mode 100644 src/core/math/Angles.h create mode 100644 tests/core/Angles.test.cpp diff --git a/src/core/math/Angles.h b/src/core/math/Angles.h new file mode 100644 index 000000000..3294d892b --- /dev/null +++ b/src/core/math/Angles.h @@ -0,0 +1,34 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "Constants.h" + +namespace walberla +{ +namespace math +{ +///Converts a degrees angle to radians. +constexpr real_t degToRad(real_t deg) {return deg * (pi / real_t(180));} +///Converts a radians angle to degrees. +constexpr real_t radToDeg(real_t rad) {return rad * (real_t(180) / pi);} +} // namespace math +} // namespace walberla diff --git a/tests/core/Angles.test.cpp b/tests/core/Angles.test.cpp new file mode 100644 index 000000000..6190dc41b --- /dev/null +++ b/tests/core/Angles.test.cpp @@ -0,0 +1,44 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "core/DataTypes.h" +#include "core/math/Angles.h" +#include "core/debug/TestSubsystem.h" + +namespace walberla{ + +int main( int /*argc*/, char** /*argv*/ ) +{ + using namespace walberla::math; + + debug::enterTestMode(); + + WALBERLA_CHECK_FLOAT_EQUAL( radToDeg(half_pi), 90_r ); + WALBERLA_CHECK_FLOAT_EQUAL( half_pi, degToRad(90_r) ); + + return EXIT_SUCCESS; +} + +} //namespace walberla + +int main( int argc, char** argv ) +{ + return walberla::main(argc, argv); +} diff --git a/tests/core/CMakeLists.txt b/tests/core/CMakeLists.txt index df07f5c8f..992b516f4 100644 --- a/tests/core/CMakeLists.txt +++ b/tests/core/CMakeLists.txt @@ -186,6 +186,9 @@ else() endif() waLBerla_execute_test( NAME AllHeaderTest ) +waLBerla_compile_test( FILES Angles.test.cpp ) +waLBerla_execute_test( NAME Angles ) + waLBerla_compile_test( FILES ConcatIterator.cpp ) waLBerla_execute_test( NAME ConcatIterator ) -- GitLab From db86915e7c1119c8f6155c4fcb299c1164770e47 Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Thu, 7 Jan 2021 11:03:55 +0100 Subject: [PATCH 31/83] Update README.md --- README.md | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 2fe23457a..bca339ae9 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # waLBerla -waLBerla (widely applicable Lattice Boltzmann from Erlangen) is a massively -parallel framework for multi physics applications. Besides its original -objective, Lattice Boltzmann solvers for hydrodynamics, it now contains -modules for other applications like Multigrid and rigid body dynamics -as well. Great emphasis is placed on the interoperability between the modules -in particular the fluid-particle coupling. -It scales from laptops to current and future supercomputers while maintaining +waLBerla (widely applicable Lattice Boltzmann from Erlangen) is a massively +parallel framework for multi physics applications. Besides its original +objective, Lattice Boltzmann solvers for hydrodynamics, it now contains +modules for other applications like Multigrid and rigid body dynamics +as well. Great emphasis is placed on the interoperability between the modules +in particular the fluid-particle coupling. +It scales from laptops to current and future supercomputers while maintaining near-perfect efficiency. See https://www.walberla.net/ for more information and a showcase of applications. @@ -48,27 +48,28 @@ Many thanks go to waLBerla's [contributors](AUTHORS.txt) If you use waLBerla in a publication, please cite the following articles: Overview: - - M. Bauer et al, *waLBerla: A block-structured high-performance framework for - multiphysics simulations*. Computers & Mathematics with Applications, 2020, + - M. Bauer et al, *waLBerla: A block-structured high-performance framework for + multiphysics simulations*. Computers & Mathematics with Applications, 2020. https://doi.org/10.1016/j.camwa.2020.01.007. - + Grid Refinement: - - F. Schornbaum and U. Rüde, *Massively parallel algorithms for the lattice boltzmann - method on nonuniform grids*. SIAM Journal on Scientific Computing, 2016. + - F. Schornbaum and U. Rüde, *Massively parallel algorithms for the lattice boltzmann + method on nonuniform grids*. SIAM Journal on Scientific Computing, 2016. https://doi.org/10.1137/15M1035240 - -LBM - Particles Coupling: - - C. Rettinger and U. Rüde, *Dynamic load balancing techniques for particulate flow simulations*. - Computation, 2019. https://doi.org/10.3390/computation7010009 - + +LBM - Particle Coupling: + - C. Rettinger and U. Rüde, *A comparative study of fluid-particle coupling methods for + fully resolved lattice Boltzmann simulations*. Computers & Fluids, 2017. + https://doi.org/10.1016/j.compfluid.2017.05.033 + MESA-PD: - - S. Eibl and U. Rüde, *A Modular and Extensible Software Architecture for Particle Dynamics*. + - S. Eibl and U. Rüde, *A Modular and Extensible Software Architecture for Particle Dynamics*. Proceedings Of The 8Th International Conference On Discrete Element Methods. https://mercurylab.co.uk/dem8/full-papers/#page-content - + Carbon Nanotubes: - - G. Drozdov et al, *Densification of single-walled carbon nanotube films: - Mesoscopic distinct element method simulations and experimental validation*. + - G. Drozdov et al, *Densification of single-walled carbon nanotube films: + Mesoscopic distinct element method simulations and experimental validation*. Journal of Applied Physics, 2020. https://doi.org/10.1063/5.0025505 ## License -- GitLab From 539237b0a0a5a29a142a40c94fcbae98f4da9de5 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 3 Nov 2020 10:25:03 +0100 Subject: [PATCH 32/83] added unit test for infinite domain --- src/mesa_pd/domain/InfiniteDomain.h | 18 ++++++-- tests/mesa_pd/CMakeLists.txt | 3 ++ tests/mesa_pd/domain/InfiniteDomain.cpp | 60 +++++++++++++++++++++++++ 3 files changed, 78 insertions(+), 3 deletions(-) create mode 100644 tests/mesa_pd/domain/InfiniteDomain.cpp diff --git a/src/mesa_pd/domain/InfiniteDomain.h b/src/mesa_pd/domain/InfiniteDomain.h index b9dc4f322..591da8902 100644 --- a/src/mesa_pd/domain/InfiniteDomain.h +++ b/src/mesa_pd/domain/InfiniteDomain.h @@ -20,22 +20,34 @@ #pragma once +#include <core/mpi/MPIManager.h> #include <mesa_pd/domain/IDomain.h> namespace walberla { namespace mesa_pd { namespace domain { +/** + * Every process assumes the whole simulation space belongs to its subdomain. + */ class InfiniteDomain : public IDomain { public: - bool isContainedInProcessSubdomain(const uint_t /*rank*/, const Vec3& /*pt*/) const override {return true;} - int findContainingProcessRank(const Vec3& /*pt*/) const override {return walberla::mpi::MPIManager::instance()->rank();} + ///Everything belongs to the calling process. + bool isContainedInProcessSubdomain(const uint_t rank, const Vec3& /*pt*/) const override {return rank==rank_;} + ///Everything belongs to the calling process. + int findContainingProcessRank(const Vec3& /*pt*/) const override {return static_cast<int>(rank_);} + ///Nothing to do here since domain is infinite. void periodicallyMapToDomain(Vec3& /*pt*/) const override {} + ///If I own everything I do not have neighbors. std::vector<uint_t> getNeighborProcesses() const override {return {};} + ///Everything belongs to my subdomain. bool intersectsWithProcessSubdomain(const uint_t rank, const Vec3& /*pt*/, const real_t& /*radius*/) const override - { return int_c(rank)==walberla::mpi::MPIManager::instance()->rank() ? true : false;} + { return rank==rank_;} + ///Nothing to do here. void correctParticlePosition(Vec3& /*pt*/) const override {} +private: + const uint_t rank_ = static_cast<uint_t>(MPIManager::instance()->rank()); }; } //namespace domain diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index ad034a098..6bbc471dc 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -66,6 +66,9 @@ waLBerla_execute_test( NAME MESA_PD_Domain_DistanceCalculation ) waLBerla_compile_test( NAME MESA_PD_Domain_DynamicRefinement FILES domain/DynamicRefinement.cpp DEPENDS blockforest core pe ) waLBerla_execute_test( NAME MESA_PD_Domain_DynamicRefinement PROCESSES 8) +waLBerla_compile_test( NAME MESA_PD_Domain_InfiniteDomain FILES domain/InfiniteDomain.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Domain_InfiniteDomain ) + waLBerla_compile_test( NAME MESA_PD_Domain_SerializeDeserialize FILES domain/SerializeDeserialize.cpp DEPENDS blockforest core pe) waLBerla_execute_test( NAME MESA_PD_Domain_SerializeDeserialize PROCESSES 8 ) diff --git a/tests/mesa_pd/domain/InfiniteDomain.cpp b/tests/mesa_pd/domain/InfiniteDomain.cpp new file mode 100644 index 000000000..74dee98a9 --- /dev/null +++ b/tests/mesa_pd/domain/InfiniteDomain.cpp @@ -0,0 +1,60 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file InfiniteDomain.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/domain/InfiniteDomain.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { + +using namespace walberla::mesa_pd; + +void main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + auto rank = mpi::MPIManager::instance()->rank(); + + auto randomPoint = Vec3(1.23_r,2.34_r,3.45_r); + domain::InfiniteDomain domain; + WALBERLA_CHECK(domain.isContainedInProcessSubdomain(static_cast<uint_t>(rank), randomPoint)); + WALBERLA_CHECK(!domain.isContainedInProcessSubdomain(static_cast<uint_t>(rank + 1), randomPoint)); + WALBERLA_CHECK_EQUAL(domain.findContainingProcessRank(randomPoint), rank); + auto pt = randomPoint; + domain.periodicallyMapToDomain(pt); + WALBERLA_CHECK_IDENTICAL(pt, randomPoint); + WALBERLA_CHECK_EQUAL(domain.getNeighborProcesses().size(), 0); + WALBERLA_CHECK(domain.intersectsWithProcessSubdomain(static_cast<uint_t>(rank), randomPoint, 1_r)); + WALBERLA_CHECK(!domain.intersectsWithProcessSubdomain(static_cast<uint_t>(rank + 1), randomPoint, 1_r)); + domain.correctParticlePosition(pt); + WALBERLA_CHECK_IDENTICAL(pt, randomPoint); +} + +} + +int main( int argc, char ** argv ) +{ + walberla::main(argc, argv); + return EXIT_SUCCESS; +} -- GitLab From 43b8bacf1d7ef8ecf8a5ee48eac69a950b1c4585 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 3 Nov 2020 10:39:19 +0100 Subject: [PATCH 33/83] added unit test for contact history --- tests/mesa_pd/CMakeLists.txt | 3 ++ tests/mesa_pd/data/ContactHistory.cpp | 72 +++++++++++++++++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 tests/mesa_pd/data/ContactHistory.cpp diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 6bbc471dc..0c3e69f27 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -37,6 +37,9 @@ waLBerla_execute_test( NAME MESA_PD_COMMON_IntersectionRatio ) waLBerla_compile_test( NAME MESA_PD_ContactDetection FILES ContactDetection.cpp DEPENDS blockforest core pe) waLBerla_execute_test( NAME MESA_PD_ContactDetection PROCESSES 8 ) +waLBerla_compile_test( NAME MESA_PD_Data_ContactHistory FILES data/ContactHistory.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Data_ContactHistory ) + waLBerla_compile_test( NAME MESA_PD_Data_Flags FILES data/Flags.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Data_Flags ) diff --git a/tests/mesa_pd/data/ContactHistory.cpp b/tests/mesa_pd/data/ContactHistory.cpp new file mode 100644 index 000000000..fbc237eda --- /dev/null +++ b/tests/mesa_pd/data/ContactHistory.cpp @@ -0,0 +1,72 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file ContactHistory.cpp +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ContactHistory.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <algorithm> +#include <iostream> + +namespace walberla { + +using namespace walberla::mesa_pd; + +void basic_test() +{ + //init data structures + data::ContactHistory cs; + + cs.setImpactVelocityMagnitude(1.23456_r); + cs.setIsSticking(true); + cs.setTangentialSpringDisplacement(Vec3(1.23_r,2.345_r,3.56_r)); + + mpi::SendBuffer sb; + sb << cs; + mpi::RecvBuffer rb(sb); + + data::ContactHistory cs_recv; + rb >> cs_recv; + + WALBERLA_CHECK_IDENTICAL(cs.getImpactVelocityMagnitude(), cs_recv.getImpactVelocityMagnitude()); + WALBERLA_CHECK_IDENTICAL(cs.getIsSticking(), cs_recv.getIsSticking()); + WALBERLA_CHECK_IDENTICAL(cs.getTangentialSpringDisplacement(), cs_recv.getTangentialSpringDisplacement()); + + WALBERLA_LOG_DEVEL( cs ); +} + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + basic_test(); + + return EXIT_SUCCESS; +} + +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::main(argc, argv); +} -- GitLab From db2a27f6f8597846ebfe634753ba3eff65ec6b49 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Mon, 11 Jan 2021 17:19:12 +0100 Subject: [PATCH 34/83] make string literal _r constexpr --- src/core/DataTypes.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/DataTypes.h b/src/core/DataTypes.h index 28fdf80c7..121f836c5 100644 --- a/src/core/DataTypes.h +++ b/src/core/DataTypes.h @@ -163,8 +163,8 @@ typedef double real_t; typedef float real_t; #endif -inline real_t operator"" _r( long double t ) { return static_cast< real_t >(t); } -inline real_t operator"" _r( unsigned long long int t ) { return static_cast< real_t >(t); } +inline constexpr real_t operator"" _r( long double t ) { return static_cast< real_t >(t); } +inline constexpr real_t operator"" _r( unsigned long long int t ) { return static_cast< real_t >(t); } template< typename T > inline real_t real_c ( T t ) { return numeric_cast< real_t >(t); } ///< cast to type real_t using "real_c(x)" template< typename T > inline double double_c( T t ) { return numeric_cast< double >(t); } ///< cast to type double template< typename T > inline float float_c ( T t ) { return numeric_cast< float > (t); } ///< cast to type float -- GitLab From d37a1961da4d63fea7fe4353b3de5ac62aca2d7b Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Tue, 12 Jan 2021 18:27:50 +0100 Subject: [PATCH 35/83] Check whether LTO works before enabling it --- CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index bc0d8638d..4b05ed5d7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1112,7 +1112,14 @@ endif() ## ############################################################################################################################ if ( WALBERLA_BUILD_WITH_LTO ) - set( CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE ) + cmake_policy( SET CMP0069 NEW ) + include( CheckIPOSupported ) + check_ipo_supported( RESULT LTO_SUPPORTED LANGUAGES CXX ) + if( LTO_SUPPORTED ) + set( CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE ) + else() + message( WARNING "Link-time optimization is not supported with this compiler" ) + endif() endif ( ) ############################################################################################################################ -- GitLab From 88bb098cf3a089df712733131d506107f52f01fc Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Thu, 17 Dec 2020 15:40:02 +0100 Subject: [PATCH 36/83] [ADD] MESA-PD kernel for the VBondModel wall contact --- src/mesa_pd/kernel/VBondModel/WallContact.h | 113 ++++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/VBondModel/WallContact.test.cpp | 102 ++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 src/mesa_pd/kernel/VBondModel/WallContact.h create mode 100644 tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp diff --git a/src/mesa_pd/kernel/VBondModel/WallContact.h b/src/mesa_pd/kernel/VBondModel/WallContact.h new file mode 100644 index 000000000..24d153ca5 --- /dev/null +++ b/src/mesa_pd/kernel/VBondModel/WallContact.h @@ -0,0 +1,113 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace VBondModel { + +/** + * Repulsive wall interaction kernel. + * + * Implementation follows: + * Wittmaack, Volkov, Zhigilei, "Phase transformation as the mechanism of mechanical deformation of vertically aligned CNT arrays" - Carbon, 2019 + * https://doi.org/10.1016/j.carbon.2018.11.066 + * + * The force is divided into three areas. + * ========================== z=0, position of the wall + * close to wall + * -------------------------- z=z1+r + * spline interpolation + * -------------------------- z=z2+r + * far away from wall + */ +class WallContact +{ +public: + explicit WallContact(real_t zPos) : zPos_(zPos) {} + + template<typename Accessor> + void operator()(const size_t p_idx1, + Accessor &ac); + + static constexpr real_t r = 6.78_r; ///< A + static constexpr real_t eps = 0.254e-3_r; ///< eV/amu + static constexpr real_t m = 2648.8_r; ///< amu + static constexpr real_t s = 3.6_r; ///< A + static constexpr real_t s12 = ((s * s) * (s * s) * (s * s)) * ((s * s) * (s * s) * (s * s)); + + static constexpr real_t z1 = 10_r; ///< A + static constexpr real_t z2 = 12_r; ///< A + + auto getLastForce() const {return F_;} + + void setZPos(const real_t& zPos) {zPos_ = zPos;} + auto getZPos() const {return zPos_;} + +private: + real_t zPos_ = 0_r; + real_t F_ = 0_r; ///< resulting force from the last interaction +}; + +template<typename Accessor> +inline void WallContact::operator()(const size_t p_idx, + Accessor &ac) +{ + auto dz = ac.getPosition(p_idx)[2] - zPos_; + F_ = std::copysign(1_r, dz); + dz = std::abs(dz); + + if (dz < r + z1) + { + //close to wall + const auto tmp = dz - r; + const auto pow = ((tmp * tmp) * (tmp * tmp) * (tmp * tmp)) * ((tmp * tmp) * (tmp * tmp) * (tmp * tmp)) * tmp; + F_ *= m * eps * s12 * 12_r / pow; + } else if (dz < r + z2) + { + //cubic spline interpolation + auto S = [](real_t x) { return (3_r * (12_r + r) * (14_r + r) - 6_r * (13_r + r) * x + 3_r * x * x) * 5e-14_r; }; + F_ *= m * eps * s12 * S(dz); + } else + { + //far away from wall + F_ = 0_r; + } + + addForceAtomic( p_idx, ac, Vec3(0_r, 0_r, F_) ); +} + +} //namespace VBondModel +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 0c3e69f27..b68b61f25 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -164,6 +164,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) +waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_WallContact FILES kernel/VBondModel/WallContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_WallContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_VelocityVerlet FILES kernel/VelocityVerlet.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VelocityVerlet ) diff --git a/tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp b/tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp new file mode 100644 index 000000000..f923ee41d --- /dev/null +++ b/tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp @@ -0,0 +1,102 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleAccessor.h> +#include <mesa_pd/data/ParticleStorage.h> + +#include <mesa_pd/kernel/VBondModel/WallContact.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { +namespace mesa_pd { + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + //init data structures + data::SingleParticleAccessor p; + p.setPosition(0, Vec3(0,0,0)); + + //init kernels + kernel::VBondModel::WallContact wallContact(0_r); + + auto calcForce = [&](const real_t zPos) + { + clear(p.getForceRef(0)); + p.getPositionRef(0)[2] = zPos; + wallContact(0, p); + WALBERLA_CHECK_FLOAT_EQUAL(wallContact.getLastForce(), p.getForce(0)[2]); + return p.getForce(0)[2]; + }; + + WALBERLA_LOG_INFO("checking that force is always repulsive"); + WALBERLA_CHECK_GREATER_EQUAL( calcForce(wallContact.z1 * 0.5_r + wallContact.r), + 0_r ); + WALBERLA_CHECK_GREATER_EQUAL( calcForce((wallContact.z1 + wallContact.z2) * 0.5_r + wallContact.r), + 0_r ); + WALBERLA_CHECK_GREATER_EQUAL( calcForce(wallContact.z2 * 2_r + wallContact.r), + 0_r ); + + WALBERLA_CHECK_LESS_EQUAL( calcForce(-wallContact.z1 * 0.5_r - wallContact.r), + 0_r ); + WALBERLA_CHECK_LESS_EQUAL( calcForce(-(wallContact.z1 + wallContact.z2) * 0.5_r - wallContact.r), + 0_r ); + WALBERLA_CHECK_LESS_EQUAL( calcForce(-wallContact.z2 * 2_r - wallContact.r), + 0_r ); + + WALBERLA_LOG_INFO("checking that force is symmetric"); + WALBERLA_CHECK_FLOAT_EQUAL(calcForce(wallContact.z1 * 0.5_r + wallContact.r), + -calcForce(-wallContact.z1 * 0.5_r - wallContact.r) ); + WALBERLA_CHECK_FLOAT_EQUAL(calcForce((wallContact.z1 + wallContact.z2) * 0.5_r + wallContact.r), + -calcForce(-(wallContact.z1 + wallContact.z2) * 0.5_r - wallContact.r) ); + WALBERLA_CHECK_FLOAT_EQUAL(calcForce(wallContact.z2 * 2_r + wallContact.r), + -calcForce(-wallContact.z2 * 2_r - wallContact.r) ); + + WALBERLA_LOG_INFO("checking smoothness of the force"); + WALBERLA_CHECK_FLOAT_EQUAL( calcForce(std::nextafter(wallContact.z1 + wallContact.r, 0_r)), + calcForce(std::nextafter(wallContact.z1 + wallContact.r, std::numeric_limits<real_t>::infinity())) ); + WALBERLA_CHECK_FLOAT_EQUAL( calcForce(std::nextafter(wallContact.z2 + wallContact.r, 0_r)), + calcForce(std::nextafter(wallContact.z2 + wallContact.r, std::numeric_limits<real_t>::infinity())) ); + + return EXIT_SUCCESS; +} + +} //namespace mesa_pd +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::mesa_pd::main(argc, argv); +} -- GitLab From 0c5bee3223420db350449d31844a0f1018725e1a Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Sat, 16 Jan 2021 09:56:55 +0100 Subject: [PATCH 37/83] Update pybind11 --- extern/pybind11 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/pybind11 b/extern/pybind11 index 687c69625..48534089f 160000 --- a/extern/pybind11 +++ b/extern/pybind11 @@ -1 +1 @@ -Subproject commit 687c69625bd2b96ac0596d1a9cc0ab2101485d70 +Subproject commit 48534089f7f1b0229bc7ae2e4d0f21dc9ad169b5 -- GitLab From a89bd2c7661f73fcae39fca77cc518eff9d3cdfa Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 22 Jan 2021 09:37:27 +0100 Subject: [PATCH 38/83] making constructors constexpr --- src/core/math/Matrix3.h | 22 +++++++++++----------- src/core/math/Vector3.h | 24 ++++++++++++------------ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/core/math/Matrix3.h b/src/core/math/Matrix3.h index b206d484d..665c6529e 100644 --- a/src/core/math/Matrix3.h +++ b/src/core/math/Matrix3.h @@ -95,11 +95,11 @@ private: public: //**Constructors***************************************************************************************************** - explicit inline Matrix3() = default; - explicit inline Matrix3( Type init ); - explicit inline Matrix3( const Vector3<Type>& a, const Vector3<Type>& b, const Vector3<Type>& c ); - explicit inline Matrix3( Type xx, Type xy, Type xz, Type yx, Type yy, Type yz, Type zx, Type zy, Type zz ); - explicit inline Matrix3( const Type* init ); + explicit inline constexpr Matrix3() = default; + explicit inline constexpr Matrix3( Type init ); + explicit inline constexpr Matrix3( const Vector3<Type>& a, const Vector3<Type>& b, const Vector3<Type>& c ); + explicit inline constexpr Matrix3( Type xx, Type xy, Type xz, Type yx, Type yy, Type yz, Type zx, Type zy, Type zz ); + explicit inline constexpr Matrix3( const Type* init ); template< typename Axis, typename Angle > explicit Matrix3( Vector3<Axis> axis, Angle angle ); @@ -274,7 +274,7 @@ static_assert( std::is_trivially_copyable<Matrix3<real_t>>::value, "Matrix3<real // \param init Initial value for all matrix elements. */ template< typename Type > -inline Matrix3<Type>::Matrix3( Type init ) +inline constexpr Matrix3<Type>::Matrix3( Type init ) { v_[0] = v_[1] = v_[2] = v_[3] = v_[4] = v_[5] = v_[6] = v_[7] = v_[8] = init; } @@ -289,7 +289,7 @@ inline Matrix3<Type>::Matrix3( Type init ) // \param c The third column of the matrix. //********************************************************************************************************************** template< typename Type > -inline Matrix3<Type>::Matrix3( const Vector3<Type>& a, const Vector3<Type>& b, const Vector3<Type>& c ) +inline constexpr Matrix3<Type>::Matrix3( const Vector3<Type>& a, const Vector3<Type>& b, const Vector3<Type>& c ) { v_[0] = a[0]; v_[1] = b[0]; v_[2] = c[0]; v_[3] = a[1]; v_[4] = b[1]; v_[5] = c[1]; @@ -313,9 +313,9 @@ inline Matrix3<Type>::Matrix3( const Vector3<Type>& a, const Vector3<Type>& b, c // \param zz The initial value for the zz-component. */ template< typename Type > -inline Matrix3<Type>::Matrix3( Type xx, Type xy, Type xz, - Type yx, Type yy, Type yz, - Type zx, Type zy, Type zz ) +inline constexpr Matrix3<Type>::Matrix3( Type xx, Type xy, Type xz, + Type yx, Type yy, Type yz, + Type zx, Type zy, Type zz ) { v_[0] = xx; v_[1] = xy; v_[2] = xz; v_[3] = yx; v_[4] = yy; v_[5] = yz; @@ -333,7 +333,7 @@ inline Matrix3<Type>::Matrix3( Type xx, Type xy, Type xz, // The array is assumed to have at least nine valid elements. */ template< typename Type > -inline Matrix3<Type>::Matrix3( const Type* init ) +inline constexpr Matrix3<Type>::Matrix3( const Type* init ) { v_[0] = init[0]; v_[1] = init[1]; diff --git a/src/core/math/Vector3.h b/src/core/math/Vector3.h index 7bc9e87af..8bc4e3233 100644 --- a/src/core/math/Vector3.h +++ b/src/core/math/Vector3.h @@ -101,15 +101,15 @@ public: //******************************************************************************************************************* //**Constructors***************************************************************************************************** - explicit inline Vector3() = default; - explicit inline Vector3( Type init ); - template< typename Other > explicit inline Vector3( Other init ); - explicit inline Vector3( Type x, Type y, Type z ); - explicit inline Vector3( const Type* init ); - inline Vector3( const Vector3& v ) = default; + explicit inline constexpr Vector3() = default; + explicit inline constexpr Vector3( Type init ); + template< typename Other > explicit inline constexpr Vector3( Other init ); + explicit inline constexpr Vector3( Type x, Type y, Type z ); + explicit inline constexpr Vector3( const Type* init ); + inline constexpr Vector3( const Vector3& v ) = default; template< typename Other > - inline Vector3( const Vector3<Other>& v ); + inline constexpr Vector3( const Vector3<Other>& v ); //******************************************************************************************************************* //**Destructor******************************************************************************************************* @@ -208,7 +208,7 @@ Vector3<T> & normalize( Vector3<T> & v ); // \param init Initial value for all vector elements. */ template< typename Type > -inline Vector3<Type>::Vector3( Type init ) +inline constexpr Vector3<Type>::Vector3( Type init ) { v_[0] = v_[1] = v_[2] = init; } @@ -223,7 +223,7 @@ inline Vector3<Type>::Vector3( Type init ) */ template< typename Type > template< typename Other > -inline Vector3<Type>::Vector3( Other init ) +inline constexpr Vector3<Type>::Vector3( Other init ) { static_assert( std::is_arithmetic<Other>::value, "Vector3 only accepts arithmetic data types in Vector3( Other init )"); @@ -241,7 +241,7 @@ inline Vector3<Type>::Vector3( Other init ) // \param z The initial value for the z-component. */ template< typename Type > -inline Vector3<Type>::Vector3( Type x, Type y, Type z ) +inline constexpr Vector3<Type>::Vector3( Type x, Type y, Type z ) { v_[0] = x; v_[1] = y; @@ -259,7 +259,7 @@ inline Vector3<Type>::Vector3( Type x, Type y, Type z ) // The array is assumed to have at least three valid elements. */ template< typename Type > -inline Vector3<Type>::Vector3( const Type* init ) +inline constexpr Vector3<Type>::Vector3( const Type* init ) { v_[0] = init[0]; v_[1] = init[1]; @@ -276,7 +276,7 @@ inline Vector3<Type>::Vector3( const Type* init ) */ template< typename Type > template< typename Other > -inline Vector3<Type>::Vector3( const Vector3<Other>& v ) +inline constexpr Vector3<Type>::Vector3( const Vector3<Other>& v ) { v_[0] = numeric_cast<Type>( v.v_[0] ); v_[1] = numeric_cast<Type>( v.v_[1] ); -- GitLab From 15897ac155d3a2a0f58d4030ba080caaebe653b8 Mon Sep 17 00:00:00 2001 From: Dominik Thoennes <dominik.thoennes@fau.de> Date: Fri, 22 Jan 2021 09:41:14 +0100 Subject: [PATCH 39/83] the often used cuda 10 does not support c++17 --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4b05ed5d7..80a06fc8d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1045,6 +1045,7 @@ if ( WALBERLA_BUILD_WITH_CUDA ) #CUDA_FOUND is need for our cmake mechanism set ( CUDA_FOUND TRUE ) + set(CMAKE_CUDA_STANDARD_REQUIRED OFF) else() set ( WALBERLA_BUILD_WITH_CUDA FALSE ) endif ( ) -- GitLab From 951deefd1a7a8c44d971ec6fd1fd2ea48672a51b Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 22 Jan 2021 10:00:35 +0100 Subject: [PATCH 40/83] [BUGFIX] uninitialized variable --- .../discrete_particle_methods/utility/BodyVelocityInitializer.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h b/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h index 9ffbad829..6ff059c61 100644 --- a/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h +++ b/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h @@ -84,8 +84,6 @@ public: { if(!dpmBodySelectorFct_(bodyIt.getBodyID())) continue; - Vector3<real_t> forceOnFluid( real_t(0) ); - Vector3<real_t> bodyPosition = bodyIt->getPosition(); // interpolate fluid velocity to body position -- GitLab From 878d3b9c920273f71297c86c06aa8fd1fa8c1e28 Mon Sep 17 00:00:00 2001 From: Arash Partow <partow@gmail.com> Date: Mon, 25 Jan 2021 12:12:19 +1100 Subject: [PATCH 41/83] Update ExprTk library --- src/core/math/extern/exprtk.h | 4947 ++++++++++++++++++++------------- 1 file changed, 3052 insertions(+), 1895 deletions(-) diff --git a/src/core/math/extern/exprtk.h b/src/core/math/extern/exprtk.h index 4c88bbdf6..afa862bf1 100644 --- a/src/core/math/extern/exprtk.h +++ b/src/core/math/extern/exprtk.h @@ -2,7 +2,7 @@ ****************************************************************** * C++ Mathematical Expression Toolkit Library * * * - * Author: Arash Partow (1999-2019) * + * Author: Arash Partow (1999-2021) * * URL: http://www.partow.net/programming/exprtk/index.html * * * * Copyright notice: * @@ -35,6 +35,7 @@ #include <algorithm> +#include <cassert> #include <cctype> #include <cmath> #include <complex> @@ -83,12 +84,14 @@ namespace exprtk namespace details { - typedef unsigned char uchar_t; - typedef char char_t; - typedef uchar_t* uchar_ptr; - typedef char_t* char_ptr; - typedef uchar_t const* uchar_cptr; - typedef char_t const* char_cptr; + typedef unsigned char uchar_t; + typedef char char_t; + typedef uchar_t* uchar_ptr; + typedef char_t* char_ptr; + typedef uchar_t const* uchar_cptr; + typedef char_t const* char_cptr; + typedef unsigned long long int _uint64_t; + typedef long long int _int64_t; inline bool is_whitespace(const char_t c) { @@ -162,6 +165,12 @@ namespace exprtk ('\'' != c); } + inline bool is_valid_string_char(const char_t c) + { + return std::isprint(static_cast<unsigned char>(c)) || + is_whitespace(c); + } + #ifndef exprtk_disable_caseinsensitivity inline void case_normalise(std::string& s) { @@ -308,31 +317,30 @@ namespace exprtk } template <typename Iterator> - inline void parse_hex(Iterator& itr, Iterator end, std::string::value_type& result) + inline bool parse_hex(Iterator& itr, Iterator end, + std::string::value_type& result) { if ( - (end != (itr )) && - (end != (itr + 1)) && - (end != (itr + 2)) && - (end != (itr + 3)) && - ('0' == *(itr )) && - ( - ('x' == *(itr + 1)) || - ('X' == *(itr + 1)) - ) && - (is_hex_digit(*(itr + 2))) && - (is_hex_digit(*(itr + 3))) + (end == (itr )) || + (end == (itr + 1)) || + (end == (itr + 2)) || + (end == (itr + 3)) || + ('0' != *(itr )) || + ('X' != std::toupper(*(itr + 1))) || + (!is_hex_digit(*(itr + 2))) || + (!is_hex_digit(*(itr + 3))) ) { - result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | - hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; - itr += 3; + return false; } - else - result = '\0'; + + result = hex_to_bin(static_cast<uchar_t>(*(itr + 2))) << 4 | + hex_to_bin(static_cast<uchar_t>(*(itr + 3))) ; + + return true; } - inline void cleanup_escapes(std::string& s) + inline bool cleanup_escapes(std::string& s) { typedef std::string::iterator str_itr_t; @@ -346,36 +354,41 @@ namespace exprtk { if ('\\' == (*itr1)) { - ++removal_count; - if (end == ++itr1) - break; - else if ('\\' != (*itr1)) { - switch (*itr1) - { - case 'n' : (*itr1) = '\n'; break; - case 'r' : (*itr1) = '\r'; break; - case 't' : (*itr1) = '\t'; break; - case '0' : parse_hex(itr1, end, (*itr1)); - removal_count += 3; - break; - } - - continue; + return false; } + else if (parse_hex(itr1, end, *itr2)) + { + itr1+= 4; + itr2+= 1; + removal_count +=4; + } + else if ('a' == (*itr1)) { (*itr2++) = '\a'; ++itr1; ++removal_count; } + else if ('b' == (*itr1)) { (*itr2++) = '\b'; ++itr1; ++removal_count; } + else if ('f' == (*itr1)) { (*itr2++) = '\f'; ++itr1; ++removal_count; } + else if ('n' == (*itr1)) { (*itr2++) = '\n'; ++itr1; ++removal_count; } + else if ('r' == (*itr1)) { (*itr2++) = '\r'; ++itr1; ++removal_count; } + else if ('t' == (*itr1)) { (*itr2++) = '\t'; ++itr1; ++removal_count; } + else if ('v' == (*itr1)) { (*itr2++) = '\v'; ++itr1; ++removal_count; } + else if ('0' == (*itr1)) { (*itr2++) = '\0'; ++itr1; ++removal_count; } + else + { + (*itr2++) = (*itr1++); + ++removal_count; + } + continue; } - - if (itr1 != itr2) - { - (*itr2) = (*itr1); - } - - ++itr1; - ++itr2; + else + (*itr2++) = (*itr1++); } + if ((removal_count > s.size()) || (0 == removal_count)) + return false; + s.resize(s.size() - removal_count); + + return true; } class build_string @@ -643,23 +656,19 @@ namespace exprtk inline bool wc_match(const std::string& wild_card, const std::string& str) { - return match_impl<char_cptr,cs_match>(wild_card.data(), - wild_card.data() + wild_card.size(), - str.data(), - str.data() + str.size(), - '*', - '?'); + return match_impl<char_cptr,cs_match>( + wild_card.data(), wild_card.data() + wild_card.size(), + str.data(), str.data() + str.size(), + '*', '?'); } inline bool wc_imatch(const std::string& wild_card, const std::string& str) { - return match_impl<char_cptr,cis_match>(wild_card.data(), - wild_card.data() + wild_card.size(), - str.data(), - str.data() + str.size(), - '*', - '?'); + return match_impl<char_cptr,cis_match>( + wild_card.data(), wild_card.data() + wild_card.size(), + str.data(), str.data() + str.size(), + '*', '?'); } inline bool sequence_match(const std::string& pattern, @@ -773,15 +782,15 @@ namespace exprtk }; #define exprtk_register_real_type_tag(T) \ - template<> struct number_type<T> \ + template <> struct number_type<T> \ { typedef real_type_tag type; number_type() {} }; \ #define exprtk_register_complex_type_tag(T) \ - template<> struct number_type<std::complex<T> > \ + template <> struct number_type<std::complex<T> > \ { typedef complex_type_tag type; number_type() {} }; \ #define exprtk_register_int_type_tag(T) \ - template<> struct number_type<T> \ + template <> struct number_type<T> \ { typedef int_type_tag type; number_type() {} }; \ exprtk_register_real_type_tag(double ) @@ -792,12 +801,12 @@ namespace exprtk exprtk_register_complex_type_tag(long double) exprtk_register_complex_type_tag(float ) - exprtk_register_int_type_tag(short ) - exprtk_register_int_type_tag(int ) - exprtk_register_int_type_tag(long long int ) - exprtk_register_int_type_tag(unsigned short ) - exprtk_register_int_type_tag(unsigned int ) - exprtk_register_int_type_tag(unsigned long long int) + exprtk_register_int_type_tag(short ) + exprtk_register_int_type_tag(int ) + exprtk_register_int_type_tag(_int64_t ) + exprtk_register_int_type_tag(unsigned short) + exprtk_register_int_type_tag(unsigned int ) + exprtk_register_int_type_tag(_uint64_t ) #undef exprtk_register_real_type_tag #undef exprtk_register_int_type_tag @@ -827,7 +836,7 @@ namespace exprtk { static inline long double value() { - const long double epsilon = (long double)(0.000000000001); + const long double epsilon = static_cast<long double>(0.000000000001); return epsilon; } }; @@ -845,9 +854,9 @@ namespace exprtk } template <typename T> - inline long long int to_int64_impl(const T v, real_type_tag) + inline _int64_t to_int64_impl(const T v, real_type_tag) { - return static_cast<long long int>(v); + return static_cast<_int64_t>(v); } template <typename T> @@ -1028,7 +1037,7 @@ namespace exprtk template <typename T> inline T roundn_impl(const T v0, const T v1, real_type_tag) { - const int index = std::max<int>(0, std::min<int>(pow10_size - 1, (int)std::floor(v1))); + const int index = std::max<int>(0, std::min<int>(pow10_size - 1, static_cast<int>(std::floor(v1)))); const T p10 = T(pow10[index]); if (v0 < T(0)) @@ -1372,10 +1381,10 @@ namespace exprtk template <typename Type> struct numeric_info { enum { length = 0, size = 32, bound_length = 0, min_exp = 0, max_exp = 0 }; }; - template<> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; - template<> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; - template<> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; - template<> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; + template <> struct numeric_info<int> { enum { length = 10, size = 16, bound_length = 9}; }; + template <> struct numeric_info<float> { enum { min_exp = -38, max_exp = +38}; }; + template <> struct numeric_info<double> { enum { min_exp = -308, max_exp = +308}; }; + template <> struct numeric_info<long double> { enum { min_exp = -308, max_exp = +308}; }; template <typename T> inline int to_int32(const T v) @@ -1385,7 +1394,7 @@ namespace exprtk } template <typename T> - inline long long int to_int64(const T v) + inline _int64_t to_int64(const T v) { const typename details::number_type<T>::type num_type; return to_int64_impl(v, num_type); @@ -1827,6 +1836,13 @@ namespace exprtk return true; } + template <typename T> + inline bool valid_exponent(const int exponent, numeric::details::real_type_tag) + { + return (std::numeric_limits<T>::min_exponent10 <= exponent) && + (exponent <= std::numeric_limits<T>::max_exponent10) ; + } + template <typename Iterator, typename T> inline bool string_to_real(Iterator& itr_external, const Iterator end, T& t, numeric::details::real_type_tag) { @@ -1867,12 +1883,12 @@ namespace exprtk while ((end != itr) && (zero == (*itr))) ++itr; - unsigned int digit; - while (end != itr) { // Note: For 'physical' superscalar architectures it // is advised that the following loop be: 4xPD1 and 1xPD2 + unsigned int digit; + #ifdef exprtk_enable_superscalar parse_digit_1(d) parse_digit_1(d) @@ -1892,11 +1908,12 @@ namespace exprtk if ('.' == (*itr)) { const Iterator curr = ++itr; - unsigned int digit; T tmp_d = T(0); while (end != itr) { + unsigned int digit; + #ifdef exprtk_enable_superscalar parse_digit_1(tmp_d) parse_digit_1(tmp_d) @@ -1910,7 +1927,13 @@ namespace exprtk if (curr != itr) { instate = true; - d += compute_pow10(tmp_d,static_cast<int>(-std::distance(curr,itr))); + + const int exponent = static_cast<int>(-std::distance(curr, itr)); + + if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) + return false; + + d += compute_pow10(tmp_d, exponent); } #undef parse_digit_1 @@ -1981,6 +2004,8 @@ namespace exprtk if ((end != itr) || (!instate)) return false; + else if (!valid_exponent<T>(exponent, numeric::details::real_type_tag())) + return false; else if (exponent) d = compute_pow10(d,exponent); @@ -2019,6 +2044,50 @@ namespace exprtk } // namespace details + struct loop_runtime_check + { + enum loop_types + { + e_invalid = 0, + e_for_loop = 1, + e_while_loop = 2, + e_repeat_until_loop = 4, + e_all_loops = 7 + }; + + enum violation_type + { + e_unknown = 0, + e_iteration_count = 1, + e_timeout = 2 + }; + + loop_types loop_set; + + loop_runtime_check() + : loop_set(e_invalid), + max_loop_iterations(0) + {} + + details::_uint64_t max_loop_iterations; + + struct violation_context + { + loop_types loop; + violation_type violation; + details::_uint64_t iteration_count; + }; + + virtual void handle_runtime_violation(const violation_context&) + { + throw std::runtime_error("ExprTk Loop run-time violation."); + } + + virtual ~loop_runtime_check() {} + }; + + typedef loop_runtime_check* loop_runtime_check_ptr; + namespace lexer { struct token @@ -2199,7 +2268,7 @@ namespace exprtk typedef token token_t; typedef std::vector<token_t> token_list_t; - typedef std::vector<token_t>::iterator token_list_itr_t; + typedef token_list_t::iterator token_list_itr_t; typedef details::char_t char_t; generator() @@ -2334,9 +2403,9 @@ namespace exprtk if (finished()) return ""; else if (token_list_.begin() != token_itr_) - return std::string(base_itr_ + (token_itr_ - 1)->position,s_end_); + return std::string(base_itr_ + (token_itr_ - 1)->position, s_end_); else - return std::string(base_itr_ + token_itr_->position,s_end_); + return std::string(base_itr_ + token_itr_->position, s_end_); } private: @@ -2346,9 +2415,9 @@ namespace exprtk return (s_end_ == itr); } + #ifndef exprtk_disable_comments inline bool is_comment_start(details::char_cptr itr) { - #ifndef exprtk_disable_comments const char_t c0 = *(itr + 0); const char_t c1 = *(itr + 1); @@ -2359,9 +2428,14 @@ namespace exprtk if (('/' == c0) && ('/' == c1)) return true; if (('/' == c0) && ('*' == c1)) return true; } - #endif return false; } + #else + inline bool is_comment_start(details::char_cptr) + { + return false; + } + #endif inline void skip_whitespace() { @@ -2637,6 +2711,7 @@ namespace exprtk { t.set_error(token::e_err_number, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); + return; } @@ -2715,7 +2790,10 @@ namespace exprtk // $fdd(x,x,x) = at least 11 chars if (std::distance(s_itr_,s_end_) < 11) { - t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + t.set_error( + token::e_err_sfunc, + initial_itr, std::min(initial_itr + 11, s_end_), + base_itr_); token_list_.push_back(t); return; @@ -2728,7 +2806,10 @@ namespace exprtk (details::is_digit(*(s_itr_ + 3)))) ) { - t.set_error(token::e_err_sfunc, initial_itr, s_itr_, base_itr_); + t.set_error( + token::e_err_sfunc, + initial_itr, std::min(initial_itr + 4, s_end_), + base_itr_); token_list_.push_back(t); return; @@ -2752,6 +2833,7 @@ namespace exprtk { t.set_error(token::e_err_string, s_itr_, s_end_, base_itr_); token_list_.push_back(t); + return; } @@ -2762,7 +2844,14 @@ namespace exprtk while (!is_end(s_itr_)) { - if (!escaped && ('\\' == *s_itr_)) + if (!details::is_valid_string_char(*s_itr_)) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } + else if (!escaped && ('\\' == *s_itr_)) { escaped_found = true; escaped = true; @@ -2777,28 +2866,17 @@ namespace exprtk } else if (escaped) { - if (!is_end(s_itr_) && ('0' == *(s_itr_))) + if ( + !is_end(s_itr_) && ('0' == *(s_itr_)) && + ((s_itr_ + 4) <= s_end_) + ) { - /* - Note: The following 'awkward' conditional is - due to various broken msvc compilers. - */ - #if defined(_MSC_VER) && (_MSC_VER == 1600) - const bool within_range = !is_end(s_itr_ + 2) && - !is_end(s_itr_ + 3) ; - #else - const bool within_range = !is_end(s_itr_ + 1) && - !is_end(s_itr_ + 2) && - !is_end(s_itr_ + 3) ; - #endif + const bool x_seperator = ('X' == std::toupper(*(s_itr_ + 1))); - const bool x_seperator = ('x' == *(s_itr_ + 1)) || - ('X' == *(s_itr_ + 1)) ; + const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && + details::is_hex_digit(*(s_itr_ + 3)) ; - const bool both_digits = details::is_hex_digit(*(s_itr_ + 2)) && - details::is_hex_digit(*(s_itr_ + 3)) ; - - if (!within_range || !x_seperator || !both_digits) + if (!(x_seperator && both_digits)) { t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); token_list_.push_back(t); @@ -2829,7 +2907,13 @@ namespace exprtk { std::string parsed_string(initial_itr,s_itr_); - details::cleanup_escapes(parsed_string); + if (!details::cleanup_escapes(parsed_string)) + { + t.set_error(token::e_err_string, initial_itr, s_itr_, base_itr_); + token_list_.push_back(t); + + return; + } t.set_string( parsed_string, @@ -2845,10 +2929,10 @@ namespace exprtk private: - token_list_t token_list_; - token_list_itr_t token_itr_; - token_list_itr_t store_token_itr_; - token_t eof_token_; + token_list_t token_list_; + token_list_itr_t token_itr_; + token_list_itr_t store_token_itr_; + token_t eof_token_; details::char_cptr base_itr_; details::char_cptr s_itr_; details::char_cptr s_end_; @@ -3018,6 +3102,10 @@ namespace exprtk std::size_t changes = 0; + typedef std::pair<std::size_t, token> insert_t; + std::vector<insert_t> insert_list; + insert_list.reserve(10000); + for (std::size_t i = 0; i < (g.token_list_.size() - stride_ + 1); ++i) { int insert_index = -1; @@ -3041,17 +3129,36 @@ namespace exprtk break; } - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if ((insert_index >= 0) && (insert_index <= (static_cast<int>(stride_) + 1))) { - g.token_list_.insert( - g.token_list_.begin() + static_cast<diff_t>(i + static_cast<std::size_t>(insert_index)), t); - + insert_list.push_back(insert_t(i, t)); changes++; } } + if (!insert_list.empty()) + { + generator::token_list_t token_list; + + std::size_t insert_index = 0; + + for (std::size_t i = 0; i < g.token_list_.size(); ++i) + { + token_list.push_back(g.token_list_[i]); + + if ( + (insert_index < insert_list.size()) && + (insert_list[insert_index].first == i) + ) + { + token_list.push_back(insert_list[insert_index].second); + insert_index++; + } + } + + std::swap(g.token_list_,token_list); + } + return changes; } @@ -3086,7 +3193,7 @@ namespace exprtk { public: - token_joiner(const std::size_t& stride) + explicit token_joiner(const std::size_t& stride) : stride_(stride) {} @@ -3110,59 +3217,82 @@ namespace exprtk inline std::size_t process_stride_2(generator& g) { - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if (g.token_list_.size() < 2) return 0; std::size_t changes = 0; + generator::token_list_t token_list; + token_list.reserve(10000); + for (int i = 0; i < static_cast<int>(g.token_list_.size() - 1); ++i) { token t; - while (join(g[i], g[i + 1], t)) + for ( ; ; ) { - g.token_list_[i] = t; + if (!join(g[i], g[i + 1], t)) + { + token_list.push_back(g[i]); + break; + } - g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1)); + token_list.push_back(t); ++changes; - if (static_cast<std::size_t>(i + 1) >= g.token_list_.size()) + i+=2; + + if (static_cast<std::size_t>(i) >= g.token_list_.size()) break; } } + token_list.push_back(g.token_list_.back()); + + std::swap(token_list, g.token_list_); + return changes; } inline std::size_t process_stride_3(generator& g) { - typedef std::iterator_traits<generator::token_list_t::iterator>::difference_type diff_t; - if (g.token_list_.size() < 3) return 0; std::size_t changes = 0; + generator::token_list_t token_list; + token_list.reserve(10000); + for (int i = 0; i < static_cast<int>(g.token_list_.size() - 2); ++i) { token t; - while (join(g[i], g[i + 1], g[i + 2], t)) + for ( ; ; ) { - g.token_list_[i] = t; + if (!join(g[i], g[i + 1], g[i + 2], t)) + { + token_list.push_back(g[i]); + break; + } + + token_list.push_back(t); - g.token_list_.erase(g.token_list_.begin() + static_cast<diff_t>(i + 1), - g.token_list_.begin() + static_cast<diff_t>(i + 3)); ++changes; - if (static_cast<std::size_t>(i + 2) >= g.token_list_.size()) + i+=3; + + if (static_cast<std::size_t>(i) >= g.token_list_.size()) break; } } + token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 2)); + token_list.push_back(*(g.token_list_.begin() + g.token_list_.size() - 1)); + + std::swap(token_list, g.token_list_); + return changes; } @@ -3172,11 +3302,11 @@ namespace exprtk namespace helper { - inline void dump(lexer::generator& generator) + inline void dump(const lexer::generator& generator) { for (std::size_t i = 0; i < generator.size(); ++i) { - lexer::token t = generator[i]; + const lexer::token& t = generator[i]; printf("Token[%02d] @ %03d %6s --> '%s'\n", static_cast<int>(i), static_cast<int>(t.position), @@ -3251,7 +3381,7 @@ namespace exprtk { public: - operator_joiner(const std::size_t& stride) + explicit operator_joiner(const std::size_t& stride) : token_joiner(stride) {} @@ -3649,10 +3779,11 @@ namespace exprtk sequence_validator() : lexer::token_scanner(2) { - add_invalid(lexer::token::e_number ,lexer::token::e_number ); - add_invalid(lexer::token::e_string ,lexer::token::e_string ); - add_invalid(lexer::token::e_number ,lexer::token::e_string ); - add_invalid(lexer::token::e_string ,lexer::token::e_number ); + add_invalid(lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_number, lexer::token::e_string); + add_invalid(lexer::token::e_string, lexer::token::e_number); + add_invalid_set1(lexer::token::e_assign ); add_invalid_set1(lexer::token::e_shr ); add_invalid_set1(lexer::token::e_shl ); @@ -3726,21 +3857,21 @@ namespace exprtk void add_invalid_set1(lexer::token::token_type t) { - add_invalid(t,lexer::token::e_assign); - add_invalid(t,lexer::token::e_shr ); - add_invalid(t,lexer::token::e_shl ); - add_invalid(t,lexer::token::e_lte ); - add_invalid(t,lexer::token::e_ne ); - add_invalid(t,lexer::token::e_gte ); - add_invalid(t,lexer::token::e_lt ); - add_invalid(t,lexer::token::e_gt ); - add_invalid(t,lexer::token::e_eq ); - add_invalid(t,lexer::token::e_comma ); - add_invalid(t,lexer::token::e_div ); - add_invalid(t,lexer::token::e_mul ); - add_invalid(t,lexer::token::e_mod ); - add_invalid(t,lexer::token::e_pow ); - add_invalid(t,lexer::token::e_colon ); + add_invalid(t, lexer::token::e_assign); + add_invalid(t, lexer::token::e_shr ); + add_invalid(t, lexer::token::e_shl ); + add_invalid(t, lexer::token::e_lte ); + add_invalid(t, lexer::token::e_ne ); + add_invalid(t, lexer::token::e_gte ); + add_invalid(t, lexer::token::e_lt ); + add_invalid(t, lexer::token::e_gt ); + add_invalid(t, lexer::token::e_eq ); + add_invalid(t, lexer::token::e_comma ); + add_invalid(t, lexer::token::e_div ); + add_invalid(t, lexer::token::e_mul ); + add_invalid(t, lexer::token::e_mod ); + add_invalid(t, lexer::token::e_pow ); + add_invalid(t, lexer::token::e_colon ); } bool invalid_bracket_check(lexer::token::token_type base, lexer::token::token_type t) @@ -3750,7 +3881,7 @@ namespace exprtk switch (t) { case lexer::token::e_assign : return (']' != base); - case lexer::token::e_string : return true; + case lexer::token::e_string : return (')' != base); default : return false; } } @@ -3821,23 +3952,23 @@ namespace exprtk sequence_validator_3tokens() : lexer::token_scanner(3) { - add_invalid(lexer::token::e_number , lexer::token::e_number , lexer::token::e_number); - add_invalid(lexer::token::e_string , lexer::token::e_string , lexer::token::e_string); - add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); + add_invalid(lexer::token::e_number, lexer::token::e_number, lexer::token::e_number); + add_invalid(lexer::token::e_string, lexer::token::e_string, lexer::token::e_string); + add_invalid(lexer::token::e_comma , lexer::token::e_comma , lexer::token::e_comma ); - add_invalid(lexer::token::e_add ,lexer::token::e_add , lexer::token::e_add); - add_invalid(lexer::token::e_sub ,lexer::token::e_sub , lexer::token::e_sub); - add_invalid(lexer::token::e_div ,lexer::token::e_div , lexer::token::e_div); - add_invalid(lexer::token::e_mul ,lexer::token::e_mul , lexer::token::e_mul); - add_invalid(lexer::token::e_mod ,lexer::token::e_mod , lexer::token::e_mod); - add_invalid(lexer::token::e_pow ,lexer::token::e_pow , lexer::token::e_pow); + add_invalid(lexer::token::e_add , lexer::token::e_add , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_sub , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_div , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_mul , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_mod , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_pow , lexer::token::e_pow ); - add_invalid(lexer::token::e_add ,lexer::token::e_sub , lexer::token::e_add); - add_invalid(lexer::token::e_sub ,lexer::token::e_add , lexer::token::e_sub); - add_invalid(lexer::token::e_div ,lexer::token::e_mul , lexer::token::e_div); - add_invalid(lexer::token::e_mul ,lexer::token::e_div , lexer::token::e_mul); - add_invalid(lexer::token::e_mod ,lexer::token::e_pow , lexer::token::e_mod); - add_invalid(lexer::token::e_pow ,lexer::token::e_mod , lexer::token::e_pow); + add_invalid(lexer::token::e_add , lexer::token::e_sub , lexer::token::e_add ); + add_invalid(lexer::token::e_sub , lexer::token::e_add , lexer::token::e_sub ); + add_invalid(lexer::token::e_div , lexer::token::e_mul , lexer::token::e_div ); + add_invalid(lexer::token::e_mul , lexer::token::e_div , lexer::token::e_mul ); + add_invalid(lexer::token::e_mod , lexer::token::e_pow , lexer::token::e_mod ); + add_invalid(lexer::token::e_pow , lexer::token::e_mod , lexer::token::e_pow ); } bool result() @@ -4231,14 +4362,14 @@ namespace exprtk inline vector_view<T> make_vector_view(T* data, const std::size_t size, const std::size_t offset = 0) { - return vector_view<T>(data + offset,size); + return vector_view<T>(data + offset, size); } template <typename T> inline vector_view<T> make_vector_view(std::vector<T>& v, const std::size_t size, const std::size_t offset = 0) { - return vector_view<T>(v.data() + offset,size); + return vector_view<T>(v.data() + offset, size); } template <typename T> class results_context; @@ -4273,7 +4404,7 @@ namespace exprtk { public: - parameter_list(std::vector<type_store>& pl) + explicit parameter_list(std::vector<type_store>& pl) : parameter_list_(pl) {} @@ -4330,12 +4461,12 @@ namespace exprtk typedef type_store<T> type_store_t; typedef ViewType value_t; - type_view(type_store_t& ts) + explicit type_view(type_store_t& ts) : ts_(ts), data_(reinterpret_cast<value_t*>(ts_.data)) {} - type_view(const type_store_t& ts) + explicit type_view(const type_store_t& ts) : ts_(const_cast<type_store_t&>(ts)), data_(reinterpret_cast<value_t*>(ts_.data)) {} @@ -4380,11 +4511,11 @@ namespace exprtk typedef type_store<T> type_store_t; typedef T value_t; - scalar_view(type_store_t& ts) + explicit scalar_view(type_store_t& ts) : v_(*reinterpret_cast<value_t*>(ts.data)) {} - scalar_view(const type_store_t& ts) + explicit scalar_view(const type_store_t& ts) : v_(*reinterpret_cast<value_t*>(const_cast<type_store_t&>(ts).data)) {} @@ -4572,27 +4703,33 @@ namespace exprtk { switch (opr) { - case e_add : return "+"; - case e_sub : return "-"; - case e_mul : return "*"; - case e_div : return "/"; - case e_mod : return "%"; - case e_pow : return "^"; - case e_assign : return ":="; - case e_addass : return "+="; - case e_subass : return "-="; - case e_mulass : return "*="; - case e_divass : return "/="; - case e_modass : return "%="; - case e_lt : return "<"; - case e_lte : return "<="; - case e_eq : return "=="; - case e_equal : return "="; - case e_ne : return "!="; - case e_nequal : return "<>"; - case e_gte : return ">="; - case e_gt : return ">"; - default : return"N/A"; + case e_add : return "+" ; + case e_sub : return "-" ; + case e_mul : return "*" ; + case e_div : return "/" ; + case e_mod : return "%" ; + case e_pow : return "^" ; + case e_assign : return ":=" ; + case e_addass : return "+=" ; + case e_subass : return "-=" ; + case e_mulass : return "*=" ; + case e_divass : return "/=" ; + case e_modass : return "%=" ; + case e_lt : return "<" ; + case e_lte : return "<=" ; + case e_eq : return "==" ; + case e_equal : return "=" ; + case e_ne : return "!=" ; + case e_nequal : return "<>" ; + case e_gte : return ">=" ; + case e_gt : return ">" ; + case e_and : return "and" ; + case e_or : return "or" ; + case e_xor : return "xor" ; + case e_nand : return "nand"; + case e_nor : return "nor" ; + case e_xnor : return "xnor"; + default : return "N/A" ; } } @@ -4617,8 +4754,8 @@ namespace exprtk struct details { - details(const std::size_t& vsize, - const unsigned int loop_batch_size = global_loop_batch_size) + explicit details(const std::size_t& vsize, + const unsigned int loop_batch_size = global_loop_batch_size) : batch_size(loop_batch_size ), remainder (vsize % batch_size), upper_bound(static_cast<int>(vsize - (remainder ? loop_batch_size : 0))) @@ -4665,7 +4802,7 @@ namespace exprtk destruct (true) {} - control_block(const std::size_t& dsize) + explicit control_block(const std::size_t& dsize) : ref_count(1 ), size (dsize), data (0 ), @@ -4732,7 +4869,7 @@ namespace exprtk { destruct = true; data = new T[size]; - std::fill_n(data,size,T(0)); + std::fill_n(data, size, T(0)); dump_ptr("control_block::create_data() - data",data,size); } }; @@ -4743,8 +4880,8 @@ namespace exprtk : control_block_(control_block::create(0)) {} - vec_data_store(const std::size_t& size) - : control_block_(control_block::create(size,(data_t)(0),true)) + explicit vec_data_store(const std::size_t& size) + : control_block_(control_block::create(size,reinterpret_cast<data_t>(0),true)) {} vec_data_store(const std::size_t& size, data_t data, bool dstrct = false) @@ -4829,7 +4966,7 @@ namespace exprtk static inline void match_sizes(type& vds0, type& vds1) { - std::size_t size = min_size(vds0.control_block_,vds1.control_block_); + const std::size_t size = min_size(vds0.control_block_,vds1.control_block_); vds0.control_block_->size = size; vds1.control_block_->size = size; } @@ -4993,58 +5130,77 @@ namespace exprtk template <typename T> inline T process(const operator_type operation, const T arg0, const T arg1) { - return exprtk::details::numeric::details::process_impl(operation,arg0,arg1); + return exprtk::details::numeric::details::process_impl(operation, arg0, arg1); } } + template <typename Node> + struct node_collector_interface + { + typedef Node* node_ptr_t; + typedef Node** node_pp_t; + typedef std::vector<node_pp_t> noderef_list_t; + + virtual ~node_collector_interface() {} + + virtual void collect_nodes(noderef_list_t&) {} + }; + + template <typename Node> + struct node_depth_base; + template <typename T> - class expression_node + class expression_node : public node_collector_interface<expression_node<T> >, + public node_depth_base<expression_node<T> > { public: enum node_type { - e_none , e_null , e_constant , e_unary , - e_binary , e_binary_ext , e_trinary , e_quaternary , - e_vararg , e_conditional , e_while , e_repeat , - e_for , e_switch , e_mswitch , e_return , - e_retenv , e_variable , e_stringvar , e_stringconst , - e_stringvarrng , e_cstringvarrng, e_strgenrange , e_strconcat , - e_stringvarsize, e_strswap , e_stringsize , e_stringvararg , - e_function , e_vafunction , e_genfunction , e_strfunction , - e_strcondition , e_strccondition, e_add , e_sub , - e_mul , e_div , e_mod , e_pow , - e_lt , e_lte , e_gt , e_gte , - e_eq , e_ne , e_and , e_nand , - e_or , e_nor , e_xor , e_xnor , - e_in , e_like , e_ilike , e_inranges , - e_ipow , e_ipowinv , e_abs , e_acos , - e_acosh , e_asin , e_asinh , e_atan , - e_atanh , e_ceil , e_cos , e_cosh , - e_exp , e_expm1 , e_floor , e_log , - e_log10 , e_log2 , e_log1p , e_neg , - e_pos , e_round , e_sin , e_sinc , - e_sinh , e_sqrt , e_tan , e_tanh , - e_cot , e_sec , e_csc , e_r2d , - e_d2r , e_d2g , e_g2d , e_notl , - e_sgn , e_erf , e_erfc , e_ncdf , - e_frac , e_trunc , e_uvouv , e_vov , - e_cov , e_voc , e_vob , e_bov , - e_cob , e_boc , e_vovov , e_vovoc , - e_vocov , e_covov , e_covoc , e_vovovov , - e_vovovoc , e_vovocov , e_vocovov , e_covovov , - e_covocov , e_vocovoc , e_covovoc , e_vococov , - e_sf3ext , e_sf4ext , e_nulleq , e_strass , - e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , - e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , - e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , - e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , - e_valvecarith , e_vecunaryop , e_break , e_continue , + e_none , e_null , e_constant , e_unary , + e_binary , e_binary_ext , e_trinary , e_quaternary , + e_vararg , e_conditional , e_while , e_repeat , + e_for , e_switch , e_mswitch , e_return , + e_retenv , e_variable , e_stringvar , e_stringconst , + e_stringvarrng , e_cstringvarrng , e_strgenrange , e_strconcat , + e_stringvarsize , e_strswap , e_stringsize , e_stringvararg , + e_function , e_vafunction , e_genfunction , e_strfunction , + e_strcondition , e_strccondition , e_add , e_sub , + e_mul , e_div , e_mod , e_pow , + e_lt , e_lte , e_gt , e_gte , + e_eq , e_ne , e_and , e_nand , + e_or , e_nor , e_xor , e_xnor , + e_in , e_like , e_ilike , e_inranges , + e_ipow , e_ipowinv , e_abs , e_acos , + e_acosh , e_asin , e_asinh , e_atan , + e_atanh , e_ceil , e_cos , e_cosh , + e_exp , e_expm1 , e_floor , e_log , + e_log10 , e_log2 , e_log1p , e_neg , + e_pos , e_round , e_sin , e_sinc , + e_sinh , e_sqrt , e_tan , e_tanh , + e_cot , e_sec , e_csc , e_r2d , + e_d2r , e_d2g , e_g2d , e_notl , + e_sgn , e_erf , e_erfc , e_ncdf , + e_frac , e_trunc , e_uvouv , e_vov , + e_cov , e_voc , e_vob , e_bov , + e_cob , e_boc , e_vovov , e_vovoc , + e_vocov , e_covov , e_covoc , e_vovovov , + e_vovovoc , e_vovocov , e_vocovov , e_covovov , + e_covocov , e_vocovoc , e_covovoc , e_vococov , + e_sf3ext , e_sf4ext , e_nulleq , e_strass , + e_vector , e_vecelem , e_rbvecelem , e_rbveccelem , + e_vecdefass , e_vecvalass , e_vecvecass , e_vecopvalass , + e_vecopvecass , e_vecfunc , e_vecvecswap , e_vecvecineq , + e_vecvalineq , e_valvecineq , e_vecvecarith , e_vecvalarith , + e_valvecarith , e_vecunaryop , e_break , e_continue , e_swap }; typedef T value_type; typedef expression_node<T>* expression_ptr; + typedef node_collector_interface<expression_node<T> > nci_t; + typedef typename nci_t::noderef_list_t noderef_list_t; + typedef node_depth_base<expression_node<T> > ndb_t; virtual ~expression_node() {} @@ -5095,12 +5251,24 @@ namespace exprtk return std::not_equal_to<T>()(T(0),node->value()); } + template <typename T> + inline bool is_true(const std::pair<expression_node<T>*,bool>& node) + { + return std::not_equal_to<T>()(T(0),node.first->value()); + } + template <typename T> inline bool is_false(const expression_node<T>* node) { return std::equal_to<T>()(T(0),node->value()); } + template <typename T> + inline bool is_false(const std::pair<expression_node<T>*,bool>& node) + { + return std::equal_to<T>()(T(0),node.first->value()); + } + template <typename T> inline bool is_unary_node(const expression_node<T>* node) { @@ -5243,7 +5411,8 @@ namespace exprtk template <typename T> inline bool branch_deletable(expression_node<T>* node) { - return !is_variable_node(node) && + return (0 != node) && + !is_variable_node(node) && !is_string_node (node) ; } @@ -5301,6 +5470,76 @@ namespace exprtk return true; } + template <typename Node> + class node_collection_destructor + { + public: + + typedef node_collector_interface<Node> nci_t; + + typedef typename nci_t::node_ptr_t node_ptr_t; + typedef typename nci_t::node_pp_t node_pp_t; + typedef typename nci_t::noderef_list_t noderef_list_t; + + static void delete_nodes(node_ptr_t& root) + { + std::vector<node_pp_t> node_delete_list; + node_delete_list.reserve(1000); + + collect_nodes(root, node_delete_list); + + for (std::size_t i = 0; i < node_delete_list.size(); ++i) + { + node_ptr_t& node = *node_delete_list[i]; + exprtk_debug(("ncd::delete_nodes() - deleting: %p\n", static_cast<void*>(node))); + delete node; + node = reinterpret_cast<node_ptr_t>(0); + } + } + + private: + + static void collect_nodes(node_ptr_t& root, noderef_list_t& node_delete_list) + { + std::deque<node_ptr_t> node_list; + node_list.push_back(root); + node_delete_list.push_back(&root); + + noderef_list_t child_node_delete_list; + child_node_delete_list.reserve(1000); + + while (!node_list.empty()) + { + node_list.front()->collect_nodes(child_node_delete_list); + + if (!child_node_delete_list.empty()) + { + for (std::size_t i = 0; i < child_node_delete_list.size(); ++i) + { + node_pp_t& node = child_node_delete_list[i]; + + if (0 == (*node)) + { + exprtk_debug(("ncd::collect_nodes() - null node encountered.\n")); + } + + node_list.push_back(*node); + } + + node_delete_list.insert( + node_delete_list.end(), + child_node_delete_list.begin(), child_node_delete_list.end()); + + child_node_delete_list.clear(); + } + + node_list.pop_front(); + } + + std::reverse(node_delete_list.begin(), node_delete_list.end()); + } + }; + template <typename NodeAllocator, typename T, std::size_t N> inline void free_all_nodes(NodeAllocator& node_allocator, expression_node<T>* (&b)[N]) { @@ -5325,28 +5564,239 @@ namespace exprtk } template <typename NodeAllocator, typename T> - inline void free_node(NodeAllocator& node_allocator, expression_node<T>*& node, const bool force_delete = false) + inline void free_node(NodeAllocator&, expression_node<T>*& node) { - if (0 != node) + if ((0 == node) || is_variable_node(node) || is_string_node(node)) { - if ( - (is_variable_node(node) || is_string_node(node)) || - force_delete - ) - return; - - node_allocator.free(node); - node = reinterpret_cast<expression_node<T>*>(0); + return; } + + node_collection_destructor<expression_node<T> > + ::delete_nodes(node); } template <typename T> inline void destroy_node(expression_node<T>*& node) { - delete node; - node = reinterpret_cast<expression_node<T>*>(0); + if (0 != node) + { + node_collection_destructor<expression_node<T> > + ::delete_nodes(node); + } } + template <typename Node> + struct node_depth_base + { + node_depth_base() + : depth_set(false), + depth(0) + {} + + virtual ~node_depth_base() {} + + virtual std::size_t node_depth() const { return 1; } + + std::size_t compute_node_depth(const Node* const& node) const + { + if (!depth_set) + { + depth = 1 + (node ? node->node_depth() : 0); + depth_set = true; + } + + return depth; + } + + std::size_t compute_node_depth(const std::pair<Node*,bool>& branch) const + { + if (!depth_set) + { + depth = 1 + (branch.first ? branch.first->node_depth() : 0); + depth_set = true; + } + + return depth; + } + + template <std::size_t N> + std::size_t compute_node_depth(const std::pair<Node*,bool> (&branch)[N]) const + { + if (!depth_set) + { + depth = 0; + for (std::size_t i = 0; i < N; ++i) + { + if (branch[i].first) + { + depth = std::max(depth,branch[i].first->node_depth()); + } + } + depth += 1; + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1) const + { + if (!depth_set) + { + depth = 1 + std::max(compute_node_depth(n0), compute_node_depth(n1)); + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, + const BranchType& n2) const + { + if (!depth_set) + { + depth = 1 + std::max( + std::max(compute_node_depth(n0), compute_node_depth(n1)), + compute_node_depth(n2)); + depth_set = true; + } + + return depth; + } + + template <typename BranchType> + std::size_t compute_node_depth(const BranchType& n0, const BranchType& n1, + const BranchType& n2, const BranchType& n3) const + { + if (!depth_set) + { + depth = 1 + std::max( + std::max(compute_node_depth(n0), compute_node_depth(n1)), + std::max(compute_node_depth(n2), compute_node_depth(n3))); + depth_set = true; + } + + return depth; + } + + template <typename Allocator, + template <typename, typename> class Sequence> + std::size_t compute_node_depth(const Sequence<Node*, Allocator>& branch_list) const + { + if (!depth_set) + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + if (branch_list[i]) + { + depth = std::max(depth, compute_node_depth(branch_list[i])); + } + } + depth_set = true; + } + + return depth; + } + + template <typename Allocator, + template <typename, typename> class Sequence> + std::size_t compute_node_depth(const Sequence<std::pair<Node*,bool>,Allocator>& branch_list) const + { + if (!depth_set) + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + if (branch_list[i].first) + { + depth = std::max(depth, compute_node_depth(branch_list[i].first)); + } + } + depth_set = true; + } + + return depth; + } + + mutable bool depth_set; + mutable std::size_t depth; + + template <typename NodeSequence> + void collect(Node*const& node, + const bool deletable, + NodeSequence& delete_node_list) const + { + if ((0 != node) && deletable) + { + delete_node_list.push_back(const_cast<Node**>(&node)); + } + } + + template <typename NodeSequence> + void collect(const std::pair<Node*, bool>& branch, + NodeSequence& delete_node_list) const + { + collect(branch.first, branch.second, delete_node_list); + } + + template <typename NodeSequence> + void collect(Node*& node, + NodeSequence& delete_node_list) const + { + collect(node, branch_deletable(node), delete_node_list); + } + + template <std::size_t N, typename NodeSequence> + void collect(const std::pair<Node*, bool>(&branch)[N], + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < N; ++i) + { + collect(branch[i].first, branch[i].second, delete_node_list); + } + } + + template <typename Allocator, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<std::pair<Node*, bool>, Allocator>& branch, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch.size(); ++i) + { + collect(branch[i].first, branch[i].second, delete_node_list); + } + } + + template <typename Allocator, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<Node*, Allocator>& branch_list, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + collect(branch_list[i], branch_deletable(branch_list[i]), delete_node_list); + } + } + + template <typename Boolean, + typename AllocatorT, + typename AllocatorB, + template <typename, typename> class Sequence, + typename NodeSequence> + void collect(const Sequence<Node*, AllocatorT>& branch_list, + const Sequence<Boolean, AllocatorB>& branch_deletable_list, + NodeSequence& delete_node_list) const + { + for (std::size_t i = 0; i < branch_list.size(); ++i) + { + collect(branch_list[i], branch_deletable_list[i], delete_node_list); + } + } + }; + template <typename Type> class vector_holder { @@ -5560,30 +6010,70 @@ namespace exprtk } }; + template <typename T, std::size_t N> + inline void construct_branch_pair(std::pair<expression_node<T>*,bool> (&branch)[N], + expression_node<T>* b, + const std::size_t& index) + { + if (b && (index < N)) + { + branch[index] = std::make_pair(b,branch_deletable(b)); + } + } + + template <typename T> + inline void construct_branch_pair(std::pair<expression_node<T>*,bool>& branch, expression_node<T>* b) + { + if (b) + { + branch = std::make_pair(b,branch_deletable(b)); + } + } + + template <std::size_t N, typename T> + inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], + expression_node<T>* b0, + expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), + expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) + { + construct_branch_pair(branch, b0, 0); + construct_branch_pair(branch, b1, 1); + construct_branch_pair(branch, b2, 2); + construct_branch_pair(branch, b3, 3); + construct_branch_pair(branch, b4, 4); + construct_branch_pair(branch, b5, 5); + construct_branch_pair(branch, b6, 6); + construct_branch_pair(branch, b7, 7); + construct_branch_pair(branch, b8, 8); + construct_branch_pair(branch, b9, 9); + } + template <typename T> class null_eq_node : public expression_node<T> { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - null_eq_node(expression_ptr brnch, const bool equality = true) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)), - equality_(equality) - {} - - ~null_eq_node() + explicit null_eq_node(expression_ptr branch, const bool equality = true) + : equality_(equality) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_, branch); } inline T value() const { - const T v = branch_->value(); + assert(branch_.first); + + const T v = branch_.first->value(); const bool result = details::numeric::is_nan(v); if (result) @@ -5604,14 +6094,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_,node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: - expression_ptr branch_; - const bool branch_deletable_; bool equality_; + branch_t branch_; }; template <typename T> @@ -5759,25 +6258,19 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - unary_node(const operator_type& opr, - expression_ptr brnch) - : operation_(opr), - branch_(brnch), - branch_deletable_(branch_deletable(branch_)) - {} - - ~unary_node() + unary_node(const operator_type& opr, expression_ptr branch) + : operation_(opr) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_,branch); } inline T value() const { - const T arg = branch_->value(); + assert(branch_.first); + + const T arg = branch_.first->value(); return numeric::process<T>(operation_,arg); } @@ -5794,94 +6287,28 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; } inline void release() { - branch_deletable_ = false; + branch_.second = false; } - protected: - - operator_type operation_; - expression_ptr branch_; - bool branch_deletable_; - }; - - template <typename T, std::size_t D, bool B> - struct construct_branch_pair - { - template <std::size_t N> - static inline void process(std::pair<expression_node<T>*,bool> (&)[N], expression_node<T>*) - {} - }; - - template <typename T, std::size_t D> - struct construct_branch_pair<T,D,true> - { - template <std::size_t N> - static inline void process(std::pair<expression_node<T>*,bool> (&branch)[N], expression_node<T>* b) + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) { - if (b) - { - branch[D] = std::make_pair(b,branch_deletable(b)); - } + expression_node<T>::ndb_t::collect(branch_, node_delete_list); } - }; - template <std::size_t N, typename T> - inline void init_branches(std::pair<expression_node<T>*,bool> (&branch)[N], - expression_node<T>* b0, - expression_node<T>* b1 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b2 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b3 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b4 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b5 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b6 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b7 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b8 = reinterpret_cast<expression_node<T>*>(0), - expression_node<T>* b9 = reinterpret_cast<expression_node<T>*>(0)) - { - construct_branch_pair<T,0,(N > 0)>::process(branch,b0); - construct_branch_pair<T,1,(N > 1)>::process(branch,b1); - construct_branch_pair<T,2,(N > 2)>::process(branch,b2); - construct_branch_pair<T,3,(N > 3)>::process(branch,b3); - construct_branch_pair<T,4,(N > 4)>::process(branch,b4); - construct_branch_pair<T,5,(N > 5)>::process(branch,b5); - construct_branch_pair<T,6,(N > 6)>::process(branch,b6); - construct_branch_pair<T,7,(N > 7)>::process(branch,b7); - construct_branch_pair<T,8,(N > 8)>::process(branch,b8); - construct_branch_pair<T,9,(N > 9)>::process(branch,b9); - } - - struct cleanup_branches - { - template <typename T, std::size_t N> - static inline void execute(std::pair<expression_node<T>*,bool> (&branch)[N]) + std::size_t node_depth() const { - for (std::size_t i = 0; i < N; ++i) - { - if (branch[i].first && branch[i].second) - { - destroy_node(branch[i].first); - } - } + return expression_node<T>::ndb_t::compute_node_depth(branch_); } - template <typename T, - typename Allocator, - template <typename, typename> class Sequence> - static inline void execute(Sequence<std::pair<expression_node<T>*,bool>,Allocator>& branch) - { - for (std::size_t i = 0; i < branch.size(); ++i) - { - if (branch[i].first && branch[i].second) - { - destroy_node(branch[i].first); - } - } - } + protected: + + operator_type operation_; + branch_t branch_; }; template <typename T> @@ -5900,13 +6327,11 @@ namespace exprtk init_branches<2>(branch_, branch0, branch1); } - ~binary_node() - { - cleanup_branches::execute<T,2>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); @@ -5933,6 +6358,16 @@ namespace exprtk return reinterpret_cast<expression_ptr>(0); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); + } + protected: operator_type operation_; @@ -5952,13 +6387,11 @@ namespace exprtk init_branches<2>(branch_, branch0, branch1); } - ~binary_ext_node() - { - cleanup_branches::execute<T,2>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); @@ -5985,6 +6418,16 @@ namespace exprtk return reinterpret_cast<expression_ptr>(0); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<2>(branch_); + } + protected: branch_t branch_[2]; @@ -6007,13 +6450,12 @@ namespace exprtk init_branches<3>(branch_, branch0, branch1, branch2); } - ~trinary_node() - { - cleanup_branches::execute<T,3>(branch_); - } - inline T value() const { + assert(branch_[0].first); + assert(branch_[1].first); + assert(branch_[2].first); + const T arg0 = branch_[0].first->value(); const T arg1 = branch_[1].first->value(); const T arg2 = branch_[2].first->value(); @@ -6039,6 +6481,16 @@ namespace exprtk return expression_node<T>::e_trinary; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<3>(branch_); + } + protected: operator_type operation_; @@ -6063,11 +6515,6 @@ namespace exprtk init_branches<4>(branch_, branch0, branch1, branch2, branch3); } - ~quaternary_node() - { - cleanup_branches::execute<T,4>(branch_); - } - inline T value() const { return std::numeric_limits<T>::quiet_NaN(); @@ -6078,6 +6525,16 @@ namespace exprtk return expression_node<T>::e_quaternary; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<4>(branch_); + } + protected: operator_type operation_; @@ -6090,42 +6547,27 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - conditional_node(expression_ptr test, + conditional_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative) - : test_(test), - consequent_(consequent), - alternative_(alternative), - test_deletable_(branch_deletable(test_)), - consequent_deletable_(branch_deletable(consequent_)), - alternative_deletable_(branch_deletable(alternative_)) - {} - - ~conditional_node() { - if (test_ && test_deletable_) - { - destroy_node(test_); - } - - if (consequent_ && consequent_deletable_ ) - { - destroy_node(consequent_); - } - - if (alternative_ && alternative_deletable_) - { - destroy_node(alternative_); - } + construct_branch_pair(condition_ , condition ); + construct_branch_pair(consequent_ , consequent ); + construct_branch_pair(alternative_, alternative); } inline T value() const { - if (is_true(test_)) - return consequent_->value(); + assert(condition_ .first); + assert(consequent_ .first); + assert(alternative_.first); + + if (is_true(condition_)) + return consequent_.first->value(); else - return alternative_->value(); + return alternative_.first->value(); } inline typename expression_node<T>::node_type type() const @@ -6133,14 +6575,24 @@ namespace exprtk return expression_node<T>::e_conditional; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(consequent_ , node_delete_list); + expression_node<T>::ndb_t::collect(alternative_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (condition_, consequent_, alternative_); + } + private: - expression_ptr test_; - expression_ptr consequent_; - expression_ptr alternative_; - const bool test_deletable_; - const bool consequent_deletable_; - const bool alternative_deletable_; + branch_t condition_; + branch_t consequent_; + branch_t alternative_; }; template <typename T> @@ -6150,32 +6602,22 @@ namespace exprtk // Consequent only conditional statement node typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - cons_conditional_node(expression_ptr test, + cons_conditional_node(expression_ptr condition, expression_ptr consequent) - : test_(test), - consequent_(consequent), - test_deletable_(branch_deletable(test_)), - consequent_deletable_(branch_deletable(consequent_)) - {} - - ~cons_conditional_node() { - if (test_ && test_deletable_) - { - destroy_node(test_); - } - - if (consequent_ && consequent_deletable_) - { - destroy_node(consequent_); - } + construct_branch_pair(condition_ , condition ); + construct_branch_pair(consequent_, consequent); } inline T value() const { - if (is_true(test_)) - return consequent_->value(); + assert(condition_ .first); + assert(consequent_.first); + + if (is_true(condition_)) + return consequent_.first->value(); else return std::numeric_limits<T>::quiet_NaN(); } @@ -6185,12 +6627,22 @@ namespace exprtk return expression_node<T>::e_conditional; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(consequent_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t:: + compute_node_depth(condition_, consequent_); + } + private: - expression_ptr test_; - expression_ptr consequent_; - const bool test_deletable_; - const bool consequent_deletable_; + branch_t condition_; + branch_t consequent_; }; #ifndef exprtk_disable_break_continue @@ -6199,7 +6651,7 @@ namespace exprtk { public: - break_exception(const T& v) + explicit break_exception(const T& v) : value(v) {} @@ -6215,23 +6667,16 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; break_node(expression_ptr ret = expression_ptr(0)) - : return_(ret), - return_deletable_(branch_deletable(return_)) - {} - - ~break_node() { - if (return_deletable_) - { - destroy_node(return_); - } + construct_branch_pair(return_, ret); } inline T value() const { - throw break_exception<T>(return_ ? return_->value() : std::numeric_limits<T>::quiet_NaN()); + throw break_exception<T>(return_.first ? return_.first->value() : std::numeric_limits<T>::quiet_NaN()); #ifndef _MSC_VER return std::numeric_limits<T>::quiet_NaN(); #endif @@ -6242,10 +6687,19 @@ namespace exprtk return expression_node<T>::e_break; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(return_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(return_); + } + private: - expression_ptr return_; - const bool return_deletable_; + branch_t return_; }; template <typename T> @@ -6268,40 +6722,90 @@ namespace exprtk }; #endif - template <typename T> - class while_loop_node : public expression_node<T> + #ifdef exprtk_enable_runtime_checks + struct loop_runtime_checker { - public: - - typedef expression_node<T>* expression_ptr; - - while_loop_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) + loop_runtime_checker(loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0), + loop_runtime_check::loop_types lp_typ = loop_runtime_check::e_invalid) + : iteration_count_(0), + loop_runtime_check_(loop_rt_chk), + loop_type(lp_typ) {} - ~while_loop_node() + inline void reset(const _uint64_t initial_value = 0) const { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } + iteration_count_ = initial_value; + } - if (loop_body_ && loop_body_deletable_) + inline bool check() const + { + if ( + (0 == loop_runtime_check_) || + (++iteration_count_ <= loop_runtime_check_->max_loop_iterations) + ) { - destroy_node(loop_body_); + return true; } + + loop_runtime_check::violation_context ctxt; + ctxt.loop = loop_type; + ctxt.violation = loop_runtime_check::e_iteration_count; + + loop_runtime_check_->handle_runtime_violation(ctxt); + + return false; + } + + mutable _uint64_t iteration_count_; + mutable loop_runtime_check_ptr loop_runtime_check_; + loop_runtime_check::loop_types loop_type; + }; + #else + struct loop_runtime_checker + { + loop_runtime_checker(loop_runtime_check_ptr, loop_runtime_check::loop_types) + {} + + inline void reset(const _uint64_t = 0) const + {} + + inline bool check() const + { + return true; + } + }; + #endif + + template <typename T> + class while_loop_node : public expression_node<T>, + public loop_runtime_checker + { + public: + + typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + + while_loop_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk,loop_runtime_check::e_while_loop) + { + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - while (is_true(condition_)) + loop_runtime_checker::reset(); + + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); + result = loop_body_.first->value(); } return result; @@ -6312,50 +6816,55 @@ namespace exprtk return expression_node<T>::e_while; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class repeat_until_loop_node : public expression_node<T> + class repeat_until_loop_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - repeat_until_loop_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~repeat_until_loop_node() + repeat_until_loop_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); + loop_runtime_checker::reset(1); + do { - result = loop_body_->value(); + result = loop_body_.first->value(); } - while (is_false(condition_)); + while (is_false(condition_.first) && loop_runtime_checker::check()); return result; } @@ -6365,78 +6874,70 @@ namespace exprtk return expression_node<T>::e_repeat; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class for_loop_node : public expression_node<T> + class for_loop_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; for_loop_node(expression_ptr initialiser, expression_ptr condition, expression_ptr incrementor, - expression_ptr loop_body) - : initialiser_(initialiser), - condition_ (condition ), - incrementor_(incrementor), - loop_body_ (loop_body ), - initialiser_deletable_(branch_deletable(initialiser_)), - condition_deletable_ (branch_deletable(condition_ )), - incrementor_deletable_(branch_deletable(incrementor_)), - loop_body_deletable_ (branch_deletable(loop_body_ )) - {} - - ~for_loop_node() + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) { - if (initialiser_ && initialiser_deletable_) - { - destroy_node(initialiser_); - } - - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (incrementor_ && incrementor_deletable_) - { - destroy_node(incrementor_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(initialiser_, initialiser); + construct_branch_pair(condition_ , condition ); + construct_branch_pair(incrementor_, incrementor); + construct_branch_pair(loop_body_ , loop_body ); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - if (initialiser_) - initialiser_->value(); + loop_runtime_checker::reset(); + + if (initialiser_.first) + initialiser_.first->value(); - if (incrementor_) + if (incrementor_.first) { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); - incrementor_->value(); + result = loop_body_.first->value(); + incrementor_.first->value(); } } else { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { - result = loop_body_->value(); + result = loop_body_.first->value(); } } @@ -6448,55 +6949,61 @@ namespace exprtk return expression_node<T>::e_for; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_, node_delete_list); + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(incrementor_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (initialiser_, condition_, incrementor_, loop_body_); + } + private: - expression_ptr initialiser_ ; - expression_ptr condition_ ; - expression_ptr incrementor_ ; - expression_ptr loop_body_ ; - const bool initialiser_deletable_; - const bool condition_deletable_ ; - const bool incrementor_deletable_; - const bool loop_body_deletable_ ; + branch_t initialiser_; + branch_t condition_ ; + branch_t incrementor_; + branch_t loop_body_ ; }; #ifndef exprtk_disable_break_continue template <typename T> - class while_loop_bc_node : public expression_node<T> + class while_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - while_loop_bc_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~while_loop_bc_node() + while_loop_bc_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_while_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - while (is_true(condition_)) + loop_runtime_checker::reset(); + + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6514,50 +7021,55 @@ namespace exprtk return expression_node<T>::e_while; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class repeat_until_loop_bc_node : public expression_node<T> + class repeat_until_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - repeat_until_loop_bc_node(expression_ptr condition, expression_ptr loop_body) - : condition_(condition), - loop_body_(loop_body), - condition_deletable_(branch_deletable(condition_)), - loop_body_deletable_(branch_deletable(loop_body_)) - {} - - ~repeat_until_loop_bc_node() + repeat_until_loop_bc_node(expression_ptr condition, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_repeat_until_loop) { - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(condition_, condition); + construct_branch_pair(loop_body_, loop_body); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); + loop_runtime_checker::reset(); + do { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6566,7 +7078,7 @@ namespace exprtk catch(const continue_exception&) {} } - while (is_false(condition_)); + while (is_false(condition_.first) && loop_runtime_checker::check()); return result; } @@ -6576,72 +7088,64 @@ namespace exprtk return expression_node<T>::e_repeat; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(condition_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(condition_, loop_body_); + } + private: - expression_ptr condition_; - expression_ptr loop_body_; - const bool condition_deletable_; - const bool loop_body_deletable_; + branch_t condition_; + branch_t loop_body_; }; template <typename T> - class for_loop_bc_node : public expression_node<T> + class for_loop_bc_node : public expression_node<T>, + public loop_runtime_checker { public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; for_loop_bc_node(expression_ptr initialiser, - expression_ptr condition, - expression_ptr incrementor, - expression_ptr loop_body) - : initialiser_(initialiser), - condition_ (condition ), - incrementor_(incrementor), - loop_body_ (loop_body ), - initialiser_deletable_(branch_deletable(initialiser_)), - condition_deletable_ (branch_deletable(condition_ )), - incrementor_deletable_(branch_deletable(incrementor_)), - loop_body_deletable_ (branch_deletable(loop_body_ )) - {} - - ~for_loop_bc_node() + expression_ptr condition, + expression_ptr incrementor, + expression_ptr loop_body, + loop_runtime_check_ptr loop_rt_chk = loop_runtime_check_ptr(0)) + : loop_runtime_checker(loop_rt_chk, loop_runtime_check::e_for_loop) { - if (initialiser_ && initialiser_deletable_) - { - destroy_node(initialiser_); - } - - if (condition_ && condition_deletable_) - { - destroy_node(condition_); - } - - if (incrementor_ && incrementor_deletable_) - { - destroy_node(incrementor_); - } - - if (loop_body_ && loop_body_deletable_) - { - destroy_node(loop_body_); - } + construct_branch_pair(initialiser_, initialiser); + construct_branch_pair(condition_ , condition ); + construct_branch_pair(incrementor_, incrementor); + construct_branch_pair(loop_body_ , loop_body ); } inline T value() const { + assert(condition_.first); + assert(loop_body_.first); + T result = T(0); - if (initialiser_) - initialiser_->value(); + loop_runtime_checker::reset(); - if (incrementor_) + if (initialiser_.first) + initialiser_.first->value(); + + if (incrementor_.first) { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6650,16 +7154,16 @@ namespace exprtk catch(const continue_exception&) {} - incrementor_->value(); + incrementor_.first->value(); } } else { - while (is_true(condition_)) + while (is_true(condition_) && loop_runtime_checker::check()) { try { - result = loop_body_->value(); + result = loop_body_.first->value(); } catch(const break_exception<T>& e) { @@ -6678,16 +7182,26 @@ namespace exprtk return expression_node<T>::e_for; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_, node_delete_list); + expression_node<T>::ndb_t::collect(condition_ , node_delete_list); + expression_node<T>::ndb_t::collect(incrementor_, node_delete_list); + expression_node<T>::ndb_t::collect(loop_body_ , node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth + (initialiser_, condition_, incrementor_, loop_body_); + } + private: - expression_ptr initialiser_; - expression_ptr condition_ ; - expression_ptr incrementor_; - expression_ptr loop_body_ ; - const bool initialiser_deletable_; - const bool condition_deletable_ ; - const bool incrementor_deletable_; - const bool loop_body_deletable_ ; + branch_t initialiser_; + branch_t condition_ ; + branch_t incrementor_; + branch_t loop_body_ ; }; #endif @@ -6697,44 +7211,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - switch_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit switch_node(const Sequence<expression_ptr,Allocator>& arg_list) { if (1 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~switch_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { if (!arg_list_.empty()) @@ -6743,8 +7244,8 @@ namespace exprtk for (std::size_t i = 0; i < upper_bound; i += 2) { - expression_ptr condition = arg_list_[i ]; - expression_ptr consequent = arg_list_[i + 1]; + expression_ptr condition = arg_list_[i ].first; + expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { @@ -6752,7 +7253,7 @@ namespace exprtk } } - return arg_list_[upper_bound]->value(); + return arg_list_[upper_bound].first->value(); } else return std::numeric_limits<T>::quiet_NaN(); @@ -6763,10 +7264,19 @@ namespace exprtk return expression_node<T>::e_switch; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + protected: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T, typename Switch_N> @@ -6778,7 +7288,7 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit switch_n_node(const Sequence<expression_ptr,Allocator>& arg_list) : switch_node<T>(arg_list) {} @@ -6794,44 +7304,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit multi_switch_node(const Sequence<expression_ptr,Allocator>& arg_list) { if (0 != (arg_list.size() & 1)) return; arg_list_.resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~multi_switch_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { T result = T(0); @@ -6845,8 +7342,8 @@ namespace exprtk for (std::size_t i = 0; i < upper_bound; i += 2) { - expression_ptr condition = arg_list_[i ]; - expression_ptr consequent = arg_list_[i + 1]; + expression_ptr condition = arg_list_[i ].first; + expression_ptr consequent = arg_list_[i + 1].first; if (is_true(condition)) { @@ -6862,10 +7359,19 @@ namespace exprtk return expression_node<T>::e_mswitch; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T> @@ -6892,7 +7398,7 @@ namespace exprtk : value_(&null_value) {} - variable_node(T& v) + explicit variable_node(T& v) : value_(&v) {} @@ -6981,30 +7487,26 @@ namespace exprtk } } - bool const_range() + bool const_range() const { return ( n0_c.first && n1_c.first) && (!n0_e.first && !n1_e.first); } - bool var_range() + bool var_range() const { return ( n0_e.first && n1_e.first) && (!n0_c.first && !n1_c.first); } - bool operator() (std::size_t& r0, std::size_t& r1, const std::size_t& size = std::numeric_limits<std::size_t>::max()) const + bool operator() (std::size_t& r0, std::size_t& r1, + const std::size_t& size = std::numeric_limits<std::size_t>::max()) const { if (n0_c.first) r0 = n0_c.second; else if (n0_e.first) { - T r0_value = n0_e.second->value(); - - if (r0_value < 0) - return false; - else - r0 = static_cast<std::size_t>(details::numeric::to_int64(r0_value)); + r0 = static_cast<std::size_t>(details::numeric::to_int64(n0_e.second->value())); } else return false; @@ -7013,12 +7515,7 @@ namespace exprtk r1 = n1_c.second; else if (n1_e.first) { - T r1_value = n1_e.second->value(); - - if (r1_value < 0) - return false; - else - r1 = static_cast<std::size_t>(details::numeric::to_int64(r1_value)); + r1 = static_cast<std::size_t>(details::numeric::to_int64(n1_e.second->value())); } else return false; @@ -7034,7 +7531,11 @@ namespace exprtk cache.first = r0; cache.second = r1; + #ifndef exprtk_enable_runtime_checks return (r0 <= r1); + #else + return range_runtime_check(r0, r1, size); + #endif } inline std::size_t const_size() const @@ -7052,6 +7553,27 @@ namespace exprtk std::pair<bool,std::size_t > n0_c; std::pair<bool,std::size_t > n1_c; mutable cached_range_t cache; + + #ifdef exprtk_enable_runtime_checks + bool range_runtime_check(const std::size_t r0, + const std::size_t r1, + const std::size_t size) const + { + if ((r0 < 0) || (r0 >= size)) + { + throw std::runtime_error("range error: (r0 < 0) || (r0 >= size)"); + return false; + } + + if ((r1 < 0) || (r1 >= size)) + { + throw std::runtime_error("range error: (r1 < 0) || (r1 >= size)"); + return false; + } + + return (r0 <= r1); + } + #endif }; template <typename T> @@ -7115,7 +7637,7 @@ namespace exprtk typedef vector_node<T>* vector_node_ptr; typedef vec_data_store<T> vds_t; - vector_node(vector_holder_t* vh) + explicit vector_node(vector_holder_t* vh) : vector_holder_(vh), vds_((*vector_holder_).size(),(*vector_holder_)[0]) { @@ -7179,38 +7701,31 @@ namespace exprtk { public: - typedef expression_node<T>* expression_ptr; - typedef vector_holder<T> vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; + typedef expression_node<T>* expression_ptr; + typedef vector_holder<T> vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef std::pair<expression_ptr,bool> branch_t; vector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : index_(index), - vec_holder_(vec_holder), - vector_base_((*vec_holder)[0]), - index_deletable_(branch_deletable(index_)) - {} - - ~vector_elem_node() + : vec_holder_(vec_holder), + vector_base_((*vec_holder)[0]) { - if (index_ && index_deletable_) - { - destroy_node(index_); - } + construct_branch_pair(index_, index); } inline T value() const { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline T& ref() { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline const T& ref() const { - return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vector_base_ + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline typename expression_node<T>::node_type type() const @@ -7223,12 +7738,21 @@ namespace exprtk return (*vec_holder_); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(index_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(index_); + } + private: - expression_ptr index_; vector_holder_ptr vec_holder_; T* vector_base_; - const bool index_deletable_; + branch_t index_; }; template <typename T> @@ -7237,41 +7761,33 @@ namespace exprtk { public: - typedef expression_node<T>* expression_ptr; - typedef vector_holder<T> vector_holder_t; - typedef vector_holder_t* vector_holder_ptr; - typedef vec_data_store<T> vds_t; + typedef expression_node<T>* expression_ptr; + typedef vector_holder<T> vector_holder_t; + typedef vector_holder_t* vector_holder_ptr; + typedef vec_data_store<T> vds_t; + typedef std::pair<expression_ptr,bool> branch_t; rebasevector_elem_node(expression_ptr index, vector_holder_ptr vec_holder) - : index_(index), - index_deletable_(branch_deletable(index_)), - vector_holder_(vec_holder), + : vector_holder_(vec_holder), vds_((*vector_holder_).size(),(*vector_holder_)[0]) { vector_holder_->set_ref(&vds_.ref()); - } - - ~rebasevector_elem_node() - { - if (index_ && index_deletable_) - { - destroy_node(index_); - } + construct_branch_pair(index_, index); } inline T value() const { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline T& ref() { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline const T& ref() const { - return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_->value()))); + return *(vds_.data() + static_cast<std::size_t>(details::numeric::to_int64(index_.first->value()))); } inline typename expression_node<T>::node_type type() const @@ -7284,12 +7800,21 @@ namespace exprtk return (*vector_holder_); } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(index_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(index_); + } + private: - expression_ptr index_; - const bool index_deletable_; vector_holder_ptr vector_holder_; vds_t vds_; + branch_t index_; }; template <typename T> @@ -7360,17 +7885,6 @@ namespace exprtk single_value_initialse_(single_value_initialse) {} - ~vector_assignment_node() - { - for (std::size_t i = 0; i < initialiser_list_.size(); ++i) - { - if (branch_deletable(initialiser_list_[i])) - { - destroy_node(initialiser_list_[i]); - } - } - } - inline T value() const { if (single_value_initialse_) @@ -7406,6 +7920,16 @@ namespace exprtk return expression_node<T>::e_vecdefass; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(initialiser_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(initialiser_list_); + } + private: vector_assignment_node<T>& operator=(const vector_assignment_node<T>&); @@ -7527,6 +8051,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + if (initialised_) { binary_node<T>::branch_[0].first->value(); @@ -7831,18 +8358,18 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef stringvar_node <T>* strvar_node_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef stringvar_node <T>* strvar_node_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + generic_string_range_node(expression_ptr str_branch, const range_t& brange) : initialised_(false), - branch_(str_branch), - branch_deletable_(branch_deletable(branch_)), str_base_ptr_ (0), str_range_ptr_(0), base_range_(brange) @@ -7852,14 +8379,16 @@ namespace exprtk range_.cache.first = range_.n0_c.second; range_.cache.second = range_.n1_c.second; - if (is_generally_string_node(branch_)) + construct_branch_pair(branch_, str_branch); + + if (is_generally_string_node(branch_.first)) { - str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); if (0 == str_base_ptr_) return; - str_range_ptr_ = dynamic_cast<irange_ptr>(branch_); + str_range_ptr_ = dynamic_cast<irange_ptr>(branch_.first); if (0 == str_range_ptr_) return; @@ -7871,18 +8400,15 @@ namespace exprtk ~generic_string_range_node() { base_range_.free(); - - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } } inline T value() const { if (initialised_) { - branch_->value(); + assert(branch_.first); + + branch_.first->value(); std::size_t str_r0 = 0; std::size_t str_r1 = 0; @@ -7890,13 +8416,13 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = 0; - range_t& range = str_range_ptr_->range_ref(); + const range_t& range = str_range_ptr_->range_ref(); const std::size_t base_str_size = str_base_ptr_->size(); if ( - range (str_r0,str_r1,base_str_size) && - base_range_( r0, r1,base_str_size) + range (str_r0, str_r1, base_str_size) && + base_range_( r0, r1, base_str_size) ) { const std::size_t size = (r1 - r0) + 1; @@ -7941,11 +8467,20 @@ namespace exprtk return expression_node<T>::e_strgenrange; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bool initialised_; - expression_ptr branch_; - const bool branch_deletable_; + branch_t branch_; str_base_ptr str_base_ptr_; irange_ptr str_range_ptr_; mutable range_t base_range_; @@ -8019,6 +8554,9 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8028,12 +8566,12 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = str0_range_ptr_->range_ref(); - range_t& range1 = str1_range_ptr_->range_ref(); + const range_t& range0 = str0_range_ptr_->range_ref(); + const range_t& range1 = str1_range_ptr_->range_ref(); if ( - range0(str0_r0,str0_r1,str0_base_ptr_->size()) && - range1(str1_r0,str1_r1,str1_base_ptr_->size()) + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = (str0_r1 - str0_r0) + 1; @@ -8129,10 +8667,13 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - std::swap(str0_node_ptr_->ref(),str1_node_ptr_->ref()); + std::swap(str0_node_ptr_->ref(), str1_node_ptr_->ref()); } return std::numeric_limits<T>::quiet_NaN(); @@ -8236,6 +8777,9 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8245,12 +8789,12 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( - range0(str0_r0,str0_r1,str0_base_ptr_->size()) && - range1(str1_r0,str1_r1,str1_base_ptr_->size()) + range0(str0_r0, str0_r1, str0_base_ptr_->size()) && + range1(str1_r0, str1_r1, str1_base_ptr_->size()) ) { const std::size_t size0 = range0.cache_size(); @@ -8288,8 +8832,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { std::swap(s0[i],s1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { std::swap(s0[i], s1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -8367,38 +8911,32 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef string_base_node<T>* str_base_ptr; + typedef expression_node <T>* expression_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef std::pair<expression_ptr,bool> branch_t; + - string_size_node(expression_ptr brnch) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)), - str_base_ptr_(0) + explicit string_size_node(expression_ptr branch) + : str_base_ptr_(0) { - if (is_generally_string_node(branch_)) + construct_branch_pair(branch_, branch); + + if (is_generally_string_node(branch_.first)) { - str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(branch_.first); if (0 == str_base_ptr_) return; } } - ~string_size_node() - { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } - } - inline T value() const { T result = std::numeric_limits<T>::quiet_NaN(); if (str_base_ptr_) { - branch_->value(); + branch_.first->value(); result = T(str_base_ptr_->size()); } @@ -8410,11 +8948,20 @@ namespace exprtk return expression_node<T>::e_stringsize; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: - expression_ptr branch_; - const bool branch_deletable_; - str_base_ptr str_base_ptr_; + branch_t branch_; + str_base_ptr str_base_ptr_; }; struct asn_assignment @@ -8486,12 +9033,15 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[1].first->value(); std::size_t r0 = 0; std::size_t r1 = 0; - range_t& range = (*str1_range_ptr_); + const range_t& range = (*str1_range_ptr_); if (range(r0, r1, str1_base_ptr_->size())) { @@ -8552,28 +9102,29 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef stringvar_node <T>* strvar_node_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef stringvar_node <T>* strvar_node_ptr; + typedef string_range_node<T>* str_rng_node_ptr; + typedef string_base_node <T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; assignment_string_range_node(const operator_type& opr, expression_ptr branch0, expression_ptr branch1) : binary_node<T>(opr, branch0, branch1), initialised_(false), - str0_base_ptr_ (0), - str1_base_ptr_ (0), - str0_node_ptr_ (0), - str0_range_ptr_(0), - str1_range_ptr_(0) + str0_base_ptr_ (0), + str1_base_ptr_ (0), + str0_rng_node_ptr_ (0), + str0_range_ptr_ (0), + str1_range_ptr_ (0) { if (is_string_range_node(binary_node<T>::branch_[0].first)) { - str0_node_ptr_ = static_cast<strvar_node_ptr>(binary_node<T>::branch_[0].first); + str0_rng_node_ptr_ = static_cast<str_rng_node_ptr>(binary_node<T>::branch_[0].first); str0_base_ptr_ = dynamic_cast<str_base_ptr>(binary_node<T>::branch_[0].first); @@ -8600,17 +9151,20 @@ namespace exprtk str1_range_ptr_ = &(range->range_ref()); } - initialised_ = str0_base_ptr_ && - str1_base_ptr_ && - str0_node_ptr_ && - str0_range_ptr_ && - str1_range_ptr_ ; + initialised_ = str0_base_ptr_ && + str1_base_ptr_ && + str0_rng_node_ptr_ && + str0_range_ptr_ && + str1_range_ptr_ ; } inline T value() const { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); @@ -8620,15 +9174,15 @@ namespace exprtk std::size_t s1_r0 = 0; std::size_t s1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( range0(s0_r0, s0_r1, str0_base_ptr_->size()) && range1(s1_r0, s1_r1, str1_base_ptr_->size()) ) { - std::size_t size = std::min((s0_r1 - s0_r0),(s1_r1 - s1_r0)) + 1; + const std::size_t size = std::min((s0_r1 - s0_r0), (s1_r1 - s1_r0)) + 1; std::copy(str1_base_ptr_->base() + s1_r0, str1_base_ptr_->base() + s1_r0 + size, @@ -8641,27 +9195,27 @@ namespace exprtk std::string str() const { - return str0_node_ptr_->str(); + return str0_base_ptr_->str(); } char_cptr base() const { - return str0_node_ptr_->base(); + return str0_base_ptr_->base(); } std::size_t size() const { - return str0_node_ptr_->size(); + return str0_base_ptr_->size(); } range_t& range_ref() { - return str0_node_ptr_->range_ref(); + return str0_rng_node_ptr_->range_ref(); } const range_t& range_ref() const { - return str0_node_ptr_->range_ref(); + return str0_rng_node_ptr_->range_ref(); } inline typename expression_node<T>::node_type type() const @@ -8671,12 +9225,12 @@ namespace exprtk private: - bool initialised_; - str_base_ptr str0_base_ptr_; - str_base_ptr str1_base_ptr_; - strvar_node_ptr str0_node_ptr_; - range_ptr str0_range_ptr_; - range_ptr str1_range_ptr_; + bool initialised_; + str_base_ptr str0_base_ptr_; + str_base_ptr str1_base_ptr_; + str_rng_node_ptr str0_rng_node_ptr_; + range_ptr str0_range_ptr_; + range_ptr str1_range_ptr_; }; template <typename T> @@ -8693,16 +9247,16 @@ namespace exprtk typedef range_interface<T> irange_t; typedef irange_t* irange_ptr; - conditional_string_node(expression_ptr test, + conditional_string_node(expression_ptr condition, expression_ptr consequent, expression_ptr alternative) - : trinary_node<T>(details::e_default,consequent,alternative,test), + : trinary_node<T>(details::e_default,consequent,alternative,condition), initialised_(false), str0_base_ptr_ (0), str1_base_ptr_ (0), str0_range_ptr_(0), str1_range_ptr_(0), - test_ (test), + condition_ (condition), consequent_ (consequent), alternative_(alternative) { @@ -8749,14 +9303,18 @@ namespace exprtk { if (initialised_) { + assert(condition_ ); + assert(consequent_ ); + assert(alternative_); + std::size_t r0 = 0; std::size_t r1 = 0; - if (is_true(test_)) + if (is_true(condition_)) { consequent_->value(); - range_t& range = str0_range_ptr_->range_ref(); + const range_t& range = str0_range_ptr_->range_ref(); if (range(r0, r1, str0_base_ptr_->size())) { @@ -8774,7 +9332,7 @@ namespace exprtk { alternative_->value(); - range_t& range = str1_range_ptr_->range_ref(); + const range_t& range = str1_range_ptr_->range_ref(); if (range(r0, r1, str1_base_ptr_->size())) { @@ -8833,7 +9391,7 @@ namespace exprtk mutable range_t range_; mutable std::string value_; - expression_ptr test_; + expression_ptr condition_; expression_ptr consequent_; expression_ptr alternative_; }; @@ -8852,13 +9410,13 @@ namespace exprtk typedef range_interface<T> irange_t; typedef irange_t* irange_ptr; - cons_conditional_str_node(expression_ptr test, + cons_conditional_str_node(expression_ptr condition, expression_ptr consequent) - : binary_node<T>(details::e_default, consequent, test), + : binary_node<T>(details::e_default, consequent, condition), initialised_(false), str0_base_ptr_ (0), str0_range_ptr_(0), - test_ (test), + condition_ (condition), consequent_(consequent) { range_.n0_c = std::make_pair<bool,std::size_t>(true,0); @@ -8887,11 +9445,14 @@ namespace exprtk { if (initialised_) { - if (is_true(test_)) + assert(condition_ ); + assert(consequent_); + + if (is_true(condition_)) { consequent_->value(); - range_t& range = str0_range_ptr_->range_ref(); + const range_t& range = str0_range_ptr_->range_ref(); std::size_t r0 = 0; std::size_t r1 = 0; @@ -8951,7 +9512,7 @@ namespace exprtk mutable range_t range_; mutable std::string value_; - expression_ptr test_; + expression_ptr condition_; expression_ptr consequent_; }; @@ -8962,33 +9523,34 @@ namespace exprtk { public: - typedef expression_node <T>* expression_ptr; - typedef string_base_node<T>* str_base_ptr; - typedef range_pack <T> range_t; - typedef range_t* range_ptr; - typedef range_interface<T> irange_t; - typedef irange_t* irange_ptr; + typedef expression_node <T>* expression_ptr; + typedef string_base_node<T>* str_base_ptr; + typedef range_pack <T> range_t; + typedef range_t* range_ptr; + typedef range_interface<T> irange_t; + typedef irange_t* irange_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) - : final_node_(arg_list.back()), - final_deletable_(branch_deletable(final_node_)), - initialised_(false), + explicit str_vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) + : initialised_(false), str_base_ptr_ (0), str_range_ptr_(0) { - if (0 == final_node_) + construct_branch_pair(final_node_, const_cast<expression_ptr>(arg_list.back())); + + if (0 == final_node_.first) return; - else if (!is_generally_string_node(final_node_)) + else if (!is_generally_string_node(final_node_.first)) return; - str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_); + str_base_ptr_ = dynamic_cast<str_base_ptr>(final_node_.first); if (0 == str_base_ptr_) return; - str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_); + str_range_ptr_ = dynamic_cast<irange_ptr>(final_node_.first); if (0 == str_range_ptr_) return; @@ -9000,41 +9562,22 @@ namespace exprtk const std::size_t arg_list_size = arg_list.size() - 1; arg_list_.resize(arg_list_size); - delete_branch_.resize(arg_list_size); for (std::size_t i = 0; i < arg_list_size; ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i], arg_list[i]); } else { - arg_list_ .clear(); - delete_branch_.clear(); + arg_list_.clear(); return; } } } } - ~str_vararg_node() - { - if (final_node_ && final_deletable_) - { - destroy_node(final_node_); - } - - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { if (!arg_list_.empty()) @@ -9042,7 +9585,7 @@ namespace exprtk VarArgFunction::process(arg_list_); } - final_node_->value(); + final_node_.first->value(); return std::numeric_limits<T>::quiet_NaN(); } @@ -9077,15 +9620,26 @@ namespace exprtk return expression_node<T>::e_stringvararg; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(final_node_, node_delete_list); + expression_node<T>::ndb_t::collect(arg_list_ , node_delete_list); + } + + std::size_t node_depth() const + { + return std::max( + expression_node<T>::ndb_t::compute_node_depth(final_node_), + expression_node<T>::ndb_t::compute_node_depth(arg_list_ )); + } + private: - expression_ptr final_node_; - bool final_deletable_; - bool initialised_; - str_base_ptr str_base_ptr_; - irange_ptr str_range_ptr_; - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + bool initialised_; + branch_t final_node_; + str_base_ptr str_base_ptr_; + irange_ptr str_range_ptr_; + std::vector<branch_t> arg_list_; }; #endif @@ -9118,14 +9672,14 @@ namespace exprtk template <typename T> \ struct sf##NN##_op : public sf_base<T> \ { \ - typedef typename sf_base<T>::Type Type; \ + typedef typename sf_base<T>::Type const Type; \ static inline T process(Type x, Type y, Type z) \ { \ return (OP0); \ } \ static inline std::string id() \ { \ - return OP1; \ + return (OP1); \ } \ }; \ @@ -9182,12 +9736,15 @@ namespace exprtk template <typename T> \ struct sf##NN##_op : public sf_base<T> \ { \ - typedef typename sf_base<T>::Type Type; \ + typedef typename sf_base<T>::Type const Type; \ static inline T process(Type x, Type y, Type z, Type w) \ { \ return (OP0); \ } \ - static inline std::string id() { return OP1; } \ + static inline std::string id() \ + { \ + return (OP1); \ + } \ }; \ define_sfop4(48,(x + ((y + z) / w)),"t+((t+t)/t)") @@ -9326,6 +9883,10 @@ namespace exprtk inline T value() const { + assert(trinary_node<T>::branch_[0].first); + assert(trinary_node<T>::branch_[1].first); + assert(trinary_node<T>::branch_[2].first); + const T x = trinary_node<T>::branch_[0].first->value(); const T y = trinary_node<T>::branch_[1].first->value(); const T z = trinary_node<T>::branch_[2].first->value(); @@ -9351,6 +9912,11 @@ namespace exprtk inline T value() const { + assert(quaternary_node<T>::branch_[0].first); + assert(quaternary_node<T>::branch_[1].first); + assert(quaternary_node<T>::branch_[2].first); + assert(quaternary_node<T>::branch_[3].first); + const T x = quaternary_node<T>::branch_[0].first->value(); const T y = quaternary_node<T>::branch_[1].first->value(); const T z = quaternary_node<T>::branch_[2].first->value(); @@ -9434,47 +10000,31 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; template <typename Allocator, template <typename, typename> class Sequence> - vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) + explicit vararg_node(const Sequence<expression_ptr,Allocator>& arg_list) { - arg_list_ .resize(arg_list.size()); - delete_branch_.resize(arg_list.size()); + arg_list_.resize(arg_list.size()); for (std::size_t i = 0; i < arg_list.size(); ++i) { if (arg_list[i]) { - arg_list_[i] = arg_list[i]; - delete_branch_[i] = static_cast<unsigned char>(branch_deletable(arg_list_[i]) ? 1 : 0); + construct_branch_pair(arg_list_[i],arg_list[i]); } else { arg_list_.clear(); - delete_branch_.clear(); return; } } } - ~vararg_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && delete_branch_[i]) - { - destroy_node(arg_list_[i]); - } - } - } - inline T value() const { - if (!arg_list_.empty()) - return VarArgFunction::process(arg_list_); - else - return std::numeric_limits<T>::quiet_NaN(); + return VarArgFunction::process(arg_list_); } inline typename expression_node<T>::node_type type() const @@ -9482,10 +10032,19 @@ namespace exprtk return expression_node<T>::e_vararg; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(arg_list_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: - std::vector<expression_ptr> arg_list_; - std::vector<unsigned char> delete_branch_; + std::vector<branch_t> arg_list_; }; template <typename T, typename VarArgFunction> @@ -9497,7 +10056,7 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) + explicit vararg_varnode(const Sequence<expression_ptr,Allocator>& arg_list) { arg_list_.resize(arg_list.size()); @@ -9540,33 +10099,29 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; - vectorize_node(const expression_ptr v) - : ivec_ptr_(0), - v_(v), - v_deletable_(branch_deletable(v_)) + explicit vectorize_node(const expression_ptr v) + : ivec_ptr_(0) { - if (is_ivector_node(v)) + construct_branch_pair(v_, v); + + if (is_ivector_node(v_.first)) { - ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v); + ivec_ptr_ = dynamic_cast<vector_interface<T>*>(v_.first); } else ivec_ptr_ = 0; } - ~vectorize_node() - { - if (v_ && v_deletable_) - { - destroy_node(v_); - } - } - inline T value() const { if (ivec_ptr_) { - v_->value(); + assert(v_.first); + + v_.first->value(); + return VecFunction::process(ivec_ptr_); } else @@ -9578,11 +10133,20 @@ namespace exprtk return expression_node<T>::e_vecfunc; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(v_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(v_); + } + private: vector_interface<T>* ivec_ptr_; - expression_ptr v_; - const bool v_deletable_; + branch_t v_; }; template <typename T> @@ -9608,6 +10172,8 @@ namespace exprtk { if (var_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = var_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9646,6 +10212,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = vec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9684,6 +10252,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = rbvec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9722,6 +10292,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& result = rbvec_node_ptr_->ref(); result = binary_node<T>::branch_[1].first->value(); @@ -9764,6 +10336,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[1].first->value(); T* vec = vds().data(); @@ -9773,8 +10347,8 @@ namespace exprtk while (vec < upper_bound) { - #define exprtk_loop(N) \ - vec[N] = v; \ + #define exprtk_loop(N) \ + vec[N] = v; \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -9909,6 +10483,8 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[1].first->value(); if (src_is_ivec_) @@ -10030,6 +10606,8 @@ namespace exprtk { if (var_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = var_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10067,6 +10645,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = vec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10104,6 +10684,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10141,6 +10723,8 @@ namespace exprtk { if (rbvec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + T& v = rbvec_node_ptr_->ref(); v = Operation::process(v,binary_node<T>::branch_[1].first->value()); @@ -10182,6 +10766,8 @@ namespace exprtk { if (vec_node_ptr_) { + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[1].first->value(); T* vec = vds().data(); @@ -10327,19 +10913,22 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(vec0[N],vec1[N]); \ + #define exprtk_loop(N) \ + vec0[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10361,8 +10950,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(vec0[i],vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10512,20 +11101,23 @@ namespace exprtk { if (initialised_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); - T* vec2 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); + T* vec2 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec2 + lud.upper_bound; while (vec2 < upper_bound) { - #define exprtk_loop(N) \ - vec2[N] = Operation::process(vec0[N],vec1[N]); \ + #define exprtk_loop(N) \ + vec2[N] = Operation::process(vec0[N], vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10548,8 +11140,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec2[i] = Operation::process(vec0[i],vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec2[i] = Operation::process(vec0[i], vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10671,19 +11263,22 @@ namespace exprtk { if (vec0_node_ptr_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + binary_node<T>::branch_[0].first->value(); const T v = binary_node<T>::branch_[1].first->value(); - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec1[N] = Operation::process(vec0[N],v); \ + #define exprtk_loop(N) \ + vec1[N] = Operation::process(vec0[N], v); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10705,8 +11300,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec1[i] = Operation::process(vec0[i],v); ++i; } \ + #define case_stmt(N) \ + case N : { vec1[i] = Operation::process(vec0[i], v); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10826,19 +11421,22 @@ namespace exprtk { if (vec1_node_ptr_) { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + const T v = binary_node<T>::branch_[0].first->value(); binary_node<T>::branch_[1].first->value(); - T* vec0 = vds().data(); - T* vec1 = vec1_node_ptr_->vds().data(); + T* vec0 = vds().data(); + const T* vec1 = vec1_node_ptr_->vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; while (vec0 < upper_bound) { - #define exprtk_loop(N) \ - vec0[N] = Operation::process(v,vec1[N]); \ + #define exprtk_loop(N) \ + vec0[N] = Operation::process(v, vec1[N]); \ exprtk_loop( 0) exprtk_loop( 1) exprtk_loop( 2) exprtk_loop( 3) @@ -10860,8 +11458,8 @@ namespace exprtk exprtk_disable_fallthrough_begin switch (lud.remainder) { - #define case_stmt(N) \ - case N : { vec0[i] = Operation::process(v,vec1[i]); ++i; } \ + #define case_stmt(N) \ + case N : { vec0[i] = Operation::process(v, vec1[i]); ++i; } \ #ifndef exprtk_disable_superscalar_unroll case_stmt(15) case_stmt(14) @@ -10942,15 +11540,15 @@ namespace exprtk { bool vec0_is_ivec = false; - if (is_vector_node(unary_node<T>::branch_)) + if (is_vector_node(unary_node<T>::branch_.first)) { - vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_); + vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_.first); } - else if (is_ivector_node(unary_node<T>::branch_)) + else if (is_ivector_node(unary_node<T>::branch_.first)) { vector_interface<T>* vi = reinterpret_cast<vector_interface<T>*>(0); - if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_))) + if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_.first))) { vec0_node_ptr_ = vi->vec(); vec0_is_ivec = true; @@ -10977,12 +11575,14 @@ namespace exprtk inline T value() const { - unary_node<T>::branch_->value(); + assert(unary_node<T>::branch_.first); + + unary_node<T>::branch_.first->value(); if (vec0_node_ptr_) { - T* vec0 = vec0_node_ptr_->vds().data(); - T* vec1 = vds().data(); + const T* vec0 = vec0_node_ptr_->vds().data(); + T* vec1 = vds().data(); loop_unroll::details lud(size()); const T* upper_bound = vec0 + lud.upper_bound; @@ -11090,6 +11690,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + return ( std::not_equal_to<T>() (T(0),binary_node<T>::branch_[0].first->value()) && @@ -11114,6 +11717,9 @@ namespace exprtk inline T value() const { + assert(binary_node<T>::branch_[0].first); + assert(binary_node<T>::branch_[1].first); + return ( std::not_equal_to<T>() (T(0),binary_node<T>::branch_[0].first->value()) || @@ -11133,16 +11739,11 @@ namespace exprtk typedef std::pair<expression_ptr,bool> branch_t; typedef IFunction ifunction; - function_N_node(ifunction* func) + explicit function_N_node(ifunction* func) : function_((N == func->param_count) ? func : reinterpret_cast<ifunction*>(0)), parameter_count_(func->param_count) {} - ~function_N_node() - { - cleanup_branches::execute<T,N>(branch_); - } - template <std::size_t NumBranches> bool init_branches(expression_ptr (&b)[NumBranches]) { @@ -11409,6 +12010,16 @@ namespace exprtk return expression_node<T>::e_function; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::template compute_node_depth<N>(branch_); + } + private: ifunction* function_; @@ -11424,7 +12035,7 @@ namespace exprtk typedef expression_node<T>* expression_ptr; typedef IFunction ifunction; - function_N_node(ifunction* func) + explicit function_N_node(ifunction* func) : function_((0 == func->param_count) ? func : reinterpret_cast<ifunction*>(0)) {} @@ -11466,17 +12077,6 @@ namespace exprtk value_list_.resize(arg_list.size(),std::numeric_limits<T>::quiet_NaN()); } - ~vararg_function_node() - { - for (std::size_t i = 0; i < arg_list_.size(); ++i) - { - if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) - { - destroy_node(arg_list_[i]); - } - } - } - inline bool operator <(const vararg_function_node<T,VarArgFunction>& fn) const { return this < (&fn); @@ -11498,6 +12098,22 @@ namespace exprtk return expression_node<T>::e_vafunction; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + for (std::size_t i = 0; i < arg_list_.size(); ++i) + { + if (arg_list_[i] && !details::is_variable_node(arg_list_[i])) + { + node_delete_list.push_back(&arg_list_[i]); + } + } + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(arg_list_); + } + private: inline void populate_value_list() const @@ -11533,15 +12149,23 @@ namespace exprtk typedef std::vector<type_store_t> typestore_list_t; typedef std::vector<range_data_type_t> range_list_t; - generic_function_node(const std::vector<expression_ptr>& arg_list, - GenericFunction* func = (GenericFunction*)(0)) + explicit generic_function_node(const std::vector<expression_ptr>& arg_list, + GenericFunction* func = reinterpret_cast<GenericFunction*>(0)) : function_(func), arg_list_(arg_list) {} virtual ~generic_function_node() + {} + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const { - cleanup_branches::execute(branch_); + return expression_node<T>::ndb_t::compute_node_depth(branch_); } virtual bool init_branches() @@ -11549,7 +12173,7 @@ namespace exprtk expr_as_vec1_store_.resize(arg_list_.size(),T(0) ); typestore_list_ .resize(arg_list_.size(),type_store_t() ); range_list_ .resize(arg_list_.size(),range_data_type_t()); - branch_ .resize(arg_list_.size(),branch_t((expression_ptr)0,false)); + branch_ .resize(arg_list_.size(),branch_t(reinterpret_cast<expression_ptr>(0),false)); for (std::size_t i = 0; i < arg_list_.size(); ++i) { @@ -11591,7 +12215,7 @@ namespace exprtk if (0 == (ri = dynamic_cast<range_interface_t*>(arg_list_[i]))) return false; - range_t& rp = ri->range_ref(); + const range_t& rp = ri->range_ref(); if ( rp.const_range() && @@ -11670,11 +12294,11 @@ namespace exprtk if (rdt.range) { - range_t& rp = (*rdt.range); - std::size_t r0 = 0; - std::size_t r1 = 0; + const range_t& rp = (*rdt.range); + std::size_t r0 = 0; + std::size_t r1 = 0; - if (rp(r0,r1,rdt.size)) + if (rp(r0, r1, rdt.size)) { type_store_t& ts = typestore_list_[i]; @@ -11740,7 +12364,10 @@ namespace exprtk typedef typename StringFunction::parameter_list_t parameter_list_t; const T result = (*gen_function_t::function_) - (ret_string_, parameter_list_t(gen_function_t::typestore_list_)); + ( + ret_string_, + parameter_list_t(gen_function_t::typestore_list_) + ); range_.n1_c.second = ret_string_.size() - 1; range_.cache.second = range_.n1_c.second; @@ -11812,8 +12439,11 @@ namespace exprtk { typedef typename GenericFunction::parameter_list_t parameter_list_t; - return (*gen_function_t::function_)(param_seq_index_, - parameter_list_t(gen_function_t::typestore_list_)); + return (*gen_function_t::function_) + ( + param_seq_index_, + parameter_list_t(gen_function_t::typestore_list_) + ); } } @@ -11854,9 +12484,12 @@ namespace exprtk { typedef typename StringFunction::parameter_list_t parameter_list_t; - const T result = (*str_function_t::function_)(param_seq_index_, - str_function_t::ret_string_, - parameter_list_t(str_function_t::typestore_list_)); + const T result = (*str_function_t::function_) + ( + param_seq_index_, + str_function_t::ret_string_, + parameter_list_t(str_function_t::typestore_list_) + ); str_function_t::range_.n1_c.second = str_function_t::ret_string_.size() - 1; str_function_t::range_.cache.second = str_function_t::range_.n1_c.second; @@ -11951,30 +12584,25 @@ namespace exprtk typedef expression_node<T>* expression_ptr; typedef results_context<T> results_context_t; + typedef std::pair<expression_ptr,bool> branch_t; return_envelope_node(expression_ptr body, results_context_t& rc) : results_context_(&rc ), - return_invoked_ (false), - body_ (body ), - body_deletable_ (branch_deletable(body_)) - {} - - ~return_envelope_node() + return_invoked_ (false) { - if (body_ && body_deletable_) - { - destroy_node(body_); - } + construct_branch_pair(body_, body); } inline T value() const { + assert(body_.first); + try { return_invoked_ = false; results_context_->clear(); - return body_->value(); + return body_.first->value(); } catch(const return_exception&) { @@ -11993,12 +12621,21 @@ namespace exprtk return &return_invoked_; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(body_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(body_); + } + private: results_context_t* results_context_; - mutable bool return_invoked_; - expression_ptr body_; - const bool body_deletable_; + mutable bool return_invoked_; + branch_t body_; }; #endif @@ -12345,11 +12982,23 @@ namespace exprtk } template <typename T> - inline T value(T* t) + inline T value(std::pair<details::expression_node<T>*,bool> n) + { + return n.first->value(); + } + + template <typename T> + inline T value(const T* t) { return (*t); } + template <typename T> + inline T value(const T& t) + { + return t; + } + template <typename T> struct vararg_add_op : public opr_base<T> { @@ -12597,16 +13246,16 @@ namespace exprtk static inline T process_4(const Sequence& arg_list) { return std::min<T>( - std::min<T>(value(arg_list[0]),value(arg_list[1])), - std::min<T>(value(arg_list[2]),value(arg_list[3]))); + std::min<T>(value(arg_list[0]), value(arg_list[1])), + std::min<T>(value(arg_list[2]), value(arg_list[3]))); } template <typename Sequence> static inline T process_5(const Sequence& arg_list) { return std::min<T>( - std::min<T>(std::min<T>(value(arg_list[0]),value(arg_list[1])), - std::min<T>(value(arg_list[2]),value(arg_list[3]))), + std::min<T>(std::min<T>(value(arg_list[0]), value(arg_list[1])), + std::min<T>(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; @@ -12668,16 +13317,16 @@ namespace exprtk static inline T process_4(const Sequence& arg_list) { return std::max<T>( - std::max<T>(value(arg_list[0]),value(arg_list[1])), - std::max<T>(value(arg_list[2]),value(arg_list[3]))); + std::max<T>(value(arg_list[0]), value(arg_list[1])), + std::max<T>(value(arg_list[2]), value(arg_list[3]))); } template <typename Sequence> static inline T process_5(const Sequence& arg_list) { return std::max<T>( - std::max<T>(std::max<T>(value(arg_list[0]),value(arg_list[1])), - std::max<T>(value(arg_list[2]),value(arg_list[3]))), + std::max<T>(std::max<T>(value(arg_list[0]), value(arg_list[1])), + std::max<T>(value(arg_list[2]), value(arg_list[3]))), value(arg_list[4])); } }; @@ -13181,7 +13830,7 @@ namespace exprtk for (std::size_t i = 1; i < vec_size; ++i) { - T v_i = vec[i]; + const T v_i = vec[i]; if (v_i < result) result = v_i; @@ -13205,7 +13854,7 @@ namespace exprtk for (std::size_t i = 1; i < vec_size; ++i) { - T v_i = vec[i]; + const T v_i = vec[i]; if (v_i > result) result = v_i; @@ -13296,8 +13945,8 @@ namespace exprtk { public: - virtual ~cob_base_node() - {} + virtual ~cob_base_node() + {} inline virtual operator_type operation() const { @@ -13516,24 +14165,17 @@ namespace exprtk public: typedef expression_node<T>* expression_ptr; + typedef std::pair<expression_ptr,bool> branch_t; typedef Operation operation_t; - explicit unary_branch_node(expression_ptr brnch) - : branch_(brnch), - branch_deletable_(branch_deletable(branch_)) - {} - - ~unary_branch_node() + explicit unary_branch_node(expression_ptr branch) { - if (branch_ && branch_deletable_) - { - destroy_node(branch_); - } + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_->value()); + return Operation::process(branch_.first->value()); } inline typename expression_node<T>::node_type type() const @@ -13548,12 +14190,22 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_; + return branch_.first; } inline void release() { - branch_deletable_ = false; + branch_.second = false; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -13561,8 +14213,7 @@ namespace exprtk unary_branch_node(unary_branch_node<T,Operation>&); unary_branch_node<T,Operation>& operator=(unary_branch_node<T,Operation>&); - expression_ptr branch_; - bool branch_deletable_; + branch_t branch_; }; template <typename T> struct is_const { enum {result = 0}; }; @@ -14392,7 +15043,7 @@ namespace exprtk inline T3 t3() const { - return t2_; + return t3_; } std::string type_id() const @@ -14623,20 +15274,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit vob_node(const T& var, const expression_ptr brnch) + explicit vob_node(const T& var, const expression_ptr branch) : v_(var) { - init_branches<1>(branch_,brnch); - } - - ~vob_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(v_,branch_[0].first->value()); + assert(branch_.first); + return Operation::process(v_,branch_.first->value()); } inline operator_type operation() const @@ -14651,7 +15298,17 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14660,7 +15317,7 @@ namespace exprtk vob_node<T,Operation>& operator=(const vob_node<T,Operation>&); const T& v_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14673,20 +15330,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit bov_node(const expression_ptr brnch, const T& var) + explicit bov_node(const expression_ptr branch, const T& var) : v_(var) { - init_branches<1>(branch_,brnch); - } - - ~bov_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_[0].first->value(),v_); + assert(branch_.first); + return Operation::process(branch_.first->value(),v_); } inline operator_type operation() const @@ -14701,7 +15354,17 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14710,7 +15373,7 @@ namespace exprtk bov_node<T,Operation>& operator=(const bov_node<T,Operation>&); const T& v_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14723,20 +15386,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit cob_node(const T const_var, const expression_ptr brnch) + explicit cob_node(const T const_var, const expression_ptr branch) : c_(const_var) { - init_branches<1>(branch_,brnch); - } - - ~cob_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(c_,branch_[0].first->value()); + assert(branch_.first); + return Operation::process(c_,branch_.first->value()); } inline operator_type operation() const @@ -14756,13 +15415,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; } inline expression_node<T>* move_branch(const std::size_t&) { - branch_[0].second = false; - return branch_[0].first; + branch_.second = false; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14771,7 +15440,7 @@ namespace exprtk cob_node<T,Operation>& operator=(const cob_node<T,Operation>&); const T c_; - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename Operation> @@ -14784,20 +15453,16 @@ namespace exprtk typedef Operation operation_t; // variable op constant node - explicit boc_node(const expression_ptr brnch, const T const_var) + explicit boc_node(const expression_ptr branch, const T const_var) : c_(const_var) { - init_branches<1>(branch_,brnch); - } - - ~boc_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return Operation::process(branch_[0].first->value(),c_); + assert(branch_.first); + return Operation::process(branch_.first->value(),c_); } inline operator_type operation() const @@ -14817,13 +15482,23 @@ namespace exprtk inline expression_node<T>* branch(const std::size_t&) const { - return branch_[0].first; + return branch_.first; } inline expression_node<T>* move_branch(const std::size_t&) { - branch_[0].second = false; - return branch_[0].first; + branch_.second = false; + return branch_.first; + } + + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); } private: @@ -14832,7 +15507,7 @@ namespace exprtk boc_node<T,Operation>& operator=(const boc_node<T,Operation>&); const T c_; - branch_t branch_[1]; + branch_t branch_; }; #ifndef exprtk_disable_string_capabilities @@ -15158,8 +15833,8 @@ namespace exprtk std::size_t str1_r0 = 0; std::size_t str1_r1 = 0; - range_t& range0 = (*str0_range_ptr_); - range_t& range1 = (*str1_range_ptr_); + const range_t& range0 = (*str0_range_ptr_); + const range_t& range1 = (*str1_range_ptr_); if ( range0(str0_r0, str0_r1, str0_base_ptr_->size()) && @@ -15294,19 +15969,15 @@ namespace exprtk typedef std::pair<expression_ptr, bool> branch_t; typedef PowOp operation_t; - explicit bipow_node(expression_ptr brnch) + explicit bipow_node(expression_ptr branch) { - init_branches<1>(branch_, brnch); - } - - ~bipow_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return PowOp::result(branch_[0].first->value()); + assert(branch_.first); + return PowOp::result(branch_.first->value()); } inline typename expression_node<T>::node_type type() const @@ -15314,12 +15985,22 @@ namespace exprtk return expression_node<T>::e_ipow; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bipow_node(const bipow_node<T,PowOp>&); bipow_node<T,PowOp>& operator=(const bipow_node<T,PowOp>&); - branch_t branch_[1]; + branch_t branch_; }; template <typename T, typename PowOp> @@ -15361,19 +16042,15 @@ namespace exprtk typedef std::pair<expression_ptr, bool> branch_t; typedef PowOp operation_t; - explicit bipowninv_node(expression_ptr brnch) + explicit bipowninv_node(expression_ptr branch) { - init_branches<1>(branch_, brnch); - } - - ~bipowninv_node() - { - cleanup_branches::execute<T,1>(branch_); + construct_branch_pair(branch_, branch); } inline T value() const { - return (T(1) / PowOp::result(branch_[0].first->value())); + assert(branch_.first); + return (T(1) / PowOp::result(branch_.first->value())); } inline typename expression_node<T>::node_type type() const @@ -15381,12 +16058,22 @@ namespace exprtk return expression_node<T>::e_ipowinv; } + void collect_nodes(typename expression_node<T>::noderef_list_t& node_delete_list) + { + expression_node<T>::ndb_t::template collect(branch_, node_delete_list); + } + + std::size_t node_depth() const + { + return expression_node<T>::ndb_t::compute_node_depth(branch_); + } + private: bipowninv_node(const bipowninv_node<T,PowOp>&); bipowninv_node<T,PowOp>& operator=(const bipowninv_node<T,PowOp>&); - branch_t branch_[1]; + branch_t branch_; }; template <typename T> @@ -15535,37 +16222,55 @@ namespace exprtk template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[1]) { - return allocate<ResultNode>(operation, branch[0]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[2]) { - return allocate<ResultNode>(operation, branch[0], branch[1]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[3]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[4]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[5]) { - return allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0],branch[1], branch[2], branch[3], branch[4]); + result->node_depth(); + return result; } template <typename ResultNode, typename OpType, typename ExprNode> inline expression_node<typename ResultNode::value_type>* allocate(OpType& operation, ExprNode (&branch)[6]) { - return allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); + expression_node<typename ResultNode::value_type>* result = + allocate<ResultNode>(operation, branch[0], branch[1], branch[2], branch[3], branch[4], branch[5]); + result->node_depth(); + return result; } template <typename node_type> @@ -15580,89 +16285,128 @@ namespace exprtk template <typename, typename> class Sequence> inline expression_node<typename node_type::value_type>* allocate(const Sequence<Type,Allocator>& seq) const { - return (new node_type(seq)); + expression_node<typename node_type::value_type>* + result = (new node_type(seq)); + result->node_depth(); + return result; } template <typename node_type, typename T1> inline expression_node<typename node_type::value_type>* allocate(T1& t1) const { - return (new node_type(t1)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1)); + result->node_depth(); + return result; } template <typename node_type, typename T1> inline expression_node<typename node_type::value_type>* allocate_c(const T1& t1) const { - return (new node_type(t1)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_cr(const T1& t1, T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_rc(T1& t1, const T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_rr(T1& t1, T2& t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2> inline expression_node<typename node_type::value_type>* allocate_tt(T1 t1, T2 t2) const { - return (new node_type(t1, t2)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_ttt(T1 t1, T2 t2, T3 t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4> inline expression_node<typename node_type::value_type>* allocate_tttt(T1 t1, T2 t2, T3 t3, T4 t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_rrr(T1& t1, T2& t2, T3& t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4> inline expression_node<typename node_type::value_type>* allocate_rrrr(T1& t1, T2& t2, T3& t3, T4& t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3, typename T4, typename T5> inline expression_node<typename node_type::value_type>* allocate_rrrrr(T1& t1, T2& t2, T3& t3, T4& t4, T5& t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15670,7 +16414,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, const T3& t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, @@ -15679,7 +16426,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, @@ -15689,7 +16439,10 @@ namespace exprtk const T3& t3, const T4& t4, const T5& t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15699,7 +16452,10 @@ namespace exprtk const T3& t3, const T4& t4, const T5& t5, const T6& t6) const { - return (new node_type(t1, t2, t3, t4, t5, t6)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6)); + result->node_depth(); + return result; } template <typename node_type, @@ -15711,7 +16467,10 @@ namespace exprtk const T5& t5, const T6& t6, const T7& t7) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); + result->node_depth(); + return result; } template <typename node_type, @@ -15724,7 +16483,10 @@ namespace exprtk const T5& t5, const T6& t6, const T7& t7, const T8& t8) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8)); + result->node_depth(); + return result; } template <typename node_type, @@ -15738,7 +16500,10 @@ namespace exprtk const T7& t7, const T8& t8, const T9& t9) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9)); + result->node_depth(); + return result; } template <typename node_type, @@ -15753,14 +16518,20 @@ namespace exprtk const T7& t7, const T8& t8, const T9& t9, const T10& t10) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7, t8, t9, t10)); + result->node_depth(); + return result; } template <typename node_type, typename T1, typename T2, typename T3> inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3) const { - return (new node_type(t1, t2, t3)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3)); + result->node_depth(); + return result; } template <typename node_type, @@ -15769,7 +16540,10 @@ namespace exprtk inline expression_node<typename node_type::value_type>* allocate_type(T1 t1, T2 t2, T3 t3, T4 t4) const { - return (new node_type(t1, t2, t3, t4)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4)); + result->node_depth(); + return result; } template <typename node_type, @@ -15780,7 +16554,10 @@ namespace exprtk T3 t3, T4 t4, T5 t5) const { - return (new node_type(t1, t2, t3, t4, t5)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5)); + result->node_depth(); + return result; } template <typename node_type, @@ -15791,7 +16568,10 @@ namespace exprtk T3 t3, T4 t4, T5 t5, T6 t6) const { - return (new node_type(t1, t2, t3, t4, t5, t6)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6)); + result->node_depth(); + return result; } template <typename node_type, @@ -15803,12 +16583,19 @@ namespace exprtk T5 t5, T6 t6, T7 t7) const { - return (new node_type(t1, t2, t3, t4, t5, t6, t7)); + expression_node<typename node_type::value_type>* + result = (new node_type(t1, t2, t3, t4, t5, t6, t7)); + result->node_depth(); + return result; } template <typename T> void inline free(expression_node<T>*& e) const { + exprtk_debug(("node_allocator::free() - deleting expression_node " + "type: %03d addr: %p\n", + static_cast<int>(e->type()), + reinterpret_cast<void*>(e))); delete e; e = 0; } @@ -15971,83 +16758,84 @@ namespace exprtk virtual ~ifunction() {} - #define empty_method_body \ + #define empty_method_body(N) \ { \ + exprtk_debug(("ifunction::operator() - Operator(" #N ") has not been overridden\n")); \ return std::numeric_limits<T>::quiet_NaN(); \ } \ inline virtual T operator() () - empty_method_body + empty_method_body(0) - inline virtual T operator() (const T&) - empty_method_body + inline virtual T operator() (const T&) + empty_method_body(1) - inline virtual T operator() (const T&,const T&) - empty_method_body + inline virtual T operator() (const T&,const T&) + empty_method_body(2) - inline virtual T operator() (const T&, const T&, const T&) - empty_method_body + inline virtual T operator() (const T&, const T&, const T&) + empty_method_body(3) inline virtual T operator() (const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(4) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(5) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(6) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(7) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(8) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(9) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(10) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, - const T&) - empty_method_body + const T&) + empty_method_body(11) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(12) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(13) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(14) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(15) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(16) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(17) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(18) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(19) inline virtual T operator() (const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&, const T&) - empty_method_body + empty_method_body(20) #undef empty_method_body @@ -16064,7 +16852,7 @@ namespace exprtk inline virtual T operator() (const std::vector<T>&) { - exprtk_debug(("ivararg_function::operator() - Operator has not been overridden.\n")); + exprtk_debug(("ivararg_function::operator() - Operator has not been overridden\n")); return std::numeric_limits<T>::quiet_NaN(); } }; @@ -16095,7 +16883,7 @@ namespace exprtk #define igeneric_function_empty_body(N) \ { \ - exprtk_debug(("igeneric_function::operator() - Operator has not been overridden. ["#N"]\n")); \ + exprtk_debug(("igeneric_function::operator() - Operator(" #N ") has not been overridden\n")); \ return std::numeric_limits<T>::quiet_NaN(); \ } \ @@ -16150,7 +16938,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} + explicit freefunc00(ff00_functor ff) : exprtk::ifunction<T>(0), f(ff) {} inline T operator() () { return f(); } ff00_functor f; @@ -16160,7 +16948,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} + explicit freefunc01(ff01_functor ff) : exprtk::ifunction<T>(1), f(ff) {} inline T operator() (const T& v0) { return f(v0); } ff01_functor f; @@ -16170,7 +16958,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} + explicit freefunc02(ff02_functor ff) : exprtk::ifunction<T>(2), f(ff) {} inline T operator() (const T& v0, const T& v1) { return f(v0, v1); } ff02_functor f; @@ -16180,7 +16968,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} + explicit freefunc03(ff03_functor ff) : exprtk::ifunction<T>(3), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2) { return f(v0, v1, v2); } ff03_functor f; @@ -16190,7 +16978,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} + explicit freefunc04(ff04_functor ff) : exprtk::ifunction<T>(4), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3) { return f(v0, v1, v2, v3); } ff04_functor f; @@ -16200,7 +16988,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} + explicit freefunc05(ff05_functor ff) : exprtk::ifunction<T>(5), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4) { return f(v0, v1, v2, v3, v4); } ff05_functor f; @@ -16210,7 +16998,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} + explicit freefunc06(ff06_functor ff) : exprtk::ifunction<T>(6), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) { return f(v0, v1, v2, v3, v4, v5); } ff06_functor f; @@ -16220,7 +17008,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} + explicit freefunc07(ff07_functor ff) : exprtk::ifunction<T>(7), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6) { return f(v0, v1, v2, v3, v4, v5, v6); } @@ -16231,7 +17019,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} + explicit freefunc08(ff08_functor ff) : exprtk::ifunction<T>(8), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7) { return f(v0, v1, v2, v3, v4, v5, v6, v7); } @@ -16242,7 +17030,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} + explicit freefunc09(ff09_functor ff) : exprtk::ifunction<T>(9), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8); } @@ -16253,7 +17041,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} + explicit freefunc10(ff10_functor ff) : exprtk::ifunction<T>(10), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8, const T& v9) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9); } @@ -16264,7 +17052,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} + explicit freefunc11(ff11_functor ff) : exprtk::ifunction<T>(11), f(ff) {} inline T operator() (const T& v0, const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6, const T& v7, const T& v8, const T& v9, const T& v10) { return f(v0, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10); } @@ -16275,7 +17063,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} + explicit freefunc12(ff12_functor ff) : exprtk::ifunction<T>(12), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11) @@ -16287,7 +17075,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} + explicit freefunc13(ff13_functor ff) : exprtk::ifunction<T>(13), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12) @@ -16299,7 +17087,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} + explicit freefunc14(ff14_functor ff) : exprtk::ifunction<T>(14), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12, const T& v13) @@ -16311,7 +17099,7 @@ namespace exprtk { using exprtk::ifunction<T>::operator(); - freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} + explicit freefunc15(ff15_functor ff) : exprtk::ifunction<T>(15), f(ff) {} inline T operator() (const T& v00, const T& v01, const T& v02, const T& v03, const T& v04, const T& v05, const T& v06, const T& v07, const T& v08, const T& v09, const T& v10, const T& v11, const T& v12, const T& v13, const T& v14) @@ -16348,6 +17136,27 @@ namespace exprtk : size(0) {} + struct deleter + { + #define exprtk_define_process(Type) \ + static inline void process(std::pair<bool,Type*>& n) \ + { \ + delete n.second; \ + } \ + + exprtk_define_process(variable_node_t ) + exprtk_define_process(vector_t ) + #ifndef exprtk_disable_string_capabilities + exprtk_define_process(stringvar_node_t) + #endif + + #undef exprtk_define_process + + template <typename DeleteType> + static inline void process(std::pair<bool,DeleteType*>&) + {} + }; + inline bool symbol_exists(const std::string& symbol_name) const { if (symbol_name.empty()) @@ -16583,16 +17392,6 @@ namespace exprtk if (map.end() != itr) { - struct deleter - { - static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } - #ifndef exprtk_disable_string_capabilities - static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } - #endif - static inline void process(std::pair<bool,function_t*>&) { } - }; - if (delete_node) { deleter::process((*itr).second); @@ -16629,16 +17428,6 @@ namespace exprtk inline void clear(const bool delete_node = true) { - struct deleter - { - static inline void process(std::pair<bool,variable_node_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,vector_t*>& n) { delete n.second; } - static inline void process(std::pair<bool,function_t*>&) { } - #ifndef exprtk_disable_string_capabilities - static inline void process(std::pair<bool,stringvar_node_t*>& n) { delete n.second; } - #endif - }; - if (!map.empty()) { if (delete_node) @@ -16704,20 +17493,20 @@ namespace exprtk } }; - typedef details::expression_node<T>* expression_ptr; - typedef typename details::variable_node<T> variable_t; - typedef typename details::vector_holder<T> vector_holder_t; - typedef variable_t* variable_ptr; + typedef details::expression_node<T>* expression_ptr; + typedef typename details::variable_node<T> variable_t; + typedef typename details::vector_holder<T> vector_holder_t; + typedef variable_t* variable_ptr; #ifndef exprtk_disable_string_capabilities typedef typename details::stringvar_node<T> stringvar_t; - typedef stringvar_t* stringvar_ptr; + typedef stringvar_t* stringvar_ptr; #endif - typedef ifunction <T> function_t; - typedef ivararg_function <T> vararg_function_t; - typedef igeneric_function<T> generic_function_t; - typedef function_t* function_ptr; - typedef vararg_function_t* vararg_function_ptr; - typedef generic_function_t* generic_function_ptr; + typedef ifunction <T> function_t; + typedef ivararg_function <T> vararg_function_t; + typedef igeneric_function<T> generic_function_t; + typedef function_t* function_ptr; + typedef vararg_function_t* vararg_function_ptr; + typedef generic_function_t* generic_function_ptr; static const std::size_t lut_size = 256; @@ -16726,16 +17515,16 @@ namespace exprtk { struct st_data { - type_store<typename details::variable_node<T>,T> variable_store; + type_store<variable_t , T > variable_store; + type_store<function_t , function_t > function_store; + type_store<vararg_function_t , vararg_function_t > vararg_function_store; + type_store<generic_function_t, generic_function_t> generic_function_store; + type_store<generic_function_t, generic_function_t> string_function_store; + type_store<generic_function_t, generic_function_t> overload_function_store; + type_store<vector_holder_t , vector_holder_t > vector_store; #ifndef exprtk_disable_string_capabilities - type_store<typename details::stringvar_node<T>,std::string> stringvar_store; + type_store<stringvar_t , std::string > stringvar_store; #endif - type_store<ifunction<T>,ifunction<T> > function_store; - type_store<ivararg_function <T>,ivararg_function <T> > vararg_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > generic_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > string_function_store; - type_store<igeneric_function<T>,igeneric_function<T> > overload_function_store; - type_store<vector_holder_t,vector_holder_t> vector_store; st_data() { @@ -16785,7 +17574,7 @@ namespace exprtk data_(st_data::create()) {} - control_block(st_data* data) + explicit control_block(st_data* data) : ref_count(1), data_(data) {} @@ -17117,7 +17906,7 @@ namespace exprtk else if (symbol_exists(variable_name)) return false; else - return local_data().variable_store.add(variable_name,t,is_constant); + return local_data().variable_store.add(variable_name, t, is_constant); } inline bool add_constant(const std::string& constant_name, const T& value) @@ -17132,7 +17921,7 @@ namespace exprtk local_data().local_symbol_list_.push_back(value); T& t = local_data().local_symbol_list_.back(); - return add_variable(constant_name,t,true); + return add_variable(constant_name, t, true); } #ifndef exprtk_disable_string_capabilities @@ -17145,7 +17934,7 @@ namespace exprtk else if (symbol_exists(stringvar_name)) return false; else - return local_data().stringvar_store.add(stringvar_name,s,is_constant); + return local_data().stringvar_store.add(stringvar_name, s, is_constant); } #endif @@ -17181,30 +17970,22 @@ namespace exprtk return false; else if (symbol_exists(function_name)) return false; - else if ( - ( - (generic_function_t::e_rtrn_scalar == function.rtrn_type) || - (generic_function_t::e_rtrn_string == function.rtrn_type) - ) && - std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|") - ) - return false; - else if ( - (generic_function_t::e_rtrn_overload == function.rtrn_type) && - std::string::npos != function.parameter_sequence.find_first_not_of("STVZ*?|:") - ) - return false; - - switch (function.rtrn_type) + else { - case generic_function_t::e_rtrn_scalar : - return local_data().generic_function_store.add(function_name,function); + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().generic_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_string : - return local_data().string_function_store.add(function_name,function); + case generic_function_t::e_rtrn_string : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().string_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_overload : - return local_data().overload_function_store.add(function_name,function); + case generic_function_t::e_rtrn_overload : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? + local_data().overload_function_store.add(function_name,function) : false; + } } return false; @@ -17270,30 +18051,22 @@ namespace exprtk return false; else if (symbol_exists(function_name,false)) return false; - else if ( - ( - (generic_function_t::e_rtrn_scalar == function.rtrn_type) || - (generic_function_t::e_rtrn_string == function.rtrn_type) - ) && - std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|") - ) - return false; - else if ( - generic_function_t::e_rtrn_overload && - std::string::npos != function.parameter_sequence.find_first_not_of("STV*?|:") - ) - return false; - - switch (function.rtrn_type) + else { - case generic_function_t::e_rtrn_scalar : - return local_data().generic_function_store.add(function_name,function); + switch (function.rtrn_type) + { + case generic_function_t::e_rtrn_scalar : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().generic_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_string : - return local_data().string_function_store.add(function_name,function); + case generic_function_t::e_rtrn_string : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|")) ? + local_data().string_function_store.add(function_name,function) : false; - case generic_function_t::e_rtrn_overload : - return local_data().overload_function_store.add(function_name,function); + case generic_function_t::e_rtrn_overload : + return (std::string::npos == function.parameter_sequence.find_first_not_of("STVZ*?|:")) ? + local_data().overload_function_store.add(function_name,function) : false; + } } return false; @@ -17323,7 +18096,7 @@ namespace exprtk else if (0 == v_size) return false; else - return local_data().vector_store.add(vector_name,v,v_size); + return local_data().vector_store.add(vector_name, v, v_size); } template <typename Allocator> @@ -17686,7 +18459,7 @@ namespace exprtk ('_' != symbol[i]) ) { - if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) continue; else return false; @@ -17712,7 +18485,7 @@ namespace exprtk ('_' != symbol[i]) ) { - if (('.' == symbol[i]) && (i < (symbol.size() - 1))) + if ((i < (symbol.size() - 1)) && ('.' == symbol[i])) continue; else return false; @@ -17794,7 +18567,7 @@ namespace exprtk return_invoked(&retinv_null) {} - control_block(expression_ptr e) + explicit control_block(expression_ptr e) : ref_count(1), expr (e), results (0), @@ -17821,13 +18594,13 @@ namespace exprtk case e_vecholder : delete reinterpret_cast<vector_holder_ptr>(local_data_list[i].pointer); break; - case e_data : delete (T*)(local_data_list[i].pointer); + case e_data : delete reinterpret_cast<T*>(local_data_list[i].pointer); break; - case e_vecdata : delete [] (T*)(local_data_list[i].pointer); + case e_vecdata : delete [] reinterpret_cast<T*>(local_data_list[i].pointer); break; - case e_string : delete (std::string*)(local_data_list[i].pointer); + case e_string : delete reinterpret_cast<std::string*>(local_data_list[i].pointer); break; default : break; @@ -17887,7 +18660,7 @@ namespace exprtk control_block_->ref_count++; } - expression(const symbol_table<T>& symbol_table) + explicit expression(const symbol_table<T>& symbol_table) : control_block_(0) { set_expression(new details::null_node<T>()); @@ -17946,6 +18719,9 @@ namespace exprtk inline T value() const { + assert(control_block_ ); + assert(control_block_->expr); + return control_block_->expr->value(); } @@ -18103,7 +18879,7 @@ namespace exprtk } control_block* control_block_; - symtab_list_t symbol_table_list_; + symtab_list_t symbol_table_list_; friend class parser<T>; friend class expression_helper<T>; @@ -18162,7 +18938,8 @@ namespace exprtk e_numeric = 4, e_symtab = 5, e_lexer = 6, - e_helper = 7 + e_helper = 7, + e_parser = 8 }; struct type @@ -18220,6 +18997,7 @@ namespace exprtk case e_symtab : return std::string("Symbol Error" ); case e_lexer : return std::string("Lexer Error" ); case e_helper : return std::string("Helper Error" ); + case e_parser : return std::string("Parser Error" ); default : return std::string("Unknown Error"); } } @@ -18508,7 +19286,7 @@ namespace exprtk typedef variable_node_t* variable_node_ptr; typedef parser<T> parser_t; - scope_element_manager(parser<T>& p) + explicit scope_element_manager(parser<T>& p) : parser_(p), input_param_cnt_(0) {} @@ -18619,26 +19397,24 @@ namespace exprtk inline void free_element(scope_element& se) { - #ifdef exprtk_enable_debugging exprtk_debug(("free_element() - se[%s]\n", se.name.c_str())); - #endif switch (se.type) { - case scope_element::e_variable : if (se.data ) delete (T*) se.data; - if (se.var_node) delete se.var_node; + case scope_element::e_variable : delete reinterpret_cast<T*>(se.data); + delete se.var_node; break; - case scope_element::e_vector : if (se.data ) delete[] (T*) se.data; - if (se.vec_node) delete se.vec_node; + case scope_element::e_vector : delete[] reinterpret_cast<T*>(se.data); + delete se.vec_node; break; - case scope_element::e_vecelem : if (se.var_node) delete se.var_node; + case scope_element::e_vecelem : delete se.var_node; break; #ifndef exprtk_disable_string_capabilities - case scope_element::e_string : if (se.data ) delete (std::string*) se.data; - if (se.str_node) delete se.str_node; + case scope_element::e_string : delete reinterpret_cast<std::string*>(se.data); + delete se.str_node; break; #endif @@ -18705,7 +19481,7 @@ namespace exprtk typedef parser<T> parser_t; - scope_handler(parser<T>& p) + explicit scope_handler(parser<T>& p) : parser_(p) { parser_.state_.scope_depth++; @@ -18736,6 +19512,45 @@ namespace exprtk parser_t& parser_; }; + class stack_limit_handler + { + public: + + typedef parser<T> parser_t; + + explicit stack_limit_handler(parser<T>& p) + : parser_(p), + limit_exceeded_(false) + { + if (++parser_.state_.stack_depth > parser_.settings_.max_stack_depth_) + { + limit_exceeded_ = true; + parser_.set_error( + make_error(parser_error::e_parser, + "ERR000 - Current stack depth " + details::to_str(parser_.state_.stack_depth) + + " exceeds maximum allowed stack depth of " + details::to_str(parser_.settings_.max_stack_depth_), + exprtk_error_location)); + } + } + + ~stack_limit_handler() + { + parser_.state_.stack_depth--; + } + + bool operator!() + { + return limit_exceeded_; + } + + private: + + stack_limit_handler& operator=(const stack_limit_handler&); + + parser_t& parser_; + bool limit_exceeded_; + }; + struct symtab_store { symbol_table_list_t symtab_list_; @@ -19179,11 +19994,13 @@ namespace exprtk void reset() { - parsing_return_stmt = false; - parsing_break_stmt = false; - return_stmt_present = false; - side_effect_present = false; - scope_depth = 0; + parsing_return_stmt = false; + parsing_break_stmt = false; + return_stmt_present = false; + side_effect_present = false; + scope_depth = 0; + stack_depth = 0; + parsing_loop_stmt_count = 0; } #ifndef exprtk_enable_debugging @@ -19206,6 +20023,8 @@ namespace exprtk bool side_effect_present; bool type_check_enabled; std::size_t scope_depth; + std::size_t stack_depth; + std::size_t parsing_loop_stmt_count; }; public: @@ -19532,6 +20351,8 @@ namespace exprtk e_strength_reduction; settings_store(const std::size_t compile_options = compile_all_opts) + : max_stack_depth_(400), + max_node_depth_(10000) { load_compile_options(compile_options); } @@ -19736,6 +20557,15 @@ namespace exprtk .find(assign_opr_to_string(assignment_operation)); } + bool logic_disabled(const details::operator_type logic_operation) const + { + if (disabled_logic_set_.empty()) + return false; + else + return disabled_logic_set_.end() != disabled_logic_set_ + .find(logic_opr_to_string(logic_operation)); + } + bool arithmetic_disabled(const details::operator_type arithmetic_operation) const { if (disabled_arithmetic_set_.empty()) @@ -19940,6 +20770,16 @@ namespace exprtk return (*this); } + void set_max_stack_depth(const std::size_t mx_stack_depth) + { + max_stack_depth_ = mx_stack_depth; + } + + void set_max_node_depth(const std::size_t max_node_depth) + { + max_node_depth_ = max_node_depth; + } + private: void load_compile_options(const std::size_t compile_options) @@ -20002,6 +20842,21 @@ namespace exprtk } } + std::string logic_opr_to_string(details::operator_type opr) const + { + switch (opr) + { + case details::e_and : return "and" ; + case details::e_or : return "or" ; + case details::e_xor : return "xor" ; + case details::e_nand : return "nand"; + case details::e_nor : return "nor" ; + case details::e_xnor : return "xnor"; + case details::e_notl : return "not" ; + default : return "" ; + } + } + bool enable_replacer_; bool enable_joiner_; bool enable_numeric_check_; @@ -20023,6 +20878,9 @@ namespace exprtk disabled_entity_set_t disabled_assignment_set_; disabled_entity_set_t disabled_inequality_set_; + std::size_t max_stack_depth_; + std::size_t max_node_depth_; + friend class parser<T>; }; @@ -20042,7 +20900,8 @@ namespace exprtk #pragma warning(pop) #endif operator_joiner_2_(2), - operator_joiner_3_(3) + operator_joiner_3_(3), + loop_runtime_check_(0) { init_precompilation(); @@ -20080,8 +20939,8 @@ namespace exprtk if (settings_.replacer_enabled()) { symbol_replacer_.clear(); - symbol_replacer_.add_replace("true" ,"1",lexer::token::e_number); - symbol_replacer_.add_replace("false","0",lexer::token::e_number); + symbol_replacer_.add_replace("true" , "1", lexer::token::e_number); + symbol_replacer_.add_replace("false", "0", lexer::token::e_number); helper_assembly_.token_modifier_list.clear(); helper_assembly_.register_modifier(&symbol_replacer_); } @@ -20146,7 +21005,7 @@ namespace exprtk { set_error( make_error(parser_error::e_syntax, - "ERR000 - Empty expression!", + "ERR001 - Empty expression!", exprtk_error_location)); return false; @@ -20162,7 +21021,7 @@ namespace exprtk { set_error( make_error(parser_error::e_syntax, - "ERR001 - Empty expression!", + "ERR002 - Empty expression!", exprtk_error_location)); return false; @@ -20191,7 +21050,7 @@ namespace exprtk dec_.return_present_ = true; e = expression_generator_ - .return_envelope(e,results_context_,retinvk_ptr); + .return_envelope(e, results_context_, retinvk_ptr); } expr.set_expression(e); @@ -20209,7 +21068,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR002 - Invalid expression encountered", + "ERR003 - Invalid expression encountered", exprtk_error_location)); } @@ -20228,13 +21087,13 @@ namespace exprtk inline expression_t compile(const std::string& expression_string, symbol_table_t& symtab) { - expression_t expr; + expression_t expression; - expr.register_symbol_table(symtab); + expression.register_symbol_table(symtab); - compile(expression_string,expr); + compile(expression_string,expression); - return expr; + return expression; } void process_lexer_errors() @@ -20243,7 +21102,7 @@ namespace exprtk { if (lexer()[i].is_error()) { - std::string diagnostic = "ERR003 - "; + std::string diagnostic = "ERR004 - "; switch (lexer()[i].type) { @@ -20311,7 +21170,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, bracket_checker_ptr->error_token(), - "ERR004 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", + "ERR005 - Mismatched brackets: '" + bracket_checker_ptr->error_token().value + "'", exprtk_error_location)); } else if (0 != (numeric_checker_ptr = dynamic_cast<lexer::helper::numeric_checker*>(helper_assembly_.error_token_scanner))) @@ -20323,7 +21182,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token, - "ERR005 - Invalid numeric token: '" + error_token.value + "'", + "ERR006 - Invalid numeric token: '" + error_token.value + "'", exprtk_error_location)); } @@ -20341,7 +21200,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token.first, - "ERR006 - Invalid token sequence: '" + + "ERR007 - Invalid token sequence: '" + error_token.first.value + "' and '" + error_token.second.value + "'", exprtk_error_location)); @@ -20361,7 +21220,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, error_token.first, - "ERR007 - Invalid token sequence: '" + + "ERR008 - Invalid token sequence: '" + error_token.first.value + "' and '" + error_token.second.value + "'", exprtk_error_location)); @@ -20455,6 +21314,16 @@ namespace exprtk unknown_symbol_resolver_ = &default_usr_; } + inline void register_loop_runtime_check(loop_runtime_check& lrtchk) + { + loop_runtime_check_ = &lrtchk; + } + + inline void clear_loop_runtime_check() + { + loop_runtime_check_ = loop_runtime_check_ptr(0); + } + private: inline bool valid_base_operation(const std::string& symbol) const @@ -20498,6 +21367,11 @@ namespace exprtk settings_.function_enabled(symbol); } + bool is_invalid_logic_operation(const details::operator_type operation) const + { + return settings_.logic_disabled(operation); + } + bool is_invalid_arithmetic_operation(const details::operator_type operation) const { return settings_.arithmetic_disabled(operation); @@ -20517,13 +21391,17 @@ namespace exprtk inline void next_token() { const std::string ct_str = current_token().value; + const std::size_t ct_pos = current_token().position; parser_helper::next_token(); const std::string depth(2 * state_.scope_depth,' '); exprtk_debug(("%s" - "prev[%s] --> curr[%s]\n", + "prev[%s | %04d] --> curr[%s | %04d] stack_level: %3d\n", depth.c_str(), ct_str.c_str(), - current_token().value.c_str())); + static_cast<unsigned int>(ct_pos), + current_token().value.c_str(), + static_cast<unsigned int>(current_token().position), + static_cast<unsigned int>(state_.stack_depth))); } #endif @@ -20532,8 +21410,6 @@ namespace exprtk std::vector<expression_node_ptr> arg_list; std::vector<bool> side_effect_list; - expression_node_ptr result = error_node(); - scoped_vec_delete<expression_node_t> sdd((*this),arg_list); lexer::token begin_token; @@ -20554,7 +21430,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR008 - Invalid expression encountered", + "ERR009 - Invalid expression encountered", exprtk_error_location)); } @@ -20600,7 +21476,7 @@ namespace exprtk dec_.final_stmt_return_ = true; } - result = simplify(arg_list,side_effect_list); + const expression_node_ptr result = simplify(arg_list,side_effect_list); sdd.delete_ptr = (0 == result); @@ -20646,6 +21522,13 @@ namespace exprtk inline expression_node_ptr parse_expression(precedence_level precedence = e_level00) { + stack_limit_handler slh(*this); + + if (!slh) + { + return error_node(); + } + expression_node_ptr expression = parse_branch(precedence); if (0 == expression) @@ -20663,25 +21546,25 @@ namespace exprtk switch (current_token().type) { - case token_t::e_assign : current_state.set(e_level00,e_level00,details::e_assign); break; - case token_t::e_addass : current_state.set(e_level00,e_level00,details::e_addass); break; - case token_t::e_subass : current_state.set(e_level00,e_level00,details::e_subass); break; - case token_t::e_mulass : current_state.set(e_level00,e_level00,details::e_mulass); break; - case token_t::e_divass : current_state.set(e_level00,e_level00,details::e_divass); break; - case token_t::e_modass : current_state.set(e_level00,e_level00,details::e_modass); break; - case token_t::e_swap : current_state.set(e_level00,e_level00,details::e_swap ); break; - case token_t::e_lt : current_state.set(e_level05,e_level06,details:: e_lt); break; - case token_t::e_lte : current_state.set(e_level05,e_level06,details:: e_lte); break; - case token_t::e_eq : current_state.set(e_level05,e_level06,details:: e_eq); break; - case token_t::e_ne : current_state.set(e_level05,e_level06,details:: e_ne); break; - case token_t::e_gte : current_state.set(e_level05,e_level06,details:: e_gte); break; - case token_t::e_gt : current_state.set(e_level05,e_level06,details:: e_gt); break; - case token_t::e_add : current_state.set(e_level07,e_level08,details:: e_add); break; - case token_t::e_sub : current_state.set(e_level07,e_level08,details:: e_sub); break; - case token_t::e_div : current_state.set(e_level10,e_level11,details:: e_div); break; - case token_t::e_mul : current_state.set(e_level10,e_level11,details:: e_mul); break; - case token_t::e_mod : current_state.set(e_level10,e_level11,details:: e_mod); break; - case token_t::e_pow : current_state.set(e_level12,e_level12,details:: e_pow); break; + case token_t::e_assign : current_state.set(e_level00,e_level00, details::e_assign); break; + case token_t::e_addass : current_state.set(e_level00,e_level00, details::e_addass); break; + case token_t::e_subass : current_state.set(e_level00,e_level00, details::e_subass); break; + case token_t::e_mulass : current_state.set(e_level00,e_level00, details::e_mulass); break; + case token_t::e_divass : current_state.set(e_level00,e_level00, details::e_divass); break; + case token_t::e_modass : current_state.set(e_level00,e_level00, details::e_modass); break; + case token_t::e_swap : current_state.set(e_level00,e_level00, details::e_swap ); break; + case token_t::e_lt : current_state.set(e_level05,e_level06, details:: e_lt); break; + case token_t::e_lte : current_state.set(e_level05,e_level06, details:: e_lte); break; + case token_t::e_eq : current_state.set(e_level05,e_level06, details:: e_eq); break; + case token_t::e_ne : current_state.set(e_level05,e_level06, details:: e_ne); break; + case token_t::e_gte : current_state.set(e_level05,e_level06, details:: e_gte); break; + case token_t::e_gt : current_state.set(e_level05,e_level06, details:: e_gt); break; + case token_t::e_add : current_state.set(e_level07,e_level08, details:: e_add); break; + case token_t::e_sub : current_state.set(e_level07,e_level08, details:: e_sub); break; + case token_t::e_div : current_state.set(e_level10,e_level11, details:: e_div); break; + case token_t::e_mul : current_state.set(e_level10,e_level11, details:: e_mul); break; + case token_t::e_mod : current_state.set(e_level10,e_level11, details:: e_mod); break; + case token_t::e_pow : current_state.set(e_level12,e_level12, details:: e_pow); break; default : if (token_t::e_symbol == current_token().type) { static const std::string s_and = "and"; @@ -20784,14 +21667,26 @@ namespace exprtk expression_node_ptr right_branch = error_node(); expression_node_ptr new_expression = error_node(); - if (is_invalid_arithmetic_operation(current_state.operation)) + if (is_invalid_logic_operation(current_state.operation)) { free_node(node_allocator_,expression); set_error( make_error(parser_error::e_syntax, prev_token, - "ERR009 - Invalid arithmetic operation '" + details::to_str(current_state.operation) + "'", + "ERR010 - Invalid or disabled logic operation '" + details::to_str(current_state.operation) + "'", + exprtk_error_location)); + + return error_node(); + } + else if (is_invalid_arithmetic_operation(current_state.operation)) + { + free_node(node_allocator_,expression); + + set_error( + make_error(parser_error::e_syntax, + prev_token, + "ERR011 - Invalid or disabled arithmetic operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20803,7 +21698,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR010 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", + "ERR012 - Invalid inequality operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20815,7 +21710,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR011 - Invalid assignment operation '" + details::to_str(current_state.operation) + "'", + "ERR013 - Invalid or disabled assignment operation '" + details::to_str(current_state.operation) + "'", exprtk_error_location)); return error_node(); @@ -20834,7 +21729,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR012 - Return statements cannot be part of sub-expressions", + "ERR014 - Return statements cannot be part of sub-expressions", exprtk_error_location)); return error_node(); @@ -20857,7 +21752,7 @@ namespace exprtk prev_token, !synthesis_error_.empty() ? synthesis_error_ : - "ERR013 - General parsing error at token: '" + prev_token.value + "'", + "ERR015 - General parsing error at token: '" + prev_token.value + "'", exprtk_error_location)); } @@ -20882,6 +21777,20 @@ namespace exprtk } } + if ((0 != expression) && (expression->node_depth() > settings_.max_node_depth_)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR016 - Expression depth of " + details::to_str(static_cast<int>(expression->node_depth())) + + " exceeds maximum allowed expression depth of " + details::to_str(static_cast<int>(settings_.max_node_depth_)), + exprtk_error_location)); + + free_node(node_allocator_,expression); + + return error_node(); + } + return expression; } @@ -20927,7 +21836,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR014 - Failed to find variable node in symbol table", + "ERR017 - Failed to find variable node in symbol table", exprtk_error_location)); free_node(node_allocator_,node); @@ -20945,6 +21854,31 @@ namespace exprtk return reinterpret_cast<expression_node_ptr>(0); } + struct scoped_expression_delete + { + scoped_expression_delete(parser<T>& pr, expression_node_ptr& expression) + : delete_ptr(true), + parser_(pr), + expression_(expression) + {} + + ~scoped_expression_delete() + { + if (delete_ptr) + { + free_node(parser_.node_allocator_, expression_); + } + } + + bool delete_ptr; + parser<T>& parser_; + expression_node_ptr& expression_; + + private: + + scoped_expression_delete& operator=(const scoped_expression_delete&); + }; + template <typename Type, std::size_t N> struct scoped_delete { @@ -20968,7 +21902,7 @@ namespace exprtk { for (std::size_t i = 0; i < N; ++i) { - free_node(parser_.node_allocator_,p_[i]); + free_node(parser_.node_allocator_, p_[i]); } } } @@ -21050,7 +21984,7 @@ namespace exprtk struct scoped_bool_negator { - scoped_bool_negator(bool& bb) + explicit scoped_bool_negator(bool& bb) : b(bb) { b = !b; } @@ -21062,7 +21996,7 @@ namespace exprtk struct scoped_bool_or_restorer { - scoped_bool_or_restorer(bool& bb) + explicit scoped_bool_or_restorer(bool& bb) : b(bb), original_value_(bb) {} @@ -21076,6 +22010,21 @@ namespace exprtk bool original_value_; }; + struct scoped_inc_dec + { + explicit scoped_inc_dec(std::size_t& v) + : v_(v) + { ++v_; } + + ~scoped_inc_dec() + { + assert(v_ > 0); + --v_; + } + + std::size_t& v_; + }; + inline expression_node_ptr parse_function_invocation(ifunction<T>* function, const std::string& function_name) { expression_node_ptr func_node = reinterpret_cast<expression_node_ptr>(0); @@ -21107,7 +22056,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR015 - Invalid number of parameters for function: '" + function_name + "'", + "ERR018 - Invalid number of parameters for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21121,7 +22070,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR016 - Failed to generate call to function: '" + function_name + "'", + "ERR019 - Failed to generate call to function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21140,7 +22089,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR017 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", + "ERR020 - Expecting ifunction '" + function_name + "' to have non-zero parameter count", exprtk_error_location)); return error_node(); @@ -21163,7 +22112,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR018 - Expecting argument list for function: '" + function_name + "'", + "ERR021 - Expecting argument list for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21178,7 +22127,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR019 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", + "ERR022 - Failed to parse argument " + details::to_str(i) + " for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21190,7 +22139,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR020 - Invalid number of arguments for function: '" + function_name + "'", + "ERR023 - Invalid number of arguments for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21203,7 +22152,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR021 - Invalid number of arguments for function: '" + function_name + "'", + "ERR024 - Invalid number of arguments for function: '" + function_name + "'", exprtk_error_location)); return error_node(); @@ -21211,7 +22160,7 @@ namespace exprtk else result = expression_generator_.function(function,branch); - sd.delete_ptr = false; + sd.delete_ptr = (0 == result); return result; } @@ -21232,7 +22181,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR022 - Expecting '()' to proceed call to function: '" + function_name + "'", + "ERR025 - Expecting '()' to proceed call to function: '" + function_name + "'", exprtk_error_location)); free_node(node_allocator_,result); @@ -21257,7 +22206,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR023 - Expected a '(' at start of function call to '" + function_name + + "ERR026 - Expected a '(' at start of function call to '" + function_name + "', instead got: '" + current_token().value + "'", exprtk_error_location)); @@ -21269,7 +22218,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR024 - Expected at least one input parameter for function call '" + function_name + "'", + "ERR027 - Expected at least one input parameter for function call '" + function_name + "'", exprtk_error_location)); return 0; @@ -21295,7 +22244,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR025 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", + "ERR028 - Expected a ',' between function input parameters, instead got: '" + current_token().value + "'", exprtk_error_location)); return 0; @@ -21307,7 +22256,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR026 - Invalid number of input parameters passed to function '" + function_name + "'", + "ERR029 - Invalid number of input parameters passed to function '" + function_name + "'", exprtk_error_location)); return 0; @@ -21330,7 +22279,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, diagnostic_token, - "ERR027 - No entry found for base operation: " + operation_name, + "ERR030 - No entry found for base operation: " + operation_name, exprtk_error_location)); return error_node(); @@ -21377,7 +22326,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, diagnostic_token, - "ERR028 - Invalid number of input parameters for call to function: '" + operation_name + "'", + "ERR031 - Invalid number of input parameters for call to function: '" + operation_name + "'", exprtk_error_location)); return error_node(); @@ -21397,7 +22346,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR029 - Expected ',' between if-statement condition and consequent", + "ERR032 - Expected ',' between if-statement condition and consequent", exprtk_error_location)); result = false; } @@ -21406,7 +22355,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR030 - Failed to parse consequent for if-statement", + "ERR033 - Failed to parse consequent for if-statement", exprtk_error_location)); result = false; } @@ -21415,7 +22364,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR031 - Expected ',' between if-statement consequent and alternative", + "ERR034 - Expected ',' between if-statement consequent and alternative", exprtk_error_location)); result = false; } @@ -21424,7 +22373,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR032 - Failed to parse alternative for if-statement", + "ERR035 - Failed to parse alternative for if-statement", exprtk_error_location)); result = false; } @@ -21433,7 +22382,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR033 - Expected ')' at the end of if-statement", + "ERR036 - Expected ')' at the end of if-statement", exprtk_error_location)); result = false; } @@ -21449,13 +22398,13 @@ namespace exprtk if (consq_is_str && alter_is_str) { return expression_generator_ - .conditional_string(condition,consequent,alternative); + .conditional_string(condition, consequent, alternative); } set_error( make_error(parser_error::e_syntax, current_token(), - "ERR034 - Return types of ternary if-statement differ", + "ERR037 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21465,15 +22414,15 @@ namespace exprtk if (!result) { - free_node(node_allocator_, condition); - free_node(node_allocator_, consequent); - free_node(node_allocator_,alternative); + free_node(node_allocator_, condition ); + free_node(node_allocator_, consequent ); + free_node(node_allocator_, alternative); return error_node(); } else return expression_generator_ - .conditional(condition,consequent,alternative); + .conditional(condition, consequent, alternative); } inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition) @@ -21490,7 +22439,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR035 - Failed to parse body of consequent for if-statement", + "ERR038 - Failed to parse body of consequent for if-statement", exprtk_error_location)); result = false; @@ -21513,7 +22462,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR036 - Expected ';' at the end of the consequent for if-statement", + "ERR039 - Expected ';' at the end of the consequent for if-statement", exprtk_error_location)); result = false; @@ -21524,7 +22473,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR037 - Failed to parse body of consequent for if-statement", + "ERR040 - Failed to parse body of consequent for if-statement", exprtk_error_location)); result = false; @@ -21544,7 +22493,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR038 - Failed to parse body of the 'else' for if-statement", + "ERR041 - Failed to parse body of the 'else' for if-statement", exprtk_error_location)); result = false; @@ -21557,7 +22506,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR039 - Failed to parse body of if-else statement", + "ERR042 - Failed to parse body of if-else statement", exprtk_error_location)); result = false; @@ -21570,7 +22519,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR040 - Expected ';' at the end of the 'else-if' for the if-statement", + "ERR043 - Expected ';' at the end of the 'else-if' for the if-statement", exprtk_error_location)); result = false; @@ -21581,7 +22530,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR041 - Failed to parse body of the 'else' for if-statement", + "ERR044 - Failed to parse body of the 'else' for if-statement", exprtk_error_location)); result = false; @@ -21606,7 +22555,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR042 - Return types of ternary if-statement differ", + "ERR045 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21638,7 +22587,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR043 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", + "ERR046 - Expected '(' at start of if-statement, instead got: '" + current_token().value + "'", exprtk_error_location)); return error_node(); @@ -21648,7 +22597,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR044 - Failed to parse condition for if-statement", + "ERR047 - Failed to parse condition for if-statement", exprtk_error_location)); return error_node(); @@ -21680,7 +22629,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR045 - Invalid if-statement", + "ERR048 - Invalid if-statement", exprtk_error_location)); free_node(node_allocator_,condition); @@ -21701,7 +22650,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR046 - Encountered invalid condition branch for ternary if-statement", + "ERR049 - Encountered invalid condition branch for ternary if-statement", exprtk_error_location)); return error_node(); @@ -21711,7 +22660,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR047 - Expected '?' after condition of ternary if-statement", + "ERR050 - Expected '?' after condition of ternary if-statement", exprtk_error_location)); result = false; @@ -21721,7 +22670,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR048 - Failed to parse consequent for ternary if-statement", + "ERR051 - Failed to parse consequent for ternary if-statement", exprtk_error_location)); result = false; @@ -21731,7 +22680,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR049 - Expected ':' between ternary if-statement consequent and alternative", + "ERR052 - Expected ':' between ternary if-statement consequent and alternative", exprtk_error_location)); result = false; @@ -21741,7 +22690,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR050 - Failed to parse alternative for ternary if-statement", + "ERR053 - Failed to parse alternative for ternary if-statement", exprtk_error_location)); result = false; @@ -21764,7 +22713,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR051 - Return types of ternary if-statement differ", + "ERR054 - Return types of ternary if-statement differ", exprtk_error_location)); result = false; @@ -21785,6 +22734,22 @@ namespace exprtk .conditional(condition, consequent, alternative); } + inline expression_node_ptr parse_not_statement() + { + if (settings_.logic_disabled("not")) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR055 - Invalid or disabled logic operation 'not'", + exprtk_error_location)); + + return error_node(); + } + + return parse_base_operation(); + } + inline expression_node_ptr parse_while_loop() { // Parse: [while][(][test expr][)][{][expression][}] @@ -21801,7 +22766,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR052 - Expected '(' at start of while-loop condition statement", + "ERR056 - Expected '(' at start of while-loop condition statement", exprtk_error_location)); return error_node(); @@ -21811,7 +22776,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR053 - Failed to parse condition for while-loop", + "ERR057 - Failed to parse condition for while-loop", exprtk_error_location)); return error_node(); @@ -21821,7 +22786,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR054 - Expected ')' at end of while-loop condition statement", + "ERR058 - Expected ')' at end of while-loop condition statement", exprtk_error_location)); result = false; @@ -21831,12 +22796,14 @@ namespace exprtk if (result) { + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + if (0 == (branch = parse_multi_sequence("while-loop"))) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR055 - Failed to parse body of while-loop")); + "ERR059 - Failed to parse body of while-loop")); result = false; } else if (0 == (result_node = expression_generator_.while_loop(condition, @@ -21846,7 +22813,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR056 - Failed to synthesize while-loop", + "ERR060 - Failed to synthesize while-loop", exprtk_error_location)); result = false; @@ -21894,6 +22861,8 @@ namespace exprtk scoped_bool_or_restorer sbr(state_.side_effect_present); + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + for ( ; ; ) { state_.side_effect_present = false; @@ -21922,7 +22891,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR057 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", + "ERR061 - Expected '" + token_t::to_str(seperator) + "' in body of repeat until loop", exprtk_error_location)); return error_node(); @@ -21946,7 +22915,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR058 - Failed to parse body of repeat until loop", + "ERR062 - Failed to parse body of repeat until loop", exprtk_error_location)); return error_node(); @@ -21960,7 +22929,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR059 - Expected '(' before condition statement of repeat until loop", + "ERR063 - Expected '(' before condition statement of repeat until loop", exprtk_error_location)); free_node(node_allocator_,branch); @@ -21974,7 +22943,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR060 - Failed to parse condition for repeat until loop", + "ERR064 - Failed to parse condition for repeat until loop", exprtk_error_location)); free_node(node_allocator_,branch); @@ -21986,7 +22955,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR061 - Expected ')' after condition of repeat until loop", + "ERR065 - Expected ')' after condition of repeat until loop", exprtk_error_location)); free_node(node_allocator_, branch); @@ -22007,7 +22976,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR062 - Failed to synthesize repeat until loop", + "ERR066 - Failed to synthesize repeat until loop", exprtk_error_location)); free_node(node_allocator_,condition); @@ -22042,7 +23011,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR063 - Expected '(' at start of for-loop", + "ERR067 - Expected '(' at start of for-loop", exprtk_error_location)); return error_node(); @@ -22062,7 +23031,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR064 - Expected a variable at the start of initialiser section of for-loop", + "ERR068 - Expected a variable at the start of initialiser section of for-loop", exprtk_error_location)); return error_node(); @@ -22072,7 +23041,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR065 - Expected variable assignment of initialiser section of for-loop", + "ERR069 - Expected variable assignment of initialiser section of for-loop", exprtk_error_location)); return error_node(); @@ -22087,7 +23056,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR066 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", + "ERR070 - For-loop variable '" + loop_counter_symbol+ "' is being shadowed by a previous declaration", exprtk_error_location)); return error_node(); @@ -22112,14 +23081,14 @@ namespace exprtk nse.type = scope_element::e_variable; nse.depth = state_.scope_depth; nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR067 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", + "ERR071 - Failed to add new local variable '" + loop_counter_symbol + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -22141,7 +23110,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR068 - Failed to parse initialiser of for-loop", + "ERR072 - Failed to parse initialiser of for-loop", exprtk_error_location)); result = false; @@ -22151,7 +23120,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR069 - Expected ';' after initialiser of for-loop", + "ERR073 - Expected ';' after initialiser of for-loop", exprtk_error_location)); result = false; @@ -22165,7 +23134,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR070 - Failed to parse condition of for-loop", + "ERR074 - Failed to parse condition of for-loop", exprtk_error_location)); result = false; @@ -22175,7 +23144,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR071 - Expected ';' after condition section of for-loop", + "ERR075 - Expected ';' after condition section of for-loop", exprtk_error_location)); result = false; @@ -22189,7 +23158,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR072 - Failed to parse incrementor of for-loop", + "ERR076 - Failed to parse incrementor of for-loop", exprtk_error_location)); result = false; @@ -22199,7 +23168,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR073 - Expected ')' after incrementor section of for-loop", + "ERR077 - Expected ')' after incrementor section of for-loop", exprtk_error_location)); result = false; @@ -22210,12 +23179,14 @@ namespace exprtk { brkcnt_list_.push_front(false); + scoped_inc_dec sid(state_.parsing_loop_stmt_count); + if (0 == (loop_body = parse_multi_sequence("for-loop"))) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR074 - Failed to parse body of for-loop", + "ERR078 - Failed to parse body of for-loop", exprtk_error_location)); result = false; @@ -22265,7 +23236,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR075 - Expected keyword 'switch'", + "ERR079 - Expected keyword 'switch'", exprtk_error_location)); return error_node(); @@ -22280,85 +23251,100 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR076 - Expected '{' for call to switch statement", + "ERR080 - Expected '{' for call to switch statement", exprtk_error_location)); return error_node(); } + expression_node_ptr default_statement = error_node(); + + scoped_expression_delete defstmt_delete((*this), default_statement); + for ( ; ; ) { - if (!details::imatch("case",current_token().value)) + if (details::imatch("case",current_token().value)) { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR077 - Expected either a 'case' or 'default' statement", - exprtk_error_location)); + next_token(); - return error_node(); - } + expression_node_ptr condition = parse_expression(); - next_token(); + if (0 == condition) + return error_node(); + else if (!token_is(token_t::e_colon)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR081 - Expected ':' for case of switch statement", + exprtk_error_location)); - expression_node_ptr condition = parse_expression(); + free_node(node_allocator_, condition); - if (0 == condition) - return error_node(); - else if (!token_is(token_t::e_colon)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR078 - Expected ':' for case of switch statement", - exprtk_error_location)); + return error_node(); + } - return error_node(); - } + expression_node_ptr consequent = parse_expression(); - expression_node_ptr consequent = parse_expression(); + if (0 == consequent) + { + free_node(node_allocator_, condition); - if (0 == consequent) - return error_node(); - else if (!token_is(token_t::e_eof)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR079 - Expected ';' at end of case for switch statement", - exprtk_error_location)); + return error_node(); + } + else if (!token_is(token_t::e_eof)) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR082 - Expected ';' at end of case for switch statement", + exprtk_error_location)); - return error_node(); - } + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + + return error_node(); + } + + // Can we optimise away the case statement? + if (is_constant_node(condition) && is_false(condition)) + { + free_node(node_allocator_, condition); + free_node(node_allocator_, consequent); + } + else + { + arg_list.push_back( condition); + arg_list.push_back(consequent); + } - // Can we optimise away the case statement? - if (is_constant_node(condition) && is_false(condition)) - { - free_node(node_allocator_, condition); - free_node(node_allocator_, consequent); } - else + else if (details::imatch("default",current_token().value)) { - arg_list.push_back( condition); - arg_list.push_back(consequent); - } + if (0 != default_statement) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR083 - Multiple default cases for switch statement", + exprtk_error_location)); + + return error_node(); + } - if (details::imatch("default",current_token().value)) - { next_token(); + if (!token_is(token_t::e_colon)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR080 - Expected ':' for default of switch statement", + "ERR084 - Expected ':' for default of switch statement", exprtk_error_location)); return error_node(); } - expression_node_ptr default_statement = error_node(); - if (token_is(token_t::e_lcrlbracket,prsrhlpr_t::e_hold)) default_statement = parse_multi_sequence("switch-default"); else @@ -22368,36 +23354,40 @@ namespace exprtk return error_node(); else if (!token_is(token_t::e_eof)) { - free_node(node_allocator_,default_statement); - set_error( make_error(parser_error::e_syntax, current_token(), - "ERR081 - Expected ';' at end of default for switch statement", + "ERR085 - Expected ';' at end of default for switch statement", exprtk_error_location)); return error_node(); } - - arg_list.push_back(default_statement); + } + else if (token_is(token_t::e_rcrlbracket)) break; + else + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR086 - Expected '}' at end of switch statement", + exprtk_error_location)); + + return error_node(); } } - if (!token_is(token_t::e_rcrlbracket)) - { - set_error( - make_error(parser_error::e_syntax, - current_token(), - "ERR082 - Expected '}' at end of switch statement", - exprtk_error_location)); + const bool default_statement_present = (0 != default_statement); - return error_node(); + if (default_statement_present) + { + arg_list.push_back(default_statement); } - result = expression_generator_.switch_statement(arg_list); + result = expression_generator_.switch_statement(arg_list, (0 != default_statement)); svd.delete_ptr = (0 == result); + defstmt_delete.delete_ptr = (0 == result); return result; } @@ -22405,14 +23395,13 @@ namespace exprtk inline expression_node_ptr parse_multi_switch_statement() { std::vector<expression_node_ptr> arg_list; - expression_node_ptr result = error_node(); if (!details::imatch(current_token().value,"[*]")) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR083 - Expected token '[*]'", + "ERR087 - Expected token '[*]'", exprtk_error_location)); return error_node(); @@ -22427,7 +23416,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR084 - Expected '{' for call to [*] statement", + "ERR088 - Expected '{' for call to [*] statement", exprtk_error_location)); return error_node(); @@ -22440,7 +23429,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR085 - Expected a 'case' statement for multi-switch", + "ERR089 - Expected a 'case' statement for multi-switch", exprtk_error_location)); return error_node(); @@ -22458,7 +23447,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR086 - Expected ':' for case of [*] statement", + "ERR090 - Expected ':' for case of [*] statement", exprtk_error_location)); return error_node(); @@ -22474,7 +23463,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR087 - Expected ';' at end of case for [*] statement", + "ERR091 - Expected ';' at end of case for [*] statement", exprtk_error_location)); return error_node(); @@ -22503,13 +23492,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR088 - Expected '}' at end of [*] statement", + "ERR092 - Expected '}' at end of [*] statement", exprtk_error_location)); return error_node(); } - result = expression_generator_.multi_switch_statement(arg_list); + const expression_node_ptr result = expression_generator_.multi_switch_statement(arg_list); svd.delete_ptr = (0 == result); @@ -22519,7 +23508,6 @@ namespace exprtk inline expression_node_ptr parse_vararg_function() { std::vector<expression_node_ptr> arg_list; - expression_node_ptr result = error_node(); details::operator_type opt_type = details::e_default; const std::string symbol = current_token().value; @@ -22545,7 +23533,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR089 - Unsupported vararg function: " + symbol, + "ERR093 - Unsupported vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -22562,7 +23550,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR090 - Expected '(' for call to vararg function: " + symbol, + "ERR094 - Expected '(' for call to vararg function: " + symbol, exprtk_error_location)); return error_node(); @@ -22584,14 +23572,14 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR091 - Expected ',' for call to vararg function: " + symbol, + "ERR095 - Expected ',' for call to vararg function: " + symbol, exprtk_error_location)); return error_node(); } } - result = expression_generator_.vararg_function(opt_type,arg_list); + const expression_node_ptr result = expression_generator_.vararg_function(opt_type,arg_list); sdd.delete_ptr = (0 == result); return result; @@ -22605,7 +23593,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR092 - Expected '[' as start of string range definition", + "ERR096 - Expected '[' as start of string range definition", exprtk_error_location)); free_node(node_allocator_,expression); @@ -22633,10 +23621,11 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR093 - Failed to generate string range node", + "ERR097 - Failed to generate string range node", exprtk_error_location)); free_node(node_allocator_,expression); + rp.free(); } rp.clear(); @@ -22769,7 +23758,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR094 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + + "ERR098 - Expected '" + token_t::to_str(close_bracket) + "' for call to multi-sequence" + ((!source.empty()) ? std::string(" section of " + source): ""), exprtk_error_location)); @@ -22809,14 +23798,14 @@ namespace exprtk if (token_is(close_bracket)) break; - bool is_next_close = peek_token_is(close_bracket); + const bool is_next_close = peek_token_is(close_bracket); if (!token_is(seperator) && is_next_close) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR095 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, + "ERR099 - Expected '" + details::to_str(seperator) + "' for call to multi-sequence section of " + source, exprtk_error_location)); return error_node(); @@ -22850,7 +23839,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR096 - Expected '[' for start of range", + "ERR100 - Expected '[' for start of range", exprtk_error_location)); return false; @@ -22871,7 +23860,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR097 - Failed parse begin section of range", + "ERR101 - Failed parse begin section of range", exprtk_error_location)); return false; @@ -22894,7 +23883,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR098 - Range lower bound less than zero! Constraint: r0 >= 0", + "ERR102 - Range lower bound less than zero! Constraint: r0 >= 0", exprtk_error_location)); return false; @@ -22911,7 +23900,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR099 - Expected ':' for break in range", + "ERR103 - Expected ':' for break in range", exprtk_error_location)); rp.free(); @@ -22934,7 +23923,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR100 - Failed parse end section of range", + "ERR104 - Failed parse end section of range", exprtk_error_location)); rp.free(); @@ -22959,9 +23948,11 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR101 - Range upper bound less than zero! Constraint: r1 >= 0", + "ERR105 - Range upper bound less than zero! Constraint: r1 >= 0", exprtk_error_location)); + rp.free(); + return false; } } @@ -22976,7 +23967,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR102 - Expected ']' for start of range", + "ERR106 - Expected ']' for start of range", exprtk_error_location)); rp.free(); @@ -22990,14 +23981,21 @@ namespace exprtk std::size_t r0 = 0; std::size_t r1 = 0; - const bool rp_result = rp(r0,r1); + bool rp_result = false; + + try + { + rp_result = rp(r0, r1); + } + catch (std::runtime_error&) + {} if (!rp_result || (r0 > r1)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR103 - Invalid range, Constraint: r0 <= r1", + "ERR107 - Invalid range, Constraint: r0 <= r1", exprtk_error_location)); return false; @@ -23038,7 +24036,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR104 - Unknown string symbol", + "ERR108 - Unknown string symbol", exprtk_error_location)); return error_node(); @@ -23132,6 +24130,7 @@ namespace exprtk if (!parse_range(rp)) { free_node(node_allocator_,result); + rp.free(); return error_node(); } @@ -23152,11 +24151,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR105 - Overflow in range for string: '" + const_str + "'[" + + "ERR109 - Overflow in range for string: '" + const_str + "'[" + (rp.n0_c.first ? details::to_str(static_cast<int>(rp.n0_c.second)) : "?") + ":" + (rp.n1_c.first ? details::to_str(static_cast<int>(rp.n1_c.second)) : "?") + "]", exprtk_error_location)); + rp.free(); + return error_node(); } @@ -23196,7 +24197,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR106 - Symbol '" + symbol+ " not a vector", + "ERR110 - Symbol '" + symbol+ " not a vector", exprtk_error_location)); return error_node(); @@ -23222,7 +24223,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR107 - Failed to parse index for vector: '" + symbol + "'", + "ERR111 - Failed to parse index for vector: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -23232,7 +24233,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR108 - Expected ']' for index of vector: '" + symbol + "'", + "ERR112 - Expected ']' for index of vector: '" + symbol + "'", exprtk_error_location)); free_node(node_allocator_,index_expr); @@ -23251,7 +24252,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR109 - Index of " + details::to_str(index) + " out of range for " + "ERR113 - Index of " + details::to_str(index) + " out of range for " "vector '" + symbol + "' of size " + details::to_str(vec_size), exprtk_error_location)); @@ -23261,7 +24262,7 @@ namespace exprtk } } - return expression_generator_.vector_element(symbol,vec,index_expr); + return expression_generator_.vector_element(symbol, vec, index_expr); } inline expression_node_ptr parse_vararg_function_call(ivararg_function<T>* vararg_function, const std::string& vararg_function_name) @@ -23283,7 +24284,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR110 - Zero parameter call to vararg function: " + "ERR114 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -23308,7 +24309,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR111 - Expected ',' for call to vararg function: " + "ERR115 - Expected ',' for call to vararg function: " + vararg_function_name, exprtk_error_location)); @@ -23322,7 +24323,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR112 - Zero parameter call to vararg function: " + "ERR116 - Zero parameter call to vararg function: " + vararg_function_name + " not allowed", exprtk_error_location)); @@ -23334,7 +24335,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR113 - Invalid number of parameters to call to vararg function: " + "ERR117 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require at least " + details::to_str(static_cast<int>(vararg_function->min_num_args())) + " parameters", exprtk_error_location)); @@ -23346,7 +24347,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR114 - Invalid number of parameters to call to vararg function: " + "ERR118 - Invalid number of parameters to call to vararg function: " + vararg_function_name + ", require no more than " + details::to_str(static_cast<int>(vararg_function->max_num_args())) + " parameters", exprtk_error_location)); @@ -23393,11 +24394,6 @@ namespace exprtk parse_function_prototypes(func_prototypes); } - void set_default_return_type(const std::string& return_type) - { - default_return_type_ = return_type; - } - bool verify(const std::string& param_seq, std::size_t& pseq_index) { if (function_definition_list_.empty()) @@ -23429,7 +24425,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR115 - Failed parameter type check for function '" + function_name_ + "', " + "ERR119 - Failed parameter type check for function '" + function_name_ + "', " "Expected '" + function_definition_list_[0].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -23451,7 +24447,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR116 - Failed parameter type check for function '" + function_name_ + "', " + "ERR120 - Failed parameter type check for function '" + function_name_ + "', " "Best match: '" + function_definition_list_[max_diff_index].param_seq + "' call set: '" + param_seq + "'", exprtk_error_location)); @@ -23508,8 +24504,7 @@ namespace exprtk if (*iter == delimiter) { result.push_back(std::string(current_begin, iter)); - ++iter; - current_begin = iter; + current_begin = ++iter; } else ++iter; @@ -23594,7 +24589,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR117 - Invalid parameter sequence of '" + param_seq_list[i] + + "ERR121 - Invalid parameter sequence of '" + param_seq_list[i] + "' for function: " + function_name_, exprtk_error_location)); return; @@ -23610,7 +24605,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, parser_.current_token(), - "ERR118 - Function '" + function_name_ + "' has a parameter sequence conflict between " + + "ERR122 - Function '" + function_name_ + "' has a parameter sequence conflict between " + "pseq_idx[" + details::to_str(seq_itr->second) + "] and" + "pseq_idx[" + details::to_str(i) + "] " + "param seq: " + param_seq_list[i], @@ -23649,7 +24644,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR119 - Type checker instantiation failure for generic function: " + function_name, + "ERR123 - Type checker instantiation failure for generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23667,7 +24662,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR120 - Zero parameter call to generic function: " + "ERR124 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23699,7 +24694,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR121 - Expected ',' for call to generic function: " + function_name, + "ERR125 - Expected ',' for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23716,7 +24711,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR122 - Zero parameter call to generic function: " + "ERR126 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23733,7 +24728,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR123 - Invalid input parameter sequence for call to generic function: " + function_name, + "ERR127 - Invalid input parameter sequence for call to generic function: " + function_name, exprtk_error_location)); return error_node(); @@ -23755,7 +24750,7 @@ namespace exprtk inline bool parse_igeneric_function_params(std::string& param_type_list, std::vector<expression_node_ptr>& arg_list, - const std::string function_name, + const std::string& function_name, igeneric_function<T>* function, const type_checker& tc) { @@ -23771,7 +24766,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR124 - Zero parameter call to generic function: " + "ERR128 - Zero parameter call to generic function: " + function_name + " not allowed", exprtk_error_location)); @@ -23803,7 +24798,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR125 - Expected ',' for call to string function: " + function_name, + "ERR129 - Expected ',' for call to string function: " + function_name, exprtk_error_location)); return false; @@ -23850,7 +24845,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR126 - Invalid input parameter sequence for call to string function: " + function_name, + "ERR130 - Invalid input parameter sequence for call to string function: " + function_name, exprtk_error_location)); return error_node(); @@ -23902,7 +24897,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR127 - Invalid input parameter sequence for call to overloaded function: " + function_name, + "ERR131 - Invalid input parameter sequence for call to overloaded function: " + function_name, exprtk_error_location)); return error_node(); @@ -23933,7 +24928,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR128 - Invalid return type for call to overloaded function: " + function_name, + "ERR132 - Invalid return type for call to overloaded function: " + function_name, exprtk_error_location)); } @@ -23945,12 +24940,12 @@ namespace exprtk template <typename Type, std::size_t NumberOfParameters> struct parse_special_function_impl { - static inline expression_node_ptr process(parser<Type>& p,const details::operator_type opt_type, const std::string& sf_name) + static inline expression_node_ptr process(parser<Type>& p, const details::operator_type opt_type, const std::string& sf_name) { expression_node_ptr branch[NumberOfParameters]; - expression_node_ptr result = error_node(); + expression_node_ptr result = error_node(); - std::fill_n(branch,NumberOfParameters,reinterpret_cast<expression_node_ptr>(0)); + std::fill_n(branch, NumberOfParameters, reinterpret_cast<expression_node_ptr>(0)); scoped_delete<expression_node_t,NumberOfParameters> sd(p,branch); @@ -23961,7 +24956,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR129 - Expected '(' for special function '" + sf_name + "'", + "ERR133 - Expected '(' for special function '" + sf_name + "'", exprtk_error_location)); return error_node(); @@ -23982,7 +24977,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR130 - Expected ',' before next parameter of special function '" + sf_name + "'", + "ERR134 - Expected ',' before next parameter of special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -23995,7 +24990,7 @@ namespace exprtk p.set_error( make_error(parser_error::e_syntax, p.current_token(), - "ERR131 - Invalid number of parameters for special function '" + sf_name + "'", + "ERR135 - Invalid number of parameters for special function '" + sf_name + "'", exprtk_error_location)); return p.error_node(); @@ -24022,7 +25017,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR132 - Invalid special function[1]: " + sf_name, + "ERR136 - Invalid special function[1]: " + sf_name, exprtk_error_location)); return error_node(); @@ -24036,7 +25031,7 @@ namespace exprtk set_error( make_error(parser_error::e_token, current_token(), - "ERR133 - Invalid special function[2]: " + sf_name, + "ERR137 - Invalid special function[2]: " + sf_name, exprtk_error_location)); return error_node(); @@ -24068,7 +25063,17 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR134 - Break call within a break call is not allowed", + "ERR138 - Invoking 'break' within a break call is not allowed", + exprtk_error_location)); + + return error_node(); + } + else if (0 == state_.parsing_loop_stmt_count) + { + set_error( + make_error(parser_error::e_syntax, + current_token(), + "ERR139 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); @@ -24091,7 +25096,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR135 - Failed to parse return expression for 'break' statement", + "ERR140 - Failed to parse return expression for 'break' statement", exprtk_error_location)); return error_node(); @@ -24101,7 +25106,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR136 - Expected ']' at the completion of break's return expression", + "ERR141 - Expected ']' at the completion of break's return expression", exprtk_error_location)); free_node(node_allocator_,return_expr); @@ -24119,7 +25124,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR137 - Invalid use of 'break', allowed only in the scope of a loop", + "ERR142 - Invalid use of 'break', allowed only in the scope of a loop", exprtk_error_location)); } @@ -24128,25 +25133,25 @@ namespace exprtk inline expression_node_ptr parse_continue_statement() { - if (!brkcnt_list_.empty()) - { - next_token(); - - brkcnt_list_.front() = true; - state_.activate_side_effect("parse_continue_statement()"); - - return node_allocator_.allocate<details::continue_node<T> >(); - } - else + if (0 == state_.parsing_loop_stmt_count) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR138 - Invalid use of 'continue', allowed only in the scope of a loop", + "ERR143 - Invalid use of 'continue', allowed only in the scope of a loop", exprtk_error_location)); return error_node(); } + else + { + next_token(); + + brkcnt_list_.front() = true; + state_.activate_side_effect("parse_continue_statement()"); + + return node_allocator_.allocate<details::continue_node<T> >(); + } } #endif @@ -24159,7 +25164,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR139 - Expected '[' as part of vector size definition", + "ERR144 - Expected '[' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -24169,7 +25174,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR140 - Failed to determine size of vector '" + vec_name + "'", + "ERR145 - Failed to determine size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24181,13 +25186,13 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR141 - Expected a literal number as size of vector '" + vec_name + "'", + "ERR146 - Expected a literal number as size of vector '" + vec_name + "'", exprtk_error_location)); return error_node(); } - T vector_size = size_expr->value(); + const T vector_size = size_expr->value(); free_node(node_allocator_,size_expr); @@ -24203,7 +25208,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR142 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + + "ERR147 - Invalid vector size. Must be an integer in the range [0,2e9], size: " + details::to_str(details::numeric::to_int32(vector_size)), exprtk_error_location)); @@ -24223,7 +25228,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR143 - Expected ']' as part of vector size definition", + "ERR148 - Expected ']' as part of vector size definition", exprtk_error_location)); return error_node(); @@ -24235,7 +25240,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR144 - Expected ':=' as part of vector definition", + "ERR149 - Expected ':=' as part of vector definition", exprtk_error_location)); return error_node(); @@ -24249,7 +25254,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR145 - Failed to parse single vector initialiser", + "ERR150 - Failed to parse single vector initialiser", exprtk_error_location)); return error_node(); @@ -24262,7 +25267,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR146 - Expected ']' to close single value vector initialiser", + "ERR151 - Expected ']' to close single value vector initialiser", exprtk_error_location)); return error_node(); @@ -24278,7 +25283,7 @@ namespace exprtk if (token_t::e_symbol == current_token().type) { // Is it a locally defined vector? - scope_element& se = sem_.get_active_element(current_token().value); + const scope_element& se = sem_.get_active_element(current_token().value); if (scope_element::e_vector == se.type) { @@ -24309,7 +25314,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR147 - Expected '{' as part of vector initialiser list", + "ERR152 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -24329,7 +25334,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR148 - Expected '{' as part of vector initialiser list", + "ERR153 - Expected '{' as part of vector initialiser list", exprtk_error_location)); return error_node(); @@ -24340,14 +25345,14 @@ namespace exprtk if (token_is(token_t::e_rcrlbracket)) break; - bool is_next_close = peek_token_is(token_t::e_rcrlbracket); + const bool is_next_close = peek_token_is(token_t::e_rcrlbracket); if (!token_is(token_t::e_comma) && is_next_close) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR149 - Expected ',' between vector initialisers", + "ERR154 - Expected ',' between vector initialisers", exprtk_error_location)); return error_node(); @@ -24369,7 +25374,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR150 - Expected ';' at end of vector definition", + "ERR155 - Expected ';' at end of vector definition", exprtk_error_location)); return error_node(); @@ -24381,7 +25386,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR151 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", + "ERR156 - Initialiser list larger than the number of elements in the vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24401,7 +25406,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR152 - Illegal redefinition of local vector: '" + vec_name + "'", + "ERR157 - Illegal redefinition of local vector: '" + vec_name + "'", exprtk_error_location)); return error_node(); @@ -24428,14 +25433,14 @@ namespace exprtk nse.depth = state_.scope_depth; nse.size = vec_size; nse.data = new T[vec_size]; - nse.vec_node = new typename scope_element::vector_holder_t((T*)(nse.data),nse.size); + nse.vec_node = new typename scope_element::vector_holder_t(reinterpret_cast<T*>(nse.data),nse.size); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR153 - Failed to add new local vector '" + vec_name + "' to SEM", + "ERR158 - Failed to add new local vector '" + vec_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -24494,7 +25499,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR154 - Illegal redefinition of local variable: '" + str_name + "'", + "ERR159 - Illegal redefinition of local variable: '" + str_name + "'", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24519,14 +25524,14 @@ namespace exprtk nse.type = scope_element::e_string; nse.depth = state_.scope_depth; nse.data = new std::string; - nse.str_node = new stringvar_node_t(*(std::string*)(nse.data)); + nse.str_node = new stringvar_node_t(*reinterpret_cast<std::string*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR155 - Failed to add new local string variable '" + str_name + "' to SEM", + "ERR160 - Failed to add new local string variable '" + str_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24572,7 +25577,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR156 - Illegal variable definition", + "ERR161 - Illegal variable definition", exprtk_error_location)); return error_node(); @@ -24593,7 +25598,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR157 - Expected a symbol for variable definition", + "ERR162 - Expected a symbol for variable definition", exprtk_error_location)); return error_node(); @@ -24603,7 +25608,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR158 - Illegal redefinition of reserved keyword: '" + var_name + "'", + "ERR163 - Illegal redefinition of reserved keyword: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24613,7 +25618,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR159 - Illegal redefinition of variable '" + var_name + "'", + "ERR164 - Illegal redefinition of variable '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24623,7 +25628,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR160 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR165 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24643,7 +25648,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR161 - Failed to parse initialisation expression", + "ERR166 - Failed to parse initialisation expression", exprtk_error_location)); return error_node(); @@ -24661,7 +25666,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR162 - Expected ';' after variable definition", + "ERR167 - Expected ';' after variable definition", exprtk_error_location)); free_node(node_allocator_,initialisation_expression); @@ -24689,7 +25694,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR163 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR168 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -24714,14 +25719,14 @@ namespace exprtk nse.type = scope_element::e_variable; nse.depth = state_.scope_depth; nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR164 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR169 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); free_node(node_allocator_, initialisation_expression); @@ -24758,7 +25763,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR165 - Expected a '{}' for uninitialised var definition", + "ERR170 - Expected a '{}' for uninitialised var definition", exprtk_error_location)); return error_node(); @@ -24768,7 +25773,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR166 - Expected ';' after uninitialised variable definition", + "ERR171 - Expected ';' after uninitialised variable definition", exprtk_error_location)); return error_node(); @@ -24785,7 +25790,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR167 - Illegal redefinition of local variable: '" + var_name + "'", + "ERR172 - Illegal redefinition of local variable: '" + var_name + "'", exprtk_error_location)); return error_node(); @@ -24808,14 +25813,14 @@ namespace exprtk nse.depth = state_.scope_depth; nse.ip_index = sem_.next_ip_index(); nse.data = new T(T(0)); - nse.var_node = node_allocator_.allocate<variable_node_t>(*(T*)(nse.data)); + nse.var_node = node_allocator_.allocate<variable_node_t>(*reinterpret_cast<T*>(nse.data)); if (!sem_.add_element(nse)) { set_error( make_error(parser_error::e_syntax, current_token(), - "ERR168 - Failed to add new local variable '" + var_name + "' to SEM", + "ERR173 - Failed to add new local variable '" + var_name + "' to SEM", exprtk_error_location)); sem_.free_element(nse); @@ -24848,7 +25853,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR169 - Expected '(' at start of swap statement", + "ERR174 - Expected '(' at start of swap statement", exprtk_error_location)); return error_node(); @@ -24867,7 +25872,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR170 - Expected a symbol for variable or vector element definition", + "ERR175 - Expected a symbol for variable or vector element definition", exprtk_error_location)); return error_node(); @@ -24879,7 +25884,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR171 - First parameter to swap is an invalid vector element: '" + var0_name + "'", + "ERR176 - First parameter to swap is an invalid vector element: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -24894,7 +25899,7 @@ namespace exprtk variable0 = symtab_store_.get_variable(var0_name); } - scope_element& se = sem_.get_element(var0_name); + const scope_element& se = sem_.get_element(var0_name); if ( (se.active) && @@ -24912,7 +25917,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR172 - First parameter to swap is an invalid variable: '" + var0_name + "'", + "ERR177 - First parameter to swap is an invalid variable: '" + var0_name + "'", exprtk_error_location)); return error_node(); @@ -24926,7 +25931,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR173 - Expected ',' between parameters to swap", + "ERR178 - Expected ',' between parameters to swap", exprtk_error_location)); if (variable0_generated) @@ -24944,7 +25949,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR174 - Expected a symbol for variable or vector element definition", + "ERR179 - Expected a symbol for variable or vector element definition", exprtk_error_location)); if (variable0_generated) @@ -24961,7 +25966,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR175 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", + "ERR180 - Second parameter to swap is an invalid vector element: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -24981,7 +25986,7 @@ namespace exprtk variable1 = symtab_store_.get_variable(var1_name); } - scope_element& se = sem_.get_element(var1_name); + const scope_element& se = sem_.get_element(var1_name); if ( (se.active) && @@ -24999,7 +26004,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR176 - Second parameter to swap is an invalid variable: '" + var1_name + "'", + "ERR181 - Second parameter to swap is an invalid variable: '" + var1_name + "'", exprtk_error_location)); if (variable0_generated) @@ -25018,7 +26023,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR177 - Expected ')' at end of swap statement", + "ERR182 - Expected ')' at end of swap statement", exprtk_error_location)); if (variable0_generated) @@ -25075,7 +26080,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR178 - Return call within a return call is not allowed", + "ERR183 - Return call within a return call is not allowed", exprtk_error_location)); return error_node(); @@ -25099,7 +26104,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR179 - Expected '[' at start of return statement", + "ERR184 - Expected '[' at start of return statement", exprtk_error_location)); return error_node(); @@ -25122,7 +26127,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR180 - Expected ',' between values during call to return", + "ERR185 - Expected ',' between values during call to return", exprtk_error_location)); return error_node(); @@ -25134,7 +26139,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR181 - Zero parameter return statement not allowed", + "ERR186 - Zero parameter return statement not allowed", exprtk_error_location)); return error_node(); @@ -25149,7 +26154,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, prev_token, - "ERR182 - Invalid ']' found during return call", + "ERR187 - Invalid ']' found during return call", exprtk_error_location)); return error_node(); @@ -25202,7 +26207,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR183 - Invalid sequence of variable '"+ symbol + "' and bracket", + "ERR188 - Invalid sequence of variable '"+ symbol + "' and bracket", exprtk_error_location)); return false; @@ -25250,7 +26255,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR184 - Invalid sequence of brackets", + "ERR189 - Invalid sequence of brackets", exprtk_error_location)); return false; @@ -25347,7 +26352,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR185 - Failed to generate node for function: '" + symbol + "'", + "ERR190 - Failed to generate node for function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25373,7 +26378,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR186 - Failed to generate node for vararg function: '" + symbol + "'", + "ERR191 - Failed to generate node for vararg function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25399,7 +26404,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR187 - Failed to generate node for generic function: '" + symbol + "'", + "ERR192 - Failed to generate node for generic function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25426,7 +26431,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR188 - Failed to generate node for string function: '" + symbol + "'", + "ERR193 - Failed to generate node for string function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25452,7 +26457,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR189 - Failed to generate node for overload function: '" + symbol + "'", + "ERR194 - Failed to generate node for overload function: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25478,7 +26483,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR190 - Invalid use of reserved symbol '" + symbol + "'", + "ERR195 - Invalid use of reserved symbol '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25541,7 +26546,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR191 - Failed to create variable: '" + symbol + "'" + + "ERR196 - Failed to create variable: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); @@ -25561,7 +26566,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR192 - Failed to resolve symbol: '" + symbol + "'" + + "ERR197 - Failed to resolve symbol: '" + symbol + "'" + (error_message.empty() ? "" : " - " + error_message), exprtk_error_location)); } @@ -25573,7 +26578,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR193 - Undefined symbol: '" + symbol + "'", + "ERR198 - Undefined symbol: '" + symbol + "'", exprtk_error_location)); return error_node(); @@ -25592,11 +26597,16 @@ namespace exprtk static const std::string symbol_var = "var" ; static const std::string symbol_swap = "swap" ; static const std::string symbol_return = "return" ; + static const std::string symbol_not = "not" ; if (valid_vararg_operation(current_token().value)) { return parse_vararg_function(); } + else if (details::imatch(current_token().value, symbol_not)) + { + return parse_not_statement(); + } else if (valid_base_operation(current_token().value)) { return parse_base_operation(); @@ -25680,7 +26690,7 @@ namespace exprtk set_error( make_error(parser_error::e_symtab, current_token(), - "ERR194 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, + "ERR199 - Variable or function detected, yet symbol-table is invalid, Symbol: " + current_token().value, exprtk_error_location)); return error_node(); @@ -25689,6 +26699,13 @@ namespace exprtk inline expression_node_ptr parse_branch(precedence_level precedence = e_level00) { + stack_limit_handler slh(*this); + + if (!slh) + { + return error_node(); + } + expression_node_ptr branch = error_node(); if (token_t::e_number == current_token().type) @@ -25704,7 +26721,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR195 - Failed generate node for scalar: '" + current_token().value + "'", + "ERR200 - Failed generate node for scalar: '" + current_token().value + "'", exprtk_error_location)); return error_node(); @@ -25718,7 +26735,7 @@ namespace exprtk set_error( make_error(parser_error::e_numeric, current_token(), - "ERR196 - Failed to convert '" + current_token().value + "' to a number", + "ERR201 - Failed to convert '" + current_token().value + "' to a number", exprtk_error_location)); return error_node(); @@ -25745,7 +26762,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR197 - Expected ')' instead of: '" + current_token().value + "'", + "ERR202 - Expected ')' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25770,7 +26787,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR198 - Expected ']' instead of: '" + current_token().value + "'", + "ERR203 - Expected ']' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25795,7 +26812,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR199 - Expected '}' instead of: '" + current_token().value + "'", + "ERR204 - Expected '}' instead of: '" + current_token().value + "'", exprtk_error_location)); free_node(node_allocator_,branch); @@ -25822,7 +26839,16 @@ namespace exprtk ) ) { - branch = expression_generator_(details::e_neg,branch); + expression_node_ptr result = expression_generator_(details::e_neg,branch); + + if (0 == result) + { + free_node(node_allocator_,branch); + + return error_node(); + } + else + branch = result; } } else if (token_t::e_add == current_token().type) @@ -25835,7 +26861,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR200 - Premature end of expression[1]", + "ERR205 - Premature end of expression[1]", exprtk_error_location)); return error_node(); @@ -25845,7 +26871,7 @@ namespace exprtk set_error( make_error(parser_error::e_syntax, current_token(), - "ERR201 - Premature end of expression[2]", + "ERR206 - Premature end of expression[2]", exprtk_error_location)); return error_node(); @@ -26839,6 +27865,19 @@ namespace exprtk } #endif + inline loop_runtime_check_ptr get_loop_runtime_check(const loop_runtime_check::loop_types loop_type) const + { + if ( + parser_->loop_runtime_check_ && + (loop_type == (parser_->loop_runtime_check_->loop_set & loop_type)) + ) + { + return parser_->loop_runtime_check_; + } + + return loop_runtime_check_ptr(0); + } + inline expression_node_ptr while_loop(expression_node_ptr& condition, expression_node_ptr& branch, const bool brkcont = false) const @@ -26864,10 +27903,20 @@ namespace exprtk return branch; } else if (!brkcont) - return node_allocator_->allocate<while_loop_node_t>(condition,branch); + return node_allocator_->allocate<while_loop_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_while_loop) + ); #ifndef exprtk_disable_break_continue else - return node_allocator_->allocate<while_loop_bc_node_t>(condition,branch); + return node_allocator_->allocate<while_loop_bc_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_while_loop) + ); #else return error_node(); #endif @@ -26901,10 +27950,20 @@ namespace exprtk return branch; } else if (!brkcont) - return node_allocator_->allocate<repeat_until_loop_node_t>(condition,branch); + return node_allocator_->allocate<repeat_until_loop_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) + ); #ifndef exprtk_disable_break_continue else - return node_allocator_->allocate<repeat_until_loop_bc_node_t>(condition,branch); + return node_allocator_->allocate<repeat_until_loop_bc_node_t> + ( + condition, + branch, + get_loop_runtime_check(loop_runtime_check::e_repeat_until_loop) + ); #else return error_node(); #endif @@ -26947,7 +28006,8 @@ namespace exprtk initialiser, condition, incrementor, - loop_body + loop_body, + get_loop_runtime_check(loop_runtime_check::e_for_loop) ); #ifndef exprtk_disable_break_continue @@ -26957,7 +28017,8 @@ namespace exprtk initialiser, condition, incrementor, - loop_body + loop_body, + get_loop_runtime_check(loop_runtime_check::e_for_loop) ); #else return error_node(); @@ -27038,10 +28099,10 @@ namespace exprtk struct switch_nodes { - typedef std::vector<expression_node_ptr> arg_list_t; + typedef std::vector<std::pair<expression_node_ptr,bool> > arg_list_t; - #define case_stmt(N) \ - if (is_true(arg[(2 * N)])) { return arg[(2 * N) + 1]->value(); } \ + #define case_stmt(N) \ + if (is_true(arg[(2 * N)].first)) { return arg[(2 * N) + 1].first->value(); } \ struct switch_1 { @@ -27049,7 +28110,7 @@ namespace exprtk { case_stmt(0) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27059,7 +28120,7 @@ namespace exprtk { case_stmt(0) case_stmt(1) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27070,7 +28131,7 @@ namespace exprtk case_stmt(0) case_stmt(1) case_stmt(2) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27081,7 +28142,7 @@ namespace exprtk case_stmt(0) case_stmt(1) case_stmt(2) case_stmt(3) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27093,7 +28154,7 @@ namespace exprtk case_stmt(2) case_stmt(3) case_stmt(4) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27105,7 +28166,7 @@ namespace exprtk case_stmt(2) case_stmt(3) case_stmt(4) case_stmt(5) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27118,7 +28179,7 @@ namespace exprtk case_stmt(4) case_stmt(5) case_stmt(6) - return arg.back()->value(); + return arg.back().first->value(); } }; @@ -27127,14 +28188,13 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list) + inline expression_node_ptr switch_statement(Sequence<expression_node_ptr,Allocator>& arg_list, const bool default_statement_present) { if (arg_list.empty()) return error_node(); else if ( - !all_nodes_valid(arg_list) || - (arg_list.size() < 3) || - ((arg_list.size() % 2) != 1) + !all_nodes_valid(arg_list) || + (!default_statement_present && (arg_list.size() < 2)) ) { details::free_all_nodes(*node_allocator_,arg_list); @@ -27631,24 +28691,31 @@ namespace exprtk if (details::is_constant_node(result)) return result; else if (!all_nodes_valid(b)) + { + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); + return error_node(); + } else if (N != f->param_count) { - details::free_all_nodes(*node_allocator_,b); + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); return error_node(); } - function_N_node_t* func_node_ptr = static_cast<function_N_node_t*>(result); + function_N_node_t* func_node_ptr = reinterpret_cast<function_N_node_t*>(result); - if (func_node_ptr->init_branches(b)) - return result; - else + if (!func_node_ptr->init_branches(b)) { - details::free_all_nodes(*node_allocator_,b); + details::free_node(*node_allocator_,result); + std::fill_n(b, N, reinterpret_cast<expression_node_ptr>(0)); return error_node(); } + + return result; } } @@ -27872,7 +28939,7 @@ namespace exprtk return node_allocator_->allocate<rebasevector_celem_node_t>(i,vector_base); } - scope_element& se = parser_->sem_.get_element(symbol,i); + const scope_element& se = parser_->sem_.get_element(symbol,i); if (se.index == i) { @@ -28724,8 +29791,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_right<vtype> - (expr_gen, v, operation, branch[1], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_right<vtype> + (expr_gen, v, operation, branch[1], result); if (synthesis_result) { @@ -28798,8 +29866,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<vtype> - (expr_gen, v, operation, branch[0], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_left<vtype> + (expr_gen, v, operation, branch[0], result); if (synthesis_result) { @@ -28980,7 +30049,11 @@ namespace exprtk { expression_node_ptr result = error_node(); - if (synthesize_sf4ext_expression::template compile_right<ctype>(expr_gen,c,operation,branch[1],result)) + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_right<ctype> + (expr_gen, c, operation, branch[1], result); + + if (synthesis_result) { free_node(*expr_gen.node_allocator_,branch[1]); @@ -29095,8 +30168,9 @@ namespace exprtk { expression_node_ptr result = error_node(); - const bool synthesis_result = synthesize_sf4ext_expression::template compile_left<ctype> - (expr_gen, c, operation, branch[0], result); + const bool synthesis_result = + synthesize_sf4ext_expression::template compile_left<ctype> + (expr_gen, c, operation, branch[0], result); if (synthesis_result) { @@ -30450,7 +31524,7 @@ namespace exprtk const bool synthesis_result = synthesize_sf3ext_expression::template compile<ctype, vtype, ctype> - (expr_gen, id(expr_gen, o0, o1), c0, v, c1,result); + (expr_gen, id(expr_gen, o0, o1), c0, v, c1, result); if (synthesis_result) return result; @@ -30946,7 +32020,7 @@ namespace exprtk const bool synthesis_result = synthesize_sf4ext_expression::template compile<T0, T1, T2, T3> - (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3,result); + (expr_gen, id(expr_gen, o0, o1, o2), v0, v1, v2, v3, result); if (synthesis_result) return result; @@ -34572,8 +35646,8 @@ namespace exprtk { const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); std::string& s1 = static_cast<details::string_range_node<Type>*> (branch[1])->ref (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); - range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp1 = static_cast<details::string_range_node<Type>*> (branch[1])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); static_cast<details::string_range_node<Type>*> (branch[1])->range_ref().clear(); @@ -34586,9 +35660,9 @@ namespace exprtk inline expression_node_ptr synthesize_csrocs_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) { - std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); + const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); const std::string s1 = static_cast<details::string_literal_node<Type>*> (branch[1])->str (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); @@ -34599,10 +35673,10 @@ namespace exprtk inline expression_node_ptr synthesize_csrocsr_expression(const details::operator_type& opr, expression_node_ptr (&branch)[2]) { - std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); - std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); - range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); - range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); + const std::string s0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->str (); + const std::string s1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->str (); + const range_t rp0 = static_cast<details::const_string_range_node<Type>*>(branch[0])->range(); + const range_t rp1 = static_cast<details::const_string_range_node<Type>*>(branch[1])->range(); static_cast<details::const_string_range_node<Type>*>(branch[0])->range_ref().clear(); static_cast<details::const_string_range_node<Type>*>(branch[1])->range_ref().clear(); @@ -34847,8 +35921,8 @@ namespace exprtk typedef typename details::null_eq_node<T> nulleq_node_t; - bool b0_null = details::is_null_node(branch[0]); - bool b1_null = details::is_null_node(branch[1]); + const bool b0_null = details::is_null_node(branch[0]); + const bool b1_null = details::is_null_node(branch[1]); if (b0_null && b1_null) { @@ -34909,21 +35983,22 @@ namespace exprtk { return branch[0]; } - else if ( - (details::e_lt == operation) || (details::e_lte == operation) || - (details::e_gt == operation) || (details::e_gte == operation) || - (details::e_and == operation) || (details::e_nand == operation) || - (details::e_or == operation) || (details::e_nor == operation) || - (details::e_xor == operation) || (details::e_xnor == operation) || - (details::e_in == operation) || (details::e_like == operation) || - (details::e_ilike == operation) - ) + + details::free_node(*node_allocator_, branch[0]); + + if ( + (details::e_lt == operation) || (details::e_lte == operation) || + (details::e_gt == operation) || (details::e_gte == operation) || + (details::e_and == operation) || (details::e_nand == operation) || + (details::e_or == operation) || (details::e_nor == operation) || + (details::e_xor == operation) || (details::e_xnor == operation) || + (details::e_in == operation) || (details::e_like == operation) || + (details::e_ilike == operation) + ) { return node_allocator_->allocate_c<literal_node_t>(T(0)); } - details::free_node(*node_allocator_,branch[0]); - return node_allocator_->allocate<details::null_node<Type> >(); } @@ -34953,7 +36028,7 @@ namespace exprtk if (is_constant_foldable<N>(branch)) { - Type v = expression_point->value(); + const Type v = expression_point->value(); details::free_node(*node_allocator_,expression_point); return node_allocator_->allocate<literal_node_t>(v); @@ -35328,40 +36403,116 @@ namespace exprtk lexer::helper::sequence_validator sequence_validator_; lexer::helper::sequence_validator_3tokens sequence_validator_3tkns_; + loop_runtime_check_ptr loop_runtime_check_; + template <typename ParserType> friend void details::disable_type_checking(ParserType& p); }; + namespace details + { + template <typename T> + struct collector_helper + { + typedef exprtk::symbol_table<T> symbol_table_t; + typedef exprtk::expression<T> expression_t; + typedef exprtk::parser<T> parser_t; + typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef typename parser_t::unknown_symbol_resolver usr_t; + + struct resolve_as_vector : public parser_t::unknown_symbol_resolver + { + typedef exprtk::parser<T> parser_t; + + resolve_as_vector() + : usr_t(usr_t::e_usrmode_extended) + {} + + virtual bool process(const std::string& unknown_symbol, + symbol_table_t& symbol_table, + std::string&) + { + static T v[1]; + symbol_table.add_vector(unknown_symbol,v); + return true; + } + }; + + static inline bool collection_pass(const std::string& expression_string, + std::set<std::string>& symbol_set, + const bool collect_variables, + const bool collect_functions, + const bool vector_pass, + symbol_table_t& ext_symbol_table) + { + symbol_table_t symbol_table; + expression_t expression; + parser_t parser; + + resolve_as_vector vect_resolver; + + expression.register_symbol_table(symbol_table ); + expression.register_symbol_table(ext_symbol_table); + + if (vector_pass) + parser.enable_unknown_symbol_resolver(&vect_resolver); + else + parser.enable_unknown_symbol_resolver(); + + if (collect_variables) + parser.dec().collect_variables() = true; + + if (collect_functions) + parser.dec().collect_functions() = true; + + bool pass_result = false; + + details::disable_type_checking(parser); + + if (parser.compile(expression_string, expression)) + { + pass_result = true; + + std::deque<symbol_t> symb_list; + parser.dec().symbols(symb_list); + + for (std::size_t i = 0; i < symb_list.size(); ++i) + { + symbol_set.insert(symb_list[i].first); + } + } + + return pass_result; + } + }; + } + template <typename Allocator, template <typename, typename> class Sequence> - inline bool collect_variables(const std::string& expr_str, + inline bool collect_variables(const std::string& expression, Sequence<std::string, Allocator>& symbol_list) { typedef double T; - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef details::collector_helper<T> collect_t; - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + collect_t::symbol_table_t null_symbol_table; - expression.register_symbol_table(symbol_table); + std::set<std::string> symbol_set; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_variables() = true; + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, null_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35370,37 +36521,28 @@ namespace exprtk template <typename T, typename Allocator, template <typename, typename> class Sequence> - inline bool collect_variables(const std::string& expr_str, + inline bool collect_variables(const std::string& expression, exprtk::symbol_table<T>& extrnl_symbol_table, Sequence<std::string, Allocator>& symbol_list) { - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; - - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; - - expression.register_symbol_table(symbol_table); - expression.register_symbol_table(extrnl_symbol_table); + typedef details::collector_helper<T> collect_t; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_variables() = true; + std::set<std::string> symbol_set; - details::disable_type_checking(parser); + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, true, false, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, true, false, true, extrnl_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35408,34 +36550,30 @@ namespace exprtk template <typename Allocator, template <typename, typename> class Sequence> - inline bool collect_functions(const std::string& expr_str, + inline bool collect_functions(const std::string& expression, Sequence<std::string, Allocator>& symbol_list) { typedef double T; - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef parser_t::dependent_entity_collector::symbol_t symbol_t; + typedef details::collector_helper<T> collect_t; - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + collect_t::symbol_table_t null_symbol_table; - expression.register_symbol_table(symbol_table); + std::set<std::string> symbol_set; - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_functions() = true; + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, null_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, null_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35444,37 +36582,28 @@ namespace exprtk template <typename T, typename Allocator, template <typename, typename> class Sequence> - inline bool collect_functions(const std::string& expr_str, + inline bool collect_functions(const std::string& expression, exprtk::symbol_table<T>& extrnl_symbol_table, Sequence<std::string, Allocator>& symbol_list) { - typedef exprtk::symbol_table<T> symbol_table_t; - typedef exprtk::expression<T> expression_t; - typedef exprtk::parser<T> parser_t; - typedef typename parser_t::dependent_entity_collector::symbol_t symbol_t; - - symbol_table_t symbol_table; - expression_t expression; - parser_t parser; + typedef details::collector_helper<T> collect_t; - expression.register_symbol_table(symbol_table); - expression.register_symbol_table(extrnl_symbol_table); - - parser.enable_unknown_symbol_resolver(); - parser.dec().collect_functions() = true; + std::set<std::string> symbol_set; - details::disable_type_checking(parser); + const bool variable_pass = collect_t::collection_pass + (expression, symbol_set, false, true, false, extrnl_symbol_table); + const bool vector_pass = collect_t::collection_pass + (expression, symbol_set, false, true, true, extrnl_symbol_table); - if (!parser.compile(expr_str, expression)) + if (!variable_pass && !vector_pass) return false; - std::deque<symbol_t> symb_list; + std::set<std::string>::iterator itr = symbol_set.begin(); - parser.dec().symbols(symb_list); - - for (std::size_t i = 0; i < symb_list.size(); ++i) + while (symbol_set.end() != itr) { - symbol_list.push_back(symb_list[i].first); + symbol_list.push_back(*itr); + ++itr; } return true; @@ -35520,8 +36649,8 @@ namespace exprtk if (var) { T& x = var->ref(); - T x_original = x; - T result = integrate(e,x,r0,r1,number_of_intervals); + const T x_original = x; + const T result = integrate(e, x, r0, r1, number_of_intervals); x = x_original; return result; @@ -35611,8 +36740,8 @@ namespace exprtk if (var) { T& x = var->ref(); - T x_original = x; - T result = derivative(e,x,h); + const T x_original = x; + const T result = derivative(e, x, h); x = x_original; return result; @@ -35639,7 +36768,7 @@ namespace exprtk { T& x = var->ref(); const T x_original = x; - const T result = second_derivative(e,x,h); + const T result = second_derivative(e, x, h); x = x_original; return result; @@ -35666,7 +36795,7 @@ namespace exprtk { T& x = var->ref(); const T x_original = x; - const T result = third_derivative(e,x,h); + const T result = third_derivative(e, x, h); x = x_original; return result; @@ -35959,62 +37088,62 @@ namespace exprtk inline virtual T operator() (const T& x, const T& c1, const T& c0) { - poly_rtrn(1) poly_impl<T,1>::evaluate(x,c1,c0); + poly_rtrn(1) (poly_impl<T,1>::evaluate(x, c1, c0)); } inline virtual T operator() (const T& x, const T& c2, const T& c1, const T& c0) { - poly_rtrn(2) poly_impl<T,2>::evaluate(x,c2,c1,c0); + poly_rtrn(2) (poly_impl<T,2>::evaluate(x, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(3) poly_impl<T,3>::evaluate(x,c3,c2,c1,c0); + poly_rtrn(3) (poly_impl<T,3>::evaluate(x, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(4) poly_impl<T,4>::evaluate(x,c4,c3,c2,c1,c0); + poly_rtrn(4) (poly_impl<T,4>::evaluate(x, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(5) poly_impl<T,5>::evaluate(x,c5,c4,c3,c2,c1,c0); + poly_rtrn(5) (poly_impl<T,5>::evaluate(x, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(6) poly_impl<T,6>::evaluate(x,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(6) (poly_impl<T,6>::evaluate(x, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(7) poly_impl<T,7>::evaluate(x,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(7) (poly_impl<T,7>::evaluate(x, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(8) poly_impl<T,8>::evaluate(x,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(8) (poly_impl<T,8>::evaluate(x, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(9) poly_impl<T,9>::evaluate(x,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(9) (poly_impl<T,9>::evaluate(x, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(10) poly_impl<T,10>::evaluate(x,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(10) (poly_impl<T,10>::evaluate(x, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(11) poly_impl<T,11>::evaluate(x,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(11) (poly_impl<T,11>::evaluate(x, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } inline virtual T operator() (const T& x, const T& c12, const T& c11, const T& c10, const T& c9, const T& c8, const T& c7, const T& c6, const T& c5, const T& c4, const T& c3, const T& c2, const T& c1, const T& c0) { - poly_rtrn(12) poly_impl<T,12>::evaluate(x,c12,c11,c10,c9,c8,c7,c6,c5,c4,c3,c2,c1,c0); + poly_rtrn(12) (poly_impl<T,12>::evaluate(x, c12, c11, c10, c9, c8, c7, c6, c5, c4, c3, c2, c1, c0)); } #undef poly_rtrn @@ -36202,7 +37331,7 @@ namespace exprtk typedef typename expression_t::control_block::local_data_list_t ldl_t; - ldl_t ldl = expr.local_data_list(); + const ldl_t ldl = expr.local_data_list(); std::vector<std::size_t> index_list; @@ -36371,8 +37500,16 @@ namespace exprtk template <typename BaseFuncType> struct scoped_bft { - scoped_bft(BaseFuncType& bft) : bft_(bft) { bft_.pre (); } - ~scoped_bft() { bft_.post(); } + explicit scoped_bft(BaseFuncType& bft) + : bft_(bft) + { + bft_.pre (); + } + + ~scoped_bft() + { + bft_.post(); + } BaseFuncType& bft_; @@ -36472,7 +37609,7 @@ namespace exprtk typedef typename results_context_t::type_store_t type_t; typedef typename type_t::scalar_view scalar_t; - T result = e.value(); + const T result = e.value(); if (e.return_invoked()) { @@ -36566,6 +37703,11 @@ namespace exprtk return symbol_table_; } + inline const symbol_table_t& symbol_table() const + { + return symbol_table_; + } + inline void add_auxiliary_symtab(symbol_table_t& symtab) { auxiliary_symtab_list_.push_back(&symtab); @@ -36781,89 +37923,90 @@ namespace exprtk template <typename T> inline bool pgo_primer() { - static const std::string expression_list[] - = { - "(y + x)", - "2 * (y + x)", - "(2 * y + 2 * x)", - "(y + x / y) * (x - y / x)", - "x / ((x + y) * (x - y)) / y", - "1 - ((x * y) + (y / x)) - 3", - "sin(2 * x) + cos(pi / y)", - "1 - sin(2 * x) + cos(pi / y)", - "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", - "(x^2 / sin(2 * pi / y)) -x / 2", - "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", - "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", - "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", - "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", - "(yy + xx)", - "2 * (yy + xx)", - "(2 * yy + 2 * xx)", - "(yy + xx / yy) * (xx - yy / xx)", - "xx / ((xx + yy) * (xx - yy)) / yy", - "1 - ((xx * yy) + (yy / xx)) - 3", - "sin(2 * xx) + cos(pi / yy)", - "1 - sin(2 * xx) + cos(pi / yy)", - "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", - "(xx^2 / sin(2 * pi / yy)) -xx / 2", - "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", - "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", - "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", - "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", - "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", - "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", - "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", - "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", - "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", - "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", - "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", - "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", - "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", - "2 + (x * (y / 3))", "x + (2 * (3 / y))", - "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", - "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", - "x + ((2 * 3) / y)", "(((x + y) * z) / w)", - "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", - "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", - "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", - "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", - "((x + (2 * 3)) / y)", - "(xx + yy) * zz", "xx + (yy * zz)", - "(xx + yy) * 7", "xx + (yy * 7)", - "(xx + 7) * yy", "xx + (7 * yy)", - "(7 + xx) * yy", "7 + (xx * yy)", - "(2 + x) * 3", "2 + (x * 3)", - "(2 + 3) * x", "2 + (3 * x)", - "(x + 2) * 3", "x + (2 * 3)", - "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", - "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", - "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", - "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", - "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", - "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", - "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", - "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", - "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", - "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", - "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", - "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", - "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", - "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", - "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", - "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", - "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", - "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", - "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", - "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", - "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", - "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", - "((xx + (2 * 3)) / yy)" - }; + static const std::string expression_list[] = + { + "(y + x)", + "2 * (y + x)", + "(2 * y + 2 * x)", + "(y + x / y) * (x - y / x)", + "x / ((x + y) * (x - y)) / y", + "1 - ((x * y) + (y / x)) - 3", + "sin(2 * x) + cos(pi / y)", + "1 - sin(2 * x) + cos(pi / y)", + "sqrt(1 - sin(2 * x) + cos(pi / y) / 3)", + "(x^2 / sin(2 * pi / y)) -x / 2", + "x + (cos(y - sin(2 / x * pi)) - sin(x - cos(2 * y / pi))) - y", + "clamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "iclamp(-1.0, sin(2 * pi * x) + cos(y / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * x) + cos(pi / y) / 3), 1.11))", + "if(avg(x,y) <= x + y, x - y, x * y) + 2 * pi / x", + "1.1x^1 + 2.2y^2 - 3.3x^3 + 4.4y^4 - 5.5x^5 + 6.6y^6 - 7.7x^27 + 8.8y^55", + "(yy + xx)", + "2 * (yy + xx)", + "(2 * yy + 2 * xx)", + "(yy + xx / yy) * (xx - yy / xx)", + "xx / ((xx + yy) * (xx - yy)) / yy", + "1 - ((xx * yy) + (yy / xx)) - 3", + "sin(2 * xx) + cos(pi / yy)", + "1 - sin(2 * xx) + cos(pi / yy)", + "sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3)", + "(xx^2 / sin(2 * pi / yy)) -xx / 2", + "xx + (cos(yy - sin(2 / xx * pi)) - sin(xx - cos(2 * yy / pi))) - yy", + "clamp(-1.0, sin(2 * pi * xx) + cos(yy / 2 * pi), +1.0)", + "max(3.33, min(sqrt(1 - sin(2 * xx) + cos(pi / yy) / 3), 1.11))", + "if(avg(xx,yy) <= xx + yy, xx - yy, xx * yy) + 2 * pi / xx", + "1.1xx^1 + 2.2yy^2 - 3.3xx^3 + 4.4yy^4 - 5.5xx^5 + 6.6yy^6 - 7.7xx^27 + 8.8yy^55", + "(1.1*(2.2*(3.3*(4.4*(5.5*(6.6*(7.7*(8.8*(9.9+x)))))))))", + "(((((((((x+9.9)*8.8)*7.7)*6.6)*5.5)*4.4)*3.3)*2.2)*1.1)", + "(x + y) * z", "x + (y * z)", "(x + y) * 7", "x + (y * 7)", + "(x + 7) * y", "x + (7 * y)", "(7 + x) * y", "7 + (x * y)", + "(2 + x) * 3", "2 + (x * 3)", "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(x + y) * (z / w)", "(x + y) * (z / 7)", "(x + y) * (7 / z)", "(x + 7) * (y / z)", + "(7 + x) * (y / z)", "(2 + x) * (y / z)", "(x + 2) * (y / 3)", "(2 + x) * (y / 3)", + "(x + 2) * (3 / y)", "x + (y * (z / w))", "x + (y * (z / 7))", "x + (y * (7 / z))", + "x + (7 * (y / z))", "7 + (x * (y / z))", "2 + (x * (3 / y))", "x + (2 * (y / 4))", + "2 + (x * (y / 3))", "x + (2 * (3 / y))", + "x + ((y * z) / w)", "x + ((y * z) / 7)", "x + ((y * 7) / z)", "x + ((7 * y) / z)", + "7 + ((y * z) / w)", "2 + ((x * 3) / y)", "x + ((2 * y) / 3)", "2 + ((x * y) / 3)", + "x + ((2 * 3) / y)", "(((x + y) * z) / w)", + "(((x + y) * z) / 7)", "(((x + y) * 7) / z)", "(((x + 7) * y) / z)", "(((7 + x) * y) / z)", + "(((2 + x) * 3) / y)", "(((x + 2) * y) / 3)", "(((2 + x) * y) / 3)", "(((x + 2) * 3) / y)", + "((x + (y * z)) / w)", "((x + (y * z)) / 7)", "((x + (y * 7)) / y)", "((x + (7 * y)) / z)", + "((7 + (x * y)) / z)", "((2 + (x * 3)) / y)", "((x + (2 * y)) / 3)", "((2 + (x * y)) / 3)", + "((x + (2 * 3)) / y)", + "(xx + yy) * zz", "xx + (yy * zz)", + "(xx + yy) * 7", "xx + (yy * 7)", + "(xx + 7) * yy", "xx + (7 * yy)", + "(7 + xx) * yy", "7 + (xx * yy)", + "(2 + x) * 3", "2 + (x * 3)", + "(2 + 3) * x", "2 + (3 * x)", + "(x + 2) * 3", "x + (2 * 3)", + "(xx + yy) * (zz / ww)", "(xx + yy) * (zz / 7)", + "(xx + yy) * (7 / zz)", "(xx + 7) * (yy / zz)", + "(7 + xx) * (yy / zz)", "(2 + xx) * (yy / zz)", + "(xx + 2) * (yy / 3)", "(2 + xx) * (yy / 3)", + "(xx + 2) * (3 / yy)", "xx + (yy * (zz / ww))", + "xx + (yy * (zz / 7))", "xx + (yy * (7 / zz))", + "xx + (7 * (yy / zz))", "7 + (xx * (yy / zz))", + "2 + (xx * (3 / yy))", "xx + (2 * (yy / 4))", + "2 + (xx * (yy / 3))", "xx + (2 * (3 / yy))", + "xx + ((yy * zz) / ww)", "xx + ((yy * zz) / 7)", + "xx + ((yy * 7) / zz)", "xx + ((7 * yy) / zz)", + "7 + ((yy * zz) / ww)", "2 + ((xx * 3) / yy)", + "xx + ((2 * yy) / 3)", "2 + ((xx * yy) / 3)", + "xx + ((2 * 3) / yy)", "(((xx + yy) * zz) / ww)", + "(((xx + yy) * zz) / 7)", "(((xx + yy) * 7) / zz)", + "(((xx + 7) * yy) / zz)", "(((7 + xx) * yy) / zz)", + "(((2 + xx) * 3) / yy)", "(((xx + 2) * yy) / 3)", + "(((2 + xx) * yy) / 3)", "(((xx + 2) * 3) / yy)", + "((xx + (yy * zz)) / ww)", "((xx + (yy * zz)) / 7)", + "((xx + (yy * 7)) / yy)", "((xx + (7 * yy)) / zz)", + "((7 + (xx * yy)) / zz)", "((2 + (xx * 3)) / yy)", + "((xx + (2 * yy)) / 3)", "((2 + (xx * yy)) / 3)", + "((xx + (2 * 3)) / yy)" + }; + static const std::size_t expression_list_size = sizeof(expression_list) / sizeof(std::string); T x = T(0); @@ -37048,14 +38191,14 @@ namespace exprtk { if (stop_time_.tv_sec >= start_time_.tv_sec) { - return 1000000LLU * static_cast<unsigned long long int>(stop_time_.tv_sec - start_time_.tv_sec ) + - static_cast<unsigned long long int>(stop_time_.tv_usec - start_time_.tv_usec) ; + return 1000000LLU * static_cast<details::_uint64_t>(stop_time_.tv_sec - start_time_.tv_sec ) + + static_cast<details::_uint64_t>(stop_time_.tv_usec - start_time_.tv_usec) ; } else - return std::numeric_limits<unsigned long long int>::max(); + return std::numeric_limits<details::_uint64_t>::max(); } else - return std::numeric_limits<unsigned long long int>::max(); + return std::numeric_limits<details::_uint64_t>::max(); } inline double time() const @@ -38107,10 +39250,13 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; - std::size_t shift = n % dist; + const std::size_t dist = r1 - r0 + 1; + const std::size_t shift = n % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); return T(1); } @@ -38158,7 +39304,10 @@ namespace exprtk std::size_t dist = r1 - r0 + 1; std::size_t shift = (dist - (n % dist)) % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); return T(1); } @@ -38203,12 +39352,15 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; + const std::size_t dist = r1 - r0 + 1; if (n > dist) return T(0); - std::rotate(vec.begin() + r0, vec.begin() + r0 + n, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + n, + vec.begin() + r1 + 1); for (std::size_t i = r1 - n + 1; i <= r1; ++i) { @@ -38258,14 +39410,17 @@ namespace exprtk ) return T(0); - std::size_t dist = r1 - r0 + 1; + const std::size_t dist = r1 - r0 + 1; if (n > dist) return T(0); - std::size_t shift = (dist - (n % dist)) % dist; + const std::size_t shift = (dist - (n % dist)) % dist; - std::rotate(vec.begin() + r0, vec.begin() + r0 + shift, vec.begin() + r1 + 1); + std::rotate( + vec.begin() + r0, + vec.begin() + r0 + shift, + vec.begin() + r1 + 1); for (std::size_t i = r0; i < r0 + n; ++i) { @@ -38882,9 +40037,11 @@ namespace exprtk namespace information { static const char* library = "Mathematical Expression Toolkit"; - static const char* version = "2.71828182845904523536028747135266249775724709369995957" - "4966967627724076630353547594571382178525166427427466391"; - static const char* date = "20190818"; + static const char* version = "2.718281828459045235360287471352" + "66249775724709369995957496696762" + "77240766303535475945713821785251" + "66427427466391932003059921817413"; + static const char* date = "20210101"; static inline std::string data() { -- GitLab From c6a0c1ca8d41faac8b01d479efda0f6469da09ac Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Mon, 25 Jan 2021 13:31:50 +0100 Subject: [PATCH 42/83] [ADD] constexpr to constructors of Matrix2 and MatrixMxN --- src/core/math/Matrix2.h | 26 +++++++++++++------------- src/core/math/MatrixMxN.h | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/core/math/Matrix2.h b/src/core/math/Matrix2.h index e3d889333..f8310899c 100644 --- a/src/core/math/Matrix2.h +++ b/src/core/math/Matrix2.h @@ -87,16 +87,16 @@ private: public: //**Constructors***************************************************************************************************** - explicit inline Matrix2(); - explicit inline Matrix2( Type init ); - explicit inline Matrix2( Type xx, Type xy, Type yx, Type yy ); - explicit inline Matrix2( const Type* init ); + explicit inline constexpr Matrix2(); + explicit inline constexpr Matrix2( Type init ); + explicit inline constexpr Matrix2( Type xx, Type xy, Type yx, Type yy ); + explicit inline constexpr Matrix2( const Type* init ); - inline Matrix2( const Matrix2& m ); + inline constexpr Matrix2( const Matrix2& m ); template< typename Other > - inline Matrix2( const Matrix2<Other>& m ); + inline constexpr Matrix2( const Matrix2<Other>& m ); //******************************************************************************************************************* //**Destructor******************************************************************************************************* @@ -189,7 +189,7 @@ private: // with 0. */ template< typename Type > -inline Matrix2<Type>::Matrix2() +inline constexpr Matrix2<Type>::Matrix2() { v_[0] = v_[3] = Type(1); v_[1] = v_[2] = Type(0); @@ -204,7 +204,7 @@ inline Matrix2<Type>::Matrix2() // \param init Initial value for all matrix elements. */ template< typename Type > -inline Matrix2<Type>::Matrix2( Type init ) +inline constexpr Matrix2<Type>::Matrix2( Type init ) { v_[0] = v_[1] = v_[2] = v_[3] = init; } @@ -221,8 +221,8 @@ inline Matrix2<Type>::Matrix2( Type init ) // \param yy The initial value for the yy-component. */ template< typename Type > -inline Matrix2<Type>::Matrix2( Type xx, Type xy, - Type yx, Type yy ) +inline constexpr Matrix2<Type>::Matrix2( Type xx, Type xy, + Type yx, Type yy ) { v_[0] = xx; v_[1] = xy; v_[2] = yx; v_[3] = yy; @@ -239,7 +239,7 @@ inline Matrix2<Type>::Matrix2( Type xx, Type xy, // The array is assumed to have at least nine valid elements. */ template< typename Type > -inline Matrix2<Type>::Matrix2( const Type* init ) +inline constexpr Matrix2<Type>::Matrix2( const Type* init ) { v_[0] = init[0]; v_[1] = init[1]; @@ -258,7 +258,7 @@ inline Matrix2<Type>::Matrix2( const Type* init ) // The copy constructor is explicitly defined in order to enable/facilitate NRV optimization. */ template< typename Type > -inline Matrix2<Type>::Matrix2( const Matrix2& m ) +inline constexpr Matrix2<Type>::Matrix2( const Matrix2& m ) { v_[0] = m.v_[0]; v_[1] = m.v_[1]; @@ -276,7 +276,7 @@ inline Matrix2<Type>::Matrix2( const Matrix2& m ) */ template< typename Type > template< typename Other > -inline Matrix2<Type>::Matrix2( const Matrix2<Other>& m ) +inline constexpr Matrix2<Type>::Matrix2( const Matrix2<Other>& m ) { v_[0] = m.v_[0]; v_[1] = m.v_[1]; diff --git a/src/core/math/MatrixMxN.h b/src/core/math/MatrixMxN.h index 70854e2b6..be490da34 100644 --- a/src/core/math/MatrixMxN.h +++ b/src/core/math/MatrixMxN.h @@ -105,13 +105,13 @@ public: //**Constructors******************************************************************************** /*!\name Constructors */ //@{ - explicit inline MatrixMxN(); - explicit inline MatrixMxN( size_t m, size_t n ); - explicit inline MatrixMxN( size_t m, size_t n, Type init ); - inline MatrixMxN( const MatrixMxN& m ); + explicit inline constexpr MatrixMxN(); + explicit inline constexpr MatrixMxN( size_t m, size_t n ); + explicit inline constexpr MatrixMxN( size_t m, size_t n, Type init ); + inline constexpr MatrixMxN( const MatrixMxN& m ); template< typename Other, size_t M, size_t N > - inline MatrixMxN( const Other (&rhs)[M][N] ); + inline constexpr MatrixMxN( const Other (&rhs)[M][N] ); //@} //********************************************************************************************** @@ -199,7 +199,7 @@ private: /*!\brief The default constructor for MatrixMxN. */ template< typename Type > // Data type of the matrix -inline MatrixMxN<Type>::MatrixMxN() +inline constexpr MatrixMxN<Type>::MatrixMxN() : m_ ( 0 ) // The current number of rows of the matrix , n_ ( 0 ) // The current number of columns of the matrix , capacity_( 0 ) // The maximum capacity of the matrix @@ -218,7 +218,7 @@ inline MatrixMxN<Type>::MatrixMxN() * element initialization is performed! */ template< typename Type > // Data type of the matrix -inline MatrixMxN<Type>::MatrixMxN( size_t m, size_t n ) +inline constexpr MatrixMxN<Type>::MatrixMxN( size_t m, size_t n ) : m_ ( m ) // The current number of rows of the matrix , n_ ( n ) // The current number of columns of the matrix , capacity_( m*n ) // The maximum capacity of the matrix @@ -237,7 +237,7 @@ inline MatrixMxN<Type>::MatrixMxN( size_t m, size_t n ) * All matrix elements are initialized with the specified value. */ template< typename Type > // Data type of the matrix -inline MatrixMxN<Type>::MatrixMxN( size_t m, size_t n, Type init ) +inline constexpr MatrixMxN<Type>::MatrixMxN( size_t m, size_t n, Type init ) : m_ ( m ) // The current number of rows of the matrix , n_ ( n ) // The current number of columns of the matrix , capacity_( m*n ) // The maximum capacity of the matrix @@ -258,7 +258,7 @@ inline MatrixMxN<Type>::MatrixMxN( size_t m, size_t n, Type init ) * and in order to enable/facilitate NRV optimization. */ template< typename Type > // Data type of the matrix -inline MatrixMxN<Type>::MatrixMxN( const MatrixMxN& m ) +inline constexpr MatrixMxN<Type>::MatrixMxN( const MatrixMxN& m ) : m_ ( m.m_ ) // The current number of rows of the matrix , n_ ( m.n_ ) // The current number of columns of the matrix , capacity_( m_*n_ ) // The maximum capacity of the matrix @@ -292,7 +292,7 @@ template< typename Type > // Data type of the matrix template< typename Other // Data type of the initialization array , size_t M // Number of rows of the initialization array , size_t N > // Number of columns of the initialization array -inline MatrixMxN<Type>::MatrixMxN( const Other (&rhs)[M][N] ) +inline constexpr MatrixMxN<Type>::MatrixMxN( const Other (&rhs)[M][N] ) : m_ ( M ) // The current number of rows of the matrix , n_ ( N ) // The current number of columns of the matrix , capacity_( M*N ) // The maximum capacity of the matrix -- GitLab From bcc28acb80c19d09980843ee4d98ecdcc8523687 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Mon, 25 Jan 2021 22:27:40 +0100 Subject: [PATCH 43/83] Display ctest results in Gitlab --- .gitlab-ci.yml | 215 ++++++++++++++++++------------------------- cmake/ctest2junit.py | 157 +++++++++++++++++++++++++++++++ 2 files changed, 249 insertions(+), 123 deletions(-) create mode 100755 cmake/ctest2junit.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2248c4cdd..e671445c2 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -52,7 +52,9 @@ stages: -DWALBERLA_STL_BOUNDS_CHECKS=$WALBERLA_STL_BOUNDS_CHECKS - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - - ctest -LE $CTEST_EXCLUDE_LABELS -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES + - ctest -LE $CTEST_EXCLUDE_LABELS -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES -T Test + after_script: + - python3 cmake/ctest2junit.py build > report.xml tags: - docker variables: @@ -67,6 +69,12 @@ stages: WALBERLA_BUILD_WITH_METIS: "ON" WALBERLA_BUILD_WITH_PARMETIS: "ON" WALBERLA_ENABLE_GUI: "OFF" + artifacts: + when: always + reports: + junit: + - report.xml + - python/report.xml ############################################################################### @@ -83,8 +91,7 @@ intel_19_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -109,8 +116,7 @@ intel_19_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -133,8 +139,7 @@ intel_19_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -152,8 +157,7 @@ intel_19_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -175,8 +179,7 @@ intel_19_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -196,8 +199,7 @@ intel_19_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -230,8 +232,7 @@ gcc_7_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -255,8 +256,7 @@ gcc_7_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -278,8 +278,7 @@ gcc_7_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -300,8 +299,7 @@ gcc_7_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -327,8 +325,7 @@ gcc_7_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -351,8 +348,7 @@ gcc_7_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -387,8 +383,7 @@ gcc_8_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -412,8 +407,7 @@ gcc_8_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -435,8 +429,7 @@ gcc_8_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -457,8 +450,7 @@ gcc_8_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -483,8 +475,7 @@ gcc_8_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -507,8 +498,7 @@ gcc_8_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -547,8 +537,7 @@ gcc_9_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -570,8 +559,7 @@ gcc_9_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -591,8 +579,7 @@ gcc_9_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -611,8 +598,7 @@ gcc_9_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -635,8 +621,7 @@ gcc_9_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -657,8 +642,7 @@ gcc_9_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -694,8 +678,7 @@ gcc_10_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -717,8 +700,7 @@ gcc_10_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -739,8 +721,7 @@ gcc_10_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -755,8 +736,7 @@ gcc_10_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -775,8 +755,7 @@ gcc_10_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -793,8 +772,7 @@ gcc_10_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. variables: WALBERLA_BUILD_WITH_CUDA: "OFF" @@ -822,8 +800,7 @@ clang_6.0_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -847,8 +824,7 @@ clang_6.0_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -870,8 +846,7 @@ clang_6.0_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -892,8 +867,7 @@ clang_6.0_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -918,8 +892,7 @@ clang_6.0_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -942,8 +915,7 @@ clang_6.0_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -978,8 +950,7 @@ clang_7.0_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1003,8 +974,7 @@ clang_7.0_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1026,8 +996,7 @@ clang_7.0_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1048,8 +1017,7 @@ clang_7.0_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1074,8 +1042,7 @@ clang_7.0_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1098,8 +1065,7 @@ clang_7.0_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1138,8 +1104,7 @@ clang_8.0_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1163,8 +1128,7 @@ clang_8.0_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1186,8 +1150,7 @@ clang_8.0_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1208,8 +1171,7 @@ clang_8.0_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1234,8 +1196,7 @@ clang_8.0_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1258,8 +1219,7 @@ clang_8.0_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1298,8 +1258,7 @@ clang_9.0_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1323,8 +1282,7 @@ clang_9.0_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1346,8 +1304,7 @@ clang_9.0_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1368,8 +1325,7 @@ clang_9.0_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1394,8 +1350,7 @@ clang_9.0_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1418,8 +1373,7 @@ clang_9.0_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1458,8 +1412,7 @@ clang_10.0_serial: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1483,8 +1436,7 @@ clang_10.0_mpionly: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1506,8 +1458,7 @@ clang_10.0_hybrid: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1524,8 +1475,7 @@ clang_10.0_serial_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1546,8 +1496,7 @@ clang_10.0_mpionly_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1566,8 +1515,7 @@ clang_10.0_hybrid_dbg: before_script: - pip3 install lbmpy jinja2 - cd python - - python3 -m unittest discover pystencils_walberla/ - - python3 -m unittest discover lbmpy_walberla/ + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla - cd .. - CC=gcc CXX=g++ pip3 install pycuda variables: @@ -1757,7 +1705,9 @@ coverage: - cd build - cmake -LA -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_DOUBLE_ACCURACY=$WALBERLA_DOUBLE_ACCURACY -DWARNING_ERROR=ON -G "$CMAKE_GENERATOR" -DCMAKE_DISABLE_FIND_PACKAGE_Boost=TRUE .. - MSBuild.exe walberla.sln /property:Configuration=$BUILD_CONFIGURATION /verbosity:minimal /maxcpucount:4 - - ctest -LE $CTEST_EXCLUDE_LABELS -C $BUILD_CONFIGURATION --output-on-failure -j 4 + - ctest -LE $CTEST_EXCLUDE_LABELS -C $BUILD_CONFIGURATION --output-on-failure -j 4 -T Test + after_script: + - python3 cmake/ctest2junit.py build > report.xml variables: CMAKE_GENERATOR: "Visual Studio 15 2017 Win64" BUILD_CONFIGURATION: "Release" @@ -1765,6 +1715,12 @@ coverage: WALBERLA_BUILD_WITH_MPI: "ON" WALBERLA_BUILD_WITH_OPENMP: "ON" WALBERLA_DOUBLE_ACCURACY: "ON" + artifacts: + when: always + reports: + junit: + - report.xml + - python/report.xml @@ -1937,9 +1893,22 @@ msvc-14.2_mpionly: - cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DWARNING_ERROR=ON - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - - ctest -LE "$CTEST_EXCLUDE_LABELS|cuda" -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES + - ctest -LE "$CTEST_EXCLUDE_LABELS|cuda" -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES -T Test + before_script: + - pip3 install --user lbmpy jinja2 pytest-cov lxml + - cd python + - python3 -m pytest --junitxml=report.xml pystencils_walberla lbmpy_walberla + - cd .. + after_script: + - python3 cmake/ctest2junit.py build > report.xml tags: - mac + artifacts: + when: always + reports: + junit: + - report.xml + - python/report.xml mac_Serial_Dbg: <<: *mac_build_definition diff --git a/cmake/ctest2junit.py b/cmake/ctest2junit.py new file mode 100755 index 000000000..9474cd260 --- /dev/null +++ b/cmake/ctest2junit.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python3 +# This file is from https://github.com/scikit-build/scikit-ci-addons/tree/master/anyci +# under Apache 2.0 license. + +import os +import sys + +from lxml import etree + + +def process(build_dir): + + tag_file = build_dir + "/Testing/TAG" + if not os.path.exists(tag_file): + raise RuntimeError("Missing tag file %s" % tag_file) + + with open(build_dir + "/Testing/TAG", 'r') as tag: + dir_name = tag.readline().strip() + + test_xml = build_dir + "/Testing/" + dir_name + "/Test.xml" + if not os.path.exists(test_xml): + raise RuntimeError("Couldn't find %s" % test_xml) + + xsl = """<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> +<xsl:output method="xml" indent="yes"/> + + <xsl:template match="/Site"> + <testsuite> + <xsl:variable name="BuildName"><xsl:value-of select="@BuildName"/></xsl:variable> + <xsl:variable name="BuildStamp"><xsl:value-of select="@BuildStamp"/></xsl:variable> + <xsl:variable name="Name"><xsl:value-of select="@Name"/></xsl:variable> + <xsl:variable name="Generator"><xsl:value-of select="@Generator"/></xsl:variable> + <xsl:variable name="CompilerName"><xsl:value-of select="@CompilerName"/></xsl:variable> + <xsl:variable name="OSName"><xsl:value-of select="@OSName"/></xsl:variable> + <xsl:variable name="Hostname"><xsl:value-of select="@Hostname"/></xsl:variable> + <xsl:variable name="OSRelease"><xsl:value-of select="@OSRelease"/></xsl:variable> + <xsl:variable name="OSVersion"><xsl:value-of select="@OSVersion"/></xsl:variable> + <xsl:variable name="OSPlatform"><xsl:value-of select="@OSPlatform"/></xsl:variable> + <xsl:variable name="Is64Bits"><xsl:value-of select="@Is64Bits"/></xsl:variable> + <xsl:variable name="VendorString"><xsl:value-of select="@VendorString"/></xsl:variable> + <xsl:variable name="VendorID"><xsl:value-of select="@VendorID"/></xsl:variable> + <xsl:variable name="FamilyID"><xsl:value-of select="@FamilyID"/></xsl:variable> + <xsl:variable name="ModelID"><xsl:value-of select="@ModelID"/></xsl:variable> + <xsl:variable name="ProcessorCacheSize"><xsl:value-of select="@ProcessorCacheSize"/></xsl:variable> + <xsl:variable name="NumberOfLogicalCPU"><xsl:value-of select="@NumberOfLogicalCPU"/></xsl:variable> + <xsl:variable name="NumberOfPhysicalCPU"><xsl:value-of select="@NumberOfPhysicalCPU"/></xsl:variable> + <xsl:variable name="TotalVirtualMemory"><xsl:value-of select="@TotalVirtualMemory"/></xsl:variable> + <xsl:variable name="TotalPhysicalMemory"><xsl:value-of select="@TotalPhysicalMemory"/></xsl:variable> + <xsl:variable name="LogicalProcessorsPerPhysical"> + <xsl:value-of select="@LogicalProcessorsPerPhysical"/> + </xsl:variable> + <xsl:variable name="ProcessorClockFrequency"> + <xsl:value-of select="@ProcessorClockFrequency"/> + </xsl:variable> + <properties> + <property name="BuildName" value="{$BuildName}" /> + <property name="BuildStamp" value="{$BuildStamp}" /> + <property name="Name" value="{$Name}" /> + <property name="Generator" value="{$Generator}" /> + <property name="CompilerName" value="{$CompilerName}" /> + <property name="OSName" value="{$OSName}" /> + <property name="Hostname" value="{$Hostname}" /> + <property name="OSRelease" value="{$OSRelease}" /> + <property name="OSVersion" value="{$OSVersion}" /> + <property name="OSPlatform" value="{$OSPlatform}" /> + <property name="Is64Bits" value="{$Is64Bits}" /> + <property name="VendorString" value="{$VendorString}" /> + <property name="VendorID" value="{$VendorID}" /> + <property name="FamilyID" value="{$FamilyID}" /> + <property name="ModelID" value="{$ModelID}" /> + <property name="ProcessorCacheSize" value="{$ProcessorCacheSize}" /> + <property name="NumberOfLogicalCPU" value="{$NumberOfLogicalCPU}" /> + <property name="NumberOfPhysicalCPU" value="{$NumberOfPhysicalCPU}" /> + <property name="TotalVirtualMemory" value="{$TotalVirtualMemory}" /> + <property name="TotalPhysicalMemory" value="{$TotalPhysicalMemory}" /> + <property name="LogicalProcessorsPerPhysical" value="{$LogicalProcessorsPerPhysical}" /> + <property name="ProcessorClockFrequency" value="{$ProcessorClockFrequency}" /> + </properties> + <xsl:apply-templates select="Testing/Test"/> + + <system-out> + BuildName: <xsl:value-of select="$BuildName" /> + BuildStamp: <xsl:value-of select="$BuildStamp" /> + Name: <xsl:value-of select="$Name" /> + Generator: <xsl:value-of select="$Generator" /> + CompilerName: <xsl:value-of select="$CompilerName" /> + OSName: <xsl:value-of select="$OSName" /> + Hostname: <xsl:value-of select="$Hostname" /> + OSRelease: <xsl:value-of select="$OSRelease" /> + OSVersion: <xsl:value-of select="$OSVersion" /> + OSPlatform: <xsl:value-of select="$OSPlatform" /> + Is64Bits: <xsl:value-of select="$Is64Bits" /> + VendorString: <xsl:value-of select="$VendorString" /> + VendorID: <xsl:value-of select="$VendorID" /> + FamilyID: <xsl:value-of select="$FamilyID" /> + ModelID: <xsl:value-of select="$ModelID" /> + ProcessorCacheSize: <xsl:value-of select="$ProcessorCacheSize" /> + NumberOfLogicalCPU: <xsl:value-of select="$NumberOfLogicalCPU" /> + NumberOfPhysicalCPU: <xsl:value-of select="$NumberOfPhysicalCPU" /> + TotalVirtualMemory: <xsl:value-of select="$TotalVirtualMemory" /> + TotalPhysicalMemory: <xsl:value-of select="$TotalPhysicalMemory" /> + LogicalProcessorsPerPhysical: <xsl:value-of select="$LogicalProcessorsPerPhysical" /> + ProcessorClockFrequency: <xsl:value-of select="$ProcessorClockFrequency" /> + </system-out> + </testsuite> + </xsl:template> + + <xsl:template match="Testing/Test"> + <xsl:variable name="testcasename"><xsl:value-of select= "Name"/></xsl:variable> + <xsl:variable name="exectime"> + <xsl:for-each select="Results/NamedMeasurement"> + <xsl:if test="@name = 'Execution Time'"> + <xsl:value-of select="."/> + </xsl:if> + </xsl:for-each> + </xsl:variable> + + <testcase name="{$testcasename}" classname="TestSuite" time="{$exectime}"> + <xsl:if test="@Status = 'passed'"> + </xsl:if> + <xsl:if test="@Status = 'failed'"> + <xsl:variable name="failtype"> + <xsl:for-each select="Results/NamedMeasurement"> + <xsl:if test="@name = 'Exit Code'"> + <xsl:value-of select="."/> + </xsl:if> + </xsl:for-each> + </xsl:variable> + <xsl:variable name="failcode"> + <xsl:for-each select="Results/NamedMeasurement"> + <xsl:if test="@name = 'Exit Value'"> + <xsl:value-of select="."/> + </xsl:if> + </xsl:for-each> + </xsl:variable> + <error message="{$failtype} ({$failcode})"> + <xsl:value-of select="Results/Measurement/Value/text()" /> + </error> + </xsl:if> + <xsl:if test="@Status = 'notrun'"> + <skipped><xsl:value-of select="Results/Measurement/Value/text()" /></skipped> + </xsl:if> + </testcase> + </xsl:template> + +</xsl:stylesheet> +""" + + xml_doc = etree.parse(test_xml) + xslt_root = etree.XML(xsl) + transform = etree.XSLT(xslt_root) + result_tree = transform(xml_doc) + return result_tree + + +if __name__ == "__main__": + print(process(sys.argv[1])) -- GitLab From 212502d122ec5828155c3db5ef6f485b859967f2 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Tue, 26 Jan 2021 14:48:00 +0100 Subject: [PATCH 44/83] Enable codegen in Mac CI jobs --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e671445c2..bb024cdc0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1890,7 +1890,7 @@ msvc-14.2_mpionly: - mpirun --version - mkdir build - cd build - - cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DWARNING_ERROR=ON + - cmake .. -DWALBERLA_BUILD_TESTS=ON -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON -DWALBERLA_BUILD_WITH_CODEGEN=$WALBERLA_BUILD_WITH_CODEGEN -DWALBERLA_BUILD_WITH_OPENMP=$WALBERLA_BUILD_WITH_OPENMP -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DCMAKE_BUILD_TYPE=$CMAKE_BUILD_TYPE -DWARNING_ERROR=ON - cmake . -LA - make -j $NUM_BUILD_CORES -l $NUM_CORES - ctest -LE "$CTEST_EXCLUDE_LABELS|cuda" -C $CMAKE_BUILD_TYPE --output-on-failure -j $NUM_CORES -T Test @@ -1918,6 +1918,7 @@ mac_Serial_Dbg: WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" + WALBERLA_BUILD_WITH_CODEGEN: "ON" mac_Serial: <<: *mac_build_definition @@ -1927,6 +1928,7 @@ mac_Serial: WALBERLA_BUILD_WITH_MPI: "OFF" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" + WALBERLA_BUILD_WITH_CODEGEN: "ON" mac_MpiOnly_Dbg: <<: *mac_build_definition @@ -1936,6 +1938,7 @@ mac_MpiOnly_Dbg: WALBERLA_BUILD_WITH_MPI: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" + WALBERLA_BUILD_WITH_CODEGEN: "ON" OMPI_MCA_btl: "self,tcp" mac_MpiOnly: @@ -1946,6 +1949,7 @@ mac_MpiOnly: WALBERLA_BUILD_WITH_MPI: "ON" WALBERLA_BUILD_WITH_OPENMP: "OFF" WALBERLA_BUILD_WITH_PYTHON: "ON" + WALBERLA_BUILD_WITH_CODEGEN: "ON" OMPI_MCA_btl: "self,tcp" ############################################################################### -- GitLab From 346dbbdc6c0a29280b26b024e8a7c595ba2b6b4f Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Tue, 26 Jan 2021 16:57:43 +0100 Subject: [PATCH 45/83] improve ctest2junit --- cmake/ctest2junit.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake/ctest2junit.py b/cmake/ctest2junit.py index 9474cd260..d1e5c77b7 100755 --- a/cmake/ctest2junit.py +++ b/cmake/ctest2junit.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# This file is from https://github.com/scikit-build/scikit-ci-addons/tree/master/anyci +# Adapted from https://github.com/scikit-build/scikit-ci-addons/tree/master/anyci # under Apache 2.0 license. import os @@ -107,29 +107,30 @@ def process(build_dir): <xsl:template match="Testing/Test"> <xsl:variable name="testcasename"><xsl:value-of select= "Name"/></xsl:variable> + <xsl:variable name="testsuitename"><xsl:value-of select= "Path"/></xsl:variable> <xsl:variable name="exectime"> <xsl:for-each select="Results/NamedMeasurement"> <xsl:if test="@name = 'Execution Time'"> - <xsl:value-of select="."/> + <xsl:value-of select="Value"/> </xsl:if> </xsl:for-each> </xsl:variable> - <testcase name="{$testcasename}" classname="TestSuite" time="{$exectime}"> + <testcase name="{$testcasename}" classname="{$testsuitename}" time="{$exectime}"> <xsl:if test="@Status = 'passed'"> </xsl:if> <xsl:if test="@Status = 'failed'"> <xsl:variable name="failtype"> <xsl:for-each select="Results/NamedMeasurement"> <xsl:if test="@name = 'Exit Code'"> - <xsl:value-of select="."/> + <xsl:value-of select="Value/text()"/> </xsl:if> </xsl:for-each> </xsl:variable> <xsl:variable name="failcode"> <xsl:for-each select="Results/NamedMeasurement"> <xsl:if test="@name = 'Exit Value'"> - <xsl:value-of select="."/> + <xsl:value-of select="Value/text()"/> </xsl:if> </xsl:for-each> </xsl:variable> -- GitLab From 0a07c07dd04a145d7f443a6c5b6a027ba5519a48 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Wed, 27 Jan 2021 09:53:51 +0100 Subject: [PATCH 46/83] Update pybind11 to 2.6.2 release --- extern/pybind11 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/pybind11 b/extern/pybind11 index 48534089f..8de7772cc 160000 --- a/extern/pybind11 +++ b/extern/pybind11 @@ -1 +1 @@ -Subproject commit 48534089f7f1b0229bc7ae2e4d0f21dc9ad169b5 +Subproject commit 8de7772cc72daca8e947b79b83fea46214931604 -- GitLab From 01223796259c4fbb8881c4864e052b1e841608bc Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Wed, 27 Jan 2021 11:38:41 +0100 Subject: [PATCH 47/83] fix PhaseFieldAllenCahn on Mac CI --- apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py index 7a00cbca6..999f76d3c 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py +++ b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py @@ -153,7 +153,7 @@ info_header = f""" """ with CodeGeneration() as ctx: - if ctx.cuda is False: + if not ctx.cuda: if not ctx.optimize_for_localhost: cpu_vec = {'instruction_set': None} -- GitLab From 00f6dd84bc6861318305b4979d2e8324611fbf31 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 27 Jan 2021 11:42:33 +0100 Subject: [PATCH 48/83] [BUGFIX] handle failing of FindOpenMP --- CMakeLists.txt | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 80a06fc8d..36c6831d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1001,19 +1001,25 @@ endif() option ( WALBERLA_THREAD_SAFE_LOGGING "Enables/Disables thread-safe logging" ON ) if ( WALBERLA_BUILD_WITH_OPENMP ) - if ( WALBERLA_CXX_COMPILER_IS_NEC ) - add_flag ( CMAKE_C_FLAGS "-Popenmp" ) - add_flag ( CMAKE_CXX_FLAGS "-Popenmp" ) + find_package( OpenMP ) + if (OpenMP_FOUND) + add_flag ( CMAKE_C_FLAGS "${OpenMP_C_FLAGS}" ) + add_flag ( CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS}" ) + list ( APPEND SERVICE_LIBS ${OpenMP_CXX_LIBRARIES} ) else() - find_package( OpenMP ) - add_flag ( CMAKE_C_FLAGS "${OpenMP_C_FLAGS}" ) - add_flag ( CMAKE_CXX_FLAGS "${OpenMP_CXX_FLAGS}" ) - list ( APPEND SERVICE_LIBS ${OpenMP_CXX_LIBRARIES} ) + #workarounds + if ( WALBERLA_CXX_COMPILER_IS_NEC ) + message( STATUS "Enabling OpenMP workaround for NEC") + add_flag ( CMAKE_C_FLAGS "-Popenmp" ) + add_flag ( CMAKE_CXX_FLAGS "-Popenmp" ) + else() + message(FATAL_ERROR "Could NOT enable OpenMP") + endif() endif() else() if ( WALBERLA_CXX_COMPILER_IS_CRAY ) - add_flag ( CMAKE_C_FLAGS "-h noomp" ) - add_flag ( CMAKE_CXX_FLAGS "-h noomp" ) + add_flag ( CMAKE_C_FLAGS "-h noomp" ) + add_flag ( CMAKE_CXX_FLAGS "-h noomp" ) endif() endif() ############################################################################################################################ -- GitLab From 05483e1443c4e3a4add1b41223ded7e4ca537c4a Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Wed, 27 Jan 2021 17:55:20 +0100 Subject: [PATCH 49/83] Eliminate 75% of the visibility warnings on Mac builds constructing an empty std::set has almost no cost --- src/core/Set.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/Set.h b/src/core/Set.h index 36bed9a61..3b77f42e7 100644 --- a/src/core/Set.h +++ b/src/core/Set.h @@ -101,7 +101,7 @@ public: inline virtual ~Set() {} - static const Set<T>& emptySet() { static Set set; return set; } + static const Set<T> emptySet() { return {}; } inline std::pair<iterator,bool> insert( const T& element ) { return set_.insert( element ); } inline iterator insert( iterator position, const T& element ) { return set_.insert( position, element ); } -- GitLab From 9b84dd4f15232d46d5b1c373eca03a5817f83a26 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 12 Jan 2021 16:56:53 +0100 Subject: [PATCH 50/83] [ADD] kernel for the VBondModel, viscous damping --- .../kernel/VBondModel/ViscousDamping.h | 77 +++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/VBondModel/ViscousDamping.test.cpp | 86 +++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 src/mesa_pd/kernel/VBondModel/ViscousDamping.h create mode 100644 tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp diff --git a/src/mesa_pd/kernel/VBondModel/ViscousDamping.h b/src/mesa_pd/kernel/VBondModel/ViscousDamping.h new file mode 100644 index 000000000..9f9fe2c69 --- /dev/null +++ b/src/mesa_pd/kernel/VBondModel/ViscousDamping.h @@ -0,0 +1,77 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace VBondModel { + +class ViscousDamping +{ +public: + ViscousDamping(real_t forceDampingFactor, real_t torqueDampingFactor) + : forceDampingFactor_(forceDampingFactor) + , torqueDampingFactor_(torqueDampingFactor) + {} + + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) const; + + auto getForceDampingFactor() const {return forceDampingFactor_;} + auto getTorqueDampingFactor() const {return torqueDampingFactor_;} +private: + const real_t forceDampingFactor_; + const real_t torqueDampingFactor_; +}; + +template<typename Accessor> +inline void ViscousDamping::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) const +{ + Vec3 velDampingForce = (ac.getLinearVelocity(p_idx1) - ac.getLinearVelocity(p_idx2)) * forceDampingFactor_; + addForceAtomic(p_idx1, ac, -velDampingForce); + addForceAtomic(p_idx2, ac, velDampingForce); + + Vec3 angDampingTorque = (ac.getAngularVelocity(p_idx1) - ac.getAngularVelocity(p_idx2)) * torqueDampingFactor_; + addTorqueAtomic(p_idx1, ac, -angDampingTorque); + addTorqueAtomic(p_idx2, ac, angDampingTorque); + +} + +} //namespace VBondModel +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index b68b61f25..b39c37338 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -164,6 +164,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) +waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping FILES kernel/VBondModel/ViscousDamping.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping ) + waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_WallContact FILES kernel/VBondModel/WallContact.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_WallContact ) diff --git a/tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp b/tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp new file mode 100644 index 000000000..8f54645ff --- /dev/null +++ b/tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp @@ -0,0 +1,86 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleAccessor.h> +#include <mesa_pd/data/ParticleStorage.h> + +#include <mesa_pd/kernel/VBondModel/ViscousDamping.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { +namespace mesa_pd { + +int main( int argc, char ** argv ) +{ + + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + //init data structures + auto ps = std::make_shared<data::ParticleStorage>(2); + data::Particle &&p1 = *ps->create(); + data::Particle &&p2 = *ps->create(); + + data::ParticleAccessor ac(ps); + + //init kernels + kernel::VBondModel::ViscousDamping damping(0.2_r,0.5_r); + WALBERLA_CHECK_FLOAT_EQUAL(damping.getForceDampingFactor(), + 0.2_r); + WALBERLA_CHECK_FLOAT_EQUAL(damping.getTorqueDampingFactor(), + 0.5_r); + + p1.setLinearVelocity(Vec3(1_r, 2_r, 3_r)); + p2.setLinearVelocity(Vec3(3_r, 2_r, 1_r)); + p1.setAngularVelocity(Vec3(2_r, 3_r, 4_r)); + p2.setAngularVelocity(Vec3(3_r, 2_r, 1_r)); + damping(0, 1, ac); + WALBERLA_CHECK_FLOAT_EQUAL(p1.getForce(), + Vec3(0.4_r, 0_r, -0.4_r)); + WALBERLA_CHECK_FLOAT_EQUAL(p2.getForce(), + Vec3(-0.4_r, 0_r, 0.4_r)); + WALBERLA_CHECK_FLOAT_EQUAL(p1.getTorque(), + Vec3(0.5_r, -0.5_r, -1.5_r)); + WALBERLA_CHECK_FLOAT_EQUAL(p2.getTorque(), + Vec3(-0.5_r, 0.5_r, 1.5_r)); + + return EXIT_SUCCESS; +} + +} //namespace mesa_pd +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::mesa_pd::main(argc, argv); +} -- GitLab From 4c45f84d586b09f8e8367c8a6d0c6df183a7bb31 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 13:39:43 +0100 Subject: [PATCH 51/83] [ADD] kernel for the cnt model: isotropic vdW contact --- src/mesa_pd/kernel/cnt/IsotropicVDWContact.h | 106 ++++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/cnt/IsotropicVDWContact.test.cpp | 87 ++++++++++++++ 3 files changed, 196 insertions(+) create mode 100644 src/mesa_pd/kernel/cnt/IsotropicVDWContact.h create mode 100644 tests/mesa_pd/kernel/cnt/IsotropicVDWContact.test.cpp diff --git a/src/mesa_pd/kernel/cnt/IsotropicVDWContact.h b/src/mesa_pd/kernel/cnt/IsotropicVDWContact.h new file mode 100644 index 000000000..a92ecda09 --- /dev/null +++ b/src/mesa_pd/kernel/cnt/IsotropicVDWContact.h @@ -0,0 +1,106 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace cnt { + +/** + * Isotropic vdW contact model. + * + * implementation follows: + * I. Ostanin, R. Ballarini, D. Potyondy, T. Dumitrica, A distinct element method for large scale simulations of carbon nanotube assemblies, J. Mech. Phys. Solid. 61 (2013) 762-782. + * https://doi.org/10.1016/j.jmps.2012.10.016 + */ +class IsotropicVDWContact +{ +public: + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac); + static real_t equilibriumDistance(); + + static constexpr real_t eps = 0.07124_r; + static constexpr real_t A = 0.0223_r; + static constexpr real_t B = 1.31_r; + static constexpr real_t alpha = 9.5_r; + static constexpr real_t beta = 4.0_r; + static constexpr real_t r = 6.78_r; + static constexpr real_t Rinv = 1.0_r / r; + static constexpr real_t Dc = 0.4_r; + + auto getLastForce() const {return F_;} + auto getLastEnergy() const {return U_;} +private: + real_t F_ = 0_r; ///< resulting force from the last interaction + real_t U_ = 0_r; ///< resulting energy from the last interaction +}; + +template<typename Accessor> +inline +void IsotropicVDWContact::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) +{ + Vec3 n = ac.getPosition(p_idx2) - ac.getPosition(p_idx1); ///< contact normal + real_t L = n.length(); + n *= (1_r/L); + + real_t D = L * Rinv - 2_r; + F_ = 0.01_r; //default value + U_ = 0_r; //default value + + if (D > Dc) + { + const auto pow_alpha = std::pow(D, alpha); + const auto pow_beta = std::pow(D, beta); + F_ = 4_r * eps * (-(alpha * A) / (pow_alpha * D) + (beta * B) / (pow_beta * D)); + U_ = 4_r * eps * (A / pow_alpha - B / pow_beta); + } + + Vec3 force = n * F_; + addForceAtomic(p_idx1, ac, force); + addForceAtomic(p_idx2, ac, -force); +} + +real_t IsotropicVDWContact::equilibriumDistance() +{ + return r * ( std::pow( (alpha*A)/(beta*B), 1_r/(alpha-beta)) + 2_r); +} + +} //namespace cnt +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index b68b61f25..07a3b6b6b 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -84,6 +84,9 @@ waLBerla_execute_test( NAME MESA_PD_DropTestGeneral ) waLBerla_compile_test( NAME MESA_PD_Kernel_ClearNextNeighborSync FILES kernel/ClearNextNeighborSync.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_ClearNextNeighborSync PROCESSES 2 ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact FILES kernel/cnt/IsotropicVDWContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSD FILES kernel/CoefficientOfRestitutionSD.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDEuler COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDVelocityVerlet COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> --useVV ) diff --git a/tests/mesa_pd/kernel/cnt/IsotropicVDWContact.test.cpp b/tests/mesa_pd/kernel/cnt/IsotropicVDWContact.test.cpp new file mode 100644 index 000000000..60e4e6eca --- /dev/null +++ b/tests/mesa_pd/kernel/cnt/IsotropicVDWContact.test.cpp @@ -0,0 +1,87 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleAccessor.h> +#include <mesa_pd/data/ParticleStorage.h> + +#include <mesa_pd/kernel/cnt/IsotropicVDWContact.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { +namespace mesa_pd { + +int main(int argc, char **argv) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + //init data structures + auto ps = std::make_shared<data::ParticleStorage>(2); + data::Particle &&p1 = *ps->create(); + data::Particle &&p2 = *ps->create(); + + data::ParticleAccessor accessor(ps); + + //init kernels + kernel::cnt::IsotropicVDWContact vdWContact; + + auto calcForce = [&](const Vec3 pos1, const Vec3 pos2) { + p1.setPosition(pos1); + p2.setPosition(pos2); + clear(p1.getForceRef()); + clear(p2.getForceRef()); + vdWContact(0, 1, accessor); + return p1.getForce(); + }; + + const Vec3 randomNormal = Vec3(1_r, 2_r, 3_r).getNormalized(); + + WALBERLA_LOG_INFO("checking repulsion - equilibrium - attraction"); + vdWContact(0, 1, accessor); + WALBERLA_CHECK_LESS (dot(randomNormal, calcForce(Vec3(0), randomNormal * (vdWContact.equilibriumDistance() - 1_r))), + 0_r); + WALBERLA_CHECK_FLOAT_EQUAL(dot(randomNormal, calcForce(Vec3(0), randomNormal * vdWContact.equilibriumDistance())), + 0_r); + WALBERLA_CHECK_GREATER (dot(randomNormal, calcForce(Vec3(0), randomNormal * (vdWContact.equilibriumDistance() + 1_r))), + 0_r); + + return EXIT_SUCCESS; +} + +} //namespace mesa_pd +} //namespace walberla + +int main(int argc, char **argv) +{ + return walberla::mesa_pd::main(argc, argv); +} -- GitLab From 8dfb5edccd9c1a84e936f51e89c6c9e4899068df Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 15:50:11 +0100 Subject: [PATCH 52/83] [ADD] kernel for the VBondModel, vbond contact --- src/mesa_pd/kernel/VBondModel/VBondContact.h | 164 ++++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/VBondModel/VBondContact.test.cpp | 80 +++++++++ 3 files changed, 247 insertions(+) create mode 100644 src/mesa_pd/kernel/VBondModel/VBondContact.h create mode 100644 tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp diff --git a/src/mesa_pd/kernel/VBondModel/VBondContact.h b/src/mesa_pd/kernel/VBondModel/VBondContact.h new file mode 100644 index 000000000..716fdc195 --- /dev/null +++ b/src/mesa_pd/kernel/VBondModel/VBondContact.h @@ -0,0 +1,164 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace VBondModel { + +/** + * Advanced DEM kernel + */ +class VBondContact +{ +public: + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac); + + static constexpr real_t S = 142.7_r; // Area of the bond, + static constexpr real_t E = 1029_r * 0.006242_r; // Conversion from GPa to eV/A^3 + static constexpr real_t G = 459_r * 0.006242_r; + static constexpr real_t a = 2_r * 6.78_r; // (10,10) CNTS + static constexpr real_t J = 3480_r; + static constexpr real_t Jp = 2_r * J; + + // Stiffnesses, equilibrium length etc + static constexpr real_t B1 = E * S / a; // Need to calibrate + static constexpr real_t B2 = 12_r * E * J / a; + static constexpr real_t B3 = -2_r * E * J / a - G * Jp / (2_r * a); + static constexpr real_t B4 = G * Jp / a; + + Vector3<bool> isPeriodic_; + Vector3<int64_t> maxSegments_; + + + // Calibration through atomistic simulation + //constexpr real_t B1 = 60.1_r; + //constexpr real_t B2 = 17100_r; + //constexpr real_t B3 = 3610_r; + //constexpr real_t B4 = 1107_r; + + real_t U; + real_t U_1; + real_t U_2; + real_t U_3; + real_t U_4; +}; + +/** + * + * @tparam Accessor + * @param p_idx1 + * @param p_idx2 + * @param ac + * @return vdW adhesion energy + */ +template<typename Accessor> +inline +void VBondContact::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) +{ + Vec3 ri = ac.getPosition(p_idx1); + Vec3 rj = ac.getPosition(p_idx2); + + // Fix for the issue of segment's undefined sides + real_t sign = ac.getSegmentID(p_idx1) <= ac.getSegmentID(p_idx2) ? 1_r : -1_r; + if (((isPeriodic_[0]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[0] - 1)) or + ((isPeriodic_[1]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[1] - 1))) + sign = -sign; // special case for periodic fibers + + Vec3 ni1 = ac.getRotation(p_idx1).getMatrix() * Vec3(sign, 0_r, 0_r); + Vec3 ni2 = ac.getRotation(p_idx1).getMatrix() * Vec3(0_r, 1_r, 0_r); + Vec3 ni3 = ac.getRotation(p_idx1).getMatrix() * Vec3(0_r, 0_r, 1_r); + + Vec3 nj1 = ac.getRotation(p_idx2).getMatrix() * Vec3(-sign, 0_r, 0_r); + Vec3 nj2 = ac.getRotation(p_idx2).getMatrix() * Vec3(0_r, 1_r, 0_r); + Vec3 nj3 = ac.getRotation(p_idx2).getMatrix() * Vec3(0_r, 0_r, 1_r); + + // Vectors Dij and dij + Vec3 Dij = rj - ri; + real_t s = Dij.length(); + Vec3 dij = Dij * (1_r / s); + + real_t C = 1_r; + + /* + //srand(SID_1); + double AA = 0.2 + 0.2 * ((rand() % 1000)/1000); //strain of initiation of stress corrosion + //double BB = 0.01; // width of stress corrosion band + //double DD = 1. + AA/BB; + //double KK = 1 / BB; + //if (((std::fabs((s-a)/s))>AA)&&((std::fabs((s-a)/s))<=AA+BB)) C = DD - std::fabs((s-a)/s) * KK; + //if ((std::fabs((s-a)/s))>AA+BB) C = 0; + if ((std::fabs((s-a)/s))>AA) C = 0; + + // Potential energy + real_t U_1 = C * 0.5 * B1 * (s - a) * (s - a); + real_t U_2 = C * 0.5 * B2 * (nj1 - ni1) * dij + B2; + real_t U_3 = C * B3 * ni1 * nj1 + B3; + real_t U_4 = C * -0.5 * B4 * (ni2 * nj2 + ni3 * nj3) + B4; + real_t U = U_1 + U_2 + U_3 + U_4; + */ + U_1 = 0.5_r * B1 * (s - a) * (s - a); + U_2 = B2 * (0.5_r * (nj1 - ni1) * dij - 0.25_r * ni1 * nj1 + 0.75_r); + U_3 = (0.25_r * B2 + B3 + 0.5_r * B4) * (ni1 * nj1 + 1_r); + U_4 = -0.5_r * B4 * (ni1 * nj1 + ni2 * nj2 + ni3 * nj3 - 1_r); + U = U_1 + U_2 + U_3 + U_4; + + Vec3 rij = dij; + + Vec3 Fij = C * B1 * (s - a) * rij + B2 / (2_r * s) * ((nj1 - ni1) - ((nj1 - ni1) * dij) * dij); + Vec3 Fji = -Fij; + Vec3 M_TB = C * B3 * (nj1 % ni1) - 0.5_r * B4 * (nj2 % ni2 + nj3 % ni3); + Vec3 Mij = -C * 0.5_r * B2 * (dij % ni1) + M_TB; + Vec3 Mji = C * 0.5_r * B2 * (dij % nj1) - M_TB; + + addForceAtomic(p_idx1, ac, Fij); + addForceAtomic(p_idx2, ac, Fji); + addTorqueAtomic(p_idx1, ac, Mij); + addTorqueAtomic(p_idx2, ac, Mji); +} + +} //namespace VBondModel +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index a70fa950f..f68304f20 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -167,6 +167,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) +waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_VBondContact FILES kernel/VBondModel/VBondContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_VBondContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping FILES kernel/VBondModel/ViscousDamping.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping ) diff --git a/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp new file mode 100644 index 000000000..941b4c285 --- /dev/null +++ b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp @@ -0,0 +1,80 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleAccessor.h> +#include <mesa_pd/data/ParticleStorage.h> + +#include <mesa_pd/kernel/VBondModel/VBondContact.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { +namespace mesa_pd { + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + //init data structures + auto ps = std::make_shared<data::ParticleStorage>(100); + + data::Particle&& p1 = *ps->create(); + p1.getPositionRef() = Vec3(0,0,0); + p1.getForceRef() = Vec3(0,0,0); + p1.getTypeRef() = 0; + + data::Particle&& p2 = *ps->create(); + p2.getPositionRef() = Vec3(0,0,0); + p2.getForceRef() = Vec3(0,0,0); + p2.getTypeRef() = 0; + + data::ParticleAccessor accessor(ps); + + //init kernels + kernel::VBondModel::VBondContact vbond; + + //check equilibrium distance + vbond(0, 1, accessor); + WALBERLA_CHECK_FLOAT_EQUAL( p1.getForce(), Vec3(0,0,0) ); + WALBERLA_CHECK_FLOAT_EQUAL( p2.getForce(), Vec3(0,0,0) ); + + return EXIT_SUCCESS; +} + +} //namespace mesa_pd +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::mesa_pd::main(argc, argv); +} -- GitLab From 04247e91e3094c3f33a787ef70fa1f31f0d015ec Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Thu, 21 Jan 2021 10:16:00 +0100 Subject: [PATCH 53/83] [ADD] benchmark --- apps/benchmarks/CMakeLists.txt | 1 + apps/benchmarks/CNT/Accessor.h | 48 +++++++ apps/benchmarks/CNT/CMakeLists.txt | 3 + apps/benchmarks/CNT/VBondModel.cpp | 128 ++++++++++++++++++ src/core/math/Constants.h | 28 ++-- src/mesa_pd/kernel/cnt/Parameters.h | 108 +++++++++++++++ .../kernel/{VBondModel => cnt}/VBondContact.h | 66 +++------ .../kernel/VBondModel/VBondContact.test.cpp | 4 +- 8 files changed, 325 insertions(+), 61 deletions(-) create mode 100644 apps/benchmarks/CNT/Accessor.h create mode 100644 apps/benchmarks/CNT/CMakeLists.txt create mode 100644 apps/benchmarks/CNT/VBondModel.cpp create mode 100644 src/mesa_pd/kernel/cnt/Parameters.h rename src/mesa_pd/kernel/{VBondModel => cnt}/VBondContact.h (73%) diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index d16b4255d..420dc32d3 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -1,4 +1,5 @@ add_subdirectory( AdaptiveMeshRefinementFluidParticleCoupling ) +add_subdirectory( CNT ) add_subdirectory( ComplexGeometry ) add_subdirectory( DEM ) add_subdirectory( MeshDistance ) diff --git a/apps/benchmarks/CNT/Accessor.h b/apps/benchmarks/CNT/Accessor.h new file mode 100644 index 000000000..d23002562 --- /dev/null +++ b/apps/benchmarks/CNT/Accessor.h @@ -0,0 +1,48 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "mesa_pd/data/ParticleAccessor.h" +#include "mesa_pd/kernel/cnt/Parameters.h" + +namespace walberla { +namespace mesa_pd { + +class Accessor : public data::ParticleAccessor +{ +public: + Accessor(std::shared_ptr<data::ParticleStorage>& ps) + : ParticleAccessor(ps) + {} + + constexpr auto getInvMass(const size_t /*p_idx*/) const {return 1_r / kernel::cnt::mass_T;} + + constexpr auto& getInvInertiaBF(const size_t /*p_idx*/) const {return invI;} +private: + // - sphere : I = (2/5)*mass*radius^2 + static constexpr auto Ia = 0.4_r * kernel::cnt::mass_T * kernel::cnt::inner_radius * kernel::cnt::inner_radius; + static constexpr auto invI = Mat3(1_r/Ia, 0_r, 0_r, 0_r, 1_r/Ia, 0_r, 0_r, 0_r, 1_r/Ia); +}; + +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/apps/benchmarks/CNT/CMakeLists.txt b/apps/benchmarks/CNT/CMakeLists.txt new file mode 100644 index 000000000..320d0ce94 --- /dev/null +++ b/apps/benchmarks/CNT/CMakeLists.txt @@ -0,0 +1,3 @@ +waLBerla_add_executable ( NAME VBondModel + FILES VBondModel.cpp + DEPENDS core mesa_pd ) diff --git a/apps/benchmarks/CNT/VBondModel.cpp b/apps/benchmarks/CNT/VBondModel.cpp new file mode 100644 index 000000000..091327c2f --- /dev/null +++ b/apps/benchmarks/CNT/VBondModel.cpp @@ -0,0 +1,128 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "Accessor.h" +#include "mesa_pd/data/Flags.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/cnt/Parameters.h" +#include "mesa_pd/kernel/cnt/VBondContact.h" +#include "mesa_pd/kernel/VelocityVerlet.h" + +#include "core/Environment.h" +#include "core/math/Constants.h" + +namespace walberla { +using namespace walberla::mesa_pd; + +int main(int argc, char **argv) +{ + Environment env(argc, argv); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + logging::Logging::instance()->setStreamLogLevel(logging::Logging::INFO); + logging::Logging::instance()->setFileLogLevel(logging::Logging::INFO); + + WALBERLA_LOG_INFO_ON_ROOT("loading configuration parameters"); + constexpr auto numSimulationSteps = 500ll; + + WALBERLA_LOG_INFO_ON_ROOT("creating initial particle setup"); + auto ps = std::make_shared<data::ParticleStorage>(10); + auto ac = Accessor(ps); + + for (auto i = 0; i < 10; ++i) + { + data::Particle &&p = *ps->create(); + p.setPosition(Vec3(0_r, 0_r, real_c(i) * 13.56_r)); + p.setSegmentID(i); + p.setClusterID(1); + if (i == 0) + data::particle_flags::set(p.getFlagsRef(), data::particle_flags::FIXED); + p.getRotationRef().rotate(Vec3(0_r, 1_r, 0_r), -0.5_r * math::pi); + p.getRotationRef().rotate(Vec3(0_r, 0_r, 1_r), 0_r); + } + data::Particle &&last_segment = *(ps->end() - 1); + + WALBERLA_LOG_INFO_ON_ROOT("setting up interaction models"); + kernel::cnt::VBondContact vbond; + kernel::VelocityVerletPreForceUpdate vv_pre(kernel::cnt::dT); + kernel::VelocityVerletPostForceUpdate vv_post(kernel::cnt::dT); + + WALBERLA_LOG_INFO_ON_ROOT("running simulation"); + auto appliedForce = Vec3(1_r, 0_r, 0_r); + auto appliedTorque = Vec3(0_r); + std::ofstream fout("output.txt"); + for (auto i = 0; i < numSimulationSteps; ++i) + { + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_pre, + ac); + + last_segment.setForce(appliedForce); + last_segment.setTorque(appliedTorque); + constexpr auto cutoff2 = kernel::cnt::outer_radius * kernel::cnt::outer_radius; + + real_t tensileEnergy = 0_r; + real_t shearEnergy = 0_r; + real_t bendingEnergy = 0_r; + real_t twistingEnergy = 0_r; + + ps->forEachParticlePairHalf(false, + kernel::SelectAll(), + ac, + [&](size_t p_idx1, size_t p_idx2, Accessor &ac) + { + if ((ac.getPosition(p_idx1) - ac.getPosition(p_idx2)).sqrLength() < cutoff2) + { + vbond(p_idx1, p_idx2, ac); + tensileEnergy += vbond.tensileEnergy; + shearEnergy += vbond.shearEnergy; + bendingEnergy += vbond.bendingEnergy; + twistingEnergy += vbond.twistingEnergy; + } + }, + ac); + + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_post, + ac); + + fout << last_segment.getPosition()[0] << " " + << tensileEnergy << " " + << shearEnergy << " " + << bendingEnergy << " " + << twistingEnergy + << std::endl; + } + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main(int argc, char *argv[]) +{ + return walberla::main(argc, argv); +} diff --git a/src/core/math/Constants.h b/src/core/math/Constants.h index 92e49678d..5487e14cf 100644 --- a/src/core/math/Constants.h +++ b/src/core/math/Constants.h @@ -34,19 +34,21 @@ namespace walberla { namespace math { -constexpr real_t e = real_t(2.7182818284590452354); /* e */ -constexpr real_t log2_e = real_t(1.4426950408889634074); /* log_2 e */ -constexpr real_t log10_e = real_t(0.43429448190325182765); /* log_10 e */ -constexpr real_t ln_two = real_t(0.69314718055994530942); /* log_e 2 */ -constexpr real_t ln_ten = real_t(2.30258509299404568402); /* log_e 10 */ -constexpr real_t pi = real_t(3.14159265358979323846); /* pi */ -constexpr real_t half_pi = real_t(1.57079632679489661923); /* pi/2 */ -constexpr real_t fourth_pi = real_t(0.78539816339744830962); /* pi/4 */ -constexpr real_t one_div_pi = real_t(0.31830988618379067154); /* 1/pi */ -constexpr real_t two_div_pi = real_t(0.63661977236758134308); /* 2/pi */ -constexpr real_t two_div_root_pi = real_t(1.12837916709551257390); /* 2/sqrt(pi) */ -constexpr real_t root_two = real_t(1.41421356237309504880); /* sqrt(2) */ -constexpr real_t one_div_root_two = real_t(0.70710678118654752440); /* 1/sqrt(2) */ +constexpr real_t e = real_t(2.7182818284590452354); /* e */ +constexpr real_t log2_e = real_t(1.4426950408889634074); /* log_2 e */ +constexpr real_t log10_e = real_t(0.43429448190325182765); /* log_10 e */ +constexpr real_t ln_two = real_t(0.69314718055994530942); /* log_e 2 */ +constexpr real_t ln_ten = real_t(2.30258509299404568402); /* log_e 10 */ +constexpr real_t pi = real_t(3.14159265358979323846); /* pi */ +constexpr real_t half_pi = real_t(1.57079632679489661923); /* pi/2 */ +constexpr real_t fourth_pi = real_t(0.78539816339744830962); /* pi/4 */ +constexpr real_t one_div_pi = real_t(0.31830988618379067154); /* 1/pi */ +constexpr real_t two_div_pi = real_t(0.63661977236758134308); /* 2/pi */ +constexpr real_t two_div_root_pi = real_t(1.12837916709551257390); /* 2/sqrt(pi) */ +constexpr real_t root_two = real_t(1.41421356237309504880); /* sqrt(2) */ +constexpr real_t one_div_root_two = real_t(0.70710678118654752440); /* 1/sqrt(2) */ +constexpr real_t root_three = real_t(1.73205080757); /* sqrt(3) */ +constexpr real_t one_div_root_three = real_t(0.57735026919); /* 1/sqrt(3) */ } // namespace math } // namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/kernel/cnt/Parameters.h b/src/mesa_pd/kernel/cnt/Parameters.h new file mode 100644 index 000000000..63f256a04 --- /dev/null +++ b/src/mesa_pd/kernel/cnt/Parameters.h @@ -0,0 +1,108 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "core/DataTypes.h" +#include "core/math/Constants.h" + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace cnt { + +//====================CNT inertial and elastic parameters======================================================== + +// Within our model, CNTs are represented with intersecting capsule primitives - cylinders with capped ends. +// Capped ends are necessary for a continuous normal definition +// Each capsule represents the inertial properties of a cylindrical segment. + +// For the units system used see PFC 5 implementation docs + +/// timestep is fixed to 20 fs. +constexpr auto dT = 20_r; + +/// vdW interaction radius w/r to inertial segment radius +constexpr auto CutoffFactor = 4_r; + +// CNT lattice numbers (m,n) CNT +constexpr auto mm = 10_r; +constexpr auto nn = 10_r; + +/// CNT Young modulus in GPa based on atomistic simulations +constexpr auto En = 1029_r; +/// CNT shear modulus in GPa based on atomistic simulations +constexpr auto Gs = 459_r; + +/// Equilibrium distance of a covalent C-C bond +constexpr auto a_CC = 1.42_r; + +/// Equilibrium vdW separation of two CNT surfaces +constexpr auto a_VD = 3.35_r; + +/// CNT radius +constexpr auto R_CNT = 6.78_r; //( a_CC / (2 * PII)) * std::sqrt( 3.0 * ( mm * mm + nn * nn + mm * nn ) ); + +/// external radius of an idealized hollow cylindrical shell +constexpr auto R_1 = R_CNT + 0.5_r * a_VD; +/// internal radius of an idealized hollow cylindrical shell +constexpr auto R_2 = R_CNT - 0.5_r * a_VD; + +/// height of a cylindrical segment +constexpr auto T = 2_r * R_CNT; + +/// linear density in atoms per A +constexpr auto ro = 4_r * mm / ( math::root_three * a_CC ); + +/// Atomic mass of Carbon in AMU +constexpr auto M_C = 12.011_r; + +/// Mass of the repetative cell in AMU +constexpr auto mass_T = ro * T * M_C * 104.397_r; + +// Volume of a capsule +//double vol = (4./3.) * PII * (R_CNT * R_CNT * R_CNT) + PII * R_CNT * R_CNT * T; + +// Density of a capsule +//double dens = mass_T / vol; + +/// V-bond parameter +constexpr auto knorm = (En * 0.006242_r) / T; +/// V-bond parameter +constexpr auto kshear = (Gs * 0.006242_r) / T; + +constexpr auto margin = 10.e-10_r; + +constexpr auto outer_radius = CutoffFactor * R_CNT; +// real_t inner_radius = R_CNT; // Capsule +constexpr auto inner_radius = 1.5811_r * R_CNT; // Sphere + +/// volume of a sphere +constexpr auto vol = (4_r/3_r) * math::pi * (inner_radius * inner_radius * inner_radius); + +/// density of a sphere +constexpr auto dens = mass_T / vol; + +} //namespace cnt +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/kernel/VBondModel/VBondContact.h b/src/mesa_pd/kernel/cnt/VBondContact.h similarity index 73% rename from src/mesa_pd/kernel/VBondModel/VBondContact.h rename to src/mesa_pd/kernel/cnt/VBondContact.h index 716fdc195..f245aca1e 100644 --- a/src/mesa_pd/kernel/VBondModel/VBondContact.h +++ b/src/mesa_pd/kernel/cnt/VBondContact.h @@ -40,10 +40,17 @@ namespace walberla { namespace mesa_pd { namespace kernel { -namespace VBondModel { +namespace cnt { /** - * Advanced DEM kernel + * VBond interaction model + * + * Implementation according to: + * + * Ostanin, I., Dumitrică, T., Eibl, S., and Rüde, U. (October 4, 2019). + * "Size-Independent Mechanical Response of Ultrathin Carbon Nanotube Films in Mesoscopic Distinct Element Method Simulations." + * ASME. J. Appl. Mech. December 2019; 86(12): 121006. + * https://doi.org/10.1115/1.4044413 */ class VBondContact { @@ -61,7 +68,7 @@ public: static constexpr real_t Jp = 2_r * J; // Stiffnesses, equilibrium length etc - static constexpr real_t B1 = E * S / a; // Need to calibrate + static constexpr real_t B1 = E * S / a; static constexpr real_t B2 = 12_r * E * J / a; static constexpr real_t B3 = -2_r * E * J / a - G * Jp / (2_r * a); static constexpr real_t B4 = G * Jp / a; @@ -69,28 +76,13 @@ public: Vector3<bool> isPeriodic_; Vector3<int64_t> maxSegments_; - - // Calibration through atomistic simulation - //constexpr real_t B1 = 60.1_r; - //constexpr real_t B2 = 17100_r; - //constexpr real_t B3 = 3610_r; - //constexpr real_t B4 = 1107_r; - - real_t U; - real_t U_1; - real_t U_2; - real_t U_3; - real_t U_4; + real_t tensileEnergy; + real_t shearEnergy; + real_t bendingEnergy; + real_t twistingEnergy; }; -/** - * - * @tparam Accessor - * @param p_idx1 - * @param p_idx2 - * @param ac - * @return vdW adhesion energy - */ + template<typename Accessor> inline void VBondContact::operator()(const size_t p_idx1, @@ -121,28 +113,10 @@ void VBondContact::operator()(const size_t p_idx1, real_t C = 1_r; - /* - //srand(SID_1); - double AA = 0.2 + 0.2 * ((rand() % 1000)/1000); //strain of initiation of stress corrosion - //double BB = 0.01; // width of stress corrosion band - //double DD = 1. + AA/BB; - //double KK = 1 / BB; - //if (((std::fabs((s-a)/s))>AA)&&((std::fabs((s-a)/s))<=AA+BB)) C = DD - std::fabs((s-a)/s) * KK; - //if ((std::fabs((s-a)/s))>AA+BB) C = 0; - if ((std::fabs((s-a)/s))>AA) C = 0; - - // Potential energy - real_t U_1 = C * 0.5 * B1 * (s - a) * (s - a); - real_t U_2 = C * 0.5 * B2 * (nj1 - ni1) * dij + B2; - real_t U_3 = C * B3 * ni1 * nj1 + B3; - real_t U_4 = C * -0.5 * B4 * (ni2 * nj2 + ni3 * nj3) + B4; - real_t U = U_1 + U_2 + U_3 + U_4; - */ - U_1 = 0.5_r * B1 * (s - a) * (s - a); - U_2 = B2 * (0.5_r * (nj1 - ni1) * dij - 0.25_r * ni1 * nj1 + 0.75_r); - U_3 = (0.25_r * B2 + B3 + 0.5_r * B4) * (ni1 * nj1 + 1_r); - U_4 = -0.5_r * B4 * (ni1 * nj1 + ni2 * nj2 + ni3 * nj3 - 1_r); - U = U_1 + U_2 + U_3 + U_4; + tensileEnergy = 0.5_r * B1 * (s - a) * (s - a); + shearEnergy = B2 * (0.5_r * (nj1 - ni1) * dij - 0.25_r * ni1 * nj1 + 0.75_r); + bendingEnergy = (0.25_r * B2 + B3 + 0.5_r * B4) * (ni1 * nj1 + 1_r); + twistingEnergy = -0.5_r * B4 * (ni1 * nj1 + ni2 * nj2 + ni3 * nj3 - 1_r); Vec3 rij = dij; @@ -158,7 +132,7 @@ void VBondContact::operator()(const size_t p_idx1, addTorqueAtomic(p_idx2, ac, Mji); } -} //namespace VBondModel +} //namespace cnt } //namespace kernel } //namespace mesa_pd } //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp index 941b4c285..796eca106 100644 --- a/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp +++ b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp @@ -23,7 +23,7 @@ #include <mesa_pd/data/ParticleAccessor.h> #include <mesa_pd/data/ParticleStorage.h> -#include <mesa_pd/kernel/VBondModel/VBondContact.h> +#include <mesa_pd/kernel/cnt/VBondContact.h> #include <core/Environment.h> #include <core/logging/Logging.h> @@ -61,7 +61,7 @@ int main( int argc, char ** argv ) data::ParticleAccessor accessor(ps); //init kernels - kernel::VBondModel::VBondContact vbond; + kernel::cnt::VBondContact vbond; //check equilibrium distance vbond(0, 1, accessor); -- GitLab From e488bad556ddd78766300ce7bd08cf30c58d9081 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 3 Feb 2021 15:31:44 +0100 Subject: [PATCH 54/83] moved VBondContact from VBond to cnt --- tests/mesa_pd/CMakeLists.txt | 6 +++--- .../kernel/{VBondModel => cnt}/VBondContact.test.cpp | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename tests/mesa_pd/kernel/{VBondModel => cnt}/VBondContact.test.cpp (100%) diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index f68304f20..310062c6d 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -87,6 +87,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_ClearNextNeighborSync PROCESSES 2 ) waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact FILES kernel/cnt/IsotropicVDWContact.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_VBondContact FILES kernel/cnt/VBondContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_VBondContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSD FILES kernel/CoefficientOfRestitutionSD.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDEuler COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDVelocityVerlet COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> --useVV ) @@ -167,9 +170,6 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) -waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_VBondContact FILES kernel/VBondModel/VBondContact.test.cpp DEPENDS core ) -waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_VBondContact ) - waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping FILES kernel/VBondModel/ViscousDamping.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping ) diff --git a/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp b/tests/mesa_pd/kernel/cnt/VBondContact.test.cpp similarity index 100% rename from tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp rename to tests/mesa_pd/kernel/cnt/VBondContact.test.cpp -- GitLab From 7318dc56b008421789a3b5fc17dfa6dc620c7ca5 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 3 Feb 2021 15:46:17 +0100 Subject: [PATCH 55/83] added vtk output to VBondModel benchmark --- apps/benchmarks/CNT/VBondModel.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/benchmarks/CNT/VBondModel.cpp b/apps/benchmarks/CNT/VBondModel.cpp index 091327c2f..048ba24ef 100644 --- a/apps/benchmarks/CNT/VBondModel.cpp +++ b/apps/benchmarks/CNT/VBondModel.cpp @@ -27,9 +27,11 @@ #include "mesa_pd/kernel/cnt/Parameters.h" #include "mesa_pd/kernel/cnt/VBondContact.h" #include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" #include "core/Environment.h" #include "core/math/Constants.h" +#include "vtk/VTKOutput.h" namespace walberla { using namespace walberla::mesa_pd; @@ -62,6 +64,17 @@ int main(int argc, char **argv) } data::Particle &&last_segment = *(ps->end() - 1); + WALBERLA_LOG_INFO_ON_ROOT("setting up VTK output"); + auto vtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + vtkOutput->addOutput<data::SelectParticlePosition>("position"); + auto vtkWriter = walberla::vtk::createVTKOutput_PointData(vtkOutput, + "cnt", + 1, + "vtk", + "particles", + false, + false); + WALBERLA_LOG_INFO_ON_ROOT("setting up interaction models"); kernel::cnt::VBondContact vbond; kernel::VelocityVerletPreForceUpdate vv_pre(kernel::cnt::dT); @@ -73,6 +86,8 @@ int main(int argc, char **argv) std::ofstream fout("output.txt"); for (auto i = 0; i < numSimulationSteps; ++i) { + vtkWriter->write(); + ps->forEachParticle(false, kernel::SelectAll(), ac, -- GitLab From 88b5df1c0e1f36b34a096b2d18d4d00256aaaaa1 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Thu, 4 Feb 2021 16:11:35 +0100 Subject: [PATCH 56/83] added check macros to vbondmodel benchmark --- apps/benchmarks/CNT/CMakeLists.txt | 2 ++ apps/benchmarks/CNT/VBondModel.cpp | 35 ++++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/apps/benchmarks/CNT/CMakeLists.txt b/apps/benchmarks/CNT/CMakeLists.txt index 320d0ce94..5fc6f783f 100644 --- a/apps/benchmarks/CNT/CMakeLists.txt +++ b/apps/benchmarks/CNT/CMakeLists.txt @@ -1,3 +1,5 @@ waLBerla_add_executable ( NAME VBondModel FILES VBondModel.cpp DEPENDS core mesa_pd ) +#waLBerla_execute_test( NAME MESA_PD_CNT_VBondModel +# COMMAND $<TARGET_FILE:VBondModel> ) diff --git a/apps/benchmarks/CNT/VBondModel.cpp b/apps/benchmarks/CNT/VBondModel.cpp index 048ba24ef..de90df0ce 100644 --- a/apps/benchmarks/CNT/VBondModel.cpp +++ b/apps/benchmarks/CNT/VBondModel.cpp @@ -54,7 +54,7 @@ int main(int argc, char **argv) for (auto i = 0; i < 10; ++i) { data::Particle &&p = *ps->create(); - p.setPosition(Vec3(0_r, 0_r, real_c(i) * 13.56_r)); + p.setPosition(Vec3(500_r, 500_r, 500_r + real_c(i) * 13.56_r)); p.setSegmentID(i); p.setClusterID(1); if (i == 0) @@ -82,7 +82,13 @@ int main(int argc, char **argv) WALBERLA_LOG_INFO_ON_ROOT("running simulation"); auto appliedForce = Vec3(1_r, 0_r, 0_r); - auto appliedTorque = Vec3(0_r); + auto appliedTorque = Vec3(0_r, 0_r, 1_r); + + real_t tensileEnergy = 0_r; + real_t shearEnergy = 0_r; + real_t bendingEnergy = 0_r; + real_t twistingEnergy = 0_r; + std::ofstream fout("output.txt"); for (auto i = 0; i < numSimulationSteps; ++i) { @@ -98,16 +104,18 @@ int main(int argc, char **argv) last_segment.setTorque(appliedTorque); constexpr auto cutoff2 = kernel::cnt::outer_radius * kernel::cnt::outer_radius; - real_t tensileEnergy = 0_r; - real_t shearEnergy = 0_r; - real_t bendingEnergy = 0_r; - real_t twistingEnergy = 0_r; + tensileEnergy = 0_r; + shearEnergy = 0_r; + bendingEnergy = 0_r; + twistingEnergy = 0_r; ps->forEachParticlePairHalf(false, kernel::SelectAll(), ac, - [&](size_t p_idx1, size_t p_idx2, Accessor &ac) + [&](size_t p_idx1, size_t p_idx2) { + if (ac.getClusterID(p_idx1) != ac.getClusterID(p_idx2)) return; + if (std::abs(ac.getSegmentID(p_idx1) - ac.getSegmentID(p_idx2)) != 1) return; if ((ac.getPosition(p_idx1) - ac.getPosition(p_idx2)).sqrLength() < cutoff2) { vbond(p_idx1, p_idx2, ac); @@ -116,8 +124,7 @@ int main(int argc, char **argv) bendingEnergy += vbond.bendingEnergy; twistingEnergy += vbond.twistingEnergy; } - }, - ac); + }); ps->forEachParticle(false, kernel::SelectAll(), @@ -133,11 +140,21 @@ int main(int argc, char **argv) << std::endl; } + WALBERLA_CHECK_FLOAT_EQUAL(tensileEnergy, 1.88111638964774328e-02_r); + WALBERLA_CHECK_FLOAT_EQUAL(shearEnergy, 2.04795345750102054e-01_r); + WALBERLA_CHECK_FLOAT_EQUAL(bendingEnergy, 3.28859587360327978e+01_r); + WALBERLA_CHECK_FLOAT_EQUAL(twistingEnergy, 1.44177931971837983e-03_r); + return EXIT_SUCCESS; } } // namespace walberla int main(int argc, char *argv[]) { + if (std::is_same<walberla::real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } return walberla::main(argc, argv); } -- GitLab From 75fbf89f14c4e9065dd81728c9c893b03f754324 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 5 Feb 2021 10:27:49 +0100 Subject: [PATCH 57/83] vbond test now checks attraction and repulsion --- .../mesa_pd/kernel/cnt/VBondContact.test.cpp | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/tests/mesa_pd/kernel/cnt/VBondContact.test.cpp b/tests/mesa_pd/kernel/cnt/VBondContact.test.cpp index 796eca106..f0f945883 100644 --- a/tests/mesa_pd/kernel/cnt/VBondContact.test.cpp +++ b/tests/mesa_pd/kernel/cnt/VBondContact.test.cpp @@ -45,6 +45,8 @@ int main( int argc, char ** argv ) return EXIT_SUCCESS; } + using Interaction = kernel::cnt::VBondContact; + //init data structures auto ps = std::make_shared<data::ParticleStorage>(100); @@ -54,19 +56,34 @@ int main( int argc, char ** argv ) p1.getTypeRef() = 0; data::Particle&& p2 = *ps->create(); - p2.getPositionRef() = Vec3(0,0,0); + p2.getPositionRef() = Vec3(Interaction::a,0,0); p2.getForceRef() = Vec3(0,0,0); p2.getTypeRef() = 0; data::ParticleAccessor accessor(ps); //init kernels - kernel::cnt::VBondContact vbond; - - //check equilibrium distance - vbond(0, 1, accessor); - WALBERLA_CHECK_FLOAT_EQUAL( p1.getForce(), Vec3(0,0,0) ); - WALBERLA_CHECK_FLOAT_EQUAL( p2.getForce(), Vec3(0,0,0) ); + Interaction vbond; + + auto calcForce = [&](const Vec3 pos1, const Vec3 pos2) { + p1.setPosition(pos1); + p2.setPosition(pos2); + clear(p1.getForceRef()); + clear(p2.getForceRef()); + vbond(0, 1, accessor); + WALBERLA_CHECK_FLOAT_EQUAL(p1.getForce(), -p2.getForce()); + return p1.getForce(); + }; + + const Vec3 randomNormal = Vec3(1_r, 2_r, 3_r).getNormalized(); + + WALBERLA_LOG_INFO("checking repulsion - equilibrium - attraction"); + WALBERLA_CHECK_LESS (dot(randomNormal, calcForce(Vec3(0), randomNormal * (Interaction::a - 1_r))), + 0_r); + WALBERLA_CHECK_FLOAT_EQUAL(dot(randomNormal, calcForce(Vec3(0), randomNormal * Interaction::a)), + 0_r); + WALBERLA_CHECK_GREATER (dot(randomNormal, calcForce(Vec3(0), randomNormal * (Interaction::a + 1_r))), + 0_r); return EXIT_SUCCESS; } -- GitLab From d84b6ba7d6f4bd4b3cd0fca89eb6068970b03b2b Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 5 Feb 2021 13:57:28 +0100 Subject: [PATCH 58/83] [BUGFIX] msvc error --- src/mesa_pd/kernel/cnt/VBondContact.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mesa_pd/kernel/cnt/VBondContact.h b/src/mesa_pd/kernel/cnt/VBondContact.h index f245aca1e..2153daa69 100644 --- a/src/mesa_pd/kernel/cnt/VBondContact.h +++ b/src/mesa_pd/kernel/cnt/VBondContact.h @@ -94,7 +94,7 @@ void VBondContact::operator()(const size_t p_idx1, // Fix for the issue of segment's undefined sides real_t sign = ac.getSegmentID(p_idx1) <= ac.getSegmentID(p_idx2) ? 1_r : -1_r; - if (((isPeriodic_[0]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[0] - 1)) or + if (((isPeriodic_[0]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[0] - 1)) || ((isPeriodic_[1]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[1] - 1))) sign = -sign; // special case for periodic fibers -- GitLab From 43358cbee28a7af09263d64e9de456fe7e551940 Mon Sep 17 00:00:00 2001 From: Helen Schottenhamml <helen.schottenhamml@fau.de> Date: Fri, 5 Feb 2021 16:50:09 +0100 Subject: [PATCH 59/83] Allow deeper hierarchies in CMake. --- cmake/waLBerlaFunctions.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake/waLBerlaFunctions.cmake b/cmake/waLBerlaFunctions.cmake index f4c4b1f68..2974ca22d 100644 --- a/cmake/waLBerlaFunctions.cmake +++ b/cmake/waLBerlaFunctions.cmake @@ -99,7 +99,7 @@ function ( waLBerla_add_module ) waLBerla_register_dependency ( ${moduleName} ${ARG_DEPENDS} ) - set_property( TARGET ${moduleName} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} ) + set_property( TARGET ${moduleLibraryName} PROPERTY CXX_STANDARD ${CMAKE_CXX_STANDARD} ) # This property is needed for visual studio to group modules together if( WALBERLA_GROUP_PROJECTS ) -- GitLab From 85be0096a6d4387212aba463162e3598c8bf66d5 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 9 Feb 2021 18:00:21 +0100 Subject: [PATCH 60/83] extend clang-tidy coverage --- .clang-tidy | 3 +- src/blockforest/AABBRefinementSelection.h | 18 ++-- src/blockforest/Block.h | 8 +- src/blockforest/BlockDataHandling.h | 58 ++++++------ src/blockforest/BlockForest.h | 90 +++++++++--------- src/blockforest/BlockID.h | 10 +- src/blockforest/BlockReconstruction.h | 2 +- src/blockforest/GlobalLoadBalancing.h | 26 +++--- src/blockforest/Initialization.h | 4 +- src/blockforest/PhantomBlock.h | 2 +- src/blockforest/SetupBlock.h | 4 +- src/blockforest/SetupBlockForest.h | 22 ++--- src/blockforest/StructuredBlockForest.h | 32 +++---- .../communication/NonUniformPackInfo.h | 4 +- src/blockforest/loadbalancing/Cartesian.h | 2 +- src/boundary/Boundary.h | 2 +- src/boundary/BoundaryHandling.h | 10 +- src/boundary/communication/HandlingPackInfo.h | 12 +-- src/communication/ReducePackInfo.h | 2 +- src/communication/UniformMPIDatatypeInfo.h | 4 +- src/communication/UniformPackInfo.h | 4 +- src/core/Abort.h | 2 +- src/core/Array.h | 4 +- src/core/ConcatIterator.h | 9 +- src/core/NonCopyable.h | 4 +- src/core/Set.h | 4 +- src/core/StringUtility.impl.h | 4 +- src/core/cell/Cell.h | 2 +- src/core/cell/CellArray.h | 4 +- src/core/cell/CellInterval.h | 7 +- src/core/cell/CellVector.h | 6 +- src/core/config/Config.h | 4 +- src/core/config/Iterator.h | 4 +- src/core/debug/CheckFunctions.h | 2 +- src/core/debug/CheckFunctions.impl.h | 4 +- src/core/debug/demangle.h | 2 +- src/core/logging/Logging.h | 2 +- src/core/math/Matrix2.h | 28 ++---- src/core/math/Matrix3.h | 58 ++++-------- src/core/math/MatrixMxN.h | 2 +- src/core/math/Quaternion.h | 14 +-- src/core/math/Vector2.h | 21 +---- src/core/math/Vector3.h | 16 +--- src/core/math/equation_system/Operator.h | 18 ++-- src/core/mpi/BufferSystem.h | 2 +- src/core/mpi/BufferSystemHelper.h | 42 ++++----- src/core/mpi/Gather.h | 2 +- src/core/mpi/Gatherv.h | 10 +- src/core/mpi/MPIWrapper.h | 6 +- src/core/mpi/RecvBuffer.h | 12 +-- src/core/mpi/Reduce.h | 20 ++-- src/core/selectable/SelectableObject.h | 10 +- src/core/selectable/SetSelectableObject.h | 6 +- src/core/singleton/Singleton.h | 4 +- src/core/timing/TimingNode.h | 14 +-- src/core/timing/TimingPool.h | 2 +- src/core/timing/TimingTree.h | 4 +- src/domain_decomposition/BlockDataHandling.h | 34 +++---- src/domain_decomposition/BlockStorage.h | 10 +- src/domain_decomposition/IBlock.h | 30 +++--- src/domain_decomposition/IBlockID.h | 2 +- .../StructuredBlockStorage.h | 16 ++-- src/executiontree/ExecutionTree.h | 6 +- src/field/EvaluationFilter.h | 2 +- src/field/Field.impl.h | 14 +-- src/field/FlagField.h | 4 +- src/field/GhostLayerField.h | 12 +-- src/field/GhostLayerField.impl.h | 7 +- src/field/StabilityChecker.h | 12 +-- src/field/SymmetryCheck.h | 4 +- src/field/adaptors/AdaptorCreators.h | 2 +- src/field/adaptors/GhostLayerFieldAdaptor.h | 2 +- src/field/allocation/FieldAllocator.h | 20 ++-- src/field/blockforest/BlockDataHandling.h | 32 +++---- src/field/blockforest/GradientRefinement.h | 2 +- src/field/communication/PackInfo.h | 12 +-- src/field/communication/ReducePackInfo.h | 10 +- .../StencilRestrictedMPIDatatypeInfo.h | 10 +- .../communication/StencilRestrictedPackInfo.h | 12 +-- .../communication/UniformMPIDatatypeInfo.h | 10 +- .../UniformPullReductionPackInfo.h | 12 +-- src/field/distributors/DistributorCreators.h | 2 +- .../interpolators/FieldInterpolatorCreators.h | 2 +- src/field/iterators/FieldIterator.impl.h | 12 +-- src/field/refinement/PackInfo.h | 24 ++--- src/field/vtk/FlagFieldMapping.h | 6 +- src/field/vtk/VTKWriter.h | 6 +- src/gather/CellGatherPackInfo.h | 8 +- src/gather/CurveGatherPackInfo.h | 10 +- src/gather/GatherPackInfo.h | 2 +- src/gather/GnuPlotGraphWriter.h | 2 +- src/geometry/bodies/DynamicBody.h | 6 +- .../IndeterminateLeafNode.h | 2 +- .../containment_octree/InsideLeafNode.h | 2 +- src/geometry/containment_octree/LeafNode.h | 2 +- src/geometry/containment_octree/Node.h | 2 +- .../containment_octree/OutsideLeafNode.h | 2 +- src/geometry/initializer/BoundaryFromBody.h | 2 +- .../initializer/BoundaryFromCellInterval.h | 2 +- .../initializer/BoundaryFromDomainBorder.h | 2 +- src/geometry/initializer/BoundaryFromImage.h | 2 +- .../initializer/BoundaryFromVoxelFile.h | 2 +- .../BoundarySetterFlagFieldSpecialization.h | 2 +- src/geometry/initializer/Initializer.h | 2 +- .../initializer/OverlapFieldFromBody.h | 2 +- .../initializer/ScalarFieldFromBody.h | 2 +- .../ScalarFieldFromGrayScaleImage.h | 2 +- .../structured/BasicVoxelFileReader.impl.h | 2 +- src/geometry/structured/GrayScaleImage.h | 2 +- src/geometry/structured/RGBAImage.h | 2 +- src/geometry/structured/extern/lodepng.h | 4 +- src/gui/PropertyTree.h | 4 +- src/gui/PropertyTree.impl.h | 2 +- src/lbm/PerformanceLogger.h | 2 +- src/lbm/blockforest/PostProcessing.h | 22 ++--- src/lbm/boundary/Curved.h | 2 +- src/lbm/boundary/DiffusionDirichlet.h | 4 +- src/lbm/boundary/UBB.h | 4 +- src/lbm/boundary/VelocityBoundary.h | 2 +- src/lbm/field/AddToStorage.h | 16 ++-- src/lbm/field/Density.h | 2 +- src/lbm/field/DensityVelocityCallback.h | 2 +- src/lbm/field/PdfField.h | 4 +- .../initializer/PoiseuilleInitializer.h | 2 +- src/lbm/lattice_model/CollisionModel.h | 2 +- src/lbm/lattice_model/D2Q9.h | 4 +- src/lbm/lattice_model/D3Q15.h | 4 +- src/lbm/lattice_model/D3Q19.h | 4 +- src/lbm/lattice_model/D3Q27.h | 4 +- src/lbm/lattice_model/ForceModel.h | 4 +- src/lbm/lattice_model/LatticeModelBase.h | 2 +- src/lbm/refinement/PdfFieldPackInfo.h | 92 +++++++++---------- src/lbm/refinement/TimeStep.h | 16 ++-- src/lbm/srt/SplitPureSweep.impl.h | 16 ++-- src/lbm/srt/SplitSweep.impl.h | 32 +++---- src/lbm/sweeps/ActiveCellSweep.h | 2 +- src/lbm/trt/SplitPureSweep.impl.h | 16 ++-- src/lbm/trt/SplitSweep.impl.h | 32 +++---- src/lbm/vtk/Density.h | 6 +- src/lbm/vtk/NonEquilibrium.h | 6 +- src/lbm/vtk/VTKOutput.h | 2 +- src/lbm/vtk/Velocity.h | 12 +-- .../utility/SubCyclingManager.h | 2 +- .../AnalyticContactDetection.h | 2 +- src/mesa_pd/collision_detection/BroadPhase.h | 3 +- .../GeneralContactDetection.h | 8 +- src/mesa_pd/data/ContactAccessor.h | 4 +- src/mesa_pd/data/ParticleAccessor.h | 4 +- src/mesa_pd/domain/BlockForestDataHandling.h | 22 ++--- src/mesa_pd/kernel/ParticleSelector.h | 6 +- src/mesa_pd/vtk/OutputSelector.h | 2 +- src/pde/sweeps/Jacobi.h | 8 +- src/pde/sweeps/JacobiFixedStencil.h | 6 +- src/pde/sweeps/RBGS.h | 6 +- src/pde/sweeps/RBGSFixedStencil.h | 4 +- src/pde/sweeps/SOR.h | 6 +- src/pde/sweeps/SORFixedStencil.h | 4 +- src/pe/bg/IBG.h | 2 +- src/pe/bg/SimpleBGDataHandling.h | 2 +- src/pe/ccd/HashGrids.h | 32 +++---- src/pe/ccd/HashGridsBodyTrait.h | 2 +- src/pe/ccd/HashGridsDataHandling.h | 2 +- src/pe/ccd/ICCD.h | 4 +- src/pe/ccd/SimpleCCD.h | 6 +- src/pe/ccd/SimpleCCDDataHandling.h | 2 +- src/pe/cr/DEM.h | 10 +- src/pe/cr/DEM.impl.h | 12 +-- src/pe/cr/HCSITS.h | 10 +- src/pe/cr/HCSITS.impl.h | 74 +++++++-------- src/pe/cr/ICR.h | 2 +- src/pe/cr/PlainIntegrator.h | 6 +- src/pe/cr/PlainIntegrator.impl.h | 8 +- src/pe/fcd/GenericFCD.h | 2 +- src/pe/fcd/IFCD.h | 2 +- src/pe/fcd/SimpleFCD.h | 2 +- src/pe/raytracing/Intersects.h | 10 +- src/pe/raytracing/Lighting.h | 4 +- src/pe/raytracing/Raytracer.h | 36 ++++---- src/pe/raytracing/ShadingParameters.h | 4 +- src/pe/rigidbody/BodyIterators.h | 27 +----- src/pe/rigidbody/Box.h | 16 ++-- src/pe/rigidbody/Capsule.h | 14 +-- src/pe/rigidbody/CylindricalBoundary.h | 10 +- src/pe/rigidbody/Ellipsoid.h | 14 +-- src/pe/rigidbody/GeomPrimitive.h | 2 +- src/pe/rigidbody/MPIRigidBodyTrait.h | 6 +- src/pe/rigidbody/Plane.h | 24 ++--- src/pe/rigidbody/RigidBody.h | 2 +- src/pe/rigidbody/RigidBodyCastIterator.h | 4 +- src/pe/rigidbody/RigidBodyIterator.h | 4 +- src/pe/rigidbody/Sphere.h | 14 +-- src/pe/rigidbody/Squirmer.h | 2 +- src/pe/rigidbody/StorageDataHandling.h | 22 ++--- src/pe/rigidbody/Union.h | 34 +++---- src/pe/rigidbody/UnionFactory.h | 12 +-- src/pe/synchronization/SyncForces.h | 4 +- src/pe/synchronization/SyncNextNeighbors.h | 16 ++-- src/pe/synchronization/SyncShadowOwners.h | 18 ++-- src/pe/utility/BodyCast.h | 2 +- src/pe/vtk/BodyVtkOutput.h | 10 +- src/pe/vtk/EllipsoidVtkOutput.h | 10 +- src/pe/vtk/SphereVtkOutput.h | 10 +- .../gns_lbm/GNSSweep.h | 6 +- .../PSMSweep.h | 10 +- src/timeloop/ITimeloop.h | 2 +- src/timeloop/SelectableFunctionCreators.h | 6 +- src/timeloop/SweepTimeloop.h | 6 +- src/timeloop/Timeloop.h | 20 ++-- src/vtk/BlockCellDataWriter.h | 20 ++-- src/vtk/DumpBlockStructureLevel.h | 4 +- src/vtk/DumpBlockStructureProcess.h | 4 +- src/vtk/Initialization.h | 2 +- src/vtk/PointDataSource.h | 2 +- src/vtk/PolylineDataSource.h | 2 +- src/vtk/VTKOutput.h | 10 +- tests/core/FunctionTraitsTest.cpp | 2 +- tests/core/mpi/ReduceTest.cpp | 16 ++-- tests/mesa_pd/domain/BlockForestDomain.cpp | 4 +- .../ExplicitEulerInterfaceCheck.cpp | 2 +- .../ExplicitEulerWithShapeInterfaceCheck.cpp | 2 +- .../interfaces/ForceLJInterfaceCheck.cpp | 2 +- .../HeatConductionInterfaceCheck.cpp | 2 +- .../interfaces/PFCDampingInterfaceCheck.cpp | 2 +- .../SemiImplicitEulerInterfaceCheck.cpp | 2 +- .../SpringDashpotInterfaceCheck.cpp | 2 +- .../TemperatureIntegrationInterfaceCheck.cpp | 2 +- .../VelocityVerletInterfaceCheck.cpp | 2 +- .../VelocityVerletWithShapeInterfaceCheck.cpp | 2 +- .../TaylorCouetteFlowMEM.cpp | 2 +- 229 files changed, 1009 insertions(+), 1122 deletions(-) diff --git a/.clang-tidy b/.clang-tidy index 00ffd56f0..7127535c8 100644 --- a/.clang-tidy +++ b/.clang-tidy @@ -65,7 +65,6 @@ readability-use-anyofallof ' WarningsAsErrors: '*' -HeaderFilterRegex: '' -AnalyzeTemporaryDtors: false +HeaderFilterRegex: '.*' ... diff --git a/src/blockforest/AABBRefinementSelection.h b/src/blockforest/AABBRefinementSelection.h index fc454bedc..45847dca5 100644 --- a/src/blockforest/AABBRefinementSelection.h +++ b/src/blockforest/AABBRefinementSelection.h @@ -40,7 +40,7 @@ class AABBRefinementSelection { public: - AABBRefinementSelection(){} + AABBRefinementSelection()= default; AABBRefinementSelection( const Config::BlockHandle & configBlock ) { @@ -74,12 +74,12 @@ public: void addAABB( const math::AABB & aabb, const uint_t level ) { - aabbs_.push_back( std::make_pair( aabb, level ) ); + aabbs_.emplace_back( aabb, level ); } void addRegion( const math::AABB & region, const uint_t level ) { - regions_.push_back( std::make_pair( region, level ) ); + regions_.emplace_back( region, level ); } // for static refinement @@ -144,12 +144,12 @@ private: std::vector< std::pair< math::AABB, uint_t > > aabbs; for( auto region = regions_.begin(); region != regions_.end(); ++region ) { - aabbs.push_back( std::make_pair( math::AABB( simulationDomain.xMin() + region->first.xMin() * simulationDomain.xSize(), - simulationDomain.yMin() + region->first.yMin() * simulationDomain.ySize(), - simulationDomain.zMin() + region->first.zMin() * simulationDomain.zSize(), - simulationDomain.xMin() + region->first.xMax() * simulationDomain.xSize(), - simulationDomain.yMin() + region->first.yMax() * simulationDomain.ySize(), - simulationDomain.zMin() + region->first.zMax() * simulationDomain.zSize() ), region->second ) ); + aabbs.emplace_back( math::AABB( simulationDomain.xMin() + region->first.xMin() * simulationDomain.xSize(), + simulationDomain.yMin() + region->first.yMin() * simulationDomain.ySize(), + simulationDomain.zMin() + region->first.zMin() * simulationDomain.zSize(), + simulationDomain.xMin() + region->first.xMax() * simulationDomain.xSize(), + simulationDomain.yMin() + region->first.yMax() * simulationDomain.ySize(), + simulationDomain.zMin() + region->first.zMax() * simulationDomain.zSize() ), region->second ); } return aabbs; } diff --git a/src/blockforest/Block.h b/src/blockforest/Block.h index 39d958b7e..caf87d623 100644 --- a/src/blockforest/Block.h +++ b/src/blockforest/Block.h @@ -79,14 +79,14 @@ public: Block( BlockForest & forest, const BlockID & id, const AABB & aabb, const uint_t level, mpi::RecvBuffer & buffer, const std::function< uint_t ( const uint_t ) > & processMapping = std::function< uint_t ( const uint_t ) >() ); - virtual ~Block() {} + ~Block() override = default; void toBuffer( mpi::SendBuffer & buffer ) const; const BlockForest & getForest() const { return forest_; } BlockForest & getForest() { return forest_; } - const BlockID & getId() const { return id_; } + const BlockID & getId() const override { return id_; } uint_t getProcess() const; uint_t getLevel() const { return level_; } @@ -135,7 +135,7 @@ public: protected: - bool equal( const IBlock* rhs ) const; + bool equal( const IBlock* rhs ) const override; private: @@ -296,7 +296,7 @@ inline void Block::addNeighbor( const BlockID & id, const uint_t process, const WALBERLA_ASSERT( neighborhood_[i].getId() < id || id < neighborhood_[i].getId() ); #endif - neighborhood_.push_back( NeighborBlock( forest_, id, process, state ) ); + neighborhood_.emplace_back( forest_, id, process, state ); } diff --git a/src/blockforest/BlockDataHandling.h b/src/blockforest/BlockDataHandling.h index c947b3e03..be978d3a8 100644 --- a/src/blockforest/BlockDataHandling.h +++ b/src/blockforest/BlockDataHandling.h @@ -36,7 +36,7 @@ template< typename T > class BlockDataHandling : public domain_decomposition::BlockDataHandling<T> { public: - virtual ~BlockDataHandling() {} + ~BlockDataHandling() override = default; /// must be thread-safe ! virtual void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) = 0; @@ -60,19 +60,19 @@ template< typename T > class AlwaysInitializeBlockDataHandling : public BlockDataHandling<T> { public: - ~AlwaysInitializeBlockDataHandling() {} + ~AlwaysInitializeBlockDataHandling() override = default; - void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) {} - void serializeCoarseToFine( Block * const, const BlockDataID &, mpi::SendBuffer &, const uint_t ) {} - void serializeFineToCoarse( Block * const, const BlockDataID &, mpi::SendBuffer & ) {} + void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) override {} + void serializeCoarseToFine( Block * const, const BlockDataID &, mpi::SendBuffer &, const uint_t ) override {} + void serializeFineToCoarse( Block * const, const BlockDataID &, mpi::SendBuffer & ) override {} - T * deserialize( IBlock * const block ) { return this->initialize( block ); } - T * deserializeCoarseToFine( Block * const block ) { return this->initialize( block ); } - T * deserializeFineToCoarse( Block * const block ) { return this->initialize( block ); } + T * deserialize( IBlock * const block ) override { return this->initialize( block ); } + T * deserializeCoarseToFine( Block * const block ) override { return this->initialize( block ); } + T * deserializeFineToCoarse( Block * const block ) override { return this->initialize( block ); } - void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) {} - void deserializeCoarseToFine( Block * const, const BlockDataID &, mpi::RecvBuffer & ) {} - void deserializeFineToCoarse( Block * const, const BlockDataID &, mpi::RecvBuffer &, const uint_t ) {} + void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) override {} + void deserializeCoarseToFine( Block * const, const BlockDataID &, mpi::RecvBuffer & ) override {} + void deserializeFineToCoarse( Block * const, const BlockDataID &, mpi::RecvBuffer &, const uint_t ) override {} }; @@ -81,9 +81,9 @@ template< typename T > class AlwaysCreateBlockDataHandling : public AlwaysInitializeBlockDataHandling<T> { public: - ~AlwaysCreateBlockDataHandling() {} + ~AlwaysCreateBlockDataHandling() override = default; - T * initialize( IBlock * const /*block*/ ) {return new T();} + T * initialize( IBlock * const /*block*/ ) override {return new T();} }; @@ -97,7 +97,7 @@ class BlockDataHandlingWrapper : public domain_decomposition::internal::BlockDat public: typedef domain_decomposition::internal::BlockData BlockData; - virtual ~BlockDataHandlingWrapper() {} + ~BlockDataHandlingWrapper() override = default; virtual void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) = 0; virtual void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) = 0; @@ -118,67 +118,67 @@ public: typedef domain_decomposition::internal::BlockData BlockData; BlockDataHandlingHelper( const shared_ptr< BlockDataHandling<T> > & dataHandling ) : dataHandling_( dataHandling ) {} - ~BlockDataHandlingHelper() {} + ~BlockDataHandlingHelper() override = default; - BlockData * initialize( IBlock * const block ) + BlockData * initialize( IBlock * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->initialize( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) + void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->serialize( block, id, buffer ); } - void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->serializeCoarseToFine( block, id, buffer, child ); } - void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->serializeFineToCoarse( block, id, buffer ); } - BlockData * deserialize( IBlock * const block ) + BlockData * deserialize( IBlock * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->deserialize( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - BlockData * deserializeCoarseToFine( Block * const block ) + BlockData * deserializeCoarseToFine( Block * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->deserializeCoarseToFine( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - BlockData * deserializeFineToCoarse( Block * const block ) + BlockData * deserializeFineToCoarse( Block * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->deserializeFineToCoarse( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->deserialize( block, id, buffer ); } - void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->deserializeCoarseToFine( block, id, buffer ); } - void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->deserializeFineToCoarse( block, id, buffer, child ); diff --git a/src/blockforest/BlockForest.h b/src/blockforest/BlockForest.h index b0731c115..bd66ced43 100644 --- a/src/blockforest/BlockForest.h +++ b/src/blockforest/BlockForest.h @@ -179,13 +179,13 @@ public: bool getState( Set<SUID>& state, const BlockID& id ) const { const Node* node = getNode( id ); if( node ) { state = node->state_; return true; } return false; } - bool exists( const real_t x, const real_t y, const real_t z ) const { return getNode(x,y,z) != NULL; } - bool exists( const BlockID& id ) const { return getNode( id ) != NULL; } + bool exists( const real_t x, const real_t y, const real_t z ) const { return getNode(x,y,z) != nullptr; } + bool exists( const BlockID& id ) const { return getNode( id ) != nullptr; } bool existsRemotely( const real_t x, const real_t y, const real_t z ) const - { const Node* node = getNode( x, y, z ); return ( node != NULL && node->process_ != forest_.getProcess() ); } + { const Node* node = getNode( x, y, z ); return ( node != nullptr && node->process_ != forest_.getProcess() ); } bool existsRemotely( const BlockID& id ) const - { const Node* node = getNode( id ); return ( node != NULL && node->process_ != forest_.getProcess() ); } + { const Node* node = getNode( id ); return ( node != nullptr && node->process_ != forest_.getProcess() ); } bool getId( BlockID& id, const real_t x, const real_t y, const real_t z ) const; @@ -197,10 +197,10 @@ public: bool getRootBlockState( Set<SUID>& state, const uint_t x, const uint_t y, const uint_t z ) const { const Node* node = getRootNode(x,y,z); if( node ) { state = node->state_; return true; } return false; } - bool rootBlockExists( const uint_t x, const uint_t y, const uint_t z ) const { return getRootNode(x,y,z) != NULL; } + bool rootBlockExists( const uint_t x, const uint_t y, const uint_t z ) const { return getRootNode(x,y,z) != nullptr; } bool rootBlockExistsRemotely( const uint_t x, const uint_t y, const uint_t z ) const - { const Node* node = getRootNode(x,y,z); return ( node != NULL && node->process_ != forest_.getProcess() ); } + { const Node* node = getRootNode(x,y,z); return ( node != nullptr && node->process_ != forest_.getProcess() ); } private: @@ -210,7 +210,7 @@ public: const Node * getRootNode( const uint_t x, const uint_t y, const uint_t z ) const { const uint_t index = z * forest_.getYSize() * forest_.getXSize() + y * forest_.getXSize() + x; if( index >= nodes_.size() ) - return NULL; + return nullptr; return nodes_[ index ].get(); } @@ -223,7 +223,7 @@ public: BlockForest( const uint_t process, const SetupBlockForest& forest, const bool keepGlobalBlockInformation = false ); BlockForest( const uint_t process, const char* const filename, const bool broadcastFile = true, const bool keepGlobalBlockInformation = false ); - ~BlockForest() {} + ~BlockForest() override = default; uint_t getProcess() const { return process_; } uint_t getProcessIdBytes() const { return processIdBytes_; } @@ -277,45 +277,45 @@ public: inline void getBlocks( std::vector< const Block* >& blocks, const uint_t level ) const; inline void getBlocks( std::vector< Block* >& blocks, const uint_t level ); - inline void getBlocksContainedWithinAABB( std::vector< const IBlock* >& blocks, const AABB& aabb ) const; - inline void getBlocksContainedWithinAABB( std::vector< IBlock* >& blocks, const AABB& aabb ); + inline void getBlocksContainedWithinAABB( std::vector< const IBlock* >& blocks, const AABB& aabb ) const override; + inline void getBlocksContainedWithinAABB( std::vector< IBlock* >& blocks, const AABB& aabb ) override; - inline void getBlocksOverlappedByAABB( std::vector< const IBlock* >& blocks, const AABB& aabb ) const; - inline void getBlocksOverlappedByAABB( std::vector< IBlock* >& blocks, const AABB& aabb ); + inline void getBlocksOverlappedByAABB( std::vector< const IBlock* >& blocks, const AABB& aabb ) const override; + inline void getBlocksOverlappedByAABB( std::vector< IBlock* >& blocks, const AABB& aabb ) override; using BlockStorage::getBlock; - inline const Block* getBlock( const IBlockID& id ) const; - inline Block* getBlock( const IBlockID& id ); + inline const Block* getBlock( const IBlockID& id ) const override; + inline Block* getBlock( const IBlockID& id ) override; - inline const Block* getBlock( const real_t x, const real_t y, const real_t z ) const; - inline Block* getBlock( const real_t x, const real_t y, const real_t z ); + inline const Block* getBlock( const real_t x, const real_t y, const real_t z ) const override; + inline Block* getBlock( const real_t x, const real_t y, const real_t z ) override; inline const Block* getRootBlock( const uint_t x, const uint_t y, const uint_t z ) const; inline Block* getRootBlock( const uint_t x, const uint_t y, const uint_t z ); - bool containsGlobalBlockInformation() const { return blockInformation_->active(); } + bool containsGlobalBlockInformation() const override { return blockInformation_->active(); } - inline void getAllBlocks( std::vector< shared_ptr< IBlockID > >& blocks ) const; + inline void getAllBlocks( std::vector< shared_ptr< IBlockID > >& blocks ) const override; - inline bool blockExists ( const real_t x, const real_t y, const real_t z ) const; - inline bool blockExistsLocally ( const real_t x, const real_t y, const real_t z ) const; - inline bool blockExistsRemotely( const real_t x, const real_t y, const real_t z ) const; + inline bool blockExists ( const real_t x, const real_t y, const real_t z ) const override; + inline bool blockExistsLocally ( const real_t x, const real_t y, const real_t z ) const override; + inline bool blockExistsRemotely( const real_t x, const real_t y, const real_t z ) const override; - inline bool blockExists ( const IBlockID& id ) const; - inline bool blockExistsLocally ( const IBlockID& id ) const; - inline bool blockExistsRemotely( const IBlockID& id ) const; + inline bool blockExists ( const IBlockID& id ) const override; + inline bool blockExistsLocally ( const IBlockID& id ) const override; + inline bool blockExistsRemotely( const IBlockID& id ) const override; inline bool rootBlockExists ( const uint_t x, const uint_t y, const uint_t z ) const; inline bool rootBlockExistsLocally ( const uint_t x, const uint_t y, const uint_t z ) const; inline bool rootBlockExistsRemotely( const uint_t x, const uint_t y, const uint_t z ) const; - void getBlockID( IBlockID& id, const real_t x, const real_t y, const real_t z ) const; - void getAABB ( AABB& aabb, const IBlockID& id ) const; - void getState ( Set<SUID>& state, const IBlockID& id ) const; - void getProcessRank( uint_t& rank, const IBlockID& id ) const; + void getBlockID( IBlockID& id, const real_t x, const real_t y, const real_t z ) const override; + void getAABB ( AABB& aabb, const IBlockID& id ) const override; + void getState ( Set<SUID>& state, const IBlockID& id ) const override; + void getProcessRank( uint_t& rank, const IBlockID& id ) const override; void getRootBlockAABB ( AABB& aabb, const uint_t x, const uint_t y, const uint_t z ) const; void getRootBlockState ( Set<SUID>& state, const uint_t x, const uint_t y, const uint_t z ) const; @@ -324,7 +324,7 @@ public: const BlockInformation & getBlockInformation() const { return *blockInformation_; } - inline uint_t getLevel( const IBlock& block ) const; + inline uint_t getLevel( const IBlock& block ) const override; inline uint_t getLevelFromBlockId( const BlockID& id ) const; inline uint_t getAABBFromBlockId( AABB& aabb, const BlockID& id ) const; inline AABB getAABBFromBlockId( const BlockID& id ) const; @@ -338,9 +338,9 @@ public: bool insertBuffersIntoProcessNetwork() const { return insertBuffersIntoProcessNetwork_; } const std::vector< uint_t > & getNeighborhood() const { return neighborhood_; } - const std::vector< uint_t > & getNeighboringProcesses() const { return getNeighborhood(); } + const std::vector< uint_t > & getNeighboringProcesses() const override { return getNeighborhood(); } - std::map< uint_t, std::vector< Vector3<real_t> > > getNeighboringProcessOffsets() const; + std::map< uint_t, std::vector< Vector3<real_t> > > getNeighboringProcessOffsets() const override; @@ -484,7 +484,7 @@ public: protected: - bool equal( const BlockStorage* rhs ) const; + bool equal( const BlockStorage* rhs ) const override; void addBlockData( IBlock * const block, const BlockDataID & index, domain_decomposition::internal::BlockData * const data ) { BlockStorage::addBlockData( block, index, data ); } @@ -643,7 +643,7 @@ inline const Block* BlockForest::getBlock( const IBlockID& id ) const { if( it != blocks_.end() ) return it->second.get(); - return NULL; + return nullptr; } @@ -657,7 +657,7 @@ inline Block* BlockForest::getBlock( const IBlockID& id ) { if( it != blocks_.end() ) return it->second.get(); - return NULL; + return nullptr; } @@ -667,7 +667,7 @@ inline const Block* BlockForest::getBlock( const real_t x, const real_t y, const for( auto it = blocks_.begin(); it != blocks_.end(); ++it ) if( it->second->getAABB().contains(x,y,z) ) return it->second.get(); - return NULL; + return nullptr; } @@ -677,7 +677,7 @@ inline Block* BlockForest::getBlock( const real_t x, const real_t y, const real_ for( auto it = blocks_.begin(); it != blocks_.end(); ++it ) if( it->second->getAABB().contains(x,y,z) ) return it->second.get(); - return NULL; + return nullptr; } @@ -721,14 +721,14 @@ inline bool BlockForest::blockExists( const real_t x, const real_t y, const real if( blockInformation_->active() ) return blockInformation_->exists(x,y,z); - return getBlock(x,y,z) != NULL; + return getBlock(x,y,z) != nullptr; } inline bool BlockForest::blockExistsLocally( const real_t x, const real_t y, const real_t z ) const { - return getBlock(x,y,z) != NULL; + return getBlock(x,y,z) != nullptr; } @@ -738,7 +738,7 @@ inline bool BlockForest::blockExistsRemotely( const real_t x, const real_t y, co if( blockInformation_->active() ) return blockInformation_->existsRemotely(x,y,z); - return getBlock(x,y,z) == NULL; + return getBlock(x,y,z) == nullptr; } @@ -750,14 +750,14 @@ inline bool BlockForest::blockExists( const IBlockID& id ) const { if( blockInformation_->active() ) return blockInformation_->exists( *static_cast< const BlockID* >( &id ) ); - return getBlock( id ) != NULL; + return getBlock( id ) != nullptr; } inline bool BlockForest::blockExistsLocally( const IBlockID& id ) const { - return getBlock( id ) != NULL; + return getBlock( id ) != nullptr; } @@ -769,7 +769,7 @@ inline bool BlockForest::blockExistsRemotely( const IBlockID& id ) const { if( blockInformation_->active() ) return blockInformation_->existsRemotely( *static_cast< const BlockID* >( &id ) ); - return getBlock( id ) == NULL; + return getBlock( id ) == nullptr; } @@ -779,14 +779,14 @@ inline bool BlockForest::rootBlockExists( const uint_t x, const uint_t y, const if( blockInformation_->active() ) return blockInformation_->rootBlockExists(x,y,z); - return getRootBlock(x,y,z) != NULL; + return getRootBlock(x,y,z) != nullptr; } inline bool BlockForest::rootBlockExistsLocally( const uint_t x, const uint_t y, const uint_t z ) const { - return getRootBlock(x,y,z) != NULL; + return getRootBlock(x,y,z) != nullptr; } @@ -796,7 +796,7 @@ inline bool BlockForest::rootBlockExistsRemotely( const uint_t x, const uint_t y if( blockInformation_->active() ) return blockInformation_->rootBlockExistsRemotely(x,y,z); - return getRootBlock(x,y,z) == NULL; + return getRootBlock(x,y,z) == nullptr; } diff --git a/src/blockforest/BlockID.h b/src/blockforest/BlockID.h index ff64a5b19..d4efc6bcc 100644 --- a/src/blockforest/BlockID.h +++ b/src/blockforest/BlockID.h @@ -283,18 +283,18 @@ public: void removeBranchId() { WALBERLA_ASSERT_GREATER_EQUAL( getUsedBits(), uint_c(4) ); id_ >>= 3; } uint_t getBranchId() const { WALBERLA_ASSERT_GREATER_EQUAL( getUsedBits(), uint_c(4) ); return id_ & uint_c(7); } - bool operator< ( const IBlockID& rhs ) const + bool operator< ( const IBlockID& rhs ) const override { WALBERLA_ASSERT_EQUAL( dynamic_cast< const BlockID* >( &rhs ), &rhs ); return id_ < static_cast< const BlockID* >( &rhs )->id_; } bool operator> ( const IBlockID& rhs ) const { WALBERLA_ASSERT_EQUAL( dynamic_cast< const BlockID* >( &rhs ), &rhs ); return id_ > static_cast< const BlockID* >( &rhs )->id_; } - bool operator==( const IBlockID& rhs ) const + bool operator==( const IBlockID& rhs ) const override { WALBERLA_ASSERT_EQUAL( dynamic_cast< const BlockID* >( &rhs ), &rhs ); return id_ == static_cast< const BlockID* >( &rhs )->id_; } - bool operator!=( const IBlockID& rhs ) const + bool operator!=( const IBlockID& rhs ) const override { WALBERLA_ASSERT_EQUAL( dynamic_cast< const BlockID* >( &rhs ), &rhs ); return id_ != static_cast< const BlockID* >( &rhs )->id_; } - inline IDType getID() const; + inline IDType getID() const override; - inline std::ostream& toStream( std::ostream& os ) const; + inline std::ostream& toStream( std::ostream& os ) const override; void toByteArray( std::vector< uint8_t >& array, const uint_t offset, const uint_t bytes ) const { uintToByteArray( id_, array, offset, bytes ); } diff --git a/src/blockforest/BlockReconstruction.h b/src/blockforest/BlockReconstruction.h index 68a2aba2f..c41689b94 100644 --- a/src/blockforest/BlockReconstruction.h +++ b/src/blockforest/BlockReconstruction.h @@ -164,7 +164,7 @@ void BlockReconstruction::reconstructNeighborhood( BLOCK* block, const std::vect const NeighborhoodReconstructionBlock* neighbor = &(neighbors[i]); uint_t index = 0; - if( neighborhood.insert( neighbor ).second == true ) { + if( neighborhood.insert( neighbor ).second ) { index = block->getNeighborhoodSize(); neighborhoodIndex[ neighbor ] = index; diff --git a/src/blockforest/GlobalLoadBalancing.h b/src/blockforest/GlobalLoadBalancing.h index 521af77de..ca7c687a9 100644 --- a/src/blockforest/GlobalLoadBalancing.h +++ b/src/blockforest/GlobalLoadBalancing.h @@ -57,7 +57,7 @@ public: public: typedef std::function< memory_t ( const BLOCK* const, const BLOCK* const ) > CommunicationFunction; - MetisConfiguration( const bool _includeMetis = false, const bool _forceMetis = false, CommunicationFunction _communicationFunction = 0, + MetisConfiguration( const bool _includeMetis = false, const bool _forceMetis = false, CommunicationFunction _communicationFunction = nullptr, const real_t _maxUbvec = real_c(1.5), const uint_t _iterations = uint_c(10) ) : includeMetis_( _includeMetis ), forceMetis_( _forceMetis ), communicationFunction_( _communicationFunction ), maxUbvec_( _maxUbvec ), iterations_( _iterations ) {} @@ -103,13 +103,13 @@ public: template< typename BLOCK > static inline uint_t minimizeProcesses( const std::vector< BLOCK* >& blocks, const memory_t memoryLimit, const MetisConfiguration<BLOCK>& metisConfig, - const std::vector< workload_t >* processesWork = NULL, - const std::vector< memory_t >* processesMemory = NULL ); + const std::vector< workload_t >* processesWork = nullptr, + const std::vector< memory_t >* processesMemory = nullptr ); template< typename BLOCK > static inline uint_t maximizeMemoryUtilization( const std::vector< BLOCK* >& blocks, const memory_t memoryLimit, const MetisConfiguration<BLOCK>& metisConfig, - const std::vector< workload_t >* processesWork = NULL, - const std::vector< memory_t >* processesMemory = NULL ); + const std::vector< workload_t >* processesWork = nullptr, + const std::vector< memory_t >* processesMemory = nullptr ); // optimize workload template< typename BLOCK > @@ -130,7 +130,7 @@ private: template< typename BLOCK > static uint_t fixedWork( const std::vector< BLOCK* >& blocks, const workload_t workloadLimit, const memory_t memoryLimit, - const std::vector< workload_t >* processesWork = NULL, const std::vector< memory_t >* processesMemory = NULL ); + const std::vector< workload_t >* processesWork = nullptr, const std::vector< memory_t >* processesMemory = nullptr ); #ifdef WALBERLA_BUILD_WITH_METIS @@ -490,7 +490,7 @@ inline uint_t GlobalLoadBalancing::minimizeProcesses( const std::vector< BLOCK* // minimize number of processes == do not care about the amount of workload that is assigned to a process, // just put as many blocks as possible on any process - workload_t workloadLimit = workloadSum( blocks ) + ( ( processesWork == NULL ) ? static_cast< workload_t >(0) : + workload_t workloadLimit = workloadSum( blocks ) + ( ( processesWork == nullptr ) ? static_cast< workload_t >(0) : math::kahanSummation( processesWork->begin(), processesWork->end() ) ); uint_t numberOfProcesses = fixedWork( blocks, workloadLimit, memoryLimit, processesWork, processesMemory ); @@ -642,7 +642,7 @@ void GlobalLoadBalancing::prepareProcessReordering( const std::vector< BLOCK* > const BLOCK* const block = (*it).second; for( uint_t i = 0; i != block->getNeighborhoodSize(); ++i ) - if( neighbors.insert( block->getNeighborTargetProcess(i) ).second == true ) + if( neighbors.insert( block->getNeighborTargetProcess(i) ).second ) processNeighbors[ uint_c(p) ].push_back( block->getNeighborTargetProcess(i) ); // for( uint_t n = 0; n != 26; ++n ) @@ -673,7 +673,7 @@ void GlobalLoadBalancing::reorderProcessesByBFS( std::vector< BLOCK* > & blocks, uint_t startIndex = numberOfProcesses; for( uint_t i = previousStartIndex; i < numberOfProcesses; ++i ) { - if( !processed[i] && processNeighbors[i].size() != 0 ) + if( !processed[i] && !processNeighbors[i].empty() ) { startIndex = i; break; @@ -741,8 +741,8 @@ uint_t GlobalLoadBalancing::fixedWork( const std::vector< BLOCK* >& blocks, cons WALBERLA_ASSERT_GREATER( memoryLimit , static_cast< memory_t >(0) ); uint_t processes = 0; - workload_t workload = ( processesWork != NULL && processes < processesWork->size() ) ? (*processesWork)[processes] : static_cast< workload_t >(0); - memory_t memory = ( processesMemory != NULL && processes < processesMemory->size() ) ? (*processesMemory)[processes] : static_cast< memory_t >(0); + workload_t workload = ( processesWork != nullptr && processes < processesWork->size() ) ? (*processesWork)[processes] : static_cast< workload_t >(0); + memory_t memory = ( processesMemory != nullptr && processes < processesMemory->size() ) ? (*processesMemory)[processes] : static_cast< memory_t >(0); for( uint_t i = 0; i != blocks.size(); ++i ) { @@ -754,8 +754,8 @@ uint_t GlobalLoadBalancing::fixedWork( const std::vector< BLOCK* >& blocks, cons ++processes; - workload = ( processesWork != NULL && processes < processesWork->size() ) ? (*processesWork)[processes] : static_cast< workload_t >(0); - memory = ( processesMemory != NULL && processes < processesMemory->size() ) ? (*processesMemory)[processes] : static_cast< memory_t >(0); + workload = ( processesWork != nullptr && processes < processesWork->size() ) ? (*processesWork)[processes] : static_cast< workload_t >(0); + memory = ( processesMemory != nullptr && processes < processesMemory->size() ) ? (*processesMemory)[processes] : static_cast< memory_t >(0); } WALBERLA_ASSERT_LESS_EQUAL( blocks[i]->getWorkload() + workload, workloadLimit ); diff --git a/src/blockforest/Initialization.h b/src/blockforest/Initialization.h index 3a87f2811..aecdd20ad 100644 --- a/src/blockforest/Initialization.h +++ b/src/blockforest/Initialization.h @@ -34,11 +34,11 @@ namespace blockforest { shared_ptr< StructuredBlockForest > createUniformBlockGridFromConfig( const shared_ptr< Config > & config, - CellInterval * requestedDomainSize = NULL, + CellInterval * requestedDomainSize = nullptr, const bool keepGlobalBlockInformation = false ); shared_ptr< StructuredBlockForest > createUniformBlockGridFromConfig( const Config::BlockHandle & configBlock, - CellInterval * requestedDomainSize = NULL, + CellInterval * requestedDomainSize = nullptr, const bool keepGlobalBlockInformation = false ); diff --git a/src/blockforest/PhantomBlock.h b/src/blockforest/PhantomBlock.h index 0df698690..2d6c2b6ee 100644 --- a/src/blockforest/PhantomBlock.h +++ b/src/blockforest/PhantomBlock.h @@ -304,7 +304,7 @@ inline void PhantomBlock::addNeighbor( const BlockID & id, const uint_t process, WALBERLA_ASSERT( neighborhood_[i].getId() < id || id < neighborhood_[i].getId() ); #endif - neighborhood_.push_back( NeighborBlock( phantomForest_, id, process, state ) ); + neighborhood_.emplace_back( phantomForest_, id, process, state ); } diff --git a/src/blockforest/SetupBlock.h b/src/blockforest/SetupBlock.h index bd391aac8..64b7b89ca 100644 --- a/src/blockforest/SetupBlock.h +++ b/src/blockforest/SetupBlock.h @@ -83,7 +83,7 @@ public: inline SetupBlock* getChild( const uint_t index ) { WALBERLA_ASSERT_LESS( index, children_.size() ); return children_[index]; } inline void setChild( const uint_t index, SetupBlock* const child ); - bool hasFather() const { return father_ != NULL; } + bool hasFather() const { return father_ != nullptr; } bool hasChildren() const { return !children_.empty(); } const std::vector< SetupBlock* >& getNeighborhoodSection( const uint_t index ) const { WALBERLA_ASSERT_LESS( index, 26 ); return neighborhoodSection_[index]; } @@ -168,7 +168,7 @@ inline void SetupBlock::setChild( const uint_t index, SetupBlock* const child ) WALBERLA_ASSERT( children_.empty() || children_.size() == 8 ); if( children_.empty() ) - children_.resize( 8, NULL ); + children_.resize( 8, nullptr ); children_[index] = child; } diff --git a/src/blockforest/SetupBlockForest.h b/src/blockforest/SetupBlockForest.h index a9192cac2..2dac1578f 100644 --- a/src/blockforest/SetupBlockForest.h +++ b/src/blockforest/SetupBlockForest.h @@ -98,7 +98,7 @@ public: public: - iterator( const iterator& it ) : forest_( it.forest_ ), block_( it.block_ ) {} + iterator( const iterator& it ) = default; iterator& operator++() { WALBERLA_ASSERT_NOT_NULLPTR( block_ ); block_ = forest_->getNextBlock( block_ ); return *this; } // prefix ++X iterator operator++(int) { iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -127,7 +127,7 @@ public: public: const_iterator( const iterator& it ) : forest_( it.forest_ ), block_( it.block_ ) {} - const_iterator( const const_iterator& it ) : forest_( it.forest_ ), block_( it.block_ ) {} + const_iterator( const const_iterator& it ) = default; const_iterator& operator++() { WALBERLA_ASSERT_NOT_NULLPTR( block_ ); block_ = forest_->getNextBlock( block_ ); return *this; } // prefix ++X const_iterator operator++(int) { const_iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -183,10 +183,10 @@ public: uint_t getNumberOfBlocks( const uint_t level ) const; inline const_iterator begin() const; - inline const_iterator end() const { return const_iterator( this, NULL ); } + inline const_iterator end() const { return const_iterator( this, nullptr ); } inline iterator begin(); - inline iterator end() { return iterator( this, NULL ); } + inline iterator end() { return iterator( this, nullptr ); } const SetupBlock* getFirstBlock() const; SetupBlock* getFirstBlock(); @@ -420,7 +420,7 @@ inline SetupBlockForest::~SetupBlockForest() { for( uint_t i = 0; i != forest_.size(); ++i ) { - if( forest_[i] != NULL ) delete forest_[i]; + if( forest_[i] != nullptr ) delete forest_[i]; } } @@ -430,7 +430,7 @@ inline SetupBlockForest::const_iterator SetupBlockForest::begin() const { const SetupBlock* block = getFirstBlock(); - if( block == NULL ) + if( block == nullptr ) return end(); return SetupBlockForest::const_iterator( this, block ); @@ -442,7 +442,7 @@ inline SetupBlockForest::iterator SetupBlockForest::begin() { SetupBlock* block = getFirstBlock(); - if( block == NULL ) + if( block == nullptr ) return end(); return SetupBlockForest::iterator( this, block ); @@ -467,10 +467,10 @@ inline SetupBlock* SetupBlockForest::getRootBlock( const uint_t x, const uint_t inline const SetupBlock* SetupBlockForest::getBlock( const real_t px, const real_t py, const real_t pz ) const { if( !domain_.contains( px, py, pz ) ) - return NULL; + return nullptr; SetupBlock* block = forest_[ mapPointToTreeIndex( px, py, pz ) ]; - if( block == NULL ) return NULL; + if( block == nullptr ) return nullptr; return mapPointToBlock( block, px, py, pz ); } @@ -480,10 +480,10 @@ inline const SetupBlock* SetupBlockForest::getBlock( const real_t px, const real inline SetupBlock* SetupBlockForest::getBlock( const real_t px, const real_t py, const real_t pz ) { if( !domain_.contains( px, py, pz ) ) - return NULL; + return nullptr; SetupBlock* block = forest_[ mapPointToTreeIndex( px, py, pz ) ]; - if( block == NULL ) return NULL; + if( block == nullptr ) return nullptr; return mapPointToBlock( block, px, py, pz ); } diff --git a/src/blockforest/StructuredBlockForest.h b/src/blockforest/StructuredBlockForest.h index ac021fe66..04b61a94f 100644 --- a/src/blockforest/StructuredBlockForest.h +++ b/src/blockforest/StructuredBlockForest.h @@ -50,31 +50,31 @@ public: using StructuredBlockStorage::blockExistsLocally; using StructuredBlockStorage::blockExistsRemotely; - bool blockExists ( const Cell& cell, const uint_t level = 0 ) const; - inline bool blockExistsLocally ( const Cell& cell, const uint_t level = 0 ) const; - inline bool blockExistsRemotely( const Cell& cell, const uint_t level = 0 ) const; + bool blockExists ( const Cell& cell, const uint_t level = 0 ) const override; + inline bool blockExistsLocally ( const Cell& cell, const uint_t level = 0 ) const override; + inline bool blockExistsRemotely( const Cell& cell, const uint_t level = 0 ) const override; - void getBlockID( IBlockID& id, const Cell& cell, const uint_t level = 0 ) const; + void getBlockID( IBlockID& id, const Cell& cell, const uint_t level = 0 ) const override; - inline uint_t getLevel( const IBlock& block ) const; + inline uint_t getLevel( const IBlock& block ) const override; using StructuredBlockStorage::getNumberOfXCells; using StructuredBlockStorage::getNumberOfYCells; using StructuredBlockStorage::getNumberOfZCells; #ifdef NDEBUG - uint_t getNumberOfXCells( const IBlock& /*block*/ ) const { return blockCells_[0]; } - uint_t getNumberOfYCells( const IBlock& /*block*/ ) const { return blockCells_[1]; } - uint_t getNumberOfZCells( const IBlock& /*block*/ ) const { return blockCells_[2]; } + uint_t getNumberOfXCells( const IBlock& /*block*/ ) const override { return blockCells_[0]; } + uint_t getNumberOfYCells( const IBlock& /*block*/ ) const override { return blockCells_[1]; } + uint_t getNumberOfZCells( const IBlock& /*block*/ ) const override { return blockCells_[2]; } #else - uint_t getNumberOfXCells( const IBlock& block ) const { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[0]; } - uint_t getNumberOfYCells( const IBlock& block ) const { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[1]; } - uint_t getNumberOfZCells( const IBlock& block ) const { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[2]; } + uint_t getNumberOfXCells( const IBlock& block ) const override { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[0]; } + uint_t getNumberOfYCells( const IBlock& block ) const override { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[1]; } + uint_t getNumberOfZCells( const IBlock& block ) const override { WALBERLA_ASSERT_EQUAL( &(getBlockStorage()), &(block.getBlockStorage()) ); return blockCells_[2]; } #endif using StructuredBlockStorage::getNumberOfCells; - inline uint_t getNumberOfCells( const IBlock& block, const uint_t index ) const; + inline uint_t getNumberOfCells( const IBlock& block, const uint_t index ) const override; // direct access to all member functions which are special to of BlockForest (-> for documentation of these functions see class BlockForest) @@ -164,21 +164,21 @@ public: protected: - inline bool equal( const StructuredBlockStorage* rhs ) const; + inline bool equal( const StructuredBlockStorage* rhs ) const override; // helper class for 'StructuredBlockForest::addCellBoundingBoxesAsBlockData' class CellBoundingBoxHandling : public AlwaysInitializeBlockDataHandling< CellInterval > { public: CellBoundingBoxHandling( const StructuredBlockForest & forest ) : forest_( forest ) {} - CellInterval * initialize( IBlock * const block ) { return forest_.initializeCellBoundingBox( block ); } + CellInterval * initialize( IBlock * const block ) override { return forest_.initializeCellBoundingBox( block ); } private: const StructuredBlockForest & forest_; }; friend class CellBoundingBoxHandling; //using StructuredBlockStorage::initializeCellBoundingBox; - inline BlockDataID addCellBoundingBoxesAsBlockData( const std::string & identifier ); + inline BlockDataID addCellBoundingBoxesAsBlockData( const std::string & identifier ) override; private: @@ -217,7 +217,7 @@ inline StructuredBlockForest::StructuredBlockForest( const shared_ptr< BlockFore inline bool StructuredBlockForest::blockExistsLocally( const Cell& cell, const uint_t level ) const { - return getBlock( cell, level ) != NULL; + return getBlock( cell, level ) != nullptr; } diff --git a/src/blockforest/communication/NonUniformPackInfo.h b/src/blockforest/communication/NonUniformPackInfo.h index a653169a5..0b32369c6 100644 --- a/src/blockforest/communication/NonUniformPackInfo.h +++ b/src/blockforest/communication/NonUniformPackInfo.h @@ -44,8 +44,8 @@ public: //**Construction & Destruction************************************************************ /*! \name Construction & Destruction */ //@{ - NonUniformPackInfo() {} - virtual ~NonUniformPackInfo() {} + NonUniformPackInfo() = default; + virtual ~NonUniformPackInfo() = default; //@} //******************************************************************************************************************* diff --git a/src/blockforest/loadbalancing/Cartesian.h b/src/blockforest/loadbalancing/Cartesian.h index 261473a9d..a147f1c98 100644 --- a/src/blockforest/loadbalancing/Cartesian.h +++ b/src/blockforest/loadbalancing/Cartesian.h @@ -35,7 +35,7 @@ class CartesianDistribution public: CartesianDistribution( const uint_t numberOfXProcesses, const uint_t numberOfYProcesses, const uint_t numberOfZProcesses, - std::vector< uint_t > * processIdMap = NULL ) : + std::vector< uint_t > * processIdMap = nullptr ) : numberOfXProcesses_( numberOfXProcesses ), numberOfYProcesses_( numberOfYProcesses ), numberOfZProcesses_( numberOfZProcesses ), processIdMap_( processIdMap ) {} diff --git a/src/boundary/Boundary.h b/src/boundary/Boundary.h index 8d83aea92..d7b3679f8 100644 --- a/src/boundary/Boundary.h +++ b/src/boundary/Boundary.h @@ -36,7 +36,7 @@ namespace boundary { class BoundaryConfiguration { public: - virtual ~BoundaryConfiguration() {} + virtual ~BoundaryConfiguration() = default; static const BoundaryConfiguration& null() { return *boundaryNullPtr; } static const shared_ptr<BoundaryConfiguration> nullPtr() { return boundaryNullPtr; } private: diff --git a/src/boundary/BoundaryHandling.h b/src/boundary/BoundaryHandling.h index cf724cdc1..0910be455 100644 --- a/src/boundary/BoundaryHandling.h +++ b/src/boundary/BoundaryHandling.h @@ -414,7 +414,7 @@ private: template< typename Boundary_T, typename BoundariesTuple, int N = std::tuple_size<BoundariesTuple>::value - 1 > inline const typename std::enable_if<(N!=0), Boundary_T>::type & getBoundaryCondition( const BoundaryUID & uid, const BoundariesTuple & boundaryConditions, - typename std::enable_if< std::is_same< Boundary_T, typename std::tuple_element<N, BoundariesTuple>::type >::value >::type* /*dummy*/ = 0 ) const + typename std::enable_if< std::is_same< Boundary_T, typename std::tuple_element<N, BoundariesTuple>::type >::value >::type* /*dummy*/ = nullptr ) const { if( uid == std::get<N>( boundaryConditions ).getUID() ) return std::get<N>( boundaryConditions ); @@ -424,7 +424,7 @@ private: template< typename Boundary_T, typename BoundariesTuple, int N = std::tuple_size<BoundariesTuple>::value - 1 > inline const typename std::enable_if<(N==0), Boundary_T>::type & getBoundaryCondition( const BoundaryUID & uid, const BoundariesTuple & boundaryConditions, - typename std::enable_if< std::is_same< Boundary_T, typename std::tuple_element<N, BoundariesTuple>::type >::value >::type* /*dummy*/ = 0 ) const + typename std::enable_if< std::is_same< Boundary_T, typename std::tuple_element<N, BoundariesTuple>::type >::value >::type* /*dummy*/ = nullptr ) const { if( uid == std::get<N>( boundaryConditions ).getUID() ) return std::get<N>( boundaryConditions ); @@ -439,8 +439,8 @@ private: template< typename Boundary_T, typename BoundariesTuple, int N = std::tuple_size<BoundariesTuple>::value - 1 > inline const typename std::enable_if<(N!=0), Boundary_T>::type & getBoundaryCondition( const BoundaryUID & uid, const BoundariesTuple & boundaryConditions, typename std::enable_if< std::is_same< typename std::is_same< Boundary_T, typename std::tuple_element<N, BoundariesTuple>::type >::type, - std::false_type >::value >::type* /*dummy*/ = 0, - typename std::enable_if< (N>0) >::type* /*dummy*/ = 0 ) const + std::false_type >::value >::type* /*dummy*/ = nullptr, + typename std::enable_if< (N>0) >::type* /*dummy*/ = nullptr ) const { return getBoundaryCondition< Boundary_T, BoundariesTuple, N-1 >( uid, boundaryConditions ); } @@ -490,7 +490,7 @@ private: template< typename Boundary_T, typename BoundariesTuple, int N = std::tuple_size<BoundariesTuple>::value - 1 > inline const typename std::enable_if<(N==0), Boundary_T>::type & getBoundaryCondition_TypeExists( const BoundaryUID & uid, const BoundariesTuple & /*boundaryConditions*/, typename std::enable_if< std::is_same< typename std::is_same< Boundary_T, typename std::tuple_element<0, BoundariesTuple>::type >::type, - std::false_type >::value >::type* /*dummy*/ = 0 ) const + std::false_type >::value >::type* /*dummy*/ = nullptr ) const { WALBERLA_ABORT( "The requested boundary condition " << uid.getIdentifier() << " is not part of this boundary handling." ); diff --git a/src/boundary/communication/HandlingPackInfo.h b/src/boundary/communication/HandlingPackInfo.h index d730bf2ad..460ec60e4 100644 --- a/src/boundary/communication/HandlingPackInfo.h +++ b/src/boundary/communication/HandlingPackInfo.h @@ -39,18 +39,18 @@ public: HandlingPackInfo( const BlockDataID & bdId, const bool assumeIdenticalFlagMapping = true, const uint_t numberOfLayers = 0 ) : bdId_( bdId ), numberOfLayers_( numberOfLayers ), assumeIdenticalFlagMapping_( assumeIdenticalFlagMapping ) {} - ~HandlingPackInfo() {} + ~HandlingPackInfo() override = default; - bool constantDataExchange() const { return false; } - bool threadsafeReceiving() const { return false; } + bool constantDataExchange() const override { return false; } + bool threadsafeReceiving() const override { return false; } - void unpackData( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ); + void unpackData( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; - void communicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ); + void communicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ) override; protected: - void packDataImpl( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const; + void packDataImpl( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; diff --git a/src/communication/ReducePackInfo.h b/src/communication/ReducePackInfo.h index d353d6f37..141dd9828 100644 --- a/src/communication/ReducePackInfo.h +++ b/src/communication/ReducePackInfo.h @@ -42,7 +42,7 @@ class ReducePackInfo { public: ReducePackInfo( ) : size_(0u) {} - virtual ~ReducePackInfo() {} + virtual ~ReducePackInfo() = default; size_t getSize() const { return size_; } diff --git a/src/communication/UniformMPIDatatypeInfo.h b/src/communication/UniformMPIDatatypeInfo.h index be8689441..8f8e0d6c4 100644 --- a/src/communication/UniformMPIDatatypeInfo.h +++ b/src/communication/UniformMPIDatatypeInfo.h @@ -49,8 +49,8 @@ namespace communication { //**Construction & Destruction************************************************************************************ /*! \name Construction & Destruction */ //@{ - UniformMPIDatatypeInfo() {} - virtual ~UniformMPIDatatypeInfo() {} + UniformMPIDatatypeInfo() = default; + virtual ~UniformMPIDatatypeInfo() = default; //@} //**************************************************************************************************************** diff --git a/src/communication/UniformPackInfo.h b/src/communication/UniformPackInfo.h index d2737a19c..5ec6db29d 100644 --- a/src/communication/UniformPackInfo.h +++ b/src/communication/UniformPackInfo.h @@ -57,8 +57,8 @@ public: //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ //@{ - UniformPackInfo() {} - virtual ~UniformPackInfo() {} + UniformPackInfo() = default; + virtual ~UniformPackInfo() = default; //@} //******************************************************************************************************************* diff --git a/src/core/Abort.h b/src/core/Abort.h index 8c52f6783..23b1ef1ff 100644 --- a/src/core/Abort.h +++ b/src/core/Abort.h @@ -52,7 +52,7 @@ public: private: - Abort() {} + Abort() = default; AbortFunction abortFunction_; }; diff --git a/src/core/Array.h b/src/core/Array.h index 1c5f8c2b2..42ab4efe5 100644 --- a/src/core/Array.h +++ b/src/core/Array.h @@ -41,12 +41,12 @@ class Array { public: - inline Array() : array_( NULL ), size_( uint_c(0) ) {} + inline Array() : array_( nullptr ), size_( uint_c(0) ) {} inline Array( const uint_t n, const T& t = T() ); inline Array( const std::vector<T>& vector ); inline Array( const Array& array ); - ~Array() { if( array_ != NULL ) delete[] array_; } + ~Array() { if( array_ != nullptr ) delete[] array_; } uint_t size() const { return size_; } bool empty() const { return size_ == 0; } diff --git a/src/core/ConcatIterator.h b/src/core/ConcatIterator.h index f76c79f62..9b0ad071d 100644 --- a/src/core/ConcatIterator.h +++ b/src/core/ConcatIterator.h @@ -62,14 +62,7 @@ public: { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } return it_ == rhs.it_; diff --git a/src/core/NonCopyable.h b/src/core/NonCopyable.h index c01b4faf3..59b7773d2 100644 --- a/src/core/NonCopyable.h +++ b/src/core/NonCopyable.h @@ -36,8 +36,8 @@ class NonCopyable { protected: - NonCopyable(){} // no object of type 'NonCopyable' can be created! - ~NonCopyable(){} + NonCopyable()= default; // no object of type 'NonCopyable' can be created! + ~NonCopyable()= default; private: diff --git a/src/core/Set.h b/src/core/Set.h index 3b77f42e7..7f094ad96 100644 --- a/src/core/Set.h +++ b/src/core/Set.h @@ -96,10 +96,10 @@ public: friend inline bool operator==( const Set& a, const Set& b ) { return setIsEqual(a,b); } ///< compares the content of two sets friend inline bool operator!=( const Set& a, const Set& b ) { return !setIsEqual(a,b); } ///< compares the content of two sets - inline Set() {} + inline Set() = default; inline Set( const T& element ) { set_.insert( element ); } - inline virtual ~Set() {} + inline virtual ~Set() = default; static const Set<T> emptySet() { return {}; } diff --git a/src/core/StringUtility.impl.h b/src/core/StringUtility.impl.h index ddc5f7482..730bf5928 100644 --- a/src/core/StringUtility.impl.h +++ b/src/core/StringUtility.impl.h @@ -104,7 +104,7 @@ inline std::vector<std::string> string_split(std::string s, const std::string &d if (*it == d) { // current character in s is a delimiter sub_end = it; if (sub_begin < sub_end) { // make sure that the substring is not empty - substrings.push_back(std::string(sub_begin, sub_end)); + substrings.emplace_back(sub_begin, sub_end); } sub_begin = ++sub_end; continue; @@ -114,7 +114,7 @@ inline std::vector<std::string> string_split(std::string s, const std::string &d // add substring from last delimiter to the end of s if (sub_begin < s.end()) { - substrings.push_back(std::string(sub_begin, s.end())); + substrings.emplace_back(sub_begin, s.end()); } return substrings; diff --git a/src/core/cell/Cell.h b/src/core/cell/Cell.h index 8fc8ef14e..3df78ce5b 100644 --- a/src/core/cell/Cell.h +++ b/src/core/cell/Cell.h @@ -47,7 +47,7 @@ public: /*! \name Constructors */ //@{ - Cell() {} + Cell() = default; inline Cell( const cell_idx_t _x, const cell_idx_t _y, const cell_idx_t _z ) { cell[0] = _x; cell[1] = _y; cell[2] = _z; } //inline Cell( const int _x, const int _y, const int _z ); inline Cell( const uint_t _x, const uint_t _y, const uint_t _z ); diff --git a/src/core/cell/CellArray.h b/src/core/cell/CellArray.h index 3f26ee61c..732b2b853 100644 --- a/src/core/cell/CellArray.h +++ b/src/core/cell/CellArray.h @@ -41,7 +41,7 @@ public: CellArray( const CellVector& cells ) { - this->array_ = cells.size() == 0 ? NULL : new Cell[ cells.size() ]; + this->array_ = cells.empty() ? nullptr : new Cell[ cells.size() ]; this->size_ = cells.size(); for( uint_t i = 0; i != this->size_; ++i ) @@ -50,7 +50,7 @@ public: CellArray( const CellSet& cells ) { - this->array_ = cells.size() == 0 ? NULL : new Cell[ cells.size() ]; + this->array_ = cells.empty() ? nullptr : new Cell[ cells.size() ]; this->size_ = cells.size(); uint_t i = 0; diff --git a/src/core/cell/CellInterval.h b/src/core/cell/CellInterval.h index 10dfb0d9b..10f2529aa 100644 --- a/src/core/cell/CellInterval.h +++ b/src/core/cell/CellInterval.h @@ -236,11 +236,8 @@ inline bool CellInterval::overlaps( const CellInterval& other ) const if( empty() || other.empty() ) return false; - if( other.min_.x() > max_.x() || other.min_.y() > max_.y() || other.min_.z() > max_.z() || - other.max_.x() < min_.x() || other.max_.y() < min_.y() || other.max_.z() < min_.z() ) - return false; - else - return true; + return !(other.min_.x() > max_.x() || other.min_.y() > max_.y() || other.min_.z() > max_.z() || + other.max_.x() < min_.x() || other.max_.y() < min_.y() || other.max_.z() < min_.z()); } diff --git a/src/core/cell/CellVector.h b/src/core/cell/CellVector.h index 0d9fe9f81..aa0fdefbd 100644 --- a/src/core/cell/CellVector.h +++ b/src/core/cell/CellVector.h @@ -56,7 +56,7 @@ public: /*! \name Constructors */ //@{ - CellVector() {} + CellVector() = default; CellVector(size_type n, const Cell & value = Cell()) : cells_(n, value) {} template <class InputIterator> CellVector(InputIterator first, InputIterator last) : cells_(first, last) { } @@ -140,14 +140,14 @@ std::ostream & operator<<( std::ostream & os, const CellVector & cells ); inline void CellVector::push_back( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z ) { - cells_.push_back( Cell(x, y, z) ); + cells_.emplace_back(x, y, z ); } inline void CellVector::push_back( const uint_t x, const uint_t y, const uint_t z ) { - cells_.push_back( Cell(x, y, z) ); + cells_.emplace_back(x, y, z ); } diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 9837b870c..056661251 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -280,7 +280,7 @@ public: template< typename T > inline Parameter<T> getParameter( const std::string & key, const T& defaultValue ) const; - bool isValid() const { return block_ != NULL; } + bool isValid() const { return block_ != nullptr; } operator bool() const { return isValid(); } inline const_iterator begin() const; @@ -1058,7 +1058,7 @@ inline Config::const_iterator Config::Block::end() const // an error until the BlockHandle object is bound to a block. */ inline Config::BlockHandle::BlockHandle() - :block_(0) + :block_(nullptr) {} //********************************************************************************************************************** diff --git a/src/core/config/Iterator.h b/src/core/config/Iterator.h index 3b9759426..9796f59bf 100644 --- a/src/core/config/Iterator.h +++ b/src/core/config/Iterator.h @@ -29,7 +29,7 @@ namespace config { struct ConfigGenerator { - virtual ~ConfigGenerator() {} + virtual ~ConfigGenerator() = default; virtual shared_ptr<Config> next() = 0; }; @@ -37,7 +37,7 @@ namespace config { class Iterator { public: - Iterator() {} + Iterator() = default; Iterator( const shared_ptr<ConfigGenerator> & configGenerator ) : generator_ ( configGenerator ) { diff --git a/src/core/debug/CheckFunctions.h b/src/core/debug/CheckFunctions.h index 04444255c..4431b654d 100644 --- a/src/core/debug/CheckFunctions.h +++ b/src/core/debug/CheckFunctions.h @@ -212,7 +212,7 @@ namespace check_functions_detail { struct ExitHandler { - ExitHandler() {}; + ExitHandler() = default; ExitHandler( const std::string & message ) : message_( message ) {} void operator()( const std::string & checkErrorMessage ); private: diff --git a/src/core/debug/CheckFunctions.impl.h b/src/core/debug/CheckFunctions.impl.h index 023d5f7d3..e1932fdda 100644 --- a/src/core/debug/CheckFunctions.impl.h +++ b/src/core/debug/CheckFunctions.impl.h @@ -37,7 +37,7 @@ namespace check_functions_detail { template< typename T > inline bool check_nullptr( T * p ) { - return p == 0; + return p == nullptr; } template< typename T > @@ -49,7 +49,7 @@ inline bool check_nullptr( const shared_ptr<T> & p ) template< typename T > inline bool check_not_nullptr( T * p ) { - return p != 0; + return p != nullptr; } template< typename T > diff --git a/src/core/debug/demangle.h b/src/core/debug/demangle.h index 2e317436e..55334b550 100644 --- a/src/core/debug/demangle.h +++ b/src/core/debug/demangle.h @@ -42,7 +42,7 @@ inline std::string demangle( const std::string & name ) #ifdef HAVE_CXXABI_H int status = 0; std::size_t size = 0; - const char * demangled = abi::__cxa_demangle( name.c_str(), NULL, &size, &status ); + const char * demangled = abi::__cxa_demangle( name.c_str(), nullptr, &size, &status ); if( demangled == nullptr ) { return name; diff --git a/src/core/logging/Logging.h b/src/core/logging/Logging.h index 1a4377851..8d174df51 100644 --- a/src/core/logging/Logging.h +++ b/src/core/logging/Logging.h @@ -82,7 +82,7 @@ public: class CustomStamp { public: - virtual ~CustomStamp() {} + virtual ~CustomStamp() = default; virtual std::string stamp() = 0; virtual uint_t maxStampWidth() = 0; }; diff --git a/src/core/math/Matrix2.h b/src/core/math/Matrix2.h index f8310899c..a9377506d 100644 --- a/src/core/math/Matrix2.h +++ b/src/core/math/Matrix2.h @@ -375,12 +375,10 @@ inline bool Matrix2<Type>::operator==( const Matrix2<Other>& rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type. - if( !equal( v_[0], rhs.v_[0] ) || - !equal( v_[1], rhs.v_[1] ) || - !equal( v_[2], rhs.v_[2] ) || - !equal( v_[3], rhs.v_[3] ) ) - return false; - else return true; + return equal( v_[0], rhs.v_[0] ) && + equal( v_[1], rhs.v_[1] ) && + equal( v_[2], rhs.v_[2] ) && + equal( v_[3], rhs.v_[3] ); } //********************************************************************************************************************** @@ -398,12 +396,7 @@ inline bool Matrix2<Type>::operator!=( const Matrix2<Other>& rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type. - if( !equal( v_[0], rhs.v_[0] ) || - !equal( v_[1], rhs.v_[1] ) || - !equal( v_[2], rhs.v_[2] ) || - !equal( v_[3], rhs.v_[3] ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** @@ -781,9 +774,7 @@ inline const Matrix2<Type> Matrix2<Type>::getInverse() const template< typename Type > inline bool Matrix2<Type>::isSingular() const { - if( equal( getDeterminant(), Type(0) ) ) - return true; - else return false; + return equal( getDeterminant(), Type(0) ); } //********************************************************************************************************************** @@ -875,11 +866,8 @@ std::ostream& operator<<( std::ostream& os, const Matrix2<Type>& m ) template< typename Type > inline bool isnan( const Matrix2<Type>& m ) { - if( math::isnan( m[0] ) || math::isnan( m[1] )|| - math::isnan( m[2] ) || math::isnan( m[3] ) ) - return true; - else - return false; + return math::isnan( m[0] ) || math::isnan( m[1] )|| + math::isnan( m[2] ) || math::isnan( m[3] ); } //********************************************************************************************************************** diff --git a/src/core/math/Matrix3.h b/src/core/math/Matrix3.h index 665c6529e..e8253b4ad 100644 --- a/src/core/math/Matrix3.h +++ b/src/core/math/Matrix3.h @@ -525,17 +525,15 @@ inline bool Matrix3<Type>::operator==( const Matrix3<Other>& rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type. - if( !equal( v_[0], rhs.v_[0] ) || - !equal( v_[1], rhs.v_[1] ) || - !equal( v_[2], rhs.v_[2] ) || - !equal( v_[3], rhs.v_[3] ) || - !equal( v_[4], rhs.v_[4] ) || - !equal( v_[5], rhs.v_[5] ) || - !equal( v_[6], rhs.v_[6] ) || - !equal( v_[7], rhs.v_[7] ) || - !equal( v_[8], rhs.v_[8] ) ) - return false; - else return true; + return equal( v_[0], rhs.v_[0] ) && + equal( v_[1], rhs.v_[1] ) && + equal( v_[2], rhs.v_[2] ) && + equal( v_[3], rhs.v_[3] ) && + equal( v_[4], rhs.v_[4] ) && + equal( v_[5], rhs.v_[5] ) && + equal( v_[6], rhs.v_[6] ) && + equal( v_[7], rhs.v_[7] ) && + equal( v_[8], rhs.v_[8] ); } //********************************************************************************************************************** @@ -553,17 +551,7 @@ inline bool Matrix3<Type>::operator!=( const Matrix3<Other>& rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type. - if( !equal( v_[0], rhs.v_[0] ) || - !equal( v_[1], rhs.v_[1] ) || - !equal( v_[2], rhs.v_[2] ) || - !equal( v_[3], rhs.v_[3] ) || - !equal( v_[4], rhs.v_[4] ) || - !equal( v_[5], rhs.v_[5] ) || - !equal( v_[6], rhs.v_[6] ) || - !equal( v_[7], rhs.v_[7] ) || - !equal( v_[8], rhs.v_[8] ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** @@ -1129,9 +1117,7 @@ inline const Matrix3<HIGH> Matrix3<Type>::diagRotate( const Matrix3<Other>& m ) template< typename Type > inline bool Matrix3<Type>::isSingular() const { - if( equal( getDeterminant(), Type(0) ) ) - return true; - else return false; + return equal( getDeterminant(), Type(0) ); } //********************************************************************************************************************** @@ -1145,9 +1131,7 @@ inline bool Matrix3<Type>::isSingular() const template< typename Type > inline bool Matrix3<Type>::isSymmetric() const { - if( !equal( v_[1], v_[3] ) || !equal( v_[2], v_[6] ) || !equal( v_[5], v_[7] ) ) - return false; - else return true; + return equal( v_[1], v_[3] ) && equal( v_[2], v_[6] ) && equal( v_[5], v_[7] ); } //********************************************************************************************************************** @@ -1160,7 +1144,7 @@ inline bool Matrix3<Type>::isSymmetric() const template< typename Type > inline bool Matrix3<Type>::isZero() const { - if( equal( v_[0], Type(0) ) && + return equal( v_[0], Type(0) ) && equal( v_[1], Type(0) ) && equal( v_[2], Type(0) ) && equal( v_[3], Type(0) ) && @@ -1168,9 +1152,7 @@ inline bool Matrix3<Type>::isZero() const equal( v_[5], Type(0) ) && equal( v_[6], Type(0) ) && equal( v_[7], Type(0) ) && - equal( v_[8], Type(0) ) ) - return true; - else return false; + equal( v_[8], Type(0) ); } //********************************************************************************************************************** @@ -1595,11 +1577,9 @@ std::ostream& operator<<( std::ostream& os, const Matrix3<Type>& m ) template< typename Type > inline bool isnan( const Matrix3<Type>& m ) { - if( math::isnan( m[0] ) || math::isnan( m[1] ) || math::isnan( m[2] ) || + return math::isnan( m[0] ) || math::isnan( m[1] ) || math::isnan( m[2] ) || math::isnan( m[3] ) || math::isnan( m[4] ) || math::isnan( m[5] ) || - math::isnan( m[6] ) || math::isnan( m[7] ) || math::isnan( m[8] ) ) - return true; - else return false; + math::isnan( m[6] ) || math::isnan( m[7] ) || math::isnan( m[8] ); } //********************************************************************************************************************** @@ -1658,11 +1638,9 @@ inline const Matrix3<Type> fabs( const Matrix3<Type>& m ) template< typename Type > inline bool isinf( const Matrix3<Type>& m ) { - if( math::isinf( m[0] ) || math::isinf( m[1] ) || math::isinf( m[2] ) || + return math::isinf( m[0] ) || math::isinf( m[1] ) || math::isinf( m[2] ) || math::isinf( m[3] ) || math::isinf( m[4] ) || math::isinf( m[5] ) || - math::isinf( m[6] ) || math::isinf( m[7] ) || math::isinf( m[8] ) ) - return true; - else return false; + math::isinf( m[6] ) || math::isinf( m[7] ) || math::isinf( m[8] ); } //********************************************************************************************************************** diff --git a/src/core/math/MatrixMxN.h b/src/core/math/MatrixMxN.h index be490da34..1d633e74e 100644 --- a/src/core/math/MatrixMxN.h +++ b/src/core/math/MatrixMxN.h @@ -203,7 +203,7 @@ inline constexpr MatrixMxN<Type>::MatrixMxN() : m_ ( 0 ) // The current number of rows of the matrix , n_ ( 0 ) // The current number of columns of the matrix , capacity_( 0 ) // The maximum capacity of the matrix - , v_ ( 0 ) // The matrix elements + , v_ ( nullptr ) // The matrix elements {} //************************************************************************************************* diff --git a/src/core/math/Quaternion.h b/src/core/math/Quaternion.h index 90fd652de..9ca8c6f53 100644 --- a/src/core/math/Quaternion.h +++ b/src/core/math/Quaternion.h @@ -816,12 +816,10 @@ inline bool operator==( const Quaternion<T1>& lhs, const Quaternion<T2>& rhs ) { // In order to compare the two quaternions, the data values of the lower-order data // type are converted to the higher-order data type within the equal function. - if( !equal( lhs[0], rhs[0] ) || - !equal( lhs[1], rhs[1] ) || - !equal( lhs[2], rhs[2] ) || - !equal( lhs[2], rhs[2] ) ) - return false; - else return true; + return equal( lhs[0], rhs[0] ) && + equal( lhs[1], rhs[1] ) && + equal( lhs[2], rhs[2] ) && + equal( lhs[2], rhs[2] ); } //************************************************************************************************* @@ -911,9 +909,7 @@ std::istream& operator>>( std::istream& is, Quaternion<Type>& q ) template< typename Type > // Data type of the quaternion inline bool isnan( const Quaternion<Type>& q ) { - if( isnan( q[0] ) || isnan( q[1] ) || isnan( q[2] ) || isnan( q[3] ) ) - return true; - else return false; + return isnan( q[0] ) || isnan( q[1] ) || isnan( q[2] ) || isnan( q[3] ); } //************************************************************************************************* diff --git a/src/core/math/Vector2.h b/src/core/math/Vector2.h index b0decf8ec..c69f7bcc7 100644 --- a/src/core/math/Vector2.h +++ b/src/core/math/Vector2.h @@ -322,9 +322,7 @@ inline bool Vector2<Type>::operator==( Other rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs ) || !equal( v_[1], rhs ) ) - return false; - else return true; + return equal( v_[0], rhs ) && equal( v_[1], rhs ); } //********************************************************************************************************************** @@ -342,9 +340,7 @@ inline bool Vector2<Type>::operator==( const Vector2<Other>& rhs ) const { // In order to compare the two vectors, the data values of the lower-order data // type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs.v_[0] ) || !equal( v_[1], rhs.v_[1] ) ) - return false; - else return true; + return equal( v_[0], rhs.v_[0] ) && equal( v_[1], rhs.v_[1] ); } //********************************************************************************************************************** @@ -365,9 +361,7 @@ inline bool Vector2<Type>::operator!=( Other rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs ) || !equal( v_[1], rhs ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** @@ -385,9 +379,7 @@ inline bool Vector2<Type>::operator!=( const Vector2<Other>& rhs ) const { // In order to compare the two vectors, the data values of the lower-order data // type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs.v_[0] ) || !equal( v_[1], rhs.v_[1] ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** @@ -1457,10 +1449,7 @@ inline std::istream& operator>>( std::istream& is, Vector2<bool>& v ) template< typename Type > inline bool isnan( const Vector2<Type>& v ) { - if( walberla::math::isnan( v[0] ) || walberla::math::isnan( v[1] ) ) - return true; - else - return false; + return walberla::math::isnan( v[0] ) || walberla::math::isnan( v[1] ); } //********************************************************************************************************************** diff --git a/src/core/math/Vector3.h b/src/core/math/Vector3.h index 8bc4e3233..72b6a45fa 100644 --- a/src/core/math/Vector3.h +++ b/src/core/math/Vector3.h @@ -333,9 +333,7 @@ inline bool Vector3<Type>::operator==( Other rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs ) || !equal( v_[1], rhs ) || !equal( v_[2], rhs ) ) - return false; - else return true; + return equal( v_[0], rhs ) && equal( v_[1], rhs ) && equal( v_[2], rhs ); } //********************************************************************************************************************** @@ -353,9 +351,7 @@ inline bool Vector3<Type>::operator==( const Vector3<Other>& rhs ) const { // In order to compare the two vectors, the data values of the lower-order data // type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs.v_[0] ) || !equal( v_[1], rhs.v_[1] ) || !equal( v_[2], rhs.v_[2] ) ) - return false; - else return true; + return equal( v_[0], rhs.v_[0] ) && equal( v_[1], rhs.v_[1] ) && equal( v_[2], rhs.v_[2] ); } //********************************************************************************************************************** @@ -376,9 +372,7 @@ inline bool Vector3<Type>::operator!=( Other rhs ) const { // In order to compare the vector and the scalar value, the data values of the lower-order // data type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs ) || !equal( v_[1], rhs ) || !equal( v_[2], rhs ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** @@ -396,9 +390,7 @@ inline bool Vector3<Type>::operator!=( const Vector3<Other>& rhs ) const { // In order to compare the two vectors, the data values of the lower-order data // type are converted to the higher-order data type within the equal function. - if( !equal( v_[0], rhs.v_[0] ) || !equal( v_[1], rhs.v_[1] ) || !equal( v_[2], rhs.v_[2] ) ) - return true; - else return false; + return !(*this == rhs); } //********************************************************************************************************************** diff --git a/src/core/math/equation_system/Operator.h b/src/core/math/equation_system/Operator.h index b0dcd809b..e9a6a75e1 100644 --- a/src/core/math/equation_system/Operator.h +++ b/src/core/math/equation_system/Operator.h @@ -42,7 +42,7 @@ namespace math { OpType( const char& sign, const std::string& n, const unsigned int strength ) : sign_(sign), name_(n), strength_(strength) {} - virtual ~OpType() {} + virtual ~OpType() = default; private: OpType& operator=( const OpType& ){ return *this; } @@ -68,56 +68,56 @@ namespace math { public: OpNo( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double &, const double & ) { WALBERLA_ABORT( "NO OPERATION" ); return 0; } + double operator() ( const double &, const double & ) override { WALBERLA_ABORT( "NO OPERATION" ); return 0; } }; class OpPlus : public OpType{ public: OpPlus( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {}; - double operator() ( const double & a, const double & b ) { return a + b; } + double operator() ( const double & a, const double & b ) override { return a + b; } }; class OpMinus : public OpType{ public: OpMinus( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return a - b; } + double operator() ( const double & a, const double & b ) override { return a - b; } }; class OpMult : public OpType{ public: OpMult( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return a * b; } + double operator() ( const double & a, const double & b ) override { return a * b; } }; class OpDiv : public OpType{ public: OpDiv( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return a / b; } + double operator() ( const double & a, const double & b ) override { return a / b; } }; class OpProd : public OpType{ public: OpProd( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return pow( a, b ); } + double operator() ( const double & a, const double & b ) override { return pow( a, b ); } }; class OpRoot : public OpType{ public: OpRoot( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return pow( a, 1/b ); } + double operator() ( const double & a, const double & b ) override { return pow( a, 1/b ); } }; class OpLog : public OpType{ public: OpLog( const char& sign, const std::string& name, const unsigned int strength ) : OpType( sign, name, strength ) {} - double operator() ( const double & a, const double & b ) { return log10(a) / log10(b); } + double operator() ( const double & a, const double & b ) override { return log10(a) / log10(b); } }; diff --git a/src/core/mpi/BufferSystem.h b/src/core/mpi/BufferSystem.h index 8be65ea4a..ea1037b13 100644 --- a/src/core/mpi/BufferSystem.h +++ b/src/core/mpi/BufferSystem.h @@ -118,7 +118,7 @@ public: explicit GenericBufferSystem( const MPI_Comm & communicator, int tag = 0 ); GenericBufferSystem( const GenericBufferSystem & other ); GenericBufferSystem & operator=( const GenericBufferSystem & other ); - ~GenericBufferSystem() {} + ~GenericBufferSystem() = default; //@} //******************************************************************************************************************* diff --git a/src/core/mpi/BufferSystemHelper.h b/src/core/mpi/BufferSystemHelper.h index 661e46358..78b77c5ed 100644 --- a/src/core/mpi/BufferSystemHelper.h +++ b/src/core/mpi/BufferSystemHelper.h @@ -43,7 +43,7 @@ namespace internal { : communicator_( communicator), tag_(tag) {} - virtual ~AbstractCommunication() {} + virtual ~AbstractCommunication() = default; struct ReceiveInfo { @@ -110,15 +110,15 @@ namespace internal { KnownSizeCommunication( const MPI_Comm & communicator, int tag = 0 ) : AbstractCommunication<RecvBuffer_T, SendBuffer_T>( communicator, tag ), sending_(false), receiving_(false) {} - virtual ~KnownSizeCommunication() {} + ~KnownSizeCommunication() override = default; - virtual void send( MPIRank receiver, const SendBuffer_T & sendBuffer ); - virtual void waitForSends(); + void send( MPIRank receiver, const SendBuffer_T & sendBuffer ) override; + void waitForSends() override; - virtual void scheduleReceives ( std::map<MPIRank, ReceiveInfo> & recvInfos ); + void scheduleReceives ( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; /// size field of recvInfos is expected to be valid - virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ); + MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; private: bool sending_; @@ -138,15 +138,15 @@ namespace internal { UnknownSizeCommunication( const MPI_Comm & communicator, int tag = 0 ) : AbstractCommunication<RecvBuffer_T, SendBuffer_T>( communicator, tag ), sending_(false), receiving_(false) {} - virtual ~UnknownSizeCommunication() {} + ~UnknownSizeCommunication() override = default; - virtual void send( MPIRank receiver, const SendBuffer_T & sendBuffer ); - virtual void waitForSends(); + void send( MPIRank receiver, const SendBuffer_T & sendBuffer ) override; + void waitForSends() override; - virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ); + void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; /// size field of recvInfos can be invalid, is filled in with the actual message size - virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ); + MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; private: bool sending_; @@ -170,15 +170,15 @@ namespace internal { UnknownSizeCommunicationIProbe( const MPI_Comm & communicator, int tag = 0 ) : AbstractCommunication<RecvBuffer_T, SendBuffer_T>( communicator, tag ), sending_(false), receiving_(false) {} - virtual ~UnknownSizeCommunicationIProbe() {} + ~UnknownSizeCommunicationIProbe() override = default; - virtual void send( MPIRank receiver, const SendBuffer_T & sendBuffer ); - virtual void waitForSends(); + void send( MPIRank receiver, const SendBuffer_T & sendBuffer ) override; + void waitForSends() override; - virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ); + void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; /// size field of recvInfos can be invalid, is filled in with the actual message size - virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ); + MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; private: bool sending_; @@ -198,15 +198,15 @@ namespace internal { NoMPICommunication( const MPI_Comm & communicator, int tag = 0 ) : AbstractCommunication<RecvBuffer_T, SendBuffer_T>( communicator, tag ), received_( false ) {} - virtual ~NoMPICommunication() {} + ~NoMPICommunication() override = default; - virtual void send( MPIRank receiver, const SendBuffer_T & sendBuffer ); - virtual void waitForSends(); + void send( MPIRank receiver, const SendBuffer_T & sendBuffer ) override; + void waitForSends() override; - virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ); + void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; /// size field of recvInfos can be invalid, is filled in with the actual message size - virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ); + MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ) override; private: bool received_; diff --git a/src/core/mpi/Gather.h b/src/core/mpi/Gather.h index 5cad16189..976981f9f 100644 --- a/src/core/mpi/Gather.h +++ b/src/core/mpi/Gather.h @@ -78,7 +78,7 @@ std::vector<T> gather( T value, int recvRank = 0, MPI_Comm comm = MPI_COMM_WORLD return result; } - MPI_Gather( &value, 1, MPITrait<T>::type(), NULL, 1, MPITrait<T>::type(), + MPI_Gather( &value, 1, MPITrait<T>::type(), nullptr, 1, MPITrait<T>::type(), recvRank, comm ); return std::vector<T>(); diff --git a/src/core/mpi/Gatherv.h b/src/core/mpi/Gatherv.h index 7ffda280a..7a9de2652 100644 --- a/src/core/mpi/Gatherv.h +++ b/src/core/mpi/Gatherv.h @@ -90,9 +90,9 @@ std::vector<T> gatherv( const std::vector<T> & values, int recvRank = 0, MPI_Com if( values.empty() ) { if( !result.empty() ) - MPI_Gatherv( NULL, 0, MPITrait<T>::type(), &(result[0]), &(recvCounts[0]), &(displacements[0]), MPITrait<T>::type(), recvRank, comm ); + MPI_Gatherv( nullptr, 0, MPITrait<T>::type(), &(result[0]), &(recvCounts[0]), &(displacements[0]), MPITrait<T>::type(), recvRank, comm ); else - MPI_Gatherv( NULL, 0, MPITrait<T>::type(), NULL, &(recvCounts[0]), &(displacements[0]), MPITrait<T>::type(), recvRank, comm ); + MPI_Gatherv( nullptr, 0, MPITrait<T>::type(), nullptr, &(recvCounts[0]), &(displacements[0]), MPITrait<T>::type(), recvRank, comm ); } else { @@ -109,11 +109,11 @@ std::vector<T> gatherv( const std::vector<T> & values, int recvRank = 0, MPI_Com if( values.empty() ) { - MPI_Gatherv( NULL, 0, MPITrait<T>::type(), NULL, NULL, NULL, MPITrait<T>::type(), recvRank, comm ); + MPI_Gatherv( nullptr, 0, MPITrait<T>::type(), nullptr, nullptr, nullptr, MPITrait<T>::type(), recvRank, comm ); } else { - MPI_Gatherv( const_cast<T*>( &(values[0]) ), int_c( values.size() ), MPITrait<T>::type(), NULL, NULL, NULL, MPITrait<T>::type(), + MPI_Gatherv( const_cast<T*>( &(values[0]) ), int_c( values.size() ), MPITrait<T>::type(), nullptr, nullptr, nullptr, MPITrait<T>::type(), recvRank, comm ); } @@ -171,7 +171,7 @@ std::vector<T> allGatherv( const std::vector<T> & values, MPI_Comm comm = MPI_CO { if( values.empty() ) { - MPI_Allgatherv( NULL, 0, MPITrait<T>::type(), &(result[0]), &(recvCounts[0]), &(displacements[0]), + MPI_Allgatherv( nullptr, 0, MPITrait<T>::type(), &(result[0]), &(recvCounts[0]), &(displacements[0]), MPITrait<T>::type(), comm ); } else diff --git a/src/core/mpi/MPIWrapper.h b/src/core/mpi/MPIWrapper.h index 14e72cc5d..233baa6bb 100644 --- a/src/core/mpi/MPIWrapper.h +++ b/src/core/mpi/MPIWrapper.h @@ -177,10 +177,10 @@ const int MPI_REQUEST_NULL = 0; const int MPI_FILE_NULL = 0; -static MPI_Status* MPI_STATUS_IGNORE = NULL; -static MPI_Status* MPI_STATUSES_IGNORE = NULL; +static MPI_Status* MPI_STATUS_IGNORE = nullptr; +static MPI_Status* MPI_STATUSES_IGNORE = nullptr; -namespace non_mpi_internal { inline void disableDefinedButNotUsedWarning() { MPI_STATUS_IGNORE = NULL; MPI_STATUSES_IGNORE = NULL; } } +namespace non_mpi_internal { inline void disableDefinedButNotUsedWarning() { MPI_STATUS_IGNORE = nullptr; MPI_STATUSES_IGNORE = nullptr; } } const int MPI_MAX_OBJECT_NAME = 255; const int MPI_MAX_ERROR_STRING = 255; diff --git a/src/core/mpi/RecvBuffer.h b/src/core/mpi/RecvBuffer.h index c35b0c2aa..b3dacb3db 100644 --- a/src/core/mpi/RecvBuffer.h +++ b/src/core/mpi/RecvBuffer.h @@ -189,9 +189,9 @@ typedef GenericRecvBuffer<> RecvBuffer; template< typename T > // Element type inline GenericRecvBuffer<T>::GenericRecvBuffer() : capacity_( 0 ) // Capacity of the receive buffer - , begin_ ( NULL ) // Pointer to the first element - , cur_ ( NULL ) // Pointer to the current element - , end_ ( NULL ) // Pointer to the last element + , begin_ ( nullptr ) // Pointer to the first element + , cur_ ( nullptr ) // Pointer to the current element + , end_ ( nullptr ) // Pointer to the last element {} //********************************************************************************************************************** @@ -615,9 +615,9 @@ inline void GenericRecvBuffer<T>::reset() { delete [] begin_; capacity_ = 0; - begin_ = NULL; - cur_ = NULL; - end_ = NULL; + begin_ = nullptr; + cur_ = nullptr; + end_ = nullptr; } //********************************************************************************************************************** diff --git a/src/core/mpi/Reduce.h b/src/core/mpi/Reduce.h index f60502868..c93e9443f 100644 --- a/src/core/mpi/Reduce.h +++ b/src/core/mpi/Reduce.h @@ -93,7 +93,7 @@ void reduceInplace( T & value, Operation operation, int recvRank = 0, MPI_Comm c } else { - MPI_Reduce( &value, 0, 1, MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( &value, nullptr, 1, MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); } } @@ -130,7 +130,7 @@ inline void reduceInplace( bool & value, Operation operation, int recvRank = 0, } else { - MPI_Reduce( &intValue, 0, 1, MPITrait<int>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( &intValue, nullptr, 1, MPITrait<int>::type(), toMPI_Op(operation), recvRank, comm ); } value = intValue != 0; @@ -174,7 +174,7 @@ T reduce( const T value, Operation operation, int recvRank = 0, MPI_Comm comm = } else { - MPI_Reduce( const_cast<T*>( &value ), 0, 1, MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( const_cast<T*>( &value ), nullptr, 1, MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); } return result; @@ -215,7 +215,7 @@ inline bool reduce( const bool value, Operation operation, int recvRank = 0, MPI } else { - MPI_Reduce( &intValue, 0, 1, MPITrait<int>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( &intValue, nullptr, 1, MPITrait<int>::type(), toMPI_Op(operation), recvRank, comm ); } return intResult != 0; @@ -251,11 +251,11 @@ void reduceInplace( std::vector<T> & values, Operation operation, int recvRank = if( myRank == recvRank ) { - MPI_Reduce( MPI_IN_PLACE, values.empty() ? 0 : &values[0], int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( MPI_IN_PLACE, values.empty() ? nullptr : &values[0], int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); } else { - MPI_Reduce( values.empty() ? 0 : &values[0], 0, int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( values.empty() ? nullptr : &values[0], nullptr, int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), recvRank, comm ); } } @@ -291,14 +291,14 @@ inline void reduceInplace( std::vector<bool> & values, Operation operation, int if( myRank == recvRank ) { - MPI_Reduce( MPI_IN_PLACE, sendBuffer.empty() ? 0 : &sendBuffer[0], int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( MPI_IN_PLACE, sendBuffer.empty() ? nullptr : &sendBuffer[0], int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), recvRank, comm ); size_t size = values.size(); convert( sendBuffer, values ); values.resize(size); } else { - MPI_Reduce( sendBuffer.empty() ? 0 : &sendBuffer[0], 0, int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), recvRank, comm ); + MPI_Reduce( sendBuffer.empty() ? nullptr : &sendBuffer[0], nullptr, int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), recvRank, comm ); } } @@ -426,7 +426,7 @@ void allReduceInplace( std::vector<T> & values, Operation operation, MPI_Comm co WALBERLA_NON_MPI_SECTION() { return; } - MPI_Allreduce( MPI_IN_PLACE, values.empty() ? 0 : &values[0], int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), comm ); + MPI_Allreduce( MPI_IN_PLACE, values.empty() ? nullptr : &values[0], int_c( values.size() ), MPITrait<T>::type(), toMPI_Op(operation), comm ); } @@ -451,7 +451,7 @@ inline void allReduceInplace( std::vector<bool> & bools, Operation operation, MP std::vector<uint8_t> sendBuffer; convert( bools, sendBuffer ); - MPI_Allreduce( MPI_IN_PLACE, sendBuffer.empty() ? 0 : &sendBuffer[0], int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), comm ); + MPI_Allreduce( MPI_IN_PLACE, sendBuffer.empty() ? nullptr : &sendBuffer[0], int_c( sendBuffer.size() ), MPITrait<uint8_t>::type(), toMPI_Op(operation), comm ); auto size = bools.size(); convert(sendBuffer, bools); bools.resize(size); diff --git a/src/core/selectable/SelectableObject.h b/src/core/selectable/SelectableObject.h index 7f317c115..6a282536d 100644 --- a/src/core/selectable/SelectableObject.h +++ b/src/core/selectable/SelectableObject.h @@ -138,7 +138,7 @@ public: - virtual ~SelectableObject() {} + virtual ~SelectableObject() = default; void add( const T& object, const A& attributes, const std::string& identifier = std::string() ); @@ -221,7 +221,7 @@ size_t SelectableObject<T,A,S>::get( T& object, const S& selector ) const { select( index, selector ); - if( index.size() >= 1 ) { + if( !index.empty() ) { WALBERLA_ASSERT_LESS( index[0], object_.size() ); object = object_[ index[0] ]; } @@ -270,7 +270,7 @@ size_t SelectableObject<T,A,S>::get( T& object, std::string& identifier, const S select( index, selector ); - if( index.size() >= 1 ) { + if( !index.empty() ) { WALBERLA_ASSERT_LESS( index[0], object_.size() ); object = object_[ index[0] ]; identifier = identifier_[ index[0] ]; @@ -325,7 +325,7 @@ const T* SelectableObject<T,A,S>::getUnique( const S& selector ) const { return &(object_[ index[0] ]); } - return NULL; + return nullptr; } @@ -363,7 +363,7 @@ const T* SelectableObject<T,A,S>::getUnique( const S& selector, std::string & id return &(object_[ index[0] ]); } - return NULL; + return nullptr; } diff --git a/src/core/selectable/SetSelectableObject.h b/src/core/selectable/SetSelectableObject.h index 8c88a3f23..e43740aef 100644 --- a/src/core/selectable/SetSelectableObject.h +++ b/src/core/selectable/SetSelectableObject.h @@ -49,14 +49,14 @@ class SetSelectableObject : public SelectableObject< T, SetSelectionPair<U>, Set { public: - SetSelectableObject() {} + SetSelectableObject() = default; SetSelectableObject( const T& object, const Set<U>& include, const Set<U>& exclude, const std::string& identifier = std::string() ) { add( object, include, exclude, identifier ); } - virtual ~SetSelectableObject() {} + ~SetSelectableObject() override = default; void add( const T& object, const Set<U>& include, const Set<U>& exclude, const std::string& identifier = std::string() ) { @@ -73,7 +73,7 @@ private: }; // added inline qualifier to suppress unjustified MSVC warning C4505 - virtual inline void select( std::vector< size_t >& index, const Set<U>& selector ) const; + inline void select( std::vector< size_t >& index, const Set<U>& selector ) const override; }; // SetSelectableObject diff --git a/src/core/singleton/Singleton.h b/src/core/singleton/Singleton.h index ead687d0c..f1e5975df 100644 --- a/src/core/singleton/Singleton.h +++ b/src/core/singleton/Singleton.h @@ -70,14 +70,14 @@ protected: // In case a cyclic lifetime dependency is detected, a compilation error is created. */ explicit Singleton() - {} + = default; //******************************************************************************************************************* //**Destructor******************************************************************************************************* /*!\brief Destructor for the Singleton class. */ ~Singleton() - {} + = default; //******************************************************************************************************************* public: diff --git a/src/core/timing/TimingNode.h b/src/core/timing/TimingNode.h index acd33ecd2..a99dfe05b 100644 --- a/src/core/timing/TimingNode.h +++ b/src/core/timing/TimingNode.h @@ -76,14 +76,14 @@ struct TimingNode template< typename TP > // Timing policy TimingNode<TP>::TimingNode() - : last_(NULL) + : last_(nullptr) { } template< typename TP > // Timing policy TimingNode<TP>::TimingNode(const TimingNode<TP>& tn) - : last_(NULL) + : last_(nullptr) , timer_(tn.timer_) , tree_(tn.tree_) { @@ -301,11 +301,11 @@ void reduceInplace( TimingNode<TP>& tn, ReduceType rt = REDUCE_TOTAL, int target if( targetRank >= 0 ) { - void * minTarget = targetRank == rank ? &minRed.front() : NULL; - void * maxTarget = targetRank == rank ? &maxRed.front() : NULL; - void * sumTarget = targetRank == rank ? &sumRed.front() : NULL; - void * sumSqTarget = targetRank == rank ? &sumSqRed.front() : NULL; - void * countTarget = targetRank == rank ? &countRed.front() : NULL; + void * minTarget = targetRank == rank ? &minRed.front() : nullptr; + void * maxTarget = targetRank == rank ? &maxRed.front() : nullptr; + void * sumTarget = targetRank == rank ? &sumRed.front() : nullptr; + void * sumSqTarget = targetRank == rank ? &sumSqRed.front() : nullptr; + void * countTarget = targetRank == rank ? &countRed.front() : nullptr; MPI_Reduce( &min.front(), minTarget, int_c(min.size()), MPITrait<double>::type(), MPI_MIN, targetRank,MPI_COMM_WORLD ); diff --git a/src/core/timing/TimingPool.h b/src/core/timing/TimingPool.h index 5e8fd7104..b927151ac 100644 --- a/src/core/timing/TimingPool.h +++ b/src/core/timing/TimingPool.h @@ -63,7 +63,7 @@ public: //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ //@{ - TimingPool() {} + TimingPool() = default; //@} //******************************************************************************************************************* diff --git a/src/core/timing/TimingTree.h b/src/core/timing/TimingTree.h index b4f4e736b..7fe833b1e 100644 --- a/src/core/timing/TimingTree.h +++ b/src/core/timing/TimingTree.h @@ -179,9 +179,7 @@ bool TimingTree<TP>::isTimerRunning(const std::string& name) const { WALBERLA_ASSERT_NOT_NULLPTR( current_->last_ ); auto timerIt = current_->last_->tree_.find(name); - if ((timerIt == current_->last_->tree_.end()) || (&(timerIt->second) != current_)) - return false; - return true; + return !((timerIt == current_->last_->tree_.end()) || (&(timerIt->second) != current_)); } template< typename TP > // Timing policy diff --git a/src/domain_decomposition/BlockDataHandling.h b/src/domain_decomposition/BlockDataHandling.h index 4bd96dae0..4b07594e0 100644 --- a/src/domain_decomposition/BlockDataHandling.h +++ b/src/domain_decomposition/BlockDataHandling.h @@ -47,7 +47,7 @@ class BlockDataHandling public: typedef T value_type; - virtual ~BlockDataHandling() {} + virtual ~BlockDataHandling() = default; /// must be thread-safe ! virtual T * initialize( IBlock * const block ) = 0; @@ -66,11 +66,11 @@ template< typename T > class AlwaysInitializeBlockDataHandling : public BlockDataHandling<T> { public: - ~AlwaysInitializeBlockDataHandling() {} + ~AlwaysInitializeBlockDataHandling() override = default; - void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) {} - T * deserialize( IBlock * const block ) { return this->initialize( block ); } - void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) {} + void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) override {} + T * deserialize( IBlock * const block ) override { return this->initialize( block ); } + void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) override {} }; @@ -86,25 +86,25 @@ public: BlockDataHandlingFunctionAdaptor( const Function & function ) : function_( function ) {} - ~BlockDataHandlingFunctionAdaptor() {} + ~BlockDataHandlingFunctionAdaptor() override = default; - T * initialize( IBlock * const block ) { return function_( block ); } + T * initialize( IBlock * const block ) override { return function_( block ); } - void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) + void serialize( IBlock * const, const BlockDataID &, mpi::SendBuffer & ) override { WALBERLA_ABORT( "You are trying to serialize a block data item for which only an initialization function was registered" ); #ifdef __IBMCPP__ return NULL; // never reached, helps to suppress a warning from the IBM compiler #endif } - T * deserialize( IBlock * const ) + T * deserialize( IBlock * const ) override { WALBERLA_ABORT( "You are trying to deserialize a block data item for which only an initialization function was registered" ); #ifdef __IBMCPP__ return NULL; // never reached, helps to suppress a warning from the IBM compiler #endif } - void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) + void deserialize( IBlock * const, const BlockDataID &, mpi::RecvBuffer & ) override { WALBERLA_ABORT( "You are trying to deserialize a block data item for which only an initialization function was registered" ); } @@ -155,7 +155,7 @@ namespace internal { class BlockDataHandlingWrapper { public: - virtual ~BlockDataHandlingWrapper() {} + virtual ~BlockDataHandlingWrapper() = default; virtual BlockData * initialize( IBlock * const block ) = 0; @@ -173,27 +173,27 @@ public: BlockDataHandlingHelper( const shared_ptr< BlockDataHandling<T> > & dataHandling ) : dataHandling_( dataHandling ) {} - BlockData * initialize( IBlock * const block ) + BlockData * initialize( IBlock * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->initialize( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) + void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->serialize( block, id, buffer ); } - BlockData * deserialize( IBlock * const block ) + BlockData * deserialize( IBlock * const block ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); T * ptr = dataHandling_->deserialize( block ); - return ptr ? new BlockData( ptr ) : NULL; + return ptr ? new BlockData( ptr ) : nullptr; } - void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override { WALBERLA_ASSERT_NOT_NULLPTR( block ); dataHandling_->deserialize( block, id, buffer ); diff --git a/src/domain_decomposition/BlockStorage.h b/src/domain_decomposition/BlockStorage.h index e00f3ee86..0d6dfc6c1 100644 --- a/src/domain_decomposition/BlockStorage.h +++ b/src/domain_decomposition/BlockStorage.h @@ -87,8 +87,7 @@ public: using pointer = IBlock*; using reference = IBlock&; - iterator( const iterator & it ) : - it_( it.it_ ), end_( it.end_ ), requiredSelectors_( it.requiredSelectors_ ), incompatibleSelectors_( it.incompatibleSelectors_ ) {} + iterator( const iterator & it ) = default; iterator & operator++() { ++it_; checkStateAndAdapt(); return *this; } // prefix ++X iterator operator++(int) { iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -133,8 +132,7 @@ public: const_iterator( const iterator & it ) : it_( it.it_ ), end_( it.end_ ), requiredSelectors_( it.requiredSelectors_ ), incompatibleSelectors_( it.incompatibleSelectors_ ) {} - const_iterator( const const_iterator & it ) : - it_( it.it_ ), end_( it.end_ ), requiredSelectors_( it.requiredSelectors_ ), incompatibleSelectors_( it.incompatibleSelectors_ ) {} + const_iterator( const const_iterator & it ) = default; const_iterator & operator++() { ++it_; checkStateAndAdapt(); return *this; } // prefix ++X const_iterator operator++(int) { const_iterator it( *this ); operator++(); return it; }; // postfix X++ @@ -285,7 +283,7 @@ public: if( it != iBlocks_.end()) return it->second; - return NULL; + return nullptr; } //******************************************************************************************************************* @@ -306,7 +304,7 @@ public: if( it != iBlocks_.end()) return it->second; - return NULL; + return nullptr; } //******************************************************************************************************************* diff --git a/src/domain_decomposition/IBlock.h b/src/domain_decomposition/IBlock.h index c25c55ee9..27c0b894f 100644 --- a/src/domain_decomposition/IBlock.h +++ b/src/domain_decomposition/IBlock.h @@ -50,7 +50,7 @@ private: class DataBase { public: - virtual ~DataBase() {} + virtual ~DataBase() = default; virtual bool operator==( const DataBase& rhs ) const = 0; virtual bool isOfSameType( const DataBase& rhs ) const = 0; }; @@ -59,13 +59,13 @@ private: class Data : public DataBase { public: Data( T* data ) : data_( data ) {} - ~Data() { delete data_; } - bool operator==( const DataBase& rhs ) const { + ~Data() override { delete data_; } + bool operator==( const DataBase& rhs ) const override { const Data<T>* rhsData = dynamic_cast< const Data<T>* >( &rhs ); return ( rhsData == &rhs ) && ( *data_ == *(rhsData->data_) ); // every object that is registered as block data // must be comparable with "==" ! } - bool isOfSameType( const DataBase& rhs ) const { return dynamic_cast< const Data<T>* >( &rhs ) == &rhs; } + bool isOfSameType( const DataBase& rhs ) const override { return dynamic_cast< const Data<T>* >( &rhs ) == &rhs; } private: T* data_; }; @@ -299,7 +299,7 @@ inline bool IBlock::isBlockDataAllocated( const ConstBlockDataID & index ) const WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); - return ( data_[index] != NULL ); + return ( data_[index] != nullptr ); } @@ -314,8 +314,8 @@ inline const T* IBlock::getData( const ConstBlockDataID & index ) const { WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); - if( data_[index] == NULL ) - return NULL; + if( data_[index] == nullptr ) + return nullptr; return data_[index]->template get< T >(); } @@ -337,8 +337,8 @@ inline const T* IBlock::getData( const BlockDataID & index ) const { WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); - if( data_[index] == NULL ) - return NULL; + if( data_[index] == nullptr ) + return nullptr; return data_[index]->template get< T >(); } @@ -368,7 +368,7 @@ inline void IBlock::deleteData( const BlockDataID & index ) { WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); delete data_[index]; - data_[index] = NULL; + data_[index] = nullptr; } @@ -445,9 +445,9 @@ inline bool IBlock::isDataOfSameType( const ConstBlockDataID & indexA, const Con inline void IBlock::addData( const BlockDataID & index, BlockData * const data ) { if( data_.size() <= index ) - data_.resize( index+1, NULL ); + data_.resize( index+1, nullptr ); - if( data != NULL ) { + if( data != nullptr ) { WALBERLA_ASSERT_NULLPTR( data_[index] ); data_[index] = data; } @@ -465,7 +465,7 @@ inline const T* IBlock::uncheckedFastGetData( const ConstBlockDataID & index ) c WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); - if( data_[index] == NULL ) + if( data_[index] == nullptr ) return NULL; return data_[index]->template uncheckedFastGet< T >(); @@ -485,8 +485,8 @@ inline const T* IBlock::uncheckedFastGetData( const BlockDataID & index ) const WALBERLA_ASSERT_LESS( uint_t( index ), data_.size() ); - if( data_[index] == NULL ) - return NULL; + if( data_[index] == nullptr ) + return nullptr; return data_[index]->template uncheckedFastGet< T >(); } diff --git a/src/domain_decomposition/IBlockID.h b/src/domain_decomposition/IBlockID.h index c30f83fdf..e73a50101 100644 --- a/src/domain_decomposition/IBlockID.h +++ b/src/domain_decomposition/IBlockID.h @@ -46,7 +46,7 @@ public: /// ID type which can be used as a key in a map typedef uint64_t IDType; - virtual ~IBlockID() {} + virtual ~IBlockID() = default; virtual bool operator< ( const IBlockID& rhs ) const = 0; virtual bool operator==( const IBlockID& rhs ) const = 0; diff --git a/src/domain_decomposition/StructuredBlockStorage.h b/src/domain_decomposition/StructuredBlockStorage.h index 752107f47..8a44ebfd8 100644 --- a/src/domain_decomposition/StructuredBlockStorage.h +++ b/src/domain_decomposition/StructuredBlockStorage.h @@ -426,7 +426,7 @@ protected: StructuredBlockStorage( const shared_ptr<BlockStorage> & blockStorage, const std::vector< uint_t > & xCells, const std::vector< uint_t > & yCells, const std::vector< uint_t > & zCells ); - virtual ~StructuredBlockStorage() {} ///< Must not be made public! No one should be allowed to delete a variable of type 'StructuredBlockStorage*' + virtual ~StructuredBlockStorage() = default; ///< Must not be made public! No one should be allowed to delete a variable of type 'StructuredBlockStorage*' void resetCellDecomposition( const std::vector< uint_t > & xCells, const std::vector< uint_t > & yCells, const std::vector< uint_t > & zCells ); @@ -437,7 +437,7 @@ protected: { public: CellBoundingBoxHandling( const StructuredBlockStorage & storage ) : storage_( storage ) {} - CellInterval * initialize( IBlock * const block ) { return storage_.initializeCellBoundingBox( block ); } + CellInterval * initialize( IBlock * const block ) override { return storage_.initializeCellBoundingBox( block ); } private: const StructuredBlockStorage & storage_; }; @@ -693,10 +693,10 @@ inline const IBlock* StructuredBlockStorage::getBlock( const Cell& cell, const u getCellCenter( x, y, z, cell, level ); const IBlock* block = blockStorage_->getBlock(x,y,z); - if( block == NULL ) - return NULL; + if( block == nullptr ) + return nullptr; - return ( getLevel( *block ) == level ) ? block : NULL; + return ( getLevel( *block ) == level ) ? block : nullptr; } @@ -716,10 +716,10 @@ inline IBlock* StructuredBlockStorage::getBlock( const Cell& cell, const uint_t getCellCenter( x, y, z, cell, level ); IBlock* block = blockStorage_->getBlock(x,y,z); - if( block == NULL ) - return NULL; + if( block == nullptr ) + return nullptr; - return ( getLevel( *block ) == level ) ? block : NULL; + return ( getLevel( *block ) == level ) ? block : nullptr; } diff --git a/src/executiontree/ExecutionTree.h b/src/executiontree/ExecutionTree.h index f9c838ec6..b9d39d798 100644 --- a/src/executiontree/ExecutionTree.h +++ b/src/executiontree/ExecutionTree.h @@ -107,7 +107,7 @@ std::ostream &operator<<( std::ostream &os, const IFunctionNode &node ); class IFunctionNode { public: - virtual ~IFunctionNode() {} + virtual ~IFunctionNode() = default; virtual void operator()() = 0; virtual std::string getName() const = 0; virtual std::deque< shared_ptr< IFunctionNode > > getChildren() const { return {}; } @@ -122,7 +122,7 @@ public: const std::string &name, const TimingTreePtr & timingTree ); - std::string getName() const override { return name_ != "" ? name_ : "Functor"; }; + std::string getName() const override { return !name_.empty() ? name_ : "Functor"; }; void operator() () override; private: @@ -158,7 +158,7 @@ public: void push_back( const IFunctionNodePtr &fct ) { children_.push_back( fct ); } void push_front( const IFunctionNodePtr &fct ) { children_.push_front( fct ); } - std::string getName() const override { return name_ != "" ? name_ : "Sequence"; }; + std::string getName() const override { return !name_.empty() ? name_ : "Sequence"; }; std::deque< IFunctionNodePtr > getChildren() const override { return children_; }; private: diff --git a/src/field/EvaluationFilter.h b/src/field/EvaluationFilter.h index b4ef168ef..7c9ac2c1e 100644 --- a/src/field/EvaluationFilter.h +++ b/src/field/EvaluationFilter.h @@ -69,7 +69,7 @@ class FlagFieldEvaluationFilter public: FlagFieldEvaluationFilter( const ConstBlockDataID & flagFieldId, const Set< FlagUID > & cellsToEvaluate ) : - flagFieldId_( flagFieldId ), flagField_( NULL ), cellsToEvaluate_( cellsToEvaluate ) {} + flagFieldId_( flagFieldId ), flagField_( nullptr ), cellsToEvaluate_( cellsToEvaluate ) {} void operator()( const IBlock & block ) { diff --git a/src/field/Field.impl.h b/src/field/Field.impl.h index 4856de7ee..a70bdf813 100644 --- a/src/field/Field.impl.h +++ b/src/field/Field.impl.h @@ -45,7 +45,7 @@ namespace field { *******************************************************************************************************************/ template<typename T, uint_t fSize_> Field<T,fSize_>::Field( ) - : values_( NULL ), valuesWithOffset_( NULL ), + : values_( nullptr ), valuesWithOffset_( nullptr ), xSize_(0), ySize_(0), zSize_(0), xAllocSize_(0), yAllocSize_(0), zAllocSize_(0), fAllocSize_(0) { @@ -63,7 +63,7 @@ namespace field { template<typename T, uint_t fSize_> Field<T,fSize_>::Field( uint_t _xSize, uint_t _ySize, uint_t _zSize, const Layout & l, const shared_ptr<FieldAllocator<T> > &alloc ) - : values_( NULL ), valuesWithOffset_( NULL ) + : values_( nullptr ), valuesWithOffset_( nullptr ) { init(_xSize,_ySize,_zSize,l,alloc); } @@ -82,7 +82,7 @@ namespace field { template<typename T, uint_t fSize_> Field<T,fSize_>::Field( uint_t _xSize, uint_t _ySize, uint_t _zSize, const T & initVal, const Layout & l, const shared_ptr<FieldAllocator<T> > &alloc ) - : values_( NULL ), valuesWithOffset_( NULL ) + : values_( nullptr ), valuesWithOffset_( nullptr ) { init(_xSize,_ySize,_zSize,l,alloc); set(initVal); @@ -122,8 +122,8 @@ namespace field { return; allocator_->decrementReferenceCount( values_ ); - values_ = NULL; - valuesWithOffset_ = NULL; + values_ = nullptr; + valuesWithOffset_ = nullptr; init( _xSize, _ySize, _zSize, layout_, allocator_ ); } @@ -314,7 +314,7 @@ namespace field { WALBERLA_ASSERT_NULLPTR( valuesWithOffset_ ); // Automatically select allocator if none was given - if ( alloc == 0 ) + if ( alloc == nullptr ) { #ifdef __BIGGEST_ALIGNMENT__ const uint_t alignment = __BIGGEST_ALIGNMENT__; @@ -340,7 +340,7 @@ namespace field { allocator_ = alloc; allocator_->setInnerGhostLayerSize( innerGhostLayerSizeForAlignedAlloc ); - values_ = 0; + values_ = nullptr; xSize_ = _xSize; ySize_ = _ySize; zSize_ = _zSize; diff --git a/src/field/FlagField.h b/src/field/FlagField.h index 62f9deef5..ebf17fb39 100644 --- a/src/field/FlagField.h +++ b/src/field/FlagField.h @@ -111,7 +111,7 @@ public: FlagField( uint_t xSize, uint_t ySize, uint_t zSize, uint_t gl, const shared_ptr<FieldAllocator<T> > &alloc = make_shared<StdFieldAlloc<T> >()); - virtual ~FlagField(); + ~FlagField() override; inline FlagField<T> * clone() const; inline FlagField<T> * cloneUninitialized() const; @@ -196,7 +196,7 @@ protected: /*! \name Shallow Copy */ //@{ FlagField(const FlagField<T> & other); - virtual Field<T,1> * cloneShallowCopyInternal() const; + Field<T,1> * cloneShallowCopyInternal() const override; //@} //******************************************************************************************************************* diff --git a/src/field/GhostLayerField.h b/src/field/GhostLayerField.h index e6c8b454c..9a1a57704 100644 --- a/src/field/GhostLayerField.h +++ b/src/field/GhostLayerField.h @@ -90,7 +90,7 @@ namespace field { const std::vector<T> & fValues, const Layout & layout = zyxf, const shared_ptr<FieldAllocator<T> > &alloc = shared_ptr<FieldAllocator<T> >() ); - virtual ~GhostLayerField() {} + ~GhostLayerField() override = default; @@ -102,7 +102,7 @@ namespace field { const shared_ptr<FieldAllocator<T> > &alloc = shared_ptr<FieldAllocator<T> >() ); - virtual void resize( uint_t xSize, uint_t ySize, uint_t zSize ); + void resize( uint_t xSize, uint_t ySize, uint_t zSize ) override; void resize( uint_t xSize, uint_t ySize, uint_t zSize, uint_t gl ); using Field<T,fSize_>::resize; @@ -200,8 +200,8 @@ namespace field { /*! \name Slicing */ //@{ GhostLayerField<T,fSize_> * getSlicedField( const CellInterval & interval ) const; - virtual void slice ( const CellInterval & interval ); - virtual void shiftCoordinates( cell_idx_t cx, cell_idx_t cy, cell_idx_t cz ); + void slice ( const CellInterval & interval ) override; + void shiftCoordinates( cell_idx_t cx, cell_idx_t cy, cell_idx_t cz ) override; //@} //**************************************************************************************************************** @@ -214,8 +214,8 @@ namespace field { //** Shallow Copy ************************************************************************************************ /*! \name Shallow Copy */ //@{ - virtual Field<T,fSize_> * cloneShallowCopyInternal() const; - virtual typename Field<T,fSize_>::FlattenedField * flattenedShallowCopyInternal() const; + Field<T,fSize_> * cloneShallowCopyInternal() const override; + typename Field<T,fSize_>::FlattenedField * flattenedShallowCopyInternal() const override; GhostLayerField(const GhostLayerField<T,fSize_> & other); template <typename T2, uint_t fSize2> GhostLayerField(const GhostLayerField<T2, fSize2> & other); diff --git a/src/field/GhostLayerField.impl.h b/src/field/GhostLayerField.impl.h index 5a8c6cc7a..8e122c36a 100644 --- a/src/field/GhostLayerField.impl.h +++ b/src/field/GhostLayerField.impl.h @@ -369,15 +369,12 @@ namespace field { template<typename T, uint_t fSize_> bool GhostLayerField<T,fSize_>::isInInnerPart( const Cell & cell ) const { - if ( cell[0] < 0 || + return !(cell[0] < 0 || cell[1] < 0 || cell[2] < 0 || cell[0] >= cell_idx_c( this->xSize() ) || cell[1] >= cell_idx_c( this->ySize() ) || - cell[2] >= cell_idx_c( this->zSize() ) ) - return false; - - return true; + cell[2] >= cell_idx_c( this->zSize() )); } //******************************************************************************************************************* diff --git a/src/field/StabilityChecker.h b/src/field/StabilityChecker.h index 8a6e80b28..85a29e725 100644 --- a/src/field/StabilityChecker.h +++ b/src/field/StabilityChecker.h @@ -184,9 +184,9 @@ private: protected: - void configure() {} + void configure() override {} - uint8_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + uint8_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { WALBERLA_ASSERT( map_.find( this->block_ ) != map_.end() ); WALBERLA_ASSERT( map_[ this->block_ ].find( Cell(x,y,z) ) != map_[ this->block_ ].end() ); @@ -205,8 +205,8 @@ private: public: LocalCoordVTKWriter( const std::string & id ) : vtk::BlockCellDataWriter< cell_idx_t, 3 >( id ) {} protected: - void configure() {} - cell_idx_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + void configure() override {} + cell_idx_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { return ( f == cell_idx_t(0) ) ? x : ( ( f == cell_idx_t(1) ) ? y : z ); } @@ -218,8 +218,8 @@ private: public: GlobalCoordVTKWriter( const std::string & id ) : vtk::BlockCellDataWriter< cell_idx_t, 3 >( id ) {} protected: - void configure() {} - cell_idx_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + void configure() override {} + cell_idx_t evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { Cell cell(x,y,z); this->blockStorage_->transformBlockLocalToGlobalCell( cell, *(this->block_) ); diff --git a/src/field/SymmetryCheck.h b/src/field/SymmetryCheck.h index 8aa914352..ec9237b54 100644 --- a/src/field/SymmetryCheck.h +++ b/src/field/SymmetryCheck.h @@ -41,7 +41,7 @@ namespace field { */ //******************************************************************************************************************* template< typename Field_T > - bool isSymmetric( const Field_T * field, uint_t dimension, uint_t fCoord = 0, Cell * differingCell = NULL ) + bool isSymmetric( const Field_T * field, uint_t dimension, uint_t fCoord = 0, Cell * differingCell = nullptr ) { WALBERLA_ASSERT_LESS( dimension, 3 ); @@ -63,7 +63,7 @@ namespace field { auto value2 = field->get( compareCell, fCoord ); if ( ! math::equal( value1, value2 ) ) { - if ( differingCell != NULL ) + if ( differingCell != nullptr ) *differingCell = currentCell; return false; diff --git a/src/field/adaptors/AdaptorCreators.h b/src/field/adaptors/AdaptorCreators.h index 1c410ca91..56bfff201 100644 --- a/src/field/adaptors/AdaptorCreators.h +++ b/src/field/adaptors/AdaptorCreators.h @@ -43,7 +43,7 @@ public: AdaptorHandling( const ConstBlockDataID & adaptedFieldId, const AdaptionFunction_T & function ) : adaptedFieldId_( adaptedFieldId ), function_( function ) {} - Adaptor_T * initialize( IBlock * const block ) + Adaptor_T * initialize( IBlock * const block ) override { typedef typename Adaptor_T::basefield_t AdaptedField_T; const AdaptedField_T * adaptedField = block->getData< AdaptedField_T >( adaptedFieldId_ ); diff --git a/src/field/adaptors/GhostLayerFieldAdaptor.h b/src/field/adaptors/GhostLayerFieldAdaptor.h index f26f87b0a..3b22ae6ef 100644 --- a/src/field/adaptors/GhostLayerFieldAdaptor.h +++ b/src/field/adaptors/GhostLayerFieldAdaptor.h @@ -112,7 +112,7 @@ public: // since Field/GhostLayerField is polymorphic, this class also has to be polymorphic // example: dynamic_cast< field_t > would fail if field_t = GhostLayerFieldAdaptor - virtual ~GhostLayerFieldAdaptor() {} + virtual ~GhostLayerFieldAdaptor() = default; const functor_t & getFunctor() const { return functor_; } diff --git a/src/field/allocation/FieldAllocator.h b/src/field/allocation/FieldAllocator.h index f78771e15..781cda4bc 100644 --- a/src/field/allocation/FieldAllocator.h +++ b/src/field/allocation/FieldAllocator.h @@ -238,8 +238,8 @@ namespace field { protected: - virtual T * allocateMemory ( uint_t size0, uint_t size1, uint_t size2, uint_t size3, - uint_t & allocSize1, uint_t & allocSize2, uint_t & allocSize3) + T * allocateMemory ( uint_t size0, uint_t size1, uint_t size2, uint_t size3, + uint_t & allocSize1, uint_t & allocSize2, uint_t & allocSize3) override { allocSize1=size1; allocSize2=size2; @@ -254,7 +254,7 @@ namespace field { return allocateMemory ( size0 * allocSize1 * allocSize2 * allocSize3 ); } - virtual T * allocateMemory ( uint_t size ) + T * allocateMemory ( uint_t size ) override { void * ptr = aligned_malloc_with_offset(size * sizeof(T) + alignment, alignment, offset_ % alignment ); if(!ptr) @@ -274,11 +274,11 @@ namespace field { return ret; } - virtual void setInnerGhostLayerSize( uint_t innerGhostLayerSize ) { + void setInnerGhostLayerSize( uint_t innerGhostLayerSize ) override { offset_ = sizeof(T) * innerGhostLayerSize; } - virtual void deallocate(T *& values ) + void deallocate(T *& values ) override { WALBERLA_ASSERT ( nrOfElements_.find(values) != nrOfElements_.end() ); @@ -328,8 +328,8 @@ namespace field { class StdFieldAlloc : public FieldAllocator<T> { public: - virtual T * allocateMemory ( uint_t size0, uint_t size1, uint_t size2, uint_t size3, - uint_t & allocSize1, uint_t & allocSize2, uint_t & allocSize3) + T * allocateMemory ( uint_t size0, uint_t size1, uint_t size2, uint_t size3, + uint_t & allocSize1, uint_t & allocSize2, uint_t & allocSize3) override { allocSize1=size1; allocSize2=size2; @@ -337,14 +337,14 @@ namespace field { return new T[size0*size1*size2*size3]; } - virtual T * allocateMemory ( uint_t size ) + T * allocateMemory ( uint_t size ) override { return new T[size]; } - virtual void deallocate(T *& values) { + void deallocate(T *& values) override { delete[] values; - values = 0; + values = nullptr; } }; diff --git a/src/field/blockforest/BlockDataHandling.h b/src/field/blockforest/BlockDataHandling.h index dc6328a66..e0caa9869 100644 --- a/src/field/blockforest/BlockDataHandling.h +++ b/src/field/blockforest/BlockDataHandling.h @@ -45,11 +45,11 @@ public: typedef typename Field_T::value_type Value_T; typedef std::function< void ( Field_T * field, IBlock * const block ) > InitializationFunction_T; - virtual ~BlockDataHandling() {} + ~BlockDataHandling() override = default; void addInitializationFunction( const InitializationFunction_T & initFunction ) { initFunction_ = initFunction; } - Field_T * initialize( IBlock * const block ) + Field_T * initialize( IBlock * const block ) override { Field_T * field = allocate( block ); @@ -59,20 +59,20 @@ public: return field; } - inline void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ); + inline void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ); - void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ); + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - Field_T * deserialize( IBlock * const block ) { return reallocate( block ); } + Field_T * deserialize( IBlock * const block ) override { return reallocate( block ); } - Field_T * deserializeCoarseToFine( Block * const block ) { return reallocate( block ); } - Field_T * deserializeFineToCoarse( Block * const block ) { return reallocate( block ); } + Field_T * deserializeCoarseToFine( Block * const block ) override { return reallocate( block ); } + Field_T * deserializeFineToCoarse( Block * const block ) override { return reallocate( block ); } - void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; - void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); - void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ); + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; protected: @@ -421,7 +421,7 @@ public: protected: - GhostLayerField_T * allocate( IBlock * const block ) + GhostLayerField_T * allocate( IBlock * const block ) override { auto blocks = blocks_.lock(); WALBERLA_CHECK_NOT_NULLPTR( blocks, "Trying to access 'DefaultBlockDataHandling' for a block storage object that doesn't exist anymore" ); @@ -430,7 +430,7 @@ protected: nrOfGhostLayers_, initValue_, layout_ ); } - GhostLayerField_T * reallocate( IBlock * const block ) + GhostLayerField_T * reallocate( IBlock * const block ) override { auto blocks = blocks_.lock(); WALBERLA_CHECK_NOT_NULLPTR( blocks, "Trying to access 'DefaultBlockDataHandling' for a block storage object that doesn't exist anymore" ); @@ -484,7 +484,7 @@ public: void addInitializationFunction( const InitializationFunction_T & initFunction ) { initFunction_ = initFunction; } - GhostLayerField_T * initialize( IBlock * const block ) + GhostLayerField_T * initialize( IBlock * const block ) override { auto blocks = blocks_.lock(); WALBERLA_CHECK_NOT_NULLPTR( blocks, "Trying to access 'AlwaysInitializeBlockDataHandling' for a block storage object that doesn't exist anymore" ); @@ -524,7 +524,7 @@ public: fieldToClone_( fieldToClone ) {} - Field_T * initialize( IBlock * const block ) + Field_T * initialize( IBlock * const block ) override { const Field_T * toClone = block->template getData< Field_T >( fieldToClone_ ); return toClone->clone(); @@ -550,7 +550,7 @@ public: fieldToClone_( fieldToClone ) {} - typename Field_T::FlattenedField * initialize( IBlock * const block ) + typename Field_T::FlattenedField * initialize( IBlock * const block ) override { const Field_T * toClone = block->template getData< Field_T >( fieldToClone_ ); return toClone->flattenedShallowCopy(); diff --git a/src/field/blockforest/GradientRefinement.h b/src/field/blockforest/GradientRefinement.h index b05b8d1df..fb7f8b466 100644 --- a/src/field/blockforest/GradientRefinement.h +++ b/src/field/blockforest/GradientRefinement.h @@ -81,7 +81,7 @@ void GradientRefinement< VectorField_T, Filter_T, Pseudo2D >::operator()( std::v const Block * const block = it->first; const VectorField_T * u = block->template getData< VectorField_T >( fieldId_ ); - if( u == NULL ) + if( u == nullptr ) { it->second = uint_t(0); continue; diff --git a/src/field/communication/PackInfo.h b/src/field/communication/PackInfo.h index 0c74f604f..a8e95ce75 100644 --- a/src/field/communication/PackInfo.h +++ b/src/field/communication/PackInfo.h @@ -50,17 +50,17 @@ public: PackInfo( const BlockDataID & bdId, const uint_t numberOfGhostLayers ) : bdId_( bdId ), communicateAllGhostLayers_( false ), numberOfGhostLayers_( numberOfGhostLayers ) {} - virtual ~PackInfo() {} + ~PackInfo() override = default; - bool constantDataExchange() const { return mpi::BufferSizeTrait<T>::constantSize; } - bool threadsafeReceiving() const { return true; } + bool constantDataExchange() const override { return mpi::BufferSizeTrait<T>::constantSize; } + bool threadsafeReceiving() const override { return true; } - void unpackData(IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer); + void unpackData(IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer) override; - void communicateLocal(const IBlock * sender, IBlock * receiver, stencil::Direction dir); + void communicateLocal(const IBlock * sender, IBlock * receiver, stencil::Direction dir) override; protected: - void packDataImpl(const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer) const; + void packDataImpl(const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer) const override; uint_t numberOfGhostLayersToCommunicate( const GhostLayerField_T * const field ) const; diff --git a/src/field/communication/ReducePackInfo.h b/src/field/communication/ReducePackInfo.h index 81a142612..135574dcd 100644 --- a/src/field/communication/ReducePackInfo.h +++ b/src/field/communication/ReducePackInfo.h @@ -50,19 +50,19 @@ public: op_() {} - virtual ~ReducePackInfo() {} + ~ReducePackInfo() override = default; bool constantDataExchange() const { return false; } bool threadsafeReceiving() const { return false; } - virtual void safeCommunicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ); - virtual void packData ( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer ); - virtual void safeUnpackData ( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ); + void safeCommunicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ) override; + void packData ( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer ) override; + void safeUnpackData ( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; size_t getDataSize() const { return getSize() * sizeof(T); } protected: - virtual size_t initData( IBlock * receiver, stencil::Direction dir ); + size_t initData( IBlock * receiver, stencil::Direction dir ) override; const BlockDataID bdId_; const T init_; diff --git a/src/field/communication/StencilRestrictedMPIDatatypeInfo.h b/src/field/communication/StencilRestrictedMPIDatatypeInfo.h index 1150c76ff..64421ee77 100644 --- a/src/field/communication/StencilRestrictedMPIDatatypeInfo.h +++ b/src/field/communication/StencilRestrictedMPIDatatypeInfo.h @@ -39,26 +39,26 @@ class StencilRestrictedMPIDatatypeInfo : public walberla::communication::Uniform public: StencilRestrictedMPIDatatypeInfo( BlockDataID fieldID ) : fieldID_( fieldID ) {} - virtual ~StencilRestrictedMPIDatatypeInfo() {} + ~StencilRestrictedMPIDatatypeInfo() override = default; - virtual shared_ptr<mpi::Datatype> getSendDatatype ( IBlock * block, const stencil::Direction dir ) + shared_ptr<mpi::Datatype> getSendDatatype ( IBlock * block, const stencil::Direction dir ) override { return make_shared<mpi::Datatype>( field::communication::mpiDatatypeSliceBeforeGhostlayerXYZ( *getField( block ), dir, uint_t( 1 ), getOptimizedCommunicationIndices( dir ), false ) ); } - virtual shared_ptr<mpi::Datatype> getRecvDatatype ( IBlock * block, const stencil::Direction dir ) + shared_ptr<mpi::Datatype> getRecvDatatype ( IBlock * block, const stencil::Direction dir ) override { return make_shared<mpi::Datatype>( field::communication::mpiDatatypeGhostLayerOnlyXYZ( *getField( block ), dir, false, getOptimizedCommunicationIndices( stencil::inverseDir[dir] ) ) ); } - virtual void * getSendPointer( IBlock * block, const stencil::Direction ) + void * getSendPointer( IBlock * block, const stencil::Direction ) override { return getField(block)->data(); } - virtual void * getRecvPointer( IBlock * block, const stencil::Direction ) + void * getRecvPointer( IBlock * block, const stencil::Direction ) override { return getField(block)->data(); } diff --git a/src/field/communication/StencilRestrictedPackInfo.h b/src/field/communication/StencilRestrictedPackInfo.h index 72e405845..45527cadf 100644 --- a/src/field/communication/StencilRestrictedPackInfo.h +++ b/src/field/communication/StencilRestrictedPackInfo.h @@ -47,18 +47,18 @@ class StencilRestrictedPackInfo : public walberla::communication::UniformPackInf { public: StencilRestrictedPackInfo( const BlockDataID & fieldId ) : fieldId_( fieldId ) {} - virtual ~StencilRestrictedPackInfo() {} + ~StencilRestrictedPackInfo() override = default; - bool constantDataExchange() const { return true; } - bool threadsafeReceiving() const { return true; } + bool constantDataExchange() const override { return true; } + bool threadsafeReceiving() const override { return true; } - void unpackData( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ); + void unpackData( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; - void communicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ); + void communicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir ) override; protected: - void packDataImpl( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer ) const; + void packDataImpl( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer ) const override; const BlockDataID fieldId_; diff --git a/src/field/communication/UniformMPIDatatypeInfo.h b/src/field/communication/UniformMPIDatatypeInfo.h index 4734344c1..e7042ab57 100644 --- a/src/field/communication/UniformMPIDatatypeInfo.h +++ b/src/field/communication/UniformMPIDatatypeInfo.h @@ -39,26 +39,26 @@ public: UniformMPIDatatypeInfo( BlockDataID blockDataID, const uint_t numberOfGhostLayers ) : blockDataID_( blockDataID ), communicateAllGhostLayers_( false ), numberOfGhostLayers_( numberOfGhostLayers ) {} - virtual ~UniformMPIDatatypeInfo() {} + ~UniformMPIDatatypeInfo() override = default; - virtual shared_ptr<mpi::Datatype> getSendDatatype ( IBlock * block, const stencil::Direction dir ) + shared_ptr<mpi::Datatype> getSendDatatype ( IBlock * block, const stencil::Direction dir ) override { auto numGl = numberOfGhostLayersToCommunicate( block ); return make_shared<mpi::Datatype>( mpiDatatypeSliceBeforeGhostlayer( *getField( block ), dir, numGl ) ); } - virtual shared_ptr<mpi::Datatype> getRecvDatatype ( IBlock * block, const stencil::Direction dir ) + shared_ptr<mpi::Datatype> getRecvDatatype ( IBlock * block, const stencil::Direction dir ) override { auto numGl = numberOfGhostLayersToCommunicate( block ); return make_shared<mpi::Datatype>( mpiDatatypeGhostLayerOnly( *getField(block), numGl, dir ) ); } - virtual void * getSendPointer( IBlock * block, const stencil::Direction ) + void * getSendPointer( IBlock * block, const stencil::Direction ) override { return getField(block)->data(); } - virtual void * getRecvPointer( IBlock * block, const stencil::Direction ) + void * getRecvPointer( IBlock * block, const stencil::Direction ) override { return getField(block)->data(); } diff --git a/src/field/communication/UniformPullReductionPackInfo.h b/src/field/communication/UniformPullReductionPackInfo.h index 71ceb7e8e..4233a3d23 100644 --- a/src/field/communication/UniformPullReductionPackInfo.h +++ b/src/field/communication/UniformPullReductionPackInfo.h @@ -57,17 +57,17 @@ public: UniformPullReductionPackInfo( const BlockDataID & bdID, const uint_t numberOfGhostLayers ) : bdID_( bdID ), communicateAllGhostLayers_( false ), numberOfGhostLayers_( numberOfGhostLayers ) {} - virtual ~UniformPullReductionPackInfo() {} + ~UniformPullReductionPackInfo() override = default; - bool constantDataExchange() const { return mpi::BufferSizeTrait<T>::constantSize; } - bool threadsafeReceiving() const { return true; } + bool constantDataExchange() const override { return mpi::BufferSizeTrait<T>::constantSize; } + bool threadsafeReceiving() const override { return true; } - void unpackData(IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer); + void unpackData(IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer) override; - void communicateLocal(const IBlock * sender, IBlock * receiver, stencil::Direction dir); + void communicateLocal(const IBlock * sender, IBlock * receiver, stencil::Direction dir) override; protected: - void packDataImpl(const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer) const; + void packDataImpl(const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer) const override; uint_t numberOfGhostLayersToCommunicate( const GhostLayerField_T * const field ) const; diff --git a/src/field/distributors/DistributorCreators.h b/src/field/distributors/DistributorCreators.h index e87b907ce..ab555911c 100644 --- a/src/field/distributors/DistributorCreators.h +++ b/src/field/distributors/DistributorCreators.h @@ -65,7 +65,7 @@ public: blockStorage_( blockStorage ), distributionDestinationFieldID_( distributionDestinationFieldID ), flagFieldID_( flagFieldID ), cellsToEvaluate_( cellsToEvaluate ) {} - Distributor_T * initialize( IBlock * const block ) + Distributor_T * initialize( IBlock * const block ) override { typedef typename Distributor_T::BaseField_T DistributionDestinationField_T; typedef typename FlagField_T::flag_t flag_t; diff --git a/src/field/interpolators/FieldInterpolatorCreators.h b/src/field/interpolators/FieldInterpolatorCreators.h index 560df7879..760db9b7c 100644 --- a/src/field/interpolators/FieldInterpolatorCreators.h +++ b/src/field/interpolators/FieldInterpolatorCreators.h @@ -64,7 +64,7 @@ public: blockStorage_( blockStorage ), interpolatedFieldID_( interpolatedFieldID ), flagFieldID_( flagFieldID ), cellsToEvaluate_( cellsToEvaluate ) {} - Interpolator_T * initialize( IBlock * const block ) + Interpolator_T * initialize( IBlock * const block ) override { typedef typename Interpolator_T::BaseField_T InterpolatedField_T; typedef typename FlagField_T::flag_t flag_t; diff --git a/src/field/iterators/FieldIterator.impl.h b/src/field/iterators/FieldIterator.impl.h index 0a132ae01..a643984c8 100644 --- a/src/field/iterators/FieldIterator.impl.h +++ b/src/field/iterators/FieldIterator.impl.h @@ -41,9 +41,9 @@ FieldIterator<T,fs>::FieldIterator( const typename FieldIterator<T,fs>::FieldTyp { if ( field->xyzSize().empty() ) { - linePtr_ = NULL; - lineEnd_ = NULL; - f_ = NULL; + linePtr_ = nullptr; + lineEnd_ = nullptr; + f_ = nullptr; return; } @@ -114,7 +114,7 @@ FieldIterator<T,fs>::FieldIterator( const typename FieldIterator<T,fs>::FieldTyp **********************************************************************************************************************/ template <typename T, uint_t fs> FieldIterator<T,fs>::FieldIterator() - : linePtr_(NULL), lineEnd_(NULL), f_(NULL) + : linePtr_(nullptr), lineEnd_(nullptr), f_(nullptr) { } @@ -228,7 +228,7 @@ inline void FieldIterator<T,fs>::incrementLine() if(cur_[0] == cell_idx_c(sizes_[0]) ) { // iterator at end - linePtr_ = NULL; + linePtr_ = nullptr; return; } } @@ -264,7 +264,7 @@ inline void FieldIterator<T,fs>::decrementLine() if(cur_[0] < 0 ) { // iterator at end - linePtr_ = NULL; + linePtr_ = nullptr; return; } } diff --git a/src/field/refinement/PackInfo.h b/src/field/refinement/PackInfo.h index bfc485289..bc4f68344 100644 --- a/src/field/refinement/PackInfo.h +++ b/src/field/refinement/PackInfo.h @@ -39,25 +39,25 @@ class PackInfo : public blockforest::communication::NonUniformPackInfo public: PackInfo( const BlockDataID & fieldId ) : fieldId_( fieldId ) {} - virtual ~PackInfo() {} + ~PackInfo() override = default; - bool constantDataExchange() const { return true; } - bool threadsafeReceiving() const { return true; } + bool constantDataExchange() const override { return true; } + bool threadsafeReceiving() const override { return true; } - void unpackDataEqualLevel( Block * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalEqualLevel( const Block * sender, Block * receiver, stencil::Direction dir ); + void unpackDataEqualLevel( Block * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalEqualLevel( const Block * sender, Block * receiver, stencil::Direction dir ) override; - void unpackDataCoarseToFine( Block * fineReceiver, const BlockID & coarseSender, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalCoarseToFine( const Block * coarseSender, Block * fineReceiver, stencil::Direction dir ); + void unpackDataCoarseToFine( Block * fineReceiver, const BlockID & coarseSender, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalCoarseToFine( const Block * coarseSender, Block * fineReceiver, stencil::Direction dir ) override; - void unpackDataFineToCoarse( Block * coarseReceiver, const BlockID & fineSender, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalFineToCoarse( const Block * fineSender, Block * coarseReceiver, stencil::Direction dir ); + void unpackDataFineToCoarse( Block * coarseReceiver, const BlockID & fineSender, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalFineToCoarse( const Block * fineSender, Block * coarseReceiver, stencil::Direction dir ) override; protected: - void packDataEqualLevelImpl( const Block * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const; - void packDataCoarseToFineImpl( const Block * coarseSender, const BlockID & fineReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const; - void packDataFineToCoarseImpl( const Block * fineSender, const BlockID & coarseReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const; + void packDataEqualLevelImpl( const Block * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; + void packDataCoarseToFineImpl( const Block * coarseSender, const BlockID & fineReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; + void packDataFineToCoarseImpl( const Block * fineSender, const BlockID & coarseReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; /////////////////////////////////////////////////////////////////////// // Helper functions for determining packing/unpacking cell intervals // diff --git a/src/field/vtk/FlagFieldMapping.h b/src/field/vtk/FlagFieldMapping.h index 8b25ce58e..e496657df 100644 --- a/src/field/vtk/FlagFieldMapping.h +++ b/src/field/vtk/FlagFieldMapping.h @@ -41,7 +41,7 @@ public: vtk::BlockCellDataWriter<T,1>( id ), flagId_( flagId ), flagField_( NULL ) {} FlagFieldMapping( const ConstBlockDataID flagId, const std::string& id, const std::map< FlagUID, T > mapping ) : - vtk::BlockCellDataWriter<T,1>( id ), flagId_( flagId ), flagField_( NULL ), mapping_( mapping ) {} + vtk::BlockCellDataWriter<T,1>( id ), flagId_( flagId ), flagField_( nullptr ), mapping_( mapping ) {} void addMapping( const FlagUID& flag, const T& value ) { @@ -51,7 +51,7 @@ public: protected: - void configure() + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); flagField_ = this->block_->template getData< FlagField_T >( flagId_ ); @@ -64,7 +64,7 @@ protected: } } - T evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) + T evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) override { WALBERLA_ASSERT_NOT_NULLPTR( flagField_ ); T result = 0; diff --git a/src/field/vtk/VTKWriter.h b/src/field/vtk/VTKWriter.h index c83033fe8..a86d8fa52 100644 --- a/src/field/vtk/VTKWriter.h +++ b/src/field/vtk/VTKWriter.h @@ -108,16 +108,16 @@ public: typedef vtk::BlockCellDataWriter<OutputType, OutputTrait::F_SIZE * Field_T::F_SIZE> base_t; VTKWriter( const ConstBlockDataID bdid, const std::string& id ) : - base_t( id ), bdid_( bdid ), field_( NULL ) {} + base_t( id ), bdid_( bdid ), field_( nullptr ) {} protected: - void configure() { + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); field_ = this->block_->template getData< Field_T >( bdid_ ); } - OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { WALBERLA_ASSERT_NOT_NULLPTR( field_ ); diff --git a/src/gather/CellGatherPackInfo.h b/src/gather/CellGatherPackInfo.h index 0055a2ba0..e12e5ab6f 100644 --- a/src/gather/CellGatherPackInfo.h +++ b/src/gather/CellGatherPackInfo.h @@ -79,12 +79,12 @@ public: /*! \name Packing Interface */ //@{ - virtual void packData ( const IBlock * sender, - mpi::SendBuffer & outBuffer ); + void packData ( const IBlock * sender, + mpi::SendBuffer & outBuffer ) override; - virtual void unpackData( mpi::RecvBuffer & buffer ); + void unpackData( mpi::RecvBuffer & buffer ) override; - virtual void gatherFinished(); + void gatherFinished() override; //@} //******************************************************************************************************************* diff --git a/src/gather/CurveGatherPackInfo.h b/src/gather/CurveGatherPackInfo.h index 112f018b3..6bdd3bab0 100644 --- a/src/gather/CurveGatherPackInfo.h +++ b/src/gather/CurveGatherPackInfo.h @@ -106,7 +106,7 @@ class CurveGatherPackInfo : public GatherPackInfo const shared_ptr<DataProcessor> & dp); - virtual ~CurveGatherPackInfo() {} + ~CurveGatherPackInfo() override {} //@} //**************************************************************************************************************** @@ -117,13 +117,13 @@ class CurveGatherPackInfo : public GatherPackInfo /*! \name Packing Interface */ //@{ - virtual void packData ( const IBlock * sender, - mpi::SendBuffer & outBuffer ); + void packData ( const IBlock * sender, + mpi::SendBuffer & outBuffer ) override; - virtual void unpackData( mpi::RecvBuffer & buffer ); + void unpackData( mpi::RecvBuffer & buffer ) override; - virtual void gatherFinished(); + void gatherFinished() override; //@} //**************************************************************************************************************** diff --git a/src/gather/GatherPackInfo.h b/src/gather/GatherPackInfo.h index a4688bc0e..640866581 100644 --- a/src/gather/GatherPackInfo.h +++ b/src/gather/GatherPackInfo.h @@ -38,7 +38,7 @@ namespace gather { class GatherPackInfo { public: - virtual ~GatherPackInfo() {} + virtual ~GatherPackInfo() = default; /**********************************************************************************************************//** * Packs all data to be gathered into the given buffer diff --git a/src/gather/GnuPlotGraphWriter.h b/src/gather/GnuPlotGraphWriter.h index c8a70fbfe..48d09f61a 100644 --- a/src/gather/GnuPlotGraphWriter.h +++ b/src/gather/GnuPlotGraphWriter.h @@ -59,7 +59,7 @@ class GnuPlotGraphWriter : public DataProcessor ++callNr; } - virtual void process(const std::vector<std::vector<real_t> > & data) { writeDataSet(data); } + void process(const std::vector<std::vector<real_t> > & data) override { writeDataSet(data); } private: std::string filename_; diff --git a/src/geometry/bodies/DynamicBody.h b/src/geometry/bodies/DynamicBody.h index 8a0ecfd52..1ebd1670e 100644 --- a/src/geometry/bodies/DynamicBody.h +++ b/src/geometry/bodies/DynamicBody.h @@ -45,15 +45,15 @@ public: : body_(b) {} - virtual bool contains (const Vector3<real_t> & point ) const + bool contains (const Vector3<real_t> & point ) const override { return geometry::contains( body_, point ); } - virtual FastOverlapResult fastOverlapCheck ( const Vector3<real_t> & cellMidpoint, const Vector3<real_t> & dx ) const + FastOverlapResult fastOverlapCheck ( const Vector3<real_t> & cellMidpoint, const Vector3<real_t> & dx ) const override { return geometry::fastOverlapCheck( body_, cellMidpoint, dx ); } - virtual FastOverlapResult fastOverlapCheck ( const AABB & box ) const + FastOverlapResult fastOverlapCheck ( const AABB & box ) const override { return geometry::fastOverlapCheck( body_, box); } diff --git a/src/geometry/containment_octree/IndeterminateLeafNode.h b/src/geometry/containment_octree/IndeterminateLeafNode.h index 349d18369..977c0a1cb 100644 --- a/src/geometry/containment_octree/IndeterminateLeafNode.h +++ b/src/geometry/containment_octree/IndeterminateLeafNode.h @@ -44,7 +44,7 @@ public: IndeterminateLeafNode( const shared_ptr<const DistanceObject> & distanceObject, const Scalar epsilon ) : distanceObject_( distanceObject ), sqEpsilon_( epsilon * epsilon ) { } - virtual ~IndeterminateLeafNode() {} + virtual ~IndeterminateLeafNode() = default; virtual bool contains( const Point & p ) const { return distanceObject_->sqSignedDistance(p) <= sqEpsilon_; } diff --git a/src/geometry/containment_octree/InsideLeafNode.h b/src/geometry/containment_octree/InsideLeafNode.h index f291a5c37..b673d61e1 100644 --- a/src/geometry/containment_octree/InsideLeafNode.h +++ b/src/geometry/containment_octree/InsideLeafNode.h @@ -41,7 +41,7 @@ public: typedef typename LeafNode<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; - virtual ~InsideLeafNode() {} + virtual ~InsideLeafNode() = default; virtual bool contains( const Point & /*p*/ ) const { return true; } diff --git a/src/geometry/containment_octree/LeafNode.h b/src/geometry/containment_octree/LeafNode.h index 57c1b6553..47223f8b5 100644 --- a/src/geometry/containment_octree/LeafNode.h +++ b/src/geometry/containment_octree/LeafNode.h @@ -42,7 +42,7 @@ public: typedef typename Node<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; - virtual ~LeafNode() {} + virtual ~LeafNode() = default; virtual uint_t height() const { return uint_t(0); } virtual uint_t numNodes() const { return uint_t(0); } diff --git a/src/geometry/containment_octree/Node.h b/src/geometry/containment_octree/Node.h index 0a0d03ce6..a1bc9325f 100644 --- a/src/geometry/containment_octree/Node.h +++ b/src/geometry/containment_octree/Node.h @@ -40,7 +40,7 @@ public: typedef typename ContainmentOctreeT::DistanceObject DistanceObject; typedef typename ContainmentOctreeT::KahanAccumulator KahanAccumulator; - virtual ~Node() {} + virtual ~Node() = default; virtual bool contains( const Point & p ) const = 0; virtual uint_t height() const = 0; virtual uint_t numNodes() const = 0; diff --git a/src/geometry/containment_octree/OutsideLeafNode.h b/src/geometry/containment_octree/OutsideLeafNode.h index 2144b4e4d..b5fc61813 100644 --- a/src/geometry/containment_octree/OutsideLeafNode.h +++ b/src/geometry/containment_octree/OutsideLeafNode.h @@ -42,7 +42,7 @@ public: typedef typename LeafNode<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; - virtual ~OutsideLeafNode() {} + virtual ~OutsideLeafNode() = default; virtual bool contains( const Point & /*p*/ ) const { return false; } diff --git a/src/geometry/initializer/BoundaryFromBody.h b/src/geometry/initializer/BoundaryFromBody.h index 0c5c696a9..1eb9e06b7 100644 --- a/src/geometry/initializer/BoundaryFromBody.h +++ b/src/geometry/initializer/BoundaryFromBody.h @@ -79,7 +79,7 @@ public: * The body parameters and the parameters for the boundary are read from configuration. * *****************************************************************************************************************/ - virtual void init( BlockStorage & , const Config::BlockHandle & blockHandle ) { return init(blockHandle); } + void init( BlockStorage & , const Config::BlockHandle & blockHandle ) override { return init(blockHandle); } void init( const Config::BlockHandle & blockHandle ); diff --git a/src/geometry/initializer/BoundaryFromCellInterval.h b/src/geometry/initializer/BoundaryFromCellInterval.h index 80355b49f..f2245274c 100644 --- a/src/geometry/initializer/BoundaryFromCellInterval.h +++ b/src/geometry/initializer/BoundaryFromCellInterval.h @@ -84,7 +84,7 @@ public: * The cell interval and the parameters for the boundary are read from configuration. * *****************************************************************************************************************/ - virtual void init( BlockStorage & , const Config::BlockHandle & blockHandle ) { return init(blockHandle); } + void init( BlockStorage & , const Config::BlockHandle & blockHandle ) override { return init(blockHandle); } void init( const Config::BlockHandle & blockHandle ); diff --git a/src/geometry/initializer/BoundaryFromDomainBorder.h b/src/geometry/initializer/BoundaryFromDomainBorder.h index 9fa993781..9329a72ad 100644 --- a/src/geometry/initializer/BoundaryFromDomainBorder.h +++ b/src/geometry/initializer/BoundaryFromDomainBorder.h @@ -80,7 +80,7 @@ public: void init ( const Config::BlockHandle & blockHandle ); - virtual void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ); + void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ) override; void init( FlagUID flagUID, stencil::Direction direction, diff --git a/src/geometry/initializer/BoundaryFromImage.h b/src/geometry/initializer/BoundaryFromImage.h index 9db375940..d19f4dcbe 100644 --- a/src/geometry/initializer/BoundaryFromImage.h +++ b/src/geometry/initializer/BoundaryFromImage.h @@ -97,7 +97,7 @@ namespace initializer { * Initializes the scalar field using parameters of config block * for syntax see class documentation *****************************************************************************************************************/ - virtual void init ( BlockStorage & , const Config::BlockHandle & block ) { init(block); } + void init ( BlockStorage & , const Config::BlockHandle & block ) override { init(block); } void init( const Config::BlockHandle & block ); diff --git a/src/geometry/initializer/BoundaryFromVoxelFile.h b/src/geometry/initializer/BoundaryFromVoxelFile.h index 6bef2c8c3..3b0640e33 100644 --- a/src/geometry/initializer/BoundaryFromVoxelFile.h +++ b/src/geometry/initializer/BoundaryFromVoxelFile.h @@ -88,7 +88,7 @@ class BoundaryFromVoxelFile : public Initializer public: BoundaryFromVoxelFile( const StructuredBlockStorage & structuredBlockStorage, BlockDataID & boundaryHandlerID ); - virtual void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ); + void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ) override; protected: diff --git a/src/geometry/initializer/BoundarySetterFlagFieldSpecialization.h b/src/geometry/initializer/BoundarySetterFlagFieldSpecialization.h index 1ae6a04e2..f731a37f0 100644 --- a/src/geometry/initializer/BoundarySetterFlagFieldSpecialization.h +++ b/src/geometry/initializer/BoundarySetterFlagFieldSpecialization.h @@ -97,7 +97,7 @@ namespace initializer { ++blockHandleIt; } - if (boundaryConfigBlocks.size () > 0 ) { + if (!boundaryConfigBlocks.empty() ) { WALBERLA_ABORT_NO_DEBUG_INFO( "No boundary setup blocks are allowed when configuring a flag field" << blockHandle.getKey() ); } diff --git a/src/geometry/initializer/Initializer.h b/src/geometry/initializer/Initializer.h index a724baacf..88336d0ec 100644 --- a/src/geometry/initializer/Initializer.h +++ b/src/geometry/initializer/Initializer.h @@ -51,7 +51,7 @@ namespace initializer { class Initializer { public: - virtual ~Initializer() { } + virtual ~Initializer() = default; virtual void init( domain_decomposition::BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ) = 0; }; diff --git a/src/geometry/initializer/OverlapFieldFromBody.h b/src/geometry/initializer/OverlapFieldFromBody.h index b12b9e2bc..0438b85e8 100644 --- a/src/geometry/initializer/OverlapFieldFromBody.h +++ b/src/geometry/initializer/OverlapFieldFromBody.h @@ -101,7 +101,7 @@ namespace initializer { * Interface implementation for Initializer - sets a body on a scalar field with options from configuration file * *****************************************************************************************************************/ - virtual void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ); + void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ) override; diff --git a/src/geometry/initializer/ScalarFieldFromBody.h b/src/geometry/initializer/ScalarFieldFromBody.h index ba8b72f9b..97ef3cc95 100644 --- a/src/geometry/initializer/ScalarFieldFromBody.h +++ b/src/geometry/initializer/ScalarFieldFromBody.h @@ -97,7 +97,7 @@ namespace initializer { * Interface implementation for Initializer - sets a body on a scalar field with options from configuration file * *****************************************************************************************************************/ - virtual void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ); + void init( BlockStorage & blockStorage, const Config::BlockHandle & blockHandle ) override; diff --git a/src/geometry/initializer/ScalarFieldFromGrayScaleImage.h b/src/geometry/initializer/ScalarFieldFromGrayScaleImage.h index f570c0f11..2664fba72 100644 --- a/src/geometry/initializer/ScalarFieldFromGrayScaleImage.h +++ b/src/geometry/initializer/ScalarFieldFromGrayScaleImage.h @@ -64,7 +64,7 @@ namespace initializer { * Initializes the scalar field using parameters of config block * for syntax see class documentation *****************************************************************************************************************/ - virtual void init ( BlockStorage & blockStorage, const Config::BlockHandle & block ); + void init ( BlockStorage & blockStorage, const Config::BlockHandle & block ) override; /*************************************************************************************************************//** diff --git a/src/geometry/structured/BasicVoxelFileReader.impl.h b/src/geometry/structured/BasicVoxelFileReader.impl.h index 4dbdc8ad8..9bebb8345 100644 --- a/src/geometry/structured/BasicVoxelFileReader.impl.h +++ b/src/geometry/structured/BasicVoxelFileReader.impl.h @@ -371,7 +371,7 @@ void BasicVoxelFileReader<T>::close() assert(!filestream_.is_open()); assert(dataBegin_ == std::streampos()); - assert(filename_ == ""); + assert(filename_.empty()); assert(xSize_ == 0); assert(ySize_ == 0); assert(zSize_ == 0); diff --git a/src/geometry/structured/GrayScaleImage.h b/src/geometry/structured/GrayScaleImage.h index a32c22548..3361cc90e 100644 --- a/src/geometry/structured/GrayScaleImage.h +++ b/src/geometry/structured/GrayScaleImage.h @@ -70,7 +70,7 @@ namespace geometry { static pixel_t pixelValueFromString( const std::string & str ); protected: - GrayScaleImage() {} + GrayScaleImage() = default; uint_t size_[2]; //< 0=width, 1=height std::vector<unsigned char> image_; //< raw pixels diff --git a/src/geometry/structured/RGBAImage.h b/src/geometry/structured/RGBAImage.h index 4c7be3188..4e2871659 100644 --- a/src/geometry/structured/RGBAImage.h +++ b/src/geometry/structured/RGBAImage.h @@ -99,7 +99,7 @@ namespace geometry { static pixel_t pixelValueFromString( const std::string & str ); protected: - RGBAImage() {} + RGBAImage() = default; uint_t size_[2]; //< 0=width, 1=height std::vector<unsigned char> image_; //< raw pixels diff --git a/src/geometry/structured/extern/lodepng.h b/src/geometry/structured/extern/lodepng.h index 404ae1ec4..2d4b383cc 100644 --- a/src/geometry/structured/extern/lodepng.h +++ b/src/geometry/structured/extern/lodepng.h @@ -622,7 +622,7 @@ typedef struct LodePNGState unsigned error; #ifdef LODEPNG_COMPILE_CPP //For the lodepng::State subclass. - virtual ~LodePNGState(){} + virtual ~LodePNGState()= default; #endif } LodePNGState; @@ -808,7 +808,7 @@ class State : public LodePNGState public: State(); State(const State& other); - virtual ~State(); + ~State() override; State& operator=(const State& other); }; diff --git a/src/gui/PropertyTree.h b/src/gui/PropertyTree.h index f6a5ae179..df1965d7e 100644 --- a/src/gui/PropertyTree.h +++ b/src/gui/PropertyTree.h @@ -139,12 +139,12 @@ namespace gui { * to add children */ template <typename T> - ItemID addItem(const std::string & name, const T & val, ItemID parent=0); + ItemID addItem(const std::string & name, const T & val, ItemID parent=nullptr); /** * Convenience method, behaves like addItem above with no value -> empty second column */ - ItemID addItem(const std::string & name, ItemID parent=0); + ItemID addItem(const std::string & name, ItemID parent=nullptr); /** * Changes an existing item diff --git a/src/gui/PropertyTree.impl.h b/src/gui/PropertyTree.impl.h index a4c705355..f7d6dae8d 100644 --- a/src/gui/PropertyTree.impl.h +++ b/src/gui/PropertyTree.impl.h @@ -78,7 +78,7 @@ namespace gui { template <typename T> PropertyTree::ItemID PropertyTree::addItem(const std::string &, const T &, ItemID) { - return 0; + return nullptr; } template <typename T> diff --git a/src/lbm/PerformanceLogger.h b/src/lbm/PerformanceLogger.h index 956b4a7da..7e7f183b7 100644 --- a/src/lbm/PerformanceLogger.h +++ b/src/lbm/PerformanceLogger.h @@ -97,7 +97,7 @@ PerformanceLogger<FlagField_T>::PerformanceLogger( const shared_ptr< StructuredB const Set<SUID> & requiredSelectors /*= Set<SUID>::emptySet()*/, const Set<SUID> & incompatibleSelectors /*= Set<SUID>::emptySet()*/ ) : performanceEvaluation_( blocks, flagFieldId, fluid, requiredSelectors, incompatibleSelectors ), - interval_(interval), timestep_(1), refreshCellCountOnCall_(false), timeloop_(NULL) + interval_(interval), timestep_(1), refreshCellCountOnCall_(false), timeloop_(nullptr) { } diff --git a/src/lbm/blockforest/PostProcessing.h b/src/lbm/blockforest/PostProcessing.h index 23644cddc..361303cc1 100644 --- a/src/lbm/blockforest/PostProcessing.h +++ b/src/lbm/blockforest/PostProcessing.h @@ -377,24 +377,24 @@ public: pdfFieldId_( pdfFieldId ), filter_( filter ) {} - virtual ~MarkerData() {} + ~MarkerData() override = default; - internal::MarkerField_T * initialize( IBlock * const ) { return allocate(); } + internal::MarkerField_T * initialize( IBlock * const ) override { return allocate(); } - void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ); + void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ); - void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ); + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - internal::MarkerField_T * deserialize( IBlock * const ) { return allocate(); } + internal::MarkerField_T * deserialize( IBlock * const ) override { return allocate(); } - internal::MarkerField_T * deserializeCoarseToFine( Block * const ) { return allocate(); } - internal::MarkerField_T * deserializeFineToCoarse( Block * const ) { return allocate(); } + internal::MarkerField_T * deserializeCoarseToFine( Block * const ) override { return allocate(); } + internal::MarkerField_T * deserializeFineToCoarse( Block * const ) override { return allocate(); } - void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; - void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); - void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ); + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; protected: diff --git a/src/lbm/boundary/Curved.h b/src/lbm/boundary/Curved.h index d5f7aa08f..045a02398 100644 --- a/src/lbm/boundary/Curved.h +++ b/src/lbm/boundary/Curved.h @@ -256,7 +256,7 @@ inline void Curved< LatticeModel_T, FlagField_T >::treatDirection( const cell_id } else { - WALBERLA_ASSERT( weights_->get( nx, ny, nz ).get() != NULL ); + WALBERLA_ASSERT( weights_->get( nx, ny, nz ).get() != nullptr ); WALBERLA_ASSERT_LESS( Stencil::invDirIdx(dir), weights_->get( nx, ny, nz )->size() ); // linear multi reflection model without non-equilibirum diff --git a/src/lbm/boundary/DiffusionDirichlet.h b/src/lbm/boundary/DiffusionDirichlet.h index 4f07d41b8..96a560085 100644 --- a/src/lbm/boundary/DiffusionDirichlet.h +++ b/src/lbm/boundary/DiffusionDirichlet.h @@ -72,7 +72,7 @@ public: const real_t & val() const { return val_; } - virtual void val( real_t& _val, cell_idx_t, cell_idx_t, cell_idx_t ) const { _val = val(); } + void val( real_t& _val, cell_idx_t, cell_idx_t, cell_idx_t ) const override { _val = val(); } real_t & val(){ return val_; } @@ -122,7 +122,7 @@ inline DiffusionDirichlet< LatticeModel_T, flag_t >::DiffusionDirichlet( const B Boundary<flag_t>( boundaryUID ), uid_( uid ), pdfField_( pdfField ) { WALBERLA_ASSERT_NOT_NULLPTR( pdfField_ ); - if (flagField != NULL) + if (flagField != nullptr) sclField_ = make_shared<ScalarField>( pdfField_->xSize(), pdfField_->ySize(), pdfField_->zSize(), flagField->nrOfGhostLayers(), field::zyxf ); else sclField_ = make_shared<ScalarField>( pdfField_->xSize(), pdfField_->ySize(), pdfField_->zSize(), pdfField->nrOfGhostLayers(), field::zyxf ); diff --git a/src/lbm/boundary/UBB.h b/src/lbm/boundary/UBB.h index 5ce5fcc06..e2621fb2f 100644 --- a/src/lbm/boundary/UBB.h +++ b/src/lbm/boundary/UBB.h @@ -87,7 +87,7 @@ public: - inline UBB( const BoundaryUID & boundaryUID, const FlagUID & uid, PDFField* const pdfField, FlagField<flag_t> * const flagField = NULL ); + inline UBB( const BoundaryUID & boundaryUID, const FlagUID & uid, PDFField* const pdfField, FlagField<flag_t> * const flagField = nullptr ); void pushFlags( std::vector< FlagUID > & uids ) const { uids.push_back( uid_ ); } @@ -146,7 +146,7 @@ inline UBB< LatticeModel_T, flag_t, AdaptVelocityToExternalForce, StoreForce >:: Boundary<flag_t>( boundaryUID ), uid_( uid ), pdfField_( pdfField ) { WALBERLA_ASSERT_NOT_NULLPTR( pdfField_ ); - if (flagField != NULL) + if (flagField != nullptr) vel_ = make_shared<VelField>( pdfField_->xSize(), pdfField_->ySize(), pdfField_->zSize(), flagField->nrOfGhostLayers(), field::zyxf ); else vel_ = make_shared<VelField>( pdfField_->xSize(), pdfField_->ySize(), pdfField_->zSize(), pdfField_->nrOfGhostLayers(), field::zyxf ); diff --git a/src/lbm/boundary/VelocityBoundary.h b/src/lbm/boundary/VelocityBoundary.h index 8b470021b..0673f5a28 100644 --- a/src/lbm/boundary/VelocityBoundary.h +++ b/src/lbm/boundary/VelocityBoundary.h @@ -232,7 +232,7 @@ inline void VelocityBoundary< LatticeModel_T, flag_t >::treatDirection( const ce WALBERLA_ASSERT_EQUAL( mask & this->mask_, this->mask_ ); // only true if "this->mask_" only contains one single flag, which is the case for the // current implementation of this boundary condition (VelocityBoundary) - WALBERLA_ASSERT( vel_->get( nx, ny, nz ).get() != NULL ); + WALBERLA_ASSERT( vel_->get( nx, ny, nz ).get() != nullptr ); WALBERLA_ASSERT_LESS( Stencil::invDirIdx(dir), vel_->get( nx, ny, nz )->size() ); pdfField_->get( nx, ny, nz, Stencil::invDirIdx(dir) ) = (*(vel_->get( nx, ny, nz )))[ Stencil::invDirIdx(dir) ]; diff --git a/src/lbm/field/AddToStorage.h b/src/lbm/field/AddToStorage.h index 3cf80dc43..287673ad4 100644 --- a/src/lbm/field/AddToStorage.h +++ b/src/lbm/field/AddToStorage.h @@ -50,37 +50,37 @@ public: initialize_( _initialize ), initialVelocity_( initialVelocity ), initialDensity_( initialDensity ), nrOfGhostLayers_( nrOfGhostLayers ), layout_( layout ) {} - inline void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) + inline void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override { packLatticeModel( block, id, buffer ); Base_T::serialize( block, id, buffer ); } - void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override { packLatticeModel( block, id, buffer ); Base_T::serializeCoarseToFine( block, id, buffer, child ); } - void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override { packLatticeModel( block, id, buffer ); Base_T::serializeFineToCoarse( block, id, buffer ); } - void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override { unpackLatticeModel( block, id, buffer ); Base_T::deserialize( block, id, buffer ); } - void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override { unpackLatticeModel( block, id, buffer ); Base_T::deserializeCoarseToFine( block, id, buffer ); } - void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override { unpackLatticeModel( block, id, buffer ); Base_T::deserializeFineToCoarse( block, id, buffer, child ); @@ -88,12 +88,12 @@ public: protected: - PdfField<LatticeModel_T> * allocate( IBlock * const block ) + PdfField<LatticeModel_T> * allocate( IBlock * const block ) override { return allocateDispatch( block, initialize_, initialDensity_ ); } - PdfField<LatticeModel_T> * reallocate( IBlock * const block ) + PdfField<LatticeModel_T> * reallocate( IBlock * const block ) override { #ifdef NDEBUG return allocateDispatch( block, false, initialDensity_ ); diff --git a/src/lbm/field/Density.h b/src/lbm/field/Density.h index a7c346e13..3555e7981 100644 --- a/src/lbm/field/Density.h +++ b/src/lbm/field/Density.h @@ -80,7 +80,7 @@ struct Density< LatticeModel_T, typename std::enable_if< LatticeModel_T::compres template< typename LatticeModel_T > struct Density< LatticeModel_T, typename std::enable_if< ! LatticeModel_T::compressible >::type > { - static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); + static_assert( !LatticeModel_T::compressible, "Only works with incompressible models!" ); template< typename FieldPtrOrIterator > static inline real_t get( const LatticeModel_T & /*latticeModel*/, const FieldPtrOrIterator & it ) diff --git a/src/lbm/field/DensityVelocityCallback.h b/src/lbm/field/DensityVelocityCallback.h index 3c7c69087..d7c76c5ca 100644 --- a/src/lbm/field/DensityVelocityCallback.h +++ b/src/lbm/field/DensityVelocityCallback.h @@ -246,7 +246,7 @@ class AdvectionDiffusionDensityEquilibriumVelocityCalculation public: AdvectionDiffusionDensityEquilibriumVelocityCalculation( const ConstBlockDataID & velocityFieldId ) : - velocityFieldId_( velocityFieldId ), velocityField_( NULL ) {} + velocityFieldId_( velocityFieldId ), velocityField_( nullptr ) {} void operator()( IBlock & block ) { diff --git a/src/lbm/field/PdfField.h b/src/lbm/field/PdfField.h index 5b4429877..a9438e42b 100644 --- a/src/lbm/field/PdfField.h +++ b/src/lbm/field/PdfField.h @@ -104,7 +104,7 @@ public: const uint_t ghostLayers = uint_t(1), const field::Layout & _layout = field::zyxf, const shared_ptr< field::FieldAllocator<real_t> > & alloc = shared_ptr< field::FieldAllocator<real_t> >() ); - virtual ~PdfField() {} + ~PdfField() override = default; @@ -282,7 +282,7 @@ protected: /*! \name Shallow Copy */ //@{ inline PdfField( const PdfField< LatticeModel_T > & other ); - Field< real_t, Stencil::Size > * cloneShallowCopyInternal() const { return new PdfField< LatticeModel_T >( *this ); } + Field< real_t, Stencil::Size > * cloneShallowCopyInternal() const override { return new PdfField< LatticeModel_T >( *this ); } //@} //******************************************************************************************************************* diff --git a/src/lbm/geometry/initializer/PoiseuilleInitializer.h b/src/lbm/geometry/initializer/PoiseuilleInitializer.h index 4315bed9c..8f8898556 100644 --- a/src/lbm/geometry/initializer/PoiseuilleInitializer.h +++ b/src/lbm/geometry/initializer/PoiseuilleInitializer.h @@ -93,7 +93,7 @@ namespace initializer { field::FlagUID pressureFlag1, field::FlagUID pressureFlag2 ); - virtual void init( BlockStorage & , const Config::BlockHandle & blockHandle ) { init( blockHandle ); } + void init( BlockStorage & , const Config::BlockHandle & blockHandle ) override { init( blockHandle ); } void init( const Config::BlockHandle & blockHandle ); void init( Scenario scenario, BoundaryType boundaryType, real_t pressureDiff, Axis flowAxis, Axis parabolaAxis = INVALID_AXIS ); diff --git a/src/lbm/lattice_model/CollisionModel.h b/src/lbm/lattice_model/CollisionModel.h index df97cc3c5..c3077e97f 100644 --- a/src/lbm/lattice_model/CollisionModel.h +++ b/src/lbm/lattice_model/CollisionModel.h @@ -145,7 +145,7 @@ public: omegaFieldId_(), omegaField_( NULL ), level_( uint_t(0) ) {} SRTField( const BlockDataID & omegaFieldId, const uint_t _level = uint_t(0) ) : - omegaFieldId_( omegaFieldId ), omegaField_( NULL ), level_( _level ) {} + omegaFieldId_( omegaFieldId ), omegaField_( nullptr ), level_( _level ) {} void setFieldId( const BlockDataID & omegaFieldId, const uint_t _level = uint_t(0) ) { diff --git a/src/lbm/lattice_model/D2Q9.h b/src/lbm/lattice_model/D2Q9.h index a4080f3bc..4fe777ead 100644 --- a/src/lbm/lattice_model/D2Q9.h +++ b/src/lbm/lattice_model/D2Q9.h @@ -63,11 +63,11 @@ public: static_assert( (std::is_same< ForceModel_T, force_model::None >::value), "This constructor is only available if the force model is equal to force_model::None!" ); } - virtual ~D2Q9() {} + ~D2Q9() override = default; protected: - virtual void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) {} + void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) override {} }; template< typename CM, bool C, typename FM, int EAO > const char* D2Q9<CM,C,FM,EAO>::NAME = "D2Q9"; diff --git a/src/lbm/lattice_model/D3Q15.h b/src/lbm/lattice_model/D3Q15.h index e969749a4..a946fce3d 100644 --- a/src/lbm/lattice_model/D3Q15.h +++ b/src/lbm/lattice_model/D3Q15.h @@ -62,11 +62,11 @@ public: static_assert( (std::is_same< ForceModel_T, force_model::None >::value), "This constructor is only available if the force model is equal to force_model::None!" ); } - virtual ~D3Q15() {} + ~D3Q15() override = default; protected: - virtual void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) {} + void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) override {} }; template< typename CM, bool C, typename FM, int EAO > const char* D3Q15<CM,C,FM,EAO>::NAME = "D3Q15"; diff --git a/src/lbm/lattice_model/D3Q19.h b/src/lbm/lattice_model/D3Q19.h index e196e4ede..d8cfc3dbc 100644 --- a/src/lbm/lattice_model/D3Q19.h +++ b/src/lbm/lattice_model/D3Q19.h @@ -61,11 +61,11 @@ public: static_assert( (std::is_same< ForceModel_T, force_model::None >::value), "This constructor is only available if the force model is equal to force_model::None!" ); } - virtual ~D3Q19() {} + ~D3Q19() override = default; protected: - virtual void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) {} + void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) override {} }; template< typename CM, bool C, typename FM, int EAO > const char* D3Q19<CM,C,FM,EAO>::NAME = "D3Q19"; diff --git a/src/lbm/lattice_model/D3Q27.h b/src/lbm/lattice_model/D3Q27.h index 72b5188f5..fb8289cbf 100644 --- a/src/lbm/lattice_model/D3Q27.h +++ b/src/lbm/lattice_model/D3Q27.h @@ -64,11 +64,11 @@ public: static_assert( (std::is_same< ForceModel_T, force_model::None >::value), "This constructor is only available if the force model is equal to force_model::None!" ); } - virtual ~D3Q27() {} + ~D3Q27() override = default; protected: - virtual void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) {} + void config( IBlock & /*block*/, StructuredBlockStorage & /*sbs*/ ) override {} }; template< typename CM, bool C, typename FM, int EAO > const char* D3Q27<CM,C,FM,EAO>::NAME = "D3Q27"; diff --git a/src/lbm/lattice_model/ForceModel.h b/src/lbm/lattice_model/ForceModel.h index 9b01b48b2..b82f05634 100644 --- a/src/lbm/lattice_model/ForceModel.h +++ b/src/lbm/lattice_model/ForceModel.h @@ -563,7 +563,7 @@ public: static const bool constant = false; GuoField( const BlockDataID & forceFieldId ) : - forceFieldId_( forceFieldId ), forceField_( NULL ) {} + forceFieldId_( forceFieldId ), forceField_( nullptr ) {} void pack( mpi::SendBuffer & buffer ) const { buffer << forceFieldId_; } void unpack( mpi::RecvBuffer & buffer ) { buffer >> forceFieldId_; } @@ -644,7 +644,7 @@ public: static const bool constant = true; Correction( const BlockDataID & previousRhoVelocityId ) : - force_( real_t(0) ), previousRhoVelocityId_( previousRhoVelocityId ), previousRhoVelocity_(NULL) {} + force_( real_t(0) ), previousRhoVelocityId_( previousRhoVelocityId ), previousRhoVelocity_(nullptr) {} void pack( mpi::SendBuffer & buffer ) const { buffer << force_ << previousRhoVelocityId_; } void unpack( mpi::RecvBuffer & buffer ) { buffer >> force_ >> previousRhoVelocityId_; } diff --git a/src/lbm/lattice_model/LatticeModelBase.h b/src/lbm/lattice_model/LatticeModelBase.h index 385e9abcc..82039ee3a 100644 --- a/src/lbm/lattice_model/LatticeModelBase.h +++ b/src/lbm/lattice_model/LatticeModelBase.h @@ -82,7 +82,7 @@ public: LatticeModelBase( const CollisionModel_T & cm, const ForceModel_T & fm ) : collisionModel_( cm ), forceModel_( fm ) {} - virtual ~LatticeModelBase() {} + virtual ~LatticeModelBase() = default; virtual void pack( mpi::SendBuffer & buffer ) const { diff --git a/src/lbm/refinement/PdfFieldPackInfo.h b/src/lbm/refinement/PdfFieldPackInfo.h index 6fbfb9221..7117c64cd 100644 --- a/src/lbm/refinement/PdfFieldPackInfo.h +++ b/src/lbm/refinement/PdfFieldPackInfo.h @@ -60,31 +60,31 @@ public: equalLevelCells_( equalLevelCells() ) {} #endif - virtual ~PdfFieldPackInfo() {} + ~PdfFieldPackInfo() override = default; - bool optimizedEqualLevelCommunication() const { return optimizedEqualLevelCommunication_; } - void optimizeEqualLevelCommunication( const bool value = true ) { optimizedEqualLevelCommunication_ = value; } + bool optimizedEqualLevelCommunication() const override { return optimizedEqualLevelCommunication_; } + void optimizeEqualLevelCommunication( const bool value = true ) override { optimizedEqualLevelCommunication_ = value; } - bool optimizedForLinearExplosion() const { return optimizedForLinearExplosion_; } - void optimizeForLinearExplosion( const bool value = true ) { optimizedForLinearExplosion_ = value; } + bool optimizedForLinearExplosion() const override { return optimizedForLinearExplosion_; } + void optimizeForLinearExplosion( const bool value = true ) override { optimizedForLinearExplosion_ = value; } - bool constantDataExchange() const { return true; } - bool threadsafeReceiving() const { return true; } + bool constantDataExchange() const override { return true; } + bool threadsafeReceiving() const override { return true; } - void unpackDataEqualLevel( Block * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalEqualLevel( const Block * sender, Block * receiver, stencil::Direction dir ); + void unpackDataEqualLevel( Block * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalEqualLevel( const Block * sender, Block * receiver, stencil::Direction dir ) override; - void unpackDataCoarseToFine( Block * fineReceiver, const BlockID & coarseSender, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalCoarseToFine( const Block * coarseSender, Block * fineReceiver, stencil::Direction dir ); + void unpackDataCoarseToFine( Block * fineReceiver, const BlockID & coarseSender, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalCoarseToFine( const Block * coarseSender, Block * fineReceiver, stencil::Direction dir ) override; - void unpackDataFineToCoarse( Block * coarseReceiver, const BlockID & fineSender, stencil::Direction dir, mpi::RecvBuffer & buffer ); - void communicateLocalFineToCoarse( const Block * fineSender, Block * coarseReceiver, stencil::Direction dir ); + void unpackDataFineToCoarse( Block * coarseReceiver, const BlockID & fineSender, stencil::Direction dir, mpi::RecvBuffer & buffer ) override; + void communicateLocalFineToCoarse( const Block * fineSender, Block * coarseReceiver, stencil::Direction dir ) override; protected: - void packDataEqualLevelImpl( const Block * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const; - void packDataCoarseToFineImpl( const Block * coarseSender, const BlockID & fineReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const; - void packDataFineToCoarseImpl( const Block * fineSender, const BlockID & coarseReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const; + void packDataEqualLevelImpl( const Block * sender, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; + void packDataCoarseToFineImpl( const Block * coarseSender, const BlockID & fineReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; + void packDataFineToCoarseImpl( const Block * fineSender, const BlockID & coarseReceiver, stencil::Direction dir, mpi::SendBuffer & buffer ) const override; /////////////////////////////////////////////////////////////////////// // Helper functions for determining packing/unpacking cell intervals // @@ -1090,18 +1090,18 @@ inline std::vector< CellInterval > PdfFieldPackInfo< LatticeModel_T, BoundaryHan WALBERLA_ASSERT_EQUAL( interval.xSize(), equalLevelCells_ ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMax(), - interval.xMax(), interval.yMax(), interval.zMax() ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMin() + cell_idx_t(1), - interval.xMax(), interval.yMin(), interval.zMax() - cell_idx_t(1) ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMax(), interval.zMin() + cell_idx_t(1), - interval.xMax(), interval.yMax(), interval.zMax() - cell_idx_t(1) ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMin(), - interval.xMax(), interval.yMax(), interval.zMin() ) ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMax(), + interval.xMax(), interval.yMax(), interval.zMax() ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMin() + cell_idx_t(1), + interval.xMax(), interval.yMin(), interval.zMax() - cell_idx_t(1) ); + intervals.emplace_back( interval.xMin(), interval.yMax(), interval.zMin() + cell_idx_t(1), + interval.xMax(), interval.yMax(), interval.zMax() - cell_idx_t(1) ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMin(), + interval.xMax(), interval.yMax(), interval.zMin() ); const cell_idx_t x = ( stencil::cx[dir] > 0 ) ? interval.xMax() : interval.xMin(); - intervals.push_back( CellInterval( x, interval.yMin() + cell_idx_t(1), interval.zMin() + cell_idx_t(1), - x, interval.yMax() - cell_idx_t(1), interval.zMax() - cell_idx_t(1) ) ); + intervals.emplace_back( x, interval.yMin() + cell_idx_t(1), interval.zMin() + cell_idx_t(1), + x, interval.yMax() - cell_idx_t(1), interval.zMax() - cell_idx_t(1) ); } else if( stencil::cy[dir] != 0 ) { @@ -1110,18 +1110,18 @@ inline std::vector< CellInterval > PdfFieldPackInfo< LatticeModel_T, BoundaryHan WALBERLA_ASSERT_EQUAL( interval.ySize(), equalLevelCells_ ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMax(), - interval.xMax(), interval.yMax(), interval.zMax() ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMin() + cell_idx_t(1), - interval.xMin(), interval.yMax(), interval.zMax() - cell_idx_t(1) ) ); - intervals.push_back( CellInterval( interval.xMax(), interval.yMin(), interval.zMin() + cell_idx_t(1), - interval.xMax(), interval.yMax(), interval.zMax() - cell_idx_t(1) ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMin(), - interval.xMax(), interval.yMax(), interval.zMin() ) ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMax(), + interval.xMax(), interval.yMax(), interval.zMax() ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMin() + cell_idx_t(1), + interval.xMin(), interval.yMax(), interval.zMax() - cell_idx_t(1) ); + intervals.emplace_back( interval.xMax(), interval.yMin(), interval.zMin() + cell_idx_t(1), + interval.xMax(), interval.yMax(), interval.zMax() - cell_idx_t(1) ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMin(), + interval.xMax(), interval.yMax(), interval.zMin() ); const cell_idx_t y = ( stencil::cy[dir] > 0 ) ? interval.yMax() : interval.yMin(); - intervals.push_back( CellInterval( interval.xMin() + cell_idx_t(1), y, interval.zMin() + cell_idx_t(1), - interval.xMax() - cell_idx_t(1), y, interval.zMax() - cell_idx_t(1) ) ); + intervals.emplace_back( interval.xMin() + cell_idx_t(1), y, interval.zMin() + cell_idx_t(1), + interval.xMax() - cell_idx_t(1), y, interval.zMax() - cell_idx_t(1) ); } else { @@ -1131,18 +1131,18 @@ inline std::vector< CellInterval > PdfFieldPackInfo< LatticeModel_T, BoundaryHan WALBERLA_ASSERT_EQUAL( interval.zSize(), equalLevelCells_ ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMax(), interval.zMin(), - interval.xMax(), interval.yMax(), interval.zMax() ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin() + cell_idx_t(1), interval.zMin(), - interval.xMin(), interval.yMax() - cell_idx_t(1), interval.zMax() ) ); - intervals.push_back( CellInterval( interval.xMax(), interval.yMin() + cell_idx_t(1), interval.zMin(), - interval.xMax(), interval.yMax() - cell_idx_t(1), interval.zMax() ) ); - intervals.push_back( CellInterval( interval.xMin(), interval.yMin(), interval.zMin(), - interval.xMax(), interval.yMin(), interval.zMax() ) ); + intervals.emplace_back( interval.xMin(), interval.yMax(), interval.zMin(), + interval.xMax(), interval.yMax(), interval.zMax() ); + intervals.emplace_back( interval.xMin(), interval.yMin() + cell_idx_t(1), interval.zMin(), + interval.xMin(), interval.yMax() - cell_idx_t(1), interval.zMax() ); + intervals.emplace_back( interval.xMax(), interval.yMin() + cell_idx_t(1), interval.zMin(), + interval.xMax(), interval.yMax() - cell_idx_t(1), interval.zMax() ); + intervals.emplace_back( interval.xMin(), interval.yMin(), interval.zMin(), + interval.xMax(), interval.yMin(), interval.zMax() ); const cell_idx_t z = ( stencil::cz[dir] > 0 ) ? interval.zMax() : interval.zMin(); - intervals.push_back( CellInterval( interval.xMin() + cell_idx_t(1), interval.yMin() + cell_idx_t(1), z, - interval.xMax() - cell_idx_t(1), interval.yMax() - cell_idx_t(1), z ) ); + intervals.emplace_back( interval.xMin() + cell_idx_t(1), interval.yMin() + cell_idx_t(1), z, + interval.xMax() - cell_idx_t(1), interval.yMax() - cell_idx_t(1), z ); } return intervals; diff --git a/src/lbm/refinement/TimeStep.h b/src/lbm/refinement/TimeStep.h index 1be6a470d..84189ba4b 100644 --- a/src/lbm/refinement/TimeStep.h +++ b/src/lbm/refinement/TimeStep.h @@ -397,14 +397,14 @@ void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::consistencyChecks( continue; auto * pdfField = block->template getData< PdfField< LatticeModel_T > >( pdfFieldId ); - if( pdfField == NULL ) + if( pdfField == nullptr ) { WALBERLA_ABORT( "Could not get the PDF field from block " << block->getId() << ". Check if it is allocated on " "the block and if the LatticeModel matches!" ); } auto * boundaryHandling = block->template getData< BoundaryHandling_T >( boundaryHandlingId ); - if( boundaryHandling == NULL ) + if( boundaryHandling == nullptr ) { WALBERLA_ABORT( "Could not get the boundary handling from block " << block->getId() << ". Check if it is " "allocated on the block and if its type matches!" ); @@ -595,7 +595,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostCollideVoidFunction( const VoidFunction & function, const std::string & identifier ) { VoidFunctionWrappper wrappedFunction( globalPostCollideVoidFunctions_, globalPostCollideVoidFunctions_.size() ); - globalPostCollideVoidFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostCollideVoidFunctions_.emplace_back( function, identifier ); addFunction< VoidFunction >( postCollideVoidFunctions_, wrappedFunction, identifier ); } @@ -603,7 +603,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostCollideBlockFunction( const BlockFunction & function, const std::string & identifier ) { BlockFunctionWrappper wrappedFunction( globalPostCollideBlockFunctions_, globalPostCollideBlockFunctions_.size() ); - globalPostCollideBlockFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostCollideBlockFunctions_.emplace_back( function, identifier ); addFunction< BlockFunction >( postCollideBlockFunctions_, wrappedFunction, identifier ); } @@ -623,7 +623,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostBoundaryHandlingVoidFunction( const VoidFunction & function, const std::string & identifier ) { VoidFunctionWrappper wrappedFunction( globalPostBoundaryHandlingVoidFunctions_, globalPostBoundaryHandlingVoidFunctions_.size() ); - globalPostBoundaryHandlingVoidFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostBoundaryHandlingVoidFunctions_.emplace_back( function, identifier ); addFunction< VoidFunction >( postBoundaryHandlingVoidFunctions_, wrappedFunction, identifier ); } @@ -631,7 +631,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostBoundaryHandlingBlockFunction( const BlockFunction & function, const std::string & identifier ) { BlockFunctionWrappper wrappedFunction( globalPostBoundaryHandlingBlockFunctions_, globalPostBoundaryHandlingBlockFunctions_.size() ); - globalPostBoundaryHandlingBlockFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostBoundaryHandlingBlockFunctions_.emplace_back( function, identifier ); addFunction< BlockFunction >( postBoundaryHandlingBlockFunctions_, wrappedFunction, identifier ); } @@ -651,7 +651,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostStreamVoidFunction( const VoidFunction & function, const std::string & identifier ) { VoidFunctionWrappper wrappedFunction( globalPostStreamVoidFunctions_, globalPostStreamVoidFunctions_.size() ); - globalPostStreamVoidFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostStreamVoidFunctions_.emplace_back( function, identifier ); addFunction< VoidFunction >( postStreamVoidFunctions_, wrappedFunction, identifier ); } @@ -659,7 +659,7 @@ template< typename LatticeModel_T, typename Sweep_T, typename BoundaryHandling_T inline void TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T >::addPostStreamBlockFunction( const BlockFunction & function, const std::string & identifier ) { BlockFunctionWrappper wrappedFunction( globalPostStreamBlockFunctions_, globalPostStreamBlockFunctions_.size() ); - globalPostStreamBlockFunctions_.push_back( std::make_pair( function, identifier ) ); + globalPostStreamBlockFunctions_.emplace_back( function, identifier ); addFunction< BlockFunction >( postStreamBlockFunctions_, wrappedFunction, identifier ); } diff --git a/src/lbm/srt/SplitPureSweep.impl.h b/src/lbm/srt/SplitPureSweep.impl.h index b193c8636..3c716216c 100644 --- a/src/lbm/srt/SplitPureSweep.impl.h +++ b/src/lbm/srt/SplitPureSweep.impl.h @@ -99,8 +99,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -431,8 +431,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -794,8 +794,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -1130,8 +1130,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); diff --git a/src/lbm/srt/SplitSweep.impl.h b/src/lbm/srt/SplitSweep.impl.h index b7e630c22..e86dc16b2 100644 --- a/src/lbm/srt/SplitSweep.impl.h +++ b/src/lbm/srt/SplitSweep.impl.h @@ -93,9 +93,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -493,9 +493,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -517,8 +517,8 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s { WALBERLA_ASSERT_EQUAL( numberOfGhostLayersToInclude, uint_t(0) ); // the implementation right now doesn't support inclusion of ghost layers in collide step! - PdfField_T * src( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, flagField ); @@ -928,9 +928,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -1333,9 +1333,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -1357,8 +1357,8 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s { WALBERLA_ASSERT_EQUAL( numberOfGhostLayersToInclude, uint_t(0) ); // the implementation right now doesn't support inclusion of ghost layers in collide step! - PdfField_T * src( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, flagField ); diff --git a/src/lbm/sweeps/ActiveCellSweep.h b/src/lbm/sweeps/ActiveCellSweep.h index e191b785d..cfc3b6d35 100644 --- a/src/lbm/sweeps/ActiveCellSweep.h +++ b/src/lbm/sweeps/ActiveCellSweep.h @@ -47,7 +47,7 @@ public: const Set< FlagUID > & lbmMask, const bool _useIterators = false ) : FlagFieldSweepBase<LatticeModel_T,FlagField_T>( src, dst, flagField, lbmMask ), cellOperation_( op ), useIterators_( _useIterators ) {} - virtual ~ActiveCellSweep() {} + virtual ~ActiveCellSweep() = default; const CellOperation & getCellOperation() const { return cellOperation_; } CellOperation & getCellOperation() { return cellOperation_; } diff --git a/src/lbm/trt/SplitPureSweep.impl.h b/src/lbm/trt/SplitPureSweep.impl.h index 695cebccf..84104e092 100644 --- a/src/lbm/trt/SplitPureSweep.impl.h +++ b/src/lbm/trt/SplitPureSweep.impl.h @@ -98,8 +98,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -480,8 +480,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -891,8 +891,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); @@ -1292,8 +1292,8 @@ void SplitPureSweep< LatticeModel_T, typename std::enable_if< std::is_same< type >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); this->getFields( block, src, dst ); diff --git a/src/lbm/trt/SplitSweep.impl.h b/src/lbm/trt/SplitSweep.impl.h index fadc10b48..4439727ca 100644 --- a/src/lbm/trt/SplitSweep.impl.h +++ b/src/lbm/trt/SplitSweep.impl.h @@ -93,9 +93,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -545,9 +545,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -568,8 +568,8 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s { WALBERLA_ASSERT_EQUAL( numberOfGhostLayersToInclude, uint_t(0) ); // the implementation right now doesn't support inclusion of ghost layers in collide step! - PdfField_T * src( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, flagField ); @@ -1030,9 +1030,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::operator()( IBlock * const block ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -1501,9 +1501,9 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s >::type >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, dst, flagField ); @@ -1524,8 +1524,8 @@ void SplitSweep< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_s { WALBERLA_ASSERT_EQUAL( numberOfGhostLayersToInclude, uint_t(0) ); // the implementation right now doesn't support inclusion of ghost layers in collide step! - PdfField_T * src( NULL ); - const FlagField_T * flagField( NULL ); + PdfField_T * src( nullptr ); + const FlagField_T * flagField( nullptr ); auto lbm = this->getLbmMaskAndFields( block, src, flagField ); diff --git a/src/lbm/vtk/Density.h b/src/lbm/vtk/Density.h index 387086fe6..6b7e4ee51 100644 --- a/src/lbm/vtk/Density.h +++ b/src/lbm/vtk/Density.h @@ -39,13 +39,13 @@ public: typedef PdfField< LatticeModel_T > PdfField_T; DensityVTKWriter( const ConstBlockDataID & pdf, const std::string & id ) : - vtk::BlockCellDataWriter< OutputType >( id ), bdid_( pdf ), pdf_( NULL ) {} + vtk::BlockCellDataWriter< OutputType >( id ), bdid_( pdf ), pdf_( nullptr ) {} protected: - void configure() { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } - OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) + OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) override { WALBERLA_ASSERT_NOT_NULLPTR( pdf_ ); return numeric_cast< OutputType >( pdf_->getDensity(x,y,z) ); diff --git a/src/lbm/vtk/NonEquilibrium.h b/src/lbm/vtk/NonEquilibrium.h index c8699c43e..3754c58dd 100644 --- a/src/lbm/vtk/NonEquilibrium.h +++ b/src/lbm/vtk/NonEquilibrium.h @@ -45,13 +45,13 @@ public: typedef typename LatticeModel_T::Stencil Stencil; NonEqulibriumVTKWriter( const ConstBlockDataID & pdf, const std::string & id ) : - vtk::BlockCellDataWriter< OutputType, Stencil::Size >( id ), bdid_( pdf ), pdf_( NULL ) {} + vtk::BlockCellDataWriter< OutputType, Stencil::Size >( id ), bdid_( pdf ), pdf_( nullptr ) {} protected: - void configure() { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } - OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { WALBERLA_ASSERT_NOT_NULLPTR( pdf_ ); diff --git a/src/lbm/vtk/VTKOutput.h b/src/lbm/vtk/VTKOutput.h index 1c00b11ff..e42fb6bd9 100644 --- a/src/lbm/vtk/VTKOutput.h +++ b/src/lbm/vtk/VTKOutput.h @@ -90,7 +90,7 @@ public: const FlagUID & domainFlagUID, const FlagMap & flagFieldMapping = FlagMap() ); - virtual ~VTKOutput() {} + virtual ~VTKOutput() = default; virtual void operator()( std::vector< shared_ptr<vtk::BlockCellDataWriterInterface> > & writers, std::map< std::string, vtk::VTKOutput::CellFilter > & filters, diff --git a/src/lbm/vtk/Velocity.h b/src/lbm/vtk/Velocity.h index 6fb513745..10957ee4a 100644 --- a/src/lbm/vtk/Velocity.h +++ b/src/lbm/vtk/Velocity.h @@ -39,13 +39,13 @@ public: typedef PdfField< LatticeModel_T > PdfField_T; VelocityVTKWriter( const ConstBlockDataID & pdfFieldId, const std::string & id ) : - vtk::BlockCellDataWriter< OutputType, 3 >( id ), bdid_( pdfFieldId ), pdf_( NULL ) {} + vtk::BlockCellDataWriter< OutputType, 3 >( id ), bdid_( pdfFieldId ), pdf_( nullptr ) {} protected: - void configure() { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } - OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { WALBERLA_ASSERT_NOT_NULLPTR( pdf_ ); return numeric_cast< OutputType >( (pdf_->getVelocity(x,y,z))[ uint_c(f) ] ); @@ -66,13 +66,13 @@ public: typedef PdfField< LatticeModel_T > PdfField_T; VelocityMagnitudeVTKWriter( const ConstBlockDataID & pdfFieldId, const std::string & id ) : - vtk::BlockCellDataWriter< OutputType, 1 >( id ), bdid_( pdfFieldId ), pdf_( NULL ) {} + vtk::BlockCellDataWriter< OutputType, 1 >( id ), bdid_( pdfFieldId ), pdf_( nullptr ) {} protected: - void configure() { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); pdf_ = this->block_->template getData< PdfField_T >( bdid_ ); } - OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) + OutputType evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t /*f*/ ) override { WALBERLA_ASSERT_NOT_NULLPTR( pdf_ ); return numeric_cast< OutputType >( pdf_->getVelocity(x,y,z).length() ); diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h index d1f198916..d001a43ba 100644 --- a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h @@ -40,7 +40,7 @@ public: //@{ explicit SubCyclingManager(size_t numberOfSubCycles, shared_ptr<WcTimingPool> timingPool = nullptr); - virtual ~SubCyclingManager() {} + virtual ~SubCyclingManager() = default; //@} /*! \name Registration Functions */ diff --git a/src/mesa_pd/collision_detection/AnalyticContactDetection.h b/src/mesa_pd/collision_detection/AnalyticContactDetection.h index ce8149c1e..36941efc1 100644 --- a/src/mesa_pd/collision_detection/AnalyticContactDetection.h +++ b/src/mesa_pd/collision_detection/AnalyticContactDetection.h @@ -46,7 +46,7 @@ namespace collision_detection { class AnalyticContactDetection { public: - virtual ~AnalyticContactDetection() {} + virtual ~AnalyticContactDetection() = default; size_t& getIdx1() {return idx1_;} size_t& getIdx2() {return idx2_;} diff --git a/src/mesa_pd/collision_detection/BroadPhase.h b/src/mesa_pd/collision_detection/BroadPhase.h index a3fcb2640..f98658836 100644 --- a/src/mesa_pd/collision_detection/BroadPhase.h +++ b/src/mesa_pd/collision_detection/BroadPhase.h @@ -38,8 +38,7 @@ bool isInInteractionDistance(const size_t idx1, const size_t idx2, Accessor& ac) if (isSet(ac.getFlags(idx2), INFINITE)) return true; auto separationDist = ac.getInteractionRadius(idx1) + ac.getInteractionRadius(idx2); auto realDist2 = (ac.getPosition(idx1) - ac.getPosition(idx2)).sqrLength(); - if (realDist2 < separationDist*separationDist) return true; - return false; + return realDist2 < separationDist*separationDist; } } //namespace collision_detection diff --git a/src/mesa_pd/collision_detection/GeneralContactDetection.h b/src/mesa_pd/collision_detection/GeneralContactDetection.h index 69a95e508..9564916c0 100644 --- a/src/mesa_pd/collision_detection/GeneralContactDetection.h +++ b/src/mesa_pd/collision_detection/GeneralContactDetection.h @@ -199,13 +199,7 @@ bool GeneralContactDetection::collideGJKEPA(Support& geom0, Support& geom1) { EPA epa; epa.useSphereOptimization(false); - if (epa.doEPAmargin(geom0, geom1, gjk, contactNormal_, contactPoint_, penetrationDepth_, margin)) - { - return true; - } else - { - return false; - } + return epa.doEPAmargin(geom0, geom1, gjk, contactNormal_, contactPoint_, penetrationDepth_, margin); } else { return false; diff --git a/src/mesa_pd/data/ContactAccessor.h b/src/mesa_pd/data/ContactAccessor.h index dfa293bc9..a33d4e804 100644 --- a/src/mesa_pd/data/ContactAccessor.h +++ b/src/mesa_pd/data/ContactAccessor.h @@ -47,7 +47,7 @@ class ContactAccessor : public IContactAccessor { public: ContactAccessor(const std::shared_ptr<data::ContactStorage>& ps) : ps_(ps) {} - virtual ~ContactAccessor() = default; + ~ContactAccessor() override = default; const walberla::id_t& getUid(const size_t p_idx) const {return ps_->getUid(p_idx);} walberla::id_t& getUidRef(const size_t p_idx) {return ps_->getUidRef(p_idx);} void setUid(const size_t p_idx, const walberla::id_t& v) { ps_->setUid(p_idx, v);} @@ -156,7 +156,7 @@ inline size_t ContactAccessor::find(const id_t& uid) class SingleContactAccessor : public IAccessor { public: - virtual ~SingleContactAccessor() = default; + ~SingleContactAccessor() override = default; const walberla::id_t& getUid(const size_t /*p_idx*/) const {return uid_;} void setUid(const size_t /*p_idx*/, const walberla::id_t& v) { uid_ = v;} walberla::id_t& getUidRef(const size_t /*p_idx*/) {return uid_;} diff --git a/src/mesa_pd/data/ParticleAccessor.h b/src/mesa_pd/data/ParticleAccessor.h index 4ebdcd135..62c61f6f7 100644 --- a/src/mesa_pd/data/ParticleAccessor.h +++ b/src/mesa_pd/data/ParticleAccessor.h @@ -47,7 +47,7 @@ class ParticleAccessor : public IAccessor { public: ParticleAccessor(const std::shared_ptr<data::ParticleStorage>& ps) : ps_(ps) {} - virtual ~ParticleAccessor() = default; + ~ParticleAccessor() override = default; walberla::id_t const & getUid(const size_t p_idx) const {return ps_->getUid(p_idx);} walberla::id_t& getUidRef(const size_t p_idx) {return ps_->getUidRef(p_idx);} void setUid(const size_t p_idx, walberla::id_t const & v) { ps_->setUid(p_idx, v);} @@ -220,7 +220,7 @@ inline size_t ParticleAccessor::find(const id_t& uid) class SingleParticleAccessor : public IAccessor { public: - virtual ~SingleParticleAccessor() = default; + ~SingleParticleAccessor() override = default; walberla::id_t const & getUid(const size_t /*p_idx*/) const {return uid_;} void setUid(const size_t /*p_idx*/, walberla::id_t const & v) { uid_ = v;} walberla::id_t& getUidRef(const size_t /*p_idx*/) {return uid_;} diff --git a/src/mesa_pd/domain/BlockForestDataHandling.h b/src/mesa_pd/domain/BlockForestDataHandling.h index 2fae4d119..7f0e4172e 100644 --- a/src/mesa_pd/domain/BlockForestDataHandling.h +++ b/src/mesa_pd/domain/BlockForestDataHandling.h @@ -68,22 +68,22 @@ class BlockForestDataHandling: public blockforest::BlockDataHandling<internal::P { public: BlockForestDataHandling(const std::shared_ptr<data::ParticleStorage>& ps) : ps_(ps) {} - virtual ~BlockForestDataHandling() {} + ~BlockForestDataHandling() override = default; - virtual internal::ParticleDeleter* initialize( IBlock * const block ) override; + internal::ParticleDeleter* initialize( IBlock * const block ) override; - virtual void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - virtual internal::ParticleDeleter* deserialize( IBlock * const block ) override; - virtual void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; + internal::ParticleDeleter* deserialize( IBlock * const block ) override; + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; - virtual void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; - virtual void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; - virtual internal::ParticleDeleter* deserializeCoarseToFine( Block * const block ) override; - virtual internal::ParticleDeleter* deserializeFineToCoarse( Block * const block ) override; + internal::ParticleDeleter* deserializeCoarseToFine( Block * const block ) override; + internal::ParticleDeleter* deserializeFineToCoarse( Block * const block ) override; - virtual void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; - virtual void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; private: void deserializeImpl( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); diff --git a/src/mesa_pd/kernel/ParticleSelector.h b/src/mesa_pd/kernel/ParticleSelector.h index 85d8b81b2..9ac4392f5 100644 --- a/src/mesa_pd/kernel/ParticleSelector.h +++ b/src/mesa_pd/kernel/ParticleSelector.h @@ -59,8 +59,7 @@ public: bool operator()(const size_t idx, Accessor& ac) const { using namespace walberla::mesa_pd::data::particle_flags; - if (isSet(ac.getFlags(idx), GHOST)) return true; - return false; + return isSet(ac.getFlags(idx), GHOST); } }; @@ -71,8 +70,7 @@ public: bool operator()(const size_t idx, const size_t jdx, Accessor& ac) const { using namespace walberla::mesa_pd::data::particle_flags; - if (isSet(ac.getFlags(idx), INFINITE) && isSet(ac.getFlags(jdx), INFINITE)) return false; - return true; + return !(isSet(ac.getFlags(idx), INFINITE) && isSet(ac.getFlags(jdx), INFINITE)); } }; diff --git a/src/mesa_pd/vtk/OutputSelector.h b/src/mesa_pd/vtk/OutputSelector.h index 32ceb5dbd..03665d48e 100644 --- a/src/mesa_pd/vtk/OutputSelector.h +++ b/src/mesa_pd/vtk/OutputSelector.h @@ -38,7 +38,7 @@ class IOutputSelector { public: IOutputSelector( char const * const ts, const uint_t c) : type_string(ts), components(c) {} - virtual ~IOutputSelector() {} + virtual ~IOutputSelector() = default; virtual void push( std::ostream& os , const data::Particle&& p, const uint_t component ) = 0; virtual void push( walberla::vtk::Base64Writer& b64, const data::Particle&& p, const uint_t component ) = 0; diff --git a/src/pde/sweeps/Jacobi.h b/src/pde/sweeps/Jacobi.h index 89f3e5277..9f8b4e714 100644 --- a/src/pde/sweeps/Jacobi.h +++ b/src/pde/sweeps/Jacobi.h @@ -55,10 +55,10 @@ public: template< typename Stencil_T > void Jacobi< Stencil_T >::operator()( IBlock * const block ) { - Field_T * sf( NULL ); - Field_T * df( NULL ); - Field_T * ff( NULL ); - StencilField_T * stencil( NULL ); + Field_T * sf( nullptr ); + Field_T * df( nullptr ); + Field_T * ff( nullptr ); + StencilField_T * stencil( nullptr ); this->getFields( block, sf, df, ff, stencil ); WALBERLA_ASSERT_GREATER_EQUAL( sf->nrOfGhostLayers(), 1 ); diff --git a/src/pde/sweeps/JacobiFixedStencil.h b/src/pde/sweeps/JacobiFixedStencil.h index eb1367aae..4efc6fc5e 100644 --- a/src/pde/sweeps/JacobiFixedStencil.h +++ b/src/pde/sweeps/JacobiFixedStencil.h @@ -55,9 +55,9 @@ public: template< typename Stencil_T > void JacobiFixedStencil< Stencil_T >::operator()( IBlock * const block ) { - Field_T * sf( NULL ); - Field_T * df( NULL ); - Field_T * ff( NULL ); + Field_T * sf( nullptr ); + Field_T * df( nullptr ); + Field_T * ff( nullptr ); this->getFields( block, sf, df, ff ); WALBERLA_ASSERT_GREATER_EQUAL( sf->nrOfGhostLayers(), 1 ); diff --git a/src/pde/sweeps/RBGS.h b/src/pde/sweeps/RBGS.h index 69f7245fa..e8d800aa5 100644 --- a/src/pde/sweeps/RBGS.h +++ b/src/pde/sweeps/RBGS.h @@ -77,9 +77,9 @@ void RBGS< Stencil_T >::update( IBlock * const block, const bool rb ) WALBERLA_ASSERT( realIsIdentical( dir.length(), real_t(1) ) ); #endif - Field_T * uf( NULL ); - Field_T * ff( NULL ); - StencilField_T * stencil( NULL ); + Field_T * uf( nullptr ); + Field_T * ff( nullptr ); + StencilField_T * stencil( nullptr ); this->getFields( block, uf, ff, stencil ); WALBERLA_ASSERT_GREATER_EQUAL( uf->nrOfGhostLayers(), 1 ); diff --git a/src/pde/sweeps/RBGSFixedStencil.h b/src/pde/sweeps/RBGSFixedStencil.h index 75196987f..5b57cc351 100644 --- a/src/pde/sweeps/RBGSFixedStencil.h +++ b/src/pde/sweeps/RBGSFixedStencil.h @@ -76,8 +76,8 @@ void RBGSFixedStencil< Stencil_T >::update( IBlock * const block, const bool rb WALBERLA_ASSERT( realIsIdentical( dir.length(), real_t(1) ) ); #endif - Field_T * uf( NULL ); - Field_T * ff( NULL ); + Field_T * uf( nullptr ); + Field_T * ff( nullptr ); this->getFields( block, uf, ff ); WALBERLA_ASSERT_GREATER_EQUAL( uf->nrOfGhostLayers(), 1 ); diff --git a/src/pde/sweeps/SOR.h b/src/pde/sweeps/SOR.h index 4997b40d6..48a0b56e3 100644 --- a/src/pde/sweeps/SOR.h +++ b/src/pde/sweeps/SOR.h @@ -77,9 +77,9 @@ void SOR< Stencil_T >::update( IBlock * const block, const bool rb ) WALBERLA_ASSERT( realIsIdentical( dir.length(), real_t(1) ) ); #endif - Field_T * uf( NULL ); - Field_T * ff( NULL ); - StencilField_T * stencil( NULL ); + Field_T * uf( nullptr ); + Field_T * ff( nullptr ); + StencilField_T * stencil( nullptr ); this->getFields( block, uf, ff, stencil ); WALBERLA_ASSERT_GREATER_EQUAL( uf->nrOfGhostLayers(), 1 ); diff --git a/src/pde/sweeps/SORFixedStencil.h b/src/pde/sweeps/SORFixedStencil.h index d3983ab18..0e9387309 100644 --- a/src/pde/sweeps/SORFixedStencil.h +++ b/src/pde/sweeps/SORFixedStencil.h @@ -76,8 +76,8 @@ void SORFixedStencil< Stencil_T >::update( IBlock * const block, const bool rb ) WALBERLA_ASSERT( realIsIdentical( dir.length(), real_t(1) ) ); #endif - Field_T * uf( NULL ); - Field_T * ff( NULL ); + Field_T * uf( nullptr ); + Field_T * ff( nullptr ); this->getFields( block, uf, ff ); WALBERLA_ASSERT_GREATER_EQUAL( uf->nrOfGhostLayers(), 1 ); diff --git a/src/pe/bg/IBG.h b/src/pe/bg/IBG.h index 8c956b567..fa7ec0662 100644 --- a/src/pe/bg/IBG.h +++ b/src/pe/bg/IBG.h @@ -29,7 +29,7 @@ namespace bg { class IBG : private NonCopyable { public: - virtual ~IBG() {}; + virtual ~IBG() = default; }; //************************************************************************************************* diff --git a/src/pe/bg/SimpleBGDataHandling.h b/src/pe/bg/SimpleBGDataHandling.h index 7b31e020b..79535c82b 100644 --- a/src/pe/bg/SimpleBGDataHandling.h +++ b/src/pe/bg/SimpleBGDataHandling.h @@ -30,7 +30,7 @@ namespace bg { class SimpleBGDataHandling : public blockforest::AlwaysInitializeBlockDataHandling<SimpleBG>{ public: - SimpleBG * initialize( IBlock * const /*block*/ ) {return new SimpleBG();} + SimpleBG * initialize( IBlock * const /*block*/ ) override {return new SimpleBG();} }; inline diff --git a/src/pe/ccd/HashGrids.h b/src/pe/ccd/HashGrids.h index 24ecec304..15b2968e3 100644 --- a/src/pe/ccd/HashGrids.h +++ b/src/pe/ccd/HashGrids.h @@ -277,7 +277,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - ~HashGrids(); + ~HashGrids() override; //@} //********************************************************************************************** @@ -286,7 +286,7 @@ public: //@{ inline void add ( BodyID body ); void remove( BodyID body ); - inline int getObservedBodyCount() const { return observedBodyCount_ + static_cast<int> (globalStorage_.size()); } + inline int getObservedBodyCount() const override { return observedBodyCount_ + static_cast<int> (globalStorage_.size()); } //@} //********************************************************************************************** @@ -294,13 +294,13 @@ public: /*!\name Utility functions */ //@{ void clear (); - void reloadBodies(); + void reloadBodies() override; //@} //********************************************************************************************** //**Implementation of ICCD interface ******************************************************** - virtual PossibleContacts& generatePossibleContacts( WcTimingTree* tt = NULL ); - void update(WcTimingTree* tt = NULL); + PossibleContacts& generatePossibleContacts( WcTimingTree* tt = nullptr ) override; + void update(WcTimingTree* tt = nullptr); bool active() const { return gridActive_; } @@ -423,7 +423,7 @@ size_t HashGrids::HashGrid::process( BodyID** gridBodies, Contacts& contacts ) c Cell* nbCell = (*cell) + (*cell)->neighborOffset_[i]; BodyVector* nbBodies = nbCell->bodies_; - if( nbBodies != NULL ) + if( nbBodies != nullptr ) { for( auto aIt = cellBodies->begin(); aIt < cellBodies->end(); ++aIt ) { auto endNeighbour = nbBodies->begin(); @@ -480,7 +480,7 @@ void HashGrids::HashGrid::processBodies( BodyID* bodies, size_t bodyCount, Conta Cell* nbCell = cell + cell->neighborOffset_[i]; BodyVector* nbBodies = nbCell->bodies_; - if( nbBodies != NULL ) { + if( nbBodies != nullptr ) { auto endNeighbour = nbBodies->begin(); if ((*aIt)->isFixed()) { @@ -521,7 +521,7 @@ BodyID HashGrids::HashGrid::getBodyIntersectionForBlockCell(const Vector3<int32_ std::function<bool (const BodyID body)> isBodyVisibleFunc) const { real_t t_local; Vec3 n_local; - BodyID body = NULL; + BodyID body = nullptr; raytracing::IntersectsFunctor intersectsFunc(ray, t_local, n_local); @@ -577,7 +577,7 @@ BodyID HashGrids::HashGrid::getBodyIntersectionForBlockCell(const Vector3<int32_ const Cell* nbCell = ¢erCell + centerCell.neighborOffset_[neighborIndex]; const BodyVector* nbBodies = nbCell->bodies_; - if (nbBodies != NULL) { + if (nbBodies != nullptr) { for (const BodyID& cellBody: *nbBodies) { if (cellBody->isRemote()) { continue; @@ -618,8 +618,8 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c std::function<bool (const BodyID body)> isBodyVisibleFunc) const { const real_t realMax = std::numeric_limits<real_t>::max(); - BodyID body_local = NULL; - BodyID body_closest = NULL; + BodyID body_local = nullptr; + BodyID body_closest = nullptr; int32_t blockXCellCountMin = int32_c(blockAABB.xMin() * inverseCellSpan_) - 1; int32_t blockXCellCountMax = int32_c(std::ceil(blockAABB.xMax() * inverseCellSpan_)) + 1; @@ -642,7 +642,7 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c firstPointCenteredInCell = firstPoint - firstPointNormal * (cellSpan_/real_t(2)); tRayOriginToGrid = (ray.getOrigin() - firstPoint).length(); } else { - return NULL; + return nullptr; } } @@ -679,7 +679,7 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c body_local = getBodyIntersectionForBlockCell<BodyTuple>(currentCell, BLOCKCELL_NORMAL_INDETERMINATE, 0, ray, t_closest, n_closest, isBodyVisibleFunc); - if (body_local != NULL) { + if (body_local != nullptr) { body_closest = body_local; } } @@ -749,7 +749,7 @@ BodyID HashGrids::HashGrid::getRayIntersectingBody(const raytracing::Ray& ray, c body_local = getBodyIntersectionForBlockCell<BodyTuple>(currentCell, blockCellNormalAxis, blockCellNormalDir, ray, t_closest, n_closest, isBodyVisibleFunc); - if (body_local != NULL) { + if (body_local != nullptr) { body_closest = body_local; } } @@ -771,7 +771,7 @@ BodyID HashGrids::getClosestBodyIntersectingWithRay(const raytracing::Ray& ray, std::function<bool (const BodyID body)> isBodyVisibleFunc) const { const real_t realMax = std::numeric_limits<real_t>::max(); - BodyID body_closest = NULL; + BodyID body_closest = nullptr; real_t t_closest = realMax; Vec3 n_closest; @@ -791,7 +791,7 @@ BodyID HashGrids::getClosestBodyIntersectingWithRay(const raytracing::Ray& ray, for(auto grid: gridList_) { body_local = grid->getRayIntersectingBody<BodyTuple>(ray, blockAABB, t_closest, n_closest, isBodyVisibleFunc); - if (body_local != NULL){ + if (body_local != nullptr){ body_closest = body_local; } } diff --git a/src/pe/ccd/HashGridsBodyTrait.h b/src/pe/ccd/HashGridsBodyTrait.h index 40ab2505e..3e82abcec 100644 --- a/src/pe/ccd/HashGridsBodyTrait.h +++ b/src/pe/ccd/HashGridsBodyTrait.h @@ -88,7 +88,7 @@ protected: * \param body The rigid body containing this bounding box. */ inline HashGridsBodyTrait::HashGridsBodyTrait( ) - : grid_ (0) // Pointer to the hash grid this rigid body is currently assigned to + : grid_ (nullptr) // Pointer to the hash grid this rigid body is currently assigned to , hash_ (0) // Current hash value of this rigid body , cellId_(0) // The body's index in the body container of the grid cell this rigid body is currently assigned to {} diff --git a/src/pe/ccd/HashGridsDataHandling.h b/src/pe/ccd/HashGridsDataHandling.h index 43aa61863..7190343c3 100644 --- a/src/pe/ccd/HashGridsDataHandling.h +++ b/src/pe/ccd/HashGridsDataHandling.h @@ -33,7 +33,7 @@ namespace ccd { class HashGridsDataHandling : public blockforest::AlwaysInitializeBlockDataHandling<HashGrids>{ public: HashGridsDataHandling(const shared_ptr<BodyStorage>& globalStorage, const BlockDataID& storageID) : globalStorage_(globalStorage), storageID_(storageID) {} - HashGrids * initialize( IBlock * const block ) + HashGrids * initialize( IBlock * const block ) override { Storage* storage = block->getData< Storage >( storageID_ ); return new HashGrids(*globalStorage_, (*storage)[0], (*storage)[1]); diff --git a/src/pe/ccd/ICCD.h b/src/pe/ccd/ICCD.h index b47a301e4..8aeb8d50a 100644 --- a/src/pe/ccd/ICCD.h +++ b/src/pe/ccd/ICCD.h @@ -33,11 +33,11 @@ namespace ccd { class ICCD : private NonCopyable { public: - virtual ~ICCD() {} + virtual ~ICCD() = default; /// Generates a list of possible contact pairs. /// This list is also stored in the member variable contacts_ for reuse lateron. - virtual PossibleContacts& generatePossibleContacts( WcTimingTree* tt = NULL ) = 0; + virtual PossibleContacts& generatePossibleContacts( WcTimingTree* tt = nullptr ) = 0; PossibleContacts& getPossibleContacts() {return contacts_;} virtual void reloadBodies() {} diff --git a/src/pe/ccd/SimpleCCD.h b/src/pe/ccd/SimpleCCD.h index 42a54f599..f00a0faee 100644 --- a/src/pe/ccd/SimpleCCD.h +++ b/src/pe/ccd/SimpleCCD.h @@ -29,11 +29,11 @@ namespace ccd { class SimpleCCD : public ICCD{ public: explicit SimpleCCD(BodyStorage& globalStorage, Storage& storage); - ~SimpleCCD(); + ~SimpleCCD() override; - virtual PossibleContacts& generatePossibleContacts( WcTimingTree* tt = NULL ); + PossibleContacts& generatePossibleContacts( WcTimingTree* tt = nullptr ) override; - int getObservedBodyCount() const; + int getObservedBodyCount() const override; private: //**Add/remove functions********************************************************************* /*!\name Add/remove functions */ diff --git a/src/pe/ccd/SimpleCCDDataHandling.h b/src/pe/ccd/SimpleCCDDataHandling.h index e6eba7709..2cf7756b7 100644 --- a/src/pe/ccd/SimpleCCDDataHandling.h +++ b/src/pe/ccd/SimpleCCDDataHandling.h @@ -33,7 +33,7 @@ namespace ccd { class SimpleCCDDataHandling : public blockforest::AlwaysInitializeBlockDataHandling<SimpleCCD>{ public: SimpleCCDDataHandling(const shared_ptr<BodyStorage>& globalStorage, const BlockDataID& storageID) : globalStorage_(globalStorage), storageID_(storageID) {} - SimpleCCD * initialize( IBlock * const block ) + SimpleCCD * initialize( IBlock * const block ) override { Storage* storage = block->getData< Storage >( storageID_ ); return new SimpleCCD(*globalStorage_, *storage); diff --git a/src/pe/cr/DEM.h b/src/pe/cr/DEM.h index f716157ef..21e1e16cf 100644 --- a/src/pe/cr/DEM.h +++ b/src/pe/cr/DEM.h @@ -51,7 +51,7 @@ public: , domain_decomposition::BlockDataID storageID , domain_decomposition::BlockDataID ccdID , domain_decomposition::BlockDataID fcdID - , WcTimingTree* tt = NULL); + , WcTimingTree* tt = nullptr); /// forwards to timestep /// Convenience operator to make class a functor. @@ -61,9 +61,9 @@ public: inline Integrator getIntegrator() const { return integrate_; } inline ContactResolver getContactResolver() const { return resolveContact_; } - virtual inline real_t getMaximumPenetration() const override { return maxPenetration_; } - virtual inline size_t getNumberOfContacts() const override { return numberOfContacts_; } - virtual inline size_t getNumberOfContactsTreated() const override { return numberOfContactsTreated_; } + inline real_t getMaximumPenetration() const override { return maxPenetration_; } + inline size_t getNumberOfContacts() const override { return numberOfContacts_; } + inline size_t getNumberOfContactsTreated() const override { return numberOfContactsTreated_; } private: Integrator integrate_; ContactResolver resolveContact_; @@ -87,7 +87,7 @@ public: , domain_decomposition::BlockDataID storageID , domain_decomposition::BlockDataID ccdID , domain_decomposition::BlockDataID fcdID - , WcTimingTree* tt = NULL) + , WcTimingTree* tt = nullptr) : DEMSolver<IntegrateImplicitEuler, ResolveContactSpringDashpotHaffWerner>( IntegrateImplicitEuler(), ResolveContactSpringDashpotHaffWerner(), globalBodyStorage, blockStorage, storageID, ccdID, fcdID, tt ) diff --git a/src/pe/cr/DEM.impl.h b/src/pe/cr/DEM.impl.h index a3560e50f..792f59bb3 100644 --- a/src/pe/cr/DEM.impl.h +++ b/src/pe/cr/DEM.impl.h @@ -77,9 +77,9 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt ) ccd::ICCD* ccd = currentBlock.getData< ccd::ICCD >( ccdID_ ); fcd::IFCD* fcd = currentBlock.getData< fcd::IFCD >( fcdID_ ); ccd->generatePossibleContacts( tt_ ); - if (tt_ != NULL) tt_->start("FCD"); + if (tt_ != nullptr) tt_->start("FCD"); Contacts& cont = fcd->generateContacts( ccd->getPossibleContacts() ); - if (tt_ != NULL) tt_->stop("FCD"); + if (tt_ != nullptr) tt_->stop("FCD"); for (auto cIt = cont.begin(); cIt != cont.end(); ++cIt){ const real_t overlap( -cIt->getDistance() ); @@ -100,9 +100,9 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt ) // if (numContacts > 0) // WALBERLA_LOG_DEVEL_ON_ROOT("#Contacts: " << numContacts << "." ); - if (tt_ != NULL) tt_->start("ForceSync"); + if (tt_ != nullptr) tt_->start("ForceSync"); reduceForces( *blockStorage_, storageID_, *globalBodyStorage_); - if (tt_ != NULL) tt_->stop("ForceSync"); + if (tt_ != nullptr) tt_->stop("ForceSync"); for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it) { @@ -114,7 +114,7 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt ) // Updating the positions and velocities of all locally owned and global rigid bodies (but not shadow copies). WALBERLA_LOG_DETAIL( "Time integration starts...\n" ); - if (tt_ != NULL) tt_->start("Integration"); + if (tt_ != nullptr) tt_->start("Integration"); for( auto bodyIt = localStorage.begin(); bodyIt != localStorage.end(); ++bodyIt ) { @@ -140,7 +140,7 @@ void DEMSolver<Integrator,ContactResolver>::timestep( real_t dt ) bodyIt->resetForceAndTorque(); } - if (tt_ != NULL) tt_->stop("Integration"); + if (tt_ != nullptr) tt_->stop("Integration"); // Reset forces of shadow copies for( auto& body : shadowStorage ) { diff --git a/src/pe/cr/HCSITS.h b/src/pe/cr/HCSITS.h index 742799f08..8cf803c46 100644 --- a/src/pe/cr/HCSITS.h +++ b/src/pe/cr/HCSITS.h @@ -117,22 +117,22 @@ public: domain_decomposition::BlockDataID storageID, domain_decomposition::BlockDataID ccdID, domain_decomposition::BlockDataID fcdID, - WcTimingTree* tt = NULL ); + WcTimingTree* tt = nullptr ); //@} //********************************************************************************************** //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - ~HardContactSemiImplicitTimesteppingSolvers(); + ~HardContactSemiImplicitTimesteppingSolvers() override; //@} //********************************************************************************************** //**Get functions******************************************************************************* /*!\name Get functions */ //@{ - virtual inline real_t getMaximumPenetration() const override; - virtual inline size_t getNumberOfContacts() const override; - virtual inline size_t getNumberOfContactsTreated() const override; + inline real_t getMaximumPenetration() const override; + inline size_t getNumberOfContacts() const override; + inline size_t getNumberOfContactsTreated() const override; inline const std::map<IBlockID::IDType, ContactCache> getContactCache() const { return blockToContactCache_; } inline real_t getSpeedLimitFactor() const; inline size_t getMaxIterations() const { return maxIterations_; } diff --git a/src/pe/cr/HCSITS.impl.h b/src/pe/cr/HCSITS.impl.h index 7218b4580..25cccf846 100644 --- a/src/pe/cr/HCSITS.impl.h +++ b/src/pe/cr/HCSITS.impl.h @@ -157,7 +157,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d numContactsTreated_ = 0; maximumPenetration_ = 0; - if (tt_ != NULL) tt_->start("Simulation Step"); + if (tt_ != nullptr) tt_->start("Simulation Step"); for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it) { @@ -176,13 +176,13 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d // Detect all collisions WALBERLA_LOG_DETAIL( "Detecting contacts..."); - if (tt_ != NULL) tt_->start("Collision Detection"); + if (tt_ != nullptr) tt_->start("Collision Detection"); ccd->generatePossibleContacts( tt_ ); - if (tt_ != NULL) tt_->start("Fine"); + if (tt_ != nullptr) tt_->start("Fine"); Contacts& contacts = fcd->generateContacts( ccd->getPossibleContacts() ); - if (tt_ != NULL) tt_->stop("Fine"); + if (tt_ != nullptr) tt_->stop("Fine"); - if (tt_ != NULL) tt_->start("Filtering"); + if (tt_ != nullptr) tt_->start("Filtering"); // Filter out contacts size_t numContacts( contacts.size() ); size_t numContactsMasked( 0 ); @@ -204,10 +204,10 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d numContactsTreated_ += numContactsMasked; // WALBERLA_LOG_DEVEL("contact filtering: " << numContactsMasked << "/" << contacts.size()); - if (tt_ != NULL) tt_->stop("Filtering"); - if (tt_ != NULL) tt_->stop("Collision Detection"); + if (tt_ != nullptr) tt_->stop("Filtering"); + if (tt_ != nullptr) tt_->stop("Collision Detection"); - if (tt_ != NULL) tt_->start("Collision Response Contact Caching"); + if (tt_ != nullptr) tt_->start("Collision Response Contact Caching"); // Cache contact properties contactCache.resize( numContactsMasked ); @@ -277,8 +277,8 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d } } - if (tt_ != NULL) tt_->stop("Collision Response Contact Caching"); - if (tt_ != NULL) tt_->start("Collision Response Body Caching"); + if (tt_ != nullptr) tt_->stop("Collision Response Contact Caching"); + if (tt_ != nullptr) tt_->start("Collision Response Body Caching"); // Cache body properties (and time integrate v and w to the end of the time step by applying external forces, torques and accelerations) size_t numBodies( globalBodyStorage_->size() + localStorage.size() + shadowStorage.size() ); @@ -331,10 +331,10 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d #endif } - if (tt_ != NULL) tt_->stop("Collision Response Body Caching"); + if (tt_ != nullptr) tt_->stop("Collision Response Body Caching"); } - if (blockStorage_->size() == 0) + if (blockStorage_->empty()) { // create artificial block to handle global bodies even on processes where there are no blocks BodyCache& bodyCache = blockToBodyCache_[0]; @@ -357,7 +357,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d } } - if (tt_ != NULL) tt_->start("Collision Response Resolution"); + if (tt_ != nullptr) tt_->start("Collision Response Resolution"); const real_t rp = relaxationParam_; relaxationParam_ = real_c(1); // must be set to 1.0 such that dv and dw caused by external forces and torques are not falsely altered synchronizeVelocities( ); @@ -372,7 +372,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d iteration_ = it; - if (tt_ != NULL) tt_->start("Collision Response Solving"); + if (tt_ != nullptr) tt_->start("Collision Response Solving"); for (auto blkIt = blockStorage_->begin(); blkIt != blockStorage_->end(); ++blkIt) { IBlock& currentBlock = *blkIt; @@ -410,7 +410,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d } } - if (tt_ != NULL) tt_->stop("Collision Response Solving"); + if (tt_ != nullptr) tt_->stop("Collision Response Solving"); synchronizeVelocities( ); @@ -438,8 +438,8 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d #endif } - if (tt_ != NULL) tt_->stop("Collision Response Resolution"); - if (tt_ != NULL) tt_->start("Collision Response Integration"); + if (tt_ != nullptr) tt_->stop("Collision Response Resolution"); + if (tt_ != nullptr) tt_->start("Collision Response Integration"); // WARNING: Even though bodyCache.dv_[j] and bodyCache.dw_[j] _should_ be exactly 0 at all times for // bodies with infinite mass/inertia, this is not the case if the simulation breaks. @@ -504,12 +504,12 @@ inline void HardContactSemiImplicitTimesteppingSolvers::timestep( const real_t d // NOTE: We might still need shadow copy updates if the user sets velocities or positions. Thus we might have to split up synchronize() again. It doesn't break anything if we still communicate the shadow copy updates though. } - if (tt_ != NULL) tt_->stop("Collision Response Integration"); + if (tt_ != nullptr) tt_->stop("Collision Response Integration"); blockToBodyCache_.clear(); blockToContactCache_.clear(); - if (tt_ != NULL) tt_->stop("Simulation Step"); + if (tt_ != nullptr) tt_->stop("Simulation Step"); } //************************************************************************************************* @@ -1506,8 +1506,8 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) if ((mpi::MPIManager::instance()->numProcesses() <= 1) && (blockStorage_->size() <= 1)) return; - if (tt_ != NULL) tt_->start("Velocity Sync"); - if (tt_ != NULL) tt_->start("Velocity Sync Correction Assembling"); + if (tt_ != nullptr) tt_->start("Velocity Sync"); + if (tt_ != nullptr) tt_->start("Velocity Sync Correction Assembling"); // Sending local force contributions of shadow copies to owner. WALBERLA_LOG_DETAIL( "Assembling of velocity correction message starts...\n" ); @@ -1558,12 +1558,12 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) } } - if (tt_ != NULL) tt_->stop("Velocity Sync Correction Assembling"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Correction Assembling"); // for( ProcessIterator process = processstorage_.begin(); process != processstorage_.end(); ++process ) // sentVelocitiesSyncCorrections_.transfered( process->getSendBuffer().size() ); - if (tt_ != NULL) tt_->start("Velocity Sync Correction Communicate"); + if (tt_ != nullptr) tt_->start("Velocity Sync Correction Communicate"); WALBERLA_LOG_DETAIL( "Communication of velocity correction message starts..." ); @@ -1573,12 +1573,12 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) syncVelBS.setReceiverInfo(recvRanks, true); syncVelBS.sendAll(); - if (tt_ != NULL) tt_->stop("Velocity Sync Correction Communicate"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Correction Communicate"); // for( ProcessIterator process = processstorage_.begin(); process != processstorage_.end(); ++process ) // receivedVelocitiesSyncCorrections_.transfered( process->getRecvBuffer().size() ); - if (tt_ != NULL) tt_->start("Velocity Sync Correction Parsing"); + if (tt_ != nullptr) tt_->start("Velocity Sync Correction Parsing"); // Receiving force and torque contributions WALBERLA_LOG_DETAIL( "Parsing of velocity correction message starts..."); @@ -1595,7 +1595,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) // it.buffer() >> sender; it.buffer() >> receiver; auto blk = blockStorage_->getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); IBlock& block = *blk; Storage* storage = block.uncheckedFastGetData< Storage >( storageID_ ); BodyStorage& localStorage = (*storage)[0]; @@ -1606,9 +1606,9 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) // if (tt_ != NULL) tt_->stop("Inside Loop"); } - if (tt_ != NULL) tt_->stop("Velocity Sync Correction Parsing"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Correction Parsing"); - if (tt_ != NULL) tt_->start("Velocity Sync Update Assembling"); + if (tt_ != nullptr) tt_->start("Velocity Sync Update Assembling"); WALBERLA_LOG_DETAIL( "Assembling of velocity update message starts..."); //========================================================== @@ -1657,24 +1657,24 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) } } - if (tt_ != NULL) tt_->stop("Velocity Sync Update Assembling"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Update Assembling"); // for( ProcessIterator process = processstorage_.begin(); process != processstorage_.end(); ++process ) // sentVelocitiesSyncUpdates_.transfered( process->getSendBuffer().size() ); - if (tt_ != NULL) tt_->start("Velocity Sync Update Communincate"); + if (tt_ != nullptr) tt_->start("Velocity Sync Update Communincate"); WALBERLA_LOG_DETAIL( "Communication of velocity update message starts..."); syncVelBS.setReceiverInfo(recvRanks, true); syncVelBS.sendAll(); - if (tt_ != NULL) tt_->stop("Velocity Sync Update Communincate"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Update Communincate"); // for( ProcessIterator process = processstorage_.begin(); process != processstorage_.end(); ++process ) // receivedVelocitiesSyncUpdates_.transfered( process->getRecvBuffer().size() ); - if (tt_ != NULL) tt_->start("Velocity Sync Update Processing"); + if (tt_ != nullptr) tt_->start("Velocity Sync Update Processing"); // Receiving velocity updates WALBERLA_LOG_DETAIL( "Parsing of velocity update message starts..."); @@ -1691,7 +1691,7 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) // it.buffer() >> sender; it.buffer() >> receiver; auto blk = blockStorage_->getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); IBlock& block = *blk; Storage* storage = block.uncheckedFastGetData< Storage >( storageID_ ); // BodyStorage& localStorage = (*storage)[0]; @@ -1702,9 +1702,9 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) // if (tt_ != NULL) tt_->stop("Inside Loop"); } - if (tt_ != NULL) tt_->stop("Velocity Sync Update Processing"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Update Processing"); - if (tt_ != NULL) tt_->start("Velocity Sync Globals"); + if (tt_ != nullptr) tt_->start("Velocity Sync Globals"); /* { size_t i; @@ -1743,8 +1743,8 @@ inline void HardContactSemiImplicitTimesteppingSolvers::synchronizeVelocities( ) } }*/ - if (tt_ != NULL) tt_->stop("Velocity Sync Globals"); - if (tt_ != NULL) tt_->stop("Velocity Sync"); + if (tt_ != nullptr) tt_->stop("Velocity Sync Globals"); + if (tt_ != nullptr) tt_->stop("Velocity Sync"); } //************************************************************************************************* diff --git a/src/pe/cr/ICR.h b/src/pe/cr/ICR.h index 73d1868d3..7c86a9fa0 100644 --- a/src/pe/cr/ICR.h +++ b/src/pe/cr/ICR.h @@ -31,7 +31,7 @@ namespace cr { class ICR { public: ICR() : /*globalLinearDrag_(0),*/ globalLinearAcceleration_(0) {} - virtual ~ICR() {} + virtual ~ICR() = default; virtual void timestep( const real_t dt ) = 0; diff --git a/src/pe/cr/PlainIntegrator.h b/src/pe/cr/PlainIntegrator.h index 92abbbfb3..c2284eff2 100644 --- a/src/pe/cr/PlainIntegrator.h +++ b/src/pe/cr/PlainIntegrator.h @@ -46,13 +46,13 @@ public: const shared_ptr<BodyStorage>& globalBodyStorage, const shared_ptr<BlockStorage>& blockStorage, domain_decomposition::BlockDataID storageID, - WcTimingTree* tt = NULL ); + WcTimingTree* tt = nullptr ); /// forwards to timestep /// Convenience operator to make class a functor. void operator()(const real_t dt) { timestep(dt); } /// Advances the simulation dt seconds. - void timestep( const real_t dt ); + void timestep( const real_t dt ) override; private: const Integrator integrate_; shared_ptr<BodyStorage> globalBodyStorage_; @@ -67,7 +67,7 @@ public: PlainIntegrator( const shared_ptr<BodyStorage>& globalBodyStorage , const shared_ptr<BlockStorage>& blockStorage , domain_decomposition::BlockDataID storageID - , WcTimingTree* tt = NULL) + , WcTimingTree* tt = nullptr) : PlainIntegratorSolver<IntegrateImplicitEuler>( IntegrateImplicitEuler(), globalBodyStorage, blockStorage, storageID, tt ) { diff --git a/src/pe/cr/PlainIntegrator.impl.h b/src/pe/cr/PlainIntegrator.impl.h index e2a45b2f8..cd071eb7f 100644 --- a/src/pe/cr/PlainIntegrator.impl.h +++ b/src/pe/cr/PlainIntegrator.impl.h @@ -57,8 +57,8 @@ PlainIntegratorSolver<Integrator>::PlainIntegratorSolver( const Integrator & int template< typename Integrator > void PlainIntegratorSolver<Integrator>::timestep( const real_t dt ) { - if (tt_!=NULL) tt_->start("PlainIntegrator"); - if (tt_!=NULL) tt_->start("Integrate Bodies"); + if (tt_!=nullptr) tt_->start("PlainIntegrator"); + if (tt_!=nullptr) tt_->start("Integrate Bodies"); for (auto it = blockStorage_->begin(); it != blockStorage_->end(); ++it){ IBlock & currentBlock = *it; Storage * storage = currentBlock.getData< Storage >( storageID_ ); @@ -80,8 +80,8 @@ void PlainIntegratorSolver<Integrator>::timestep( const real_t dt ) WALBERLA_ASSERT( bd->checkInvariants(), "Invalid body state detected" ); } } - if (tt_!=NULL) tt_->stop("Integrate Bodies"); - if (tt_!=NULL) tt_->stop("PlainIntegrator"); + if (tt_!=nullptr) tt_->stop("Integrate Bodies"); + if (tt_!=nullptr) tt_->stop("PlainIntegrator"); } } // namespace cr diff --git a/src/pe/fcd/GenericFCD.h b/src/pe/fcd/GenericFCD.h index 27a311f3c..c054ae55c 100644 --- a/src/pe/fcd/GenericFCD.h +++ b/src/pe/fcd/GenericFCD.h @@ -36,7 +36,7 @@ namespace fcd { template <typename BodyTypeTuple, template <typename Container> class CollisionFunctor > class GenericFCD : public IFCD{ public: - virtual Contacts& generateContacts(PossibleContacts& possibleContacts) + Contacts& generateContacts(PossibleContacts& possibleContacts) override { contacts_.clear(); CollisionFunctor<decltype(contacts_)> func(contacts_); diff --git a/src/pe/fcd/IFCD.h b/src/pe/fcd/IFCD.h index 0fb86fc59..e34592b3d 100644 --- a/src/pe/fcd/IFCD.h +++ b/src/pe/fcd/IFCD.h @@ -35,7 +35,7 @@ namespace fcd { class IFCD : private NonCopyable{ public: - virtual ~IFCD() {}; + virtual ~IFCD() = default; /// /// \brief generates a list of actual collisions diff --git a/src/pe/fcd/SimpleFCD.h b/src/pe/fcd/SimpleFCD.h index 6f38ec190..0527459aa 100644 --- a/src/pe/fcd/SimpleFCD.h +++ b/src/pe/fcd/SimpleFCD.h @@ -32,7 +32,7 @@ namespace fcd { template <typename BodyTypeTuple> class SimpleFCD : public GenericFCD<BodyTypeTuple, AnalyticCollideFunctor>{ public: - virtual ~SimpleFCD(){} + ~SimpleFCD() override = default; }; } diff --git a/src/pe/raytracing/Intersects.h b/src/pe/raytracing/Intersects.h index 3746ce6d0..ea7c6f850 100644 --- a/src/pe/raytracing/Intersects.h +++ b/src/pe/raytracing/Intersects.h @@ -45,7 +45,7 @@ inline bool intersects(const EllipsoidID ellipsoid, const Ray& ray, real_t& t, V inline bool intersects(const BodyID body, const Ray& ray, real_t& t, Vec3& n); -inline bool intersects(const AABB& aabb, const Ray& ray, real_t& t, real_t padding = real_t(0.0), Vec3* n = NULL); +inline bool intersects(const AABB& aabb, const Ray& ray, real_t& t, real_t padding = real_t(0.0), Vec3* n = nullptr); inline bool intersectsSphere(const Vec3& gpos, real_t radius, const Ray& ray, real_t& t0, real_t& t1); struct IntersectsFunctor @@ -430,14 +430,14 @@ inline bool intersects(const AABB& aabb, const Ray& ray, real_t& t, real_t paddi tmax = tzmax; } - if (n != NULL) { + if (n != nullptr) { (*n)[0] = (*n)[1] = (*n)[2] = real_t(0); } real_t t_; if (tmin > 0) { // ray hit box from outside t_ = tmin; - if (n != NULL) { + if (n != nullptr) { (*n)[tminAxis] = real_t(1); } } else if (tmax < 0) { @@ -447,12 +447,12 @@ inline bool intersects(const AABB& aabb, const Ray& ray, real_t& t, real_t paddi } else { // ray origin within box t_ = tmax; - if (n != NULL) { + if (n != nullptr) { (*n)[tmaxAxis] = real_t(1); } } - if (n != NULL) { + if (n != nullptr) { if (ray.getDirection() * (*n) > 0) { *n = -(*n); } diff --git a/src/pe/raytracing/Lighting.h b/src/pe/raytracing/Lighting.h index 451cfe335..1d64cbc87 100644 --- a/src/pe/raytracing/Lighting.h +++ b/src/pe/raytracing/Lighting.h @@ -39,9 +39,7 @@ struct Lighting { /*!\brief Instantiation constructor for the Lighting struct. */ - Lighting () { - - } + Lighting () = default; /*!\brief Instantiation constructor for the Lighting struct. * \param pointLightOrigin Origin of the point light. diff --git a/src/pe/raytracing/Raytracer.h b/src/pe/raytracing/Raytracer.h index 39c42aa21..f53152760 100644 --- a/src/pe/raytracing/Raytracer.h +++ b/src/pe/raytracing/Raytracer.h @@ -183,7 +183,7 @@ public: /*!\name Functions */ //@{ template <typename BodyTypeTuple> - void generateImage(const size_t timestep, WcTimingTree* tt = NULL ); + void generateImage(const size_t timestep, WcTimingTree* tt = nullptr ); void setupView_(); void setupFilenameRankWidth_(); @@ -191,9 +191,9 @@ public: private: void localOutput(const std::vector<BodyIntersectionInfo>& intersectionsBuffer, size_t timestep, - WcTimingTree* tt = NULL); + WcTimingTree* tt = nullptr); void output(const std::vector<BodyIntersectionInfo>& intersectionsBuffer, size_t timestep, - WcTimingTree* tt = NULL); + WcTimingTree* tt = nullptr); std::string getOutputFilename(const std::string& base, size_t timestep, bool isGlobalImage) const; void writeImageToFile(const std::vector<BodyIntersectionInfo>& intersectionsBuffer, @@ -201,9 +201,9 @@ private: void writeImageToFile(const std::vector<BodyIntersectionInfo>& intersectionsBuffer, const std::string& fileName) const; - void syncImageUsingMPIReduce(std::vector<BodyIntersectionInfo>& intersectionsBuffer, WcTimingTree* tt = NULL); + void syncImageUsingMPIReduce(std::vector<BodyIntersectionInfo>& intersectionsBuffer, WcTimingTree* tt = nullptr); void syncImageUsingMPIGather(std::vector<BodyIntersectionInfo>& intersections, - std::vector<BodyIntersectionInfo>& intersectionsBuffer, WcTimingTree* tt = NULL); + std::vector<BodyIntersectionInfo>& intersectionsBuffer, WcTimingTree* tt = nullptr); inline bool isPlaneVisible(const PlaneID plane, const Ray& ray) const; inline size_t coordinateToArrayIndex(size_t x, size_t y) const; @@ -502,7 +502,7 @@ inline void Raytracer::traceRayInHashGrids(const Ray& ray, BodyID& body_closest, const ccd::HashGrids* hashgrids = blockIt->uncheckedFastGetData<ccd::HashGrids>(ccdID_); BodyID body = hashgrids->getClosestBodyIntersectingWithRay<BodyTypeTuple>(ray, blockAABB, t, n, isBodyVisibleFunc_); - if (body != NULL && t < t_closest) { + if (body != nullptr && t < t_closest) { t_closest = t; body_closest = body; n_closest = n; @@ -519,7 +519,7 @@ inline void Raytracer::traceRayInHashGrids(const Ray& ray, BodyID& body_closest, */ template <typename BodyTypeTuple> void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { - if (tt != NULL) tt->start("Raytracing"); + if (tt != nullptr) tt->start("Raytracing"); const real_t realMax = std::numeric_limits<real_t>::max(); std::vector<BodyIntersectionInfo> intersections; @@ -529,25 +529,25 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH_STRICTLY) { - if (tt != NULL) tt->start("HashGrids Update"); + if (tt != nullptr) tt->start("HashGrids Update"); for (auto blockIt = forest_->begin(); blockIt != forest_->end(); ++blockIt) { ccd::HashGrids* hashgrids = blockIt->getData<ccd::HashGrids>(ccdID_); hashgrids->update(); } - if (tt != NULL) tt->stop("HashGrids Update"); + if (tt != nullptr) tt->stop("HashGrids Update"); } real_t t, t_closest; Vec3 n; Vec3 n_closest; - BodyID body_closest = NULL; + BodyID body_closest = nullptr; Ray ray(cameraPosition_, Vec3(1,0,0)); IntersectsFunctor func(ray, t, n); bool isErrorneousPixel = false; uint_t pixelErrors = 0; std::map<BodyID, std::unordered_set<BodyID>> correctToIncorrectBodyIDsMap; - if (tt != NULL) tt->start("Intersection Testing"); + if (tt != nullptr) tt->start("Intersection Testing"); for (size_t x = 0; x < pixelsHorizontal_*antiAliasFactor_; x++) { for (size_t y = 0; y < pixelsVertical_*antiAliasFactor_; y++) { Vec3 pixelLocation = viewingPlaneOrigin_ + u_*(real_c(x)+real_t(0.5))*pixelWidth_ + v_*(real_c(y)+real_t(0.5))*pixelHeight_; @@ -556,7 +556,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { n.reset(); t_closest = realMax; - body_closest = NULL; + body_closest = nullptr; if (raytracingAlgorithm_ == RAYTRACE_HASHGRIDS) { traceRayInHashGrids<BodyTypeTuple>(ray, body_closest, t_closest, n_closest); @@ -567,7 +567,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { BodyID hashgrids_body_closest = body_closest; t_closest = realMax; - body_closest = NULL; + body_closest = nullptr; traceRayNaively<BodyTypeTuple>(ray, body_closest, t_closest, n_closest); if (body_closest != hashgrids_body_closest) { @@ -583,7 +583,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { intersectionInfo.imageX = uint32_t(x); intersectionInfo.imageY = uint32_t(y); - if (!realIsIdentical(t_closest, realMax) && body_closest != NULL) { + if (!realIsIdentical(t_closest, realMax) && body_closest != nullptr) { Color color = getColor(body_closest, ray, t_closest, n_closest); if (isErrorneousPixel) { color = Color(1,0,0); @@ -606,7 +606,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { } } } - if (tt != NULL) tt->stop("Intersection Testing"); + if (tt != nullptr) tt->stop("Intersection Testing"); if (raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH || raytracingAlgorithm_ == RAYTRACE_COMPARE_BOTH_STRICTLY) { if (pixelErrors > 0) { @@ -615,7 +615,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { std::stringstream ss; for (auto it: correctToIncorrectBodyIDsMap) { const BodyID correctBody = it.first; - if (it.first != NULL) { + if (it.first != nullptr) { ss << " correct body: " << correctBody->getID() << "(" << correctBody->getHash() << ")"; } else { ss << " no body naively found"; @@ -623,7 +623,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { ss << ", hashgrids found:"; for (auto incorrectBody: it.second) { ss << " "; - if (incorrectBody != NULL) { + if (incorrectBody != nullptr) { ss << incorrectBody->getID() << "(" << incorrectBody->getHash(); } else { ss << "NULL"; @@ -662,7 +662,7 @@ void Raytracer::generateImage(const size_t timestep, WcTimingTree* tt) { output(intersectionsBuffer, timestep, tt); - if (tt != NULL) tt->stop("Raytracing"); + if (tt != nullptr) tt->stop("Raytracing"); } /*!\brief Computes the color for a certain intersection. diff --git a/src/pe/raytracing/ShadingParameters.h b/src/pe/raytracing/ShadingParameters.h index 7e476527d..c6a7eb16c 100644 --- a/src/pe/raytracing/ShadingParameters.h +++ b/src/pe/raytracing/ShadingParameters.h @@ -36,9 +36,7 @@ struct ShadingParameters { /*!\brief Instantiation constructor for the Shading struct. */ - ShadingParameters () { - - } + ShadingParameters () = default; /*!\brief Instantiation constructor for the Shading struct. * \param diffuseColor Primary color of the material. diff --git a/src/pe/rigidbody/BodyIterators.h b/src/pe/rigidbody/BodyIterators.h index 903a1195b..1948465f6 100644 --- a/src/pe/rigidbody/BodyIterators.h +++ b/src/pe/rigidbody/BodyIterators.h @@ -51,14 +51,7 @@ public: { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } //std::vector::iterator cannot be compared between different instances (assert!) @@ -169,14 +162,7 @@ public: { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } return it_ == rhs.it_; @@ -265,14 +251,7 @@ public: { if (ended_ || rhs.ended_) { - if (ended_ == rhs.ended_) - { - return true; - } - else - { - return false; - } + return ended_ == rhs.ended_; } return it_ == rhs.it_; diff --git a/src/pe/rigidbody/Box.h b/src/pe/rigidbody/Box.h index 266aead5d..883739868 100644 --- a/src/pe/rigidbody/Box.h +++ b/src/pe/rigidbody/Box.h @@ -74,7 +74,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Box(); + ~Box() override; //@} //********************************************************************************************** @@ -83,7 +83,7 @@ public: /*!\name Get functions */ //@{ inline const Vec3& getLengths() const; - virtual inline real_t getVolume() const; + inline real_t getVolume() const override; //@} //********************************************************************************************** @@ -119,15 +119,15 @@ public: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual Vec3 support( const Vec3& d ) const; - inline virtual Vec3 supportContactThreshold( const Vec3& d ) const; + inline Vec3 support( const Vec3& d ) const override; + inline Vec3 supportContactThreshold( const Vec3& d ) const override; //@} //********************************************************************************************** //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** @@ -135,15 +135,15 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/Capsule.h b/src/pe/rigidbody/Capsule.h index 937aadcda..52311a204 100644 --- a/src/pe/rigidbody/Capsule.h +++ b/src/pe/rigidbody/Capsule.h @@ -79,7 +79,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Capsule(); + ~Capsule() override; //@} //********************************************************************************************** @@ -89,14 +89,14 @@ public: //@{ inline real_t getRadius() const; inline real_t getLength() const; - inline real_t getVolume() const; + inline real_t getVolume() const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual Vec3 support( const Vec3& d ) const; + inline Vec3 support( const Vec3& d ) const override; //@} //********************************************************************************************** @@ -128,18 +128,18 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** protected: - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const override; //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/CylindricalBoundary.h b/src/pe/rigidbody/CylindricalBoundary.h index c56582c20..0dc9312dc 100644 --- a/src/pe/rigidbody/CylindricalBoundary.h +++ b/src/pe/rigidbody/CylindricalBoundary.h @@ -62,7 +62,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~CylindricalBoundary(); + ~CylindricalBoundary() override; //@} //********************************************************************************************** @@ -85,7 +85,7 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** @@ -93,10 +93,10 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const override; - virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/Ellipsoid.h b/src/pe/rigidbody/Ellipsoid.h index 958c78ab3..e9a73305f 100644 --- a/src/pe/rigidbody/Ellipsoid.h +++ b/src/pe/rigidbody/Ellipsoid.h @@ -77,7 +77,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Ellipsoid(); + ~Ellipsoid() override; //@} //********************************************************************************************** //********************************************************************************************** @@ -87,7 +87,7 @@ public: /*!\name Get functions */ //@{ inline const Vec3& getSemiAxes() const; - virtual inline real_t getVolume() const; + inline real_t getVolume() const override; //@} //********************************************************************************************** @@ -99,14 +99,14 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual Vec3 support( const Vec3& d ) const; + inline Vec3 support( const Vec3& d ) const override; //@} //********************************************************************************************** @@ -124,15 +124,15 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + inline void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/GeomPrimitive.h b/src/pe/rigidbody/GeomPrimitive.h index 2fa2f059d..359a7856f 100644 --- a/src/pe/rigidbody/GeomPrimitive.h +++ b/src/pe/rigidbody/GeomPrimitive.h @@ -68,7 +68,7 @@ protected: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~GeomPrimitive() = 0; + ~GeomPrimitive() override = 0; //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/MPIRigidBodyTrait.h b/src/pe/rigidbody/MPIRigidBodyTrait.h index 022bc2dbc..a8a055e1e 100644 --- a/src/pe/rigidbody/MPIRigidBodyTrait.h +++ b/src/pe/rigidbody/MPIRigidBodyTrait.h @@ -68,7 +68,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~MPIRigidBodyTrait() {}; + virtual ~MPIRigidBodyTrait() = default; //@} //********************************************************************************************** @@ -178,9 +178,7 @@ inline void MPIRigidBodyTrait::deregisterShadowOwner( const Owner& owner ) */ inline bool MPIRigidBodyTrait::isShadowOwnerRegistered( const Owner& owner ) const { - if( std::find( shadowOwners_.begin(), shadowOwners_.end(), owner ) == shadowOwners_.end() ) - return false; - else return true; + return std::find( shadowOwners_.begin(), shadowOwners_.end(), owner ) != shadowOwners_.end(); } //************************************************************************************************* diff --git a/src/pe/rigidbody/Plane.h b/src/pe/rigidbody/Plane.h index 94368f79f..1e8bd0966 100644 --- a/src/pe/rigidbody/Plane.h +++ b/src/pe/rigidbody/Plane.h @@ -79,7 +79,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Plane(); + ~Plane() override; //@} //********************************************************************************************** @@ -87,7 +87,7 @@ public: //**Get functions******************************************************************************* /*!\name Get functions */ //@{ - virtual inline real_t getVolume() const; + inline real_t getVolume() const override; inline const Vec3& getNormal() const; inline real_t getDisplacement() const; //@} @@ -112,7 +112,7 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** @@ -120,21 +120,21 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual void setPositionImpl ( real_t px, real_t py, real_t pz ); - virtual void setOrientationImpl ( real_t r, real_t i, real_t j, real_t k ); - virtual void translateImpl ( real_t dx, real_t dy, real_t dz ); - virtual void rotateImpl ( const Quat& dq ); - virtual void rotateAroundOriginImpl( const Quat& dq ); - virtual void rotateAroundPointImpl ( const Vec3& point, const Quat& dq ); - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl ( real_t px, real_t py, real_t pz ) const; + void setPositionImpl ( real_t px, real_t py, real_t pz ) override; + void setOrientationImpl ( real_t r, real_t i, real_t j, real_t k ) override; + void translateImpl ( real_t dx, real_t dy, real_t dz ) override; + void rotateImpl ( const Quat& dq ) override; + void rotateAroundOriginImpl( const Quat& dq ) override; + void rotateAroundPointImpl ( const Vec3& point, const Quat& dq ) override; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl ( real_t px, real_t py, real_t pz ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/RigidBody.h b/src/pe/rigidbody/RigidBody.h index 440abac64..eaecb02da 100644 --- a/src/pe/rigidbody/RigidBody.h +++ b/src/pe/rigidbody/RigidBody.h @@ -498,7 +498,7 @@ inline void RigidBody::calcMotion() */ inline bool RigidBody::hasManager() const { - return manager_ != 0; + return manager_ != nullptr; } //************************************************************************************************* diff --git a/src/pe/rigidbody/RigidBodyCastIterator.h b/src/pe/rigidbody/RigidBodyCastIterator.h index 7241baa63..3486472b4 100644 --- a/src/pe/rigidbody/RigidBodyCastIterator.h +++ b/src/pe/rigidbody/RigidBodyCastIterator.h @@ -60,7 +60,7 @@ public: //**Constructors******************************************************************************** /*!\name Constructors */ //@{ - inline RigidBodyCastIterator() {} + inline RigidBodyCastIterator() = default; explicit inline RigidBodyCastIterator( const typename ContainerType::iterator& begin, const typename ContainerType::iterator& end ); RigidBodyCastIterator( const RigidBodyCastIterator<C>& it) = default; @@ -207,7 +207,7 @@ public: //**Constructors******************************************************************************** /*!\name Constructors */ //@{ - inline ConstRigidBodyCastIterator() {} + inline ConstRigidBodyCastIterator() = default; explicit inline ConstRigidBodyCastIterator( const typename ContainerType::const_iterator& begin, const typename ContainerType::const_iterator& end ); diff --git a/src/pe/rigidbody/RigidBodyIterator.h b/src/pe/rigidbody/RigidBodyIterator.h index 8e2be67d2..ffa60d2c6 100644 --- a/src/pe/rigidbody/RigidBodyIterator.h +++ b/src/pe/rigidbody/RigidBodyIterator.h @@ -58,7 +58,7 @@ public: //**Constructors******************************************************************************** /*!\name Constructors */ //@{ - inline RigidBodyIterator() {} + inline RigidBodyIterator() = default; explicit inline RigidBodyIterator( const typename ContainerType::iterator& it ) : it_(it) {} RigidBodyIterator( const RigidBodyIterator& it) = default; @@ -226,7 +226,7 @@ public: //**Constructors******************************************************************************** /*!\name Constructors */ //@{ - inline ConstRigidBodyIterator() {} + inline ConstRigidBodyIterator() = default; inline ConstRigidBodyIterator( const RigidBodyIterator& it ) : it_(it.get()) {} explicit inline ConstRigidBodyIterator( const typename ContainerType::iterator& it ) : it_(it) {} explicit inline ConstRigidBodyIterator( const typename ContainerType::const_iterator& it ) : it_(it) {} diff --git a/src/pe/rigidbody/Sphere.h b/src/pe/rigidbody/Sphere.h index 669cf07bc..a7400fdb7 100644 --- a/src/pe/rigidbody/Sphere.h +++ b/src/pe/rigidbody/Sphere.h @@ -75,7 +75,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Sphere(); + ~Sphere() override; //@} //********************************************************************************************** //********************************************************************************************** @@ -85,7 +85,7 @@ public: /*!\name Get functions */ //@{ inline real_t getRadius() const; - virtual inline real_t getVolume() const; + inline real_t getVolume() const override; //@} //********************************************************************************************** @@ -107,14 +107,14 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual Vec3 support( const Vec3& d ) const; + inline Vec3 support( const Vec3& d ) const override; //@} //********************************************************************************************** @@ -132,15 +132,15 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const; - virtual bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl( real_t px, real_t py, real_t pz ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual void calcBoundingBox(); // Calculation of the axis-aligned bounding box + inline void calcBoundingBox() override; // Calculation of the axis-aligned bounding box //@} //********************************************************************************************** diff --git a/src/pe/rigidbody/Squirmer.h b/src/pe/rigidbody/Squirmer.h index 41a27c9a7..69270d006 100644 --- a/src/pe/rigidbody/Squirmer.h +++ b/src/pe/rigidbody/Squirmer.h @@ -41,7 +41,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Squirmer(); + ~Squirmer() override; //@} //********************************************************************************************** //********************************************************************************************** diff --git a/src/pe/rigidbody/StorageDataHandling.h b/src/pe/rigidbody/StorageDataHandling.h index 12495a01b..4260f5278 100644 --- a/src/pe/rigidbody/StorageDataHandling.h +++ b/src/pe/rigidbody/StorageDataHandling.h @@ -40,32 +40,32 @@ namespace pe{ template<typename BodyTuple> class StorageDataHandling : public blockforest::BlockDataHandling<Storage>{ public: - virtual ~StorageDataHandling() {} + ~StorageDataHandling() override = default; /// must be thread-safe ! - virtual Storage * initialize( IBlock * const block ) override; + Storage * initialize( IBlock * const block ) override; /// must be thread-safe ! - virtual void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; + void serialize( IBlock * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; /// must be thread-safe ! - virtual Storage * deserialize( IBlock * const block ) override; + Storage * deserialize( IBlock * const block ) override; /// must be thread-safe ! - virtual void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void deserialize( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; /// must be thread-safe ! - virtual void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; + void serializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer, const uint_t child ) override; /// must be thread-safe ! - virtual void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; + void serializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::SendBuffer & buffer ) override; /// must be thread-safe ! - virtual Storage * deserializeCoarseToFine( Block * const block ) override; + Storage * deserializeCoarseToFine( Block * const block ) override; /// must be thread-safe ! - virtual Storage * deserializeFineToCoarse( Block * const block ) override; + Storage * deserializeFineToCoarse( Block * const block ) override; /// must be thread-safe ! - virtual void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; + void deserializeCoarseToFine( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ) override; /// must be thread-safe ! - virtual void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; + void deserializeFineToCoarse( Block * const block, const BlockDataID & id, mpi::RecvBuffer & buffer, const uint_t child ) override; private: void deserializeImpl( IBlock * const block, const BlockDataID & id, mpi::RecvBuffer & buffer ); diff --git a/src/pe/rigidbody/Union.h b/src/pe/rigidbody/Union.h index e9337e069..31a224d26 100644 --- a/src/pe/rigidbody/Union.h +++ b/src/pe/rigidbody/Union.h @@ -87,7 +87,7 @@ public: //**Destructor********************************************************************************** /*!\name Destructor */ //@{ - virtual ~Union(); + ~Union() override; //@} //********************************************************************************************** //********************************************************************************************** @@ -121,23 +121,23 @@ public: //@} //********************************************************************************************** - virtual inline real_t getVolume() const override; + inline real_t getVolume() const override; //**Set functions******************************************************************************* /*!\name Set functions */ //@{ - virtual void setRemote( bool remote ) override; + void setRemote( bool remote ) override; //@} //********************************************************************************************** - virtual inline bool hasSubBodies() const override { return true; } + inline bool hasSubBodies() const override { return true; } //**Signal functions*************************************************************************** /*!\name Signal functions */ //@{ - virtual void handleModification() override; - virtual void handleTranslation() override; - virtual void handleRotation() override; + void handleModification() override; + void handleTranslation() override; + void handleRotation() override; //@} //********************************************************************************************** @@ -158,7 +158,7 @@ public: //**Output functions**************************************************************************** /*!\name Output functions */ //@{ - virtual void print( std::ostream& os, const char* tab ) const override; + void print( std::ostream& os, const char* tab ) const override; //@} //********************************************************************************************** @@ -166,21 +166,21 @@ protected: //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - virtual void setPositionImpl ( real_t px, real_t py, real_t pz ) override; - virtual void setOrientationImpl ( real_t r, real_t i, real_t j, real_t k ) override; - virtual void translateImpl ( real_t dx, real_t dy, real_t dz ) override; - virtual void rotateImpl ( const Quat& dq ) override; - virtual void rotateAroundOriginImpl( const Quat& dq ) override; - virtual void rotateAroundPointImpl ( const Vec3& point, const Quat& dq ) override; - virtual bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; - virtual bool isSurfaceRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + void setPositionImpl ( real_t px, real_t py, real_t pz ) override; + void setOrientationImpl ( real_t r, real_t i, real_t j, real_t k ) override; + void translateImpl ( real_t dx, real_t dy, real_t dz ) override; + void rotateImpl ( const Quat& dq ) override; + void rotateAroundOriginImpl( const Quat& dq ) override; + void rotateAroundPointImpl ( const Vec3& point, const Quat& dq ) override; + bool containsRelPointImpl ( real_t px, real_t py, real_t pz ) const override; + bool isSurfaceRelPointImpl ( real_t px, real_t py, real_t pz ) const override; //@} //********************************************************************************************** //**Utility functions*************************************************************************** /*!\name Utility functions */ //@{ - inline virtual void calcBoundingBox() override; // Calculation of the axis-aligned bounding box + inline void calcBoundingBox() override; // Calculation of the axis-aligned bounding box inline void calcCenterOfMass(); // Compute mass and center of gravity inline void calcInertia(); // Calculation of the moment of inertia //@} diff --git a/src/pe/rigidbody/UnionFactory.h b/src/pe/rigidbody/UnionFactory.h index 6ad1d934e..04090a61d 100644 --- a/src/pe/rigidbody/UnionFactory.h +++ b/src/pe/rigidbody/UnionFactory.h @@ -133,7 +133,7 @@ BoxID createBox( Union<BodyTypes...>* un, throw std::runtime_error("Box TypeID not initalized!"); // union not on this process/block -> terminate creation - if (un == NULL) + if (un == nullptr) throw std::invalid_argument( "createBox: Union argument is NULL" ); // main union not on this process/block -> terminate creation @@ -159,7 +159,7 @@ BoxID createBox( Union<BodyTypes...>* un, std::unique_ptr<Box> box = std::make_unique<Box>(sid, uid, gpos, Quat(), lengths, material, global, communicating, infiniteMass); box->MPITrait.setOwner( un->MPITrait.getOwner() ); - if (box != NULL) + if (box != nullptr) { // Logging the successful creation of the box WALBERLA_LOG_DETAIL( @@ -199,7 +199,7 @@ CapsuleID createCapsule( Union<BodyTypes...>* un, throw std::runtime_error("Capsule TypeID not initalized!"); // union not on this process/block -> terminate creation - if (un == NULL) + if (un == nullptr) throw std::invalid_argument( "createCapsule: Union argument is NULL" ); // main union not on this process/block -> terminate creation @@ -229,7 +229,7 @@ CapsuleID createCapsule( Union<BodyTypes...>* un, std::unique_ptr<Capsule> capsule = std::make_unique<Capsule>(sid, uid, gpos, Quat(), radius, length, material, global, communicating, infiniteMass); capsule->MPITrait.setOwner( un->MPITrait.getOwner() ); - if (capsule != NULL) + if (capsule != nullptr) { WALBERLA_LOG_DETAIL("Created capsule " << capsule->getSystemID() << "\n" << *capsule); } @@ -260,7 +260,7 @@ SphereID createSphere( Union<BodyTypes...>* un, throw std::runtime_error("Sphere TypeID not initalized!"); // union not on this process/block -> terminate creation - if (un == NULL) + if (un == nullptr) throw std::invalid_argument( "createSphere: Union argument is NULL" ); // main union not on this process/block -> terminate creation @@ -287,7 +287,7 @@ SphereID createSphere( Union<BodyTypes...>* un, std::unique_ptr<Sphere> sphere = std::make_unique<Sphere>(sid, uid, gpos, Quat(), radius, material, global, communicating, infiniteMass); sphere->MPITrait.setOwner( un->MPITrait.getOwner() ); - if (sphere != NULL) + if (sphere != nullptr) { // Logging the successful creation of the sphere WALBERLA_LOG_DETAIL( diff --git a/src/pe/synchronization/SyncForces.h b/src/pe/synchronization/SyncForces.h index b28fb837a..a99071943 100644 --- a/src/pe/synchronization/SyncForces.h +++ b/src/pe/synchronization/SyncForces.h @@ -110,7 +110,7 @@ void reduceForces( BlockStorage& blocks, BlockDataID storageID ) it.buffer() >> sender; it.buffer() >> receiver; auto blk = blocks.getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); IBlock& block = *blk; Storage* storage = block.getData< Storage >( storageID ); BodyStorage& localStorage = (*storage)[0]; @@ -231,7 +231,7 @@ void distributeForces( BlockStorage& blocks, BlockDataID storageID ) it.buffer() >> sender; it.buffer() >> receiver; auto blk = blocks.getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); IBlock& block = *blk; Storage* storage = block.getData< Storage >( storageID ); BodyStorage& localStorage = (*storage)[0]; diff --git a/src/pe/synchronization/SyncNextNeighbors.h b/src/pe/synchronization/SyncNextNeighbors.h index 83ad74ac0..4fd166011 100644 --- a/src/pe/synchronization/SyncNextNeighbors.h +++ b/src/pe/synchronization/SyncNextNeighbors.h @@ -250,10 +250,10 @@ void generateSynchonizationMessages(mpi::BufferSystem& bs, const Block& block, B } template <typename BodyTypeTuple> -void syncNextNeighbors( BlockForest& forest, BlockDataID storageID, WcTimingTree* tt = NULL, const real_t dx = real_t(0), const bool syncNonCommunicatingBodies = false ) +void syncNextNeighbors( BlockForest& forest, BlockDataID storageID, WcTimingTree* tt = nullptr, const real_t dx = real_t(0), const bool syncNonCommunicatingBodies = false ) { - if (tt != NULL) tt->start("Sync"); - if (tt != NULL) tt->start("Assembling Body Synchronization"); + if (tt != nullptr) tt->start("Sync"); + if (tt != nullptr) tt->start("Assembling Body Synchronization"); mpi::BufferSystem bs( mpi::MPIManager::instance()->comm() ); for (auto it = forest.begin(); it != forest.end(); ++it) @@ -274,13 +274,13 @@ void syncNextNeighbors( BlockForest& forest, BlockDataID storageID, WcTimingTree } generateSynchonizationMessages<BodyTypeTuple>(bs, *block, *localStorage, *shadowStorage, dx, syncNonCommunicatingBodies); } - if (tt != NULL) tt->stop("Assembling Body Synchronization"); + if (tt != nullptr) tt->stop("Assembling Body Synchronization"); // size of buffer is unknown and changes with each send bs.setReceiverInfoFromSendBufferState(false, true); bs.sendAll(); - if (tt != NULL) tt->start("Parsing Body Synchronization"); + if (tt != nullptr) tt->start("Parsing Body Synchronization"); // Receiving the updates for the remote rigid bodies from the connected processes WALBERLA_LOG_DETAIL( "Parsing of body synchronization response starts..." ); for( auto it = bs.begin(); it != bs.end(); ++it ) @@ -294,7 +294,7 @@ void syncNextNeighbors( BlockForest& forest, BlockDataID storageID, WcTimingTree it.buffer() >> sender; it.buffer() >> receiver; auto blk = forest.getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); IBlock& block = *blk; Storage* storage = block.getData< Storage >( storageID ); BodyStorage& localStorage = (*storage)[0]; @@ -303,8 +303,8 @@ void syncNextNeighbors( BlockForest& forest, BlockDataID storageID, WcTimingTree } } WALBERLA_LOG_DETAIL( "Parsing of body synchronization response ended." ); - if (tt != NULL) tt->stop("Parsing Body Synchronization"); - if (tt != NULL) tt->stop("Sync"); + if (tt != nullptr) tt->stop("Parsing Body Synchronization"); + if (tt != nullptr) tt->stop("Sync"); } } // namespace pe diff --git a/src/pe/synchronization/SyncShadowOwners.h b/src/pe/synchronization/SyncShadowOwners.h index 89716ed28..32669e303 100644 --- a/src/pe/synchronization/SyncShadowOwners.h +++ b/src/pe/synchronization/SyncShadowOwners.h @@ -193,7 +193,7 @@ void updateAndMigrate( BlockForest& forest, BlockDataID storageID, const bool sy it.buffer() >> sender; it.buffer() >> receiver; auto blk = forest.getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); Block * block = dynamic_cast< Block * >( blk ); Storage* storage = block->getData< Storage >( storageID ); BodyStorage& localStorage = (*storage)[0]; @@ -360,7 +360,7 @@ void checkAndResolveOverlap( BlockForest& forest, BlockDataID storageID, const r it.buffer() >> sender; it.buffer() >> receiver; auto blk = forest.getBlock(receiver); - WALBERLA_CHECK(blk != NULL, receiver << " not on this process!"); + WALBERLA_CHECK(blk != nullptr, receiver << " not on this process!"); Block * block = dynamic_cast< Block * >( blk ); Storage* storage = block->getData< Storage >( storageID ); BodyStorage& localStorage = (*storage)[0]; @@ -372,25 +372,25 @@ void checkAndResolveOverlap( BlockForest& forest, BlockDataID storageID, const r } template <typename BodyTypeTuple> -void syncShadowOwners( BlockForest& forest, BlockDataID storageID, WcTimingTree* tt = NULL, const real_t dx = real_t(0), const bool syncNonCommunicatingBodies = false ) +void syncShadowOwners( BlockForest& forest, BlockDataID storageID, WcTimingTree* tt = nullptr, const real_t dx = real_t(0), const bool syncNonCommunicatingBodies = false ) { - if (tt != NULL) tt->start("Sync"); + if (tt != nullptr) tt->start("Sync"); //========================================================== // STEP1: Update & Migrate //========================================================== - if (tt != NULL) tt->start("Update&Migrate"); + if (tt != nullptr) tt->start("Update&Migrate"); updateAndMigrate<BodyTypeTuple>( forest, storageID, syncNonCommunicatingBodies); - if (tt != NULL) tt->stop("Update&Migrate"); + if (tt != nullptr) tt->stop("Update&Migrate"); //========================================================== // STEP2: Check & Resolve //========================================================== - if (tt != NULL) tt->start("Check&Resolve"); + if (tt != nullptr) tt->start("Check&Resolve"); checkAndResolveOverlap<BodyTypeTuple>( forest, storageID, dx, syncNonCommunicatingBodies); - if (tt != NULL) tt->stop("Check&Resolve"); + if (tt != nullptr) tt->stop("Check&Resolve"); - if (tt != NULL) tt->stop("Sync"); + if (tt != nullptr) tt->stop("Sync"); } } diff --git a/src/pe/utility/BodyCast.h b/src/pe/utility/BodyCast.h index ebd6574b7..f3f6e1ca8 100644 --- a/src/pe/utility/BodyCast.h +++ b/src/pe/utility/BodyCast.h @@ -39,7 +39,7 @@ public: static_assert(std::is_base_of<RigidBody, CastBodyType>::value, "only downcasting allowed!"); if (CastBodyType::getStaticTypeID() == typeID) { - CastBodyType* bd = NULL; + CastBodyType* bd = nullptr; return func( static_cast<CastBodyType *>( bd ) ); } else { diff --git a/src/pe/vtk/BodyVtkOutput.h b/src/pe/vtk/BodyVtkOutput.h index 3898f6f10..4a91a8893 100644 --- a/src/pe/vtk/BodyVtkOutput.h +++ b/src/pe/vtk/BodyVtkOutput.h @@ -42,14 +42,14 @@ public: : storageID_( storageID ) , blockStorage_( blockStorage ) { } - std::vector< Attributes > getAttributes() const; + std::vector< Attributes > getAttributes() const override; - void configure(); + void configure() override; - std::vector< Vector3< real_t > > getPoints(); + std::vector< Vector3< real_t > > getPoints() override; - inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ); - inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ); + inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ) override; + inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ) override; private: diff --git a/src/pe/vtk/EllipsoidVtkOutput.h b/src/pe/vtk/EllipsoidVtkOutput.h index 767c1b978..b4ab6c241 100644 --- a/src/pe/vtk/EllipsoidVtkOutput.h +++ b/src/pe/vtk/EllipsoidVtkOutput.h @@ -46,14 +46,14 @@ public: : storageID_( storageID ) , blockStorage_( blockStorage ) { } - std::vector< Attributes > getAttributes() const; + std::vector< Attributes > getAttributes() const override; - void configure(); + void configure() override; - std::vector< Vector3< real_t > > getPoints(); + std::vector< Vector3< real_t > > getPoints() override; - inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ); - inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ); + inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ) override; + inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ) override; private: diff --git a/src/pe/vtk/SphereVtkOutput.h b/src/pe/vtk/SphereVtkOutput.h index 655faec08..db307c273 100755 --- a/src/pe/vtk/SphereVtkOutput.h +++ b/src/pe/vtk/SphereVtkOutput.h @@ -46,14 +46,14 @@ public: : storageID_( storageID ) , blockStorage_( blockStorage ) { } - std::vector< Attributes > getAttributes() const; + std::vector< Attributes > getAttributes() const override; - void configure(); + void configure() override; - std::vector< Vector3< real_t > > getPoints(); + std::vector< Vector3< real_t > > getPoints() override; - inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ); - inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ); + inline void push( std::ostream& os , const uint_t /*data*/, const uint_t point, const uint_t component ) override; + inline void push( vtk::Base64Writer& b64, const uint_t /*data*/, const uint_t point, const uint_t component ) override; private: diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h index 72649668d..7c62ccb5b 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h @@ -121,7 +121,7 @@ void GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut { PdfField_T * src( NULL ); PdfField_T * dst( NULL ); - ScalarField_T * solidVolumeFractionField( NULL ); + ScalarField_T * solidVolumeFractionField( nullptr ); getFields( block, src, dst, solidVolumeFractionField ); @@ -187,8 +187,8 @@ template< typename LatticeModel_T, typename Filter_T, typename DensityVelocityIn void GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); lbm::SweepBase<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>::getFields( block, src, dst ); lbm::StreamPull< LatticeModel_T >::execute( src, dst, block, this->filter_, numberOfGhostLayersToInclude ); } diff --git a/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h b/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h index 78676106b..66992d54d 100644 --- a/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h +++ b/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h @@ -133,9 +133,9 @@ template< typename LatticeModel_T, typename Filter_T, typename DensityVelocityIn void PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T >::streamCollide( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); - BodyAndVolumeFractionField_T * bodyAndVolumeFractionField( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); + BodyAndVolumeFractionField_T * bodyAndVolumeFractionField( nullptr ); getFields( block, src, dst, bodyAndVolumeFractionField ); @@ -282,8 +282,8 @@ template< typename LatticeModel_T, typename Filter_T, typename DensityVelocityIn void PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T >::stream( IBlock * const block, const uint_t numberOfGhostLayersToInclude ) { - PdfField_T * src( NULL ); - PdfField_T * dst( NULL ); + PdfField_T * src( nullptr ); + PdfField_T * dst( nullptr ); lbm::SweepBase<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>::getFields( block, src, dst ); lbm::StreamPull< LatticeModel_T >::execute( src, dst, block, this->filter_, numberOfGhostLayersToInclude ); } diff --git a/src/timeloop/ITimeloop.h b/src/timeloop/ITimeloop.h index cc43aec38..3a77ca995 100644 --- a/src/timeloop/ITimeloop.h +++ b/src/timeloop/ITimeloop.h @@ -31,7 +31,7 @@ namespace timeloop { class ITimeloop { public: - virtual ~ITimeloop() {}; + virtual ~ITimeloop() = default; virtual void run() = 0; virtual void singleStep() = 0; diff --git a/src/timeloop/SelectableFunctionCreators.h b/src/timeloop/SelectableFunctionCreators.h index 4deaa2ce4..e3a29325c 100644 --- a/src/timeloop/SelectableFunctionCreators.h +++ b/src/timeloop/SelectableFunctionCreators.h @@ -55,7 +55,7 @@ namespace timeloop { template <typename FuncType> struct SelectableFunction { - SelectableFunction() {} + SelectableFunction() = default; SelectableFunction ( std::function< FuncType > fct, const std::string& identifier = std::string(), @@ -77,7 +77,7 @@ namespace timeloop { struct BeforeFunction : public SelectableFunction< void () > { - BeforeFunction() {} + BeforeFunction() = default; BeforeFunction(std::function< void () > fct, const std::string& id = std::string(), const Set<SUID>& req = Set<SUID>::emptySet(), @@ -95,7 +95,7 @@ namespace timeloop { struct AfterFunction : public SelectableFunction< void () > { - AfterFunction() {} + AfterFunction() = default; AfterFunction(std::function< void () > fct, const std::string& id = std::string(), const Set<SUID>& req = Set<SUID>::emptySet(), diff --git a/src/timeloop/SweepTimeloop.h b/src/timeloop/SweepTimeloop.h index a9b4d6d2a..3bd6c1488 100644 --- a/src/timeloop/SweepTimeloop.h +++ b/src/timeloop/SweepTimeloop.h @@ -129,7 +129,7 @@ namespace timeloop { nextId_(0), firstRun_(true) {} - virtual ~SweepTimeloop() + ~SweepTimeloop() override { for ( auto i = sweeps_.begin(); i != sweeps_.end(); ++i ) delete i->second; @@ -166,8 +166,8 @@ namespace timeloop { sweeps_.erase( *it ); } - virtual void doTimeStep(const Set<SUID> &selectors); - virtual void doTimeStep(const Set<SUID> &selectors, WcTimingPool &tp); + void doTimeStep(const Set<SUID> &selectors) override; + void doTimeStep(const Set<SUID> &selectors, WcTimingPool &tp) override; uint_t nextId_; std::vector<uint_t> sweepsToDelete_; diff --git a/src/timeloop/Timeloop.h b/src/timeloop/Timeloop.h index e2cc55001..f1430ec63 100644 --- a/src/timeloop/Timeloop.h +++ b/src/timeloop/Timeloop.h @@ -58,7 +58,7 @@ private: { public: LoggingStamp( const Timeloop & timeloop ) : timeloop_( timeloop ) {} - std::string stamp() + std::string stamp() override { std::ostringstream oss; int indention; @@ -74,7 +74,7 @@ private: << std::setfill(' ') << std::right << timeloop_.curTimeStep_; return std::string("[") + oss.str() + std::string("]"); } - uint_t maxStampWidth() + uint_t maxStampWidth() override { if( timeloop_.nrOfTimeSteps_ > 0 ) return uint_c( std::ceil( std::log10( real_c( timeloop_.nrOfTimeSteps_ ) ) ) ) + uint_c(2); @@ -111,7 +111,7 @@ public: //@{ Timeloop( uint_t nrOfTimeSteps ); - virtual ~Timeloop() {} + ~Timeloop() override = default; //@} //**************************************************************************************************************** @@ -119,19 +119,19 @@ public: //** Execution Control ******************************************************************************************* /*! \name Execution Control*/ //@{ - virtual void run() { run(true); } + void run() override { run(true); } void run( const bool logTimeStep ); void run( WcTimingPool & timing, const bool logTimeStep = true ); - virtual void singleStep() { singleStep(true); } + void singleStep() override { singleStep(true); } void singleStep( const bool logTimeStep ); void singleStep( WcTimingPool & timing, const bool logTimeStep = true ); - void stop(); - void synchronizedStop( bool stop ); + void stop() override; + void synchronizedStop( bool stop ) override; void setCurrentTimeStepToZero() { curTimeStep_ = 0; } - void setCurrentTimeStep( uint_t ts) { curTimeStep_ = ts; } + void setCurrentTimeStep( uint_t ts) override { curTimeStep_ = ts; } //@} //**************************************************************************************************************** @@ -173,8 +173,8 @@ public: //** Timestep **************************************************************************************************** /*! \name Timestep */ //@{ - uint_t getCurrentTimeStep() const { return curTimeStep_; } - uint_t getNrOfTimeSteps() const { return nrOfTimeSteps_; } + uint_t getCurrentTimeStep() const override { return curTimeStep_; } + uint_t getNrOfTimeSteps() const override { return nrOfTimeSteps_; } //@} //**************************************************************************************************************** diff --git a/src/vtk/BlockCellDataWriter.h b/src/vtk/BlockCellDataWriter.h index d0eabef2c..cac2599c7 100644 --- a/src/vtk/BlockCellDataWriter.h +++ b/src/vtk/BlockCellDataWriter.h @@ -110,8 +110,8 @@ namespace internal { class BlockCellDataWriter { public: - BlockCellDataWriter( const std::string& id ) : block_( NULL ), blockStorage_( NULL ), identifier_( id ) {} - virtual ~BlockCellDataWriter() {} + BlockCellDataWriter( const std::string& id ) : block_( nullptr ), blockStorage_( nullptr ), identifier_( id ) {} + virtual ~BlockCellDataWriter() = default; void configure( const IBlock& block, const StructuredBlockStorage& sbs ) { block_ = █ blockStorage_ = &sbs; configure(); } @@ -171,7 +171,7 @@ protected: private: - BlockCellDataWriter() {} + BlockCellDataWriter() = default; }; // class BlockCellDataWriter @@ -224,14 +224,14 @@ public: static const uint_t F_SIZE = F_SIZE_ARG; BlockCellDataWriter( const std::string & id ) : BlockCellDataWriterInterface( id ) {} - virtual ~BlockCellDataWriter() {} + ~BlockCellDataWriter() override = default; - void push( std::ostream & os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + void push( std::ostream & os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { vtk::toStream( os, evaluate( x, y, z, f ) ); } - void push( vtk::Base64Writer & b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) + void push( vtk::Base64Writer & b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) override { b64 << evaluate( x, y, z, f ); } @@ -239,7 +239,7 @@ public: void push( std::ostream& os, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f, const real_t localXCell, const real_t localYCell, const real_t localZCell, const real_t globalX, const real_t globalY, const real_t globalZ, - const real_t samplingDx, const real_t samplingDy, const real_t samplingDz ) + const real_t samplingDx, const real_t samplingDy, const real_t samplingDz ) override { vtk::toStream( os, evaluate( x, y, z, f, localXCell, localYCell, localZCell, globalX, globalY, globalZ, samplingDx, samplingDy, samplingDz ) ); @@ -248,14 +248,14 @@ public: void push( Base64Writer& b64, const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f, const real_t localXCell, const real_t localYCell, const real_t localZCell, const real_t globalX, const real_t globalY, const real_t globalZ, - const real_t samplingDx, const real_t samplingDy, const real_t samplingDz ) + const real_t samplingDx, const real_t samplingDy, const real_t samplingDz ) override { b64 << evaluate( x, y, z, f, localXCell, localYCell, localZCell, globalX, globalY, globalZ, samplingDx, samplingDy, samplingDz ); } - uint_t fSize() const { return F_SIZE; } + uint_t fSize() const override { return F_SIZE; } - std::string typeString() const { return vtk::typeToString< T >(); } + std::string typeString() const override { return vtk::typeToString< T >(); } protected: virtual T evaluate( const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, const cell_idx_t f ) = 0; diff --git a/src/vtk/DumpBlockStructureLevel.h b/src/vtk/DumpBlockStructureLevel.h index 5d0b8953b..6c0e8932b 100644 --- a/src/vtk/DumpBlockStructureLevel.h +++ b/src/vtk/DumpBlockStructureLevel.h @@ -37,9 +37,9 @@ public: protected: - void configure() { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); WALBERLA_ASSERT_NOT_NULLPTR( this->blockStorage_ ); level_ = uint8_c( this->blockStorage_->getLevel( *(this->block_) ) ); } + void configure() override { WALBERLA_ASSERT_NOT_NULLPTR( this->block_ ); WALBERLA_ASSERT_NOT_NULLPTR( this->blockStorage_ ); level_ = uint8_c( this->blockStorage_->getLevel( *(this->block_) ) ); } - uint8_t evaluate( const cell_idx_t, const cell_idx_t, const cell_idx_t, const cell_idx_t ) { return level_; } + uint8_t evaluate( const cell_idx_t, const cell_idx_t, const cell_idx_t, const cell_idx_t ) override { return level_; } uint8_t level_; diff --git a/src/vtk/DumpBlockStructureProcess.h b/src/vtk/DumpBlockStructureProcess.h index 3bdd64e6c..0887b8243 100644 --- a/src/vtk/DumpBlockStructureProcess.h +++ b/src/vtk/DumpBlockStructureProcess.h @@ -38,9 +38,9 @@ public: protected: - void configure() {} + void configure() override {} - int evaluate( const cell_idx_t, const cell_idx_t, const cell_idx_t, const cell_idx_t ) { return MPIManager::instance()->rank(); } + int evaluate( const cell_idx_t, const cell_idx_t, const cell_idx_t, const cell_idx_t ) override { return MPIManager::instance()->rank(); } }; // DumpBlockStructureProcess diff --git a/src/vtk/Initialization.h b/src/vtk/Initialization.h index 22e590218..50fd523c3 100644 --- a/src/vtk/Initialization.h +++ b/src/vtk/Initialization.h @@ -41,7 +41,7 @@ typedef std::function< void () > OutputFunction; struct SelectableOutputFunction { - SelectableOutputFunction() {} + SelectableOutputFunction() = default; SelectableOutputFunction( OutputFunction of, const Set<SUID>& rgs, const Set<SUID>& igs ) : outputFunction( of ), requiredGlobalStates( rgs ), incompatibleGlobalStates( igs ) {} diff --git a/src/vtk/PointDataSource.h b/src/vtk/PointDataSource.h index 382e0e79d..af959aafe 100644 --- a/src/vtk/PointDataSource.h +++ b/src/vtk/PointDataSource.h @@ -49,7 +49,7 @@ public: uint_t components; }; - virtual ~PointDataSource() {} + virtual ~PointDataSource() = default; virtual std::vector< Attributes > getAttributes() const = 0; diff --git a/src/vtk/PolylineDataSource.h b/src/vtk/PolylineDataSource.h index 59048019f..c3b39a18d 100644 --- a/src/vtk/PolylineDataSource.h +++ b/src/vtk/PolylineDataSource.h @@ -51,7 +51,7 @@ public: typedef std::vector< Vector3< real_t > > Polyline; - virtual ~PolylineDataSource() {} + virtual ~PolylineDataSource() = default; virtual std::vector< Attributes > getAttributes() const = 0; diff --git a/src/vtk/VTKOutput.h b/src/vtk/VTKOutput.h index a9c9ec12d..dc36ae003 100644 --- a/src/vtk/VTKOutput.h +++ b/src/vtk/VTKOutput.h @@ -62,11 +62,9 @@ private: struct VertexCompare { bool operator()( const Vertex& lhs, const Vertex& rhs ) const { - if( std::get<0>(lhs) < std::get<0>(rhs) || + return std::get<0>(lhs) < std::get<0>(rhs) || ( std::get<0>(lhs) == std::get<0>(rhs) && std::get<1>(lhs) < std::get<1>(rhs) ) || - ( std::get<0>(lhs) == std::get<0>(rhs) && std::get<1>(lhs) == std::get<1>(rhs) && std::get<2>(lhs) < std::get<2>(rhs) ) ) - return true; - return false; + ( std::get<0>(lhs) == std::get<0>(rhs) && std::get<1>(lhs) == std::get<1>(rhs) && std::get<2>(lhs) < std::get<2>(rhs) ); } }; @@ -353,7 +351,7 @@ inline void VTKOutput::addAABBInclusionFilter( const AABB & aabb ) if( pointDataSource_ || polylineDataSource_ ) aabbInclusionFilters_.push_back( aabb ); else - cellInclusionFunctions_.push_back( AABBCellFilter(aabb) ); + cellInclusionFunctions_.emplace_back(AABBCellFilter(aabb) ); } @@ -370,7 +368,7 @@ inline void VTKOutput::addAABBExclusionFilter( const AABB & aabb ) if( pointDataSource_ || polylineDataSource_ ) aabbExclusionFilters_.push_back( aabb ); else - cellExclusionFunctions_.push_back( AABBCellFilter(aabb) ); + cellExclusionFunctions_.emplace_back(AABBCellFilter(aabb) ); } diff --git a/tests/core/FunctionTraitsTest.cpp b/tests/core/FunctionTraitsTest.cpp index 4124fb6bf..8c378ecea 100644 --- a/tests/core/FunctionTraitsTest.cpp +++ b/tests/core/FunctionTraitsTest.cpp @@ -30,7 +30,7 @@ template< typename F> struct SomeClass { template< typename T> - static bool checkParameter1( typename std::enable_if< (FunctionTraits<F>::arity > 1 ), T >::type * = 0) { + static bool checkParameter1( typename std::enable_if< (FunctionTraits<F>::arity > 1 ), T >::type * = nullptr) { // The keyword "template" before "argument<1>" is crucial when these functions are inside a class. If the // keyword is dropped, compilers interpret "<1" as an arithmetic expression and therefore throw errors. diff --git a/tests/core/mpi/ReduceTest.cpp b/tests/core/mpi/ReduceTest.cpp index fa376b8d7..9093d63f3 100644 --- a/tests/core/mpi/ReduceTest.cpp +++ b/tests/core/mpi/ReduceTest.cpp @@ -140,8 +140,8 @@ void runTestAllReduceBool() const bool allTrue = true; const bool allFalse = false; - const bool oneTrue = rank == 0 ? true: false; - const bool mixed = ( rank % 2 ) ? true : false; + const bool oneTrue = rank == 0; + const bool mixed = ( rank % 2 ) != 0; WALBERLA_CHECK_EQUAL( mpi::allReduce( allTrue, mpi::LOGICAL_AND ), true ); WALBERLA_CHECK_EQUAL( mpi::allReduce( allFalse, mpi::LOGICAL_AND ), false ); @@ -212,8 +212,8 @@ void runTestAllReduceBool() std::vector<bool> bools( 4u ); bools[0] = true; bools[1] = false; - bools[2] = rank == 0 ? true : false; - bools[3] = ( rank % 2 ) ? true : false; + bools[2] = rank == 0; + bools[3] = ( rank % 2 ) != 0; { std::vector<bool> result( bools ); @@ -255,8 +255,8 @@ void runTestReduceBool( int recvRank ) const bool allTrue = true; const bool allFalse = false; - const bool oneTrue = rank == 0 ? true: false; - const bool mixed = ( rank % 2 ) ? true : false; + const bool oneTrue = rank == 0; + const bool mixed = ( rank % 2 ) != 0; { bool result0 = mpi::reduce( allTrue, mpi::LOGICAL_AND, recvRank ); @@ -387,8 +387,8 @@ void runTestReduceBool( int recvRank ) std::vector<bool> bools( 4u ); bools[0] = true; bools[1] = false; - bools[2] = rank == 0 ? true : false; - bools[3] = ( rank % 2 ) ? true : false; + bools[2] = rank == 0; + bools[3] = ( rank % 2 ) != 0; { std::vector<bool> result( bools ); diff --git a/tests/mesa_pd/domain/BlockForestDomain.cpp b/tests/mesa_pd/domain/BlockForestDomain.cpp index 297cbd5fe..6997297c7 100644 --- a/tests/mesa_pd/domain/BlockForestDomain.cpp +++ b/tests/mesa_pd/domain/BlockForestDomain.cpp @@ -66,8 +66,8 @@ void main( int argc, char ** argv ) WALBERLA_CHECK(domain.isContainedInProcessSubdomain(0, Vec3(2,2,2))); WALBERLA_CHECK(domain.isContainedInProcessSubdomain(1, Vec3(7,7,7))); - WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(2,2,2), real_t(1)), rank == 0 ? true : false); - WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(7,7,7), real_t(1)), rank == 0 ? false : true); + WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(2,2,2), real_t(1)), rank == 0); + WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(7,7,7), real_t(1)), rank != 0); WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(real_t(4.5),2,2), real_t(1)), rank == 0 ? false : false); WALBERLA_CHECK_EQUAL(domain.isContainedInProcessSubdomain(Vec3(real_t(5.5),7,7), real_t(1)), rank == 0 ? false : false); diff --git a/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp index 51ef473f2..741d3ab69 100644 --- a/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ExplicitEulerInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp index 8a5b5e917..db83474b4 100644 --- a/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ExplicitEulerWithShapeInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp index 53edabb32..26c5152b0 100644 --- a/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/ForceLJInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} walberla::mesa_pd::Vec3& getForceRef(const size_t /*p_idx*/) {return force_;} diff --git a/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp index c204acc86..26d5ecd96 100644 --- a/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/HeatConductionInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::real_t& getTemperature(const size_t /*p_idx*/) const {return temperature_;} const walberla::real_t& getHeatFlux(const size_t /*p_idx*/) const {return heatFlux_;} diff --git a/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp index d60c39fe6..bcb55bdcc 100644 --- a/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/PFCDampingInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t /*p_idx*/) const {return linearVelocity_;} void setLinearVelocity(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { linearVelocity_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp index b73f71a3d..5b287377b 100644 --- a/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/SemiImplicitEulerInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp index 80837e900..2095004ed 100644 --- a/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/SpringDashpotInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} const walberla::mesa_pd::Vec3& getLinearVelocity(const size_t /*p_idx*/) const {return linearVelocity_;} diff --git a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp index d0cdb6099..e85086212 100644 --- a/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/TemperatureIntegrationInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::real_t& getTemperature(const size_t /*p_idx*/) const {return temperature_;} void setTemperature(const size_t /*p_idx*/, const walberla::real_t& v) { temperature_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp index 1f5910166..869b4bb89 100644 --- a/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/VelocityVerletInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} diff --git a/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp b/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp index 1f5910166..869b4bb89 100644 --- a/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp +++ b/tests/mesa_pd/kernel/interfaces/VelocityVerletWithShapeInterfaceCheck.cpp @@ -37,7 +37,7 @@ namespace mesa_pd { class Accessor : public data::IAccessor { public: - virtual ~Accessor() = default; + ~Accessor() override = default; const walberla::mesa_pd::Vec3& getPosition(const size_t /*p_idx*/) const {return position_;} void setPosition(const size_t /*p_idx*/, const walberla::mesa_pd::Vec3& v) { position_ = v;} diff --git a/tests/pe_coupling/momentum_exchange_method/TaylorCouetteFlowMEM.cpp b/tests/pe_coupling/momentum_exchange_method/TaylorCouetteFlowMEM.cpp index 67ce8c233..2fad6814a 100644 --- a/tests/pe_coupling/momentum_exchange_method/TaylorCouetteFlowMEM.cpp +++ b/tests/pe_coupling/momentum_exchange_method/TaylorCouetteFlowMEM.cpp @@ -247,7 +247,7 @@ int main( int argc, char **argv ) WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); } - bool vtkIO = (vtkIOFreq == 0 ) ? false : true; + bool vtkIO = vtkIOFreq != 0; /////////////////////////// // SIMULATION PROPERTIES // -- GitLab From ee330c626dd68627529ec7cb0fca949fa3eff345 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 9 Feb 2021 12:21:11 +0100 Subject: [PATCH 61/83] added benchmark as integration test --- apps/benchmarks/CMakeLists.txt | 1 - apps/benchmarks/CNT/CMakeLists.txt | 5 - src/mesa_pd/kernel/cnt/VBondContact.h | 21 ++++- tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/cnt/SphericalSegmentAccessor.h | 4 +- .../kernel/cnt/VBondContactEnergies.ref.txt | 4 + .../kernel/cnt/VBondContactIntegration.ipynb | 94 +++++++++++++++++++ .../cnt/VBondContactIntegration.test.cpp | 25 ++--- 8 files changed, 135 insertions(+), 22 deletions(-) delete mode 100644 apps/benchmarks/CNT/CMakeLists.txt rename apps/benchmarks/CNT/Accessor.h => tests/mesa_pd/kernel/cnt/SphericalSegmentAccessor.h (92%) create mode 100644 tests/mesa_pd/kernel/cnt/VBondContactEnergies.ref.txt create mode 100644 tests/mesa_pd/kernel/cnt/VBondContactIntegration.ipynb rename apps/benchmarks/CNT/VBondModel.cpp => tests/mesa_pd/kernel/cnt/VBondContactIntegration.test.cpp (92%) diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index 420dc32d3..d16b4255d 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory( AdaptiveMeshRefinementFluidParticleCoupling ) -add_subdirectory( CNT ) add_subdirectory( ComplexGeometry ) add_subdirectory( DEM ) add_subdirectory( MeshDistance ) diff --git a/apps/benchmarks/CNT/CMakeLists.txt b/apps/benchmarks/CNT/CMakeLists.txt deleted file mode 100644 index 5fc6f783f..000000000 --- a/apps/benchmarks/CNT/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -waLBerla_add_executable ( NAME VBondModel - FILES VBondModel.cpp - DEPENDS core mesa_pd ) -#waLBerla_execute_test( NAME MESA_PD_CNT_VBondModel -# COMMAND $<TARGET_FILE:VBondModel> ) diff --git a/src/mesa_pd/kernel/cnt/VBondContact.h b/src/mesa_pd/kernel/cnt/VBondContact.h index 2153daa69..6bc5edf98 100644 --- a/src/mesa_pd/kernel/cnt/VBondContact.h +++ b/src/mesa_pd/kernel/cnt/VBondContact.h @@ -55,6 +55,12 @@ namespace cnt { class VBondContact { public: + VBondContact( const Vector3<bool>& isPeriodic = Vector3<bool>{false, false, false}, + const Vector3<int64_t>& maxSegments = Vector3<real_t>{0, 0, 0} ) + : isPeriodic_(isPeriodic) + , maxSegments_(maxSegments) + {} + template<typename Accessor> void operator()(const size_t p_idx1, const size_t p_idx2, @@ -73,13 +79,24 @@ public: static constexpr real_t B3 = -2_r * E * J / a - G * Jp / (2_r * a); static constexpr real_t B4 = G * Jp / a; - Vector3<bool> isPeriodic_; - Vector3<int64_t> maxSegments_; + + /// Get tensile energy from last contact. + auto getLastTensileEnergy() const {return tensileEnergy;} + /// Get shear energy from last contact. + auto getLastShearEnergy() const {return shearEnergy;} + /// Get bending energy from last contact. + auto getLastBendingEnergy() const {return bendingEnergy;} + /// Get twisting energy from last contact. + auto getLastTwistingEnergy() const {return twistingEnergy;} +private: real_t tensileEnergy; real_t shearEnergy; real_t bendingEnergy; real_t twistingEnergy; + + Vector3<bool> isPeriodic_; + Vector3<int64_t> maxSegments_; }; diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 310062c6d..d84af9fb2 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -90,6 +90,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact ) waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_VBondContact FILES kernel/cnt/VBondContact.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_VBondContact ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_VBondContactIntegration FILES kernel/cnt/VBondContactIntegration.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_VBondContactIntegration ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSD FILES kernel/CoefficientOfRestitutionSD.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDEuler COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDVelocityVerlet COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> --useVV ) diff --git a/apps/benchmarks/CNT/Accessor.h b/tests/mesa_pd/kernel/cnt/SphericalSegmentAccessor.h similarity index 92% rename from apps/benchmarks/CNT/Accessor.h rename to tests/mesa_pd/kernel/cnt/SphericalSegmentAccessor.h index d23002562..22c09b564 100644 --- a/apps/benchmarks/CNT/Accessor.h +++ b/tests/mesa_pd/kernel/cnt/SphericalSegmentAccessor.h @@ -28,10 +28,10 @@ namespace walberla { namespace mesa_pd { -class Accessor : public data::ParticleAccessor +class SphericalSegmentAccessor : public data::ParticleAccessor { public: - Accessor(std::shared_ptr<data::ParticleStorage>& ps) + SphericalSegmentAccessor(std::shared_ptr<data::ParticleStorage>& ps) : ParticleAccessor(ps) {} diff --git a/tests/mesa_pd/kernel/cnt/VBondContactEnergies.ref.txt b/tests/mesa_pd/kernel/cnt/VBondContactEnergies.ref.txt new file mode 100644 index 000000000..7608c5ea9 --- /dev/null +++ b/tests/mesa_pd/kernel/cnt/VBondContactEnergies.ref.txt @@ -0,0 +1,4 @@ +0.000000000000000000e+00 9.769598930999999488e-25 1.257361055000000031e-14 3.899420607000000291e-15 2.000811218999999922e-12 4.690882740999999754e-11 3.101953598000000151e-10 1.079764155999999945e-09 2.624524298999999930e-09 5.413337421000000074e-09 1.084774037999999922e-08 2.202161062999999972e-08 4.378177583000000040e-08 8.112557732999999511e-08 1.362031657999999954e-07 2.072490092999999965e-07 2.924839492000000040e-07 3.965729058000000265e-07 5.325625850000000057e-07 7.156604478000000376e-07 9.545334436000000305e-07 1.248477076000000054e-06 1.591471921999999927e-06 1.978461101000000019e-06 2.412201610999999981e-06 2.908983651000000108e-06 3.493892384000000026e-06 4.183487506000000047e-06 4.973947920999999592e-06 5.849722148000000380e-06 6.801382250000000419e-06 7.833933107000000422e-06 8.966690885999999394e-06 1.023102611999999984e-05 1.165832549999999958e-05 1.325937714000000014e-05 1.501796961000000055e-05 1.691057721000000048e-05 1.893294801000000075e-05 2.111153134000000168e-05 2.349887435999999891e-05 2.615664121000000147e-05 2.912830002999999975e-05 3.242019864000000189e-05 3.601281649999999693e-05 3.989370787000000139e-05 4.408250137000000325e-05 4.863492345000000269e-05 5.363050996999999876e-05 5.914455918000000094e-05 6.521380048999999711e-05 7.182577398000000192e-05 7.894784417999999374e-05 8.657194118999999579e-05 9.474034216000000376e-05 1.035425176999999944e-04 1.130884250999999996e-04 1.234655437999999960e-04 1.347034647999999896e-04 1.467775908999999993e-04 1.596532001999999945e-04 1.733353551999999940e-04 1.878913344999999990e-04 2.034373955999999939e-04 2.200960170999999928e-04 2.379396507000000128e-04 2.569529171999999939e-04 2.770438951999999950e-04 2.981047208000000268e-04 3.200826908000000098e-04 3.430091486000000031e-04 3.669610926000000002e-04 3.919788862999999918e-04 4.179935286000000015e-04 4.448076550999999885e-04 4.721433329999999797e-04 4.997362688000000271e-04 5.274214652999999501e-04 5.551469528999999686e-04 5.828994754999999471e-04 6.105934510000000275e-04 6.379969888000000446e-04 6.647387717000000215e-04 6.903969353999999921e-04 7.146251129999999646e-04 7.372316414000000366e-04 7.581517388999999820e-04 7.773393340000000129e-04 7.946597574999999776e-04 8.098415648999999876e-04 8.225099688999999671e-04 8.323031783000000390e-04 8.390153918000000256e-04 8.426572231999999519e-04 8.433837805999999616e-04 8.413581837000000396e-04 8.366439647999999616e-04 8.291691587000000162e-04 8.187843143000000067e-04 8.054083557000000235e-04 7.891649440999999685e-04 7.703861584000000051e-04 7.494857218999999944e-04 7.268169406000000434e-04 7.025969469000000259e-04 6.769090151999999569e-04 6.497862570999999969e-04 6.213484284000000187e-04 5.918880394000000222e-04 5.618225952999999573e-04 5.315605759000000376e-04 5.013941135000000385e-04 4.714720982999999910e-04 4.418471189000000208e-04 4.125752137999999882e-04 3.838115558999999843e-04 3.558203543999999795e-04 3.288904724999999860e-04 3.032409837000000141e-04 2.789843069000000125e-04 2.561431809999999989e-04 2.347022120999999882e-04 2.146753759000000108e-04 1.961349607000000103e-04 1.791631984999999985e-04 1.637810812000000077e-04 1.499321497999999873e-04 1.375142358000000075e-04 1.264146304000000095e-04 1.165474269999999953e-04 1.078817780000000009e-04 1.004080292999999990e-04 9.405698425000000621e-05 8.867629388999999883e-05 8.409528164999999439e-05 8.019052618000000550e-05 7.689793735999999604e-05 7.420063447999999365e-05 7.209858209999999682e-05 7.054539821000000484e-05 6.941233475999999936e-05 6.854816966000000598e-05 6.788190945999999463e-05 6.746265518000000086e-05 6.742435539000000467e-05 6.792882366000000413e-05 6.911280103999999536e-05 7.106280527999999546e-05 7.386126210000000481e-05 7.768045076000000624e-05 8.282488939999999673e-05 8.968387272000000133e-05 9.866557706999999860e-05 1.101751333999999983e-04 1.246224312999999874e-04 1.424354752000000102e-04 1.640771495999999985e-04 1.900400481999999977e-04 2.207908629999999993e-04 2.567062459999999843e-04 2.980796680999999956e-04 3.451986834000000124e-04 3.984024905999999813e-04 4.580602211000000049e-04 5.244992345000000326e-04 5.979342737999999774e-04 6.784228293999999913e-04 7.658751436999999872e-04 8.601395017000000110e-04 9.611151113000000485e-04 1.068802304000000076e-03 1.183259439000000071e-03 1.304513818999999963e-03 1.432478119000000008e-03 1.566901386000000077e-03 1.707389487999999914e-03 1.853512819000000065e-03 2.004949989000000179e-03 2.161573521000000053e-03 2.323421534000000028e-03 2.490571904999999871e-03 2.662987130999999816e-03 2.840412905999999908e-03 3.022385029000000146e-03 3.208345773999999977e-03 3.397824131000000154e-03 3.590587542000000121e-03 3.786644539000000049e-03 3.986055001999999625e-03 4.188667612999999804e-03 4.393968871000000255e-03 4.601132616999999668e-03 4.809252398000000116e-03 5.017672239000000277e-03 5.226229318999999797e-03 5.435201659000000150e-03 5.644973555000000129e-03 5.855671629000000315e-03 6.066983778000000112e-03 6.278207814999999838e-03 6.488535436999999691e-03 6.697484469999999933e-03 6.905155137999999942e-03 7.112019814999999585e-03 7.318401837999999673e-03 7.524071957999999873e-03 7.728169687999999864e-03 7.929413899999999613e-03 8.126558282999999175e-03 8.318907130000000733e-03 8.506475640000000366e-03 8.689608087999999356e-03 8.868399936999999192e-03 9.042341763999999296e-03 9.210268918999999985e-03 9.370627918000000098e-03 9.522098059999999434e-03 9.664223426000000464e-03 9.797454865999999721e-03 9.922553097000000669e-03 1.003994249999999935e-02 1.014942559999999945e-02 1.025024497000000083e-02 1.034153013000000017e-02 1.042309114000000009e-02 1.049596581000000056e-02 1.056211724000000012e-02 1.062355786999999961e-02 1.068164414000000000e-02 1.073680678000000013e-02 1.078867998000000022e-02 1.083676226000000048e-02 1.088137529999999922e-02 1.092404083999999956e-02 1.096684222999999916e-02 1.101144853999999965e-02 1.105856929000000044e-02 1.110789606999999964e-02 1.115848357999999971e-02 1.120966122000000009e-02 1.126193665000000017e-02 1.131693991999999961e-02 1.137640707000000043e-02 1.144118782000000042e-02 1.151085137000000015e-02 1.158378019999999932e-02 1.165780565000000026e-02 1.173133908000000003e-02 1.180410112000000039e-02 1.187664239000000080e-02 1.194922755000000017e-02 1.202115758000000048e-02 1.209068639000000084e-02 1.215530664999999941e-02 1.221261438000000032e-02 1.226148720000000067e-02 1.230240005999999955e-02 1.233643390999999978e-02 1.236406902000000002e-02 1.238471908999999940e-02 1.239682075000000071e-02 1.239830167999999948e-02 1.238760952000000047e-02 1.236466165000000075e-02 1.233062359999999996e-02 1.228676870999999976e-02 1.223368277000000046e-02 1.217115801000000046e-02 1.209833601000000029e-02 1.201425635999999950e-02 1.191894391000000025e-02 1.181401506999999948e-02 1.170196878000000044e-02 1.158499904000000018e-02 1.146447159000000063e-02 1.134094681999999951e-02 1.121438741000000024e-02 1.108486562000000029e-02 1.095353758999999955e-02 1.082275411999999992e-02 1.069510960000000059e-02 1.057257600000000020e-02 1.045629944000000047e-02 1.034660192999999929e-02 1.024321331000000064e-02 1.014615722000000025e-02 1.005662126000000066e-02 9.976704293000000431e-03 9.908379862999999732e-03 9.852853618000000091e-03 9.810482602999999469e-03 9.780845563999999298e-03 9.763234384999999738e-03 9.757677556000000571e-03 9.765495532000000381e-03 9.788700317000000040e-03 9.829028404000000191e-03 9.887467607999999783e-03 9.964096013000000793e-03 1.005812730999999967e-02 1.016862276999999995e-02 1.029552536999999920e-02 1.043980951999999920e-02 1.060257203000000009e-02 1.078416719000000086e-02 1.098393832999999993e-02 1.120021409999999960e-02 1.143066476000000053e-02 1.167331096999999970e-02 1.192741718999999929e-02 1.219324616000000069e-02 1.247104618000000054e-02 1.276032289999999916e-02 1.305954806999999954e-02 1.336609579999999999e-02 1.367680658999999993e-02 1.398917602000000066e-02 1.430201648000000055e-02 1.461487914999999929e-02 1.492704513999999934e-02 1.523697599999999930e-02 1.554212664999999986e-02 1.583906532999999894e-02 1.612431426000000140e-02 1.639555138000000148e-02 1.665198710000000137e-02 1.689359329000000159e-02 1.712005676999999934e-02 1.733008886999999956e-02 1.752113310999999993e-02 1.768976662999999921e-02 1.783297475999999840e-02 1.794938402000000044e-02 1.803928897999999836e-02 1.810360151999999834e-02 1.814272402000000062e-02 1.815585927999999877e-02 1.814087203999999870e-02 1.809502045999999975e-02 1.801640255000000121e-02 1.790495707000000145e-02 1.776208275000000156e-02 1.758932824000000034e-02 1.738722163000000140e-02 1.715478230000000090e-02 1.688989051000000172e-02 1.659057280000000162e-02 1.625655717999999889e-02 1.588985876000000019e-02 1.549393919999999918e-02 1.507232015000000043e-02 1.462770042000000048e-02 1.416184898999999983e-02 1.367614416999999964e-02 1.317254150999999998e-02 1.265431285999999919e-02 1.212576974000000030e-02 1.159112269999999952e-02 1.105356524000000035e-02 1.051527447999999962e-02 9.977995902000000653e-03 9.443634378000000454e-03 8.914602941000000780e-03 8.393732972000000556e-03 7.883681687000000313e-03 7.386401348000000248e-03 6.903381672000000017e-03 6.436435528000000392e-03 5.988091241999999974e-03 5.561236193000000314e-03 5.158451686999999952e-03 4.781424777999999758e-03 4.430641622000000036e-03 4.105757944999999937e-03 3.806678989999999919e-03 3.534430675000000202e-03 3.290896903000000047e-03 3.077676196000000194e-03 2.894994097000000172e-03 2.741199906000000002e-03 2.613023865999999917e-03 2.506694246000000167e-03 2.419380144999999909e-03 2.349802287999999944e-03 2.297528666000000011e-03 2.261746045000000063e-03 2.240486695000000125e-03 2.230626851999999941e-03 2.228696117000000029e-03 2.232364377999999927e-03 2.241767958000000054e-03 2.259581146999999936e-03 2.289768263000000002e-03 2.336031652000000128e-03 2.400864114999999924e-03 2.485558073999999829e-03 2.591273702000000071e-03 2.720667758999999967e-03 2.878748034999999844e-03 3.072062817000000175e-03 3.306969062000000067e-03 3.588377315999999838e-03 3.919493427000000051e-03 4.302413633999999792e-03 4.739399045999999859e-03 5.234083926000000254e-03 5.791368725000000002e-03 6.415893377999999994e-03 7.110570699000000328e-03 7.876300435999999267e-03 8.712535723999999260e-03 9.618130162999999691e-03 1.059225001999999916e-02 1.163467510000000017e-02 1.274485958999999925e-02 1.392065854000000026e-02 1.515827135000000041e-02 1.645334082999999961e-02 1.780192783999999875e-02 1.920087721999999900e-02 2.064771435999999960e-02 2.213976700999999853e-02 2.367278429999999934e-02 2.524065719999999888e-02 2.683700945999999837e-02 2.845706488000000062e-02 3.009799229000000020e-02 3.175778475999999767e-02 3.343347700000000311e-02 3.511923727999999995e-02 3.680554146000000054e-02 3.848077602999999680e-02 4.013435226999999966e-02 4.175853368000000121e-02 4.334763560999999737e-02 4.489568946999999977e-02 4.639404914999999824e-02 4.783006241999999963e-02 4.918814719999999724e-02 5.045343716000000311e-02 5.161548377999999881e-02 5.266904822000000042e-02 5.361181120999999883e-02 5.444109255000000036e-02 5.515142979999999862e-02 5.573415335000000276e-02 5.617959186000000271e-02 5.648076586999999787e-02 5.663564170000000286e-02 5.664618837999999684e-02 5.651546579999999764e-02 5.624499641999999855e-02 5.583358832000000216e-02 5.527807033999999897e-02 5.457594631999999890e-02 5.372848905000000147e-02 5.274196005000000159e-02 5.162633611999999789e-02 5.039306847000000339e-02 4.905337064999999719e-02 4.761749207000000317e-02 4.609525795000000287e-02 4.449783776999999968e-02 4.283942745000000191e-02 4.113724154000000105e-02 3.940985358000000105e-02 3.767521521000000151e-02 3.594921043999999705e-02 3.424496932999999965e-02 3.257329569999999758e-02 3.094411949999999883e-02 2.936776412000000058e-02 2.785489245000000169e-02 2.641541680000000086e-02 2.505739411999999972e-02 2.378641927999999850e-02 2.260566114000000029e-02 2.151671485000000023e-02 2.052090223999999963e-02 1.961998363000000065e-02 1.881577829000000146e-02 1.810937452999999975e-02 1.750073615000000138e-02 1.698868438000000064e-02 1.657094543999999836e-02 1.624429527000000040e-02 1.600477163999999841e-02 1.584765619000000000e-02 1.576731689000000075e-02 1.575743360999999967e-02 1.581158225999999833e-02 1.592345733999999888e-02 1.608646433000000125e-02 1.629325535000000075e-02 1.653566748999999933e-02 1.680503951999999870e-02 1.709302124999999978e-02 1.739293466000000135e-02 1.770082757000000090e-02 1.801506891000000110e-02 +0.000000000000000000e+00 1.098045087999999967e-11 2.813681244999999975e-05 1.090188794999999945e-05 4.169281264000000080e-04 1.251764690000000107e-03 1.523427812999999945e-03 8.724563367999999680e-04 1.862166737999999876e-04 2.139689969000000043e-05 4.885859669000000056e-05 3.010388863000000256e-04 1.166116673999999936e-03 2.063944842999999949e-03 1.936229357999999902e-03 9.866180774999999941e-04 3.113903725999999923e-04 2.095340148000000011e-04 3.900488171000000099e-04 1.081855028999999940e-03 2.334334598000000188e-03 3.102649195999999943e-03 2.555769900000000143e-03 1.407288505999999958e-03 7.685405318000000435e-04 7.862179179999999887e-04 1.313863788000000071e-03 2.501508352999999834e-03 3.841578630000000091e-03 4.112757584999999702e-03 3.065362944999999988e-03 1.844464178000000025e-03 1.345228863999999979e-03 1.518534461000000096e-03 2.328443189000000031e-03 3.776796619999999924e-03 4.980570515999999809e-03 4.828829556999999703e-03 3.566178691999999980e-03 2.445262806999999941e-03 2.125824189999999791e-03 2.555812025000000088e-03 3.736235042999999905e-03 5.315531947999999757e-03 6.142351960999999951e-03 5.471705153000000141e-03 4.026527172999999973e-03 3.003180169000000017e-03 2.814801066000000192e-03 3.424525675000000217e-03 4.789582199000000200e-03 6.257026718999999897e-03 6.629351478999999728e-03 5.562887592000000103e-03 4.051922910000000169e-03 3.167537500999999950e-03 3.210545122999999921e-03 4.157046682999999618e-03 5.768405326999999881e-03 7.124078447000000217e-03 7.187952340999999995e-03 6.066060721000000010e-03 4.891911774999999594e-03 4.537224692000000129e-03 5.171990106999999580e-03 6.697878200000000060e-03 8.637042634999999788e-03 9.912537683999999780e-03 9.735341915999999596e-03 8.580728685000000439e-03 7.636438120000000121e-03 7.605032599000000060e-03 8.541060304000000145e-03 1.023322527999999919e-02 1.204787086999999958e-02 1.296710704999999922e-02 1.254143586000000012e-02 1.147406670999999954e-02 1.082485428999999978e-02 1.107738913000000033e-02 1.222173638999999971e-02 1.400682674999999960e-02 1.569740781999999849e-02 1.630586435999999834e-02 1.559380404999999997e-02 1.439193249000000029e-02 1.368881985000000058e-02 1.390419310999999915e-02 1.505856839000000065e-02 1.684837759000000143e-02 1.838536152000000076e-02 1.866772138999999928e-02 1.763167204000000085e-02 1.623979785000000120e-02 1.548684428999999932e-02 1.580225837999999980e-02 1.717242294000000113e-02 1.904884664999999949e-02 2.026330632000000048e-02 1.988493926999999883e-02 1.824582598000000153e-02 1.660877230000000135e-02 1.597302801000000105e-02 1.660384716000000080e-02 1.821871497000000090e-02 1.994014598000000069e-02 2.051084824000000070e-02 1.936525026000000121e-02 1.732504483000000053e-02 1.578945635000000153e-02 1.554882687000000083e-02 1.659365755000000164e-02 1.836679047999999898e-02 1.977005157999999971e-02 1.966549101999999841e-02 1.799557158000000129e-02 1.599993626000000002e-02 1.502037837999999938e-02 1.549817717000000032e-02 1.708752831999999985e-02 1.895811463999999905e-02 1.991527552999999839e-02 1.912430446999999895e-02 1.704456474000000041e-02 1.511228327999999954e-02 1.441806024999999977e-02 1.508497429000000070e-02 1.659711305000000081e-02 1.801958886999999870e-02 1.820636494000000064e-02 1.668101569999999936e-02 1.431009458999999914e-02 1.257222069999999921e-02 1.228618635999999958e-02 1.331381872999999952e-02 1.495475842000000034e-02 1.614320476000000171e-02 1.585241533000000119e-02 1.400626471000000067e-02 1.173601720000000057e-02 1.036107860999999943e-02 1.038674728999999970e-02 1.153037393999999972e-02 1.305986987000000085e-02 1.391537531000000029e-02 1.325078053000000068e-02 1.129482348999999962e-02 9.279844114999999741e-03 8.329654203999999756e-03 8.713958784999999846e-03 1.001731286000000047e-02 1.142824331999999984e-02 1.195428441000000001e-02 1.106497422000000085e-02 9.278476290999999182e-03 7.730237216000000050e-03 7.183857695000000348e-03 7.696862898000000376e-03 8.897470693000000472e-03 1.010542709000000067e-02 1.048124689000000040e-02 9.648590824999999163e-03 8.125785788000000273e-03 6.844495477999999744e-03 6.385196228000000057e-03 6.807871963000000116e-03 7.814717755000000557e-03 8.770060995999999151e-03 8.927271413999999725e-03 8.036764202000000121e-03 6.605048020999999998e-03 5.412051182999999890e-03 4.961157029999999774e-03 5.375675463999999779e-03 6.400032251000000241e-03 7.351659233000000342e-03 7.459640772000000405e-03 6.523098909000000015e-03 5.102333577000000425e-03 4.004419278999999700e-03 3.730894763000000211e-03 4.323699311999999913e-03 5.385101278000000401e-03 6.190949137000000164e-03 6.120221093000000404e-03 5.175369548999999951e-03 3.989793152999999981e-03 3.292571785000000112e-03 3.440746584000000004e-03 4.338893800000000189e-03 5.527947033000000371e-03 6.349665053999999781e-03 6.335613914000000173e-03 5.613985610000000320e-03 4.831529428000000230e-03 4.609486022000000224e-03 5.145515512999999930e-03 6.254976078000000321e-03 7.526838073999999809e-03 8.418941035000000392e-03 8.537631037000000672e-03 8.021649913000000742e-03 7.485492348000000185e-03 7.479211323999999939e-03 8.137342089000000611e-03 9.295454555000000688e-03 1.061315349999999991e-02 1.156819794000000026e-02 1.175118583999999917e-02 1.132383592000000064e-02 1.090947742999999991e-02 1.099061590000000033e-02 1.167474427000000058e-02 1.289243823999999990e-02 1.434386665000000026e-02 1.536176384000000061e-02 1.540473216999999929e-02 1.470838762000000084e-02 1.404344775000000017e-02 1.395747051000000016e-02 1.460560932999999985e-02 1.594009966999999917e-02 1.750513845999999984e-02 1.841935299999999942e-02 1.820005951999999899e-02 1.735958567000000022e-02 1.677895532000000037e-02 1.690258948000000067e-02 1.781730875000000006e-02 1.939444425000000014e-02 2.092484060999999854e-02 2.138203301999999986e-02 2.055932695999999893e-02 1.935148814999999856e-02 1.868018742000000093e-02 1.883046571000000086e-02 1.981195406000000117e-02 2.135862981000000160e-02 2.252370723999999949e-02 2.234093654999999914e-02 2.101662589999999872e-02 1.965624926000000133e-02 1.899716741000000153e-02 1.919034761999999922e-02 2.026346868000000051e-02 2.173851775999999930e-02 2.235602730000000107e-02 2.129760154999999974e-02 1.925890456000000153e-02 1.755590345000000024e-02 1.685837287999999989e-02 1.734000310999999836e-02 1.892921125999999857e-02 2.066988964000000123e-02 2.100959851999999878e-02 1.952545333999999855e-02 1.745251982000000160e-02 1.615768873000000133e-02 1.613806327999999998e-02 1.746475361999999878e-02 1.971777808000000146e-02 2.143443069999999978e-02 2.115688888999999948e-02 1.918617859999999925e-02 1.717451353999999847e-02 1.627954375000000009e-02 1.676609708000000032e-02 1.859569298999999912e-02 2.099558521000000066e-02 2.224083687999999989e-02 2.131215965999999976e-02 1.918918324000000106e-02 1.757820217000000129e-02 1.727032460999999852e-02 1.836830965000000107e-02 2.067597838000000132e-02 2.302525542000000147e-02 2.367539620000000053e-02 2.226253708999999942e-02 2.023965366999999974e-02 1.906296684000000075e-02 1.918643327000000079e-02 2.069907250999999948e-02 2.324047917999999893e-02 2.531067571000000099e-02 2.536759566999999965e-02 2.369515466999999945e-02 2.195629291999999858e-02 2.129226925999999978e-02 2.197881276000000078e-02 2.403205137999999894e-02 2.670580893999999900e-02 2.825365897000000140e-02 2.761692653999999955e-02 2.570521064000000008e-02 2.413747488999999982e-02 2.369226563000000063e-02 2.457055601999999853e-02 2.670524756999999999e-02 2.900604555000000154e-02 2.971543993000000036e-02 2.834332566000000164e-02 2.620686515999999869e-02 2.478243360000000062e-02 2.467662685000000106e-02 2.606119738999999880e-02 2.853287011000000054e-02 3.054048034999999953e-02 3.048783757999999969e-02 2.854593635999999948e-02 2.634156325000000173e-02 2.518380886000000027e-02 2.553799740000000165e-02 2.742574792000000011e-02 3.002675435000000045e-02 3.156011447999999830e-02 3.086550331000000036e-02 2.871578835000000024e-02 2.682638661999999993e-02 2.627104593000000043e-02 2.735563557999999909e-02 2.985267158000000018e-02 3.255671654000000248e-02 3.368562483999999746e-02 3.260004108999999678e-02 3.046505342999999977e-02 2.888656527000000099e-02 2.872135418999999940e-02 3.020524009999999912e-02 3.294390619999999770e-02 3.550070158000000198e-02 3.620675079999999962e-02 3.483208175000000045e-02 3.274427012000000192e-02 3.145377608000000241e-02 3.174348653999999742e-02 3.377649058999999954e-02 3.684776314999999719e-02 3.921267960000000136e-02 3.934740502999999751e-02 3.748318199000000295e-02 3.525845958999999918e-02 3.416759400000000252e-02 3.489814589999999661e-02 3.739553431999999983e-02 4.055388218000000045e-02 4.241686413000000239e-02 4.178222420000000242e-02 3.943135575000000087e-02 3.725031213999999841e-02 3.663120758999999921e-02 3.802921089999999893e-02 4.103495939000000037e-02 4.414328002000000167e-02 4.537400546999999923e-02 4.403746134000000034e-02 4.144459293999999683e-02 3.953507633000000188e-02 3.945078286999999934e-02 4.141465191999999657e-02 4.474581605999999878e-02 4.765077491999999970e-02 4.823564068999999788e-02 4.634610144000000237e-02 4.372950873999999905e-02 4.230135992999999733e-02 4.296592879000000337e-02 4.569302948000000114e-02 4.943655193000000281e-02 5.214975843999999916e-02 5.224664417000000199e-02 5.021736479999999725e-02 4.805112389999999928e-02 4.738447994000000163e-02 4.883466990000000230e-02 5.220264517999999992e-02 5.616499422000000019e-02 5.853909537000000218e-02 5.814050307000000195e-02 5.604309186999999887e-02 5.437324896000000213e-02 5.453920028999999919e-02 5.693871295999999860e-02 6.106411720999999765e-02 6.517070929000000346e-02 6.708689303999999798e-02 6.624436858000000428e-02 6.419995925999999464e-02 6.294107760000000606e-02 6.357073134000000569e-02 6.636902606000000260e-02 7.059402475999999871e-02 7.416614434000000367e-02 7.506358058999999805e-02 7.336223947999999384e-02 7.103757296000000332e-02 7.001715288000000259e-02 7.122601517000000382e-02 7.466185828000000690e-02 7.903714705000000618e-02 8.197763847000000270e-02 8.195389224000000639e-02 7.978274693999999612e-02 7.759072546999999653e-02 7.701304049000000373e-02 7.877744014000000183e-02 8.265841438000000319e-02 8.695718198999999315e-02 8.922108609999999940e-02 8.847277197000000259e-02 8.610597665999999983e-02 8.434468004999999546e-02 8.469502516999999342e-02 8.768319772999999540e-02 9.256396228999999587e-02 9.707931071000000522e-02 9.890680390000000655e-02 9.780079123000000318e-02 9.563030992000000341e-02 9.456857476999999679e-02 9.595472397000000264e-02 1.000612302999999981e-01 1.055922863999999989e-01 1.098871111999999983e-01 1.109595693999999994e-01 1.093151983999999938e-01 1.072503603999999944e-01 1.069366499999999942e-01 1.094850529000000044e-01 1.146157857999999946e-01 1.203232783999999972e-01 1.238128750999999972e-01 1.237864961000000041e-01 1.215057940000000003e-01 1.194530783000000013e-01 1.196059594000000031e-01 1.227585964999999973e-01 1.281164261999999943e-01 1.332265281999999995e-01 1.354948709000000084e-01 1.343891641000000137e-01 1.317553599000000075e-01 1.301257403999999951e-01 1.312192595999999989e-01 1.353715399000000041e-01 1.411820397999999921e-01 1.459246818000000112e-01 1.474503628999999927e-01 1.459470861999999924e-01 1.435610048000000027e-01 1.426689959999999924e-01 1.446930674999999944e-01 1.495596228999999944e-01 1.554236328999999972e-01 1.595303432000000077e-01 1.602909436999999937e-01 1.585256815999999958e-01 1.565866635000000007e-01 1.566915185999999960e-01 1.599191171000000078e-01 1.656968162000000133e-01 1.717846372000000066e-01 1.755503327000000058e-01 1.759471824000000129e-01 1.742015671999999904e-01 1.726916896000000035e-01 1.734601668999999902e-01 1.772769128999999999e-01 1.831133191000000049e-01 1.884492271000000052e-01 1.909162681999999889e-01 1.900980771000000125e-01 1.877147532000000008e-01 1.862775906999999953e-01 1.876377506999999945e-01 1.920841523000000051e-01 1.980314081000000004e-01 2.027781117999999938e-01 2.043181491000000127e-01 2.027646596999999884e-01 2.001122127999999945e-01 1.988157517999999957e-01 2.003950733000000040e-01 2.045964194000000069e-01 2.093754133000000073e-01 2.120625872999999939e-01 2.112029098000000049e-01 2.075790237000000038e-01 2.035907939999999916e-01 2.016904861000000104e-01 2.030011084999999993e-01 2.066936591999999906e-01 2.103853867999999905e-01 2.115652101000000118e-01 2.092677652999999915e-01 2.047355029000000048e-01 2.005599788999999911e-01 1.990186617999999963e-01 2.007246850999999943e-01 2.042720507999999935e-01 +0.000000000000000000e+00 0.000000000000000000e+00 1.830075147000000035e-13 2.271339206999999938e-07 3.697562520999999752e-07 1.343033221999999912e-06 3.547050058999999842e-05 1.861336611999999996e-04 5.159842077000000330e-04 9.728372257999999507e-04 1.435700584000000092e-03 1.870900562999999912e-03 2.396687342000000144e-03 3.197327172999999984e-03 4.412280133000000097e-03 6.070971449999999596e-03 8.058617097999999299e-03 1.015841473000000071e-02 1.220399383000000081e-02 1.422303400000000072e-02 1.643257395999999856e-02 1.910539299000000094e-02 2.240138904000000056e-02 2.622779730000000115e-02 3.023218304999999995e-02 3.402154396999999830e-02 3.747324945000000268e-02 4.084126551000000216e-02 4.456187916999999887e-02 4.895723044999999995e-02 5.404702808999999747e-02 5.953321802000000051e-02 6.496362763000000651e-02 7.001722886000000257e-02 7.472294336000000203e-02 7.944106770999999345e-02 8.464057714000000621e-02 9.062771913000000623e-02 9.734821880999999788e-02 1.043732026000000063e-01 1.111471012999999952e-01 1.173695054000000043e-01 1.232033577999999963e-01 1.291453727000000107e-01 1.356938205999999869e-01 1.430453906999999969e-01 1.509661871999999905e-01 1.589076221000000066e-01 1.663357332000000022e-01 1.730712087000000066e-01 1.793997622999999875e-01 1.858969983000000048e-01 1.930966023000000031e-01 2.011757667000000083e-01 2.098318768000000112e-01 2.184723393000000125e-01 2.266286379999999934e-01 2.342919839000000004e-01 2.419289115000000101e-01 2.502013578000000238e-01 2.595871182000000221e-01 2.701049006999999835e-01 2.813024116000000241e-01 2.925459409000000233e-01 3.034388336000000130e-01 3.140824622000000232e-01 3.250147246999999795e-01 3.368794079999999913e-01 3.500209514000000022e-01 3.642462313000000007e-01 3.789283167999999979e-01 3.934037415000000149e-01 4.073827195999999984e-01 4.210930086999999933e-01 4.350988097999999860e-01 4.499384949999999939e-01 4.657907589999999987e-01 4.823531102999999987e-01 4.990113815000000175e-01 5.152011181000000217e-01 5.307346866000000052e-01 5.459025118000000454e-01 5.612995884999999463e-01 5.774713811999999669e-01 5.945742500999999791e-01 6.122601326000000066e-01 6.298691131000000443e-01 6.468125425999999845e-01 6.629148549000000168e-01 6.785207346999999611e-01 6.943025838999999921e-01 7.108565231000000262e-01 7.283093545000000057e-01 7.461889310000000552e-01 7.636719467999999456e-01 7.800826392999999914e-01 7.953346191000000287e-01 8.100150072999999784e-01 8.250231137000000325e-01 8.409777458999999622e-01 8.577876706000000517e-01 8.746874662000000411e-01 8.907288009999999590e-01 9.054064676999999950e-01 9.190029790000000531e-01 9.324181443000000291e-01 9.465903275000000505e-01 9.618856796000000431e-01 9.778515883999999714e-01 9.934965191000000306e-01 1.007923329999999895e+00 1.020909692999999896e+00 1.033049448000000092e+00 1.045351324000000082e+00 1.058556178999999986e+00 1.072623311000000079e+00 1.086724296000000090e+00 1.099754072000000082e+00 1.111030549999999950e+00 1.120719336000000066e+00 1.129698298999999961e+00 1.138960167000000023e+00 1.148956714000000101e+00 1.159302464999999893e+00 1.169009616000000085e+00 1.177100862999999942e+00 1.183219220000000016e+00 1.187849098999999908e+00 1.192006353000000018e+00 1.196596929999999892e+00 1.201847611000000038e+00 1.207160540000000060e+00 1.211490606999999997e+00 1.214023281000000010e+00 1.214716421000000102e+00 1.214338903000000025e+00 1.213984817000000049e+00 1.214399095999999956e+00 1.215546164000000040e+00 1.216667713000000095e+00 1.216775984000000088e+00 1.215278673000000031e+00 1.212353497000000058e+00 1.208847467000000009e+00 1.205775452999999997e+00 1.203726784000000105e+00 1.202530250999999994e+00 1.201386725000000100e+00 1.199409592000000080e+00 1.196232783999999993e+00 1.192271196999999949e+00 1.188463543999999983e+00 1.185701141000000014e+00 1.184332045999999972e+00 1.184029948999999915e+00 1.184068300999999934e+00 1.183805269000000049e+00 1.183076609000000001e+00 1.182276306999999971e+00 1.182116836999999920e+00 1.183233208999999952e+00 1.185841383999999943e+00 1.189626461000000024e+00 1.193937156000000055e+00 1.198183411999999892e+00 1.202181026999999958e+00 1.206227103000000023e+00 1.210893122999999960e+00 1.216687564000000110e+00 1.223771398000000010e+00 1.231865959000000066e+00 1.240406510999999989e+00 1.248862542999999992e+00 1.257043354999999973e+00 1.265220068000000087e+00 1.273992827999999911e+00 1.283951947000000038e+00 1.295312900000000100e+00 1.307775053000000076e+00 1.320730436999999924e+00 1.333680452999999932e+00 1.346564188000000106e+00 1.359797436000000026e+00 1.374026305999999975e+00 1.389749112000000064e+00 1.407027940000000088e+00 1.425474440999999981e+00 1.444519727999999947e+00 1.463779176999999931e+00 1.483280350000000025e+00 1.503437751999999961e+00 1.524799581999999987e+00 1.547708266000000110e+00 1.572090854000000038e+00 1.597527949999999919e+00 1.623536333999999970e+00 1.649851680999999903e+00 1.676554635000000015e+00 1.704013996000000031e+00 1.732683954000000082e+00 1.762843195000000085e+00 1.794429502000000065e+00 1.827083632999999985e+00 1.860360302999999993e+00 1.893965182000000080e+00 1.927901147999999898e+00 1.962454695999999998e+00 1.998009415000000066e+00 2.034789681999999988e+00 2.072709299000000005e+00 2.111404858000000218e+00 2.150396241000000153e+00 2.189299135999999812e+00 2.228027543000000055e+00 2.266864087000000083e+00 2.306289580000000061e+00 2.346651138999999997e+00 2.387901997999999804e+00 2.429583244999999891e+00 2.471055922000000127e+00 2.511871165000000072e+00 2.552066953999999832e+00 2.592163935999999946e+00 2.632830191000000042e+00 2.674455639000000051e+00 2.716921876999999874e+00 2.759679252000000194e+00 2.802083474999999879e+00 2.843833646000000215e+00 2.885235269999999907e+00 2.927053261999999823e+00 2.970029026000000183e+00 3.014416944999999792e+00 3.059846233000000026e+00 3.105563990999999913e+00 3.150916046999999942e+00 3.195791527999999992e+00 3.240724125999999927e+00 3.286555727000000093e+00 3.333910148999999823e+00 3.382833913999999886e+00 3.432782293999999901e+00 3.482938331000000165e+00 3.532728903999999837e+00 3.582245680999999848e+00 3.632244673999999840e+00 3.683684056999999790e+00 3.737122786000000030e+00 3.792365917000000142e+00 3.848551483000000051e+00 3.904657766999999780e+00 3.960175603999999794e+00 4.015494054000000368e+00 4.071677407000000137e+00 4.129774069999999853e+00 4.190137359000000394e+00 4.252177148000000351e+00 4.314690565000000255e+00 4.376617734999999954e+00 4.437761942999999931e+00 4.498940335000000346e+00 4.561428165999999784e+00 4.626110813999999571e+00 4.692917820999999989e+00 4.760853158999999835e+00 4.828594076999999984e+00 4.895330549999999725e+00 4.961307502000000369e+00 5.027668471000000139e+00 5.095710389999999812e+00 5.166074545999999934e+00 5.238368987000000310e+00 5.311421557000000071e+00 5.384036981000000388e+00 5.455810271999999905e+00 5.527427995000000038e+00 5.600231939000000381e+00 5.675382624000000042e+00 5.753187131999999870e+00 5.832953288999999764e+00 5.913426220999999927e+00 5.993583335000000289e+00 6.073308546999999891e+00 6.153476468000000033e+00 6.235389600999999615e+00 6.319963858999999573e+00 6.407160998000000163e+00 6.495986750000000143e+00 6.585090135999999816e+00 6.673630621000000041e+00 6.761821325999999743e+00 6.850756595000000004e+00 6.941680955999999902e+00 7.035212107999999631e+00 7.130965585000000218e+00 7.227772908000000385e+00 7.324388188000000355e+00 7.420263665000000231e+00 7.515875621000000173e+00 7.612391052000000435e+00 7.710918466999999943e+00 7.811798213000000324e+00 7.914334108000000256e+00 8.017163276999999866e+00 8.119092557000000099e+00 8.219856525000000858e+00 8.320262175999999954e+00 8.421637097999999710e+00 8.524963797999999926e+00 8.630229078999999359e+00 8.736380995999999399e+00 8.841956630000000317e+00 8.946005252000000851e+00 9.048686411000000263e+00 9.151145770999999485e+00 9.254777368999999254e+00 9.360344884999999948e+00 9.467487674999999214e+00 9.574930272999999659e+00 9.681297825999999773e+00 9.786011452000000332e+00 9.889662578999999454e+00 9.993643130000000596e+00 1.009929898999999942e+01 1.020712666000000013e+01 1.031648494999999954e+01 1.042600421999999938e+01 1.053444872999999937e+01 1.064148536999999983e+01 1.074788516999999999e+01 1.085505696999999969e+01 1.096419608999999973e+01 1.107553779000000027e+01 1.118817310999999926e+01 1.130057719999999932e+01 1.141154275999999967e+01 1.152093007000000036e+01 1.162975926999999920e+01 1.173958108000000067e+01 1.185149975000000033e+01 1.196545049000000027e+01 1.208020304999999972e+01 1.219411028000000030e+01 1.230613461000000086e+01 1.241650581000000031e+01 1.252659163999999947e+01 1.263804312000000074e+01 1.275173449999999953e+01 1.286717617000000047e+01 1.298279628000000052e+01 1.309692313999999946e+01 1.320884187000000054e+01 1.331924794999999939e+01 1.342980297000000078e+01 1.354207414000000043e+01 1.365653810999999962e+01 1.377227689000000055e+01 1.388753980999999982e+01 1.400081626000000057e+01 1.411177129999999913e+01 1.422146955999999918e+01 1.433172483999999969e+01 1.444396159999999973e+01 1.455830693000000053e+01 1.467349676000000080e+01 1.478766755999999916e+01 1.489954773999999915e+01 1.500929262000000008e+01 1.511841079999999948e+01 1.522882665999999929e+01 1.534170173000000048e+01 1.545676199999999945e+01 1.557251019999999997e+01 1.568716803999999954e+01 1.579979194000000042e+01 1.591089140999999962e+01 1.602214401999999893e+01 1.613536158999999870e+01 1.625135442999999924e+01 1.636940584999999970e+01 1.648769472000000036e+01 1.660442869999999971e+01 1.671898346000000046e+01 1.683229461000000171e+01 1.694624186000000066e+01 1.706245821999999990e+01 1.718133502999999962e+01 1.730179654000000156e+01 1.742194635999999974e+01 1.754021910000000162e+01 1.765636148000000105e+01 1.777161621999999852e+01 1.788796247999999878e+01 1.800687758000000116e+01 1.812838810999999950e+01 1.825101386000000048e+01 1.837268557999999885e+01 1.849208353999999943e+01 1.860950370000000120e+01 1.872666056999999995e+01 1.884559061999999940e+01 1.896739717000000169e+01 1.909159451000000018e+01 1.921641089999999963e+01 1.933987653000000151e+01 1.946105701999999837e+01 1.958065898999999987e+01 1.970061108000000161e+01 1.982287769999999938e+01 1.994822952000000171e+01 2.007572646999999932e+01 2.020327844999999911e+01 2.032898373000000092e+01 2.045237986000000063e+01 2.057476314999999900e+01 2.069838422999999850e+01 2.082506666000000095e+01 2.095509782999999970e+01 2.108704662999999968e+01 2.121864303999999990e+01 2.134821681000000027e+01 2.147579053999999843e+01 2.160310907999999941e+01 2.173257240999999951e+01 2.186572716999999955e+01 2.200224989000000164e+01 2.214009639000000007e+01 2.227678248999999866e+01 2.241098011000000056e+01 2.254335946000000135e+01 2.267613559999999850e+01 2.281165093999999982e+01 2.295089424000000022e+01 2.309285420999999872e+01 2.323511599000000061e+01 2.337535859999999843e+01 2.351281071000000011e+01 2.364872644000000079e+01 2.378558556000000124e+01 2.392552902999999986e+01 2.406899675000000016e+01 2.421442470999999941e+01 2.435922551999999897e+01 2.450143733000000168e+01 2.464095942999999878e+01 2.477958831000000117e+01 2.491987882999999826e+01 2.506356467000000166e+01 2.521049023999999861e+01 2.535870163999999960e+01 2.550566111999999919e+01 2.564983175000000060e+01 2.579162244999999842e+01 2.593310598000000056e+01 2.607670647000000130e+01 2.622366909000000135e+01 2.637325407000000155e+01 2.652317516000000097e+01 2.667101969000000139e+01 2.681573470000000015e+01 2.695823877000000124e+01 2.710081922000000176e+01 2.724571969000000138e+01 2.739376336000000123e+01 2.754383380000000159e+01 2.769355437999999836e+01 2.784076682999999974e+01 2.798487693999999948e+01 2.812721846999999897e+01 2.827021650000000008e+01 2.841586320000000043e+01 2.856443838999999940e+01 2.871429098000000124e+01 2.886284844000000049e+01 2.900820939999999837e+01 2.915029441000000077e+01 2.929085467999999892e+01 2.943236953999999983e+01 2.957650720999999905e+01 2.972307729999999992e+01 2.987013968000000119e+01 3.001522699999999944e+01 3.015690601000000015e+01 3.029568373000000037e+01 3.043370159999999913e+01 3.057341038999999938e+01 3.071603338999999977e+01 3.086078410000000005e+01 3.100536100000000062e+01 3.114740726999999865e+01 3.128598743999999954e+01 3.142216396999999972e+01 3.155835384999999960e+01 3.169686417000000134e+01 3.183848015999999959e+01 3.198198410999999908e+01 3.212493551000000025e+01 3.226522861000000120e+01 3.240243960000000101e+01 3.253812407000000206e+01 +0.000000000000000000e+00 0.000000000000000000e+00 1.820388512000000118e-07 1.949316547999999890e-09 1.835659695000000072e-06 1.153029472999999969e-05 3.576673243999999751e-05 7.910041913999999526e-05 1.420068822000000047e-04 2.207150739999999924e-04 3.087316432999999893e-04 3.992026884999999906e-04 4.869914638999999976e-04 5.696536955999999523e-04 6.471460942000000416e-04 7.207296093000000251e-04 7.918093385000000376e-04 8.612963849999999812e-04 9.296413845999999988e-04 9.972634849999999825e-04 1.064922221000000032e-03 1.133713457000000077e-03 1.204683884999999946e-03 1.278331994000000103e-03 1.354331284000000017e-03 1.431655401999999905e-03 1.509027687000000098e-03 1.585430894999999979e-03 1.660405850000000070e-03 1.734024779999999944e-03 1.806630231999999982e-03 1.878550367999999929e-03 1.949972113000000102e-03 2.021012960000000049e-03 2.091885869999999918e-03 2.162997547999999815e-03 2.234885766999999794e-03 2.308031638999999934e-03 2.382684312999999981e-03 2.458841100999999835e-03 2.536436459999999882e-03 2.615671346999999883e-03 2.697339018999999911e-03 2.783015259000000061e-03 2.875060340999999967e-03 2.976464827000000011e-03 3.090604424999999870e-03 3.220938299000000119e-03 3.370629492000000189e-03 3.542045707999999949e-03 3.736150864000000165e-03 3.951905979999999902e-03 4.185898409000000063e-03 4.432437447999999953e-03 4.684254510000000239e-03 4.933750593999999996e-03 5.174518488000000131e-03 5.402723031000000210e-03 5.617914629000000416e-03 5.822990658000000083e-03 6.023263596999999837e-03 6.224867196999999894e-03 6.432948231000000343e-03 6.650182287999999858e-03 6.876080433999999693e-03 7.107325145000000129e-03 7.339044014999999803e-03 7.566598271999999681e-03 7.787251490999999581e-03 8.001092405000000130e-03 8.210842822999999194e-03 8.420612812999999849e-03 8.634104365000000794e-03 8.853017304000000004e-03 9.076344709999999844e-03 9.300864213000000283e-03 9.522593302000000731e-03 9.738528259000000034e-03 9.947847481999999922e-03 1.015201005999999927e-02 1.035370864000000057e-02 1.055518746999999959e-02 1.075673828000000068e-02 1.095608535999999938e-02 1.114891649999999977e-02 1.133024057000000043e-02 1.149584839999999962e-02 1.164312944000000030e-02 1.177085838000000058e-02 1.187812323000000080e-02 1.196302443000000007e-02 1.202189554999999986e-02 1.204952289999999988e-02 1.204032353000000083e-02 1.198995683000000055e-02 1.189664368999999999e-02 1.176164455000000032e-02 1.158879103000000008e-02 1.138342692000000010e-02 1.115134469999999947e-02 1.089819489000000072e-02 1.062947971999999956e-02 1.035084556000000038e-02 1.006819685000000068e-02 9.787280457999999669e-03 9.512760048000000121e-03 9.247194327000000241e-03 8.990509614000000843e-03 8.740393823000000562e-03 8.493603770000000136e-03 8.247698447999999433e-03 8.002448080000000227e-03 7.760272414000000431e-03 7.525487340999999913e-03 7.302672425999999668e-03 7.094847880999999995e-03 6.902193378999999830e-03 6.721756726000000307e-03 6.548155515999999621e-03 6.374898922000000155e-03 6.195813028999999986e-03 6.006158600999999923e-03 5.803268454000000236e-03 5.586739892999999756e-03 5.358293921999999869e-03 5.121369903999999605e-03 4.880463528000000308e-03 4.640240200000000405e-03 4.404584964999999630e-03 4.175896170000000310e-03 3.954956033000000225e-03 3.741531232000000137e-03 3.535515882999999866e-03 3.338100145999999945e-03 3.152337362000000136e-03 2.982701635999999989e-03 2.833705075999999861e-03 2.708144931000000186e-03 2.605800002000000122e-03 2.523233280999999904e-03 2.454842134999999943e-03 2.394685441000000102e-03 2.338231226000000041e-03 2.283218397000000201e-03 2.229291164000000210e-03 2.176700191999999829e-03 2.124836293999999865e-03 2.071426117999999872e-03 2.012851521000000050e-03 1.945458292000000087e-03 1.867209893999999997e-03 1.778872166999999902e-03 1.684150842000000032e-03 1.588701789999999968e-03 1.498432656000000043e-03 1.417779775000000027e-03 1.348582348999999986e-03 1.289861816999999990e-03 1.238429316999999910e-03 1.189968600999999999e-03 1.140168454999999914e-03 1.085587204000000106e-03 1.024125495000000052e-03 9.551542765000000301e-04 8.794278554999999508e-04 7.989017024999999850e-04 7.165082577000000431e-04 6.358714384999999665e-04 5.609016402000000434e-04 4.952284829000000530e-04 4.414991636000000115e-04 4.006753678999999831e-04 3.715576743000000124e-04 3.507933891999999877e-04 3.335317473000000139e-04 3.146745652999999830e-04 2.903969536999999974e-04 2.594071743999999940e-04 2.234081492999999885e-04 1.864739303000000005e-04 1.534941247000000050e-04 1.282796421999999887e-04 1.121385784999999951e-04 1.035797203000000033e-04 9.931745666000000065e-05 9.615000697999999879e-05 9.285892839999999589e-05 9.125522881000000606e-05 9.589961765000000449e-05 1.126530642000000054e-04 1.467489311999999881e-04 2.012511027000000086e-04 2.765017350999999829e-04 3.706278019000000166e-04 4.806643355999999970e-04 6.036280572999999650e-04 7.370252030000000410e-04 8.786765931999999729e-04 1.026141401000000078e-03 1.176198896999999929e-03 1.324738481000000030e-03 1.467122376999999969e-03 1.598821624999999941e-03 1.716039621000000053e-03 1.816145390000000089e-03 1.897923297000000042e-03 1.961749048999999849e-03 2.009742666000000066e-03 2.045784332000000118e-03 2.075162938999999904e-03 2.103698297999999876e-03 2.136447911999999911e-03 2.176433569000000082e-03 2.223981881999999820e-03 2.277113009999999840e-03 2.332960945999999931e-03 2.389682080999999854e-03 2.447997759999999932e-03 2.511620076000000128e-03 2.586308548999999811e-03 2.677956598000000212e-03 2.790572791000000153e-03 2.925055899000000067e-03 3.079248269999999930e-03 3.249114373999999802e-03 3.430372028999999993e-03 3.619770022999999927e-03 3.815502806999999941e-03 4.016786692000000325e-03 4.223077375999999793e-03 4.433534486999999615e-03 4.647086754999999944e-03 4.862995103000000187e-03 5.081437708999999615e-03 5.303582145999999678e-03 5.530905586999999846e-03 5.764003636000000243e-03 6.001508826000000185e-03 6.239788413999999665e-03 6.473757584999999953e-03 6.698590735000000025e-03 6.911628349999999858e-03 7.113618173000000114e-03 7.308687989000000294e-03 7.503002249000000241e-03 7.702638161999999719e-03 7.911550814999999612e-03 8.130431203999999648e-03 8.356840872999999476e-03 8.586441926999999544e-03 8.814695650999999563e-03 9.038269204999999432e-03 9.255604173000000351e-03 9.466538740000000549e-03 9.671320078999999861e-03 9.869593944000000854e-03 1.005991795000000036e-02 1.024005453000000065e-02 1.040790538000000050e-02 1.056263298999999926e-02 1.070541067999999929e-02 1.083938760000000001e-02 1.096877582999999934e-02 1.109732515999999926e-02 1.122670262000000085e-02 1.135534506000000082e-02 1.147819544000000004e-02 1.158743505000000076e-02 1.167399843000000055e-02 1.172941788999999971e-02 1.174746320000000059e-02 1.172513755000000046e-02 1.166281767000000059e-02 1.156360002999999928e-02 1.143214111999999935e-02 1.127339190999999963e-02 1.109160051000000063e-02 1.088982099999999918e-02 1.066997631000000078e-02 1.043334731000000043e-02 1.018124936000000015e-02 9.915633615999999359e-03 9.639407798000000291e-03 9.356379386999999492e-03 9.070845182999999826e-03 8.786948751999999752e-03 8.507983792999999212e-03 8.235832803000000049e-03 7.970699568000000693e-03 7.711225640000000416e-03 7.454984807000000248e-03 7.199244425000000079e-03 6.941798911999999717e-03 6.681652526999999793e-03 6.419375526999999797e-03 6.157066919000000332e-03 5.897983267999999668e-03 5.645980832000000241e-03 5.404930740000000143e-03 5.178207488999999990e-03 4.968264806999999825e-03 4.776262952000000402e-03 4.601738406999999857e-03 4.442395624000000133e-03 4.294181803000000040e-03 4.151796299000000239e-03 4.009646989000000342e-03 3.863041380000000000e-03 3.709211928000000214e-03 3.547757625000000012e-03 3.380295963999999792e-03 3.209485711999999959e-03 3.037914019999999986e-03 2.867438648999999940e-03 2.699344291999999923e-03 2.535203121000000146e-03 2.377871091999999784e-03 2.231877397999999877e-03 2.102715072999999935e-03 1.995124498000000208e-03 1.911080611000000058e-03 1.848496493000000018e-03 1.801432949000000058e-03 1.761924603999999971e-03 1.722726310000000007e-03 1.679771926000000028e-03 1.633210188000000073e-03 1.586530949999999949e-03 1.544203826000000021e-03 1.508959192999999917e-03 1.479988882999999948e-03 1.452865952999999894e-03 1.421139404999999982e-03 1.378787645000000050e-03 1.322391497999999979e-03 1.252136445000000004e-03 1.171393962000000016e-03 1.085298931999999911e-03 9.990963830999999556e-04 9.169454146999999906e-04 8.414649593999999752e-04 7.738635806000000034e-04 7.142696037000000530e-04 6.619547717999999664e-04 6.154109309000000338e-04 5.724746999000000520e-04 5.307254516000000288e-04 4.881910606000000228e-04 4.441265271000000231e-04 3.994804029999999792e-04 3.567500820000000226e-04 3.192105520999999964e-04 2.898156044999999860e-04 2.702295482000000200e-04 2.603625255999999773e-04 2.585133214000000213e-04 2.619345707000000239e-04 2.674901391000000209e-04 2.721363636999999920e-04 2.731605601999999885e-04 2.683050983999999946e-04 2.559644066999999757e-04 2.355363272000000072e-04 2.078241537000000009e-04 1.752604007000000080e-04 1.417542710999999912e-04 1.121394326000000030e-04 9.140599956999999603e-05 8.400608521999999704e-05 9.345805127999999324e-05 1.222826734999999982e-04 1.721083782999999949e-04 2.437076380999999930e-04 3.368191064000000050e-04 4.498102149000000080e-04 5.794148548999999591e-04 7.208238189999999733e-04 8.682751520999999707e-04 1.016051477000000066e-03 1.159568349000000050e-03 1.296149590999999936e-03 1.425178852000000100e-03 1.547548482999999957e-03 1.664596123999999896e-03 1.776918861999999969e-03 1.883515277000000080e-03 1.981611274000000082e-03 2.067307152999999821e-03 2.136901844000000175e-03 2.188486285000000066e-03 2.223239369999999940e-03 2.245883143000000030e-03 2.263988864000000215e-03 2.286224474000000170e-03 2.320064704999999939e-03 2.369768258999999794e-03 2.435409236999999845e-03 2.513390998999999806e-03 2.598287540999999912e-03 2.685297431000000130e-03 2.772324287000000210e-03 2.860863017999999876e-03 2.955410642999999928e-03 3.061780337000000012e-03 3.185155612000000001e-03 3.328756505000000140e-03 3.493597152000000022e-03 3.679210747000000083e-03 3.884726459000000139e-03 4.109559672000000392e-03 4.353274094999999913e-03 4.614711631000000154e-03 4.890953213999999979e-03 5.176805357999999906e-03 5.465232294000000116e-03 5.748635493000000402e-03 6.020421086000000283e-03 6.276152406999999794e-03 6.513830709999999732e-03 6.733327947999999570e-03 6.935430771000000195e-03 7.121103547000000138e-03 7.291372968999999989e-03 7.447812013999999779e-03 7.593209216000000074e-03 7.731875903000000327e-03 7.869242012000000203e-03 8.010801822999999433e-03 8.160854594999999295e-03 8.321620219999999180e-03 8.493121343999999670e-03 8.673822093999999927e-03 8.861628364000000146e-03 9.054696164000000311e-03 9.251637878999999579e-03 9.451068414999999612e-03 9.650795642000000243e-03 9.847143717000000213e-03 1.003482275000000014e-02 1.020748328000000045e-02 1.035877426000000011e-02 1.048351951999999983e-02 1.057862350999999937e-02 1.064348017000000049e-02 1.067986915999999918e-02 1.069145955000000078e-02 1.068305202000000009e-02 1.065963464000000034e-02 1.062530369000000072e-02 1.058217646000000033e-02 1.052956290000000086e-02 1.046375540999999916e-02 1.037871926999999958e-02 1.026768682000000002e-02 1.012526933999999962e-02 9.949390924999999136e-03 9.742299588999999219e-03 9.510198683999999958e-03 9.261575311999999810e-03 9.004852016000000625e-03 8.746285713999999226e-03 8.488921463999999847e-03 8.232918779999999145e-03 7.976938022000000170e-03 7.719812500000000112e-03 7.461663282999999626e-03 7.203963768999999823e-03 6.948639965000000425e-03 6.696796147999999928e-03 6.447828580999999913e-03 6.199459132999999948e-03 5.948722671999999954e-03 5.693443002000000280e-03 5.433486795999999813e-03 5.171207046000000397e-03 4.910895174999999925e-03 4.657530011000000393e-03 4.415403703000000263e-03 4.187194101000000016e-03 3.973780282999999844e-03 3.774726647999999962e-03 3.589080146999999981e-03 3.416053819999999817e-03 3.255309731000000182e-03 3.106804826000000071e-03 2.970384114999999933e-03 2.845394691000000063e-03 2.730532482000000167e-03 2.623979136000000132e-03 2.523730737000000161e-03 2.427938923999999922e-03 2.335106928000000182e-03 2.244084395000000079e-03 2.153927635999999986e-03 2.063774644000000019e-03 1.972889047000000052e-03 1.880948476999999954e-03 1.788515997999999985e-03 1.697487801999999959e-03 1.611225452999999908e-03 diff --git a/tests/mesa_pd/kernel/cnt/VBondContactIntegration.ipynb b/tests/mesa_pd/kernel/cnt/VBondContactIntegration.ipynb new file mode 100644 index 000000000..3b4827b2e --- /dev/null +++ b/tests/mesa_pd/kernel/cnt/VBondContactIntegration.ipynb @@ -0,0 +1,94 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "id": "northern-indie", + "metadata": {}, + "outputs": [], + "source": [ + "import matplotlib.pyplot as pl\n", + "import numpy as np\n", + "import seaborn as sns\n", + "\n", + "%matplotlib inline\n", + "%config InlineBackend.figure_formats = ['svg']\n", + "\n", + "sns.set_context(\"talk\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "distant-tsunami", + "metadata": {}, + "outputs": [], + "source": [ + "energies = np.loadtxt('VBondContactEnergies.txt').transpose()\n", + "ref = np.loadtxt('VBondContactEnergies.ref.txt')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "failing-studio", + "metadata": {}, + "outputs": [], + "source": [ + "pl.figure( figsize=(10,10) )\n", + "pl.subplot(221)\n", + "pl.title('tensile')\n", + "pl.plot(energies[1], label='MESA-PD')\n", + "pl.plot(ref[0], label='reference')\n", + "pl.legend()\n", + "\n", + "pl.subplot(222)\n", + "pl.title('shear')\n", + "pl.plot(energies[2])\n", + "pl.plot(ref[1])\n", + "\n", + "pl.subplot(223)\n", + "pl.title('bending')\n", + "pl.plot(energies[3])\n", + "pl.plot(ref[2])\n", + "\n", + "pl.subplot(224)\n", + "pl.title('twisting')\n", + "pl.plot(energies[4])\n", + "pl.plot(ref[3])\n", + "\n", + "pl.tight_layout()\n", + "pl.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "enormous-salvation", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.8.5" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/apps/benchmarks/CNT/VBondModel.cpp b/tests/mesa_pd/kernel/cnt/VBondContactIntegration.test.cpp similarity index 92% rename from apps/benchmarks/CNT/VBondModel.cpp rename to tests/mesa_pd/kernel/cnt/VBondContactIntegration.test.cpp index de90df0ce..5c956fe61 100644 --- a/apps/benchmarks/CNT/VBondModel.cpp +++ b/tests/mesa_pd/kernel/cnt/VBondContactIntegration.test.cpp @@ -20,7 +20,7 @@ // //====================================================================================================================== -#include "Accessor.h" +#include "SphericalSegmentAccessor.h" #include "mesa_pd/data/Flags.h" #include "mesa_pd/data/ParticleStorage.h" #include "mesa_pd/kernel/ParticleSelector.h" @@ -41,6 +41,12 @@ int main(int argc, char **argv) Environment env(argc, argv); walberla::mpi::MPIManager::instance()->useWorldComm(); + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + logging::Logging::instance()->setStreamLogLevel(logging::Logging::INFO); logging::Logging::instance()->setFileLogLevel(logging::Logging::INFO); @@ -49,7 +55,7 @@ int main(int argc, char **argv) WALBERLA_LOG_INFO_ON_ROOT("creating initial particle setup"); auto ps = std::make_shared<data::ParticleStorage>(10); - auto ac = Accessor(ps); + auto ac = SphericalSegmentAccessor(ps); for (auto i = 0; i < 10; ++i) { @@ -89,7 +95,7 @@ int main(int argc, char **argv) real_t bendingEnergy = 0_r; real_t twistingEnergy = 0_r; - std::ofstream fout("output.txt"); + std::ofstream fout("VBondContactEnergies.txt"); for (auto i = 0; i < numSimulationSteps; ++i) { vtkWriter->write(); @@ -119,10 +125,10 @@ int main(int argc, char **argv) if ((ac.getPosition(p_idx1) - ac.getPosition(p_idx2)).sqrLength() < cutoff2) { vbond(p_idx1, p_idx2, ac); - tensileEnergy += vbond.tensileEnergy; - shearEnergy += vbond.shearEnergy; - bendingEnergy += vbond.bendingEnergy; - twistingEnergy += vbond.twistingEnergy; + tensileEnergy += vbond.getLastTensileEnergy(); + shearEnergy += vbond.getLastShearEnergy(); + bendingEnergy += vbond.getLastBendingEnergy(); + twistingEnergy += vbond.getLastTwistingEnergy(); } }); @@ -151,10 +157,5 @@ int main(int argc, char **argv) int main(int argc, char *argv[]) { - if (std::is_same<walberla::real_t, float>::value) - { - WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); - return EXIT_SUCCESS; - } return walberla::main(argc, argv); } -- GitLab From 01c187223030ceea15290adc6cf679b0bd2a95e7 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Thu, 11 Feb 2021 14:52:41 +0100 Subject: [PATCH 62/83] Revert "Merge branch 'exclude-fluctuating-mrt-test-optimize-localhost' into 'master'" This reverts merge request !370 --- tests/lbm/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/lbm/CMakeLists.txt b/tests/lbm/CMakeLists.txt index ff0f7ef48..b17f65cfa 100644 --- a/tests/lbm/CMakeLists.txt +++ b/tests/lbm/CMakeLists.txt @@ -84,12 +84,9 @@ waLBerla_generate_target_from_python(NAME LbCodeGenerationExampleGenerated LbCodeGenerationExample_UBB.cpp LbCodeGenerationExample_UBB.h ) waLBerla_compile_test( FILES codegen/LbCodeGenerationExample.cpp DEPENDS LbCodeGenerationExampleGenerated) -# FluctuatingMRT test does not work with WALBERLA_OPTIMIZE_FOR_LOCALHOST since the random number generator is not implemented with SIMD -if ( NOT WALBERLA_OPTIMIZE_FOR_LOCALHOST ) waLBerla_generate_target_from_python(NAME FluctuatingMRTGenerated FILE codegen/FluctuatingMRT.py OUT_FILES FluctuatingMRT_LatticeModel.cpp FluctuatingMRT_LatticeModel.h ) waLBerla_compile_test( FILES codegen/FluctuatingMRT.cpp DEPENDS FluctuatingMRTGenerated) -endif() waLBerla_generate_target_from_python(NAME FieldLayoutAndVectorizationTestGenerated FILE codegen/FieldLayoutAndVectorizationTest.py OUT_FILES FieldLayoutAndVectorizationTest_FZYX_Vec_LatticeModel.cpp FieldLayoutAndVectorizationTest_FZYX_Vec_LatticeModel.h @@ -98,4 +95,4 @@ waLBerla_generate_target_from_python(NAME FieldLayoutAndVectorizationTestGenerat FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.cpp FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.h ) waLBerla_compile_test( FILES codegen/FieldLayoutAndVectorizationTest.cpp DEPENDS FieldLayoutAndVectorizationTestGenerated) -endif() +endif() \ No newline at end of file -- GitLab From 3b2f5b487e3ae0dc2c349b8b5e2a959965b3564d Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Thu, 11 Feb 2021 22:41:35 +0100 Subject: [PATCH 63/83] Fluctuating MRT: infer RNG precision from field precision Otherwise vectorization will fail --- tests/lbm/codegen/FluctuatingMRT.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/lbm/codegen/FluctuatingMRT.py b/tests/lbm/codegen/FluctuatingMRT.py index 71a102612..4db0ca9ba 100644 --- a/tests/lbm/codegen/FluctuatingMRT.py +++ b/tests/lbm/codegen/FluctuatingMRT.py @@ -44,6 +44,7 @@ with CodeGeneration() as ctx: fluctuating={ 'temperature': temperature, 'block_offsets': 'walberla', + 'rng_node': ps.rng.PhiloxTwoDoubles if ctx.double_accuracy else ps.rng.PhiloxFourFloats, }, optimization={'cse_global': True} ) -- GitLab From e6f7c8191a703198b0b797bfd627b6c89e7bf341 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 12 Feb 2021 10:02:04 +0100 Subject: [PATCH 64/83] changed folder name from VBondModel to cnt --- .../kernel/{VBondModel => cnt}/ViscousDamping.h | 4 ++-- src/mesa_pd/kernel/{VBondModel => cnt}/WallContact.h | 4 ++-- tests/mesa_pd/CMakeLists.txt | 12 ++++++------ .../{VBondModel => cnt}/ViscousDamping.test.cpp | 4 ++-- .../kernel/{VBondModel => cnt}/WallContact.test.cpp | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) rename src/mesa_pd/kernel/{VBondModel => cnt}/ViscousDamping.h (98%) rename src/mesa_pd/kernel/{VBondModel => cnt}/WallContact.h (98%) rename tests/mesa_pd/kernel/{VBondModel => cnt}/ViscousDamping.test.cpp (96%) rename tests/mesa_pd/kernel/{VBondModel => cnt}/WallContact.test.cpp (97%) diff --git a/src/mesa_pd/kernel/VBondModel/ViscousDamping.h b/src/mesa_pd/kernel/cnt/ViscousDamping.h similarity index 98% rename from src/mesa_pd/kernel/VBondModel/ViscousDamping.h rename to src/mesa_pd/kernel/cnt/ViscousDamping.h index 9f9fe2c69..5165c0c8d 100644 --- a/src/mesa_pd/kernel/VBondModel/ViscousDamping.h +++ b/src/mesa_pd/kernel/cnt/ViscousDamping.h @@ -34,7 +34,7 @@ namespace walberla { namespace mesa_pd { namespace kernel { -namespace VBondModel { +namespace cnt { class ViscousDamping { @@ -71,7 +71,7 @@ inline void ViscousDamping::operator()(const size_t p_idx1, } -} //namespace VBondModel +} //namespace cnt } //namespace kernel } //namespace mesa_pd } //namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/kernel/VBondModel/WallContact.h b/src/mesa_pd/kernel/cnt/WallContact.h similarity index 98% rename from src/mesa_pd/kernel/VBondModel/WallContact.h rename to src/mesa_pd/kernel/cnt/WallContact.h index 24d153ca5..5c221025a 100644 --- a/src/mesa_pd/kernel/VBondModel/WallContact.h +++ b/src/mesa_pd/kernel/cnt/WallContact.h @@ -34,7 +34,7 @@ namespace walberla { namespace mesa_pd { namespace kernel { -namespace VBondModel { +namespace cnt { /** * Repulsive wall interaction kernel. @@ -107,7 +107,7 @@ inline void WallContact::operator()(const size_t p_idx, addForceAtomic( p_idx, ac, Vec3(0_r, 0_r, F_) ); } -} //namespace VBondModel +} //namespace cnt } //namespace kernel } //namespace mesa_pd } //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index d84af9fb2..983cbca6e 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -93,6 +93,12 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_VBondContact ) waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_VBondContactIntegration FILES kernel/cnt/VBondContactIntegration.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_VBondContactIntegration ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_ViscousDamping FILES kernel/cnt/ViscousDamping.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_ViscousDamping ) + +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_WallContact FILES kernel/cnt/WallContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_WallContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSD FILES kernel/CoefficientOfRestitutionSD.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDEuler COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> ) waLBerla_execute_test( NAME MESA_PD_Kernel_CoefficientOfRestitutionSDVelocityVerlet COMMAND $<TARGET_FILE:MESA_PD_Kernel_CoefficientOfRestitutionSD> --useVV ) @@ -173,12 +179,6 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) -waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping FILES kernel/VBondModel/ViscousDamping.test.cpp DEPENDS core ) -waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping ) - -waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_WallContact FILES kernel/VBondModel/WallContact.test.cpp DEPENDS core ) -waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_WallContact ) - waLBerla_compile_test( NAME MESA_PD_Kernel_VelocityVerlet FILES kernel/VelocityVerlet.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VelocityVerlet ) diff --git a/tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp b/tests/mesa_pd/kernel/cnt/ViscousDamping.test.cpp similarity index 96% rename from tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp rename to tests/mesa_pd/kernel/cnt/ViscousDamping.test.cpp index 8f54645ff..593ddecac 100644 --- a/tests/mesa_pd/kernel/VBondModel/ViscousDamping.test.cpp +++ b/tests/mesa_pd/kernel/cnt/ViscousDamping.test.cpp @@ -23,7 +23,7 @@ #include <mesa_pd/data/ParticleAccessor.h> #include <mesa_pd/data/ParticleStorage.h> -#include <mesa_pd/kernel/VBondModel/ViscousDamping.h> +#include <mesa_pd/kernel/cnt/ViscousDamping.h> #include <core/Environment.h> #include <core/logging/Logging.h> @@ -54,7 +54,7 @@ int main( int argc, char ** argv ) data::ParticleAccessor ac(ps); //init kernels - kernel::VBondModel::ViscousDamping damping(0.2_r,0.5_r); + kernel::cnt::ViscousDamping damping(0.2_r,0.5_r); WALBERLA_CHECK_FLOAT_EQUAL(damping.getForceDampingFactor(), 0.2_r); WALBERLA_CHECK_FLOAT_EQUAL(damping.getTorqueDampingFactor(), diff --git a/tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp b/tests/mesa_pd/kernel/cnt/WallContact.test.cpp similarity index 97% rename from tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp rename to tests/mesa_pd/kernel/cnt/WallContact.test.cpp index f923ee41d..50165fd4f 100644 --- a/tests/mesa_pd/kernel/VBondModel/WallContact.test.cpp +++ b/tests/mesa_pd/kernel/cnt/WallContact.test.cpp @@ -23,7 +23,7 @@ #include <mesa_pd/data/ParticleAccessor.h> #include <mesa_pd/data/ParticleStorage.h> -#include <mesa_pd/kernel/VBondModel/WallContact.h> +#include <mesa_pd/kernel/cnt/WallContact.h> #include <core/Environment.h> #include <core/logging/Logging.h> @@ -50,7 +50,7 @@ int main( int argc, char ** argv ) p.setPosition(0, Vec3(0,0,0)); //init kernels - kernel::VBondModel::WallContact wallContact(0_r); + kernel::cnt::WallContact wallContact(0_r); auto calcForce = [&](const real_t zPos) { -- GitLab From 58d371d70bd4652c384fe81fee8a884012139870 Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Fri, 12 Feb 2021 18:01:07 +0100 Subject: [PATCH 65/83] Generated outflow bc --- AUTHORS.txt | 1 + .../UniformGridGPU/UniformGridGPU.py | 5 +- .../UniformGridGenerated.py | 5 +- apps/pythonmodule/PythonModule.cpp | 2 + .../PhaseFieldAllenCahn/CPU/CMakeLists.txt | 3 +- .../PhaseFieldAllenCahn/GPU/CMakeLists.txt | 3 +- .../codegen/03_AdvancedLBMCodegen.py | 5 +- python/lbmpy_walberla/__init__.py | 3 +- .../lbmpy_walberla/additional_data_handler.py | 127 +++++++++++ python/lbmpy_walberla/boundary.py | 30 ++- python/lbmpy_walberla/packinfo.py | 82 +++++++ .../lbmpy_walberla/walberla_lbm_generation.py | 1 - .../additional_data_handler.py | 55 +++++ python/pystencils_walberla/boundary.py | 73 +++--- python/pystencils_walberla/codegen.py | 15 +- python/pystencils_walberla/jinja_filters.py | 31 +++ .../templates/Boundary.tmpl.cpp | 22 +- .../templates/Boundary.tmpl.h | 62 +++-- .../templates/Sweep.tmpl.cpp | 2 +- src/lbm/field/QCriterion.h | 59 ++--- src/timeloop/SweepTimeloop.cpp | 10 +- tests/lbm/CMakeLists.txt | 26 ++- tests/lbm/codegen/CMakeLists.txt | 8 + tests/lbm/codegen/GeneratedOutflowBC.cpp | 194 ++++++++++++++++ tests/lbm/codegen/GeneratedOutflowBC.prm | 24 ++ tests/lbm/codegen/GeneratedOutflowBC.py | 92 ++++++++ .../lbm/codegen/LbmPackInfoGenerationTest.py | 29 +++ tests/lbm/diff_packinfos.sh | 6 + tests/timeloop/CMakeLists.txt | 4 +- tests/timeloop/TimeloopAndSweepRegister.cpp | 212 +++++++----------- 30 files changed, 945 insertions(+), 246 deletions(-) create mode 100644 python/lbmpy_walberla/additional_data_handler.py create mode 100644 python/lbmpy_walberla/packinfo.py create mode 100644 python/pystencils_walberla/additional_data_handler.py create mode 100644 tests/lbm/codegen/CMakeLists.txt create mode 100644 tests/lbm/codegen/GeneratedOutflowBC.cpp create mode 100644 tests/lbm/codegen/GeneratedOutflowBC.prm create mode 100644 tests/lbm/codegen/GeneratedOutflowBC.py create mode 100644 tests/lbm/codegen/LbmPackInfoGenerationTest.py create mode 100755 tests/lbm/diff_packinfos.sh diff --git a/AUTHORS.txt b/AUTHORS.txt index b0dba6103..2f956f1b1 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -13,6 +13,7 @@ Dominik Bartuschat Ehsan Fattahi Felix Winterhalter Florian Schornbaum +Frederik Hennig Grigorii Drozdov Helen Schottenhamml Igor Ostanin diff --git a/apps/benchmarks/UniformGridGPU/UniformGridGPU.py b/apps/benchmarks/UniformGridGPU/UniformGridGPU.py index c1371278a..1a7973f6d 100644 --- a/apps/benchmarks/UniformGridGPU/UniformGridGPU.py +++ b/apps/benchmarks/UniformGridGPU/UniformGridGPU.py @@ -69,11 +69,10 @@ options_dict = { 'relaxation_rate': omega, }, 'cumulant': { + 'method': 'cumulant', 'stencil': 'D3Q19', 'compressible': True, - 'method': 'mrt', - 'cumulant': True, - 'relaxation_rates': [0, omega, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + 'relaxation_rate': omega, }, } diff --git a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py index b9ca24ba1..fc587c445 100644 --- a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py +++ b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py @@ -55,11 +55,10 @@ options_dict = { 'relaxation_rate': omega, }, 'cumulant': { + 'method': 'cumulant', 'stencil': 'D3Q19', 'compressible': True, - 'method': 'mrt', - 'cumulant': True, - 'relaxation_rates': [0, omega, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], + 'relaxation_rate': omega, }, } diff --git a/apps/pythonmodule/PythonModule.cpp b/apps/pythonmodule/PythonModule.cpp index b32f103dd..3059e3f05 100644 --- a/apps/pythonmodule/PythonModule.cpp +++ b/apps/pythonmodule/PythonModule.cpp @@ -40,11 +40,13 @@ using namespace walberla; Field<walberla::real_t,1>,\ Field<walberla::real_t,2>,\ Field<walberla::real_t,3>,\ + Field<walberla::real_t,4>,\ Field<walberla::real_t,9>,\ Field<walberla::real_t,15>,\ Field<walberla::real_t,19>,\ Field<walberla::real_t,27>,\ Field<walberla::int8_t,1>,\ + Field<walberla::int32_t,1>,\ Field<walberla::int64_t,1>,\ Field<walberla::int64_t,2>,\ Field<walberla::int64_t,3>,\ diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt b/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt index 0e8f653f7..adacc3263 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/CMakeLists.txt @@ -17,5 +17,4 @@ waLBerla_add_executable(NAME multiphaseCPU FILES multiphase.cpp PythonExports.cpp InitializerFunctions.cpp contact.cpp CalculateNormals.cpp multiphase_codegen.py DEPENDS blockforest core field postprocessing lbm geometry timeloop gui PhaseFieldCodeGenCPU) - - +set_target_properties(multiphaseCPU PROPERTIES CXX_VISIBILITY_PRESET hidden) diff --git a/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt b/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt index c65a87749..51c692203 100644 --- a/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt +++ b/apps/showcases/PhaseFieldAllenCahn/GPU/CMakeLists.txt @@ -20,5 +20,4 @@ waLBerla_add_executable(NAME multiphaseGPU FILES multiphase.cpp PythonExports.cpp InitializerFunctions.cpp CalculateNormals.cpp contact.cu multiphase_codegen.py DEPENDS blockforest core cuda field postprocessing lbm geometry timeloop gui PhaseFieldCodeGenGPU) - - +set_target_properties(multiphaseGPU PROPERTIES CXX_VISIBILITY_PRESET hidden) diff --git a/apps/tutorials/codegen/03_AdvancedLBMCodegen.py b/apps/tutorials/codegen/03_AdvancedLBMCodegen.py index a39790980..65a0602f2 100644 --- a/apps/tutorials/codegen/03_AdvancedLBMCodegen.py +++ b/apps/tutorials/codegen/03_AdvancedLBMCodegen.py @@ -36,9 +36,8 @@ optimization = {'cse_global': True, # ================== lbm_params = {'stencil': stencil, - 'method': 'mrt_raw', - 'relaxation_rates': [0, 0, 0, omega, omega, omega, 1, 1, 1], - 'cumulant': True, + 'method': 'cumulant', + 'relaxation_rate': omega, 'compressible': True} lbm_update_rule = create_lb_update_rule(optimization=optimization, diff --git a/python/lbmpy_walberla/__init__.py b/python/lbmpy_walberla/__init__.py index f7b022ab0..1a7b136a7 100644 --- a/python/lbmpy_walberla/__init__.py +++ b/python/lbmpy_walberla/__init__.py @@ -1,4 +1,5 @@ from .boundary import generate_boundary from .walberla_lbm_generation import RefinementScaling, generate_lattice_model +from .packinfo import generate_lb_pack_info -__all__ = ['generate_lattice_model', 'RefinementScaling', 'generate_boundary'] +__all__ = ['generate_lattice_model', 'RefinementScaling', 'generate_boundary', 'generate_lb_pack_info'] diff --git a/python/lbmpy_walberla/additional_data_handler.py b/python/lbmpy_walberla/additional_data_handler.py new file mode 100644 index 000000000..804c4953e --- /dev/null +++ b/python/lbmpy_walberla/additional_data_handler.py @@ -0,0 +1,127 @@ +from pystencils.stencil import inverse_direction + +from lbmpy.advanced_streaming import AccessPdfValues, numeric_offsets, numeric_index +from lbmpy.boundaries import ExtrapolationOutflow, UBB + +from pystencils_walberla.additional_data_handler import AdditionalDataHandler + + +class UBBAdditionalDataHandler(AdditionalDataHandler): + def __init__(self, stencil, boundary_object): + assert isinstance(boundary_object, UBB) + self._boundary_object = boundary_object + super(UBBAdditionalDataHandler, self).__init__(stencil=stencil) + + @property + def constructor_arguments(self): + return ", std::function<Vector3<real_t>(const Cell &, const shared_ptr<StructuredBlockForest>&, IBlock&)>& " \ + "velocityCallback " + + @property + def initialiser_list(self): + return "elementInitaliser(velocityCallback)," + + @property + def additional_arguments_for_fill_function(self): + return "blocks, " + + @property + def additional_parameters_for_fill_function(self): + return " const shared_ptr<StructuredBlockForest> &blocks, " + + def data_initialisation(self, direction): + init_list = ["Vector3<real_t> InitialisatonAdditionalData = elementInitaliser(Cell(it.x(), it.y(), it.z()), " + "blocks, *block);", "element.vel_0 = InitialisatonAdditionalData[0];", + "element.vel_1 = InitialisatonAdditionalData[1];"] + if self._dim == 3: + init_list.append("element.vel_2 = InitialisatonAdditionalData[2];") + + return "\n".join(init_list) + + @property + def additional_member_variable(self): + return "std::function<Vector3<real_t>(const Cell &, const shared_ptr<StructuredBlockForest>&, IBlock&)> " \ + "elementInitaliser; " + + +class OutflowAdditionalDataHandler(AdditionalDataHandler): + def __init__(self, stencil, boundary_object, target='cpu', field_name='pdfs'): + assert isinstance(boundary_object, ExtrapolationOutflow) + self._boundary_object = boundary_object + self._stencil = boundary_object.stencil + self._lb_method = boundary_object.lb_method + self._normal_direction = boundary_object.normal_direction + self._field_name = field_name + self._target = target + super(OutflowAdditionalDataHandler, self).__init__(stencil=stencil) + + assert sum([a != 0 for a in self._normal_direction]) == 1,\ + "The outflow boundary is only implemented for straight walls at the moment." + + @property + def constructor_arguments(self): + return f", BlockDataID {self._field_name}CPUID_" if self._target == 'gpu' else "" + + @property + def initialiser_list(self): + return f"{self._field_name}CPUID({self._field_name}CPUID_)," if self._target == 'gpu' else "" + + @property + def additional_field_data(self): + identifier = "CPU" if self._target == "gpu" else "" + return f"auto {self._field_name} = block->getData< field::GhostLayerField<double, " \ + f"{len(self._stencil)}> >({self._field_name}{identifier}ID); " + + def data_initialisation(self, direction_index): + pdf_acc = AccessPdfValues(self._boundary_object.stencil, + streaming_pattern=self._boundary_object.streaming_pattern, + timestep=self._boundary_object.zeroth_timestep, + streaming_dir='out') + + init_list = [] + for key, value in self.get_init_dict(pdf_acc, direction_index).items(): + init_list.append(f"element.{key} = {self._field_name}->get({value});") + + return "\n".join(init_list) + + @property + def additional_member_variable(self): + return f"BlockDataID {self._field_name}CPUID;" + + @property + def stencil_info(self): + stencil_info = [] + for i, d in enumerate(self._stencil): + if any([a != 0 and b != 0 and a == b for a, b in zip(self._normal_direction, d)]): + direction = d if self._dim == 3 else d + (0,) + stencil_info.append((i, direction, ", ".join([str(e) for e in direction]))) + return stencil_info + + def get_init_dict(self, pdf_accessor, direction_index): + """The Extrapolation Outflow boundary needs additional data. This function provides a list of all values + which have to be initialised""" + position = ["it.x()", "it.y()", "it.z()"] + direction = self._stencil[direction_index] + inv_dir = self._stencil.index(inverse_direction(direction)) + + tangential_offset = tuple(offset - normal for offset, normal in zip(direction, self._normal_direction)) + + result = {} + pos = [] + offsets = numeric_offsets(pdf_accessor.accs[inv_dir]) + for p, o, t in zip(position, offsets, tangential_offset): + pos.append(p + f" + cell_idx_c({str(o + t)})") + if self._dim == 2: + pos.append("0") + pos.append(str(numeric_index(pdf_accessor.accs[inv_dir])[0])) + result[f'pdf'] = ', '.join(pos) + + pos = [] + for p, o, t in zip(position, offsets, tangential_offset): + pos.append(p + f" + cell_idx_c({str(o + t)})") + if self._dim == 2: + pos.append("0") + pos.append(str(numeric_index(pdf_accessor.accs[inv_dir])[0])) + result[f'pdf_nd'] = ', '.join(pos) + + return result diff --git a/python/lbmpy_walberla/boundary.py b/python/lbmpy_walberla/boundary.py index 8f751f529..b0dafb7b3 100644 --- a/python/lbmpy_walberla/boundary.py +++ b/python/lbmpy_walberla/boundary.py @@ -1,5 +1,6 @@ import pystencils_walberla.boundary from lbmpy.boundaries.boundaryhandling import create_lattice_boltzmann_boundary_kernel +from lbmpy.advanced_streaming import Timestep, is_inplace def generate_boundary(generation_context, @@ -7,15 +8,29 @@ def generate_boundary(generation_context, boundary_object, lb_method, field_name='pdfs', + streaming_pattern='pull', + always_generate_separate_classes=False, + additional_data_handler=None, **create_kernel_params): - def boundary_creation_function(field, index_field, stencil, boundary_functor, target='cpu', openmp=True, **kwargs): - return create_lattice_boltzmann_boundary_kernel(field, - index_field, - lb_method, - boundary_functor, - target=target, - **kwargs) + pargs = (field, index_field, lb_method, boundary_functor) + kwargs = {'target': target, **kwargs} + if is_inplace(streaming_pattern) or always_generate_separate_classes: + return { + 'EvenSweep': create_lattice_boltzmann_boundary_kernel(*pargs, + streaming_pattern=streaming_pattern, + prev_timestep=Timestep.EVEN, + **kwargs), + 'OddSweep': create_lattice_boltzmann_boundary_kernel(*pargs, + streaming_pattern=streaming_pattern, + prev_timestep=Timestep.ODD, + **kwargs) + } + else: + return create_lattice_boltzmann_boundary_kernel(*pargs, + streaming_pattern=streaming_pattern, + prev_timestep=Timestep.BOTH, + **kwargs) pystencils_walberla.boundary.generate_boundary(generation_context, class_name, @@ -25,4 +40,5 @@ def generate_boundary(generation_context, index_shape=[len(lb_method.stencil)], kernel_creation_function=boundary_creation_function, namespace='lbm', + additional_data_handler=additional_data_handler, **create_kernel_params) diff --git a/python/lbmpy_walberla/packinfo.py b/python/lbmpy_walberla/packinfo.py new file mode 100644 index 000000000..54a4e6755 --- /dev/null +++ b/python/lbmpy_walberla/packinfo.py @@ -0,0 +1,82 @@ +from collections import defaultdict +from lbmpy.advanced_streaming.utility import Timestep, get_accessor, get_timesteps +from lbmpy.advanced_streaming.communication import _extend_dir +from pystencils.stencil import inverse_direction +from pystencils_walberla.codegen import comm_directions, generate_pack_info +from pystencils import Assignment, Field + + +def generate_lb_pack_info(generation_context, + class_name_prefix: str, + stencil, + pdf_field, + streaming_pattern='pull', + lb_collision_rule=None, + always_generate_separate_classes=False, + namespace='lbm', + **create_kernel_params): + """Generates waLBerla MPI PackInfos for an LBM kernel, based on a given method + and streaming pattern. For in-place streaming patterns, two PackInfos are generated; + one for the even and another for the odd time steps. + + Args: + generation_context: see documentation of `generate_sweep` + class_name_prefix: Prefix of the desired class name which will be extended with + 'Even' or 'Odd' for in-place kernels + stencil: The tuple of directions specifying the employed LB stencil. + pdf_field: pdf field for which the pack info is created + streaming_pattern: The employed streaming pattern. + lb_collision_rule: Optional. The collision rule defining the lattice boltzmann kernel, as returned + by `create_lb_collision_rule`. If specified, it will be scanned for non-local + accesses to other fields other than the PDF fields (as might be required for + computing gradients in coupled simulations), whose communication will then + be included in the PackInfo. + always_generate_separate_classes: If True, generate a pair of Even/Odd PackInfos even for a two- + fields kernel (i.e. the pull/push patterns). Otherwise, for two-fields + kernels, only one PackInfo class will be generated without a + suffix to its name. + namespace: inner namespace of the generated class + **create_kernel_params: remaining keyword arguments are passed to `pystencils.create_kernel` + """ + timesteps = [Timestep.EVEN, Timestep.ODD] \ + if always_generate_separate_classes \ + else get_timesteps(streaming_pattern) + + common_spec = defaultdict(set) + + if lb_collision_rule is not None: + assignments = lb_collision_rule.all_assignments + reads = set() + for a in assignments: + if not isinstance(a, Assignment): + continue + reads.update(a.rhs.atoms(Field.Access)) + for fa in reads: + assert all(abs(e) <= 1 for e in fa.offsets) + if all(offset == 0 for offset in fa.offsets): + continue + comm_direction = inverse_direction(fa.offsets) + for comm_dir in comm_directions(comm_direction): + common_spec[(comm_dir,)].add(fa.field.center(*fa.index)) + + for t in timesteps: + spec = common_spec.copy() + write_accesses = get_accessor(streaming_pattern, t).write(pdf_field, stencil) + for comm_dir in stencil: + if all(d == 0 for d in comm_dir): + continue + + for streaming_dir in set(_extend_dir(comm_dir)) & set(stencil): + d = stencil.index(streaming_dir) + fa = write_accesses[d] + spec[(comm_dir,)].add(fa) + + if t == Timestep.EVEN: + class_name_suffix = 'Even' + elif t == Timestep.ODD: + class_name_suffix = 'Odd' + else: + class_name_suffix = '' + + class_name = class_name_prefix + class_name_suffix + generate_pack_info(generation_context, class_name, spec, namespace=namespace, **create_kernel_params) diff --git a/python/lbmpy_walberla/walberla_lbm_generation.py b/python/lbmpy_walberla/walberla_lbm_generation.py index a7563b76c..82867d8b8 100644 --- a/python/lbmpy_walberla/walberla_lbm_generation.py +++ b/python/lbmpy_walberla/walberla_lbm_generation.py @@ -6,7 +6,6 @@ from jinja2 import Environment, PackageLoader, StrictUndefined, Template from sympy.tensor import IndexedBase import pystencils as ps -# from lbmpy.creationfunctions import create_lb_update_rule, update_with_default_parameters from lbmpy.fieldaccess import CollideOnlyInplaceAccessor, StreamPullTwoFieldsAccessor from lbmpy.relaxationrates import relaxation_rate_scaling from lbmpy.stencils import get_stencil diff --git a/python/pystencils_walberla/additional_data_handler.py b/python/pystencils_walberla/additional_data_handler.py new file mode 100644 index 000000000..7abe7d5aa --- /dev/null +++ b/python/pystencils_walberla/additional_data_handler.py @@ -0,0 +1,55 @@ +from pystencils.stencil import inverse_direction + + +class AdditionalDataHandler: + """Base class that defines how to handle boundary conditions holding additional data.""" + + def __init__(self, stencil): + self._dim = len(stencil[0]) + + # waLBerla is a 3D framework. Therefore, a zero for the z index has to be added if we work in 2D + if self._dim == 2: + self._walberla_stencil = () + for d in stencil: + d = d + (0,) + self._walberla_stencil = self._walberla_stencil + (d,) + else: + self._walberla_stencil = stencil + + @property + def constructor_arguments(self): + return "" + + @property + def initialiser_list(self): + return "" + + @property + def additional_arguments_for_fill_function(self): + return "" + + @property + def additional_parameters_for_fill_function(self): + return "" + + @property + def additional_field_data(self): + return "" + + def data_initialisation(self, direction_index): + return "" + + @property + def additional_member_variable(self): + return "" + + @property + def stencil_info(self): + return [(i, d, ", ".join([str(e) for e in d])) for i, d in enumerate(self._walberla_stencil)] + + @property + def inverse_directions(self): + inv_dirs = [] + for direction in self._walberla_stencil: + inv_dirs.append(self._walberla_stencil.index(inverse_direction(direction))) + return inv_dirs diff --git a/python/pystencils_walberla/boundary.py b/python/pystencils_walberla/boundary.py index 73d429ec5..0d251236c 100644 --- a/python/pystencils_walberla/boundary.py +++ b/python/pystencils_walberla/boundary.py @@ -1,3 +1,4 @@ +from collections import OrderedDict import numpy as np from jinja2 import Environment, PackageLoader, StrictUndefined from pystencils import Field, FieldType @@ -8,6 +9,7 @@ from pystencils.boundaries.createindexlist import ( from pystencils.data_types import TypedSymbol, create_type from pystencils_walberla.codegen import KernelInfo, default_create_kernel_parameters from pystencils_walberla.jinja_filters import add_pystencils_filters_to_jinja_env +from pystencils_walberla.additional_data_handler import AdditionalDataHandler def generate_boundary(generation_context, @@ -20,7 +22,12 @@ def generate_boundary(generation_context, kernel_creation_function=None, target='cpu', namespace='pystencils', + additional_data_handler=None, **create_kernel_params): + + if boundary_object.additional_data and additional_data_handler is None: + raise ValueError("Boundary object has additional data but you have not provided an AdditionalDataHandler.") + struct_name = "IndexInfo" boundary_object.name = class_name dim = len(neighbor_stencil[0]) @@ -44,36 +51,44 @@ def generate_boundary(generation_context, if not kernel_creation_function: kernel_creation_function = create_boundary_kernel - kernel = kernel_creation_function(field, index_field, neighbor_stencil, boundary_object, **create_kernel_params) - kernel.function_name = "boundary_" + boundary_object.name - kernel.assumed_inner_stride_one = False - - # waLBerla is a 3D framework. Therefore, a zero for the z index has to be added if we work in 2D - if dim == 2: - stencil = () - for d in neighbor_stencil: - d = d + (0,) - stencil = stencil + (d,) + kernels = kernel_creation_function(field, index_field, neighbor_stencil, boundary_object, **create_kernel_params) + if isinstance(kernels, dict): + sweep_to_kernel_info_dict = OrderedDict() + dummy_kernel_info = None + for sweep_class, sweep_kernel in kernels.items(): + sweep_kernel.function_name = "boundary_" + boundary_object.name + '_' + sweep_class + sweep_kernel.assumed_inner_stride_one = False + kernel_info = KernelInfo(sweep_kernel) + sweep_to_kernel_info_dict[sweep_class] = kernel_info + if dummy_kernel_info is None: + dummy_kernel_info = kernel_info + # elif not dummy_kernel_info.has_same_interface(kernel_info): + # raise ValueError("Multiple boundary sweeps must have the same kernel interface!") + multi_sweep = True else: - stencil = neighbor_stencil + multi_sweep = False + kernel = kernels + kernel.function_name = "boundary_" + boundary_object.name + kernel.assumed_inner_stride_one = False + kernel_info = KernelInfo(kernel) + sweep_to_kernel_info_dict = {'': kernel_info} + dummy_kernel_info = kernel_info - stencil_info = [(i, d, ", ".join([str(e) for e in d])) for i, d in enumerate(stencil)] - inv_dirs = [] - for direction in stencil: - inverse_dir = tuple([-i for i in direction]) - inv_dirs.append(stencil.index(inverse_dir)) + if additional_data_handler is None: + additional_data_handler = AdditionalDataHandler(stencil=neighbor_stencil) context = { 'class_name': boundary_object.name, + 'sweep_classes': sweep_to_kernel_info_dict, + 'multi_sweep': multi_sweep, + 'dummy_kernel_info': dummy_kernel_info, 'StructName': struct_name, 'StructDeclaration': struct_from_numpy_dtype(struct_name, index_struct_dtype), - 'kernel': KernelInfo(kernel), - 'stencil_info': stencil_info, - 'inverse_directions': inv_dirs, 'dim': dim, 'target': target, 'namespace': namespace, - 'inner_or_boundary': boundary_object.inner_or_boundary + 'inner_or_boundary': boundary_object.inner_or_boundary, + 'additional_data_handler': additional_data_handler } env = Environment(loader=PackageLoader('pystencils_walberla'), undefined=StrictUndefined) @@ -83,8 +98,8 @@ def generate_boundary(generation_context, source = env.get_template('Boundary.tmpl.cpp').render(**context) source_extension = "cpp" if target == "cpu" else "cu" - generation_context.write_file("{}.h".format(class_name), header) - generation_context.write_file("{}.{}".format(class_name, source_extension), source) + generation_context.write_file(f"{class_name}.h", header) + generation_context.write_file(f"{class_name}.{source_extension}", source) def generate_staggered_boundary(generation_context, class_name, boundary_object, @@ -102,23 +117,23 @@ def generate_staggered_flux_boundary(generation_context, class_name, boundary_ob def struct_from_numpy_dtype(struct_name, numpy_dtype): - result = "struct %s { \n" % (struct_name,) + result = f"struct {struct_name} {{ \n" equality_compare = [] constructor_params = [] constructor_initializer_list = [] for name, (sub_type, offset) in numpy_dtype.fields.items(): pystencils_type = create_type(sub_type) - result += " %s %s;\n" % (pystencils_type, name) + result += f" {pystencils_type} {name};\n" if name in boundary_index_array_coordinate_names or name == direction_member_name: - constructor_params.append("%s %s_" % (pystencils_type, name)) - constructor_initializer_list.append("%s(%s_)" % (name, name)) + constructor_params.append(f"{pystencils_type} {name}_") + constructor_initializer_list.append(f"{name}({name}_)") else: - constructor_initializer_list.append("%s()" % name) + constructor_initializer_list.append(f"{name}()") if pystencils_type.is_float(): - equality_compare.append("floatIsEqual(%s, o.%s)" % (name, name)) + equality_compare.append(f"floatIsEqual({name}, o.{name})") else: - equality_compare.append("%s == o.%s" % (name, name)) + equality_compare.append(f"{name} == o.{name}") result += " %s(%s) : %s {}\n" % \ (struct_name, ", ".join(constructor_params), ", ".join(constructor_initializer_list)) diff --git a/python/pystencils_walberla/codegen.py b/python/pystencils_walberla/codegen.py index 37013cba6..896a795cc 100644 --- a/python/pystencils_walberla/codegen.py +++ b/python/pystencils_walberla/codegen.py @@ -20,7 +20,7 @@ __all__ = ['generate_sweep', 'generate_pack_info', 'generate_pack_info_for_field def generate_sweep(generation_context, class_name, assignments, namespace='pystencils', field_swaps=(), staggered=False, varying_parameters=(), - inner_outer_split=False, + inner_outer_split=False, ghost_layers_to_include=0, **create_kernel_params): """Generates a waLBerla sweep from a pystencils representation. @@ -44,6 +44,8 @@ def generate_sweep(generation_context, class_name, assignments, the C++ class constructor even if the kernel does not need them. inner_outer_split: if True generate a sweep that supports separate iteration over inner and outer regions to allow for communication hiding. + ghost_layers_to_include: determines how many ghost layers should be included for the Sweep. + This is relevant if a setter kernel should also set correct values to the ghost layers. **create_kernel_params: remaining keyword arguments are passed to `pystencils.create_kernel` """ create_kernel_params = default_create_kernel_parameters(generation_context, create_kernel_params) @@ -78,6 +80,7 @@ def generate_sweep(generation_context, class_name, assignments, 'class_name': class_name, 'target': create_kernel_params.get("target", "cpu"), 'headers': get_headers(ast), + 'ghost_layers_to_include': ghost_layers_to_include } header = env.get_template("Sweep.tmpl.h").render(**jinja_context) source = env.get_template("Sweep.tmpl.cpp").render(**jinja_context) @@ -93,6 +96,7 @@ def generate_sweep(generation_context, class_name, assignments, 'target': create_kernel_params.get("target", "cpu"), 'field': representative_field, 'headers': get_headers(ast), + 'ghost_layers_to_include': 0 } header = env.get_template("SweepInnerOuter.tmpl.h").render(**jinja_context) source = env.get_template("SweepInnerOuter.tmpl.cpp").render(**jinja_context) @@ -132,7 +136,7 @@ def generate_pack_info_from_kernel(generation_context, class_name: str, assignme class_name: name of the generated class assignments: list of assignments from the compute kernel - generates PackInfo for "pull" part only i.e. the kernel is expected to only write to the center - kind: + kind: can either be pull or push **create_kernel_params: remaining keyword arguments are passed to `pystencils.create_kernel` """ assert kind in ('push', 'pull') @@ -240,7 +244,6 @@ def generate_pack_info(generation_context, class_name: str, pack_kernels[direction_strings] = KernelInfo(pack_ast) unpack_kernels[direction_strings] = KernelInfo(unpack_ast) elements_per_cell[direction_strings] = len(terms) - fused_kernel = create_kernel([Assignment(buffer.center, t) for t in all_accesses], **create_kernel_params) fused_kernel.assumed_inner_stride_one = create_kernel_params['cpu_vectorize_info']['assume_inner_stride_one'] @@ -333,6 +336,12 @@ class KernelInfo: self.varying_parameters = tuple(varying_parameters) self.parameters = ast.get_parameters() # cache parameters here + def has_same_interface(self, other): + return self.temporary_fields == other.temporary_fields \ + and self.field_swaps == other.field_swaps \ + and self.varying_parameters == other.varying_parameters \ + and self.parameters == other.parameters + def get_vectorize_instruction_set(generation_context): if generation_context.optimize_for_localhost: diff --git a/python/pystencils_walberla/jinja_filters.py b/python/pystencils_walberla/jinja_filters.py index 60903be9e..7158f8168 100644 --- a/python/pystencils_walberla/jinja_filters.py +++ b/python/pystencils_walberla/jinja_filters.py @@ -338,6 +338,26 @@ def generate_constructor_parameters(kernel_info, parameters_to_ignore=None): return ", ".join(parameter_list + varying_parameters) +def generate_constructor_call_arguments(kernel_info, parameters_to_ignore=None): + if parameters_to_ignore is None: + parameters_to_ignore = [] + + varying_parameters = [] + if hasattr(kernel_info, 'varying_parameters'): + varying_parameters = kernel_info.varying_parameters + varying_parameter_names = tuple(e[1] for e in varying_parameters) + parameters_to_ignore += kernel_info.temporary_fields + varying_parameter_names + + parameter_list = [] + for param in kernel_info.parameters: + if param.is_field_pointer and param.field_name not in parameters_to_ignore: + parameter_list.append("%sID" % (param.field_name, )) + elif not param.is_field_parameter and param.symbol.name not in parameters_to_ignore: + parameter_list.append(f'{param.symbol.name}_') + varying_parameters = ["%s_" % e for e in varying_parameter_names] + return ", ".join(parameter_list + varying_parameters) + + @jinja2.contextfilter def generate_members(ctx, kernel_info, parameters_to_ignore=(), only_fields=False): ast = kernel_info.ast @@ -382,14 +402,25 @@ def generate_destructor(kernel_info, class_name): return temporary_constructor.format(contents=contents, class_name=class_name) +@jinja2.contextfilter +def nested_class_method_definition_prefix(ctx, nested_class_name): + outer_class = ctx['class_name'] + if len(nested_class_name) == 0: + return outer_class + else: + return outer_class + '::' + nested_class_name + + def add_pystencils_filters_to_jinja_env(jinja_env): jinja_env.filters['generate_definition'] = generate_definition jinja_env.filters['generate_declaration'] = generate_declaration jinja_env.filters['generate_members'] = generate_members jinja_env.filters['generate_constructor_parameters'] = generate_constructor_parameters jinja_env.filters['generate_constructor_initializer_list'] = generate_constructor_initializer_list + jinja_env.filters['generate_constructor_call_arguments'] = generate_constructor_call_arguments jinja_env.filters['generate_call'] = generate_call jinja_env.filters['generate_block_data_to_field_extraction'] = generate_block_data_to_field_extraction jinja_env.filters['generate_swaps'] = generate_swaps jinja_env.filters['generate_refs_for_kernel_parameters'] = generate_refs_for_kernel_parameters jinja_env.filters['generate_destructor'] = generate_destructor + jinja_env.filters['nested_class_method_definition_prefix'] = nested_class_method_definition_prefix diff --git a/python/pystencils_walberla/templates/Boundary.tmpl.cpp b/python/pystencils_walberla/templates/Boundary.tmpl.cpp index 33f799107..ef1ec3b7b 100644 --- a/python/pystencils_walberla/templates/Boundary.tmpl.cpp +++ b/python/pystencils_walberla/templates/Boundary.tmpl.cpp @@ -51,7 +51,11 @@ namespace {{namespace}} { #endif -{{kernel|generate_definition}} +{% for sweep_class, sweep_kernel in sweep_classes.items() %} + +{{sweep_kernel|generate_definition}} + +{% endfor %} #ifdef __GNUC__ #pragma GCC diagnostic pop @@ -61,8 +65,10 @@ namespace {{namespace}} { #pragma pop #endif +{% for sweep_class, sweep_kernel in sweep_classes.items() %} + -void {{class_name}}::run( IBlock * block, IndexVectors::Type type {% if target == 'gpu'%}, cudaStream_t stream {%endif%}) +void {{sweep_class|nested_class_method_definition_prefix}}::run( IBlock * block, IndexVectors::Type type {% if target == 'gpu'%}, cudaStream_t stream {%endif%}) { auto * indexVectors = block->getData<IndexVectors>(indexVectorID); int64_t indexVectorSize = int64_c( indexVectors->indexVector(type).size() ); @@ -77,25 +83,27 @@ void {{class_name}}::run( IBlock * block, IndexVectors::Type type {% if target = uint8_t * _data_indexVector = reinterpret_cast<uint8_t*>(pointer); - {{kernel|generate_block_data_to_field_extraction(['indexVector', 'indexVectorSize'])|indent(4)}} - {{kernel|generate_call(spatial_shape_symbols=['indexVectorSize'], stream='stream')|indent(4)}} + {{sweep_kernel|generate_block_data_to_field_extraction(['indexVector', 'indexVectorSize'])|indent(4)}} + {{sweep_kernel|generate_refs_for_kernel_parameters(prefix='', parameters_to_ignore=['indexVectorSize'], ignore_fields=True)|indent(4) }} + {{sweep_kernel|generate_call(spatial_shape_symbols=['indexVectorSize'], stream='stream')|indent(4)}} } -void {{class_name}}::operator() ( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) +void {{sweep_class|nested_class_method_definition_prefix}}::operator() ( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) { run( block, IndexVectors::ALL{% if target == 'gpu'%}, stream {%endif%}); } -void {{class_name}}::inner( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) +void {{sweep_class|nested_class_method_definition_prefix}}::inner( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) { run( block, IndexVectors::INNER{% if target == 'gpu'%}, stream {%endif%} ); } -void {{class_name}}::outer( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) +void {{sweep_class|nested_class_method_definition_prefix}}::outer( IBlock * block{% if target == 'gpu'%}, cudaStream_t stream {%endif%} ) { run( block, IndexVectors::OUTER{% if target == 'gpu'%}, stream {%endif%} ); } +{% endfor %} } // namespace {{namespace}} } // namespace walberla diff --git a/python/pystencils_walberla/templates/Boundary.tmpl.h b/python/pystencils_walberla/templates/Boundary.tmpl.h index c856adcea..c0a39c32b 100644 --- a/python/pystencils_walberla/templates/Boundary.tmpl.h +++ b/python/pystencils_walberla/templates/Boundary.tmpl.h @@ -17,13 +17,13 @@ //! \\author pystencils //====================================================================================================================== - #include "core/DataTypes.h" {% if target is equalto 'cpu' -%} #include "field/GhostLayerField.h" {%- elif target is equalto 'gpu' -%} #include "cuda/GPUField.h" +#include "cuda/FieldCopy.h" {%- endif %} #include "domain_decomposition/BlockDataID.h" #include "domain_decomposition/IBlock.h" @@ -64,7 +64,7 @@ public: NUM_TYPES = 3 }; - IndexVectors() : cpuVectors_(NUM_TYPES) {} + IndexVectors() = default; bool operator==(IndexVectors & other) { return other.cpuVectors_ == cpuVectors_; } {% if target == 'gpu' -%} @@ -72,14 +72,14 @@ public: for( auto & gpuVec: gpuVectors_) cudaFree( gpuVec ); } - {% endif %} + {% endif -%} CpuIndexVector & indexVector(Type t) { return cpuVectors_[t]; } {{StructName}} * pointerCpu(Type t) { return &(cpuVectors_[t][0]); } {% if target == 'gpu' -%} {{StructName}} * pointerGpu(Type t) { return gpuVectors_[t]; } - {% endif %} + {% endif -%} void syncGPU() { @@ -100,39 +100,66 @@ public: } private: - std::vector<CpuIndexVector> cpuVectors_; + std::vector<CpuIndexVector> cpuVectors_{NUM_TYPES}; {% if target == 'gpu' -%} using GpuIndexVector = {{StructName}} *; std::vector<GpuIndexVector> gpuVectors_; - {% endif %} + {%- endif %} + }; + + {% if multi_sweep %} + {% for sweep_class_name, sweep_kernel_info in sweep_classes.items() %} + class {{sweep_class_name}} + { + public: + {{sweep_class_name}} ( {{sweep_kernel_info|generate_constructor_parameters(['indexVectorSize'])}} ) + : {{ sweep_kernel_info|generate_constructor_initializer_list(['indexVectorSize']) }} {}; + + void operator() ( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + void inner( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + void outer( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + + private: + void run( IBlock * block, IndexVectors::Type type{% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + + {{sweep_kernel_info|generate_members(['indexVectorSize'])|indent(12)}} }; + {{sweep_class_name}} get{{sweep_class_name}} () + { + return {{sweep_class_name}} ( {{sweep_kernel_info|generate_constructor_call_arguments(['indexVectorSize'])|indent(12)}} ); + } + {% endfor %} + {% endif %} {{class_name}}( const shared_ptr<StructuredBlockForest> & blocks, - {{kernel|generate_constructor_parameters(['indexVector', 'indexVectorSize'])}} ) - : {{ kernel|generate_constructor_initializer_list(['indexVector', 'indexVectorSize']) }} + {{dummy_kernel_info|generate_constructor_parameters(['indexVector', 'indexVectorSize'])}}{{additional_data_handler.constructor_arguments}}) + :{{additional_data_handler.initialiser_list}} {{ dummy_kernel_info|generate_constructor_initializer_list(['indexVector', 'indexVectorSize']) }} { auto createIdxVector = []( IBlock * const , StructuredBlockStorage * const ) { return new IndexVectors(); }; indexVectorID = blocks->addStructuredBlockData< IndexVectors >( createIdxVector, "IndexField_{{class_name}}"); }; + {% if not multi_sweep %} + void operator() ( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); void inner( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); void outer( IBlock * block {% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + {% endif %} template<typename FlagField_T> void fillFromFlagField( const shared_ptr<StructuredBlockForest> & blocks, ConstBlockDataID flagFieldID, FlagUID boundaryFlagUID, FlagUID domainFlagUID) { for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) - fillFromFlagField<FlagField_T>( &*blockIt, flagFieldID, boundaryFlagUID, domainFlagUID ); + fillFromFlagField<FlagField_T>({{additional_data_handler.additional_arguments_for_fill_function}}&*blockIt, flagFieldID, boundaryFlagUID, domainFlagUID ); } template<typename FlagField_T> - void fillFromFlagField( IBlock * block, ConstBlockDataID flagFieldID, + void fillFromFlagField({{additional_data_handler.additional_parameters_for_fill_function}}IBlock * block, ConstBlockDataID flagFieldID, FlagUID boundaryFlagUID, FlagUID domainFlagUID ) { auto * indexVectors = block->getData< IndexVectors > ( indexVectorID ); @@ -140,8 +167,8 @@ public: auto & indexVectorInner = indexVectors->indexVector(IndexVectors::INNER); auto & indexVectorOuter = indexVectors->indexVector(IndexVectors::OUTER); - auto * flagField = block->getData< FlagField_T > ( flagFieldID ); + {{additional_data_handler.additional_field_data|indent(4)}} if( !(flagField->flagExists(boundaryFlagUID) && flagField->flagExists(domainFlagUID) )) return; @@ -152,7 +179,6 @@ public: auto inner = flagField->xyzSize(); inner.expand( cell_idx_t(-1) ); - indexVectorAll.clear(); indexVectorInner.clear(); indexVectorOuter.clear(); @@ -161,15 +187,15 @@ public: { if( ! isFlagSet(it, domainFlag) ) continue; - - {%- for dirIdx, dirVec, offset in stencil_info %} + {%- for dirIdx, dirVec, offset in additional_data_handler.stencil_info %} if ( isFlagSet( it.neighbor({{offset}} {%if dim == 3%}, 0 {%endif %}), boundaryFlag ) ) { {% if inner_or_boundary -%} auto element = {{StructName}}(it.x(), it.y(), {%if dim == 3%} it.z(), {%endif %} {{dirIdx}} ); {% else -%} - auto element = {{StructName}}(it.x() + cell_idx_c({{dirVec[0]}}), it.y() + cell_idx_c({{dirVec[1]}}), {%if dim == 3%} it.z() + cell_idx_c({{dirVec[2]}}), {%endif %} {{inverse_directions[dirIdx]}} ); + auto element = {{StructName}}(it.x() + cell_idx_c({{dirVec[0]}}), it.y() + cell_idx_c({{dirVec[1]}}), {%if dim == 3%} it.z() + cell_idx_c({{dirVec[2]}}), {%endif %} {{additional_data_handler.inverse_directions[dirIdx]}} ); {% endif -%} + {{additional_data_handler.data_initialisation(dirIdx)|indent(16)}} indexVectorAll.push_back( element ); if( inner.contains( it.x(), it.y(), it.z() ) ) indexVectorInner.push_back( element ); @@ -178,16 +204,18 @@ public: } {% endfor %} } - indexVectors->syncGPU(); } private: + {% if not multi_sweep %} void run( IBlock * block, IndexVectors::Type type{% if target == 'gpu'%}, cudaStream_t stream = 0 {%endif%}); + {% endif %} BlockDataID indexVectorID; + {{additional_data_handler.additional_member_variable|indent(4)}} public: - {{kernel|generate_members(('indexVector', 'indexVectorSize'))|indent(4)}} + {{dummy_kernel_info|generate_members(('indexVector', 'indexVectorSize'))|indent(4)}} }; diff --git a/python/pystencils_walberla/templates/Sweep.tmpl.cpp b/python/pystencils_walberla/templates/Sweep.tmpl.cpp index b3b12c6b3..b26d9c6db 100644 --- a/python/pystencils_walberla/templates/Sweep.tmpl.cpp +++ b/python/pystencils_walberla/templates/Sweep.tmpl.cpp @@ -59,7 +59,7 @@ void {{class_name}}::operator()( IBlock * block{%if target is equalto 'gpu'%} , { {{kernel|generate_block_data_to_field_extraction|indent(4)}} {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} - {{kernel|generate_call(stream='stream')|indent(4)}} + {{kernel|generate_call(ghost_layers_to_include=ghost_layers_to_include, stream='stream')|indent(4)}} {{kernel|generate_swaps|indent(4)}} } diff --git a/src/lbm/field/QCriterion.h b/src/lbm/field/QCriterion.h index eff9b8015..c68111778 100644 --- a/src/lbm/field/QCriterion.h +++ b/src/lbm/field/QCriterion.h @@ -28,36 +28,40 @@ // You should never use these functions directly, always refer to the member functions // of PdfField or the free functions that can be found in MacroscopicValueCalculation.h -namespace walberla { -namespace lbm { - -struct QCriterion { +namespace walberla +{ +namespace lbm +{ +struct QCriterion +{ template< typename VelocityField_T, typename Filter_T > - static inline real_t get(const VelocityField_T & velocityField, const Filter_T & filter, - const cell_idx_t x, const cell_idx_t y, const cell_idx_t z, - real_t dx = real_t(1), real_t dy = real_t(1), real_t dz = real_t(1)) { + static inline real_t get(const VelocityField_T& velocityField, const Filter_T& filter, const cell_idx_t x, + const cell_idx_t y, const cell_idx_t z, real_t dx = real_t(1), real_t dy = real_t(1), + real_t dz = real_t(1)) + { const auto one = cell_idx_t(1); - if(filter(x,y,z) && filter(x+one,y,z) && filter(x-one,y,z) && filter(x,y+one,z) - && filter(x,y-one,z) && filter(x,y,z+one) && filter(x,y,z-one)) { - const Vector3<real_t> xa = velocityField.get(x+one,y,z); - const Vector3<real_t> xb = velocityField.get(x-one,y,z); - const Vector3<real_t> ya = velocityField.get(x,y+one,z); - const Vector3<real_t> yb = velocityField.get(x,y-one,z); - const Vector3<real_t> za = velocityField.get(x,y,z+one); - const Vector3<real_t> zb = velocityField.get(x,y,z-one); + auto f(velocityField.flattenedShallowCopy()); + + if (filter(x, y, z) && filter(x + one, y, z) && filter(x - one, y, z) && filter(x, y + one, z) && + filter(x, y - one, z) && filter(x, y, z + one) && filter(x, y, z - one)) + { + Vector3< real_t > xa(f->get(x + one, y, z, 0), f->get(x + one, y, z, 1), f->get(x + one, y, z, 2)); + Vector3< real_t > xb(f->get(x - one, y, z, 0), f->get(x - one, y, z, 1), f->get(x - one, y, z, 2)); + Vector3< real_t > ya(f->get(x, y + one, z, 0), f->get(x, y + one, z, 1), f->get(x, y + one, z, 2)); + Vector3< real_t > yb(f->get(x, y - one, z, 0), f->get(x, y - one, z, 1), f->get(x, y - one, z, 2)); + Vector3< real_t > za(f->get(x, y, z + one, 0), f->get(x, y, z + one, 1), f->get(x, y, z + one, 2)); + Vector3< real_t > zb(f->get(x, y, z - one, 0), f->get(x, y, z - one, 1), f->get(x, y, z - one, 2)); return calculate(xa, xb, ya, yb, za, zb, dx, dy, dz); } - return real_t(0); } - static inline real_t calculate(const Vector3<real_t> xa, const Vector3<real_t> xb, - const Vector3<real_t> ya, const Vector3<real_t> yb, - const Vector3<real_t> za, const Vector3<real_t> zb, - const real_t dx, const real_t dy, const real_t dz) { - + static inline real_t calculate(const Vector3< real_t > xa, const Vector3< real_t > xb, const Vector3< real_t > ya, + const Vector3< real_t > yb, const Vector3< real_t > za, const Vector3< real_t > zb, + const real_t dx, const real_t dy, const real_t dz) + { const auto halfInvDx = real_t(0.5) / dx; const auto halfInvDy = real_t(0.5) / dy; const auto halfInvDz = real_t(0.5) / dz; @@ -75,18 +79,17 @@ struct QCriterion { const real_t duzdz = (za[2] - zb[2]) * halfInvDz; // Q = 1/2 * (||W||² - ||S||²) - real_t sNormSq = duxdx*duxdx + duydy*duydy + duzdz*duzdz + - real_t(0.5)*(duxdy+duydx)*(duxdy+duydx) + real_t(0.5)*(duydz+duzdy)*(duydz+duzdy) + - real_t(0.5)*(duxdz+duzdx)*(duxdz+duzdx); + real_t sNormSq = duxdx * duxdx + duydy * duydy + duzdz * duzdz + real_t(0.5) * (duxdy + duydx) * (duxdy + duydx) + + real_t(0.5) * (duydz + duzdy) * (duydz + duzdy) + + real_t(0.5) * (duxdz + duzdx) * (duxdz + duzdx); - real_t omegaNormSq = real_t(0.5)*(duxdz-duzdx)*(duxdz-duzdx) + - real_t(0.5)*(duxdy-duydx)*(duxdy-duydx) + - real_t(0.5)*(duydz-duzdy)*(duydz-duzdy); + real_t omegaNormSq = real_t(0.5) * (duxdz - duzdx) * (duxdz - duzdx) + + real_t(0.5) * (duxdy - duydx) * (duxdy - duydx) + + real_t(0.5) * (duydz - duzdy) * (duydz - duzdy); return real_t(0.5) * (omegaNormSq - sNormSq); } }; - } // namespace lbm } // namespace walberla diff --git a/src/timeloop/SweepTimeloop.cpp b/src/timeloop/SweepTimeloop.cpp index 7fc72a38a..15b407191 100644 --- a/src/timeloop/SweepTimeloop.cpp +++ b/src/timeloop/SweepTimeloop.cpp @@ -54,10 +54,8 @@ void SweepTimeloop::doTimeStep(const Set<SUID> &selectors) } Sweep * selectedSweep = s.sweep.getUnique( selectors + bi->getState() ); - if( !selectedSweep ) - WALBERLA_ABORT("Selecting Sweep " << sweepIt->first << ": " << - "Ambiguous, or no sweep selected. Check your selector " << - selectors + bi->getState() << std::endl << s.sweep); + if (!selectedSweep) + continue; WALBERLA_LOG_PROGRESS_SECTION() { @@ -111,9 +109,7 @@ void SweepTimeloop::doTimeStep(const Set<SUID> &selectors, WcTimingPool &timing) Sweep * selectedSweep = s.sweep.getUnique( selectors + bi->getState(), sweepName ); if( !selectedSweep ) - WALBERLA_ABORT("Selecting Sweep " << sweepIt->first << ": " << - "Ambiguous, or no sweep selected. Check your selector " << - selectors + bi->getState() << std::endl << s.sweep); + continue; WALBERLA_LOG_PROGRESS("Running sweep \"" << sweepName << "\" on block " << bi->getId() ); diff --git a/tests/lbm/CMakeLists.txt b/tests/lbm/CMakeLists.txt index b17f65cfa..a2ddd6690 100644 --- a/tests/lbm/CMakeLists.txt +++ b/tests/lbm/CMakeLists.txt @@ -76,6 +76,21 @@ waLBerla_execute_test( NAME QCriterionTest ) # Code Generation if( WALBERLA_BUILD_WITH_CODEGEN ) +add_subdirectory(codegen) + +waLBerla_generate_target_from_python(NAME GeneratedOutflowBCGenerated + FILE codegen/GeneratedOutflowBC.py + OUT_FILES GeneratedOutflowBC_Sweep.cpp GeneratedOutflowBC_Sweep.h + GeneratedOutflowBC_MacroSetter.cpp GeneratedOutflowBC_MacroSetter.h + GeneratedOutflowBC_Dynamic_UBB.cpp GeneratedOutflowBC_Dynamic_UBB.h + GeneratedOutflowBC_Static_UBB.cpp GeneratedOutflowBC_Static_UBB.h + GeneratedOutflowBC_NoSlip.cpp GeneratedOutflowBC_NoSlip.h + GeneratedOutflowBC_Outflow.cpp GeneratedOutflowBC_Outflow.h + GeneratedOutflowBC_PackInfo.cpp GeneratedOutflowBC_PackInfo.h + GeneratedOutflowBC_InfoHeader.h) +waLBerla_compile_test( FILES codegen/GeneratedOutflowBC.cpp DEPENDS GeneratedOutflowBCGenerated) +waLBerla_execute_test( NAME GeneratedOutflowBC COMMAND $<TARGET_FILE:GeneratedOutflowBC> ${CMAKE_CURRENT_SOURCE_DIR}/codegen/GeneratedOutflowBC.prm ) + waLBerla_generate_target_from_python(NAME LbCodeGenerationExampleGenerated FILE codegen/LbCodeGenerationExample.py @@ -95,4 +110,13 @@ waLBerla_generate_target_from_python(NAME FieldLayoutAndVectorizationTestGenerat FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.cpp FieldLayoutAndVectorizationTest_ZYXF_NoVec_LatticeModel.h ) waLBerla_compile_test( FILES codegen/FieldLayoutAndVectorizationTest.cpp DEPENDS FieldLayoutAndVectorizationTestGenerated) -endif() \ No newline at end of file +waLBerla_generate_target_from_python(NAME LbmPackInfoGenerationTestCodegen FILE codegen/LbmPackInfoGenerationTest.py + OUT_FILES AccessorBasedPackInfoEven.cpp AccessorBasedPackInfoEven.h + AccessorBasedPackInfoOdd.cpp AccessorBasedPackInfoOdd.h + FromKernelPackInfoPull.cpp FromKernelPackInfoPull.h + FromKernelPackInfoPush.cpp FromKernelPackInfoPush.h) + +waLBerla_link_files_to_builddir( "diff_packinfos.sh" ) +waLBerla_execute_test( NAME LbmPackInfoGenerationDiffTest COMMAND bash diff_packinfos.sh ) + +endif() diff --git a/tests/lbm/codegen/CMakeLists.txt b/tests/lbm/codegen/CMakeLists.txt new file mode 100644 index 000000000..b149eda3f --- /dev/null +++ b/tests/lbm/codegen/CMakeLists.txt @@ -0,0 +1,8 @@ +############################################################################################################################# +# +# Tests for lbm module +# +############################################################################################################################# + +waLBerla_link_files_to_builddir( "*.prm" ) +waLBerla_link_files_to_builddir( "ChannelFlowCodeGenParameter.py" ) \ No newline at end of file diff --git a/tests/lbm/codegen/GeneratedOutflowBC.cpp b/tests/lbm/codegen/GeneratedOutflowBC.cpp new file mode 100644 index 000000000..66311c7eb --- /dev/null +++ b/tests/lbm/codegen/GeneratedOutflowBC.cpp @@ -0,0 +1,194 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file GeneratedOutflowBC.cpp +//! \author Markus Holzer <markus.holzer@fau.de> +//! \brief Shear flow with dynamic UBB on the left (W) with linear flow profile from zero to u_max (flow in x-direction) +//! along the y-direction. The upper wall (N) is a static UBB which applies u_max in x-direction. +//! On the right (E) an outflow boundary is used and the lower wall (S) is a No-Slip wall. +//! It is tested if the shear flow is correctly propagated through the entire domain after n timesteps. +// +//====================================================================================================================== +#include "blockforest/Initialization.h" +#include "blockforest/communication/UniformBufferedScheme.h" + +#include "core/Environment.h" +#include "core/timing/RemainingTimeLogger.h" + +#include "field/AddToStorage.h" +#include "field/vtk/VTKWriter.h" + +#include "geometry/InitBoundaryHandling.h" +#include "timeloop/SweepTimeloop.h" + +// Generated Files +#include "GeneratedOutflowBC_Dynamic_UBB.h" +#include "GeneratedOutflowBC_InfoHeader.h" +#include "GeneratedOutflowBC_MacroSetter.h" +#include "GeneratedOutflowBC_NoSlip.h" +#include "GeneratedOutflowBC_Outflow.h" +#include "GeneratedOutflowBC_PackInfo.h" +#include "GeneratedOutflowBC_Static_UBB.h" +#include "GeneratedOutflowBC_Sweep.h" + +using namespace walberla; + +using PackInfo_T = lbm::GeneratedOutflowBC_PackInfo; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField< flag_t >; + +auto pdfFieldAdder = [](IBlock* const block, StructuredBlockStorage* const storage) { + return new PdfField_T(storage->getNumberOfXCells(*block), storage->getNumberOfYCells(*block), + storage->getNumberOfZCells(*block), uint_t(1), field::fzyx, + make_shared< field::AllocateAligned< real_t, 64 > >()); +}; + +//////////////////////////////////////////// +// Linear Velocity Profile for left wall // +////////////////////////////////////////// + +class ShearProfile +{ + public: + + ShearProfile( real_t inflow_velocity ) : + inflow_velocity_( inflow_velocity ) {} + + Vector3< real_t > operator()( const Cell& pos, const shared_ptr< StructuredBlockForest >& SbF, IBlock& block ) const; + + private: + + const real_t inflow_velocity_; +}; // class ShearProfile + +Vector3< real_t > ShearProfile::operator()( const Cell& pos, const shared_ptr< StructuredBlockForest >& SbF, IBlock& block ) const +{ + Cell globalCell; + CellInterval domain = SbF->getDomainCellBB(); + real_t h_y = domain.yMax() - domain.yMin(); + SbF->transformBlockLocalToGlobalCell(globalCell, block, pos); + + real_t u = inflow_velocity_ * (globalCell[1] / h_y); + + Vector3< real_t > result(u, 0.0, 0.0); + return result; +} + +////////// +// MAIN // +////////// + +int main(int argc, char** argv) +{ + walberla::Environment walberlaEnv(argc, argv); + + auto blocks = blockforest::createUniformBlockGridFromConfig(walberlaEnv.config()); + + // read parameters + auto parameters = walberlaEnv.config()->getOneBlock("Parameters"); + + const real_t omega = parameters.getParameter< real_t >("omega", real_c(1.4)); + const real_t u_max = parameters.getParameter< real_t >("u_max", real_t(0.05)); + const uint_t timesteps = parameters.getParameter< uint_t >("timesteps", uint_c(10)); + + const double remainingTimeLoggerFrequency = + parameters.getParameter< double >("remainingTimeLoggerFrequency", 3.0); // in seconds + + // create fields + BlockDataID pdfFieldID = blocks->addStructuredBlockData< PdfField_T >(pdfFieldAdder, "PDFs"); + BlockDataID velFieldID = field::addToStorage< VelocityField_T >(blocks, "velocity", real_t(0), field::fzyx); + BlockDataID densityFieldID = field::addToStorage< ScalarField_T >(blocks, "density", real_t(0), field::fzyx); + + BlockDataID flagFieldId = field::addFlagFieldToStorage< FlagField_T >(blocks, "flag field"); + + pystencils::GeneratedOutflowBC_MacroSetter setterSweep(pdfFieldID, velFieldID); + for (auto& block : *blocks) + setterSweep(&block); + + // create and initialize boundary handling + const FlagUID fluidFlagUID("Fluid"); + + auto boundariesConfig = walberlaEnv.config()->getOneBlock("Boundaries"); + + ShearProfile velocityCallback{u_max}; + std::function< Vector3< real_t >(const Cell&, const shared_ptr< StructuredBlockForest >&, IBlock&) > + velocity_initialisation = velocityCallback; + + lbm::GeneratedOutflowBC_Dynamic_UBB ubb_dynamic(blocks, pdfFieldID, velocity_initialisation); + lbm::GeneratedOutflowBC_Static_UBB ubb_static(blocks, pdfFieldID, u_max); + lbm::GeneratedOutflowBC_NoSlip noSlip(blocks, pdfFieldID); + lbm::GeneratedOutflowBC_Outflow outflow(blocks, pdfFieldID); + + geometry::initBoundaryHandling< FlagField_T >(*blocks, flagFieldId, boundariesConfig); + geometry::setNonBoundaryCellsToDomain< FlagField_T >(*blocks, flagFieldId, fluidFlagUID); + + ubb_dynamic.fillFromFlagField< FlagField_T >(blocks, flagFieldId, FlagUID("UBB_Inflow"), fluidFlagUID); + ubb_static.fillFromFlagField< FlagField_T >(blocks, flagFieldId, FlagUID("UBB_Wall"), fluidFlagUID); + noSlip.fillFromFlagField< FlagField_T >(blocks, flagFieldId, FlagUID("NoSlip"), fluidFlagUID); + outflow.fillFromFlagField< FlagField_T >(blocks, flagFieldId, FlagUID("Outflow"), fluidFlagUID); + + // create time loop + SweepTimeloop timeloop(blocks->getBlockStorage(), timesteps); + + // create communication for PdfField + blockforest::communication::UniformBufferedScheme< Stencil_T > communication(blocks); + communication.addPackInfo(make_shared< PackInfo_T >(pdfFieldID)); + + pystencils::GeneratedOutflowBC_Sweep UpdateSweep(densityFieldID, pdfFieldID, velFieldID, omega); + + // add LBM sweep and communication to time loop + timeloop.add() << BeforeFunction(communication, "communication") << Sweep(noSlip, "noSlip boundary"); + timeloop.add() << Sweep(ubb_dynamic, "ubb inflow"); + timeloop.add() << Sweep(ubb_static, "ubb wall"); + timeloop.add() << Sweep(outflow, "outflow boundary"); + timeloop.add() << Sweep(UpdateSweep, "LB stream & collide"); + + // log remaining time + timeloop.addFuncAfterTimeStep(timing::RemainingTimeLogger(timeloop.getNrOfTimeSteps(), remainingTimeLoggerFrequency), + "remaining time logger"); + + // VTK Writer + uint_t vtkWriteFrequency = parameters.getParameter< uint_t >("vtkWriteFrequency", 0); + if (vtkWriteFrequency > 0) + { + auto vtkOutput = vtk::createVTKOutput_BlockData(*blocks, "GeneratedOutflowBC_VTK", vtkWriteFrequency, 0, false, + "vtk_out", "simulation_step", false, true, true, false, 0); + + auto velWriter = make_shared< field::VTKWriter< VelocityField_T > >(velFieldID, "velocity"); + auto densityWriter = make_shared< field::VTKWriter< ScalarField_T > >(densityFieldID, "density"); + + vtkOutput->addCellDataWriter(velWriter); + vtkOutput->addCellDataWriter(densityWriter); + + timeloop.addFuncBeforeTimeStep(vtk::writeFiles(vtkOutput), "VTK Output"); + } + timeloop.run(); + + CellInterval domain = blocks->getDomainCellBB(); + real_t h_y = domain.yMax() - domain.yMin(); + for (auto& block : *blocks) + { + auto velField = block.getData<VelocityField_T>(velFieldID); + WALBERLA_FOR_ALL_CELLS_XYZ + ( + velField, + Cell globalCell; + blocks->transformBlockLocalToGlobalCell(globalCell, block, Cell(x, y, z)); + WALBERLA_CHECK_FLOAT_EQUAL_EPSILON(velField->get(x, y, z, 0), u_max * (globalCell[1] / h_y), 0.01) + ) + } + + return EXIT_SUCCESS; +} diff --git a/tests/lbm/codegen/GeneratedOutflowBC.prm b/tests/lbm/codegen/GeneratedOutflowBC.prm new file mode 100644 index 000000000..b53043d9b --- /dev/null +++ b/tests/lbm/codegen/GeneratedOutflowBC.prm @@ -0,0 +1,24 @@ + +Parameters +{ + omega 1.8; + timesteps 500; + u_max 0.05; + vtkWriteFrequency 0; + remainingTimeLoggerFrequency 3; // in seconds +} + +DomainSetup +{ + blocks < 1, 1, 1 >; + cellsPerBlock < 30, 30, 1 >; + periodic < 0, 0, 0 >; +} + +Boundaries +{ + Border { direction W; walldistance -1; flag UBB_Inflow; } + Border { direction E; walldistance -1; flag Outflow; } + Border { direction S; walldistance -1; flag NoSlip; } + Border { direction N; walldistance -1; flag UBB_Wall; } +} diff --git a/tests/lbm/codegen/GeneratedOutflowBC.py b/tests/lbm/codegen/GeneratedOutflowBC.py new file mode 100644 index 000000000..59a916fec --- /dev/null +++ b/tests/lbm/codegen/GeneratedOutflowBC.py @@ -0,0 +1,92 @@ +from pystencils.field import fields +from lbmpy.macroscopic_value_kernels import macroscopic_values_setter +from lbmpy.stencils import get_stencil +from lbmpy.creationfunctions import create_lb_method, create_lb_update_rule +from lbmpy.boundaries import NoSlip, UBB, ExtrapolationOutflow +from lbmpy_walberla.additional_data_handler import UBBAdditionalDataHandler, OutflowAdditionalDataHandler +from pystencils_walberla import CodeGeneration, generate_sweep +from lbmpy_walberla import RefinementScaling, generate_boundary, generate_lb_pack_info + +import sympy as sp + +stencil = get_stencil("D2Q9") +q = len(stencil) +dim = len(stencil[0]) + +pdfs, pdfs_tmp = fields(f"pdfs({q}), pdfs_tmp({q}): double[{dim}D]", layout='fzyx') +velocity_field, density_field = fields(f"velocity({dim}), density(1) : double[{dim}D]", layout='fzyx') +omega = sp.Symbol("omega") +u_max = sp.Symbol("u_max") + +output = { + 'density': density_field, + 'velocity': velocity_field +} + +options = {'method': 'cumulant', + 'stencil': stencil, + 'relaxation_rate': omega, + 'galilean_correction': len(stencil) == 27, + 'field_name': 'pdfs', + 'output': output, + 'optimization': {'symbolic_field': pdfs, + 'symbolic_temporary_field': pdfs_tmp, + 'cse_global': False, + 'cse_pdfs': False}} + +method = create_lb_method(**options) + +# getter & setter +setter_assignments = macroscopic_values_setter(method, velocity=velocity_field.center_vector, + pdfs=pdfs, density=1) + +# opt = {'instruction_set': 'sse', 'assume_aligned': True, 'nontemporal': False, 'assume_inner_stride_one': True} + +update_rule = create_lb_update_rule(lb_method=method, **options) + +info_header = f""" +using namespace walberla; +#include "stencil/D{dim}Q{q}.h" +using Stencil_T = walberla::stencil::D{dim}Q{q}; +using PdfField_T = GhostLayerField<real_t, {q}>; +using VelocityField_T = GhostLayerField<real_t, {dim}>; +using ScalarField_T = GhostLayerField<real_t, 1>; + """ + +stencil = method.stencil + +with CodeGeneration() as ctx: + # sweeps + generate_sweep(ctx, 'GeneratedOutflowBC_Sweep', update_rule, field_swaps=[(pdfs, pdfs_tmp)]) + generate_sweep(ctx, 'GeneratedOutflowBC_MacroSetter', setter_assignments) + + # boundaries + ubb_dynamic = UBB(lambda *args: None, dim=dim) + ubb_data_handler = UBBAdditionalDataHandler(stencil, ubb_dynamic) + + if dim == 2: + ubb_static = UBB([sp.Symbol("u_max"), 0]) + else: + ubb_static = UBB([sp.Symbol("u_max"), 0, 0]) + + outflow = ExtrapolationOutflow(stencil[4], method) + outflow_data_handler = OutflowAdditionalDataHandler(stencil, outflow) + + # Dynamic UBB which is used to produce a specific velocity profile at the inflow. + # Note that the additional data handler is needed for that kind of boundary. + generate_boundary(ctx, 'GeneratedOutflowBC_Dynamic_UBB', ubb_dynamic, method, + additional_data_handler=ubb_data_handler) + + # Static UBB which is used to apply a certain velocity u_max at the upper wall in x-direction + generate_boundary(ctx, 'GeneratedOutflowBC_Static_UBB', ubb_static, method) + + generate_boundary(ctx, 'GeneratedOutflowBC_NoSlip', NoSlip(), method) + + generate_boundary(ctx, 'GeneratedOutflowBC_Outflow', outflow, method, + additional_data_handler=outflow_data_handler) + + # communication + generate_lb_pack_info(ctx, 'GeneratedOutflowBC_PackInfo', stencil, pdfs) + + # Info header containing correct template definitions for stencil and field + ctx.write_file("GeneratedOutflowBC_InfoHeader.h", info_header) diff --git a/tests/lbm/codegen/LbmPackInfoGenerationTest.py b/tests/lbm/codegen/LbmPackInfoGenerationTest.py new file mode 100644 index 000000000..5fab9c7ab --- /dev/null +++ b/tests/lbm/codegen/LbmPackInfoGenerationTest.py @@ -0,0 +1,29 @@ +from lbmpy.creationfunctions import create_lb_collision_rule, create_lb_update_rule +from lbmpy.advanced_streaming import Timestep +from lbmpy.stencils import get_stencil +from pystencils_walberla import CodeGeneration, generate_pack_info_from_kernel +from lbmpy_walberla.packinfo import generate_lb_pack_info +from pystencils.field import Field + +with CodeGeneration() as ctx: + streaming_pattern = 'aa' + target = 'cpu' + stencil = get_stencil('D3Q19') + dim = len(stencil[0]) + values_per_cell = len(stencil) + collision_rule = create_lb_collision_rule(method='srt', stencil=stencil) + pdf_field = Field.create_generic('pdfs', dim, index_shape=(values_per_cell,), layout='fzyx') + optimization = { + 'symbolic_field': pdf_field, + 'target': target + } + + # Generate PackInfo specifically for streaming pattern + generate_lb_pack_info(ctx, 'AccessorBasedPackInfo', stencil, pdf_field, + streaming_pattern=streaming_pattern, target=target, namespace='pystencils') + + # Generate reference using the alternating pull/push approach + update_rule_odd = create_lb_update_rule(collision_rule=collision_rule, optimization=optimization, + streaming_pattern=streaming_pattern, timestep=Timestep.ODD) + generate_pack_info_from_kernel(ctx, 'FromKernelPackInfoPull', update_rule_odd, kind='pull', target=target) + generate_pack_info_from_kernel(ctx, 'FromKernelPackInfoPush', update_rule_odd, kind='push', target=target) diff --git a/tests/lbm/diff_packinfos.sh b/tests/lbm/diff_packinfos.sh new file mode 100755 index 000000000..bfa89c5ef --- /dev/null +++ b/tests/lbm/diff_packinfos.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +REGEX='^((#include)|(void)|(uint_t))' +cd default_codegen +diff -u -B <(grep -vP "$REGEX" FromKernelPackInfoPull.cpp) <(grep -vP "$REGEX" AccessorBasedPackInfoEven.cpp) || exit 1 +diff -u -B <(grep -vP "$REGEX" FromKernelPackInfoPush.cpp) <(grep -vP "$REGEX" AccessorBasedPackInfoOdd.cpp) || exit 1 diff --git a/tests/timeloop/CMakeLists.txt b/tests/timeloop/CMakeLists.txt index 265f266fd..862c3b648 100644 --- a/tests/timeloop/CMakeLists.txt +++ b/tests/timeloop/CMakeLists.txt @@ -5,5 +5,5 @@ ################################################################################################### -#waLBerla_compile_test( FILES TimeloopAndSweepRegister.cpp DEPENDS field blockforest ) -#waLBerla_execute_test(NAME TimeloopAndSweepRegister ) +waLBerla_compile_test( FILES TimeloopAndSweepRegister.cpp DEPENDS field blockforest ) +waLBerla_execute_test(NAME TimeloopAndSweepRegister ) diff --git a/tests/timeloop/TimeloopAndSweepRegister.cpp b/tests/timeloop/TimeloopAndSweepRegister.cpp index 028e5fad7..944210821 100644 --- a/tests/timeloop/TimeloopAndSweepRegister.cpp +++ b/tests/timeloop/TimeloopAndSweepRegister.cpp @@ -1,175 +1,129 @@ //====================================================================================================================== // -// This file is part of waLBerla. waLBerla is free software: you can +// This file is part of waLBerla. waLBerla 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 3 of +// License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. -// -// waLBerla 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 +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // //! \file TimeloopAndSweepRegister.cpp //! \ingroup timeloop -//! \author Martin Bauer <martin.bauer@fau.de> +//! \author Markus Holzer <markus.holzer@fau.de> //! \brief test cases that test the registering of Sweeps at timeloop // //====================================================================================================================== -#include "timeloop/SweepTimeloop.h" +#include "blockforest/Initialization.h" + #include "core/DataTypes.h" +#include "core/Environment.h" #include "core/debug/TestSubsystem.h" -#include "core/logging/Logging.h" + +#include "field/Field.h" + +#include "timeloop/SweepTimeloop.h" #include <string> #include <vector> - -using namespace std; using namespace walberla; +using Field_T = Field< uint_t, 1 >; + +auto FieldAdder = [](IBlock* const block, StructuredBlockStorage* const storage) { + return new Field_T(storage->getNumberOfXCells(*block), storage->getNumberOfYCells(*block), + storage->getNumberOfZCells(*block), uint_t(0.0), field::fzyx, + make_shared< field::AllocateAligned< uint_t, 64 > >()); +}; -class GeneralSweep +class Sweep1 { - public: - GeneralSweep(const string & name, vector<string> & vec) - : myName(name), outVec(vec) - {} + public: + Sweep1(BlockDataID fieldID) : fieldID_(fieldID) {} + void operator()(IBlock* block) + { + auto field = block->getData< Field_T >(fieldID_); - void operator() (IBlock * ){ - outVec.push_back(myName); - } + for (auto iter = field->begin(); iter != field->end(); ++iter) + *iter += 1; + } - private: - string myName; - vector<string> & outVec; + private: + BlockDataID fieldID_; }; - -class GeneralFunction +class Sweep2 { - public: - GeneralFunction(const string & name, vector<string> & vec) - : myName(name), outVec(vec) - {} + public: + Sweep2(BlockDataID fieldID) : fieldID_(fieldID) {} - void operator() (){ - outVec.push_back(myName); - } - - private: - string myName; - vector<string> & outVec; -}; + void operator()(IBlock* block) + { + auto field = block->getData< Field_T >(fieldID_); + for (auto iter = field->begin(); iter != field->end(); ++iter) + *iter += 2; + } + private: + BlockDataID fieldID_; +}; -int main() +int main(int argc, char** argv) { debug::enterTestMode(); + mpi::Environment env(argc, argv); - vector<string> expectedSequence; - vector<string> sequence; - - SUID cpuSelect("CPU"); - SUID gpuSelect("GPU"); - - SUID srtSelect("SRT"); - SUID mrtSelect("MRT"); - - - //FIXME put a real test in here - shared_ptr<SweepTimeloop> tl = make_shared<SweepTimeloop>(shared_ptr<BlockStorage>(),100); - - typedef SweepTimeloop::SweepHandle SH; - - SH sweep1 = tl->addSweep( GeneralSweep("CPU1",sequence), cpuSelect); - tl->addSweep(sweep1, GeneralSweep("GPU1",sequence), gpuSelect); - - SH sweep2 = tl->addSweep( GeneralSweep("CPU2",sequence), cpuSelect); - tl->addSweep(sweep2, GeneralSweep("GPU2",sequence), gpuSelect); + std::vector<std::string> expectedSequence; + std::vector<std::string> sequence; + SUID sweepSelect1("Sweep1"); + SUID sweepSelect2("Sweep2"); - tl->addFuncBeforeSweep(sweep1,GeneralFunction("Pre1",sequence)); - tl->addFuncAfterSweep (sweep1,GeneralFunction("Post1",sequence)); + shared_ptr< StructuredBlockForest > blocks = blockforest::createUniformBlockGrid( + uint_c(4), uint_c(2), uint_c(2), uint_c(10), uint_c(10), uint_c(10), real_c(1), false, false, false, false); - tl->addFuncBeforeSweep(sweep2,GeneralFunction("Pre2",sequence)); - tl->addFuncAfterSweep (sweep2,GeneralFunction("Post2",sequence)); + BlockDataID fieldID = blocks->addStructuredBlockData< Field_T >(FieldAdder, "Test Field"); - typedef Timeloop::FctHandle FH; - FH preTs = tl->addFuncBeforeTimeStep( GeneralFunction("PreTimestepCPU",sequence),cpuSelect,srtSelect); - tl->addFuncBeforeTimeStep(preTs, GeneralFunction("PreTimestepGPU",sequence),gpuSelect,srtSelect); - FH postTs = tl->addFuncAfterTimeStep ( GeneralFunction("PostTimestepCPU",sequence),cpuSelect,mrtSelect); - tl->addFuncAfterTimeStep (postTs,GeneralFunction("PostTimestepGPU",sequence),gpuSelect,mrtSelect); + for (auto& block : *blocks) + { + if (block.getAABB().min()[0] < 20) + block.setState(sweepSelect1); + else + block.setState(sweepSelect2); + } + uint_t timesteps = 10; + SweepTimeloop timeloop(blocks->getBlockStorage(), timesteps); - //---------- First Run - CPU Selector --------------------------------------------- + timeloop.add() << Sweep(Sweep1(fieldID), "Sweep 1", sweepSelect1, sweepSelect2); + timeloop.add() << Sweep(Sweep2(fieldID), "Sweep 2", sweepSelect2, sweepSelect1); - expectedSequence.push_back("PreTimestepCPU"); - expectedSequence.push_back("Pre1"); - expectedSequence.push_back("CPU1"); - expectedSequence.push_back("Post1"); - expectedSequence.push_back("Pre2"); - expectedSequence.push_back("CPU2"); - expectedSequence.push_back("Post2"); - expectedSequence.push_back("PostTimestepCPU"); + WcTimingPool timingPool; - tl->singleStep(cpuSelect); - - WALBERLA_CHECK_EQUAL(expectedSequence.size(), sequence.size()); - WALBERLA_CHECK( equal(expectedSequence.begin(),expectedSequence.end(), sequence.begin() ) ); - - expectedSequence.clear(); - sequence.clear(); - - - // ------------ Second Run - GPU Selector ------------------------------------------- - - expectedSequence.push_back("PreTimestepGPU"); - expectedSequence.push_back("Pre1"); - expectedSequence.push_back("GPU1"); - expectedSequence.push_back("Post1"); - expectedSequence.push_back("Pre2"); - expectedSequence.push_back("GPU2"); - expectedSequence.push_back("Post2"); - expectedSequence.push_back("PostTimestepGPU"); - - tl->singleStep(gpuSelect); - - WALBERLA_CHECK_EQUAL(expectedSequence.size(), sequence.size()); - WALBERLA_CHECK( equal(expectedSequence.begin(),expectedSequence.end(), sequence.begin() ) ); - - expectedSequence.clear(); - sequence.clear(); - - - // ------------ Second Run - GPU and SRT ------------------------------------------- - - - expectedSequence.push_back("Pre1"); - expectedSequence.push_back("GPU1"); - expectedSequence.push_back("Post1"); - expectedSequence.push_back("Pre2"); - expectedSequence.push_back("GPU2"); - expectedSequence.push_back("Post2"); - expectedSequence.push_back("PostTimestepGPU"); - - tl->singleStep(gpuSelect + srtSelect); - - WALBERLA_CHECK_EQUAL(expectedSequence.size(), sequence.size()); - WALBERLA_CHECK( equal(expectedSequence.begin(),expectedSequence.end(), sequence.begin() ) ); - - expectedSequence.clear(); - sequence.clear(); - - - return 0; + timeloop.run(timingPool); + for (auto& block : *blocks) + { + auto field = block.getData< Field_T >(fieldID); + if (block.getAABB().min()[0] < 20) + { + for (auto iter = field->begin(); iter != field->end(); ++iter) + WALBERLA_CHECK_EQUAL(*iter, timesteps) + } + else + { + for (auto iter = field->begin(); iter != field->end(); ++iter) + WALBERLA_CHECK_EQUAL(*iter, timesteps * 2) + } + } + + return EXIT_SUCCESS; } - - - -- GitLab From c68ee2f4de47a2da68066ef2ba0ae398ebc36337 Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Fri, 19 Feb 2021 06:41:00 +0100 Subject: [PATCH 66/83] Added more functionality to sphere moving with prescribed velocity benchmark --- .../SphereMovingWithPrescribedVelocity.cpp | 407 +++++++++++++----- 1 file changed, 310 insertions(+), 97 deletions(-) diff --git a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp index 1be5bf122..0e0263ff5 100644 --- a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp +++ b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp @@ -129,7 +129,8 @@ const uint_t FieldGhostLayers = 1; const FlagUID Fluid_Flag( "fluid" ); const FlagUID NoSlip_Flag( "no slip" ); -const FlagUID MO_Flag( "moving obstacle" ); +const FlagUID MO_SBB_Flag( "moving obstacle sbb" ); +const FlagUID MO_CLI_Flag( "moving obstacle cli" ); const FlagUID FormerMO_Flag( "former moving obstacle" ); ///////////////////////////////////// @@ -141,8 +142,9 @@ class MyBoundaryHandling public: using NoSlip_T = lbm::NoSlip< LatticeModel_T, flag_t >; - using MO_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; - using Type = BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_T >; + using MO_SBB_T = lbm_mesapd_coupling::SimpleBB< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using MO_CLI_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using Type = BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_SBB_T, MO_CLI_T >; MyBoundaryHandling( const BlockDataID & flagFieldID, const BlockDataID & pdfFieldID, const BlockDataID & particleFieldID, const shared_ptr<ParticleAccessor_T>& ac) : @@ -161,7 +163,8 @@ public: Type * handling = new Type( "moving obstacle boundary handling", flagField, fluid, NoSlip_T( "NoSlip", NoSlip_Flag, pdfField ), - MO_T( "MO", MO_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ) ); + MO_SBB_T( "SBB", MO_SBB_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ), + MO_CLI_T( "CLI", MO_CLI_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ) ); handling->fillWithDomain( FieldGhostLayers ); @@ -192,7 +195,7 @@ public: const std::string & fileName, bool fileIO, real_t diameter, real_t velocity, real_t forceMag) : ac_( ac ), sphereUid_( sphereUid ), fileName_( fileName ), fileIO_(fileIO), - diameter_( diameter ), velocity_(velocity), forceMag_( forceMag ), + diameter_( diameter ), velocityRef_(velocity), forceMag_( forceMag ), position_( real_t(0) ) { if ( fileIO_ ) @@ -201,7 +204,7 @@ public: { std::ofstream file; file.open( fileName_.c_str() ); - file << "#\t t\t posZ\t posZ/D\t fZ\t fZ/fSt\n"; + file << "#\t t\t posZ\t posZ/D\t velZ\t velZ/velRef\t fZ\t fZ/fSt\n"; file.close(); } } @@ -210,6 +213,7 @@ public: void operator()() { real_t pos(real_t(0)); + real_t vel(real_t(0)); real_t hydForce(real_t(0)); size_t idx = ac_->uidToIdx(sphereUid_); @@ -218,6 +222,7 @@ public: if(!mesa_pd::data::particle_flags::isSet( ac_->getFlags(idx), mesa_pd::data::particle_flags::GHOST)) { pos = ac_->getPosition(idx)[2]; + vel = ac_->getLinearVelocity(idx)[2]; hydForce = ac_->getHydrodynamicForce(idx)[2]; } } @@ -225,10 +230,12 @@ public: WALBERLA_MPI_SECTION() { mpi::allReduceInplace( pos, mpi::SUM ); + mpi::allReduceInplace( vel, mpi::SUM ); mpi::allReduceInplace( hydForce, mpi::SUM ); } position_ = pos; + velocity_ = vel; hydForce_ = hydForce; } @@ -238,7 +245,12 @@ public: return position_; } - void writeToFile( const uint_t timestep, real_t density1, real_t density2, real_t totalMass ) + real_t getForce() const + { + return hydForce_; + } + + void writeToFile( const uint_t timestep, real_t density1, real_t density2, real_t totalMass, uint_t countSolidCells, uint_t countFluidSolidLinks, Vector3<real_t> fluidVelocity ) { WALBERLA_ROOT_SECTION() { @@ -249,10 +261,13 @@ public: auto normalizedHydForce = hydForce_ / std::abs(forceMag_); file << std::setprecision(10) - << timestep << "\t" << real_c(timestep) / (diameter_ / velocity_) << "\t" + << timestep << "\t" << real_c(timestep) / (diameter_ / velocityRef_) << "\t" << "\t" << position_ << "\t" << scaledPosition + << "\t" << velocity_ << "\t" << velocity_ / velocityRef_ << "\t" << hydForce_ << "\t" << normalizedHydForce << "\t" << density1 << "\t" << density2 << "\t" << totalMass + << "\t" << countSolidCells << "\t" << countFluidSolidLinks + << "\t" << fluidVelocity[0] << "\t" << fluidVelocity[1] << "\t" << fluidVelocity[2] << "\n"; file.close(); } @@ -263,19 +278,20 @@ private: const walberla::id_t sphereUid_; std::string fileName_; bool fileIO_; - real_t diameter_, velocity_, forceMag_; + real_t diameter_, velocityRef_, forceMag_; - real_t position_, hydForce_; + real_t position_, velocity_, hydForce_; }; -void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, const math::AABB & simulationDomain) +void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, const math::AABB & simulationDomain, real_t velocity = real_t(0)) { mesa_pd::data::Particle p2 = *ps->create(true); p2.setPosition(simulationDomain.minCorner()); p2.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(1,0,0) )); p2.setOwner(mpi::MPIManager::instance()->rank()); p2.setType(0); + p2.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),velocity)); mesa_pd::data::particle_flags::set(p2.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); mesa_pd::data::particle_flags::set(p2.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); @@ -284,6 +300,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con p3.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(-1,0,0) )); p3.setOwner(mpi::MPIManager::instance()->rank()); p3.setType(0); + p3.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),velocity)); mesa_pd::data::particle_flags::set(p3.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); mesa_pd::data::particle_flags::set(p3.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); @@ -292,6 +309,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con p4.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,1,0) )); p4.setOwner(mpi::MPIManager::instance()->rank()); p4.setType(0); + p4.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),velocity)); mesa_pd::data::particle_flags::set(p4.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); mesa_pd::data::particle_flags::set(p4.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); @@ -300,6 +318,7 @@ void createPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, con p5.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,-1,0) )); p5.setOwner(mpi::MPIManager::instance()->rank()); p5.setType(0); + p5.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),velocity)); mesa_pd::data::particle_flags::set(p5.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); mesa_pd::data::particle_flags::set(p5.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); @@ -324,6 +343,27 @@ real_t getDensityAtPosition(const shared_ptr<StructuredBlockStorage> & blocks, B return density; } +template< typename VelocityInterpolator_T> +Vector3<real_t> getVelocityAtPosition(const shared_ptr<StructuredBlockStorage> & blocks, BlockDataID velocityInterpolatorID, Vector3<real_t> position) +{ + + Vector3<real_t> vel(real_t(0)); + for( auto & block: *blocks) + { + if(block.getAABB().contains(position)) + { + auto velocityInterpolator = block.getData<VelocityInterpolator_T>(velocityInterpolatorID); + velocityInterpolator->get(position, &vel); + } + + } + mpi::reduceInplace(vel[0], mpi::SUM); + mpi::reduceInplace(vel[1], mpi::SUM); + mpi::reduceInplace(vel[2], mpi::SUM); + + return vel; +} + template< typename BoundaryHandling_T> real_t getAverageDensityInSystem(const shared_ptr<StructuredBlockStorage> & blocks, BlockDataID pdfFieldID, BlockDataID boundaryHandlingID) { @@ -348,6 +388,41 @@ real_t getAverageDensityInSystem(const shared_ptr<StructuredBlockStorage> & bloc return totalMass/real_c(count); } +template< typename BoundaryHandling_T> +void evaluateMapping(const shared_ptr<StructuredBlockStorage> & blocks, BlockDataID boundaryHandlingID, + uint_t & countSolidCells, uint_t & countFluidSolidLinks) +{ + countSolidCells = uint_t(0); + countFluidSolidLinks = uint_t(0); + for( auto & block: *blocks) + { + auto boundaryHandling = block.getData<BoundaryHandling_T>(boundaryHandlingID); + auto flagField = boundaryHandling->getFlagField(); + //auto innerDomain = flagField->xyzSize(); + WALBERLA_FOR_ALL_CELLS_XYZ(flagField, + if(!boundaryHandling->isDomain(x,y,z) ) + { + ++countSolidCells; + } else + { + for( auto neighborDir = stencil::D3Q27::beginNoCenter(); neighborDir != stencil::D3Q27::end(); ++neighborDir ) + { + Cell neighbor( x + neighborDir.cx(), y + neighborDir.cy(), z + neighborDir.cz() ); + + // check if neighbor cell is a solid cell + if( !boundaryHandling->isDomain( neighbor ) ) + { + ++countFluidSolidLinks; + } + } + } + ); + } + + mpi::reduceInplace(countSolidCells, mpi::SUM); + mpi::reduceInplace(countFluidSolidLinks, mpi::SUM); +} + ////////// // MAIN // ////////// @@ -389,13 +464,15 @@ int main( int argc, char **argv ) std::string baseFolder = "vtk_out_MovingWithPrescribedVelocity"; std::string fileNameEnding = ""; bool logDensity = true; + bool logMapping= true; + bool logFluidVelocity = true; bool vtkOutputAtEnd = true; //numerical parameters - bool averageForceTorqueOverTwoTimeSteps = true; bool conserveMomentum = false; - uint_t numRPDSubCycles = uint_t(1); std::string reconstructorType = "Grad"; // Eq, EAN, Ext, Grad + std::string forceTorqueAveragingType = "runningAvg"; // noAvg, runningAvg, twoLBM, + std::string boundaryCondition = "CLI"; // SBB, CLI real_t bulkViscRateFactor = real_t(1); real_t magicNumber = real_t(0.1875); bool useOmegaBulkAdaption = false; @@ -409,21 +486,27 @@ int main( int argc, char **argv ) real_t velocity = real_t(0.02); real_t Re = real_t(164); real_t diameter = real_t(20); - real_t numberOfPasses = real_t(3); + real_t numberOfTimeStepsNonDim = real_t(20); real_t domainWidthNonDim = real_t(4); real_t domainHeightNonDim = real_t(8); + real_t accelerationFactor = real_t(3); bool usePeriodicSetup = false; bool artificiallyAccelerateSphere = false; + bool fixedSphere = false; + + bool useGalileanInvariantSetup = false; for( int i = 1; i < argc; ++i ) { if( std::strcmp( argv[i], "--funcTest" ) == 0 ) { funcTest = true; continue; } if( std::strcmp( argv[i], "--noLogging" ) == 0 ) { fileIO = false; continue; } if( std::strcmp( argv[i], "--noVtkOutputAtEnd" ) == 0 ) { vtkOutputAtEnd = false; continue; } - if( std::strcmp( argv[i], "--logDensity" ) == 0 ) { logDensity = true; continue; } + if( std::strcmp( argv[i], "--noLogDensity" ) == 0 ) { logDensity = false; continue; } + if( std::strcmp( argv[i], "--noLogMapping" ) == 0 ) { logMapping = false; continue; } + if( std::strcmp( argv[i], "--noLogFluidVelocity" ) == 0 ) { logFluidVelocity = false; continue; } if( std::strcmp( argv[i], "--vtkIOFreq" ) == 0 ) { vtkIOFreq = uint_c( std::atof( argv[++i] ) ); continue; } - if( std::strcmp( argv[i], "--numRPDSubCycles" ) == 0 ) { numRPDSubCycles = uint_c( std::atof( argv[++i] ) ); continue; } - if( std::strcmp( argv[i], "--noForceAveraging" ) == 0 ) { averageForceTorqueOverTwoTimeSteps = false; continue; } + if( std::strcmp( argv[i], "--averagingType" ) == 0 ) { forceTorqueAveragingType = argv[++i]; continue; } + if( std::strcmp( argv[i], "--boundaryCondition" ) == 0 ) { boundaryCondition = argv[++i]; continue; } if( std::strcmp( argv[i], "--conserveMomentum" ) == 0 ) { conserveMomentum = true; continue; } if( std::strcmp( argv[i], "--baseFolder" ) == 0 ) { baseFolder = argv[++i]; continue; } if( std::strcmp( argv[i], "--reconstructorType" ) == 0 ) { reconstructorType = argv[++i]; continue; } @@ -437,16 +520,24 @@ int main( int argc, char **argv ) if( std::strcmp( argv[i], "--fileName" ) == 0 ) { fileNameEnding = argv[++i]; continue; } if( std::strcmp( argv[i], "--useOmegaBulkAdaption" ) == 0 ) { useOmegaBulkAdaption = true; continue; } if( std::strcmp( argv[i], "--adaptionLayerSize" ) == 0 ) { adaptionLayerSize = real_c(std::atof( argv[++i] )); continue; } - if( std::strcmp( argv[i], "--numberOfPasses" ) == 0 ) { numberOfPasses = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--numberOfTimeStepsNonDim" ) == 0 ) { numberOfTimeStepsNonDim = real_c(std::atof( argv[++i] )); continue; } if( std::strcmp( argv[i], "--initialSpherePosition" )== 0 ) { initialSpherePosition = real_c(std::atof( argv[++i] )); continue; } if( std::strcmp( argv[i], "--usePeriodicSetup" ) == 0 ) { usePeriodicSetup = true; continue; } if( std::strcmp( argv[i], "--artificiallyAccelerateSphere" ) == 0 ) { artificiallyAccelerateSphere = true; continue; } + if( std::strcmp( argv[i], "--accelerationFactor" ) == 0 ) { accelerationFactor = real_c(std::atof( argv[++i] )); continue; } if( std::strcmp( argv[i], "--blocksInX" ) == 0 ) { blocksInX = uint_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--blocksInY" ) == 0 ) { blocksInY = uint_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--blocksInZ" ) == 0 ) { blocksInZ = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--useGalileanInvariantSetup" ) == 0 ) { useGalileanInvariantSetup = true; continue; } + if( std::strcmp( argv[i], "--fixedSphere" ) == 0 ) { fixedSphere = true; continue; } WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); } + if(forceTorqueAveragingType != "noAvg" && forceTorqueAveragingType != "runningAvg" && forceTorqueAveragingType != "twoLBM") + { + WALBERLA_ABORT("Averaging type not implemented: " << forceTorqueAveragingType); + } + if( funcTest ) { walberla::logging::Logging::instance()->setLogLevel(logging::Logging::LogLevel::WARNING); @@ -468,24 +559,33 @@ int main( int argc, char **argv ) const real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); const real_t relaxationTime = real_t(1) / omega; const real_t omegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, bulkViscRateFactor); + const real_t tref = diameter / velocity; const Vector3<uint_t> domainSize( uint_c(domainWidthNonDim * diameter), uint_c(domainWidthNonDim * diameter), uint_c(domainHeightNonDim * diameter) ); WALBERLA_LOG_INFO_ON_ROOT("Setup (in simulation, i.e. lattice, units):"); WALBERLA_LOG_INFO_ON_ROOT(" - domain size = " << domainSize); WALBERLA_LOG_INFO_ON_ROOT(" - Re = " << Re); + WALBERLA_LOG_INFO_ON_ROOT(" - tref = " << tref); + WALBERLA_LOG_INFO_ON_ROOT(" - acceleration factor (a_acc) = " << accelerationFactor); WALBERLA_LOG_INFO_ON_ROOT(" - sphere: diameter = " << diameter << ", constant velocity = " << velocity ); - WALBERLA_LOG_INFO_ON_ROOT(" - relaxation time (tau) = " << relaxationTime << ", omega = " << omega << " kin. visc = " << viscosity ); + WALBERLA_LOG_INFO_ON_ROOT(" - relaxation time (tau) = " << relaxationTime << ", omega = " << omega << ", kin. visc = " << viscosity ); WALBERLA_LOG_INFO_ON_ROOT(" - magic number " << magicNumber); WALBERLA_LOG_INFO_ON_ROOT(" - omegaBulk = " << omegaBulk << ", bulk visc. = " << lbm_mesapd_coupling::bulkViscosityFromOmegaBulk(omegaBulk) << " (bvrf " << bulkViscRateFactor << ")"); WALBERLA_LOG_INFO_ON_ROOT(" - use omega bulk adaption = " << useOmegaBulkAdaption << " (adaption layer size = " << adaptionLayerSize << ")"); WALBERLA_LOG_INFO_ON_ROOT(" - reconstructor type = " << reconstructorType ); - if( vtkIOFreq > 0 ) - { - WALBERLA_LOG_INFO_ON_ROOT(" - writing vtk files to folder \"" << baseFolder << "\" with frequency " << vtkIOFreq); + if( vtkIOFreq > 0 ) WALBERLA_LOG_INFO_ON_ROOT(" - writing vtk files to folder \"" << baseFolder << "\" with frequency " << vtkIOFreq); + if( useGalileanInvariantSetup ) { + WALBERLA_LOG_INFO_ON_ROOT("ATTENTION: Using Galilean Invariant Setup = Moving side walls, fixed sphere"); + artificiallyAccelerateSphere = false; + usePeriodicSetup = false; + conserveMomentum = false; + fixedSphere = true; + } + /////////////////////////// // BLOCK STRUCTURE SETUP // /////////////////////////// @@ -530,6 +630,7 @@ int main( int argc, char **argv ) // bounding planes if(!usePeriodicSetup) createPlaneSetup(ps,ss,blocks->getDomain()); + if(useGalileanInvariantSetup) createPlaneSetup(ps,ss,blocks->getDomain(),-velocity); // create sphere and store Uid Vector3<real_t> initialPosition( real_t(0.5) * real_c(domainSize[0]), real_t(0.5) * real_c(domainSize[1]), initialSpherePosition * real_c(domainSize[2])); @@ -544,7 +645,7 @@ int main( int argc, char **argv ) p.setInteractionRadius(diameter * real_t(0.5)); p.setOwner(mpi::MPIManager::instance()->rank()); p.setShapeID(sphereShape); - p.setLinearVelocity(Vector3<real_t>(0.0,0.0,velocity)); + if(!useGalileanInvariantSetup && !artificiallyAccelerateSphere) p.setLinearVelocity(Vector3<real_t>(real_t(0),real_t(0),velocity)); sphereUid = p.getUid(); } mpi::allReduceInplace(sphereUid, mpi::SUM); @@ -569,7 +670,8 @@ int main( int argc, char **argv ) // add PDF field BlockDataID pdfFieldID = lbm::addPdfFieldToStorage< LatticeModel_T >( blocks, "pdf field (fzyx)", latticeModel, - Vector3< real_t >( real_t(0) ), real_t(1), + useGalileanInvariantSetup ? Vector3<real_t>(real_t(0), real_t(0), -velocity) : Vector3< real_t >( real_t(0)), + real_t(1), uint_t(1), field::fzyx ); // add flag field BlockDataID flagFieldID = field::addFlagFieldToStorage<FlagField_T>( blocks, "flag field" ); @@ -584,9 +686,13 @@ int main( int argc, char **argv ) // interpolation functionality using DensityAdaptor_T = typename lbm::Adaptor< LatticeModel_T >::Density; BlockDataID densityAdaptorID = field::addFieldAdaptor< DensityAdaptor_T >( blocks, pdfFieldID, "density adaptor" ); + using VelocityAdaptor_T = typename lbm::Adaptor< LatticeModel_T >::VelocityVector; + BlockDataID velocityAdaptorID = field::addFieldAdaptor< VelocityAdaptor_T >( blocks, pdfFieldID, "velocity adaptor" ); using DensityInterpolator_T = typename field::TrilinearFieldInterpolator<DensityAdaptor_T, FlagField_T>; BlockDataID densityInterpolatorID = field::addFieldInterpolator< DensityInterpolator_T, FlagField_T >( blocks, densityAdaptorID, flagFieldID, Fluid_Flag ); + using VelocityInterpolator_T = typename field::TrilinearFieldInterpolator<VelocityAdaptor_T, FlagField_T>; + BlockDataID velocityInterpolatorID = field::addFieldInterpolator< VelocityInterpolator_T, FlagField_T >( blocks, velocityAdaptorID, flagFieldID, Fluid_Flag ); // set up RPD functionality std::function<void(void)> syncCall = [ps,rpdDomain, adaptionLayerSize ](){ @@ -597,7 +703,6 @@ int main( int argc, char **argv ) syncCall(); - mesa_pd::kernel::ExplicitEuler explEulerIntegrator(real_t(1)/real_t(numRPDSubCycles)); mesa_pd::mpi::ReduceProperty reduceProperty; @@ -615,10 +720,18 @@ int main( int argc, char **argv ) /////////////// // map planes into the LBM simulation -> act as no-slip boundaries - ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, particleMappingKernel, *accessor, NoSlip_Flag); + //ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, particleMappingKernel, *accessor, NoSlip_Flag); // map particles into the LBM simulation - ps->forEachParticle(false, sphereSelector, *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + if(boundaryCondition == "SBB") + { + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, movingParticleMappingKernel, *accessor, MO_SBB_Flag); + } else if(boundaryCondition == "CLI") + { + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, movingParticleMappingKernel, *accessor, MO_CLI_Flag); + } else{ + WALBERLA_ABORT("Unknown boundary condition " << boundaryCondition); + } // setup of the LBM communication for synchronizing the pdf field between neighboring blocks @@ -631,7 +744,10 @@ int main( int argc, char **argv ) // create the timeloop - const uint_t timesteps = uint_c(numberOfPasses * real_c(domainSize[2]) / velocity); + real_t dtSim = real_t(1); + if (forceTorqueAveragingType == "twoLBM") dtSim = real_t(2); + + const uint_t timesteps = uint_t( numberOfTimeStepsNonDim * tref); WALBERLA_LOG_INFO_ON_ROOT("Running for " << timesteps << " time steps"); SweepTimeloop timeloop( blocks->getBlockStorage(), timesteps ); @@ -645,6 +761,7 @@ int main( int argc, char **argv ) auto particleVtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); particleVtkOutput->addOutput<mesa_pd::data::SelectParticleOwner>("owner"); particleVtkOutput->addOutput<mesa_pd::data::SelectParticleLinearVelocity>("velocity"); + particleVtkOutput->setParticleSelector( [sphereShape](const mesa_pd::data::ParticleStorage::iterator& pIt) {return pIt->getShapeID() == sphereShape;} ); //limit output to sphere auto particleVtkWriter = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles", vtkIOFreq, baseFolder, "simulation_step"); timeloop.addFuncBeforeTimeStep( vtk::writeFiles( particleVtkWriter ), "VTK (sphere data)" ); @@ -667,37 +784,86 @@ int main( int argc, char **argv ) } + // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) + auto bhSweep = BoundaryHandling_T::getBlockSweep( boundaryHandlingID ); + timeloop.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) + << Sweep(bhSweep, "Boundary Handling" ); + + // stream + collide LBM step +#ifdef WALBERLA_BUILD_WITH_CODEGEN + auto lbmSweep = LatticeModel_T::Sweep( pdfFieldID ); + //timeloop.add() << Sweep( [&lbmSweep](IBlock * const block){lbmSweep.streamCollide(block);}, "LB sweep" ); + timeloop.add() << Sweep(lbmSweep, "LB sweep" ); +#else + auto lbmSweep = lbm::makeCellwiseSweep< LatticeModel_T, FlagField_T >( pdfFieldID, flagFieldID, Fluid_Flag ); + timeloop.add() << Sweep( makeSharedSweep( lbmSweep ), "cell-wise LB sweep" ); +#endif + + + SweepTimeloop timeloopAfterParticles( blocks->getBlockStorage(), timesteps ); + // sweep for updating the particle mapping into the LBM simulation - timeloop.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T, BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MO_Flag, FormerMO_Flag, sphereSelector, conserveMomentum), "Particle Mapping" ); + if(boundaryCondition == "SBB") + { + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T, BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MO_SBB_Flag, FormerMO_Flag, sphereSelector, conserveMomentum), "Particle Mapping" ); + + } else if(boundaryCondition == "CLI") + { + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T, BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MO_CLI_Flag, FormerMO_Flag, sphereSelector, conserveMomentum), "Particle Mapping" ); + } else{ + WALBERLA_ABORT("Unknown boundary condition " << boundaryCondition); + } + bool useValuesFromGhostLayerForReconstruction = true; // true: full sync needed // sweep for restoring PDFs in cells previously occupied by particles if( reconstructorType == "EAN") { - auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); - auto equilibriumAndNonEquilibriumSphereNormalReconstructor = lbm_mesapd_coupling::makeEquilibriumAndNonEquilibriumReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); + //auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); + auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::FlagFieldNormalExtrapolationDirectionFinder<BoundaryHandling_T> >(blocks,boundaryHandlingID); + auto equilibriumAndNonEquilibriumSphereNormalReconstructor = lbm_mesapd_coupling::makeEquilibriumAndNonEquilibriumReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), useValuesFromGhostLayerForReconstruction); auto reconstructionManager = lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, equilibriumAndNonEquilibriumSphereNormalReconstructor, conserveMomentum); - timeloop.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) - << Sweep( makeSharedSweep(reconstructionManager), "PDF Restore" ); + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(reconstructionManager), "PDF Restore" ); } else if( reconstructorType == "Grad") { bool recomputeDensity = false; - auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, recomputeDensity, true, true); + bool useCentralDifferences = true; + auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, recomputeDensity, useCentralDifferences, useValuesFromGhostLayerForReconstruction); + + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, gradReconstructor, conserveMomentum) ), "PDF Restore" ); + } else if( reconstructorType == "GradDen") + { + bool recomputeDensity = true; + bool useCentralDifferences = true; + auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, recomputeDensity, useCentralDifferences, useValuesFromGhostLayerForReconstruction); - timeloop.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) - << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, gradReconstructor, conserveMomentum) ), "PDF Restore" ); + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, gradReconstructor, conserveMomentum) ), "PDF Restore" ); } else if( reconstructorType == "Eq") { - timeloop.add() << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, conserveMomentum) ), "PDF Restore" ); + auto eqReconstructor = lbm_mesapd_coupling::makeEquilibriumReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, useValuesFromGhostLayerForReconstruction); + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, eqReconstructor, conserveMomentum) ), "PDF Restore" ); } else if( reconstructorType == "Ext") { - auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); - auto extrapolationReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T, lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder, true>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); - timeloop.add() << BeforeFunction( fullPDFCommunicationScheme, "LBM Communication" ) - << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, extrapolationReconstructor, conserveMomentum)), "PDF Restore" ); - } else { + // gets easily unstable + //auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); + auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::FlagFieldNormalExtrapolationDirectionFinder<BoundaryHandling_T> >(blocks,boundaryHandlingID); + auto extrapolationReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T, lbm_mesapd_coupling::FlagFieldNormalExtrapolationDirectionFinder<BoundaryHandling_T>, false>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), useValuesFromGhostLayerForReconstruction); + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "LBM Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, extrapolationReconstructor, conserveMomentum)), "PDF Restore" ); + } else if( reconstructorType == "ExtNS") + { + //auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); + auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::FlagFieldNormalExtrapolationDirectionFinder<BoundaryHandling_T> >(blocks,boundaryHandlingID); + auto extrapolationReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T, lbm_mesapd_coupling::FlagFieldNormalExtrapolationDirectionFinder<BoundaryHandling_T>, true>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), useValuesFromGhostLayerForReconstruction); + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "LBM Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, extrapolationReconstructor, conserveMomentum)), "PDF Restore" ); + }else { WALBERLA_ABORT("Unknown reconstructor type " << reconstructorType); } @@ -707,35 +873,37 @@ int main( int argc, char **argv ) using OmegaBulkAdapter_T = lbm_mesapd_coupling::OmegaBulkAdapter<ParticleAccessor_T, decltype(sphereSelector)>; real_t defaultOmegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, real_t(1)); shared_ptr<OmegaBulkAdapter_T> omegaBulkAdapter = make_shared<OmegaBulkAdapter_T>(blocks, omegaBulkFieldID, accessor, defaultOmegaBulk, omegaBulk, adaptionLayerSize, sphereSelector); - timeloop.add() << Sweep( makeSharedSweep(omegaBulkAdapter), "Omega Bulk Adapter"); + timeloopAfterParticles.add() << Sweep( makeSharedSweep(omegaBulkAdapter), "Omega Bulk Adapter"); + // initally adapt + for (auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) { + (*omegaBulkAdapter)(blockIt.get()); + } } - // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) - auto bhSweep = BoundaryHandling_T::getBlockSweep( boundaryHandlingID ); - timeloop.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) - << Sweep(bhSweep, "Boundary Handling" ); - - // stream + collide LBM step -#ifdef WALBERLA_BUILD_WITH_CODEGEN - auto lbmSweep = LatticeModel_T::Sweep( pdfFieldID ); - timeloop.add() << Sweep( lbmSweep, "LB sweep" ); -#else - auto lbmSweep = lbm::makeCellwiseSweep< LatticeModel_T, FlagField_T >( pdfFieldID, flagFieldID, Fluid_Flag ); - timeloop.add() << Sweep( makeSharedSweep( lbmSweep ), "cell-wise LB sweep" ); -#endif - // evaluation functionality - std::string loggingFileName( baseFolder + "/LoggingPrescribedMovingSphere"); - loggingFileName += "_Re" + std::to_string(uint_c(Re)); - loggingFileName += "_D" + std::to_string(uint_c(diameter)); - loggingFileName += "_vel" + std::to_string(float(velocity)); - loggingFileName += "_recon" + reconstructorType; - loggingFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); - loggingFileName += "_mn" + std::to_string(float(magicNumber)); - if( useOmegaBulkAdaption ) loggingFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); - if( conserveMomentum ) loggingFileName += "_conserveMomentum"; - if( artificiallyAccelerateSphere ) loggingFileName += "_acc"; - if( !fileNameEnding.empty()) loggingFileName += "_" + fileNameEnding; + std::string fileNamePostFix(""); + fileNamePostFix += "_Re" + std::to_string(uint_c(Re)); + fileNamePostFix += "_D" + std::to_string(uint_c(diameter)); + fileNamePostFix += "_vel" + std::to_string(float(velocity)); + fileNamePostFix += "_" + boundaryCondition; + fileNamePostFix += "_recon" + reconstructorType; + fileNamePostFix += "_" + forceTorqueAveragingType; + fileNamePostFix += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); + //fileNamePostFix += "_mn" + std::to_string(float(magicNumber)); + if( useOmegaBulkAdaption ) fileNamePostFix += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); + + if( useGalileanInvariantSetup ) + { + fileNamePostFix += "_galileanInvariant"; + } + else{ + if( conserveMomentum ) fileNamePostFix += "_conserveMomentum"; + if( artificiallyAccelerateSphere ) fileNamePostFix += "_acc"; + if( fixedSphere ) fileNamePostFix += "_fixed"; + } + if( !fileNameEnding.empty()) fileNamePostFix += "_" + fileNameEnding; + + std::string loggingFileName( baseFolder + "/Log" + fileNamePostFix); loggingFileName += ".txt"; if( fileIO ) @@ -753,43 +921,41 @@ int main( int argc, char **argv ) const bool useOpenMP = false; - const real_t densityRatio = real_t(7800) / real_t(935); - const real_t responseTime = densityRatio * diameter * diameter / ( real_t(18) * viscosity ); - WALBERLA_LOG_INFO_ON_ROOT(" - response time " << responseTime); - const real_t accelerationFactor = real_t(1) / (real_t(0.1) * responseTime); + mesa_pd::kernel::ExplicitEuler explEulerIntegrator(dtSim); + lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; // time loop - for (uint_t i = 0; i < timesteps; ++i ) + for (uint_t i = 0; i < uint_c(real_c(timesteps)/dtSim); ++i ) { // perform a single simulation step -> this contains LBM and setting of the hydrodynamic interactions timeloop.singleStep( timeloopTiming ); - timeloopTiming["RPD"].start(); - - reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); - - if( averageForceTorqueOverTwoTimeSteps ) + if( forceTorqueAveragingType == "twoLBM") { - if( i == 0 ) - { - lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; - ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); - } - ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor ); - } + // store current force and torque in fOld and tOld + ps->forEachParticle(useOpenMP, sphereSelector, *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); - reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); - - ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, explEulerIntegrator, *accessor); - syncCall(); + // reset f and t + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); - timeloopTiming["RPD"].end(); + timeloop.singleStep( timeloopTiming ); - if( artificiallyAccelerateSphere ) + // f = (f+fOld)/2 + ps->forEachParticle(useOpenMP, sphereSelector, *accessor, averageHydrodynamicForceTorque, *accessor ); + + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + } else { - // accelerating after reading from a checkpoint file does not make sense, as current actual runtime is not known - real_t newSphereVel = velocity * (std::exp(-accelerationFactor * real_t(i) ) - real_t(1)); - ps->forEachParticle(useOpenMP, sphereSelector, *accessor, [newSphereVel](const size_t idx, ParticleAccessor_T& ac){ ac.setLinearVelocity(idx, Vector3<real_t>(real_t(0), real_t(0), newSphereVel));}, *accessor); + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + + if( forceTorqueAveragingType == "runningAvg" ) + { + if( i == 0 ) + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); + } + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor ); + } } // evaluation @@ -797,28 +963,68 @@ int main( int argc, char **argv ) logger(); + if( std::isnan(logger.getForce()) ) + { + WALBERLA_ABORT("Nan found in force - aborting"); + } + real_t density1 = real_t(0); real_t density2 = real_t(0); real_t averageDensity = real_t(0); + auto movingProbePosition = Vector3<real_t>(real_c(domainSize[0])*real_t(0.75), real_c(domainSize[1])*real_t(0.5), logger.getPosition()); if(logDensity) { density1 = getDensityAtPosition<DensityInterpolator_T >(blocks, densityInterpolatorID, Vector3<real_t>(real_c(domainSize[0])*real_t(0.25), real_c(domainSize[1])*real_t(0.5), real_c(domainSize[2])*real_t(0.5))); - density2 = getDensityAtPosition<DensityInterpolator_T >(blocks, densityInterpolatorID, Vector3<real_t>(real_c(domainSize[0])*real_t(0.75), real_c(domainSize[1])*real_t(0.5), logger.getPosition())); + density2 = getDensityAtPosition<DensityInterpolator_T >(blocks, densityInterpolatorID, movingProbePosition); averageDensity = getAverageDensityInSystem<BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID); } - logger.writeToFile(i, density1, density2, averageDensity); + + Vector3<real_t> velocityAtProbePos(real_t(0)); + if(logFluidVelocity) + { + velocityAtProbePos = getVelocityAtPosition<VelocityInterpolator_T >(blocks, velocityInterpolatorID, movingProbePosition); + } + + uint_t countSolidCells = 0; + uint_t countFluidSolidLinks = 0; + if(logMapping) evaluateMapping<BoundaryHandling_T>(blocks, boundaryHandlingID, countSolidCells, countFluidSolidLinks); + + logger.writeToFile(i*uint_c(dtSim), density1, density2, averageDensity, countSolidCells, countFluidSolidLinks, velocityAtProbePos); timeloopTiming["Logging"].end(); + // reset after logging here ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + if(!fixedSphere) + { + timeloopTiming["RPD"].start(); + + if( artificiallyAccelerateSphere ) + { + real_t newSphereVel = - velocity * (std::exp(- real_t(i) * dtSim * accelerationFactor/ tref ) - real_t(1)); + ps->forEachParticle(useOpenMP, sphereSelector, *accessor, [newSphereVel](const size_t idx, ParticleAccessor_T& ac){ ac.setLinearVelocity(idx, Vector3<real_t>(real_t(0), real_t(0), newSphereVel));}, *accessor); + } + + // there is no force acting on sphere + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, explEulerIntegrator, *accessor); + syncCall(); + + timeloopTiming["RPD"].end(); + + // update mapping, restore PDFs + timeloopAfterParticles.singleStep( timeloopTiming ); + } + + } timeloopTiming.logResultOnRoot(); if(vtkOutputAtEnd) { - std::string vtkFileName = "fluid_field"; + std::string vtkFileName = "fluid_field_final"+fileNamePostFix; vtkFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); if( useOmegaBulkAdaption ) vtkFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); @@ -843,6 +1049,13 @@ int main( int argc, char **argv ) pdfFieldVTK->addCellDataWriter( make_shared< lbm::DensityVTKWriter < LatticeModel_T, float > >( pdfFieldID, "DensityFromPDF" ) ); vtk::writeFiles(pdfFieldVTK)(); + + auto particleVtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + particleVtkOutput->addOutput<mesa_pd::data::SelectParticleLinearVelocity>("velocity"); + particleVtkOutput->setParticleSelector( [sphereShape](const mesa_pd::data::ParticleStorage::iterator& pIt) {return pIt->getShapeID() == sphereShape;} ); //limit output to sphere + auto particleVtkWriter = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles_final"+fileNamePostFix, uint_t(1), baseFolder); + + vtk::writeFiles(particleVtkWriter)(); } -- GitLab From f86bbcb014324bbefe781ed34ce9f44827e92f49 Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Mon, 22 Feb 2021 15:00:47 +0100 Subject: [PATCH 67/83] [BugFix] PackInfo generation --- python/lbmpy_walberla/packinfo.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/python/lbmpy_walberla/packinfo.py b/python/lbmpy_walberla/packinfo.py index 54a4e6755..d6a0ab23c 100644 --- a/python/lbmpy_walberla/packinfo.py +++ b/python/lbmpy_walberla/packinfo.py @@ -1,4 +1,5 @@ from collections import defaultdict +from lbmpy.stencils import get_stencil from lbmpy.advanced_streaming.utility import Timestep, get_accessor, get_timesteps from lbmpy.advanced_streaming.communication import _extend_dir from pystencils.stencil import inverse_direction @@ -59,10 +60,12 @@ def generate_lb_pack_info(generation_context, for comm_dir in comm_directions(comm_direction): common_spec[(comm_dir,)].add(fa.field.center(*fa.index)) + full_stencil = get_stencil('D3Q27') if len(stencil[0]) == 3 else get_stencil('D2Q9') + for t in timesteps: spec = common_spec.copy() write_accesses = get_accessor(streaming_pattern, t).write(pdf_field, stencil) - for comm_dir in stencil: + for comm_dir in full_stencil: if all(d == 0 for d in comm_dir): continue -- GitLab From 7749607e2620ca01dd2af9bd11372a618cd92a87 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Mon, 22 Feb 2021 15:48:32 +0100 Subject: [PATCH 68/83] Explicitly fall back to C++14 with older CUDA --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 36c6831d5..e70d89fa2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,8 +495,9 @@ else() endif() endif() -if (WALBERLA_BUILD_WITH_CUDA AND CUDA_VERSION VERSION_LESS "11.0") +if (WALBERLA_BUILD_WITH_CUDA AND (CUDA_VERSION VERSION_LESS "11.0" OR CMAKE_VERSION VERSION_LESS 3.18.0)) # CUDA < 11 does not support C++17. std::experimental::any works with C++14, unlike std::any. + set(CMAKE_CUDA_STANDARD 14) set(WALBERLA_USE_STD_EXPERIMENTAL_ANY 1) endif() @@ -1051,7 +1052,6 @@ if ( WALBERLA_BUILD_WITH_CUDA ) #CUDA_FOUND is need for our cmake mechanism set ( CUDA_FOUND TRUE ) - set(CMAKE_CUDA_STANDARD_REQUIRED OFF) else() set ( WALBERLA_BUILD_WITH_CUDA FALSE ) endif ( ) -- GitLab From 297d9f7992c466b8932052940107c0e40aaff964 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Mon, 22 Feb 2021 17:31:35 +0100 Subject: [PATCH 69/83] codegen: fix some constant types for vectorization and correct field layout for FluctuatingMRT --- apps/benchmarks/UniformGridGPU/UniformGridGPU.py | 2 +- apps/benchmarks/UniformGridGPU/UniformGridGPU_AA.py | 2 +- .../UniformGridGenerated/UniformGridGenerated.py | 4 ++-- .../PhaseFieldAllenCahn/CPU/multiphase_codegen.py | 4 +++- tests/lbm/codegen/FluctuatingMRT.cpp | 4 ++-- tests/lbm/codegen/FluctuatingMRT.py | 7 +++++-- tests/lbm/codegen/GeneratedOutflowBC.py | 2 +- 7 files changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/benchmarks/UniformGridGPU/UniformGridGPU.py b/apps/benchmarks/UniformGridGPU/UniformGridGPU.py index 1a7973f6d..20ea3f0f7 100644 --- a/apps/benchmarks/UniformGridGPU/UniformGridGPU.py +++ b/apps/benchmarks/UniformGridGPU/UniformGridGPU.py @@ -157,7 +157,7 @@ with CodeGeneration() as ctx: # getter & setter setter_assignments = macroscopic_values_setter(lb_method, velocity=velocity_field.center_vector, - pdfs=pdfs.center_vector, density=1) + pdfs=pdfs.center_vector, density=1.0) getter_assignments = macroscopic_values_getter(lb_method, velocity=velocity_field.center_vector, pdfs=pdfs.center_vector, density=None) generate_sweep(ctx, 'UniformGridGPU_MacroSetter', setter_assignments) diff --git a/apps/benchmarks/UniformGridGPU/UniformGridGPU_AA.py b/apps/benchmarks/UniformGridGPU/UniformGridGPU_AA.py index 1fb6261d3..c7e6341ae 100644 --- a/apps/benchmarks/UniformGridGPU/UniformGridGPU_AA.py +++ b/apps/benchmarks/UniformGridGPU/UniformGridGPU_AA.py @@ -106,7 +106,7 @@ with CodeGeneration() as ctx: # getter & setter setter_assignments = macroscopic_values_setter(lb_method, velocity=velocity_field.center_vector, - pdfs=pdfs.center_vector, density=1) + pdfs=pdfs.center_vector, density=1.0) getter_assignments = macroscopic_values_getter(lb_method, velocity=velocity_field.center_vector, pdfs=pdfs.center_vector, density=None) generate_sweep(ctx, 'UniformGridGPU_AA_MacroSetter', setter_assignments) diff --git a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py index fc587c445..d42452222 100644 --- a/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py +++ b/apps/benchmarks/UniformGridGenerated/UniformGridGenerated.py @@ -26,7 +26,7 @@ options_dict = { 'mrt': { 'method': 'mrt', 'stencil': 'D3Q19', - 'relaxation_rates': [0, omega, 1.3, 1.4, omega, 1.2, 1.1, 1.15, 1.234, 1.4235, 1.242, 1.2567, 0.9, 0.7], + 'relaxation_rates': [0.0, omega, 1.3, 1.4, omega, 1.2, 1.1, 1.15, 1.234, 1.4235, 1.242, 1.2567, 0.9, 0.7], }, 'mrt_full': { 'method': 'mrt', @@ -171,7 +171,7 @@ with CodeGeneration() as ctx: cpu_openmp=openmp_enabled, ghost_layers=1) setter_assignments = macroscopic_values_setter(update_rule_two_field.method, velocity=velocity_field.center_vector, - pdfs=pdfs.center_vector, density=1) + pdfs=pdfs.center_vector, density=1.0) getter_assignments = macroscopic_values_getter(update_rule_two_field.method, velocity=velocity_field.center_vector, pdfs=pdfs.center_vector, density=None) generate_sweep(ctx, 'GenMacroSetter', setter_assignments, cpu_openmp=openmp_enabled) diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py index 497e00299..fad6b4020 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py @@ -17,6 +17,7 @@ from lbmpy.phasefield_allen_cahn.force_model import MultiphaseForceModel import numpy as np import sympy as sp +import pystencils as ps stencil_phase = get_stencil("D3Q19") stencil_hydro = get_stencil("D3Q27") @@ -125,8 +126,9 @@ phase_field_LB_step = create_lb_update_rule(lb_method=method_phase, kernel_type='stream_pull_collide') phase_field_LB_step.set_main_assignments_from_dict({**phase_field_LB_step.main_assignments_dict, **{C.center: sum_h}}) +subexp = [ps.Assignment(a.lhs, float(a.rhs)) if a.rhs == 0 else a for a in phase_field_LB_step.subexpressions] phase_field_LB_step = AssignmentCollection(main_assignments=phase_field_LB_step.main_assignments, - subexpressions=phase_field_LB_step.subexpressions) + subexpressions=subexp) phase_field_LB_step = sympy_cse(phase_field_LB_step) # --------------------------------------------------------------------------------------------------------- diff --git a/tests/lbm/codegen/FluctuatingMRT.cpp b/tests/lbm/codegen/FluctuatingMRT.cpp index 342d2d423..6707c3b38 100644 --- a/tests/lbm/codegen/FluctuatingMRT.cpp +++ b/tests/lbm/codegen/FluctuatingMRT.cpp @@ -68,10 +68,10 @@ int main( int argc, char ** argv ) const double remainingTimeLoggerFrequency = parameters.getParameter< double >( "remainingTimeLoggerFrequency", 3.0 ); // in seconds // create fields - BlockDataID forceFieldId = field::addToStorage<VectorField_T>( blocks, "Force", real_t( 0.0 )); + BlockDataID forceFieldId = field::addToStorage<VectorField_T>( blocks, "Force", real_t( 0.0 ), field::fzyx); LatticeModel_T latticeModel = LatticeModel_T( forceFieldId, omega, 0, omega, omega, seed, temperature, uint_t(0) ); - BlockDataID pdfFieldId = lbm::addPdfFieldToStorage( blocks, "pdf field", latticeModel, initialVelocity, real_t(1) ); + BlockDataID pdfFieldId = lbm::addPdfFieldToStorage( blocks, "pdf field", latticeModel, initialVelocity, real_t(1), uint_t(1), field::fzyx ); BlockDataID flagFieldId = field::addFlagFieldToStorage< FlagField_T >( blocks, "flag field" ); // create and initialize flag field diff --git a/tests/lbm/codegen/FluctuatingMRT.py b/tests/lbm/codegen/FluctuatingMRT.py index 4db0ca9ba..6adba1df0 100644 --- a/tests/lbm/codegen/FluctuatingMRT.py +++ b/tests/lbm/codegen/FluctuatingMRT.py @@ -9,7 +9,7 @@ from lbmpy_walberla import generate_lattice_model with CodeGeneration() as ctx: omega_shear = sp.symbols("omega_shear") temperature = sp.symbols("temperature") - force_field, vel_field = ps.fields("force(3), velocity(3): [3D]", layout='zyxf') + force_field, vel_field = ps.fields("force(3), velocity(3): [3D]", layout='fzyx') def rr_getter(moment_group): is_shear = [is_shear_moment(m, 3) for m in moment_group] @@ -49,4 +49,7 @@ with CodeGeneration() as ctx: optimization={'cse_global': True} ) - generate_lattice_model(ctx, 'FluctuatingMRT_LatticeModel', collision_rule) + params = {} + if ctx.optimize_for_localhost: + params['cpu_vectorize_info'] = {'assume_inner_stride_one': True, 'assume_aligned': True} + generate_lattice_model(ctx, 'FluctuatingMRT_LatticeModel', collision_rule, field_layout='fzyx', **params) diff --git a/tests/lbm/codegen/GeneratedOutflowBC.py b/tests/lbm/codegen/GeneratedOutflowBC.py index 59a916fec..679d2bf6d 100644 --- a/tests/lbm/codegen/GeneratedOutflowBC.py +++ b/tests/lbm/codegen/GeneratedOutflowBC.py @@ -38,7 +38,7 @@ method = create_lb_method(**options) # getter & setter setter_assignments = macroscopic_values_setter(method, velocity=velocity_field.center_vector, - pdfs=pdfs, density=1) + pdfs=pdfs, density=1.0) # opt = {'instruction_set': 'sse', 'assume_aligned': True, 'nontemporal': False, 'assume_inner_stride_one': True} -- GitLab From a820ba0c3e01866c359c2aa4f2adda92ccf09f40 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Mon, 22 Feb 2021 21:34:32 +0100 Subject: [PATCH 70/83] Apple ARM64 support --- apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py | 2 +- apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py | 2 +- tests/lbm/codegen/GeneratedOutflowBC.py | 2 -- tests/simd/CMakeLists.txt | 2 +- 4 files changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py index 999f76d3c..a751f35a4 100644 --- a/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py +++ b/apps/benchmarks/PhaseFieldAllenCahn/multiphase_codegen.py @@ -137,7 +137,7 @@ stream_hydro = create_lb_update_rule(stencil=stencil_hydro, # GENERATE SWEEPS # ################### -cpu_vec = {'instruction_set': 'sse', 'assume_inner_stride_one': True, 'nontemporal': True} +cpu_vec = {'assume_inner_stride_one': True, 'nontemporal': True} vp = [('int32_t', 'cudaBlockSize0'), ('int32_t', 'cudaBlockSize1')] diff --git a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py index 497e00299..5621212eb 100644 --- a/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py +++ b/apps/showcases/PhaseFieldAllenCahn/CPU/multiphase_codegen.py @@ -150,7 +150,7 @@ stream_hydro = create_lb_update_rule(stencil=stencil_hydro, ################### # GENERATE SWEEPS # ################### -cpu_vec = {'instruction_set': 'sse', 'assume_inner_stride_one': True, 'nontemporal': True} +cpu_vec = {'assume_inner_stride_one': True, 'nontemporal': True} vp = [('int32_t', 'cudaBlockSize0'), ('int32_t', 'cudaBlockSize1')] diff --git a/tests/lbm/codegen/GeneratedOutflowBC.py b/tests/lbm/codegen/GeneratedOutflowBC.py index 59a916fec..c3d4fc985 100644 --- a/tests/lbm/codegen/GeneratedOutflowBC.py +++ b/tests/lbm/codegen/GeneratedOutflowBC.py @@ -40,8 +40,6 @@ method = create_lb_method(**options) setter_assignments = macroscopic_values_setter(method, velocity=velocity_field.center_vector, pdfs=pdfs, density=1) -# opt = {'instruction_set': 'sse', 'assume_aligned': True, 'nontemporal': False, 'assume_inner_stride_one': True} - update_rule = create_lb_update_rule(lb_method=method, **options) info_header = f""" diff --git a/tests/simd/CMakeLists.txt b/tests/simd/CMakeLists.txt index 6fa07c3c5..843dd9315 100644 --- a/tests/simd/CMakeLists.txt +++ b/tests/simd/CMakeLists.txt @@ -8,7 +8,7 @@ # builds the test -if ( WALBERLA_CXX_COMPILER_IS_GNU OR WALBERLA_CXX_COMPILER_IS_CLANG ) +if ( WALBERLA_CXX_COMPILER_IS_GNU OR (WALBERLA_CXX_COMPILER_IS_CLANG AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR NOT CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "arm64")) ) set( MarchNativeString "-march=native" ) endif() -- GitLab From 1bc454a244fe6eb48c3c9a73ebccbd9a32202d5f Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Tue, 23 Feb 2021 09:25:04 +0100 Subject: [PATCH 71/83] Minor updates in fp coupling functionalities --- .../MovingParticleMapping.h | 19 +++++++++++-------- .../utility/InspectionProbe.h | 7 ++++++- .../utility/ParticleSelector.h | 4 +++- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/src/lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h b/src/lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h index 29c161d4f..88d311236 100644 --- a/src/lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h +++ b/src/lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h @@ -165,9 +165,9 @@ private: } } - - // cell is already an obstacle (maybe from another particle) - if( isFlagSet( cellFlagPtr, obstacle ) ) { + else if( isFlagSet( cellFlagPtr, obstacle ) ) + { + // cell is already an obstacle (maybe from another particle) auto formerParticleUid = (*particleField)(x, y, z); auto formerParticleIdx = ac_->uidToIdx(formerParticleUid); if(!isSet(ac_->getFlags(formerParticleIdx), mesa_pd::data::particle_flags::FIXED) ) @@ -179,10 +179,9 @@ private: (*particleField)(x, y, z) = particleUid; } } - - // cell is a former obstacle cell (maybe from another particle that has moved away) - if( isFlagSet( cellFlagPtr, formerObstacle ) ) + else if( isFlagSet( cellFlagPtr, formerObstacle ) ) { + // cell is a former obstacle cell (maybe from another particle that has moved away) boundaryHandling->setBoundary( obstacle, x, y, z ); removeFlag( cellFlagPtr, formerObstacle ); (*particleField)(x, y, z) = particleUid; @@ -333,8 +332,12 @@ private: { if( singleCast(particleIdx, ac, containsPointFctr, ac, Vector3<real_t>(cx,cy,cz)) ) { - boundaryHandling->forceBoundary(obstacleFlag, x, y, z); - (*particleField)(x,y,z) = ac.getUid(particleIdx); + if(boundaryHandling->isDomain(x,y,z)) + { + boundaryHandling->forceBoundary(obstacleFlag, x, y, z); + (*particleField)(x,y,z) = ac.getUid(particleIdx); + } + // no else -> will not overwrite pre-existing boundary cells, e.g. of previously applied applied mapping (e.g. when first mapping global particles) } cx += dx; } diff --git a/src/lbm_mesapd_coupling/utility/InspectionProbe.h b/src/lbm_mesapd_coupling/utility/InspectionProbe.h index 4513cdfaf..b2644017f 100644 --- a/src/lbm_mesapd_coupling/utility/InspectionProbe.h +++ b/src/lbm_mesapd_coupling/utility/InspectionProbe.h @@ -74,6 +74,11 @@ public: } } + void setPosition(Vector3<real_t> probeLocation) + { + probeLocation_ = probeLocation; + } + private: void printStatusOfCellSurrounding(Cell centerCell, const IBlock& block) @@ -121,7 +126,7 @@ private: void printToScreen(bool isFluid, real_t rho, Vector3<real_t> velocity) { - if(printToScreen_) WALBERLA_LOG_INFO("Values in probe at position " << probeLocation_ << ": " << (isFluid?"F":"P") << ", rho = " << rho << ", velocity = " << velocity); + if(printToScreen_) WALBERLA_LOG_INFO("Values in probe at position " << probeLocation_ << " on rank " << mpi::MPIManager::instance()->rank() << ": " << (isFluid?"F":"P") << ", rho = " << rho << ", velocity = " << velocity); } void writeToFile(bool isFluid, real_t rho, Vector3<real_t> velocity) diff --git a/src/lbm_mesapd_coupling/utility/ParticleSelector.h b/src/lbm_mesapd_coupling/utility/ParticleSelector.h index 9baf0a4a1..a18a91af4 100644 --- a/src/lbm_mesapd_coupling/utility/ParticleSelector.h +++ b/src/lbm_mesapd_coupling/utility/ParticleSelector.h @@ -24,6 +24,7 @@ #include "mesa_pd/data/Flags.h" #include "mesa_pd/data/IAccessor.h" #include "mesa_pd/data/shape/Sphere.h" +#include "mesa_pd/kernel/ParticleSelector.h" namespace walberla { namespace lbm_mesapd_coupling { @@ -76,8 +77,9 @@ struct StokesNumberBasedSphereSelector static_assert(std::is_base_of<mesa_pd::data::IAccessor, ParticleAccessor_T>::value, "Provide a valid accessor as template"); lbm_mesapd_coupling::RegularParticlesSelector regularParticlesSelector; + mesa_pd::kernel::SelectLocal localParticlesSelector; - if(regularParticlesSelector(particleIdx, ac)) + if(regularParticlesSelector(particleIdx, ac) && localParticlesSelector(particleIdx, ac)) { // check for non-fixed spheres if( ac.getShape(particleIdx)->getShapeType() == mesa_pd::data::Sphere::SHAPE_TYPE ) -- GitLab From 527f387e8e14c5586b967bd85ed2f81b05e3f6d6 Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Tue, 23 Feb 2021 11:38:09 +0100 Subject: [PATCH 72/83] Added new benchmark scenario for fp coupling --- .../FluidParticleCoupling/CMakeLists.txt | 4 + .../MotionSettlingSphere.cpp | 1378 +++++++++++++++++ 2 files changed, 1382 insertions(+) create mode 100644 apps/benchmarks/FluidParticleCoupling/MotionSettlingSphere.cpp diff --git a/apps/benchmarks/FluidParticleCoupling/CMakeLists.txt b/apps/benchmarks/FluidParticleCoupling/CMakeLists.txt index a9b6e43d8..898352998 100644 --- a/apps/benchmarks/FluidParticleCoupling/CMakeLists.txt +++ b/apps/benchmarks/FluidParticleCoupling/CMakeLists.txt @@ -38,6 +38,10 @@ if( WALBERLA_BUILD_WITH_CODEGEN ) DEPENDS blockforest boundary core domain_decomposition field lbm lbm_mesapd_coupling mesa_pd postprocessing timeloop vtk FluidParticleCouplingGeneratedLBM) + waLBerla_add_executable(NAME MotionSettlingSphere FILES MotionSettlingSphere.cpp + DEPENDS blockforest boundary core domain_decomposition field lbm lbm_mesapd_coupling mesa_pd + postprocessing timeloop vtk FluidParticleCouplingGeneratedLBM) + else() waLBerla_add_executable ( NAME SphereWallCollision FILES SphereWallCollision.cpp diff --git a/apps/benchmarks/FluidParticleCoupling/MotionSettlingSphere.cpp b/apps/benchmarks/FluidParticleCoupling/MotionSettlingSphere.cpp new file mode 100644 index 000000000..69f6a438e --- /dev/null +++ b/apps/benchmarks/FluidParticleCoupling/MotionSettlingSphere.cpp @@ -0,0 +1,1378 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file MotionSettlingSphere.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#include "boundary/all.h" + +#include "blockforest/all.h" + +#include "core/all.h" + +#include "domain_decomposition/all.h" + +#include "field/AddToStorage.h" +#include "field/communication/PackInfo.h" +#include "field/vtk/all.h" + +#include "lbm/boundary/all.h" +#include "lbm/communication/PdfFieldPackInfo.h" +#include "lbm/field/AddToStorage.h" +#include "lbm/field/PdfField.h" +#include "lbm/lattice_model/D3Q19.h" +#include "lbm/sweeps/CellwiseSweep.h" +#include "lbm/sweeps/SweepWrappers.h" +#include "lbm/vtk/all.h" + +#include "lbm_mesapd_coupling/mapping/ParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/boundary/SimpleBB.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/boundary/CurvedLinear.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/Reconstructor.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/ExtrapolationDirectionFinder.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/PdfReconstructionManager.h" +#include "lbm_mesapd_coupling/utility/AddForceOnParticlesKernel.h" +#include "lbm_mesapd_coupling/utility/ParticleSelector.h" +#include "lbm_mesapd_coupling/DataTypes.h" +#include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h" +#include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/OmegaBulkAdaption.h" +#include "lbm_mesapd_coupling/utility/InspectionProbe.h" +#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h" + +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/ParticleAccessorWithShape.h" +#include "mesa_pd/data/ShapeStorage.h" +#include "mesa_pd/data/DataTypes.h" +#include "mesa_pd/data/shape/Sphere.h" +#include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/domain/BlockForestDataHandling.h" +#include "mesa_pd/kernel/DoubleCast.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/mpi/SyncNextNeighbors.h" +#include "mesa_pd/mpi/SyncGhostOwners.h" +#include "mesa_pd/mpi/ReduceProperty.h" +#include "mesa_pd/mpi/notifications/ForceTorqueNotification.h" +#include "mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "stencil/D3Q27.h" + +#include "timeloop/SweepTimeloop.h" + +#include "vtk/BlockCellDataWriter.h" +#include "vtk/Initialization.h" +#include "vtk/VTKOutput.h" + +#include <functional> +#include <memory> + +#ifdef WALBERLA_BUILD_WITH_CODEGEN +#include "GeneratedLBM.h" +#endif + +namespace motion_settling_sphere{ + +/////////// +// USING // +/////////// + +using namespace walberla; +using walberla::uint_t; + +////////////// +// TYPEDEFS // +////////////// + +using namespace walberla; +using walberla::uint_t; + +#ifdef WALBERLA_BUILD_WITH_CODEGEN +using LatticeModel_T = lbm::GeneratedLBM; +#else +using LatticeModel_T = lbm::D3Q19< lbm::collision_model::D3Q19MRT>; +#endif + +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; + +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; + +using ScalarField_T = GhostLayerField< real_t, 1>; + +const uint_t FieldGhostLayers = 1; + +/////////// +// FLAGS // +/////////// + +const FlagUID Fluid_Flag ( "fluid" ); + +const FlagUID UBB_Flag ( "velocity bounce back" ); +const FlagUID Outlet_Flag ( "outlet" ); + +const FlagUID MEM_BB_Flag ( "moving obstacle BB" ); +const FlagUID MEM_CLI_Flag ( "moving obstacle CLI" ); +const FlagUID FormerMEM_Flag( "former moving obstacle" ); + + +////////////////////////////// +// Coupling algorithm enums // +////////////////////////////// +enum MEMVariant { BB, CLI, MR }; + +MEMVariant to_MEMVariant( const std::string& s ) +{ + if( s == "BB" ) return MEMVariant::BB; + if( s == "CLI" ) return MEMVariant::CLI; + throw std::runtime_error("invalid conversion from text to MEMVariant"); +} + +std::string MEMVariant_to_string ( const MEMVariant& m ) +{ + if( m == MEMVariant::BB ) return "BB"; + if( m == MEMVariant::CLI ) return "CLI"; + throw std::runtime_error("invalid conversion from MEMVariant to string"); +} + + +///////////////////////////////////// +// BOUNDARY HANDLING CUSTOMIZATION // +///////////////////////////////////// +template <typename ParticleAccessor_T> +class MyBoundaryHandling +{ +public: + + using UBB_T = lbm::SimpleUBB< LatticeModel_T, flag_t >; + using Outlet_T = lbm::SimplePressure< LatticeModel_T, flag_t >; + using MO_SBB_T = lbm_mesapd_coupling::SimpleBB< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using MO_CLI_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using Type = BoundaryHandling< FlagField_T, Stencil_T, UBB_T, Outlet_T, MO_SBB_T, MO_CLI_T >; + + + MyBoundaryHandling( const BlockDataID & flagFieldID, const BlockDataID & pdfFieldID, + const BlockDataID & particleFieldID, const shared_ptr<ParticleAccessor_T>& ac, + Vector3<real_t> uInfty) : + flagFieldID_( flagFieldID ), pdfFieldID_( pdfFieldID ), particleFieldID_( particleFieldID ), + ac_( ac ), velocity_( uInfty ) + {} + + Type * operator()( IBlock* const block, const StructuredBlockStorage* const storage ) const + { + WALBERLA_ASSERT_NOT_NULLPTR( block ); + WALBERLA_ASSERT_NOT_NULLPTR( storage ); + + FlagField_T * flagField = block->getData< FlagField_T >( flagFieldID_ ); + PdfField_T * pdfField = block->getData< PdfField_T > ( pdfFieldID_ ); + auto * particleField = block->getData< lbm_mesapd_coupling::ParticleField_T > ( particleFieldID_ ); + + const auto fluid = flagField->flagExists( Fluid_Flag ) ? flagField->getFlag( Fluid_Flag ) : flagField->registerFlag( Fluid_Flag ); + + Type * handling = new Type( "moving obstacle boundary handling", flagField, fluid, + UBB_T( "UBB", UBB_Flag, pdfField, velocity_), + Outlet_T( "Outlet", Outlet_Flag, pdfField, real_t(1) ), + MO_SBB_T ( "MEM_BB", MEM_BB_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ), + MO_CLI_T( "MEM_CLI", MEM_CLI_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ) ); + + const auto ubb = flagField->getFlag( UBB_Flag ); + const auto outlet = flagField->getFlag( Outlet_Flag ); + + CellInterval domainBB = storage->getDomainCellBB(); + + domainBB.xMin() -= cell_idx_c( FieldGhostLayers ); // -1 + domainBB.xMax() += cell_idx_c( FieldGhostLayers ); // cellsX + + domainBB.yMin() -= cell_idx_c( FieldGhostLayers ); // 0 + domainBB.yMax() += cell_idx_c( FieldGhostLayers ); // cellsY+1 + + domainBB.zMin() -= cell_idx_c( FieldGhostLayers ); // 0 + domainBB.zMax() += cell_idx_c( FieldGhostLayers ); // cellsZ+1 + + // BOTTOM + // -1........-1........-1 + // cellsX+1..cellsY+1..-1 + CellInterval bottom( domainBB.xMin(), domainBB.yMin(), domainBB.zMin(), domainBB.xMax(), domainBB.yMax(), domainBB.zMin() ); + storage->transformGlobalToBlockLocalCellInterval( bottom, *block ); + handling->forceBoundary( ubb, bottom ); + + // TOP + // -1........-1........cellsZ+1 + // cellsX+1..cellsY+1..cellsZ+1 + CellInterval top( domainBB.xMin(), domainBB.yMin(), domainBB.zMax(), domainBB.xMax(), domainBB.yMax(), domainBB.zMax() ); + storage->transformGlobalToBlockLocalCellInterval( top, *block ); + handling->forceBoundary( outlet, top ); + + handling->fillWithDomain( FieldGhostLayers ); + + return handling; + } + +private: + const BlockDataID flagFieldID_; + const BlockDataID pdfFieldID_; + const BlockDataID particleFieldID_; + + shared_ptr<ParticleAccessor_T> ac_; + const Vector3<real_t> velocity_; + +}; // class MyBoundaryHandling + +/* + * Functionality for continuous logging of sphere properties during initial (resting) simulation + */ +template< typename ParticleAccessor_T> +class RestingSphereForceEvaluator +{ +public: + RestingSphereForceEvaluator( const shared_ptr< ParticleAccessor_T > & ac, walberla::id_t sphereUid, + uint_t averageFrequency, const std::string & basefolder ) : + ac_( ac ), sphereUid_( sphereUid ), averageFrequency_( averageFrequency ) + { + WALBERLA_ROOT_SECTION() { + // initially write header in file + std::ofstream file; + filename_ = basefolder; + filename_ += "/log_init.txt"; + file.open(filename_.c_str()); + file << "# f_z_current f_z_average f_x f_y\n"; + file.close(); + } + } + + // evaluate the acting drag force on a fixed sphere + void operator()(const uint_t timestep) + { + + // average the force over averageFrequency consecutive timesteps since there are small fluctuations in the force + auto currentForce = getForce(); + currentAverage_ += currentForce[2]; + + WALBERLA_ROOT_SECTION() + { + std::ofstream file; + file.open( filename_.c_str(), std::ofstream::app ); + file.precision(8); + file << timestep << "\t" << currentForce[2] << "\t" << dragForceNew_ + << "\t" << currentForce[0] << "\t" << currentForce[1] << std::endl; + file.close(); + } + + if( timestep % averageFrequency_ != 0) return; + + dragForceOld_ = dragForceNew_; + dragForceNew_ = currentAverage_ / real_c( averageFrequency_ ); + currentAverage_ = real_t(0); + + } + + // Return the relative temporal change in the drag force + real_t getForceDiff() const + { + return std::fabs( ( dragForceNew_ - dragForceOld_ ) / dragForceNew_ ); + } + + real_t getDragForce() const + { + return dragForceNew_; + } + +private: + + // Obtain the drag force acting on the sphere + Vector3<real_t> getForce() + { + Vector3<real_t> force(real_t( 0 )); + size_t idx = ac_->uidToIdx(sphereUid_); + if( idx != ac_->getInvalidIdx()) + { + if(!mesa_pd::data::particle_flags::isSet( ac_->getFlags(idx), mesa_pd::data::particle_flags::GHOST)) + { + force = ac_->getHydrodynamicForce(idx); + } + } + + WALBERLA_MPI_SECTION() + { + mpi::allReduceInplace( force[0], mpi::SUM ); + mpi::allReduceInplace( force[1], mpi::SUM ); + mpi::allReduceInplace( force[2], mpi::SUM ); + } + return force; + } + + shared_ptr< ParticleAccessor_T > ac_; + const walberla::id_t sphereUid_; + + real_t currentAverage_ = real_t(0); + uint_t averageFrequency_; + std::string filename_; + real_t dragForceOld_ = real_t(0); + real_t dragForceNew_ = real_t(0); + +}; + +/* + * Functionality for continuous logging of sphere properties during moving simulation + */ +template< typename ParticleAccessor_T> +class MovingSpherePropertyEvaluator +{ +public: + MovingSpherePropertyEvaluator( const shared_ptr< ParticleAccessor_T > & ac, walberla::id_t sphereUid, const std::string & basefolder, + const Vector3<real_t> & u_infty, const real_t Galileo, const real_t GalileoSim, + const real_t gravity, const real_t viscosity, const real_t diameter, + const real_t densityRatio ) : + ac_( ac ), sphereUid_( sphereUid ), + u_infty_( u_infty ), gravity_( gravity ), viscosity_( viscosity ), + diameter_( diameter ), densityRatio_( densityRatio ) + { + + WALBERLA_ROOT_SECTION() + { + std::ofstream fileSetup; + std::string filenameSetup = basefolder; + filenameSetup += "/setup.txt"; + fileSetup.open( filenameSetup.c_str() ); + + fileSetup << "# setup parameters: \n"; + fileSetup << "processes = " << MPIManager::instance()->numProcesses() << "\n"; + fileSetup << "Galileo number (targeted) = " << Galileo << "\n"; + fileSetup << "Galileo number (simulated) = " << GalileoSim << "\n"; + fileSetup << "gravity = " << gravity << "\n"; + fileSetup << "viscosity = " << viscosity << "\n"; + fileSetup << "diameter = " << diameter << "\n"; + fileSetup << "uInfty = " << u_infty_[2] << "\n"; + real_t u_ref = std::sqrt( std::fabs(densityRatio - real_t(1)) * gravity * diameter ); + fileSetup << "u_{ref} = " << u_ref << "\n"; + fileSetup.close(); + } + + filenameRes_ = basefolder; + filenameRes_ += "/log_results.txt"; + filenameAdd_ = basefolder; + filenameAdd_ += "/log_additional.txt"; + + WALBERLA_ROOT_SECTION() + { + // initially write header in file + std::ofstream fileRes; + fileRes.open( filenameRes_.c_str() ); + // raw data + fileRes << "#\t x_p_x\t x_p_y\t x_p_z\t u_p_x\t u_p_y\t u_p_z\t omega_p_x\t omega_p_y\t omega_p_z\t u_{pr}_x\t u_{pr}_y\t u_{pr}_z\t "; + // processed data, 14 - 18 + fileRes << "Re\t u_{pV}\t u_{pH}\t omega_{pV}\t omega_{pH}\t alpha\n"; + fileRes.close(); + + std::ofstream fileAdd; + fileAdd.open( filenameAdd_.c_str() ); + fileAdd << "# forceX forceY forceZ torqueX torqueY torqueZ\n"; + fileAdd.close(); + } + } + + // evaluate and write the sphere properties + void operator()(const uint_t timestep) + { + Vector3<real_t> transVel( real_t(0) ); + Vector3<real_t> angularVel( real_t(0) ); + Vector3<real_t> pos( real_t(0) ); + + Vector3<real_t> force( real_t(0) ); + Vector3<real_t> torque( real_t(0) ); + + size_t idx = ac_->uidToIdx(sphereUid_); + if( idx != ac_->getInvalidIdx()) + { + if(!mesa_pd::data::particle_flags::isSet( ac_->getFlags(idx), mesa_pd::data::particle_flags::GHOST)) + { + pos = ac_->getPosition(idx); + transVel = ac_->getLinearVelocity(idx); + angularVel = ac_->getAngularVelocity(idx); + force = ac_->getHydrodynamicForce(idx); + torque = ac_->getHydrodynamicTorque(idx); + } + } + + std::vector<real_t> particlePos(3); + particlePos[0]=pos[0]; particlePos[1]=pos[1]; particlePos[2]=pos[2]; + + std::vector<real_t> particleTransVel(3); + particleTransVel[0]=transVel[0]; particleTransVel[1]=transVel[1]; particleTransVel[2]=transVel[2]; + + std::vector<real_t> particleAngularVel(3); + particleAngularVel[0]=angularVel[0]; particleAngularVel[1]=angularVel[1]; particleAngularVel[2]=angularVel[2]; + + std::vector<real_t> particleForce(3); + particleForce[0]=force[0]; particleForce[1]=force[1]; particleForce[2]=force[2]; + + std::vector<real_t> particleTorque(3); + particleTorque[0]=torque[0]; particleTorque[1]=torque[1]; particleTorque[2]=torque[2]; + + // reduce to root + WALBERLA_MPI_SECTION() + { + mpi::allReduceInplace( particlePos, mpi::SUM ); + mpi::reduceInplace( particleTransVel, mpi::SUM ); + mpi::reduceInplace( particleAngularVel, mpi::SUM ); + mpi::reduceInplace( particleForce, mpi::SUM ); + mpi::reduceInplace( particleTorque, mpi::SUM ); + } + + particleHeight_ = particlePos[2]; + + //only root process has all the data + WALBERLA_ROOT_SECTION() + { + + Vector3<real_t> u_p_r( particleTransVel[0] - u_infty_[0], particleTransVel[1] - u_infty_[1], particleTransVel[2] - u_infty_[2]); + real_t u_p_H = std::sqrt( u_p_r[0] * u_p_r[0] + u_p_r[1] * u_p_r[1]); + real_t u_p_V = u_p_r[2]; + + real_t omega_p_H = std::sqrt( particleAngularVel[0] * particleAngularVel[0] + particleAngularVel[1] * particleAngularVel[1] ); + real_t omega_p_V = particleAngularVel[2]; + + real_t u_ref = std::sqrt( std::fabs(densityRatio_ - real_t(1)) * gravity_ * diameter_ ); + real_t Reynolds = u_p_r.length() * diameter_ / viscosity_; + + // results + std::ofstream fileRes; + fileRes.open( filenameRes_.c_str(), std::ofstream::app ); + fileRes.precision(8); + fileRes << timestep + << "\t" << particlePos[0] << "\t" << particlePos[1] << "\t" << particlePos[2] + << "\t" << particleTransVel[0] << "\t" << particleTransVel[1] << "\t" << particleTransVel[2] + << "\t" << particleAngularVel[0] << "\t" << particleAngularVel[1] << "\t" << particleAngularVel[2] + << "\t" << u_p_r[0] << "\t" << u_p_r[1] << "\t" << u_p_r[2] + << "\t" << Reynolds << "\t" << u_p_V/u_ref << "\t" << u_p_H/u_ref + << "\t" << omega_p_V*(diameter_/u_ref) << "\t" << omega_p_H*(diameter_/u_ref) + << "\t" << std::atan( u_p_H/std::fabs(u_p_V) ) + << std::endl; + fileRes.close(); + + // additional + std::ofstream fileAdd; + fileAdd.open( filenameAdd_.c_str(), std::ofstream::app ); + fileAdd.precision(8); + fileAdd << timestep + << "\t" << particleForce[0] << "\t" << particleForce[1] << "\t" << particleForce[2] + << "\t" << particleTorque[0] << "\t" << particleTorque[1] << "\t" << particleTorque[2] + << std::endl; + fileAdd.close(); + } + } + + real_t getParticleHeight() const + { + return particleHeight_; + } + +private: + + shared_ptr< ParticleAccessor_T > ac_; + const walberla::id_t sphereUid_; + + std::string filenameRes_; + std::string filenameAdd_; + + Vector3<real_t> u_infty_; + real_t gravity_; + real_t viscosity_; + real_t diameter_; + real_t densityRatio_; + + real_t particleHeight_; + +}; + +/* + * Result evaluation for the written VTK files + * + * input: vel (fluid velocity), u_p (particle velocity), u_infty (inflow velocity) + * + * needed data: + * relative flow velocity: vel_r = vel - u_p + * relative particle velocity: u_p_r = u_p - u_infty + * + * magnitude of relative particle velocity in horizontal plane: u_p_H = sqrt( (u_p_r)_x^2 + (u_p_r)_y^2 ) + * unit vector of particle motion in horizontal plane: e_p_H = ( (u_p_r)_x, (u_p_r)_y, 0) / u_p_H + * unit vector perpendicular to e_p_H and e_z: e_p_Hz_perp = ( -(u_p_r)_y, (u_p_r)_x, 0) / u_p_H + * unit vector of particle motion: e_p_parallel = u_p_r / ||u_p_r|| + * unit vector perpendicular to e_p_parallel and e_p_Hz_perp: e_p_perp = e_p_Hz_perp x e_p_parallel + * projected fluid velocities: vel_r_parallel = vel_r * (-e_p_parallel) + * vel_r_perp = vel_r * e_p_perp + * vel_r_Hz_perp = vel_r * e_p_Hz_perp + */ +template< typename ParticleAccessor_T> +class VTKInfoLogger +{ +public: + + VTKInfoLogger( SweepTimeloop* timeloop, const shared_ptr< ParticleAccessor_T > & ac, walberla::id_t sphereUid, + const std::string & baseFolder, const Vector3<real_t>& u_infty ) : + timeloop_( timeloop ), ac_( ac ), sphereUid_( sphereUid ), baseFolder_( baseFolder ), u_infty_( u_infty ) + { } + + void operator()() + { + Vector3<real_t> u_p( real_t(0) ); + + size_t idx = ac_->uidToIdx(sphereUid_); + if( idx != ac_->getInvalidIdx()) + { + if(!mesa_pd::data::particle_flags::isSet( ac_->getFlags(idx), mesa_pd::data::particle_flags::GHOST)) + { + u_p = ac_->getLinearVelocity(idx); + } + } + + WALBERLA_MPI_SECTION() + { + mpi::allReduceInplace( u_p[0], mpi::SUM ); + mpi::allReduceInplace( u_p[1], mpi::SUM ); + mpi::allReduceInplace( u_p[2], mpi::SUM ); + + } + + Vector3<real_t> u_p_r = u_p - u_infty_; + real_t u_p_r_sqr_mag = u_p_r.sqrLength(); + + real_t u_p_H = std::sqrt( u_p_r[0] * u_p_r[0] + u_p_r[1] * u_p_r[1]); + + Vector3<real_t> e_p_H (u_p_r[0], u_p_r[1], real_t(0)); + e_p_H /= u_p_H; + Vector3<real_t> e_p_Hz_perp (-u_p_r[1], u_p_r[0], real_t(0)); + e_p_Hz_perp /= u_p_H; + + Vector3<real_t> e_p_parallel = u_p_r / u_p_r.length(); + Vector3<real_t> e_p_perp = e_p_Hz_perp%e_p_parallel; + + WALBERLA_ROOT_SECTION() + { + std::ofstream file; + + std::string filename(baseFolder_); + filename += "/log_vtk/log_vtk_"; + filename += std::to_string( timeloop_->getCurrentTimeStep() ); + filename += ".txt"; + + file.open( filename.c_str() ); + file.precision(8); + + file << "u_p = " << u_p << "\n"; + file << "u_p_r_2 = " << u_p_r_sqr_mag << "\n\n"; + + file << "e_{pH} = " << e_p_H << "\n"; + file << "e_{pparallel} = " << e_p_parallel << "\n"; + file << "e_{pperp} = " << e_p_perp << "\n"; + file << "e_{pHzperp} = " << e_p_Hz_perp << "\n"; + + file.close(); + } + } + +private: + + SweepTimeloop* timeloop_; + + shared_ptr< ParticleAccessor_T > ac_; + const walberla::id_t sphereUid_; + + std::string baseFolder_; + Vector3<real_t> u_infty_; + +}; + + +/* + * This extensive, physical test case simulates a single, heavy sphere in ambient fluid flow. + * It is based on the benchmark proposed in + * Uhlman, Dusek - "The motion of a single heavy sphere in ambient fluid: A benchmark for interface-resolved + * particulate flow simulations with significant relative velocities" IJMF (2014), + * doi: 10.1016/j.ijmultiphaseflow.2013.10.010 + * Results for LBM done with waLBerla are published in + * Rettinger, Ruede - "A comparative study of fluid-particle coupling methods for fully resolved + * lattice Boltzmann simulations" CaF (2017), + * doi: 10.1016/j.compfluid.2017.05.033 + * The setup and the benchmark itself are explained in detail in these two papers. + * Several logging files are written to evaluate the benchmark quantities. + * + * This case is the same as can be found in apps/benchmarks/MotionSingleHeavySphere + * but using the lbm_mesapd_coupling, instead of the pe_coupling. + * Compared to this previous work, significantly different outcomes can be observed when using the CLI boundary condition. + * This can be traced back to the distinct way of force averaging. + * The force averaging applied in the previous study (two LBM steps, then average) introduces a error in the Galilean invariance. + * Surprisingly, this error can result in better agreement to the reference solutions. + * + */ +int main( int argc, char **argv ) +{ + debug::enterTestMode(); + + mpi::Environment env( argc, argv ); + + bool noViscosityIterations = false; + bool vtkIOInit = false; + bool longDom = false; + bool broadDom = false; + bool useOmegaBulkAdaption = false; + real_t bulkViscRateFactor = real_t(1); + uint_t averageForceTorqueOverTwoTimeStepsMode = 1; // 0: no, 1: running, 2: 2LBM + bool conserveMomentum = false; + bool useDiffusiveScaling = true; + bool useVelocityVerlet = true; + bool initFluidVelocity = true; + bool vtkOutputGhostlayers = false; + + MEMVariant memVariant = MEMVariant::BB; + std::string reconstructorType = "Grad"; // Eq, EAN, Ext, Grad + + real_t diameter = real_t(18); + uint_t XBlocks = uint_t(4); + uint_t YBlocks = uint_t(4); + + real_t viscosity = real_t(0.01); // used in diffusive scaling + real_t uIn = real_t(0.02); // used for acoustic scaling + + /* + * 0: custom + * 1: Ga = 144 + * 2: Ga = 178.46 + * 3: Ga = 190 + * 4: Ga = 250 + */ + uint_t simulationCase = 1; + real_t Galileo = real_t(1); + real_t Re_target = real_t(1); + real_t timestepsNonDim = real_t(1); + + + real_t vtkWriteSpacingNonDim = real_t(3); // write every 3 non-dim timesteps + uint_t vtkNumOutputFiles = 10; // write only 10 vtk files: the 10 final ones + + std::string folderEnding = ""; + + //////////////////////////// + // COMMAND LINE ARGUMENTS // + //////////////////////////// + + for( int i = 1; i < argc; ++i ) + { + if( std::strcmp( argv[i], "--case" ) == 0 ) {simulationCase = uint_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--Ga" ) == 0 ){Galileo = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--Re" ) == 0 ){Re_target = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--timestepsNonDim" ) == 0 ){timestepsNonDim = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--diameter" ) == 0 ){diameter = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--noViscosityIterations" ) == 0 ){noViscosityIterations = true; continue;} + if( std::strcmp( argv[i], "--viscosity" ) == 0 ){viscosity = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--uIn" ) == 0 ){uIn = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--vtkIOInit" ) == 0 ){vtkIOInit = true; continue;} + if( std::strcmp( argv[i], "--longDom" ) == 0 ){longDom = true; continue;} + if( std::strcmp( argv[i], "--broadDom" ) == 0 ){broadDom = true; continue;} + if( std::strcmp( argv[i], "--variant" ) == 0 ){memVariant = to_MEMVariant( argv[++i] ); continue;} + if( std::strcmp( argv[i], "--useOmegaBulkAdaption" ) == 0 ){useOmegaBulkAdaption = true; continue;} + if( std::strcmp( argv[i], "--bvrf" ) == 0 ){bulkViscRateFactor = real_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--forceTorqueAverageMode" ) == 0 ){averageForceTorqueOverTwoTimeStepsMode = uint_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--conserveMomentum" ) == 0 ){conserveMomentum = true; continue;} + if( std::strcmp( argv[i], "--useDiffusiveScaling" ) == 0 ){useDiffusiveScaling = true; continue;} + if( std::strcmp( argv[i], "--XBlocks" ) == 0 ){XBlocks = uint_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--YBlocks" ) == 0 ){YBlocks = uint_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--folderEnding" ) == 0 ){folderEnding = argv[++i]; continue;} + if( std::strcmp( argv[i], "--reconstructorType" ) == 0 ) {reconstructorType = argv[++i]; continue;} + if( std::strcmp( argv[i], "--useEuler" ) == 0 ) {useVelocityVerlet = false; continue;} + if( std::strcmp( argv[i], "--noFluidVelocityInit" ) == 0 ) {initFluidVelocity = false; continue;} + if( std::strcmp( argv[i], "--vtkOutputGhostlayers" ) == 0 ) {vtkOutputGhostlayers = true; continue;} + if( std::strcmp( argv[i], "--vtkNumOutputFiles" ) == 0 ){vtkNumOutputFiles = uint_c( std::atof( argv[++i] ) ); continue;} + if( std::strcmp( argv[i], "--vtkWriteSpacingNonDim" ) == 0 ){vtkWriteSpacingNonDim = real_c( std::atof( argv[++i] ) ); continue;} + WALBERLA_ABORT("command line argument unknown: " << argv[i] ); + } + + /////////////////////////// + // SIMULATION PROPERTIES // + /////////////////////////// + + const real_t radius = real_t(0.5) * diameter; + uint_t xlength = uint_c( diameter * real_t(5.34) ); + uint_t ylength = xlength; + uint_t zlength = uint_c( diameter * real_t(16) ); + + if(broadDom) + { + xlength *= uint_t(2); + ylength *= uint_t(2); + } + + if(longDom) + { + zlength *= uint_t(3); + } + + + // estimate Reynolds number (i.e. inflow velocity) based on Galileo number + // values are taken from the original simulation of Uhlmann, Dusek + switch( simulationCase ) + { + case 0: + WALBERLA_LOG_INFO_ON_ROOT("Using custom simulation case -> you have to provide Ga, Re, and time steps via command line arguments!"); + break; + case 1: + Galileo = real_t(144); + Re_target = real_t(185.08); + timestepsNonDim = real_t(100); + break; + case 2: + Galileo = real_t(178.46); + Re_target = real_t(243.01); + timestepsNonDim = real_t(250); + break; + case 3: + Galileo = real_t(190); + Re_target = real_t(262.71); + timestepsNonDim = real_t(250); + break; + case 4: + Galileo = real_t(250); + Re_target = real_t(365.10); + timestepsNonDim = real_t(510); + break; + default: + WALBERLA_ABORT("Simulation case is not supported!"); + } + + if( useDiffusiveScaling) + { + // estimate fitting inflow velocity (diffusive scaling, viscosity is fixed) + // attention: might lead to large velocities for small diameters + uIn = Re_target * viscosity / diameter; + } else { + // estimate fitting viscosity (acoustic scaling: velocity is fixed) + // note that this is different to the approach taking in the paper, where an diffusive scaling with visc = 0.01 is taken + // attention: might lead to small viscosities for small diameters + viscosity = uIn * diameter / Re_target; + } + + + real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); + real_t omegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, bulkViscRateFactor); + + Vector3<real_t> uInfty = Vector3<real_t>( real_t(0), real_t(0), uIn ); + + const real_t densityRatio = real_t(1.5); + + const uint_t averageFrequency = uint_c( ( ( uint_c(Galileo) >= 200) ? real_t(500) : real_t(2) ) * diameter / uIn ); // for initial simulation + const real_t convergenceLimit = real_t(1e-4); + const real_t convergenceLimitGalileo = real_t(1e-4); + const real_t dx = real_t(1); + const real_t magicNumberTRT = lbm::collision_model::TRT::threeSixteenth; + + const uint_t timestepsInit = uint_c( ( ( uint_c(Galileo) >= 200) ? real_t(3000) : real_t(100) ) * diameter / uIn ); // maximum number of time steps for the initial simulation + const uint_t writeFrequencyInit = uint_t(1000); // vtk write frequency init + + /////////////////////////// + // BLOCK STRUCTURE SETUP // + /////////////////////////// + const int numProcs = MPIManager::instance()->numProcesses(); + uint_t ZBlocks = uint_c(numProcs) / ( XBlocks * YBlocks ); + const uint_t XCells = xlength / XBlocks; + const uint_t YCells = ylength / YBlocks; + const uint_t ZCells = zlength / ZBlocks; + + if( (xlength != XCells * XBlocks) || (ylength != YCells * YBlocks) || (zlength != ZCells * ZBlocks) ) + { + WALBERLA_ABORT("Domain partitioning does not fit to total domain size!"); + } + + WALBERLA_LOG_INFO_ON_ROOT("Motion settling sphere simulation of case " << simulationCase << " -> Ga = " << Galileo); + WALBERLA_LOG_INFO_ON_ROOT("Diameter: " << diameter); + WALBERLA_LOG_INFO_ON_ROOT("Domain: " << xlength << " x " << ylength << " x " << zlength); + WALBERLA_LOG_INFO_ON_ROOT("Processes: " << XBlocks << " x " << YBlocks << " x " << ZBlocks); + WALBERLA_LOG_INFO_ON_ROOT("Subdomains: " << XCells << " x " << YCells << " x " << ZCells); + WALBERLA_LOG_INFO_ON_ROOT("Tau: " << real_t(1)/omega); + WALBERLA_LOG_INFO_ON_ROOT("Viscosity: " << viscosity); + WALBERLA_LOG_INFO_ON_ROOT("uIn: " << uIn); + WALBERLA_LOG_INFO_ON_ROOT("Re_infty: " << uIn * diameter / viscosity); + + auto blocks = blockforest::createUniformBlockGrid( XBlocks, YBlocks, ZBlocks, XCells, YCells, ZCells, dx, true, + true, true, false ); + + ////////////////// + // RPD COUPLING // + ////////////////// + + auto rpdDomain = std::make_shared<mesa_pd::domain::BlockForestDomain>(blocks->getBlockForestPointer()); + + //init data structures + auto ps = walberla::make_shared<mesa_pd::data::ParticleStorage>(1); + auto ss = walberla::make_shared<mesa_pd::data::ShapeStorage>(); + using ParticleAccessor_T = mesa_pd::data::ParticleAccessorWithShape; + auto accessor = walberla::make_shared<ParticleAccessor_T >(ps, ss); + + + + real_t xParticle = real_t(0); + real_t yParticle = real_t(0); + real_t zParticle = real_t(0); + + // root determines particle position, then broadcasts it + WALBERLA_ROOT_SECTION() + { + if( simulationCase == 1 ) + { + xParticle = real_c( xlength ) * real_t(0.5); + yParticle = real_c( ylength ) * real_t(0.5); + } + else if( simulationCase == 4 ) + { + // add random perturbance for chaotic regime + walberla::math::seedRandomGenerator( std::mt19937::result_type(std::time(nullptr)) ); + xParticle = real_c( xlength ) * real_t(0.5) + walberla::math::realRandom( real_t(-0.5), real_t(0.5) ); + yParticle = real_c( ylength ) * real_t(0.5) + walberla::math::realRandom( real_t(-0.5), real_t(0.5) ); + + } + else + { + //add small perturbance to sphere position to break stability due to numerical symmetry + real_t perturbance = real_t(0.35); + + xParticle = real_c( xlength ) * real_t(0.5) + perturbance; + yParticle = real_c( ylength ) * real_t(0.5); + } + + zParticle = (longDom) ? ( diameter * real_t(16) + real_c( xlength ) ) : real_c( xlength ); + } + + // broadcast to other ranks + WALBERLA_MPI_SECTION() + { + mpi::broadcastObject( xParticle ); + mpi::broadcastObject( yParticle ); + mpi::broadcastObject( zParticle ); + } + + // add sphere + Vector3<real_t> position( xParticle, yParticle, zParticle ); + auto sphereShape = ss->create<mesa_pd::data::Sphere>( radius ); + ss->shapes[sphereShape]->updateMassAndInertia(densityRatio); + + walberla::id_t sphereUid = 0; + if (rpdDomain->isContainedInProcessSubdomain( uint_c(mpi::MPIManager::instance()->rank()), position )) + { + mesa_pd::data::Particle&& p = *ps->create(); + p.setPosition(position); + p.setInteractionRadius(radius); + p.setOwner(mpi::MPIManager::instance()->rank()); + p.setShapeID(sphereShape); + sphereUid = p.getUid(); + } + mpi::allReduceInplace(sphereUid, mpi::SUM); + + // set up synchronization procedure + const real_t overlap = real_t( 1.5 ) * dx; + std::function<void(void)> syncCall; + if( XBlocks <= uint_t(4) ) + { + WALBERLA_LOG_INFO_ON_ROOT("Using next neighbor sync!") + syncCall = [&ps,&rpdDomain,overlap](){ + mesa_pd::mpi::SyncNextNeighbors syncNextNeighborFunc; + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + }; + syncCall(); + } + else + { + WALBERLA_LOG_INFO_ON_ROOT("Using ghost owner sync!") + syncCall = [&ps,&rpdDomain,overlap](){ + mesa_pd::mpi::SyncGhostOwners syncGhostOwnersFunc; + syncGhostOwnersFunc(*ps, *rpdDomain, overlap); + }; + for(uint_t i = 0; i < uint_c(XBlocks/2); ++i) syncCall(); + } + + + WALBERLA_LOG_INFO_ON_ROOT("Initial sphere position: " << position); + + /////////////////////// + // ADD DATA TO BLOCKS // + //////////////////////// + + // add omega bulk field + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); + + + // create the lattice model + real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); + real_t lambda_d = lbm::collision_model::TRT::lambda_d( omega, magicNumberTRT ); +#ifdef WALBERLA_BUILD_WITH_CODEGEN + WALBERLA_LOG_INFO_ON_ROOT("Using generated TRT-like lattice model!"); + LatticeModel_T latticeModel = LatticeModel_T(omegaBulkFieldID, lambda_d, lambda_e); +#else + WALBERLA_LOG_INFO_ON_ROOT("Using waLBerla built-in TRT lattice model and ignoring omega bulk!"); + LatticeModel_T latticeModel = LatticeModel_T( lbm::collision_model::TRT::constructWithMagicNumber( omega, magicNumberTRT ) ); +#endif + + // add PDF field + // initial velocity in domain = inflow velocity + BlockDataID pdfFieldID = lbm::addPdfFieldToStorage< LatticeModel_T >( blocks, "pdf field", latticeModel, initFluidVelocity ? uInfty : Vector3<real_t>(0), real_t(1), uint_t(1), field::fzyx ); + + // add flag field + BlockDataID flagFieldID = field::addFlagFieldToStorage< FlagField_T >( blocks, "flag field" ); + + // add particle field + BlockDataID particleFieldID = field::addToStorage<lbm_mesapd_coupling::ParticleField_T>( blocks, "particle field", accessor->getInvalidUid(), field::fzyx, FieldGhostLayers ); + + + // add boundary handling & initialize outer domain boundaries + using BoundaryHandling_T = MyBoundaryHandling<ParticleAccessor_T>::Type; + BlockDataID boundaryHandlingID = blocks->addStructuredBlockData< BoundaryHandling_T >(MyBoundaryHandling<ParticleAccessor_T>( flagFieldID, pdfFieldID, particleFieldID, accessor, uInfty), "boundary handling" ); + + // kernels + mesa_pd::mpi::ReduceProperty reduceProperty; + + lbm_mesapd_coupling::AddHydrodynamicInteractionKernel addHydrodynamicInteraction; + lbm_mesapd_coupling::ResetHydrodynamicForceTorqueKernel resetHydrodynamicForceTorque; + lbm_mesapd_coupling::AverageHydrodynamicForceTorqueKernel averageHydrodynamicForceTorque; + lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; + + lbm_mesapd_coupling::RegularParticlesSelector sphereSelector; + + lbm_mesapd_coupling::MovingParticleMappingKernel<BoundaryHandling_T> movingParticleMappingKernel(blocks, boundaryHandlingID, particleFieldID); + + // mapping of sphere required by MEM variants + // sets the correct flags + if( memVariant == MEMVariant::CLI ) + { + ps->forEachParticle(false, sphereSelector, *accessor, movingParticleMappingKernel, *accessor, MEM_CLI_Flag); + }else { + ps->forEachParticle(false, sphereSelector, *accessor, movingParticleMappingKernel, *accessor, MEM_BB_Flag); + } + + // base folder to store all logs and vtk output + std::string basefolder ("MSHS_"); + + basefolder += std::to_string( uint_c( Galileo ) ); + basefolder += "_"; + basefolder += std::to_string( uint_c( diameter ) ); + basefolder += "_MEM_"; + basefolder += MEMVariant_to_string( memVariant ); + basefolder += "_bvrf"; + basefolder += std::to_string(int(bulkViscRateFactor)); + if( useOmegaBulkAdaption ) basefolder += "Adapt"; + + basefolder += "_" + reconstructorType; + + if( longDom ) basefolder += "_longDom"; + if( broadDom ) basefolder += "_broadDom"; + if( conserveMomentum ) basefolder += "_conserveMomentum"; + if( !folderEnding.empty() ) basefolder += "_" + folderEnding; + + WALBERLA_LOG_INFO_ON_ROOT("Basefolder for simulation results: " << basefolder); + + // create base directory if it does not yet exist + filesystem::path tpath( basefolder ); + if( !filesystem::exists( tpath ) ) + filesystem::create_directory( tpath ); + + // setup of the LBM communication for synchronizing the pdf field between neighboring blocks + + blockforest::communication::UniformBufferedScheme< Stencil_T > optimizedPDFCommunicationScheme( blocks ); + optimizedPDFCommunicationScheme.addPackInfo( make_shared< lbm::PdfFieldPackInfo< LatticeModel_T > >( pdfFieldID ) ); // optimized sync + + blockforest::communication::UniformBufferedScheme< Stencil_T > fullPDFCommunicationScheme( blocks ); + fullPDFCommunicationScheme.addPackInfo( make_shared< field::communication::PackInfo< PdfField_T > >( pdfFieldID ) ); // full sync + + // omega bulk adaption + using OmegaBulkAdapter_T = lbm_mesapd_coupling::OmegaBulkAdapter<ParticleAccessor_T, decltype(sphereSelector)>; + real_t defaultOmegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, real_t(1)); + real_t adaptionLayerSize = real_t(2); + shared_ptr<OmegaBulkAdapter_T> omegaBulkAdapter = make_shared<OmegaBulkAdapter_T>(blocks, omegaBulkFieldID, accessor, defaultOmegaBulk, omegaBulk, adaptionLayerSize, sphereSelector); + for (auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) { + (*omegaBulkAdapter)(blockIt.get()); + } + + + ////////////////////////////////////// + // TIME LOOP FOR INITIAL SIMULATION // + ////////////////////////////////////// + + // Initialization simulation: fixed sphere and simulate until convergence (of drag force) + + // create the timeloop + SweepTimeloop timeloopInit( blocks->getBlockStorage(), timestepsInit ); + + // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) + auto bhSweep = BoundaryHandling_T::getBlockSweep( boundaryHandlingID ); + timeloopInit.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) + << Sweep(bhSweep, "Boundary Handling" ); + + // stream + collide LBM step +#ifdef WALBERLA_BUILD_WITH_CODEGEN + auto lbmSweep = LatticeModel_T::Sweep( pdfFieldID ); + timeloopInit.add() << Sweep( lbmSweep, "LB sweep" ); +#else + auto lbmSweep = lbm::makeCellwiseSweep< LatticeModel_T, FlagField_T >( pdfFieldID, flagFieldID, Fluid_Flag ); + timeloopInit.add() << Sweep( makeSharedSweep( lbmSweep ), "cell-wise LB sweep" ); +#endif + + if( vtkIOInit ) + { + auto pdfFieldVTKInit = vtk::createVTKOutput_BlockData( blocks, "fluid_field_init", writeFrequencyInit, 0, false, basefolder ); + + field::FlagFieldCellFilter< FlagField_T > fluidFilterInit( flagFieldID ); + fluidFilterInit.addFlag( Fluid_Flag ); + pdfFieldVTKInit->addCellInclusionFilter( fluidFilterInit ); + + pdfFieldVTKInit->addCellDataWriter( make_shared< lbm::VelocityVTKWriter< LatticeModel_T, float > >( pdfFieldID, "VelocityFromPDF" ) ); + pdfFieldVTKInit->addCellDataWriter( make_shared< lbm::DensityVTKWriter < LatticeModel_T, float > >( pdfFieldID, "DensityFromPDF" ) ); + + timeloopInit.addFuncAfterTimeStep( vtk::writeFiles( pdfFieldVTKInit ), "VTK (fluid field data)" ); + } + + timeloopInit.addFuncAfterTimeStep( RemainingTimeLogger( timeloopInit.getNrOfTimeSteps(), real_t(30) ), "Remaining Time Logger" ); + + //////////////////////////////// + // EXECUTE INITIAL SIMULATION // + //////////////////////////////// + + real_t gravity = real_t(1); + real_t GalileoSim = real_t(1); + real_t ReynoldsSim = real_t(1); + real_t u_ref = real_t(1); + + WALBERLA_LOG_INFO_ON_ROOT("Starting initialization phase (sphere is kept fixed)."); + WALBERLA_LOG_INFO_ON_ROOT("Iterating, and adapting the viscosity, until the targeted Galileo number is set."); + + RestingSphereForceEvaluator<ParticleAccessor_T> forceEval( accessor, sphereUid, averageFrequency, basefolder ); + + while (true) { + WcTimingPool timeloopInitTiming; + + WALBERLA_LOG_INFO_ON_ROOT("(Re-)Starting initial simulation."); + for( uint_t i = 1; i < timestepsInit; ++i ){ + + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + timeloopInit.singleStep( timeloopInitTiming ); + + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + forceEval(timeloopInit.getCurrentTimeStep()+1); + + // check if the relative change in the average drag force is below the specified convergence criterion + if (forceEval.getForceDiff() < convergenceLimit && i > 2 * std::max(averageFrequency, zlength) ) + { + // conditions to break: + // - force diff sufficiently small + // - AND more time steps than twice the domain size in z direction to ensure new information due + // to possible viscosity change has traveled twice through domain, + // or twice the average frequency to have converged averages + + WALBERLA_LOG_INFO_ON_ROOT("Drag force converged at time " << timeloopInit.getCurrentTimeStep()); + break; + } + // if simulation gets unstable + if( std::isnan(forceEval.getDragForce()) ) + { + WALBERLA_ABORT("NAN value detected in drag force during initial simulation, exiting...."); + } + } + WALBERLA_LOG_INFO_ON_ROOT("Initial simulation has ended.") + + //evaluate the gravitational force necessary to keep the sphere at a approximately fixed position + gravity = forceEval.getDragForce() / ( (densityRatio - real_t(1) ) * diameter * diameter * diameter * math::pi / real_t(6) ); + GalileoSim = std::sqrt( ( densityRatio - real_t(1) ) * gravity * diameter * diameter * diameter ) / viscosity; + ReynoldsSim = uIn * diameter / viscosity; + u_ref = std::sqrt( std::fabs(densityRatio - real_t(1)) * gravity * diameter ); + + WALBERLA_LOG_INFO_ON_ROOT("Acting gravity = " << gravity ); + WALBERLA_LOG_INFO_ON_ROOT("Simulated Galileo number = " << GalileoSim ); + WALBERLA_LOG_INFO_ON_ROOT("Targeted Galileo number = " << Galileo ); + WALBERLA_LOG_INFO_ON_ROOT("Reynolds number infty = " << ReynoldsSim ); + + if ( noViscosityIterations ) + { + timeloopInitTiming.logResultOnRoot(); + WALBERLA_LOG_INFO_ON_ROOT("Terminate iterations since viscosity should not be changed, flag \"--noViscosityIterations\""); + break; + } + + // if simulated Galileo number is close enough to targeted Galileo number, stop the initial simulation + if( std::abs( GalileoSim - Galileo ) / Galileo < convergenceLimitGalileo ) + { + timeloopInitTiming.logResultOnRoot(); + WALBERLA_LOG_INFO_ON_ROOT("Iterations converged, simulated Galileo number is close enough to targeted one"); + break; + } + + // else update the simulation parameter accordingly and resume simulation + real_t diff = GalileoSim/Galileo; + viscosity = diff * viscosity; + omega = lbm::collision_model::omegaFromViscosity( viscosity ); + + lambda_e = lbm::collision_model::TRT::lambda_e( omega ); + lambda_d = lbm::collision_model::TRT::lambda_d( omega, magicNumberTRT ); + + // also adapt omega bulk + omegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, bulkViscRateFactor); + defaultOmegaBulk = lbm_mesapd_coupling::omegaBulkFromOmega(omega, real_t(1)); + omegaBulkAdapter->setDefaultOmegaBulk(defaultOmegaBulk); + omegaBulkAdapter->setAdaptedOmegaBulk(omegaBulk); + + // iterate all blocks with an iterator 'block' and change the collision model + for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) + { + // get the field data out of the block + auto pdf = blockIt->getData< PdfField_T > ( pdfFieldID ); +#ifdef WALBERLA_BUILD_WITH_CODEGEN + pdf->latticeModel().omega_magic_ = lambda_d; + pdf->latticeModel().omega_visc_ = lambda_e; +#else + pdf->latticeModel().collisionModel().resetWithMagicNumber( omega, magicNumberTRT ); +#endif + (*omegaBulkAdapter)(blockIt.get()); + } + + + WALBERLA_LOG_INFO_ON_ROOT("==> Adapting viscosity:"); + WALBERLA_LOG_INFO_ON_ROOT("New viscosity = " << viscosity ); + WALBERLA_LOG_INFO_ON_ROOT("New omega = " << omega ); + WALBERLA_LOG_INFO_ON_ROOT("New omega bulk = " << omegaBulk ); + + } + + if( averageForceTorqueOverTwoTimeStepsMode == 1 ) + { + // maintain a good initial guess for averaging + ps->forEachParticle(false, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); + } + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + /////////////// + // TIME LOOP // + /////////////// + + // actual simulation: freely moving sphere with acting gravity + + // calculate the number of timesteps + + real_t dtSim = (averageForceTorqueOverTwoTimeStepsMode == 2) ? real_t(2) : real_t(1); + const real_t t_ref = ( diameter / u_ref ); + const uint_t timesteps = uint_c( timestepsNonDim * t_ref / dtSim ); + + // set vtk write frequency accordingly + + const uint_t writeFrequency = uint_c( vtkWriteSpacingNonDim * t_ref ); // vtk write frequency + const uint_t initWriteCallsToSkip = uint_c(std::max( 0, int( timesteps - ( vtkNumOutputFiles - uint_t(1) ) * writeFrequency - uint_t(1) ) ) ); // write calls to be skipped + + WALBERLA_LOG_INFO_ON_ROOT("Starting simulation timeloop with " << timesteps << " timesteps!"); + WALBERLA_LOG_INFO_ON_ROOT("Sphere is allowed to move freely under action of gravity"); + + SweepTimeloop timeloop( blocks->getBlockStorage(), uint_c(dtSim) * timesteps ); + + + timeloop.addFuncBeforeTimeStep( RemainingTimeLogger( timeloop.getNrOfTimeSteps(), real_t(30) ), "Remaining Time Logger" ); + + // vtk output + auto pdfFieldVTK = vtk::createVTKOutput_BlockData( blocks, "fluid_field", writeFrequency, (vtkOutputGhostlayers) ? FieldGhostLayers : 0, false, basefolder ); + pdfFieldVTK->setInitialWriteCallsToSkip( initWriteCallsToSkip ); + + pdfFieldVTK->addBeforeFunction( fullPDFCommunicationScheme ); + + // function to output plane infos for vtk output + pdfFieldVTK->addBeforeFunction(VTKInfoLogger<ParticleAccessor_T>( &timeloop, accessor, sphereUid, basefolder, uInfty )); + + // create folder for log_vtk files to not pollute the basefolder + filesystem::path tpath2( basefolder+"/log_vtk" ); + if( !filesystem::exists( tpath2 ) ) + filesystem::create_directory( tpath2 ); + + + field::FlagFieldCellFilter< FlagField_T > fluidFilter( flagFieldID ); + fluidFilter.addFlag( Fluid_Flag ); + pdfFieldVTK->addCellInclusionFilter( fluidFilter ); + + pdfFieldVTK->addCellDataWriter( make_shared< lbm::VelocityVTKWriter< LatticeModel_T, float > >( pdfFieldID, "VelocityFromPDF" ) ); + pdfFieldVTK->addCellDataWriter( make_shared< lbm::DensityVTKWriter < LatticeModel_T, float > >( pdfFieldID, "DensityFromPDF" ) ); + + timeloop.addFuncBeforeTimeStep( vtk::writeFiles( pdfFieldVTK ), "VTK (fluid field data)" ); + + + // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) + timeloop.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) + << Sweep(bhSweep, "Boundary Handling" ); + + // stream + collide LBM step +#ifdef WALBERLA_BUILD_WITH_CODEGEN + timeloop.add() << Sweep( lbmSweep, "LB sweep" ); +#else + timeloop.add() << Sweep( makeSharedSweep( lbmSweep ), "cell-wise LB sweep" ); +#endif + + + SweepTimeloop timeloopAfterParticles( blocks->getBlockStorage(), timesteps ); + + // sweep for updating the pe body mapping into the LBM simulation + if( memVariant == MEMVariant::CLI ) + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T, BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MEM_CLI_Flag, FormerMEM_Flag, sphereSelector, conserveMomentum), "Particle Mapping" ); + else + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T, BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MEM_BB_Flag, FormerMEM_Flag, sphereSelector, conserveMomentum), "Particle Mapping" ); + + // sweep for restoring PDFs in cells previously occupied by particles + if( reconstructorType == "EAN") + { + + auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); + auto equilibriumAndNonEquilibriumSphereNormalReconstructor = lbm_mesapd_coupling::makeEquilibriumAndNonEquilibriumReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); + auto reconstructionManager = lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMEM_Flag, Fluid_Flag, equilibriumAndNonEquilibriumSphereNormalReconstructor, conserveMomentum); + + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(reconstructionManager), "PDF Restore" ); + + } else if( reconstructorType == "Ext" ) + { + auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); + auto extrapolationSphereNormalReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T,lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder,true>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); + + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMEM_Flag, Fluid_Flag, extrapolationSphereNormalReconstructor, conserveMomentum) ), "PDF Restore" ); + } else if( reconstructorType == "Grad") + { + auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, false, true, true); + + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMEM_Flag, Fluid_Flag, gradReconstructor, conserveMomentum) ), "PDF Restore" ); + } else if( reconstructorType == "Eq") + { + timeloopAfterParticles.add() << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMEM_Flag, Fluid_Flag, conserveMomentum) ), "PDF Restore" ); + } else { + WALBERLA_ABORT("Unknown reconstructor type " << reconstructorType); + } + + // update bulk omega in all cells to adapt to changed particle position + if( useOmegaBulkAdaption ) + { + timeloopAfterParticles.add() << Sweep( makeSharedSweep(omegaBulkAdapter), "Omega Bulk Adapter"); + } + + Vector3<real_t> extForcesOnSphere( real_t(0), real_t(0), - gravity * ( densityRatio - real_t(1) ) * diameter * diameter * diameter * math::pi / real_t(6)); + lbm_mesapd_coupling::AddForceOnParticlesKernel addGravitationalForce(extForcesOnSphere); + + + mesa_pd::kernel::VelocityVerletPreForceUpdate vvIntegratorPreForce(dtSim); + mesa_pd::kernel::VelocityVerletPostForceUpdate vvIntegratorPostForce(dtSim); + mesa_pd::kernel::ExplicitEuler explicitEulerIntegrator(dtSim); + + MovingSpherePropertyEvaluator<ParticleAccessor_T> movingSpherePropertyEvaluator( accessor, sphereUid, basefolder, uInfty, Galileo, GalileoSim, gravity, viscosity, diameter, densityRatio ); + + + //////////////////////// + // EXECUTE SIMULATION // + //////////////////////// + + WcTimingPool timeloopTiming; + + const bool useOpenMP = false; + + // time loop + for (uint_t i = 0; i < timesteps; ++i ) + { + // perform a single simulation step -> this contains LBM and setting of the hydrodynamic interactions + timeloop.singleStep( timeloopTiming ); + + if( averageForceTorqueOverTwoTimeStepsMode == 2) + { + // store current force and torque in fOld and tOld + ps->forEachParticle(useOpenMP, sphereSelector, *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); + + // reset f and t + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + timeloop.singleStep( timeloopTiming ); + + + // f = (f+fOld)/2 + ps->forEachParticle(useOpenMP, sphereSelector, *accessor, averageHydrodynamicForceTorque, *accessor ); + + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + } + else + { + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + + if( averageForceTorqueOverTwoTimeStepsMode == 1 ) + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor ); + } + } + + + timeloopTiming["RPD"].start(); + + if( useVelocityVerlet) + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPreForce, *accessor); + syncCall(); + } + + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor ); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); + + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + + if( useVelocityVerlet ) { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPostForce, *accessor); + } + else + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, explicitEulerIntegrator, *accessor); + } + syncCall(); + + timeloopTiming["RPD"].end(); + + // evaluation + timeloopTiming["Logging"].start(); + movingSpherePropertyEvaluator((i+1)*uint_c(dtSim)); + timeloopTiming["Logging"].end(); + + // reset after logging here + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + timeloopAfterParticles.singleStep( timeloopTiming ); + + if(movingSpherePropertyEvaluator.getParticleHeight() > real_c(zlength) - real_t(3) * diameter) + { + pdfFieldVTK->forceWrite(timeloop.getCurrentTimeStep()); + WALBERLA_LOG_WARNING_ON_ROOT("Sphere is too close to outflow, stopping simulation"); + break; + } + + } + + timeloopTiming.logResultOnRoot(); + + return EXIT_SUCCESS; +} + +} // namespace motion_settling_sphere + +int main( int argc, char **argv ){ + motion_settling_sphere::main(argc, argv); +} -- GitLab From f2411bf61ff04fc6a8b4cfb448669949140dcb85 Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Tue, 23 Feb 2021 18:32:06 +0000 Subject: [PATCH 73/83] Added new functionalities to fp-coupling apps --- .../FluidParticleCoupling/DragForceSphere.cpp | 19 +- .../ForcesOnSphereNearPlane.cpp | 27 +- .../FluidParticleCoupling/GeneratedLBM.py | 142 +++++++++-- .../GeneratedLBMWithForce.py | 232 +++++++++++++++--- .../LubricationForceEvaluation.cpp | 54 ++-- .../ObliqueWetCollision.cpp | 2 +- .../SettlingSphereInBox.cpp | 33 ++- .../SphereMovingWithPrescribedVelocity.cpp | 2 +- .../SphereWallCollision.cpp | 32 ++- 9 files changed, 433 insertions(+), 110 deletions(-) diff --git a/apps/benchmarks/FluidParticleCoupling/DragForceSphere.cpp b/apps/benchmarks/FluidParticleCoupling/DragForceSphere.cpp index a28651957..37921bf9c 100644 --- a/apps/benchmarks/FluidParticleCoupling/DragForceSphere.cpp +++ b/apps/benchmarks/FluidParticleCoupling/DragForceSphere.cpp @@ -79,6 +79,11 @@ #ifdef WALBERLA_BUILD_WITH_CODEGEN #include "GeneratedLBMWithForce.h" + +#define USE_TRTLIKE +//#define USE_D3Q27TRTLIKE +//#define USE_CUMULANTTRT +//#define USE_CUMULANT #endif namespace drag_force_sphere_mem @@ -529,17 +534,27 @@ int main( int argc, char **argv ) real_t omegaBulk = (useSRT) ? lambda_e : lbm_mesapd_coupling::omegaBulkFromOmega(omega, bulkViscRateFactor); // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model #ifdef WALBERLA_BUILD_WITH_CODEGEN + +#if defined(USE_TRTLIKE) || defined(USE_D3Q27TRTLIKE) WALBERLA_LOG_INFO_ON_ROOT("Using generated TRT-like lattice model!"); WALBERLA_LOG_INFO_ON_ROOT(" - magic number " << magicNumber); WALBERLA_LOG_INFO_ON_ROOT(" - omegaBulk = " << omegaBulk << ", bulk visc. = " << lbm_mesapd_coupling::bulkViscosityFromOmegaBulk(omegaBulk) << " (bvrf " << bulkViscRateFactor << ")"); WALBERLA_LOG_INFO_ON_ROOT(" - lambda_e " << lambda_e << ", lambda_d " << lambda_d << ", omegaBulk " << omegaBulk ); WALBERLA_LOG_INFO_ON_ROOT(" - use omega bulk adaption = " << useOmegaBulkAdaption << " (adaption layer size = " << adaptionLayerSize << ")"); - LatticeModel_T latticeModel = LatticeModel_T(omegaBulkFieldID, setup.extForce, lambda_d, lambda_e); +#elif defined(USE_CUMULANTTRT) + WALBERLA_LOG_INFO_ON_ROOT("Using generated cumulant TRT lattice model!"); + WALBERLA_LOG_INFO_ON_ROOT(" - magic number " << magicNumber); + WALBERLA_LOG_INFO_ON_ROOT(" - lambda_e " << lambda_e << ", lambda_d " << lambda_d ); + LatticeModel_T latticeModel = LatticeModel_T(setup.extForce, lambda_d, lambda_e); +#elif defined(USE_CUMULANT) + LatticeModel_T latticeModel = LatticeModel_T(setup.extForce, omega); +#endif + #else WALBERLA_LOG_INFO_ON_ROOT("Using waLBerla built-in MRT lattice model and ignoring omega bulk field since not supported!"); WALBERLA_LOG_INFO_ON_ROOT(" - magic number " << magicNumber); diff --git a/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp b/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp index ecf14716c..ee3c0f143 100644 --- a/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp +++ b/apps/benchmarks/FluidParticleCoupling/ForcesOnSphereNearPlane.cpp @@ -407,6 +407,7 @@ int main( int argc, char **argv ) bool initializeVelocityProfile = false; bool useOmegaBulkAdaption = false; real_t adaptionLayerSize = real_t(2); + std::string boundaryCondition = "CLI"; // SBB, CLI real_t relativeChangeConvergenceEps = real_t(1e-5); real_t physicalCheckingFrequency = real_t(0.1); @@ -420,6 +421,7 @@ int main( int argc, char **argv ) if( std::strcmp( argv[i], "--timesteps" ) == 0 ) { maximumNonDimTimesteps = real_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--wallDistance" ) == 0 ) { normalizedWallDistance = real_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--Re" ) == 0 ) { ReynoldsNumberShear = real_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--boundaryCondition" ) == 0 ) { boundaryCondition = argv[++i]; continue; } if( std::strcmp( argv[i], "--velocity" ) == 0 ) { wallVelocity = real_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--xOffset" ) == 0 ) { xOffsetOfSpherePosition = real_c( std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--yOffset" ) == 0 ) { yOffsetOfSpherePosition = real_c( std::atof( argv[++i] ) ); continue; } @@ -438,6 +440,7 @@ int main( int argc, char **argv ) WALBERLA_CHECK_GREATER_EQUAL(normalizedWallDistance, real_t(0.5)); WALBERLA_CHECK_GREATER_EQUAL(ReynoldsNumberShear, real_t(0)); WALBERLA_CHECK_GREATER_EQUAL(diameter, real_t(0)); + WALBERLA_CHECK(boundaryCondition == "SBB" || boundaryCondition == "CLI"); ////////////////////////// // NUMERICAL PARAMETERS // @@ -484,6 +487,7 @@ int main( int argc, char **argv ) WALBERLA_LOG_INFO_ON_ROOT(" - use omega bulk adaption = " << useOmegaBulkAdaption << " (adaption layer size = " << adaptionLayerSize << ")"); WALBERLA_LOG_INFO_ON_ROOT(" - sphere diameter = " << diameter << ", position = " << initialPosition << " ( xOffset = " << xOffsetOfSpherePosition << ", yOffset = " << yOffsetOfSpherePosition << " )"); WALBERLA_LOG_INFO_ON_ROOT(" - base folder VTK = " << baseFolderVTK << ", base folder logging = " << baseFolderLogging ); + WALBERLA_LOG_INFO_ON_ROOT(" - boundary condition = " << boundaryCondition ); /////////////////////////// // BLOCK STRUCTURE SETUP // @@ -562,7 +566,7 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); @@ -594,11 +598,21 @@ int main( int argc, char **argv ) lbm_mesapd_coupling::MovingParticleMappingKernel<BoundaryHandling_T> movingParticleMappingKernel(blocks, boundaryHandlingID, particleFieldID); lbm_mesapd_coupling::AverageHydrodynamicForceTorqueKernel averageHydrodynamicForceTorque; - // map sphere into the LBM simulation - ps->forEachParticle(false, lbm_mesapd_coupling::RegularParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, CLI_Flag); + if(boundaryCondition == "CLI") + { + // map sphere into the LBM simulation + ps->forEachParticle(false, lbm_mesapd_coupling::RegularParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, CLI_Flag); + // map planes + ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, CLI_Flag); + } + else + { + // map sphere into the LBM simulation + ps->forEachParticle(false, lbm_mesapd_coupling::RegularParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, SBB_Flag); + // map planes + ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, SBB_Flag); + } - // map planes - ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, CLI_Flag); // initialize Couette velocity profile in whole domain if(initializeVelocityProfile) @@ -661,13 +675,13 @@ int main( int argc, char **argv ) timeloop.add() << Sweep( makeSharedSweep( lbmSweep ), "cell-wise LB sweep" ); #endif - // add force evaluation and logging real_t normalizationFactor = math::pi / real_t(8) * densityFluid * shearRate * shearRate * wallDistance * wallDistance * diameter * diameter ; std::string loggingFileName( baseFolderLogging + "/LoggingForcesNearPlane"); loggingFileName += "_D" + std::to_string(uint_c(diameter)); loggingFileName += "_Re" + std::to_string(uint_c(ReynoldsNumberShear)); loggingFileName += "_WD" + std::to_string(uint_c(normalizedWallDistance * real_t(1000))); + loggingFileName += "_" + boundaryCondition; loggingFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); if(useOmegaBulkAdaption) loggingFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); loggingFileName += "_mn" + std::to_string(magicNumber); @@ -796,6 +810,7 @@ int main( int argc, char **argv ) resultFileName += "_D" + std::to_string(uint_c(diameter)); resultFileName += "_Re" + std::to_string(uint_c(ReynoldsNumberShear)); resultFileName += "_WD" + std::to_string(uint_c(normalizedWallDistance * real_t(1000))); + resultFileName += "_" + boundaryCondition; resultFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); if(useOmegaBulkAdaption) resultFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); resultFileName += "_mn" + std::to_string(magicNumber); diff --git a/apps/benchmarks/FluidParticleCoupling/GeneratedLBM.py b/apps/benchmarks/FluidParticleCoupling/GeneratedLBM.py index 7992bcdd9..9772c5ba1 100644 --- a/apps/benchmarks/FluidParticleCoupling/GeneratedLBM.py +++ b/apps/benchmarks/FluidParticleCoupling/GeneratedLBM.py @@ -1,46 +1,140 @@ import sympy as sp +from sympy.core.cache import clear_cache import pystencils as ps from lbmpy.creationfunctions import create_lb_method_from_existing, create_lb_method from lbmpy_walberla import generate_lattice_model from pystencils_walberla import CodeGeneration +from pystencils_walberla import get_vectorize_instruction_set from lbmpy.creationfunctions import create_lb_collision_rule from lbmpy.moments import is_even, get_order, MOMENT_SYMBOLS from lbmpy.stencils import get_stencil +from collections import OrderedDict with CodeGeneration() as ctx: - omegaVisc = sp.Symbol("omega_visc") - omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') - omegaMagic = sp.Symbol("omega_magic") - stencil = get_stencil("D3Q19", 'walberla') + generatedMethod = "TRTlike" + #generatedMethod = "D3Q27TRTlike" + #generatedMethod = "cumulant" - x, y, z = MOMENT_SYMBOLS - one = sp.Rational(1, 1) - sq = x ** 2 + y ** 2 + z ** 2 - moments = [ - [one, x, y, z], # [0, 3, 5, 7] - [sq - 1], # [1] - [3 * sq ** 2 - 6 * sq + 1], # [2] - [(3 * sq - 5) * x, (3 * sq - 5) * y, (3 * sq - 5) * z], # [4, 6, 8] - [3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 11, 13, 14, 15] - [(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12] - [(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18] - ] + clear_cache() - # relaxation rate for first group of moments (1,x,y,z) is set to zero internally - relaxation_rates=[omegaBulk.center_vector, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaVisc, omegaMagic] + cpu_vectorize_info = {'instruction_set': get_vectorize_instruction_set(ctx)} - methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False, - nested_moments=moments, relaxation_rates=relaxation_rates) + if generatedMethod == "TRTlike": + omegaVisc = sp.Symbol("omega_visc") + omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') + omegaMagic = sp.Symbol("omega_magic") + stencil = get_stencil("D3Q19", 'walberla') - #print(methodWithForce.relaxation_rates) - #print(methodWithForce.moment_matrix) + x, y, z = MOMENT_SYMBOLS + one = sp.Rational(1, 1) + sq = x ** 2 + y ** 2 + z ** 2 + moments = [ + [one, x, y, z], # [0, 3, 5, 7] + [sq - 1], # [1] + [3 * sq ** 2 - 6 * sq + 1], # [2] + [(3 * sq - 5) * x, (3 * sq - 5) * y, (3 * sq - 5) * z], # [4, 6, 8] + [3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 11, 13, 14, 15] + [(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12] + [(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18] + ] - collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) - generate_lattice_model(ctx, 'GeneratedLBM', collision_rule, field_layout='fzyx') + # relaxation rate for first group of moments (1,x,y,z) is set to zero internally + relaxation_rates=[omegaBulk.center_vector, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaVisc, omegaMagic] + methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False, + nested_moments=moments, relaxation_rates=relaxation_rates) + + #print(methodWithForce.relaxation_rates) + #print(methodWithForce.moment_matrix) + collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) + generate_lattice_model(ctx, 'GeneratedLBM', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + + + if generatedMethod == "D3Q27TRTlike": + + omegaVisc = sp.Symbol("omega_visc") + omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') + omegaMagic = sp.Symbol("omega_magic") + stencil = get_stencil("D3Q27", 'walberla') + + relaxation_rates=[omegaVisc, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaMagic, omegaVisc] + + methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False,weighted=True, compressible=False, + relaxation_rates=relaxation_rates) + + collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) + generate_lattice_model(ctx, 'GeneratedLBM', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + + if generatedMethod == "cumulant": + + x,y,z = MOMENT_SYMBOLS + + cumulants = [0] * 27 + + cumulants[0] = sp.sympify(1) #000 + + cumulants[1] = x #100 + cumulants[2] = y #010 + cumulants[3] = z #001 + + cumulants[4] = x*y #110 + cumulants[5] = x*z #101 + cumulants[6] = y*z #011 + + cumulants[7] = x**2 - y**2 #200 - 020 + cumulants[8] = x**2 - z**2 #200 - 002 + cumulants[9] = x**2 + y**2 + z**2 #200 + 020 + 002 + + cumulants[10] = x*y**2 + x*z**2 #120 + 102 + cumulants[11] = x**2*y + y*z**2 #210 + 012 + cumulants[12] = x**2*z + y**2*z #201 + 021 + cumulants[13] = x*y**2 - x*z**2 #120 - 102 + cumulants[14] = x**2*y - y*z**2 #210 - 012 + cumulants[15] = x**2*z - y**2*z #201 - 021 + + cumulants[16] = x*y*z #111 + + cumulants[17] = x**2*y**2 - 2*x**2*z**2 + y**2*z**2 # 220- 2*202 +022 + cumulants[18] = x**2*y**2 + x**2*z**2 - 2*y**2*z**2 # 220 + 202 - 2*002 + cumulants[19] = x**2*y**2 + x**2*z**2 + y**2*z**2 # 220 + 202 + 022 + + cumulants[20] = x**2*y*z # 211 + cumulants[21] = x*y**2*z # 121 + cumulants[22] = x*y*z**2 # 112 + + cumulants[23] = x**2*y**2*z # 221 + cumulants[24] = x**2*y*z**2 # 212 + cumulants[25] = x*y**2*z**2 # 122 + + cumulants[26] = x**2*y**2*z**2 # 222 + + def get_relaxation_rate(cumulant, omega): + if get_order(cumulant) <= 1: + return 0 + elif get_order(cumulant) == 2 and cumulant != x**2 + y**2 + z**2: + return omega + else: + return 1 + + stencil = get_stencil("D3Q27", 'walberla') + + omega = sp.Symbol("omega") + rr_dict = OrderedDict((c, get_relaxation_rate(c, omega)) + for c in cumulants) + + from lbmpy.methods import create_with_continuous_maxwellian_eq_moments + my_method = create_with_continuous_maxwellian_eq_moments(stencil, rr_dict, cumulant=True, compressible=True,) + + collision_rule = create_lb_collision_rule(lb_method=my_method, + optimization={"cse_global": True, + "cse_pdfs": False}) + + print(my_method.relaxation_rates) + + generate_lattice_model(ctx, 'GeneratedLBM', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) diff --git a/apps/benchmarks/FluidParticleCoupling/GeneratedLBMWithForce.py b/apps/benchmarks/FluidParticleCoupling/GeneratedLBMWithForce.py index 9162d1cfe..6f7202525 100644 --- a/apps/benchmarks/FluidParticleCoupling/GeneratedLBMWithForce.py +++ b/apps/benchmarks/FluidParticleCoupling/GeneratedLBMWithForce.py @@ -1,45 +1,215 @@ import sympy as sp +from sympy.core.cache import clear_cache import pystencils as ps -from lbmpy.creationfunctions import create_lb_method_from_existing, create_lb_method +from lbmpy.creationfunctions import create_lb_method_from_existing, create_lb_ast, create_lb_method from lbmpy_walberla import generate_lattice_model from pystencils_walberla import CodeGeneration +from pystencils_walberla import get_vectorize_instruction_set from lbmpy.creationfunctions import create_lb_collision_rule -from lbmpy.moments import is_even, get_order, MOMENT_SYMBOLS +from lbmpy.moments import MOMENT_SYMBOLS, is_even, get_order from lbmpy.stencils import get_stencil from lbmpy.forcemodels import Luo +from collections import OrderedDict + with CodeGeneration() as ctx: forcing=(sp.symbols("fx"),0,0) - omegaVisc = sp.Symbol("omega_visc") - omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') - omegaMagic = sp.Symbol("omega_magic") - stencil = get_stencil("D3Q19", 'walberla') - forcemodel=Luo(forcing) - x, y, z = MOMENT_SYMBOLS - one = sp.Rational(1, 1) - sq = x ** 2 + y ** 2 + z ** 2 - moments = [ - [one, x, y, z], # [0, 3, 5, 7] - [sq - 1], # [1] - [3 * sq ** 2 - 6 * sq + 1], # [2] - [(3 * sq - 5) * x, (3 * sq - 5) * y, (3 * sq - 5) * z], # [4, 6, 8] - [3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 11, 13, 14, 15] - [(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12] - [(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18] - ] - - # relaxation rate for first group of moments (1,x,y,z) is set to zero internally - relaxation_rates=[omegaBulk.center_vector, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaVisc, omegaMagic] - - methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False, - force_model=forcemodel, nested_moments=moments, relaxation_rates=relaxation_rates) - - #print(methodWithForce.relaxation_rates) - #print(methodWithForce.moment_matrix) - - collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) - generate_lattice_model(ctx, 'GeneratedLBMWithForce', collision_rule, field_layout='fzyx') + generatedMethod = "TRTlike" + #generatedMethod = "D3Q27TRTlike" + #generatedMethod = "cumulant" + #generatedMethod = "cumulantTRT" + + print("Generating " + generatedMethod + " LBM method") + + clear_cache() + + cpu_vectorize_info = {'instruction_set': get_vectorize_instruction_set(ctx)} + + if generatedMethod == "TRTlike": + omegaVisc = sp.Symbol("omega_visc") + omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') + omegaMagic = sp.Symbol("omega_magic") + stencil = get_stencil("D3Q19", 'walberla') + + x, y, z = MOMENT_SYMBOLS + one = sp.Rational(1, 1) + sq = x ** 2 + y ** 2 + z ** 2 + moments = [ + [one, x, y, z], # [0, 3, 5, 7] + [sq - 1], # [1] + [3 * sq ** 2 - 6 * sq + 1], # [2] + [(3 * sq - 5) * x, (3 * sq - 5) * y, (3 * sq - 5) * z], # [4, 6, 8] + [3 * x ** 2 - sq, y ** 2 - z ** 2, x * y, y * z, x * z], # [9, 11, 13, 14, 15] + [(2 * sq - 3) * (3 * x ** 2 - sq), (2 * sq - 3) * (y ** 2 - z ** 2)], # [10, 12] + [(y ** 2 - z ** 2) * x, (z ** 2 - x ** 2) * y, (x ** 2 - y ** 2) * z] # [16, 17, 18] + ] + + # relaxation rate for first group of moments (1,x,y,z) is set to zero internally + relaxation_rates=[omegaBulk.center_vector, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaVisc, omegaMagic] + + methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False, + force_model=forcemodel, nested_moments=moments, relaxation_rates=relaxation_rates) + + #print(methodWithForce.relaxation_rates) + #print(methodWithForce.moment_matrix) + collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) + generate_lattice_model(ctx, 'GeneratedLBMWithForce', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + + if generatedMethod == "D3Q27TRTlike": + + omegaVisc = sp.Symbol("omega_visc") + omegaBulk = ps.fields("omega_bulk: [3D]", layout='fzyx') + omegaMagic = sp.Symbol("omega_magic") + stencil = get_stencil("D3Q27", 'walberla') + + relaxation_rates=[omegaVisc, omegaBulk.center_vector, omegaMagic, omegaVisc, omegaMagic, omegaVisc] + + methodWithForce = create_lb_method(stencil=stencil, method='mrt', maxwellian_moments=False,weighted=True, compressible=False, + force_model=forcemodel, relaxation_rates=relaxation_rates) + + collision_rule = create_lb_collision_rule(lb_method=methodWithForce, optimization={'cse_global': True}) + generate_lattice_model(ctx, 'GeneratedLBMWithForce', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + + if generatedMethod == "cumulant": + + x,y,z = MOMENT_SYMBOLS + + cumulants = [0] * 27 + + cumulants[0] = sp.sympify(1) #000 + + cumulants[1] = x #100 + cumulants[2] = y #010 + cumulants[3] = z #001 + + cumulants[4] = x*y #110 + cumulants[5] = x*z #101 + cumulants[6] = y*z #011 + + cumulants[7] = x**2 - y**2 #200 - 020 + cumulants[8] = x**2 - z**2 #200 - 002 + cumulants[9] = x**2 + y**2 + z**2 #200 + 020 + 002 + + cumulants[10] = x*y**2 + x*z**2 #120 + 102 + cumulants[11] = x**2*y + y*z**2 #210 + 012 + cumulants[12] = x**2*z + y**2*z #201 + 021 + cumulants[13] = x*y**2 - x*z**2 #120 - 102 + cumulants[14] = x**2*y - y*z**2 #210 - 012 + cumulants[15] = x**2*z - y**2*z #201 - 021 + + cumulants[16] = x*y*z #111 + + cumulants[17] = x**2*y**2 - 2*x**2*z**2 + y**2*z**2 # 220- 2*202 +022 + cumulants[18] = x**2*y**2 + x**2*z**2 - 2*y**2*z**2 # 220 + 202 - 2*002 + cumulants[19] = x**2*y**2 + x**2*z**2 + y**2*z**2 # 220 + 202 + 022 + + cumulants[20] = x**2*y*z # 211 + cumulants[21] = x*y**2*z # 121 + cumulants[22] = x*y*z**2 # 112 + + cumulants[23] = x**2*y**2*z # 221 + cumulants[24] = x**2*y*z**2 # 212 + cumulants[25] = x*y**2*z**2 # 122 + + cumulants[26] = x**2*y**2*z**2 # 222 + + def get_relaxation_rate(cumulant, omega): + if get_order(cumulant) <= 1: + return 0 + elif get_order(cumulant) == 2 and cumulant != x**2 + y**2 + z**2: + return omega + else: + return 1 + + stencil = get_stencil("D3Q27", 'walberla') + + omega = sp.Symbol("omega") + rr_dict = OrderedDict((c, get_relaxation_rate(c, omega)) + for c in cumulants) + + from lbmpy.methods import create_with_continuous_maxwellian_eq_moments + my_method = create_with_continuous_maxwellian_eq_moments(stencil, rr_dict, cumulant=True, compressible=True, force_model=forcemodel) + + collision_rule = create_lb_collision_rule(lb_method=my_method, + optimization={"cse_global": True, + "cse_pdfs": False}) + + print(my_method.relaxation_rates) + + generate_lattice_model(ctx, 'GeneratedLBMWithForce', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + + + if generatedMethod == "cumulantTRT": + + x,y,z = MOMENT_SYMBOLS + + cumulants = [0] * 27 + + cumulants[0] = sp.sympify(1) #000 + + cumulants[1] = x #100 + cumulants[2] = y #010 + cumulants[3] = z #001 + + cumulants[4] = x*y #110 + cumulants[5] = x*z #101 + cumulants[6] = y*z #011 + + cumulants[7] = x**2 - y**2 #200 - 020 + cumulants[8] = x**2 - z**2 #200 - 002 + cumulants[9] = x**2 + y**2 + z**2 #200 + 020 + 002 + + cumulants[10] = x*y**2 + x*z**2 #120 + 102 + cumulants[11] = x**2*y + y*z**2 #210 + 012 + cumulants[12] = x**2*z + y**2*z #201 + 021 + cumulants[13] = x*y**2 - x*z**2 #120 - 102 + cumulants[14] = x**2*y - y*z**2 #210 - 012 + cumulants[15] = x**2*z - y**2*z #201 - 021 + + cumulants[16] = x*y*z #111 + + cumulants[17] = x**2*y**2 - 2*x**2*z**2 + y**2*z**2 # 220- 2*202 +022 + cumulants[18] = x**2*y**2 + x**2*z**2 - 2*y**2*z**2 # 220 + 202 - 2*002 + cumulants[19] = x**2*y**2 + x**2*z**2 + y**2*z**2 # 220 + 202 + 022 + + cumulants[20] = x**2*y*z # 211 + cumulants[21] = x*y**2*z # 121 + cumulants[22] = x*y*z**2 # 112 + + cumulants[23] = x**2*y**2*z # 221 + cumulants[24] = x**2*y*z**2 # 212 + cumulants[25] = x*y**2*z**2 # 122 + + cumulants[26] = x**2*y**2*z**2 # 222 + + def get_relaxation_rate(cumulant, omegaVisc, omegaMagic): + if get_order(cumulant) <= 1: + return 0 + elif is_even(cumulant): + return omegaVisc + else: + return omegaMagic + + stencil = get_stencil("D3Q27", 'walberla') + + omegaVisc = sp.Symbol("omega_visc") + omegaMagic = sp.Symbol("omega_magic") + + rr_dict = OrderedDict((c, get_relaxation_rate(c, omegaVisc, omegaMagic)) + for c in cumulants) + + from lbmpy.methods import create_with_continuous_maxwellian_eq_moments + my_method = create_with_continuous_maxwellian_eq_moments(stencil, rr_dict, cumulant=True, compressible=True, force_model=forcemodel) + + collision_rule = create_lb_collision_rule(lb_method=my_method, + optimization={"cse_global": True, + "cse_pdfs": False}) + + print(my_method.relaxation_rates) + + generate_lattice_model(ctx, 'GeneratedLBMWithForce', collision_rule, field_layout='fzyx', cpu_vectorize_info=cpu_vectorize_info) + diff --git a/apps/benchmarks/FluidParticleCoupling/LubricationForceEvaluation.cpp b/apps/benchmarks/FluidParticleCoupling/LubricationForceEvaluation.cpp index dcb7737fe..e17092473 100644 --- a/apps/benchmarks/FluidParticleCoupling/LubricationForceEvaluation.cpp +++ b/apps/benchmarks/FluidParticleCoupling/LubricationForceEvaluation.cpp @@ -52,6 +52,7 @@ #include "lbm_mesapd_coupling/mapping/ParticleMapping.h" #include "lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h" #include "lbm_mesapd_coupling/momentum_exchange_method/boundary/CurvedLinear.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/boundary/SimpleBB.h" #include "lbm_mesapd_coupling/utility/ParticleSelector.h" #include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h" #include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h" @@ -115,7 +116,8 @@ const uint_t FieldGhostLayers = 1; const FlagUID Fluid_Flag( "fluid" ); const FlagUID FreeSlip_Flag( "free slip" ); -const FlagUID MO_Flag( "moving obstacle" ); +const FlagUID MO_SBB_Flag( "moving obstacle sbb" ); +const FlagUID MO_CLI_Flag( "moving obstacle cli" ); const FlagUID FormerMO_Flag( "former moving obstacle" ); ///////////////////////////////////// @@ -127,8 +129,9 @@ class MyBoundaryHandling public: using FreeSlip_T = lbm::FreeSlip< LatticeModel_T, FlagField_T>; - using MO_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; - using Type = BoundaryHandling< FlagField_T, Stencil_T, FreeSlip_T, MO_T >; + using MO_SBB_T = lbm_mesapd_coupling::SimpleBB< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using MO_CLI_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using Type = BoundaryHandling< FlagField_T, Stencil_T, FreeSlip_T, MO_SBB_T, MO_CLI_T >; MyBoundaryHandling( const BlockDataID & flagFieldID, const BlockDataID & pdfFieldID, const BlockDataID & particleFieldID, const shared_ptr<ParticleAccessor_T>& ac) : @@ -147,7 +150,8 @@ public: Type * handling = new Type( "moving obstacle boundary handling", flagField, fluid, FreeSlip_T( "FreeSlip", FreeSlip_Flag, pdfField, flagField, fluid ), - MO_T( "MO", MO_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ) ); + MO_SBB_T( "SBB", MO_SBB_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ), + MO_CLI_T( "CLI", MO_CLI_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ) ); const auto freeslip = flagField->getFlag( FreeSlip_Flag ); @@ -237,6 +241,7 @@ int main( int argc, char **argv ) real_t magicNumber = real_t(3)/real_t(16); bool useOmegaBulkAdaption = false; real_t adaptionLayerSize = real_t(2); + bool useSBB = false; // 1: translation in normal direction -> normal Lubrication force // 2: translation in tangential direction -> tangential Lubrication force and torque @@ -246,19 +251,20 @@ int main( int argc, char **argv ) for( int i = 1; i < argc; ++i ) { - if( std::strcmp( argv[i], "--sphWallTest" ) == 0 ) { sphSphTest = false; continue; } - if( std::strcmp( argv[i], "--noLogging" ) == 0 ) { fileIO = false; continue; } - if( std::strcmp( argv[i], "--vtkIOFreq" ) == 0 ) { vtkIOFreq = uint_c( std::atof( argv[++i] ) ); continue; } - if( std::strcmp( argv[i], "--setup" ) == 0 ) { setup = uint_c( std::atof( argv[++i] ) ); continue; } - if( std::strcmp( argv[i], "--baseFolder" ) == 0 ) { baseFolder = argv[++i]; continue; } - if( std::strcmp( argv[i], "--diameter" ) == 0 ) { radius = real_t(0.5)*real_c(std::atof(argv[++i])); continue; } + if( std::strcmp( argv[i], "--sphWallTest" ) == 0 ) { sphSphTest = false; continue; } + if( std::strcmp( argv[i], "--noLogging" ) == 0 ) { fileIO = false; continue; } + if( std::strcmp( argv[i], "--vtkIOFreq" ) == 0 ) { vtkIOFreq = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--setup" ) == 0 ) { setup = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--baseFolder" ) == 0 ) { baseFolder = argv[++i]; continue; } + if( std::strcmp( argv[i], "--diameter" ) == 0 ) { radius = real_t(0.5)*real_c(std::atof(argv[++i])); continue; } if( std::strcmp( argv[i], "--gapSize" ) == 0 ) { gapSize = real_c(std::atof(argv[++i])); continue; } - if( std::strcmp( argv[i], "--bulkViscRateFactor" ) == 0 ) { bulkViscRateFactor = real_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--bulkViscRateFactor" ) == 0 ) { bulkViscRateFactor = real_c(std::atof( argv[++i] ) ); continue; } if( std::strcmp( argv[i], "--tau" ) == 0 ) { tau = real_c(std::atof( argv[++i] ) ); continue; } - if( std::strcmp( argv[i], "--fileName" ) == 0 ) { fileNameEnding = argv[++i]; continue; } - if( std::strcmp( argv[i], "--magicNumber" ) == 0 ) { magicNumber = real_c(std::atof(argv[++i])); continue; } - if( std::strcmp( argv[i], "--useOmegaBulkAdaption" ) == 0 ) { useOmegaBulkAdaption = true; continue; } - if( std::strcmp( argv[i], "--adaptionLayerSize" ) == 0 ) { adaptionLayerSize = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--fileName" ) == 0 ) { fileNameEnding = argv[++i]; continue; } + if( std::strcmp( argv[i], "--magicNumber" ) == 0 ) { magicNumber = real_c(std::atof(argv[++i])); continue; } + if( std::strcmp( argv[i], "--useOmegaBulkAdaption" ) == 0 ) { useOmegaBulkAdaption = true; continue; } + if( std::strcmp( argv[i], "--adaptionLayerSize" ) == 0 ) { adaptionLayerSize = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--useSBB" ) == 0 ) { useSBB = true; continue; } WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); } @@ -315,6 +321,7 @@ int main( int argc, char **argv ) << " time steps = " << timesteps << "\n" << " fStokes = " << fStokes << "\n" << " setup = " << setup << "\n" + << " useSBB = " << useSBB << "\n" << "-------------------------------------------------------\n" << " domainSize = " << xSize << " x " << ySize << " x " << zSize << "\n" << " blocks = " << xBlocks << " x " << yBlocks << " x " << zBlocks << "\n" @@ -374,7 +381,7 @@ int main( int argc, char **argv ) } else if (setup == 2) { // only tangential translational velocity - p.setLinearVelocity(Vector3<real_t>( real_t(0), velocity, real_t(0))); + p.setLinearVelocity(Vector3<real_t>( real_t(0), real_t(0), velocity)); p.setAngularVelocity(Vector3<real_t>( real_t(0), real_t(0), real_t(0))); } else if (setup == 3) { @@ -406,7 +413,7 @@ int main( int argc, char **argv ) } else if (setup == 2) { // only tangential translational velocity - p.setLinearVelocity(Vector3<real_t>( real_t(0), -velocity, real_t(0))); + p.setLinearVelocity(Vector3<real_t>( real_t(0), real_t(0), -velocity)); p.setAngularVelocity(Vector3<real_t>( real_t(0), real_t(0), real_t(0))); } else if (setup == 3) { @@ -493,7 +500,7 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); @@ -546,7 +553,13 @@ int main( int argc, char **argv ) /////////////// // map particles into the LBM simulation - ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + if(useSBB) + { + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, movingParticleMappingKernel, *accessor, MO_SBB_Flag); + } else + { + ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, movingParticleMappingKernel, *accessor, MO_CLI_Flag); + } // create the timeloop SweepTimeloop timeloop( blocks->getBlockStorage(), timesteps ); @@ -637,7 +650,7 @@ int main( int argc, char **argv ) real_t curTorqueNorm = real_t(0); real_t oldTorqueNorm = real_t(0); - real_t convergenceLimit = real_t(1e-4); + real_t convergenceLimit = real_t(1e-5); // time loop for (uint_t i = 1; i <= timesteps; ++i ) @@ -747,6 +760,7 @@ int main( int argc, char **argv ) loggingFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); loggingFileName += "_mn" + std::to_string(float(magicNumber)); if( useOmegaBulkAdaption ) loggingFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); + if( useSBB ) loggingFileName += "_SBB"; if( !fileNameEnding.empty()) loggingFileName += "_" + fileNameEnding; loggingFileName += ".txt"; diff --git a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp index cac87d6c7..3bb0c57ee 100644 --- a/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp +++ b/apps/benchmarks/FluidParticleCoupling/ObliqueWetCollision.cpp @@ -815,7 +815,7 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); diff --git a/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp b/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp index f1d6ac21e..3f2f613b2 100644 --- a/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp +++ b/apps/benchmarks/FluidParticleCoupling/SettlingSphereInBox.cpp @@ -186,9 +186,10 @@ class SpherePropertyLogger public: SpherePropertyLogger( const shared_ptr< ParticleAccessor_T > & ac, walberla::id_t sphereUid, const std::string & fileName, bool fileIO, - real_t dx_SI, real_t dt_SI, real_t diameter, real_t gravitationalForceMag) : + real_t dx_SI, real_t dt_SI, real_t diameter, real_t gravitationalForceMag, real_t uref) : ac_( ac ), sphereUid_( sphereUid ), fileName_( fileName ), fileIO_(fileIO), - dx_SI_( dx_SI ), dt_SI_( dt_SI ), diameter_( diameter ), gravitationalForceMag_( gravitationalForceMag ), + dx_SI_( dx_SI ), dt_SI_( dt_SI ), diameter_( diameter ), + gravitationalForceMag_( gravitationalForceMag ), uref_(uref), tref_(diameter / uref), position_( real_t(0) ), maxVelocity_( real_t(0) ) { if ( fileIO_ ) @@ -197,7 +198,7 @@ public: { std::ofstream file; file.open( fileName_.c_str() ); - file << "#\t t\t posZ\t gapZ/D\t velZ\t velZ_SI\t fZ\t fZ/fGravi\n"; + file << "#\t t\t t/tref\t posZ\t gapZ/D\t velZ\t velZ_SI\t velZ/uref\t fZ\t fZ/fGravi\n"; file.close(); } } @@ -264,10 +265,9 @@ private: auto velocity_SI = velocity * dx_SI_ / dt_SI_; auto normalizedHydForce = hydForce / gravitationalForceMag_; - - file << timestep << "\t" << real_c(timestep) * dt_SI_ << "\t" + file << timestep << "\t" << real_c(timestep) * dt_SI_ << "\t" << real_c(timestep) / tref_ << "\t" << position[2] << "\t" << scaledPosition[2] - real_t(0.5) - << "\t" << velocity[2] << "\t" << velocity_SI[2] + << "\t" << velocity[2] << "\t" << velocity_SI[2] << "\t" << velocity[2] / uref_ << "\t" << hydForce[2] << "\t" << normalizedHydForce[2] << "\n"; file.close(); @@ -278,7 +278,7 @@ private: const walberla::id_t sphereUid_; std::string fileName_; bool fileIO_; - real_t dx_SI_, dt_SI_, diameter_, gravitationalForceMag_; + real_t dx_SI_, dt_SI_, diameter_, gravitationalForceMag_, uref_, tref_; real_t position_; real_t maxVelocity_; @@ -385,6 +385,8 @@ int main( int argc, char **argv ) real_t adaptionLayerSize = real_t(2); bool useLubricationCorrection = true; + bool useGalileoParameterization = false; + for( int i = 1; i < argc; ++i ) { if( std::strcmp( argv[i], "--shortrun" ) == 0 ) { shortrun = true; continue; } @@ -406,6 +408,7 @@ int main( int argc, char **argv ) if( std::strcmp( argv[i], "--useOmegaBulkAdaption" ) == 0 ) { useOmegaBulkAdaption = true; continue; } if( std::strcmp( argv[i], "--adaptionLayerSize" ) == 0 ) { adaptionLayerSize = real_c(std::atof( argv[++i] )); continue; } if( std::strcmp( argv[i], "--noLubricationCorrection" ) == 0 ) { useLubricationCorrection = false; continue; } + if( std::strcmp( argv[i], "--useGalileoParameterization" ) == 0 ) { useGalileoParameterization = true; continue; } WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); } @@ -433,6 +436,9 @@ int main( int argc, char **argv ) real_t densityFluid_SI; real_t dynamicViscosityFluid_SI; real_t expectedSettlingVelocity_SI; + + // expected velocity given as uMax in experiments of ten Cate (Table 2, E1-E4), with uInfty from Table 1 + // > slightly different Re than in ten Cate's Table 1 switch( fluidType ) { case 1: @@ -494,8 +500,9 @@ int main( int argc, char **argv ) const real_t diameter = diameter_SI / dx_SI; const real_t sphereVolume = math::pi / real_t(6) * diameter * diameter * diameter; - //const real_t dt_SI = characteristicVelocity / ug_SI * dx_SI; // this uses Ga for parameterization - const real_t dt_SI = characteristicVelocity / expectedSettlingVelocity_SI * dx_SI; // this uses Re for parameterization (only possible since settling velocity is known) + + const real_t dt_SI = (useGalileoParameterization) ? characteristicVelocity / ug_SI * dx_SI : // this uses Ga for parameterization, where ug is the characteristic velocity + characteristicVelocity / expectedSettlingVelocity_SI * dx_SI; // this uses Re for parameterization (only possible since settling velocity is known) const real_t viscosity = kinematicViscosityFluid_SI * dt_SI / ( dx_SI * dx_SI ); const real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); @@ -602,7 +609,7 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); @@ -779,17 +786,19 @@ int main( int argc, char **argv ) // evaluation functionality std::string loggingFileName( baseFolder + "/LoggingSettlingSphere_"); loggingFileName += std::to_string(fluidType); + loggingFileName += "_res" + std::to_string(numberOfCellsInHorizontalDirection); loggingFileName += "_recon" + reconstructorType; loggingFileName += "_bvrf" + std::to_string(uint_c(bulkViscRateFactor)); loggingFileName += "_mn" + std::to_string(float(magicNumber)); if( useOmegaBulkAdaption ) loggingFileName += "_uOBA" + std::to_string(uint_c(adaptionLayerSize)); + if( useGalileoParameterization ) loggingFileName += "_Ga"; if( !fileNameEnding.empty()) loggingFileName += "_" + fileNameEnding; loggingFileName += ".txt"; if( fileIO ) { WALBERLA_LOG_INFO_ON_ROOT(" - writing logging output to file \"" << loggingFileName << "\""); } - SpherePropertyLogger<ParticleAccessor_T> logger( accessor, sphereUid, loggingFileName, fileIO, dx_SI, dt_SI, diameter, -gravitationalForce[2] ); + SpherePropertyLogger<ParticleAccessor_T> logger( accessor, sphereUid, loggingFileName, fileIO, dx_SI, dt_SI, diameter, -gravitationalForce[2], characteristicVelocity ); //////////////////////// @@ -832,7 +841,7 @@ int main( int argc, char **argv ) syncCall(); } - ps->forEachParticle(useOpenMP, sphereSelector, *accessor, addHydrodynamicInteraction, *accessor ); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor ); ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); // lubrication correction diff --git a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp index 0e0263ff5..9c963fa9d 100644 --- a/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp +++ b/apps/benchmarks/FluidParticleCoupling/SphereMovingWithPrescribedVelocity.cpp @@ -655,7 +655,7 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx ); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); diff --git a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp index cd84f67e4..1ce306d76 100644 --- a/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp +++ b/apps/benchmarks/FluidParticleCoupling/SphereWallCollision.cpp @@ -132,6 +132,10 @@ using ScalarField_T = GhostLayerField< real_t, 1>; const uint_t FieldGhostLayers = 1; +#define USE_TRTLIKE +//#define USE_D3Q27TRTLIKE +//#define USE_CUMULANT + /////////// // FLAGS // /////////// @@ -758,10 +762,12 @@ int main( int argc, char **argv ) + "_mn" + std::to_string(magicNumber); if(useOmegaBulkAdaption) checkPointFileName +="_omegaBulkAdaption"; if(applyOutflowBCAtTop) checkPointFileName +="_outflowBC"; -#ifdef USE_TRT_LIKE_LATTICE_MODEL - checkPointFileName +="_TRTlike"; -#else - checkPointFileName += "_other"; +#if defined(USE_TRTLIKE) + checkPointFileName += "_trtlike"; +#elif defined(USE_CUMULANT) + checkPointFileName += "_cumulant"; +#elif defined(USE_D3Q27TRTLIKE) + checkPointFileName += "_d3q27trtlike"; #endif WALBERLA_LOG_INFO_ON_ROOT("Checkpointing:"); @@ -852,10 +858,10 @@ int main( int argc, char **argv ) { WALBERLA_LOG_INFO_ON_ROOT( "Initializing particles from checkpointing file!" ); particleStorageID = blocks->loadBlockData( checkPointFileName + "_mesa.txt", mesa_pd::domain::createBlockForestDataHandling(ps), "Particle Storage" ); - } else { - particleStorageID = blocks->addBlockData(mesa_pd::domain::createBlockForestDataHandling(ps), "Particle Storage"); mesa_pd::mpi::ClearNextNeighborSync CNNS; CNNS(*accessor); + } else { + particleStorageID = blocks->addBlockData(mesa_pd::domain::createBlockForestDataHandling(ps), "Particle Storage"); } // bounding planes @@ -901,14 +907,19 @@ int main( int argc, char **argv ) //////////////////////// // add omega bulk field - BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx, uint_t(0) ); + BlockDataID omegaBulkFieldID = field::addToStorage<ScalarField_T>( blocks, "omega bulk field", omegaBulk, field::fzyx); // create the lattice model real_t lambda_e = lbm::collision_model::TRT::lambda_e( omega ); real_t lambda_d = lbm::collision_model::TRT::lambda_d( omega, magicNumber ); #ifdef WALBERLA_BUILD_WITH_CODEGEN +#ifdef USE_CUMULANT + WALBERLA_LOG_INFO_ON_ROOT("Using generated cumulant lattice model!"); + LatticeModel_T latticeModel = LatticeModel_T(omega); +#elif defined(USE_TRTLIKE) || defined(USE_D3Q27TRTLIKE) WALBERLA_LOG_INFO_ON_ROOT("Using generated TRT-like lattice model!"); LatticeModel_T latticeModel = LatticeModel_T(omegaBulkFieldID, lambda_d, lambda_e); +#endif #else WALBERLA_LOG_INFO_ON_ROOT("Using waLBerla built-in MRT lattice model and ignoring omega bulk field since not supported!"); LatticeModel_T latticeModel = LatticeModel_T(lbm::collision_model::D3Q19MRT( omegaBulk, omegaBulk, lambda_d, lambda_e, lambda_e, lambda_d )); @@ -1117,11 +1128,7 @@ int main( int argc, char **argv ) }else if( reconstructorType == "Ext") { auto sphereNormalExtrapolationDirectionFinder = make_shared<lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder>(blocks); -#ifdef USE_TRT_LIKE_LATTICE_MODEL - auto extrapolationReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T, lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder, true>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); -#else auto extrapolationReconstructor = lbm_mesapd_coupling::makeExtrapolationReconstructor<BoundaryHandling_T, lbm_mesapd_coupling::SphereNormalExtrapolationDirectionFinder, false>(blocks, boundaryHandlingID, sphereNormalExtrapolationDirectionFinder, uint_t(3), true); -#endif timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "LBM Communication" ) << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, extrapolationReconstructor, conserveMomentum)), "PDF Restore" ); } else @@ -1308,9 +1315,8 @@ int main( int argc, char **argv ) } else { - lbm_mesapd_coupling::RegularParticlesSelector sphereSelector; lbm_mesapd_coupling::AddHydrodynamicInteractionKernel addHydrodynamicInteraction; - ps->forEachParticle(useOpenMP, sphereSelector, *accessor, addHydrodynamicInteraction, *accessor ); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor ); } hydForce = getForce(sphereUid,*accessor) - lubForce - collisionForce; -- GitLab From 10b6305603ef00026c769e17c64fc704b896ad3d Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Tue, 23 Feb 2021 20:48:14 +0000 Subject: [PATCH 74/83] Added new fpcoupling test --- tests/lbm_mesapd_coupling/CMakeLists.txt | 32 +- .../ForceBetweenTwoStationaryObjects.cpp | 16 +- .../HydrodynamicForceOnMultipleBlocks.cpp | 327 ++++++++++++++++++ 3 files changed, 354 insertions(+), 21 deletions(-) create mode 100644 tests/lbm_mesapd_coupling/utility/HydrodynamicForceOnMultipleBlocks.cpp diff --git a/tests/lbm_mesapd_coupling/CMakeLists.txt b/tests/lbm_mesapd_coupling/CMakeLists.txt index b17481236..90cf13471 100644 --- a/tests/lbm_mesapd_coupling/CMakeLists.txt +++ b/tests/lbm_mesapd_coupling/CMakeLists.txt @@ -13,15 +13,15 @@ waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_MovingMapping PROCESSES 3) waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_MEM_DragForceSphere FILES momentum_exchange_method/DragForceSphere.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field vtk ) waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_DragForceSphere COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_DragForceSphere> --funcTest PROCESSES 2) -waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects FILES momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field vtk ) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSS1 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSS2 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useSBB PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSS3 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useCompressible PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSS4 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --systemVelocity 0.1 PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSW1 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useSphereWallSetup PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSW2 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useSphereWallSetup --useSBB PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSW3 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useSphereWallSetup --useCompressible PROCESSES 1) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjectsSW4 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceBetweenTwoStationaryObjects> --useSphereWallSetup --systemVelocity 0.1 PROCESSES 1) +waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs FILES momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field vtk ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSS1 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSS2 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useSBB PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSS3 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useCompressible PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSS4 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --systemVelocity 0.1 PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSW1 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useSphereWallSetup PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSW2 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useSphereWallSetup --useSBB PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSW3 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useSphereWallSetup --useCompressible PROCESSES 1) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjsSW4 COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_ForceTwoStatObjs> --useSphereWallSetup --systemVelocity 0.1 PROCESSES 1) waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_MEM_SettlingSphere FILES momentum_exchange_method/SettlingSphere.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field vtk ) waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_SettlingSphere COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_MEM_SettlingSphere> --funcTest PROCESSES 4) @@ -32,9 +32,15 @@ waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_PdfReconstruction PROCESSES waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_MEM_UpdateParticleMapping FILES momentum_exchange_method/UpdateParticleMapping.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field vtk) waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_MEM_UpdateParticleMapping PROCESSES 1) -waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_UTILITY_LubricationCorrection FILES utility/LubricationCorrection.cpp DEPENDS mesa_pd lbm_mesapd_coupling ) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTILITY_LubricationCorrection PROCESSES 1 ) +waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_UTIL_LubricationCorrection FILES utility/LubricationCorrection.cpp DEPENDS mesa_pd lbm_mesapd_coupling ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_LubricationCorrection PROCESSES 1 ) -waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_UTILITY_InspectionProbe FILES utility/InspectionProbe.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field ) -waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTILITY_InspectionProbe PROCESSES 1 ) +waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_UTIL_InspectionProbe FILES utility/InspectionProbe.cpp DEPENDS core mesa_pd lbm lbm_mesapd_coupling domain_decomposition field ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_InspectionProbe PROCESSES 1 ) + +waLBerla_compile_test( NAME LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks FILES utility/HydrodynamicForceOnMultipleBlocks.cpp DEPENDS mesa_pd lbm_mesapd_coupling ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks_EulerAvg COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks> PROCESSES 4 ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks_VVAvg COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks> --useVV PROCESSES 4 ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks_EulerNoAvg COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks> --noForceAveraging PROCESSES 4 ) +waLBerla_execute_test( NAME LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks_VVNoAvg COMMAND $<TARGET_FILE:LBM_MESAPD_COUPLING_UTIL_HydForceMultBlocks> --noForceAveraging --useVV PROCESSES 4 ) diff --git a/tests/lbm_mesapd_coupling/momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp b/tests/lbm_mesapd_coupling/momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp index e244543af..8e994002b 100644 --- a/tests/lbm_mesapd_coupling/momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp +++ b/tests/lbm_mesapd_coupling/momentum_exchange_method/ForceBetweenTwoStationaryObjects.cpp @@ -300,9 +300,10 @@ int main( int argc, char **argv ) bool useCompressible = false; bool useSBB = false; bool useSphereWallSetup = false; - real_t surfaceDistance = real_t(0.5); + real_t surfaceDistance = real_t(0.1); real_t systemVelocity = real_t(0); uint_t timesteps = uint_t(10); + real_t radius = real_t(5); for( int i = 1; i < argc; ++i ) { @@ -311,6 +312,7 @@ int main( int argc, char **argv ) if( std::strcmp( argv[i], "--useSphereWallSetup" ) == 0 ) { useSphereWallSetup = true; continue;} if( std::strcmp( argv[i], "--surfaceDistance" ) == 0 ) { surfaceDistance = real_c(std::atof( argv[++i])); continue;} if( std::strcmp( argv[i], "--systemVelocity" ) == 0 ) { systemVelocity = real_c(std::atof( argv[++i])); continue;} + if( std::strcmp( argv[i], "--radius" ) == 0 ) { radius = real_c(std::atof( argv[++i])); continue;} if( std::strcmp( argv[i], "--timesteps" ) == 0 ) { timesteps = uint_c(std::atof( argv[++i])); continue;} WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); } @@ -320,8 +322,7 @@ int main( int argc, char **argv ) // SIMULATION PROPERTIES // /////////////////////////// - const uint_t length = uint_t(32); - const real_t radius = real_t(5); + const uint_t length = uint_t(real_t(4) * radius); const Vector3<real_t> velocity(systemVelocity, real_t(0), real_t(0)); /////////////////////////// @@ -347,7 +348,7 @@ int main( int argc, char **argv ) auto accessor = make_shared<ParticleAccessor_T >(ps, ss); auto sphereShape = ss->create<mesa_pd::data::Sphere>( radius ); - createPlaneSetup(ps, ss, walberla::math::AABB(real_t(0), real_t(0), real_t(0), length, length, length), velocity); + createPlaneSetup(ps, ss, walberla::math::AABB(real_t(0), real_t(0), real_t(0), real_c(length), real_c(length), real_c(length)), velocity); walberla::id_t sphereID; if(useSphereWallSetup) @@ -410,10 +411,9 @@ int main( int argc, char **argv ) auto hydrodynamicForce = accessor->getHydrodynamicForce(idx); //WALBERLA_LOG_INFO(hydrodynamicForce); - for(uint_t comp = 0; comp < 3; ++comp) - { - WALBERLA_CHECK_FLOAT_EQUAL(hydrodynamicForce[comp], real_t(0), "Found non-zero force in component " << comp); - } + + WALBERLA_CHECK_FLOAT_EQUAL(hydrodynamicForce, Vector3<real_t>(real_t(0)), "Found non-zero force"); + lbm_mesapd_coupling::ResetHydrodynamicForceTorqueKernel resetHydrodynamicForceTorque; ps->forEachParticle(false, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); diff --git a/tests/lbm_mesapd_coupling/utility/HydrodynamicForceOnMultipleBlocks.cpp b/tests/lbm_mesapd_coupling/utility/HydrodynamicForceOnMultipleBlocks.cpp new file mode 100644 index 000000000..7f0622dbb --- /dev/null +++ b/tests/lbm_mesapd_coupling/utility/HydrodynamicForceOnMultipleBlocks.cpp @@ -0,0 +1,327 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file HydrodynamicForceOnMultipleBlocks.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + + +#include "blockforest/Initialization.h" + +#include "core/Environment.h" +#include "core/debug/Debug.h" +#include "core/debug/TestSubsystem.h" +#include "core/logging/Logging.h" + +#include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h" +#include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h" +#include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/ParticleFunctions.h" + +#include "mesa_pd/common/ParticleFunctions.h" +#include "mesa_pd/data/ParticleAccessorWithShape.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/ShapeStorage.h" +#include "mesa_pd/data/shape/Sphere.h" +#include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/kernel/DoubleCast.h" +#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/mpi/SyncNextNeighbors.h" +#include "mesa_pd/mpi/ReduceProperty.h" +#include "mesa_pd/mpi/notifications/ForceTorqueNotification.h" +#include "mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h" + + +namespace hydrodynamic_force_blocks +{ + +using namespace walberla; + + +template< typename ParticleAccessor_T> +class SpherePropertyEvaluator +{ +public: + SpherePropertyEvaluator( const shared_ptr< ParticleAccessor_T > & ac, walberla::id_t sphereUid) : + ac_( ac ), sphereUid_( sphereUid ) + { } + + void operator()() + { + Vector3<real_t> pos(real_t(0)); + Vector3<real_t> transVel(real_t(0)); + Vector3<real_t> angularVel(real_t(0)); + Vector3<real_t> force(real_t(0)); + Vector3<real_t> torque(real_t(0)); + + size_t idx = ac_->uidToIdx(sphereUid_); + if( idx != ac_->getInvalidIdx()) + { + if(!mesa_pd::data::particle_flags::isSet( ac_->getFlags(idx), mesa_pd::data::particle_flags::GHOST)) + { + pos = ac_->getPosition(idx); + transVel = ac_->getLinearVelocity(idx); + angularVel = ac_->getAngularVelocity(idx); + force = ac_->getForce(idx); + torque = ac_->getTorque(idx); + } + } + + WALBERLA_MPI_SECTION() + { + mpi::allReduceInplace( pos[0], mpi::SUM ); + mpi::allReduceInplace( pos[1], mpi::SUM ); + mpi::allReduceInplace( pos[2], mpi::SUM ); + + mpi::allReduceInplace( transVel[0], mpi::SUM ); + mpi::allReduceInplace( transVel[1], mpi::SUM ); + mpi::allReduceInplace( transVel[2], mpi::SUM ); + + mpi::allReduceInplace( angularVel[0], mpi::SUM ); + mpi::allReduceInplace( angularVel[1], mpi::SUM ); + mpi::allReduceInplace( angularVel[2], mpi::SUM ); + + mpi::allReduceInplace( force[0], mpi::SUM ); + mpi::allReduceInplace( force[1], mpi::SUM ); + mpi::allReduceInplace( force[2], mpi::SUM ); + + mpi::allReduceInplace( torque[0], mpi::SUM ); + mpi::allReduceInplace( torque[1], mpi::SUM ); + mpi::allReduceInplace( torque[2], mpi::SUM ); + } + + position_ = pos; + linearVel_ = transVel; + angularVel_ = angularVel; + force_ = force; + torque_ = torque; + } + + Vector3<real_t> getPosition() const { return position_; } + Vector3<real_t> getLinearVel() const { return linearVel_; } + Vector3<real_t> getAngularVel() const { return angularVel_; } + Vector3<real_t> getForce() const { return force_; } + Vector3<real_t> getTorque() const { return torque_; } + + +private: + + shared_ptr< ParticleAccessor_T > ac_; + const walberla::id_t sphereUid_; + + Vector3<real_t> position_; + Vector3<real_t> linearVel_; + Vector3<real_t> angularVel_; + Vector3<real_t> force_; + Vector3<real_t> torque_; +}; + +template< typename ParticleAccessor_T> +void applyHydrodynamicForceTorqueOnSphere(ParticleAccessor_T & accessor, walberla::id_t sphereUid, + Vector3<real_t> hydForce, Vector3<real_t> hydTorque) +{ + + uint_t numberOfProcessesWithKnowledgeOfThisSphere = uint_t(0); + size_t idx = accessor.uidToIdx(sphereUid); + if( idx != accessor.getInvalidIdx()) + { + ++numberOfProcessesWithKnowledgeOfThisSphere; + } + + WALBERLA_MPI_SECTION() { + mpi::allReduceInplace(numberOfProcessesWithKnowledgeOfThisSphere, mpi::SUM); + } + + if( idx != accessor.getInvalidIdx()) + { + accessor.setHydrodynamicForce(idx, hydForce / real_t(numberOfProcessesWithKnowledgeOfThisSphere) ); + accessor.setHydrodynamicTorque(idx, hydTorque / real_t(numberOfProcessesWithKnowledgeOfThisSphere) ); + } +} + + +/* + * Two spheres travelling through several blocks. moved by constant (distributed) hydrodynamic force. + * This checks setting hydrodynamic forces onto particles and force averaging in parallel setup. + * Velocity of both spheres have to be equal throughout the simulation. + * + */ +int main( int argc, char ** argv ) +{ + debug::enterTestMode(); + + mpi::Environment env( argc, argv ); + + const Vector3<uint_t> domainSize( 4 * 32, 32, 32 ); + const Vector3<uint_t> numberOfBlocksPerDirection(4, 1, 1 ); + Vector3<uint_t> cellsPerBlockPerDirection( domainSize[0] / numberOfBlocksPerDirection[0], + domainSize[1] / numberOfBlocksPerDirection[1], + domainSize[2] / numberOfBlocksPerDirection[2] ); + + real_t xPos1 = real_t(0); + real_t xPos2 = real_t(45.36281); // random + + real_t radius = real_t(2); + + Vector3<real_t> hydForce( real_t(0.75), 0, 0); + Vector3<real_t> hydTorque( real_t(0.75), 0, 0); + + real_t dt = real_t(1); + real_t dx = real_t(1); + uint_t timesteps = 400; + + bool averageForceTorqueOverTwoTimeSteps = true; + bool useVelocityVerlet = false; + + + for( int i = 1; i < argc; ++i ) + { + if( std::strcmp( argv[i], "--timesteps" ) == 0 ) { timesteps = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--noForceAveraging" ) == 0 ) { averageForceTorqueOverTwoTimeSteps = false; continue; } + if( std::strcmp( argv[i], "--useVV" ) == 0 ) { useVelocityVerlet = true; continue; } + WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); + } + + // setup as in a coupled simulation even though not needed here for mesa_pd only setup + auto blocks = blockforest::createUniformBlockGrid( numberOfBlocksPerDirection[0], numberOfBlocksPerDirection[1], numberOfBlocksPerDirection[2], + cellsPerBlockPerDirection[0], cellsPerBlockPerDirection[1], cellsPerBlockPerDirection[2], dx, + 0, false, false, + true, false, false, //periodicity + false ); + + + auto rpdDomain = walberla::make_shared<mesa_pd::domain::BlockForestDomain>(blocks->getBlockForestPointer()); + + auto ps = walberla::make_shared<mesa_pd::data::ParticleStorage>(2); + auto ss = walberla::make_shared<mesa_pd::data::ShapeStorage>(); + using ParticleAccessor_T = mesa_pd::data::ParticleAccessorWithShape; + auto accessor = walberla::make_shared<ParticleAccessor_T >(ps, ss); + + auto sphereShape = ss->create<mesa_pd::data::Sphere>( radius ); + ss->shapes[sphereShape]->updateMassAndInertia(real_t(1)); + + Vector3<real_t> initialPosition1( xPos1, real_t(0.5) * real_c(domainSize[1]), real_t(0.5) * real_c(domainSize[2])); + Vector3<real_t> initialPosition2( xPos2, real_t(0.5) * real_c(domainSize[1]), real_t(0.5) * real_c(domainSize[2])); + + walberla::id_t sphereUid1 = 0; + if (rpdDomain->isContainedInProcessSubdomain( uint_c(mpi::MPIManager::instance()->rank()), initialPosition1 )) + { + mesa_pd::data::Particle&& p = *ps->create(); + p.setPosition(initialPosition1); + p.setInteractionRadius(radius); + p.setOwner(mpi::MPIManager::instance()->rank()); + p.setShapeID(sphereShape); + sphereUid1 = p.getUid(); + } + mpi::allReduceInplace(sphereUid1, mpi::SUM); + + walberla::id_t sphereUid2 = 0; + if (rpdDomain->isContainedInProcessSubdomain( uint_c(mpi::MPIManager::instance()->rank()), initialPosition2 )) + { + mesa_pd::data::Particle&& p = *ps->create(); + p.setPosition(initialPosition2); + p.setInteractionRadius(radius); + p.setOwner(mpi::MPIManager::instance()->rank()); + p.setShapeID(sphereShape); + sphereUid2 = p.getUid(); + } + mpi::allReduceInplace(sphereUid2, mpi::SUM); + + + // mesa_pd functionality + mesa_pd::kernel::VelocityVerletPreForceUpdate vvIntegratorPreForce( dt ); + mesa_pd::kernel::VelocityVerletPostForceUpdate vvIntegratorPostForce( dt ); + mesa_pd::kernel::ExplicitEuler explEulerIntegrator( dt ); + mesa_pd::mpi::ReduceProperty reduceProperty; + + std::function<void(void)> syncCall = [ps,rpdDomain](){ + const real_t overlap = real_t( 1.5 ); + mesa_pd::mpi::SyncNextNeighbors syncNextNeighborFunc; + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + }; + + syncCall(); + + // coupling functionality + lbm_mesapd_coupling::AddHydrodynamicInteractionKernel addHydrodynamicInteraction; + lbm_mesapd_coupling::ResetHydrodynamicForceTorqueKernel resetHydrodynamicForceTorque; + lbm_mesapd_coupling::AverageHydrodynamicForceTorqueKernel averageHydrodynamicForceTorque; + + // evaluation functionality + SpherePropertyEvaluator<ParticleAccessor_T> sphere1Eval(accessor, sphereUid1); + SpherePropertyEvaluator<ParticleAccessor_T> sphere2Eval(accessor, sphereUid2); + + bool useOpenMP = false; + for(uint_t t = 0; t < timesteps; ++t) { + + // set hydrodynamic force/torque distributed + applyHydrodynamicForceTorqueOnSphere(*accessor, sphereUid1, hydForce, hydTorque); + applyHydrodynamicForceTorqueOnSphere(*accessor, sphereUid2, hydForce, hydTorque); + + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + + if (averageForceTorqueOverTwoTimeSteps) { + if (t == 0) { + lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor); + } + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor); + } + + if (useVelocityVerlet) { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPreForce, *accessor); + syncCall(); + } + + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor); + + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + + // check sphere properties + sphere1Eval(); + sphere2Eval(); + + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getLinearVel()[0], sphere2Eval.getLinearVel()[0], "time step " << t << " mismatch in linear vel[0]"); + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getLinearVel()[1], sphere2Eval.getLinearVel()[1], "time step " << t << " mismatch in linear vel[1]"); + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getLinearVel()[2], sphere2Eval.getLinearVel()[2], "time step " << t << " mismatch in linear vel[2]"); + + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getAngularVel()[0], sphere2Eval.getAngularVel()[0], "time step " << t << " mismatch in angular vel[0]"); + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getAngularVel()[1], sphere2Eval.getAngularVel()[1], "time step " << t << " mismatch in angular vel[1]"); + WALBERLA_CHECK_FLOAT_EQUAL(sphere1Eval.getAngularVel()[2], sphere2Eval.getAngularVel()[2], "time step " << t << " mismatch in angular vel[2]"); + + // particle integration + if( useVelocityVerlet ) ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPostForce, *accessor); + else ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, explEulerIntegrator, *accessor); + + syncCall(); + + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + + //WALBERLA_LOG_INFO_ON_ROOT(t << " " << sphere1Eval.getPosition()[0] << " " << sphere1Eval.getLinearVel()[0] << " " << sphere1Eval.getForce()[0] << " " << sphere1Eval.getAngularVel()[0] << " " << sphere1Eval.getTorque()[0] ); + } + + return EXIT_SUCCESS; +} + +} //namespace hydrodynamic_force_blocks + +int main( int argc, char ** argv ) +{ + return hydrodynamic_force_blocks::main(argc, argv); +} -- GitLab From 80c258a619f448225380bececd19dedc731f4cbf Mon Sep 17 00:00:00 2001 From: Christoph Rettinger <christoph.rettinger@fau.de> Date: Wed, 24 Feb 2021 17:07:17 +0000 Subject: [PATCH 75/83] Fluid-particle coupling load balancing benchmark --- apps/benchmarks/CMakeLists.txt | 1 + .../CMakeLists.txt | 3 + .../FluidParticleWorkloadDistribution.cpp | 1730 +++++++++++++++++ .../FluidParticleWorkloadEvaluation.cpp | 956 +++++++++ .../Utility.h | 67 + src/lbm_mesapd_coupling/amr/BlockInfo.h | 27 +- src/lbm_mesapd_coupling/amr/InfoCollection.h | 63 +- .../MetisAssignmentFunctor.cpp | 97 + .../MetisAssignmentFunctor.h | 66 + .../WeightAssignmentFunctor.h | 67 + .../WeightEvaluationFunctions.h | 36 + 11 files changed, 3078 insertions(+), 35 deletions(-) create mode 100644 apps/benchmarks/FluidParticleCouplingWithLoadBalancing/CMakeLists.txt create mode 100644 apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadDistribution.cpp create mode 100644 apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadEvaluation.cpp create mode 100644 apps/benchmarks/FluidParticleCouplingWithLoadBalancing/Utility.h create mode 100644 src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.cpp create mode 100644 src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.h create mode 100644 src/lbm_mesapd_coupling/amr/weight_assignment/WeightAssignmentFunctor.h create mode 100644 src/lbm_mesapd_coupling/amr/weight_assignment/WeightEvaluationFunctions.h diff --git a/apps/benchmarks/CMakeLists.txt b/apps/benchmarks/CMakeLists.txt index d16b4255d..7d5901c16 100644 --- a/apps/benchmarks/CMakeLists.txt +++ b/apps/benchmarks/CMakeLists.txt @@ -4,6 +4,7 @@ add_subdirectory( DEM ) add_subdirectory( MeshDistance ) add_subdirectory( CouetteFlow ) add_subdirectory( FluidParticleCoupling ) +add_subdirectory( FluidParticleCouplingWithLoadBalancing ) add_subdirectory( ForcesOnSphereNearPlaneInShearFlow ) add_subdirectory( GranularGas ) add_subdirectory( IntegratorAccuracy ) diff --git a/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/CMakeLists.txt b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/CMakeLists.txt new file mode 100644 index 000000000..4742f47b6 --- /dev/null +++ b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/CMakeLists.txt @@ -0,0 +1,3 @@ +waLBerla_add_executable( NAME FluidParticleWorkloadEvaluation FILES FluidParticleWorkloadEvaluation.cpp DEPENDS blockforest boundary core field lbm lbm_mesapd_coupling mesa_pd postprocessing timeloop vtk ) + +waLBerla_add_executable( NAME FluidParticleWorkloadDistribution FILES FluidParticleWorkloadDistribution.cpp DEPENDS blockforest boundary core field lbm lbm_mesapd_coupling mesa_pd postprocessing timeloop vtk ) diff --git a/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadDistribution.cpp b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadDistribution.cpp new file mode 100644 index 000000000..9f93af67b --- /dev/null +++ b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadDistribution.cpp @@ -0,0 +1,1730 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file FluidParticleWorkloadDistribution.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#include "blockforest/Initialization.h" +#include "blockforest/communication/UniformBufferedScheme.h" +#include "blockforest/loadbalancing/all.h" +#include "blockforest/AABBRefinementSelection.h" + +#include "boundary/all.h" + +#include "core/DataTypes.h" +#include "core/Environment.h" +#include "core/debug/Debug.h" +#include "core/debug/TestSubsystem.h" +#include "core/math/all.h" +#include "core/timing/RemainingTimeLogger.h" +#include "core/mpi/Broadcast.h" + +#include "domain_decomposition/SharedSweep.h" +#include "domain_decomposition/BlockSweepWrapper.h" + +#include "field/AddToStorage.h" +#include "field/StabilityChecker.h" +#include "field/communication/PackInfo.h" + +#include "lbm/boundary/all.h" +#include "lbm/communication/PdfFieldPackInfo.h" +#include "lbm/field/AddToStorage.h" +#include "lbm/field/PdfField.h" +#include "lbm/field/VelocityFieldWriter.h" +#include "lbm/lattice_model/D3Q19.h" +#include "lbm/sweeps/CellwiseSweep.h" + +#include "lbm_mesapd_coupling/amr/BlockInfo.h" +#include "lbm_mesapd_coupling/amr/InfoCollection.h" +#include "lbm_mesapd_coupling/amr/weight_assignment/WeightEvaluationFunctions.h" +#include "lbm_mesapd_coupling/amr/weight_assignment/WeightAssignmentFunctor.h" +#include "lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.h" +#include "lbm_mesapd_coupling/mapping/ParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/boundary/CurvedLinear.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/Reconstructor.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/PdfReconstructionManager.h" +#include "lbm_mesapd_coupling/utility/AddForceOnParticlesKernel.h" +#include "lbm_mesapd_coupling/utility/ParticleSelector.h" +#include "lbm_mesapd_coupling/DataTypes.h" +#include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h" +#include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h" +#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h" +#include "lbm_mesapd_coupling/utility/InspectionProbe.h" + +#include "mesa_pd/collision_detection/AnalyticContactDetection.h" +#include "mesa_pd/data/ParticleAccessorWithShape.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/ShapeStorage.h" +#include "mesa_pd/data/DataTypes.h" +#include "mesa_pd/data/shape/HalfSpace.h" +#include "mesa_pd/data/shape/Sphere.h" +#include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/domain/BlockForestDataHandling.h" +#include "mesa_pd/kernel/AssocToBlock.h" +#include "mesa_pd/kernel/DoubleCast.h" +#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/LinearSpringDashpot.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/mpi/ClearNextNeighborSync.h" +#include "mesa_pd/mpi/SyncNextNeighbors.h" +#include "mesa_pd/mpi/SyncNextNeighborsBlockForest.h" +#include "mesa_pd/mpi/ReduceProperty.h" +#include "mesa_pd/mpi/ReduceContactHistory.h" +#include "mesa_pd/mpi/ContactFilter.h" +#include "mesa_pd/mpi/notifications/ForceTorqueNotification.h" +#include "mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "timeloop/SweepTimeloop.h" + +#include "vtk/all.h" +#include "field/vtk/all.h" +#include "lbm/vtk/all.h" + +#include "Utility.h" + +namespace fluid_particle_workload_distribution +{ + +/////////// +// USING // +/////////// + +using namespace walberla; +using walberla::uint_t; + +using LatticeModel_T = lbm::D3Q19< lbm::collision_model::TRT, false >; +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; + +using ParticleField_T = lbm_mesapd_coupling::ParticleField_T; +using ParticleAccessor_T = mesa_pd::data::ParticleAccessorWithShape; + +const uint_t FieldGhostLayers = 1; + +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t> ; +using MO_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; +using BoundaryHandling_T = BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_T >; + + +/////////// +// FLAGS // +/////////// + +const FlagUID Fluid_Flag( "fluid" ); +const FlagUID NoSlip_Flag( "no slip" ); +const FlagUID MO_Flag( "moving obstacle" ); +const FlagUID FormerMO_Flag( "former moving obstacle" ); + + +/////////////////////////////////// +// LOAD BALANCING FUNCTIONALITY // +////////////////////////////////// + + + +///////////////////// +// BLOCK STRUCTURE // +///////////////////// + +static void workloadAndMemoryAssignment( SetupBlockForest& forest ) +{ + for (auto &block : forest) { + block.setWorkload( numeric_cast< workload_t >( uint_t(1) << block.getLevel() ) ); + block.setMemory( numeric_cast< memory_t >(1) ); + } +} + +static shared_ptr< StructuredBlockForest > createBlockStructure( const AABB & domainAABB, Vector3<uint_t> blockSizeInCells, + bool useBox, const std::string & loadDistributionStrategy, + bool keepGlobalBlockInformation = false ) +{ + SetupBlockForest sforest; + + Vector3<uint_t> numberOfBlocksPerDirection( uint_c(domainAABB.size(0)) / blockSizeInCells[0], + uint_c(domainAABB.size(1)) / blockSizeInCells[1], + uint_c(domainAABB.size(2)) / blockSizeInCells[2] ); + + for(uint_t i = 0; i < 3; ++i ) + { + WALBERLA_CHECK_EQUAL( numberOfBlocksPerDirection[i] * blockSizeInCells[i], uint_c(domainAABB.size(i)), + "Domain can not be decomposed in direction " << i << " into fine blocks of size " << blockSizeInCells[i] ); + } + + sforest.addWorkloadMemorySUIDAssignmentFunction( workloadAndMemoryAssignment ); + + Vector3<bool> periodicity( true, true, false); + if( useBox ) + { + periodicity[0] = false; + periodicity[1] = false; + } + sforest.init( domainAABB, + numberOfBlocksPerDirection[0], numberOfBlocksPerDirection[1], numberOfBlocksPerDirection[2], + periodicity[0], periodicity[1], periodicity[2]); + + // calculate process distribution + const memory_t memoryLimit = math::Limits< memory_t >::inf(); + + if( loadDistributionStrategy == "Hilbert" ) + { + bool useHilbert = true; + sforest.balanceLoad( blockforest::StaticLevelwiseCurveBalance(useHilbert), uint_c( MPIManager::instance()->numProcesses() ), real_t(0), memoryLimit, true ); + } else if ( loadDistributionStrategy == "Morton" ) + { + bool useHilbert = false; + sforest.balanceLoad( blockforest::StaticLevelwiseCurveBalance(useHilbert), uint_c( MPIManager::instance()->numProcesses() ), real_t(0), memoryLimit, true ); + } else if ( loadDistributionStrategy == "ParMetis" ) + { + blockforest::StaticLevelwiseParMetis::Algorithm algorithm = blockforest::StaticLevelwiseParMetis::Algorithm::PARMETIS_PART_GEOM_KWAY; + blockforest::StaticLevelwiseParMetis staticParMetis(algorithm); + sforest.balanceLoad( staticParMetis, uint_c( MPIManager::instance()->numProcesses() ), real_t(0), memoryLimit, true ); + } else if (loadDistributionStrategy == "Diffusive" ) + { + // also use Hilbert curve here + bool useHilbert = true; + sforest.balanceLoad( blockforest::StaticLevelwiseCurveBalance(useHilbert), uint_c( MPIManager::instance()->numProcesses() ), real_t(0), memoryLimit, true ); + } else + { + WALBERLA_ABORT("Load distribution strategy \"" << loadDistributionStrategy << "\t not implemented! - Aborting" ); + } + + WALBERLA_LOG_INFO_ON_ROOT( sforest ); + + + // create StructuredBlockForest (encapsulates a newly created BlockForest) + shared_ptr< StructuredBlockForest > sbf = + make_shared< StructuredBlockForest >( make_shared< BlockForest >( uint_c( MPIManager::instance()->rank() ), sforest, keepGlobalBlockInformation ), + blockSizeInCells[0], blockSizeInCells[1], blockSizeInCells[2]); + sbf->createCellBoundingBoxes(); + + return sbf; +} + +///////////////////////////////////// +// BOUNDARY HANDLING CUSTOMIZATION // +///////////////////////////////////// +class MyBoundaryHandling : public blockforest::AlwaysInitializeBlockDataHandling< BoundaryHandling_T > +{ +public: + MyBoundaryHandling( const weak_ptr< StructuredBlockStorage > & blocks, + const BlockDataID & flagFieldID, const BlockDataID & pdfFieldID, + const BlockDataID & particleFieldID, const shared_ptr<ParticleAccessor_T>& ac ) : + blocks_( blocks ), flagFieldID_( flagFieldID ), pdfFieldID_( pdfFieldID ), particleFieldID_( particleFieldID ), ac_( ac ) + {} + + BoundaryHandling_T * initialize( IBlock * const block ) override; + +private: + + weak_ptr< StructuredBlockStorage > blocks_; + + const BlockDataID flagFieldID_; + const BlockDataID pdfFieldID_; + const BlockDataID particleFieldID_; + shared_ptr<ParticleAccessor_T> ac_; + +}; // class MyBoundaryHandling + +BoundaryHandling_T * MyBoundaryHandling::initialize( IBlock * const block ) +{ + WALBERLA_ASSERT_NOT_NULLPTR( block ); + + auto * flagField = block->getData< FlagField_T >( flagFieldID_ ); + auto * pdfField = block->getData< PdfField_T > ( pdfFieldID_ ); + auto* particleField = block->getData<lbm_mesapd_coupling::ParticleField_T>(particleFieldID_); + + const auto fluid = flagField->flagExists( Fluid_Flag ) ? flagField->getFlag( Fluid_Flag ) : flagField->registerFlag( Fluid_Flag ); + + auto blocksPtr = blocks_.lock(); + WALBERLA_CHECK_NOT_NULLPTR( blocksPtr ); + + BoundaryHandling_T * handling = new BoundaryHandling_T( "moving obstacle boundary handling", flagField, fluid, + NoSlip_T( "NoSlip", NoSlip_Flag, pdfField ), + MO_T( "MO", MO_Flag, pdfField, flagField, particleField, ac_, fluid, *blocksPtr, *block ), + BoundaryHandling_T::Mode::ENTIRE_FIELD_TRAVERSAL); + + handling->fillWithDomain( FieldGhostLayers ); + + return handling; +} + +void clearBoundaryHandling( BlockForest & forest, const BlockDataID & boundaryHandlingID ) { + for( auto blockIt = forest.begin(); blockIt != forest.end(); ++blockIt ) + { + BoundaryHandling_T * boundaryHandling = blockIt->getData<BoundaryHandling_T>(boundaryHandlingID); + boundaryHandling->clear( FieldGhostLayers ); + } +} + +void recreateBoundaryHandling( BlockForest & forest, const BlockDataID & boundaryHandlingID ) { + for( auto blockIt = forest.begin(); blockIt != forest.end(); ++blockIt ) + { + BoundaryHandling_T * boundaryHandling = blockIt->getData<BoundaryHandling_T>(boundaryHandlingID); + boundaryHandling->fillWithDomain( FieldGhostLayers ); + } +} + +void clearParticleField( BlockForest & forest, const BlockDataID & particleFieldID, const ParticleAccessor_T & accessor ) { + for (auto blockIt = forest.begin(); blockIt != forest.end(); ++blockIt) { + ParticleField_T *particleField = blockIt->getData<ParticleField_T>(particleFieldID); + particleField->setWithGhostLayer(accessor.getInvalidUid()); + } +} +//******************************************************************************************************************* + +void evaluateTimers(WcTimingPool & timingPool, + const std::vector<std::vector<std::string> > & timerKeys, + std::vector<real_t> & timings ) +{ + + for (auto & timingsIt : timings) + { + timingsIt = real_t(0); + } + + timingPool.unifyRegisteredTimersAcrossProcesses(); + + for (auto i = uint_t(0); i < timerKeys.size(); ++i ) + { + auto keys = timerKeys[i]; + for (const auto &timerName : keys) + { + if(timingPool.timerExists(timerName)) + { + timings[i] += real_c(timingPool[timerName].total()); + } + } + + } +} + +uint_t evaluateEdgeCut(BlockForest & forest) +{ + + //note: only works for edges in uniform grids + + auto edgecut = uint_t(0); // = edge weights between processes + + for( auto blockIt = forest.begin(); blockIt != forest.end(); ++blockIt ) + { + auto * block = static_cast<blockforest::Block*> (&(*blockIt)); + + real_t blockVolume = block->getAABB().volume(); + real_t approximateEdgeLength = std::cbrt( blockVolume ); + + uint_t faceNeighborWeight = uint_c(approximateEdgeLength * approximateEdgeLength ); //common face + uint_t edgeNeighborWeight = uint_c(approximateEdgeLength); //common edge + uint_t cornerNeighborWeight = uint_c( 1 ); //common corner + + + for( const uint_t idx : blockforest::getFaceNeighborhoodSectionIndices() ) + { + for (auto nb = uint_t(0); nb < block->getNeighborhoodSectionSize(idx); ++nb) + { + if( block->neighborExistsRemotely(idx,nb) ) edgecut += faceNeighborWeight; + } + } + + for( const uint_t idx : blockforest::getEdgeNeighborhoodSectionIndices() ) + { + for (auto nb = uint_t(0); nb < block->getNeighborhoodSectionSize(idx); ++nb) + { + if( block->neighborExistsRemotely(idx,nb) ) edgecut += edgeNeighborWeight; + } + } + + for( const uint_t idx : blockforest::getCornerNeighborhoodSectionIndices() ) + { + for (auto nb = uint_t(0); nb < block->getNeighborhoodSectionSize(idx); ++nb) + { + if( block->neighborExistsRemotely(idx,nb) ) edgecut += cornerNeighborWeight; + } + } + } + return edgecut; +} + + +void evaluateTotalSimulationTimePassed(WcTimingPool & timeloopTimingPool, const std::string & simulationString, const std::string & loadbalancingString, + double & totalSimTime, double & totalLBTime) +{ + shared_ptr< WcTimingPool> reduced = timeloopTimingPool.getReduced(timing::REDUCE_TOTAL, 0); + + double totalTime = 0.0; + WALBERLA_ROOT_SECTION(){ + totalTime = (*reduced)[simulationString].total(); + } + totalSimTime = totalTime; + + double lbTime = 0.0; + WALBERLA_ROOT_SECTION(){ + lbTime = (*reduced)[loadbalancingString].total(); + } + totalLBTime = lbTime; +} + +void createPlane( const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, + const Vector3<real_t> position, const Vector3<real_t> normal) +{ + mesa_pd::data::Particle&& p0 = *ps->create(true); + p0.setPosition(position); + p0.setShapeID(ss->create<mesa_pd::data::HalfSpace>( normal.getNormalized() )); + p0.setOwner(mpi::MPIManager::instance()->rank()); + p0.setType(0); + mesa_pd::data::particle_flags::set(p0.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); + mesa_pd::data::particle_flags::set(p0.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); + WALBERLA_LOG_INFO_ON_ROOT("Created plane at position " << position << " with normal " << normal.getNormalized ()); +} + +void createBasicPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, const math::AABB & simulationDomain) +{ + createPlane(ps, ss, simulationDomain.minCorner(), Vector3<real_t>(0,0, 1)); + //createPlane(ps, ss, Vector3<real_t>(simulationDomain.xMax() * 0.5, simulationDomain.yMax() * 0.5, simulationDomain.zMin() + std::max(simulationDomain.xMax(), simulationDomain.yMax()) * 0.5 ), Vector3<real_t>(0,1, 1)); + createPlane(ps, ss, simulationDomain.maxCorner(), Vector3<real_t>(0,0,-1)); +} + +void addBoxPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, const math::AABB & simulationDomain) +{ + // add bounding planes (four horizontal directions) + createPlane(ps, ss, simulationDomain.minCorner(), Vector3<real_t>( 1, 0,0)); + createPlane(ps, ss, simulationDomain.maxCorner(), Vector3<real_t>(-1, 0,0)); + createPlane(ps, ss, simulationDomain.minCorner(), Vector3<real_t>( 0, 1,0)); + createPlane(ps, ss, simulationDomain.maxCorner(), Vector3<real_t>( 0,-1,0)); +} + +void addHopperPlaneSetup(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, const math::AABB & simulationDomain, + real_t hopperRelHeight, real_t hopperRelOpening) +{ + //hopper planes + real_t xMax = simulationDomain.xMax(); + real_t yMax = simulationDomain.yMax(); + real_t zMax = simulationDomain.zMax(); + Vector3<real_t> p1(0,0,hopperRelHeight*zMax); + Vector3<real_t> n1(p1[2],0,hopperRelOpening*xMax-p1[0]); + Vector3<real_t> n2(0,p1[2],hopperRelOpening*yMax-p1[0]); + createPlane(ps, ss, p1, n1); + createPlane(ps, ss, p1, n2); + + Vector3<real_t> p2(xMax,yMax,hopperRelHeight*zMax); + Vector3<real_t> n3(-p2[2],0,-((real_t(1)-hopperRelOpening)*xMax-p2[0])); + Vector3<real_t> n4(0,-p2[2],-((real_t(1)-hopperRelOpening)*yMax-p2[1])); + createPlane(ps, ss, p2, n3); + createPlane(ps, ss, p2, n4); +} + +void evaluateParticleSimulation(const shared_ptr<mesa_pd::data::ParticleStorage> & ps, const shared_ptr<mesa_pd::data::ShapeStorage> & ss, + uint_t numParticles, uint_t numGlobalParticles) +{ + auto numShapes = ss->shapes.size(); + uint_t numLocalParticles = 0; + uint_t numGhostParticles = 0; + uint_t numGlobalParticlesOfRank = 0; + for(auto p = ps->begin(); p != ps->end(); ++p) + { + using namespace walberla::mesa_pd::data::particle_flags; + if (isSet(p->getFlags(), GHOST)) + { + ++numGhostParticles; + } else if (isSet(p->getFlags(), GLOBAL)) + { + ++numGlobalParticlesOfRank; + } else + { + ++numLocalParticles; + } + if(p->getShapeID() >= numShapes) + { + WALBERLA_LOG_INFO("Found invalid shape id " << *p); + } + } + //WALBERLA_LOG_INFO(numShapes << " " << numLocalParticles << " " << numGhostParticles); + + if(numGlobalParticlesOfRank != numGlobalParticles) + { + WALBERLA_LOG_INFO("Number of global particles has changed to " << numGlobalParticlesOfRank); + } + + mpi::reduceInplace(numLocalParticles, mpi::SUM); + if(numLocalParticles != numParticles) + { + WALBERLA_LOG_INFO_ON_ROOT("Number of particles has changed to " << numLocalParticles); + } +} + +bool isnan(Vector3<real_t> vec) +{ + return std::isnan(vec[0]) || std::isnan(vec[1]) || std::isnan(vec[2]); +} + +void checkParticleProperties(const shared_ptr<mesa_pd::data::ParticleStorage> & ps) +{ + for(auto p = ps->begin(); p != ps->end(); ++p) + { + if(isnan(p->getHydrodynamicForce())) WALBERLA_LOG_INFO("Found nan in hyd Force " << *p); + if(isnan(p->getOldHydrodynamicForce())) WALBERLA_LOG_INFO("Found nan in old hyd Force " << *p); + if(isnan(p->getForce())) WALBERLA_LOG_INFO("Found nan in Force " << *p); + if(isnan(p->getOldForce())) WALBERLA_LOG_INFO("Found nan in Force " << *p); + } +} + +template< typename Probe_T> +void checkMapping(const shared_ptr< StructuredBlockStorage > & blocks, const BlockDataID pdfFieldID, + const BlockDataID boundaryHandlingID, Probe_T & probe ) +{ + + for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) + { + auto * pdfField = blockIt->getData< PdfField_T >( pdfFieldID ); + auto * boundaryHandling = blockIt->getData< BoundaryHandling_T >( boundaryHandlingID ); + + WALBERLA_FOR_ALL_CELLS_XYZ(pdfField, + if (boundaryHandling->isDomain(x, y, z)) + { + uint_t f = uint_t(0); + //for( uint_t f = uint_t(0); f < PdfField_T::F_SIZE; ++f ) + //{ + if( !walberla::field::internal::stabilityCheckerIsFinite( pdfField->get( x, y, z, cell_idx_c(f) ) ) ) + { + + Vector3< real_t > center; + blocks->getBlockLocalCellCenter( *blockIt, Cell(x,y,z), center ); + + Cell gCell(x,y,z); + blocks->transformBlockLocalToGlobalCell( gCell, *blockIt); + + WALBERLA_LOG_INFO("Instability found in block local cell( " << x << ", " << y << ", " << z << " ) at index " << f + << " = global cell ( " << gCell.x() << ", " << gCell.y() << ", " << gCell.z() << " ) with cell center ( " << center[0] << ", " << center[1] << ", " << center[2] << " )"); + + probe.setPosition(center); + real_t rho; + Vector3<real_t> velocity; + probe(rho, velocity); + + } + //} + } + ); + + } +} + +//******************************************************************************************************************* +/*!\brief Simulation of settling particles inside a rectangular column filled with viscous fluid + * + * This application is used in the paper + * Rettinger, Ruede - "Dynamic Load Balancing Techniques for Particulate Flow Simulations", 2019, Computation + * in Section 4 to apply the load estimator and to evaluate different load distribution strategies. + * It has here been adapted to the new mesapd and its coupling. + * More infos can be found in the PhD thesis by Christoph Rettinger. + * + * It, however, features several different command line arguments that can be used to tweak the simulation. + * The setup can be horizontally period, a box or a hopper geometry (configurable, as in the paper). + * The size, resolution and used blocks for the domain partitioning can be changed. + * Initially, all particles are pushed upwards to obtain a dense packing at the top plane. + * + * Most importantly, the load balancing can be modified: + * - load estimation strategies: + * - pure LBM = number of cells per block = constant workload per block + * - coupling based load estimator = use fitted function from Sec. 3 of paper + * - load distribution strategies: + * - space-filling curves: Hilbert and Morton + * - ParMETIS (and several algorithms and parameters) + * - diffusive (and options) + * - load balancing frequency + */ +//******************************************************************************************************************* +int main( int argc, char **argv ) +{ + debug::enterTestMode(); + + mpi::Environment env( argc, argv ); + + MPIManager::instance()->useWorldComm(); + + /////////////////// + // Customization // + /////////////////// + + // simulation control + bool shortRun = false; + bool funcTest = false; + bool fileIO = true; + bool checkSimulation = false; + uint_t vtkWriteFreqDD = 0; //domain decomposition + uint_t vtkWriteFreqPa = 0; //particles + uint_t vtkWriteFreqFl = 0; //fluid + uint_t vtkWriteFreq = 0; //general + uint_t vtkWriteFreqInit = 0; //initial (particle-only) simulation + std::string baseFolder = "vtk_out_WorkloadDistribution"; // folder for vtk and file output + bool useProgressLogging = false; + + // physical setup + auto GalileoNumber = real_t(50); + auto densityRatio = real_t(1.5); + auto diameter = real_t(15); + auto solidVolumeFraction = real_t(0.1); + auto blockSize = uint_t(32); + auto XBlocks = uint_t(12); + auto YBlocks = uint_t(12); + auto ZBlocks = uint_t(16); + bool useBox = false; + bool useHopper = false; + auto hopperRelHeight = real_t(0.5); // for hopper setup + auto hopperRelOpening = real_t(0.3); // for hopper setup + + auto timesteps = uint_t(80000); + + //numerical parameters + auto loadBalancingCheckFrequency = uint_t(100); + auto numRPDSubCycles = uint_t(10); + bool useBlockForestSync = false; + + // load balancing + std::string loadEvaluationStrategy = "LBM"; //LBM, Fit + std::string loadDistributionStrategy = "Hilbert"; //Morton, Hilbert, ParMetis, Diffusive + real_t blockBaseWeight = real_t(1); + + auto parMetis_ipc2redist = real_t(1000); + auto parMetisTolerance = real_t(-1); + std::string parMetisAlgorithmString = "ADAPTIVE_REPART"; + + auto diffusionFlowIterations = uint_t(15); + auto diffusionMaxIterations = uint_t(20); + + bool useNoSlipForPlanes = false; + + + for( int i = 1; i < argc; ++i ) + { + if( std::strcmp( argv[i], "--shortRun" ) == 0 ) { shortRun = true; continue; } + if( std::strcmp( argv[i], "--funcTest" ) == 0 ) { funcTest = true; continue; } + if( std::strcmp( argv[i], "--fileIO" ) == 0 ) { fileIO = true; continue; } + if( std::strcmp( argv[i], "--useProgressLogging" ) == 0 ) { useProgressLogging = true; continue; } + if( std::strcmp( argv[i], "--checkSimulation" ) == 0 ) { checkSimulation = true; continue; } + if( std::strcmp( argv[i], "--vtkWriteFreqDD" ) == 0 ) { vtkWriteFreqDD = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--vtkWriteFreqPa" ) == 0 ) { vtkWriteFreqPa = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--vtkWriteFreqFl" ) == 0 ) { vtkWriteFreqFl = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--vtkWriteFreq" ) == 0 ) { vtkWriteFreq = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--vtkWriteFreqInit" ) == 0 ) { vtkWriteFreqInit = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--baseFolder" ) == 0 ) { baseFolder = argv[++i]; continue; } + if( std::strcmp( argv[i], "--densityRatio" ) == 0 ) { densityRatio = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--Ga" ) == 0 ) { GalileoNumber = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--diameter" ) == 0 ) { diameter = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--blockSize" ) == 0 ) { blockSize = uint_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--XBlocks" ) == 0 ) { XBlocks = uint_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--YBlocks" ) == 0 ) { YBlocks = uint_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--ZBlocks" ) == 0 ) { ZBlocks = uint_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--useBox" ) == 0 ) { useBox = true; continue; } + if( std::strcmp( argv[i], "--useHopper" ) == 0 ) { useHopper = true; continue; } + if( std::strcmp( argv[i], "--hopperHeight" ) == 0 ) { hopperRelHeight = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--hopperOpening" ) == 0 ) { hopperRelOpening = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--timesteps" ) == 0 ) { timesteps = uint_c(std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--numRPDSubCycles" ) == 0 ) { numRPDSubCycles = uint_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--useBlockForestSync" ) == 0 ) { useBlockForestSync = true; continue; } + if( std::strcmp( argv[i], "--useNoSlipForPlanes" ) == 0 ) { useNoSlipForPlanes = true; continue; } + if( std::strcmp( argv[i], "--blockBaseWeight" ) == 0 ) { blockBaseWeight = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--loadBalancingCheckFrequency" ) == 0 ) { loadBalancingCheckFrequency = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--loadEvaluationStrategy" ) == 0 ) { loadEvaluationStrategy = argv[++i]; continue; } + if( std::strcmp( argv[i], "--loadDistributionStrategy" ) == 0 ) { loadDistributionStrategy = argv[++i]; continue; } + if( std::strcmp( argv[i], "--ipc2redist" ) == 0 ) { parMetis_ipc2redist = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--parMetisTolerance" ) == 0 ) { parMetisTolerance = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--parMetisAlgorithm" ) == 0 ) { parMetisAlgorithmString = argv[++i]; continue; } + if( std::strcmp( argv[i], "--diffusionFlowIterations" ) == 0 ) { diffusionFlowIterations = uint_c(std::atof(argv[++i])); continue; } + if( std::strcmp( argv[i], "--diffusionMaxIterations" ) == 0 ) { diffusionMaxIterations = uint_c(std::atof(argv[++i])); continue; } + WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); + } + + if( fileIO ) + { + WALBERLA_ROOT_SECTION(){ + // create base directory if it does not yet exist + filesystem::path tpath( baseFolder ); + if( !filesystem::exists( tpath ) ) + filesystem::create_directory( tpath ); + } + WALBERLA_MPI_BARRIER(); + } + + if(useProgressLogging) logging::Logging::instance()->includeLoggingToFile(baseFolder + "/progress_logging.txt"); + + if( loadEvaluationStrategy != "LBM" && loadEvaluationStrategy != "Fit" && loadEvaluationStrategy != "FitMulti") + { + WALBERLA_ABORT("Invalid load evaluation strategy: " << loadEvaluationStrategy); + } + + if( vtkWriteFreq != 0 ) + { + vtkWriteFreqDD = vtkWriteFreq; + vtkWriteFreqPa = vtkWriteFreq; + vtkWriteFreqFl = vtkWriteFreq; + } + + if( diameter > real_c(blockSize) ) + { + WALBERLA_LOG_WARNING("Particle Synchronization might not work since bodies are large compared to block size!"); + } + + if( useHopper ) + { + WALBERLA_CHECK(hopperRelHeight >= real_t(0) && hopperRelHeight <= real_t(1), "Invalid relative hopper height of " << hopperRelHeight); + WALBERLA_CHECK(hopperRelOpening >= real_t(0) && hopperRelOpening <= real_t(1), "Invalid relative hopper opening of " << hopperRelOpening); + } + + + ////////////////////////// + // NUMERICAL PARAMETERS // + ////////////////////////// + + const Vector3<uint_t> domainSize( XBlocks * blockSize, YBlocks * blockSize, ZBlocks * blockSize ); + const auto domainVolume = real_t(domainSize[0] * domainSize[1] * domainSize[2]); + const real_t sphereVolume = math::pi / real_t(6) * diameter * diameter * diameter; + const uint_t numberOfSediments = uint_c(std::ceil(solidVolumeFraction * domainVolume / sphereVolume)); + + real_t expectedSedimentVolumeFraction = (useBox||useHopper) ? real_t(0.45) : real_t(0.52); + const real_t expectedSedimentedVolume = real_t(1)/expectedSedimentVolumeFraction * real_c(numberOfSediments) * sphereVolume; + const real_t expectedSedimentedHeight = std::max(diameter, expectedSedimentedVolume / real_c(domainSize[0] * domainSize[1])); + + const auto uRef = real_t(0.02); + const real_t xRef = diameter; + const real_t tRef = xRef / uRef; + + const real_t gravitationalAcceleration = uRef * uRef / ( (densityRatio-real_t(1)) * diameter ); + const real_t viscosity = uRef * diameter / GalileoNumber; + const real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); + const real_t tau = real_t(1) / omega; + + const auto dx = real_t(1); + const real_t overlap = real_t( 1.5 ) * dx; + + timesteps = funcTest ? 1 : ( shortRun ? uint_t(100) : timesteps ); + + WALBERLA_LOG_INFO_ON_ROOT("Setup (in simulation, i.e. lattice, units):"); + WALBERLA_LOG_INFO_ON_ROOT(" - domain size = " << domainSize); + WALBERLA_LOG_INFO_ON_ROOT(" - sediment diameter = " << diameter ); + WALBERLA_LOG_INFO_ON_ROOT(" - Galileo number = " << GalileoNumber ); + WALBERLA_LOG_INFO_ON_ROOT(" - number of sediments: " << numberOfSediments); + WALBERLA_LOG_INFO_ON_ROOT(" - densityRatio = " << densityRatio ); + WALBERLA_LOG_INFO_ON_ROOT(" - fluid: relaxation time (tau) = " << tau << ", kin. visc = " << viscosity ); + WALBERLA_LOG_INFO_ON_ROOT(" - gravitational acceleration = " << gravitationalAcceleration ); + WALBERLA_LOG_INFO_ON_ROOT(" - reference values: x = " << xRef << ", t = " << tRef << ", vel = " << uRef); + WALBERLA_LOG_INFO_ON_ROOT(" - omega: " << omega); + if( vtkWriteFreqDD > 0 ) + { + WALBERLA_LOG_INFO_ON_ROOT(" - writing vtk files of domain decomposition to folder \"" << baseFolder << "\" with frequency " << vtkWriteFreqDD); + } + if( vtkWriteFreqPa > 0 ) + { + WALBERLA_LOG_INFO_ON_ROOT(" - writing vtk files of bodies data to folder \"" << baseFolder << "\" with frequency " << vtkWriteFreqPa); + } + if( vtkWriteFreqFl > 0 ) + { + WALBERLA_LOG_INFO_ON_ROOT(" - writing vtk files of fluid data to folder \"" << baseFolder << "\" with frequency " << vtkWriteFreqFl); + } + if( useBox ) + { + WALBERLA_LOG_INFO_ON_ROOT(" - using box setup"); + } + else if ( useHopper ) + { + WALBERLA_LOG_INFO_ON_ROOT(" - using hopper setup"); + } + else + { + WALBERLA_LOG_INFO_ON_ROOT(" - using horizontally periodic domain"); + } + + WALBERLA_LOG_INFO_ON_ROOT(" - refinement / load balancing check frequency: " << loadBalancingCheckFrequency); + WALBERLA_LOG_INFO_ON_ROOT(" - load evaluation strategy: " << loadEvaluationStrategy); + WALBERLA_LOG_INFO_ON_ROOT(" - load distribution strategy: " << loadDistributionStrategy); + + /////////////////////////// + // BLOCK STRUCTURE SETUP // + /////////////////////////// + + Vector3<uint_t> blockSizeInCells( blockSize ); + + AABB simulationDomain( real_t(0), real_t(0), real_t(0), real_c(domainSize[0]), real_c(domainSize[1]), real_c(domainSize[2]) ); + AABB sedimentDomain( real_t(0), real_t(0), real_c(domainSize[2]) - expectedSedimentedHeight, real_c(domainSize[0]), real_c(domainSize[1]), real_c(domainSize[2]) ); + + auto blocks = createBlockStructure( simulationDomain, blockSizeInCells, (useBox||useHopper), loadDistributionStrategy ); + + //write initial domain decomposition to file + if( vtkWriteFreqDD > 0 ) + { + vtk::writeDomainDecomposition( blocks, "initial_domain_decomposition", baseFolder ); + } + + ///////// + // RPD // + ///////// + + const real_t restitutionCoeff = real_t(0.97); + const real_t frictionCoeffStatic = real_t(0.8); + const real_t frictionCoeffDynamic = real_t(0.15); + const real_t collisionTime = real_t(4) * diameter; // from my paper + const real_t poissonsRatio = real_t(0.22); + const real_t kappa = real_t(2) * ( real_t(1) - poissonsRatio ) / ( real_t(2) - poissonsRatio ) ; + + auto rpdDomain = std::make_shared<mesa_pd::domain::BlockForestDomain>(blocks->getBlockForestPointer()); + + //init data structures + auto ps = walberla::make_shared<mesa_pd::data::ParticleStorage>(1); + blocks->addBlockData(mesa_pd::domain::createBlockForestDataHandling(ps), "Particle Storage"); // returned ID is not used, but ps has to be known to blockforest + auto ss = walberla::make_shared<mesa_pd::data::ShapeStorage>(); + auto accessor = walberla::make_shared<ParticleAccessor_T >(ps, ss); + + real_t timeStepSizeRPD = real_t(1)/real_t(numRPDSubCycles); + mesa_pd::kernel::VelocityVerletPreForceUpdate vvIntegratorPreForce(timeStepSizeRPD); + mesa_pd::kernel::VelocityVerletPostForceUpdate vvIntegratorPostForce(timeStepSizeRPD); + + // types: 0 = wall, 1: sphere + mesa_pd::kernel::LinearSpringDashpot collisionResponse(2); + collisionResponse.setFrictionCoefficientDynamic(0,1,frictionCoeffDynamic); + collisionResponse.setFrictionCoefficientDynamic(1,1,frictionCoeffDynamic); + collisionResponse.setFrictionCoefficientStatic(0,1,frictionCoeffStatic); + collisionResponse.setFrictionCoefficientStatic(1,1,frictionCoeffStatic); + + const real_t particleMass = densityRatio * sphereVolume; + const real_t effMass_sphereWall = particleMass; + const real_t effMass_sphereSphere = particleMass * particleMass / ( real_t(2) * particleMass ); + collisionResponse.setStiffnessAndDamping(0,1,restitutionCoeff,collisionTime,kappa,effMass_sphereWall); + collisionResponse.setStiffnessAndDamping(1,1,restitutionCoeff,collisionTime,kappa,effMass_sphereSphere); + + mesa_pd::mpi::ReduceProperty reduceProperty; + mesa_pd::mpi::ReduceContactHistory reduceAndSwapContactHistory; + mesa_pd::mpi::SyncNextNeighbors syncNextNeighborFunc; + mesa_pd::kernel::AssocToBlock associateToBlock(blocks->getBlockForestPointer()); + mesa_pd::mpi::SyncNextNeighborsBlockForest syncNextNeighborBlockForestFunc; + + + // create bounding planes + + createBasicPlaneSetup(ps, ss, simulationDomain); + if(useBox || useHopper) addBoxPlaneSetup(ps, ss, simulationDomain); + if(useHopper) addHopperPlaneSetup(ps, ss, simulationDomain, hopperRelHeight, hopperRelOpening); + + auto numGlobalParticles = ps->size(); + WALBERLA_LOG_INFO_ON_ROOT("Created " << numGlobalParticles << " global particles"); + + // add the sediments + + WALBERLA_LOG_INFO_ON_ROOT("Starting creation of sediments"); + + AABB sedimentGenerationDomain( real_t(0), real_t(0), real_t(0.5)*real_c(domainSize[2]), real_c(domainSize[0]), real_c(domainSize[1]), real_c(domainSize[2]) ); + + auto xParticle = real_t(0); + auto yParticle = real_t(0); + auto zParticle = real_t(0); + + auto rank = mpi::MPIManager::instance()->rank(); + + auto sphereShape = ss->create<mesa_pd::data::Sphere>( diameter * real_t(0.5) ); + ss->shapes[sphereShape]->updateMassAndInertia(densityRatio); + + std::mt19937 randomGenerator (static_cast<unsigned int>(2610)); // fixed seed: quasi-random and reproducable + + for( uint_t nSed = 0; nSed < numberOfSediments; ++nSed ) + { + + WALBERLA_ROOT_SECTION() + { + xParticle = math::realRandom<real_t>(sedimentGenerationDomain.xMin(), sedimentGenerationDomain.xMax(),randomGenerator); + yParticle = math::realRandom<real_t>(sedimentGenerationDomain.yMin(), sedimentGenerationDomain.yMax(),randomGenerator); + zParticle = math::realRandom<real_t>(sedimentGenerationDomain.zMin(), sedimentGenerationDomain.zMax(),randomGenerator); + } + + WALBERLA_MPI_SECTION() + { + mpi::broadcastObject( xParticle ); + mpi::broadcastObject( yParticle ); + mpi::broadcastObject( zParticle ); + } + + auto position = Vector3<real_t>( xParticle, yParticle, zParticle ); + + if (!rpdDomain->isContainedInProcessSubdomain(uint_c(rank), position)) continue; + auto p = ps->create(); + p->setPosition(position); + p->setInteractionRadius(diameter * real_t(0.5)); + p->setShapeID(sphereShape); + p->setType(1); + p->setOwner(rank); + + } + + if(useBlockForestSync) + { + ps->forEachParticle(false, mesa_pd::kernel::SelectLocal(), *accessor, associateToBlock, *accessor); + syncNextNeighborBlockForestFunc(*ps, blocks->getBlockForestPointer(), rpdDomain, overlap); + + } else + { + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + } + + + // Carry out particle-only simulation to obtain dense packing at top plane + // consists of three phases: + // 1: carefully resolve initial overlaps due to random generation, no gravity + // 2: apply low gravity in positive z-direction to create packing until convergence or targeted packing height reached + // 3: carry out a few time steps with gravity in negative direction to relay the system towards the real setup + + const bool useOpenMP = false; + const real_t dt_RPD_Init = real_t(1); + const auto particleSimStepsPhase1 = uint_t(1000); + const auto maxParticleSimStepsPhase2 = (shortRun) ? uint_t(10) : uint_t(200000); + const auto particleSimStepsPhase3 = uint_t(std::sqrt(real_t(2)/std::fabs(gravitationalAcceleration))); + + uint_t maxInitialParticleSimSteps = particleSimStepsPhase1 + maxParticleSimStepsPhase2 + particleSimStepsPhase3; + + auto particleVtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + particleVtkOutput->addOutput<mesa_pd::data::SelectParticleLinearVelocity>("velocity"); + particleVtkOutput->addOutput<mesa_pd::data::SelectParticleOwner>("owner"); + particleVtkOutput->setParticleSelector( [sphereShape](const mesa_pd::data::ParticleStorage::iterator& pIt) {return !mesa_pd::data::particle_flags::isSet(pIt->getFlags(), mesa_pd::data::particle_flags::GHOST) && pIt->getShapeID() == sphereShape;} ); //limit output to local sphere + auto particleVtkWriterInit = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles_init", 1, baseFolder, "simulation_step"); + + real_t gravitationalAccelerationGeneration = gravitationalAcceleration; + auto oldMinParticlePosition = real_t(0); + real_t phase2ConvergenceLimit = std::fabs(gravitationalAccelerationGeneration); + real_t heightConvergenceThreshold = sedimentDomain.zMin(); + + uint_t beginOfPhase3SimStep = uint_t(0); + + uint_t currentPhase = 1; + + for(auto pet = uint_t(0); pet <= maxInitialParticleSimSteps; ++pet ) + { + + real_t maxPenetrationDepth = 0; + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&collisionResponse, &rpdDomain, &maxPenetrationDepth, dt_RPD_Init] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + maxPenetrationDepth = std::max(maxPenetrationDepth, std::abs(acd.getPenetrationDepth())); + collisionResponse(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), + acd.getContactNormal(), acd.getPenetrationDepth(), dt_RPD_Init); + } + } + }, + *accessor ); + + reduceAndSwapContactHistory(*ps); + + mpi::allReduceInplace(maxPenetrationDepth, mpi::MAX); + + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, mesa_pd::kernel::ExplicitEuler(dt_RPD_Init), *accessor); + if(useBlockForestSync) + { + syncNextNeighborBlockForestFunc(*ps, blocks->getBlockForestPointer(), rpdDomain, overlap); + ps->forEachParticle(false, mesa_pd::kernel::SelectLocal(), *accessor, associateToBlock, *accessor); + + } else + { + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + } + + if( vtkWriteFreqInit > uint_t(0) && pet % vtkWriteFreqInit == uint_t(0) ) + { + particleVtkWriterInit->write(); + } + + + if(currentPhase == 1) + { + // damp velocites to avoid too large ones + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [](const size_t idx, ParticleAccessor_T& ac){ + ac.setLinearVelocity(idx, ac.getLinearVelocity(idx) * real_t(0.5)); + ac.setAngularVelocity(idx, ac.getAngularVelocity(idx) * real_t(0.5)); + }, *accessor); + + if(pet > particleSimStepsPhase1) + { + WALBERLA_LOG_INFO_ON_ROOT("Starting phase 2 of initial particle simulation, with height threshold = " << heightConvergenceThreshold); + currentPhase = 2; + + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [](const size_t idx, ParticleAccessor_T& ac){ + ac.setLinearVelocity(idx, Vector3<real_t>(0.0)); + ac.setAngularVelocity(idx, Vector3<real_t>(0.0)); + }, *accessor); + } + } else if(currentPhase == 2) + { + + Vector3<real_t> gravitationalForce( real_t(0), real_t(0), (densityRatio - real_t(1)) * gravitationalAccelerationGeneration * sphereVolume ); + lbm_mesapd_coupling::AddForceOnParticlesKernel addGravitationalForce(gravitationalForce); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); + + + real_t minParticlePosition = sedimentGenerationDomain.zMax(); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [&minParticlePosition](const size_t idx, ParticleAccessor_T& ac){ + minParticlePosition = std::min(ac.getPosition(idx)[2], minParticlePosition); + }, *accessor); + + WALBERLA_MPI_SECTION() + { + mpi::allReduceInplace(minParticlePosition, mpi::MIN); + } + + WALBERLA_ROOT_SECTION() + { + if( pet % 100 == 0) + { + WALBERLA_LOG_INFO("[" << pet << "] Min position of all particles = " << minParticlePosition << " with goal height " << heightConvergenceThreshold); + } + } + + if( minParticlePosition > heightConvergenceThreshold ) currentPhase = 3; + + if( pet % 500 == 0) + { + if( std::fabs(minParticlePosition - oldMinParticlePosition) / minParticlePosition < phase2ConvergenceLimit ) currentPhase = 3; + oldMinParticlePosition = minParticlePosition; + } + + if( currentPhase == 3) + { + WALBERLA_LOG_INFO_ON_ROOT("Starting phase 3 of initial particle simulation"); + beginOfPhase3SimStep = pet; + } + + } else if(currentPhase == 3) + { + Vector3<real_t> gravitationalForce( real_t(0), real_t(0), -(densityRatio - real_t(1)) * gravitationalAccelerationGeneration * sphereVolume ); + lbm_mesapd_coupling::AddForceOnParticlesKernel addGravitationalForce(gravitationalForce); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); + + if(pet - beginOfPhase3SimStep > particleSimStepsPhase3) + { + Vector3<real_t> initialParticleVelocity(real_t(0)); + WALBERLA_LOG_INFO_ON_ROOT("Setting initial velocity " << initialParticleVelocity << " of all particles"); + // reset velocities to avoid too large ones + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [initialParticleVelocity](const size_t idx, ParticleAccessor_T& ac){ + ac.setLinearVelocity(idx, initialParticleVelocity); + ac.setAngularVelocity(idx, Vector3<real_t>(0)); + }, *accessor); + break; + } + } + } + WALBERLA_LOG_INFO_ON_ROOT("Sediment layer creation done!"); + + /////////////////////// + // ADD DATA TO BLOCKS // + //////////////////////// + + // create the lattice model + LatticeModel_T latticeModel = LatticeModel_T( lbm::collision_model::TRT::constructWithMagicNumber( omega, lbm::collision_model::TRT::threeSixteenth ) ); + + // add PDF field + BlockDataID pdfFieldID = lbm::addPdfFieldToStorage< LatticeModel_T >( blocks, "pdf field (zyxf)", latticeModel, + Vector3< real_t >( real_t(0) ), real_t(1), + FieldGhostLayers, field::zyxf ); + // add flag field + BlockDataID flagFieldID = field::addFlagFieldToStorage<FlagField_T>( blocks, "flag field", FieldGhostLayers ); + + // add particle field + BlockDataID particleFieldID = field::addToStorage<lbm_mesapd_coupling::ParticleField_T>( blocks, "particle field", accessor->getInvalidUid(), field::zyxf, FieldGhostLayers ); + + // add boundary handling & initialize outer domain boundaries + BlockDataID boundaryHandlingID = blocks->addBlockData( make_shared< MyBoundaryHandling >( blocks, flagFieldID, pdfFieldID, particleFieldID, accessor ), "boundary handling" ); + + Vector3<real_t> gravitationalForce( real_t(0), real_t(0), -(densityRatio - real_t(1)) * gravitationalAcceleration * sphereVolume ); + lbm_mesapd_coupling::AddForceOnParticlesKernel addGravitationalForce(gravitationalForce); + lbm_mesapd_coupling::ResetHydrodynamicForceTorqueKernel resetHydrodynamicForceTorque; + lbm_mesapd_coupling::AverageHydrodynamicForceTorqueKernel averageHydrodynamicForceTorque; + lbm_mesapd_coupling::LubricationCorrectionKernel lubricationCorrectionKernel(viscosity, [](real_t r){return (real_t(0.001 + real_t(0.00007)*r))*r;}); + lbm_mesapd_coupling::ParticleMappingKernel<BoundaryHandling_T> particleMappingKernel(blocks, boundaryHandlingID); + lbm_mesapd_coupling::MovingParticleMappingKernel<BoundaryHandling_T> movingParticleMappingKernel(blocks, boundaryHandlingID, particleFieldID); + lbm_mesapd_coupling::ParticleMappingKernel<BoundaryHandling_T> fixedParticleMappingKernel(blocks, boundaryHandlingID); + lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; + + WALBERLA_LOG_INFO_ON_ROOT(" - Lubrication correction:"); + WALBERLA_LOG_INFO_ON_ROOT(" - normal cut off distance = " << lubricationCorrectionKernel.getNormalCutOffDistance()); + WALBERLA_LOG_INFO_ON_ROOT(" - tangential translational cut off distance = " << lubricationCorrectionKernel.getTangentialTranslationalCutOffDistance()); + WALBERLA_LOG_INFO_ON_ROOT(" - tangential rotational cut off distance = " << lubricationCorrectionKernel.getTangentialRotationalCutOffDistance()); + const real_t maximumLubricationCutOffDistance = std::max(lubricationCorrectionKernel.getNormalCutOffDistance(), std::max(lubricationCorrectionKernel.getTangentialRotationalCutOffDistance(), lubricationCorrectionKernel.getTangentialTranslationalCutOffDistance())); + + std::function<void(void)> particleMappingCall = [ps, accessor, &movingParticleMappingKernel, &fixedParticleMappingKernel, useNoSlipForPlanes]() + { + // map planes into the LBM simulation -> act as no-slip boundaries + if(useNoSlipForPlanes) + { + ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, fixedParticleMappingKernel, *accessor, NoSlip_Flag); + } + else { + ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + } + // map particles into the LBM simulation + ps->forEachParticle(false, lbm_mesapd_coupling::RegularParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + }; + + particleMappingCall(); + + + ////////////////////////// + // LOAD BALANCING UTILs // + ////////////////////////// + + auto & blockforest = blocks->getBlockForest(); + blockforest.recalculateBlockLevelsInRefresh( false ); // = only load balancing, no refinement checking + blockforest.alwaysRebalanceInRefresh( true ); //load balancing every time refresh is triggered + blockforest.reevaluateMinTargetLevelsAfterForcedRefinement( false ); + blockforest.allowRefreshChangingDepth( false ); + blockforest.allowMultipleRefreshCycles( false ); // otherwise info collections are invalid + + shared_ptr<lbm_mesapd_coupling::amr::InfoCollection> couplingInfoCollection = walberla::make_shared<lbm_mesapd_coupling::amr::InfoCollection>(); + uint_t numberOfProcesses = uint_c(MPIManager::instance()->numProcesses()); + + if( loadDistributionStrategy == "Hilbert" || loadDistributionStrategy == "Morton") + { + + bool curveAllGather = true; + bool balanceLevelwise = true; + + if( loadDistributionStrategy == "Hilbert") + { + bool useHilbert = true; + blockforest.setRefreshPhantomBlockMigrationPreparationFunction( blockforest::DynamicCurveBalance< blockforest::PODPhantomWeight<real_t> >( useHilbert, curveAllGather, balanceLevelwise ) ); + } + else if (loadDistributionStrategy == "Morton" ) + { + bool useHilbert = false; + blockforest.setRefreshPhantomBlockMigrationPreparationFunction( blockforest::DynamicCurveBalance< blockforest::PODPhantomWeight<real_t> >( useHilbert, curveAllGather, balanceLevelwise ) ); + } + + if( loadEvaluationStrategy == "Fit" ) + { + lbm_mesapd_coupling::amr::WeightEvaluationFunctor weightEvaluationFunctor(couplingInfoCollection, lbm_mesapd_coupling::amr::fittedTotalWeightEvaluationFunction); + lbm_mesapd_coupling::amr::WeightAssignmentFunctor weightAssignmentFunctor(weightEvaluationFunctor); + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else if( loadEvaluationStrategy == "LBM" ) + { + lbm_mesapd_coupling::amr::WeightAssignmentFunctor weightAssignmentFunctor(lbm_mesapd_coupling::amr::defaultWeightEvaluationFunction); + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else + { + WALBERLA_ABORT("Invalid load evaluation strategy: " << loadEvaluationStrategy); + } + + blockforest.setRefreshPhantomBlockDataPackFunction(blockforest::PODPhantomWeightPackUnpack<real_t>()); + blockforest.setRefreshPhantomBlockDataUnpackFunction(blockforest::PODPhantomWeightPackUnpack<real_t>()); + + } + else if( loadDistributionStrategy == "ParMetis") + { + +#ifndef WALBERLA_BUILD_WITH_PARMETIS + WALBERLA_ABORT( "You are trying to use ParMetis functionality but waLBerla is not configured to use it. Set 'WALBERLA_BUILD_WITH_PARMETIS' to 'ON' in your CMake cache to build against an installed version of ParMetis!" ); +#endif + + blockforest::DynamicParMetis::Algorithm parMetisAlgorithm = blockforest::DynamicParMetis::stringToAlgorithm(parMetisAlgorithmString); + blockforest::DynamicParMetis::WeightsToUse parMetisWeightsToUse = blockforest::DynamicParMetis::WeightsToUse::PARMETIS_BOTH_WEIGHTS; + blockforest::DynamicParMetis::EdgeSource parMetisEdgeSource = blockforest::DynamicParMetis::EdgeSource::PARMETIS_EDGES_FROM_EDGE_WEIGHTS; + + blockforest::DynamicParMetis dynamicParMetis(parMetisAlgorithm, parMetisWeightsToUse, parMetisEdgeSource); + dynamicParMetis.setipc2redist(parMetis_ipc2redist); + + auto numberOfBlocks = XBlocks * YBlocks * ZBlocks; + + real_t loadImbalanceTolerance = (parMetisTolerance < real_t(1)) ? std::max(real_t(1.05), real_t(1) + real_t(1) / ( real_c(numberOfBlocks) / real_c(numberOfProcesses) ) ) : parMetisTolerance; + dynamicParMetis.setImbalanceTolerance(double(loadImbalanceTolerance), 0); + + WALBERLA_LOG_INFO_ON_ROOT(" - ParMetis configuration: "); + WALBERLA_LOG_INFO_ON_ROOT(" - algorithm = " << dynamicParMetis.algorithmToString() ); + WALBERLA_LOG_INFO_ON_ROOT(" - weights to use = " << dynamicParMetis.weightsToUseToString() ); + WALBERLA_LOG_INFO_ON_ROOT(" - edge source = " << dynamicParMetis.edgeSourceToString() ); + WALBERLA_LOG_INFO_ON_ROOT(" - ipc2redist parameter = " << dynamicParMetis.getipc2redist() ); + WALBERLA_LOG_INFO_ON_ROOT(" - imbalance tolerance = " << dynamicParMetis.getImbalanceTolerance() ); + + blockforest.setRefreshPhantomBlockDataPackFunction(blockforest::DynamicParMetisBlockInfoPackUnpack()); + blockforest.setRefreshPhantomBlockDataUnpackFunction(blockforest::DynamicParMetisBlockInfoPackUnpack()); + blockforest.setRefreshPhantomBlockMigrationPreparationFunction( dynamicParMetis ); + + if( loadEvaluationStrategy == "Fit" ) + { + lbm_mesapd_coupling::amr::WeightEvaluationFunctor weightEvaluationFunctor(couplingInfoCollection, lbm_mesapd_coupling::amr::fittedTotalWeightEvaluationFunction); + lbm_mesapd_coupling::amr::MetisAssignmentFunctor weightAssignmentFunctor(weightEvaluationFunctor); //attention: special METIS assignment functor! + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + real_t weightMultiplicator = real_t(1000); // values from predictor are in range [0-5] which is too coarse when cast to int as done in parmetis + weightAssignmentFunctor.setWeightMultiplicator(weightMultiplicator); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else if( loadEvaluationStrategy == "LBM" ) + { + lbm_mesapd_coupling::amr::MetisAssignmentFunctor weightAssignmentFunctor(lbm_mesapd_coupling::amr::defaultWeightEvaluationFunction); + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else + { + WALBERLA_ABORT("Invalid load evaluation strategy: " << loadEvaluationStrategy); + } + + } + else if( loadDistributionStrategy == "Diffusive") + { + using DB_T = blockforest::DynamicDiffusionBalance< blockforest::PODPhantomWeight<real_t> >; + DB_T dynamicDiffusion(diffusionMaxIterations, diffusionFlowIterations ); + dynamicDiffusion.setMode(DB_T::Mode::DIFFUSION_PUSH); + + WALBERLA_LOG_INFO_ON_ROOT(" - Dynamic diffusion configuration: "); + WALBERLA_LOG_INFO_ON_ROOT(" - max iterations = " << dynamicDiffusion.getMaxIterations() ); + WALBERLA_LOG_INFO_ON_ROOT(" - flow iterations = " << dynamicDiffusion.getFlowIterations()); + + blockforest.setRefreshPhantomBlockDataPackFunction(blockforest::PODPhantomWeightPackUnpack<real_t>()); + blockforest.setRefreshPhantomBlockDataUnpackFunction(blockforest::PODPhantomWeightPackUnpack<real_t>()); + blockforest.setRefreshPhantomBlockMigrationPreparationFunction( dynamicDiffusion ); + + if( loadEvaluationStrategy == "Fit" ) + { + lbm_mesapd_coupling::amr::WeightEvaluationFunctor weightEvaluationFunctor(couplingInfoCollection, lbm_mesapd_coupling::amr::fittedTotalWeightEvaluationFunction); + lbm_mesapd_coupling::amr::WeightAssignmentFunctor weightAssignmentFunctor(weightEvaluationFunctor); + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else if( loadEvaluationStrategy == "LBM" ) + { + lbm_mesapd_coupling::amr::WeightAssignmentFunctor weightAssignmentFunctor(lbm_mesapd_coupling::amr::defaultWeightEvaluationFunction); + weightAssignmentFunctor.setBlockBaseWeight(blockBaseWeight); + blockforest.setRefreshPhantomBlockDataAssignmentFunction(weightAssignmentFunctor); + } + else + { + WALBERLA_ABORT("Invalid load evaluation strategy: " << loadEvaluationStrategy); + } + + } else + { + WALBERLA_ABORT("Load distribution strategy \"" << loadDistributionStrategy << "\t not implemented! - Aborting" ); + } + + lbm_mesapd_coupling::amr::BlockInfo emptyExampleBlock(blockSize*blockSize*blockSize, 0, 0, 0, 0, numRPDSubCycles); + WALBERLA_LOG_INFO_ON_ROOT("An example empty block has the weight: " << lbm_mesapd_coupling::amr::fittedTotalWeightEvaluationFunction(emptyExampleBlock)); + + + /////////////// + // TIME LOOP // + /////////////// + + // create the timeloop + SweepTimeloop timeloop( blocks->getBlockStorage(), timesteps ); + + timeloop.addFuncBeforeTimeStep( RemainingTimeLogger( timeloop.getNrOfTimeSteps() ), "Remaining Time Logger" ); + + if( vtkWriteFreqPa != uint_t(0) ) { + auto particleVtkWriter = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles", vtkWriteFreqPa, baseFolder, "simulation_step"); + timeloop.addFuncBeforeTimeStep( vtk::writeFiles( particleVtkWriter ), "VTK (sphere data)" ); + } + + if( vtkWriteFreqFl != uint_t(0) ) { + + // pdf field + auto pdfFieldVTK = vtk::createVTKOutput_BlockData(blocks, "fluid_field", vtkWriteFreqFl, 0, false, baseFolder); + + field::FlagFieldCellFilter<FlagField_T> fluidFilter(flagFieldID); + fluidFilter.addFlag(Fluid_Flag); + pdfFieldVTK->addCellInclusionFilter(fluidFilter); + + pdfFieldVTK->addCellDataWriter( + make_shared<lbm::VelocityVTKWriter<LatticeModel_T, float> >(pdfFieldID, "VelocityFromPDF")); + pdfFieldVTK->addCellDataWriter( + make_shared<lbm::DensityVTKWriter<LatticeModel_T, float> >(pdfFieldID, "DensityFromPDF")); + + timeloop.addFuncBeforeTimeStep(vtk::writeFiles(pdfFieldVTK), "VTK (fluid field data)"); + } + + if( vtkWriteFreqDD != uint_t(0) ) { + auto domainDecompVTK = vtk::createVTKOutput_DomainDecomposition(blocks, "domain_decomposition", vtkWriteFreqDD, baseFolder ); + timeloop.addFuncBeforeTimeStep( vtk::writeFiles(domainDecompVTK), "VTK (domain decomposition)"); + } + + + // setup of the LBM communication for synchronizing the pdf field between neighboring blocks + blockforest::communication::UniformBufferedScheme< Stencil_T > optimizedPDFCommunicationScheme( blocks ); + optimizedPDFCommunicationScheme.addPackInfo( make_shared< lbm::PdfFieldPackInfo< LatticeModel_T > >( pdfFieldID ) ); // optimized sync + + auto sweep = lbm::makeCellwiseSweep< LatticeModel_T, FlagField_T >( pdfFieldID, flagFieldID, Fluid_Flag ); + + // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) + timeloop.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) + << Sweep( BoundaryHandling_T::getBlockSweep( boundaryHandlingID ), "Boundary Handling" ); + + // streaming & collide + timeloop.add() << Sweep( makeSharedSweep(sweep), "Stream&Collide" ); + + + SweepTimeloop timeloopAfterParticles( blocks->getBlockStorage(), timesteps ); + + // sweep for updating the particle mapping into the LBM simulation + bool conserveMomentum = false; + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, MO_Flag, FormerMO_Flag, + lbm_mesapd_coupling::RegularParticlesSelector(), conserveMomentum), "Particle Mapping" ); + + bool recomputeTargetDensity = false; + auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, recomputeTargetDensity,true); + blockforest::communication::UniformBufferedScheme< Stencil_T > fullPDFCommunicationScheme( blocks ); + fullPDFCommunicationScheme.addPackInfo( make_shared< field::communication::PackInfo< PdfField_T > >( pdfFieldID ) ); // full sync + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, + gradReconstructor, conserveMomentum) ), "PDF Restore" ); + + //////////////////////// + // EXECUTE SIMULATION // + //////////////////////// + + + uint_t loadEvaluationFrequency = loadBalancingCheckFrequency; + + // file for simulation infos + std::string infoFileName( baseFolder + "/simulation_info.txt"); + WALBERLA_ROOT_SECTION() + { + std::ofstream file; + file.open( infoFileName.c_str(), std::fstream::out | std::fstream::trunc ); + file << "#i\t t\t tSim\t tLoadBal\t numProcs\t blocks (min/max/sum)\n"; + file.close(); + } + + // process local timing measurements and predicted loads + std::string processLocalFiles(baseFolder + "/processLocalFiles"); + WALBERLA_ROOT_SECTION() + { + filesystem::path tpath( processLocalFiles ); + if( !filesystem::exists( tpath ) ) + filesystem::create_directory( tpath ); + } + std::string measurementFileProcessName(processLocalFiles + "/measurements_" + std::to_string(MPIManager::instance()->rank()) + ".txt"); + { + std::ofstream file; + file.open( measurementFileProcessName.c_str(), std::fstream::out | std::fstream::trunc ); + file << "#i\t t\t mTotSim\t mLB\t mLBM\t mBH\t mCoup1\t mCoup2\t mRPD\t cLBM\t cRB\t numBlocks\n"; + file.close(); + } + + std::string predictionFileProcessName(processLocalFiles + "/predictions_" + std::to_string(MPIManager::instance()->rank()) + ".txt"); + { + std::ofstream file; + file.open( predictionFileProcessName.c_str(), std::fstream::out | std::fstream::trunc ); + file << "#i\t t\t wlLBM\t wlBH\t wlCoup1\t wlCoup2\t wlRPD\t edgecut\t numBlocks\n"; + file.close(); + } + + std::vector< std::vector<std::string> > timerKeys; + std::vector<std::string> LBMTimer; + LBMTimer.emplace_back("Stream&Collide"); + timerKeys.push_back(LBMTimer); + + std::vector<std::string> bhTimer; + bhTimer.emplace_back("Boundary Handling"); + timerKeys.push_back(bhTimer); + + std::vector<std::string> couplingTimer1; + couplingTimer1.emplace_back("Particle Mapping"); + std::vector<std::string> couplingTimer2; + couplingTimer2.emplace_back("PDF Restore"); + timerKeys.push_back(couplingTimer1); + timerKeys.push_back(couplingTimer2); + + std::vector<std::string> rpdTimer; + rpdTimer.emplace_back("RPD Force"); + rpdTimer.emplace_back("RPD VV1"); + rpdTimer.emplace_back("RPD VV2"); + rpdTimer.emplace_back("RPD Lub"); + rpdTimer.emplace_back("RPD Collision"); + timerKeys.push_back(rpdTimer); + + std::vector<std::string> LBMCommTimer; + LBMCommTimer.emplace_back("LBM Communication"); + LBMCommTimer.emplace_back("PDF Communication"); + timerKeys.push_back(LBMCommTimer); + + + std::vector<std::string> rpdCommTimer; + rpdCommTimer.emplace_back("Reduce Force Torque"); + rpdCommTimer.emplace_back("Reduce Hyd Force Torque"); + rpdCommTimer.emplace_back("Reduce Contact History"); + rpdCommTimer.emplace_back("Sync"); + timerKeys.push_back(rpdCommTimer); + + std::vector<real_t> timings(timerKeys.size()); + + double oldmTotSim = 0.0; + double oldmLB = 0.0; + + auto measurementFileCounter = uint_t(0); + auto predictionFileCounter = uint_t(0); + + std::string loadEvaluationStep("load evaluation"); + std::string loadBalancingStep("load balancing"); + std::string simulationStep("simulation"); + + WcTimingPool timeloopTiming; + WcTimingPool simulationTiming; + + lbm_mesapd_coupling::InspectionProbe<PdfField_T,BoundaryHandling_T,ParticleAccessor_T> probeForNaNs( Vector3<real_t>(0, 0, 0), + blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, + true, true, "" ); + + // time loop + for (uint_t i = 0; i < timesteps; ++i ) + { + + // evaluate measurements (note: reflect simulation behavior BEFORE the evaluation) + if( loadEvaluationFrequency > 0 && i % loadEvaluationFrequency == 0 && i > 0 && fileIO) + { + + simulationTiming[loadEvaluationStep].start(); + + // write process local timing measurements to files (per process, per load balancing step) + { + auto mTotSim = simulationTiming[simulationStep].total(); + auto mLB = simulationTiming[loadBalancingStep].total(); + + evaluateTimers(timeloopTiming, timerKeys, timings); + + auto & forest = blocks->getBlockForest(); + uint_t numBlocks = forest.getNumberOfBlocks(); + + // write to process local file + std::ofstream file; + file.open( measurementFileProcessName.c_str(), std::ofstream::app ); + file << measurementFileCounter << "\t " << real_c(i) / tRef << "\t" + << mTotSim - oldmTotSim << "\t" << mLB - oldmLB << "\t"; + for (real_t timing : timings) { + file << "\t" << timing; + } + file << "\t" << numBlocks << "\n"; + file.close(); + + oldmTotSim = mTotSim; + oldmLB = mLB; + measurementFileCounter++; + + // reset timer to have measurement from evaluation to evaluation point + timeloopTiming.clear(); + + } + + // evaluate general simulation infos (on root) + { + double totalTimeToCurrentTimestep(0.0); + double totalLBTimeToCurrentTimestep(0.0); + evaluateTotalSimulationTimePassed(simulationTiming, simulationStep, loadBalancingStep, + totalTimeToCurrentTimestep, totalLBTimeToCurrentTimestep); + math::DistributedSample numberOfBlocks; + + auto & forest = blocks->getBlockForest(); + uint_t numBlocks = forest.getNumberOfBlocks(); + numberOfBlocks.castToRealAndInsert(numBlocks); + numberOfBlocks.mpiGatherRoot(); + + WALBERLA_ROOT_SECTION() + { + std::ofstream file; + file.open( infoFileName.c_str(), std::ofstream::app ); + file << i << "\t " << real_c(i) / tRef << "\t" + << totalTimeToCurrentTimestep << "\t " << totalLBTimeToCurrentTimestep << "\t " + << numberOfProcesses << "\t "; + file << uint_c(numberOfBlocks.min()) << "\t "; + file << uint_c(numberOfBlocks.max()) << "\t "; + file << uint_c(numberOfBlocks.sum()) << "\n "; + file.close(); + } + } + + simulationTiming[loadEvaluationStep].end(); + + } + + if( loadBalancingCheckFrequency != 0 && i % loadBalancingCheckFrequency == 0) + { + + if(useProgressLogging) walberla::logging::Logging::instance()->setFileLogLevel(logging::Logging::LogLevel::PROGRESS); + + simulationTiming[loadBalancingStep].start(); + + if( loadEvaluationStrategy != "LBM" ) { + + WALBERLA_LOG_INFO_ON_ROOT("Checking for load balancing..."); + + // update info collections for the particle presence based check and the load balancing: + auto &forest = blocks->getBlockForest(); + lbm_mesapd_coupling::amr::updateAndSyncInfoCollection<BoundaryHandling_T,ParticleAccessor_T >(forest, boundaryHandlingID, *accessor, numRPDSubCycles, *couplingInfoCollection); + + if(useProgressLogging) WALBERLA_LOG_INFO("Created info collection with size " << couplingInfoCollection->size()); + + auto numBlocksBefore = forest.getNumberOfBlocks(); + if(useProgressLogging) WALBERLA_LOG_INFO("Number of blocks before refresh " << numBlocksBefore); + + mesa_pd::mpi::ClearNextNeighborSync CNNS; + CNNS(*accessor); + + if(useProgressLogging) WALBERLA_LOG_INFO_ON_ROOT("Cleared particle sync and starting refresh"); + + blocks->refresh(); + + auto numBlocksAfter = forest.getNumberOfBlocks(); + if(useProgressLogging) WALBERLA_LOG_INFO("Number of blocks after refresh " << numBlocksAfter); + + if(useProgressLogging) WALBERLA_LOG_INFO_ON_ROOT("Refresh finished, recreating all datastructures"); + + //WALBERLA_LOG_INFO(rank << ", " << numBlocksBefore << " -> " << numBlocksAfter); + rpdDomain->refresh(); + if(useBlockForestSync) + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, associateToBlock, *accessor); + syncNextNeighborBlockForestFunc(*ps, blocks->getBlockForestPointer(), rpdDomain, overlap); + + } else + { + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + } + + clearBoundaryHandling(forest, boundaryHandlingID); + clearParticleField(forest, particleFieldID, *accessor); + + recreateBoundaryHandling(forest, boundaryHandlingID); + + //NOTE: order in mapping is important: first all global/fixed particles, + // only then moving ones, which do not overwrite the mapping of the global/fixed ones + particleMappingCall(); + + } + simulationTiming[loadBalancingStep].end(); + + if(useProgressLogging) walberla::logging::Logging::instance()->setFileLogLevel(logging::Logging::LogLevel::INFO); + + } + + if(checkSimulation) + { + WALBERLA_LOG_INFO_ON_ROOT("Checking time step " << i ); + evaluateParticleSimulation(ps, ss, numberOfSediments, numGlobalParticles); + checkMapping(blocks, pdfFieldID, boundaryHandlingID, probeForNaNs); + } + + // evaluate predictions (note: reflect the predictions for all upcoming simulations, thus the corresponding measurements have to be taken afterwards) + if( loadEvaluationFrequency > 0 && i % loadEvaluationFrequency == 0 && fileIO) + { + + simulationTiming[loadEvaluationStep].start(); + + // write process local load predictions to files (per process, per load balancing step) + { + + auto wlLBM = real_t(0); + auto wlBH = real_t(0); + auto wlCoup1 = real_t(0); + auto wlCoup2 = real_t(0); + auto wlRPD = real_t(0); + + auto & forest = blocks->getBlockForest(); + lbm_mesapd_coupling::amr::updateAndSyncInfoCollection<BoundaryHandling_T,ParticleAccessor_T >(forest, boundaryHandlingID, *accessor, numRPDSubCycles, *couplingInfoCollection); + + for( auto blockIt = forest.begin(); blockIt != forest.end(); ++blockIt ) { + auto * block = static_cast<blockforest::Block *> (&(*blockIt)); + const auto &blockID = block->getId(); + auto infoIt = couplingInfoCollection->find(blockID); + auto blockInfo = infoIt->second; + + wlLBM += lbm_mesapd_coupling::amr::fittedLBMWeightEvaluationFunction(blockInfo); + wlBH += lbm_mesapd_coupling::amr::fittedBHWeightEvaluationFunction(blockInfo); + wlCoup1 += lbm_mesapd_coupling::amr::fittedCoup1WeightEvaluationFunction(blockInfo); + wlCoup2 += lbm_mesapd_coupling::amr::fittedCoup2WeightEvaluationFunction(blockInfo); + wlRPD += lbm_mesapd_coupling::amr::fittedRPDWeightEvaluationFunction(blockInfo); + + } + + // note: we count the edge weight doubled here in total (to and from the other process). ParMetis only counts one direction. + uint_t edgecut = evaluateEdgeCut(forest); + uint_t numBlocks = forest.getNumberOfBlocks(); + + std::ofstream file; + file.open( predictionFileProcessName.c_str(), std::ofstream::app ); + file << predictionFileCounter << "\t " << real_c(i) / tRef << "\t" + << wlLBM << "\t" << wlBH << "\t" << wlCoup1 << "\t" << wlCoup2 << "\t" << wlRPD << "\t" + << edgecut << "\t" << numBlocks << "\n"; + file.close(); + + predictionFileCounter++;; + } + + simulationTiming[loadEvaluationStep].end(); + + } + + simulationTiming[simulationStep].start(); + + // perform a single simulation step + + timeloop.singleStep( timeloopTiming ); + + timeloopTiming["Reduce Hyd Force Torque"].start(); + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + timeloopTiming["Reduce Hyd Force Torque"].end(); + + timeloopTiming["RPD Force"].start(); + if( i == 0 ) + { + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); + } + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor ); + timeloopTiming["RPD Force"].end(); + + if(checkSimulation) + { + checkParticleProperties(ps); + } + + for(auto subCycle = uint_t(0); subCycle < numRPDSubCycles; ++subCycle ) + { + + timeloopTiming["RPD VV1"].start(); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPreForce, *accessor); + timeloopTiming["RPD VV1"].end(); + + timeloopTiming["Sync"].start(); + if(useBlockForestSync) + { + syncNextNeighborBlockForestFunc(*ps, blocks->getBlockForestPointer(), rpdDomain, overlap); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, associateToBlock, *accessor); + } else + { + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + } + timeloopTiming["Sync"].end(); + + // lubrication correction + timeloopTiming["RPD Lub"].start(); + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&lubricationCorrectionKernel,maximumLubricationCutOffDistance, &rpdDomain] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + acd.getContactThreshold() = maximumLubricationCutOffDistance; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + double_cast(acd.getIdx1(), acd.getIdx2(), ac, lubricationCorrectionKernel, ac, acd.getContactNormal(), acd.getPenetrationDepth()); + } + } + }, + *accessor ); + timeloopTiming["RPD Lub"].end(); + + // collision response + timeloopTiming["RPD Collision"].start(); + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&collisionResponse, &rpdDomain, timeStepSizeRPD] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + collisionResponse(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), acd.getContactNormal(), acd.getPenetrationDepth(), timeStepSizeRPD); + } + } + }, + *accessor ); + + timeloopTiming["RPD Collision"].end(); + + timeloopTiming["Reduce Contact History"].start(); + reduceAndSwapContactHistory(*ps); + timeloopTiming["Reduce Contact History"].end(); + + timeloopTiming["RPD Force"].start(); + lbm_mesapd_coupling::AddHydrodynamicInteractionKernel addHydrodynamicInteraction; + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor ); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); + timeloopTiming["RPD Force"].end(); + + timeloopTiming["Reduce Force Torque"].start(); + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + timeloopTiming["Reduce Force Torque"].end(); + + // integration + timeloopTiming["RPD VV2"].start(); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPostForce, *accessor); + timeloopTiming["RPD VV2"].end(); + + timeloopTiming["Sync"].start(); + if(useBlockForestSync) + { + syncNextNeighborBlockForestFunc(*ps, blocks->getBlockForestPointer(), rpdDomain, overlap); + } else + { + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + } + timeloopTiming["Sync"].end(); + + + } + + timeloopTiming["RPD Force"].start(); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + timeloopTiming["RPD Force"].end(); + + // update particle mapping + timeloopAfterParticles.singleStep(timeloopTiming); + + simulationTiming[simulationStep].end(); + + } + + simulationTiming.logResultOnRoot(); + + + return EXIT_SUCCESS; +} + +} // namespace fluid_particle_workload_distribution + +int main( int argc, char **argv ){ + fluid_particle_workload_distribution::main(argc, argv); +} diff --git a/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadEvaluation.cpp b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadEvaluation.cpp new file mode 100644 index 000000000..062e3f9c9 --- /dev/null +++ b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/FluidParticleWorkloadEvaluation.cpp @@ -0,0 +1,956 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file FluidParticleWorkLoadEvaluation.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#include "blockforest/Initialization.h" +#include "blockforest/communication/UniformBufferedScheme.h" + +#include "boundary/all.h" + +#include "core/DataTypes.h" +#include "core/Environment.h" +#include "core/debug/Debug.h" +#include "core/debug/TestSubsystem.h" +#include "core/logging/Logging.h" +#include "core/math/all.h" +#include "core/timing/RemainingTimeLogger.h" +#include "core/mpi/MPIManager.h" +#include "core/mpi/Reduce.h" +#include "core/mpi/Broadcast.h" + +#include "domain_decomposition/SharedSweep.h" + +#include "field/AddToStorage.h" +#include "field/communication/PackInfo.h" + +#include "lbm/communication/PdfFieldPackInfo.h" +#include "lbm/field/AddToStorage.h" +#include "lbm/field/PdfField.h" +#include "lbm/lattice_model/D3Q19.h" +#include "lbm/lattice_model/ForceModel.h" +#include "lbm/sweeps/CellwiseSweep.h" +#include "lbm/sweeps/SweepWrappers.h" +#include "lbm/BlockForestEvaluation.h" + +#include "lbm_mesapd_coupling/mapping/ParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/MovingParticleMapping.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/boundary/CurvedLinear.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/Reconstructor.h" +#include "lbm_mesapd_coupling/momentum_exchange_method/reconstruction/PdfReconstructionManager.h" +#include "lbm_mesapd_coupling/utility/AddForceOnParticlesKernel.h" +#include "lbm_mesapd_coupling/utility/ParticleSelector.h" +#include "lbm_mesapd_coupling/DataTypes.h" +#include "lbm_mesapd_coupling/utility/AverageHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/AddHydrodynamicInteractionKernel.h" +#include "lbm_mesapd_coupling/utility/ResetHydrodynamicForceTorqueKernel.h" +#include "lbm_mesapd_coupling/utility/LubricationCorrectionKernel.h" +#include "lbm_mesapd_coupling/utility/InitializeHydrodynamicForceTorqueForAveragingKernel.h" + +#include "mesa_pd/collision_detection/AnalyticContactDetection.h" +#include "mesa_pd/data/ParticleAccessorWithShape.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/data/ShapeStorage.h" +#include "mesa_pd/data/DataTypes.h" +#include "mesa_pd/data/shape/HalfSpace.h" +#include "mesa_pd/data/shape/Sphere.h" +#include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/domain/BlockForestDataHandling.h" +#include "mesa_pd/kernel/DoubleCast.h" +#include "mesa_pd/kernel/ExplicitEuler.h" +#include "mesa_pd/kernel/LinearSpringDashpot.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/mpi/SyncNextNeighbors.h" +#include "mesa_pd/mpi/ReduceProperty.h" +#include "mesa_pd/mpi/ReduceContactHistory.h" +#include "mesa_pd/mpi/ContactFilter.h" +#include "mesa_pd/mpi/notifications/ForceTorqueNotification.h" +#include "mesa_pd/mpi/notifications/HydrodynamicForceTorqueNotification.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "timeloop/SweepTimeloop.h" + +#include "vtk/all.h" +#include "field/vtk/all.h" +#include "lbm/vtk/all.h" + +#include <vector> +#include <iostream> + +namespace fluid_particle_workload_evaluation +{ + +/////////// +// USING // +/////////// + +using namespace walberla; +using walberla::uint_t; + +using LatticeModel_T = lbm::D3Q19< lbm::collision_model::TRT, false >; +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; + +const uint_t FieldGhostLayers = 1; + +/////////// +// FLAGS // +/////////// + +const FlagUID Fluid_Flag ( "fluid" ); +const FlagUID MO_Flag ( "moving obstacle" ); +const FlagUID FormerMO_Flag( "former moving obstacle" ); + + +///////////////////////////////////// +// BOUNDARY HANDLING CUSTOMIZATION // +///////////////////////////////////// +template <typename ParticleAccessor_T> +class MyBoundaryHandling +{ +public: + + using MO_T = lbm_mesapd_coupling::CurvedLinear< LatticeModel_T, FlagField_T, ParticleAccessor_T >; + using Type = BoundaryHandling< FlagField_T, Stencil_T, MO_T >; + + MyBoundaryHandling( const BlockDataID & flagFieldID, const BlockDataID & pdfFieldID, + const BlockDataID & particleFieldID, const shared_ptr<ParticleAccessor_T>& ac, + bool useEntireFieldTraversal) : + flagFieldID_( flagFieldID ), pdfFieldID_( pdfFieldID ), particleFieldID_( particleFieldID ), ac_( ac ), useEntireFieldTraversal_(useEntireFieldTraversal) {} + + Type * operator()( IBlock* const block, const StructuredBlockStorage* const storage ) const + { + WALBERLA_ASSERT_NOT_NULLPTR( block ); + WALBERLA_ASSERT_NOT_NULLPTR( storage ); + + auto * flagField = block->getData< FlagField_T >( flagFieldID_ ); + auto * pdfField = block->getData< PdfField_T > ( pdfFieldID_ ); + auto * particleField = block->getData< lbm_mesapd_coupling::ParticleField_T > ( particleFieldID_ ); + + const auto fluid = flagField->flagExists( Fluid_Flag ) ? flagField->getFlag( Fluid_Flag ) : flagField->registerFlag( Fluid_Flag ); + + typename Type::Mode mode = (useEntireFieldTraversal_) ? Type::Mode::ENTIRE_FIELD_TRAVERSAL : Type::Mode::OPTIMIZED_SPARSE_TRAVERSAL ; + + Type * handling = new Type( "moving obstacle boundary handling", flagField, fluid, + MO_T( "MO", MO_Flag, pdfField, flagField, particleField, ac_, fluid, *storage, *block ), + mode); + + handling->fillWithDomain( FieldGhostLayers ); + + return handling; + } + +private: + + const BlockDataID flagFieldID_; + const BlockDataID pdfFieldID_; + const BlockDataID particleFieldID_; + + shared_ptr<ParticleAccessor_T> ac_; + + bool useEntireFieldTraversal_; +}; + +template< typename BoundaryHandling_T > +void evaluateFluidQuantities(const shared_ptr< StructuredBlockStorage > & blocks, const BlockDataID boundaryHandlingID, + uint_t & numCells, uint_t & numFluidCells, uint_t & numNBCells ) +{ + + for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt) + { + auto * boundaryHandling = blockIt->getData< BoundaryHandling_T >( boundaryHandlingID ); + auto xyzSize = boundaryHandling->getFlagField()->xyzSize(); + numCells += xyzSize.numCells(); + + for(auto z = cell_idx_t(xyzSize.zMin()); z <= cell_idx_t(xyzSize.zMax()); ++z ){ + for(auto y = cell_idx_t(xyzSize.yMin()); y <= cell_idx_t(xyzSize.yMax()); ++y ){ + for(auto x = cell_idx_t(xyzSize.xMin()); x <= cell_idx_t(xyzSize.xMax()); ++x ) { + if (boundaryHandling->isDomain(x, y, z)) { + ++numFluidCells; + } + if (boundaryHandling->isNearBoundary(x, y, z)) { + ++numNBCells; + } + } + } + } + } +} + +void evaluateRPDQuantities( const shared_ptr< mesa_pd::data::ParticleStorage > & ps, + uint_t & numLocalParticles, uint_t & numGhostParticles) +{ + + for (auto pIt = ps->begin(); pIt != ps->end(); ++pIt) + { + using namespace walberla::mesa_pd::data::particle_flags; + if (isSet(pIt->getFlags(), GHOST)) + { + ++numGhostParticles; + } else + { + //note: global particles are included here + // use if (!isSet(pIt->getFlags(), GLOBAL)) if should be excluded + ++numLocalParticles; + } + } +} + +void evaluateTimers(WcTimingPool & timingPool, + const std::vector<std::vector<std::string> > & timerKeys, + std::vector<double> & timings ) +{ + + for (auto & timingsIt : timings) + { + timingsIt = 0.0; + } + + timingPool.unifyRegisteredTimersAcrossProcesses(); + + double scalingFactor = 1000.0; // milliseconds + + for (auto i = uint_t(0); i < timerKeys.size(); ++i ) + { + auto keys = timerKeys[i]; + for (const auto &timerName : keys) + { + if(timingPool.timerExists(timerName)) + { + timings[i] += timingPool[timerName].total() * scalingFactor; + } + } + + } +} + + +//******************************************************************************************************************* +/*! Application to evaluate the workload (time measurements) for a fluid-particle simulation + * + * This application is used in the paper + * Rettinger, Ruede - "Dynamic Load Balancing Techniques for Particulate Flow Simulations", 2019, Computation + * in Section 3 to develop and calibrate the workload estimator. + * The setup features settling particle inside a horizontally periodic box. + * A comprehensive description is given in Sec. 3.3 of the paper. + * It uses 4 x 4 x 5 blocks for domain partitioning. + * For each block ( = each process), the block local quantities are evaluated as well as the timing infos of + * the fluid-particle interaction algorithm. Those infos are then written to files that can be used later on + * for function fitting to obtain a workload estimator. + * + * NOTE: Since this estimator relies on timing measurements, this evaluation procedure should be carried out everytime + * a different implementation, hardware or algorithm is used. + * + */ +//******************************************************************************************************************* +int main( int argc, char **argv ) +{ + debug::enterTestMode(); + + mpi::Environment env( argc, argv ); + + auto solidVolumeFraction = real_t(0.2); + + // LBM / numerical parameters + auto blockSize = uint_t(32); + auto uSettling = real_t(0.1); // characteristic settling velocity + auto diameter = real_t(10); + + auto Ga = real_t(30); //Galileo number + auto numRPDSubCycles = uint_t(10); + + auto vtkIOFreq = uint_t(0); + auto timestepsNonDim = real_t(2.5); + auto numSamples = uint_t(2000); + std::string baseFolder = "workload_files"; // folder for vtk and file output + + bool noFileOutput = false; + bool useEntireFieldTraversal = true; + bool useFusedStreamCollide = false; + + auto XBlocks = uint_t(4); + auto YBlocks = uint_t(4); + auto ZBlocks = uint_t(5); + + real_t topWallOffsetFactor = real_t(1.05); + + bool vtkDuringInit = false; + + for( int i = 1; i < argc; ++i ) + { + if( std::strcmp( argv[i], "--vtkIOFreq" ) == 0 ) { vtkIOFreq = uint_c( std::atof( argv[++i] ) ); continue; } + if( std::strcmp( argv[i], "--noFileOutput" ) == 0 ) { noFileOutput = true; continue; } + if( std::strcmp( argv[i], "--vtkDuringInit" ) == 0 ) { vtkDuringInit = true; continue; } + if( std::strcmp( argv[i], "--basefolder" ) == 0 ) { baseFolder = argv[++i]; continue; } + if( std::strcmp( argv[i], "--solidVolumeFraction" ) == 0 ) { solidVolumeFraction = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--diameter" ) == 0 ) { diameter = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--blockSize" ) == 0 ) { blockSize = uint_c(std::atof( argv[++i]) ); continue; } + if( std::strcmp( argv[i], "--XBlocks" ) == 0 ) { XBlocks = uint_c(std::atof( argv[++i]) ); continue; } + if( std::strcmp( argv[i], "--YBlocks" ) == 0 ) { YBlocks = uint_c(std::atof( argv[++i]) ); continue; } + if( std::strcmp( argv[i], "--ZBlocks" ) == 0 ) { ZBlocks = uint_c(std::atof( argv[++i]) ); continue; } + if( std::strcmp( argv[i], "--uSettling" ) == 0 ) { uSettling = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--topWallOffsetFactor" ) == 0 ) { topWallOffsetFactor = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--Ga" ) == 0 ) { Ga = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--timestepsNonDim" ) == 0 ) { timestepsNonDim = real_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--numRPDSubCycles" ) == 0 ) { numRPDSubCycles = uint_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--useEntireFieldTraversal" ) == 0 ) { useEntireFieldTraversal = true; continue; } + if( std::strcmp( argv[i], "--numSamples" ) == 0 ) { numSamples = uint_c(std::atof( argv[++i] )); continue; } + if( std::strcmp( argv[i], "--useFusedStreamCollide" ) == 0 ) { useFusedStreamCollide = true; continue; } + WALBERLA_ABORT("Unrecognized command line argument found: " << argv[i]); + } + + WALBERLA_CHECK(diameter > real_t(1)); + WALBERLA_CHECK(uSettling > real_t(0)); + WALBERLA_CHECK(Ga > real_t(0)); + WALBERLA_CHECK(solidVolumeFraction > real_t(0)); + WALBERLA_CHECK(solidVolumeFraction < real_t(0.65)); + + /////////////////////////// + // SIMULATION PROPERTIES // + /////////////////////////// + + + if( MPIManager::instance()->numProcesses() != int(XBlocks * YBlocks * ZBlocks) ) + { + WALBERLA_LOG_WARNING_ON_ROOT("WARNING! You have specified less or more processes than number of blocks -> the time measurements are no longer blockwise!") + } + + if( diameter > real_c(blockSize) ) + { + WALBERLA_LOG_WARNING_ON_ROOT("The bodies might be too large to work with the currently used synchronization!"); + } + + WALBERLA_LOG_INFO_ON_ROOT("Using setup with sedimenting particles -> creating two planes and applying gravitational force") + + const uint_t XCells = blockSize * XBlocks; + const uint_t YCells = blockSize * YBlocks; + const uint_t ZCells = blockSize * ZBlocks; + + const real_t topWallOffset = topWallOffsetFactor * real_t(blockSize); // move the top wall downwards to take away a certain portion of the overall domain + + // determine number of spheres to generate, if necessary scale diameter a bit to reach desired solid volume fraction + real_t domainHeight = real_c(ZCells) - topWallOffset; + real_t fluidVolume = real_c( XCells * YCells ) * domainHeight; + real_t solidVolume = solidVolumeFraction * fluidVolume; + uint_t numberOfParticles = uint_c(std::ceil(solidVolume / ( math::pi / real_t(6) * diameter * diameter * diameter ))); + diameter = std::cbrt( solidVolume / ( real_c(numberOfParticles) * math::pi / real_t(6) ) ); + + auto densityRatio = real_t(2.5); + + real_t viscosity = uSettling * diameter / Ga; + const real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); + + const real_t gravitationalAcceleration = uSettling * uSettling / ( (densityRatio-real_t(1)) * diameter ); + + real_t tref = diameter / uSettling; + real_t Tref = domainHeight / uSettling; + + uint_t timesteps = uint_c(timestepsNonDim * Tref); + + const real_t dx = real_c(1); + WALBERLA_LOG_INFO_ON_ROOT("viscosity = " << viscosity); + WALBERLA_LOG_INFO_ON_ROOT("tau = " << real_t(1)/omega); + WALBERLA_LOG_INFO_ON_ROOT("diameter = " << diameter); + WALBERLA_LOG_INFO_ON_ROOT("solid volume fraction = " << solidVolumeFraction); + WALBERLA_LOG_INFO_ON_ROOT("domain size (in cells) = " << XCells << " x " << YCells << " x " << ZCells); + WALBERLA_LOG_INFO_ON_ROOT("number of bodies = " << numberOfParticles); + WALBERLA_LOG_INFO_ON_ROOT("gravitational acceleration = " << gravitationalAcceleration); + WALBERLA_LOG_INFO_ON_ROOT("Ga = " << Ga); + WALBERLA_LOG_INFO_ON_ROOT("uSettling = " << uSettling); + WALBERLA_LOG_INFO_ON_ROOT("tref = " << tref); + WALBERLA_LOG_INFO_ON_ROOT("Tref = " << Tref); + WALBERLA_LOG_INFO_ON_ROOT("timesteps = " << timesteps); + WALBERLA_LOG_INFO_ON_ROOT("number of workload samples = " << numSamples); + + // create folder to store logging files + WALBERLA_ROOT_SECTION() + { + walberla::filesystem::path path1( baseFolder ); + if( !walberla::filesystem::exists( path1 ) ) + walberla::filesystem::create_directory( path1 ); + } + + + /////////////////////////// + // BLOCK STRUCTURE SETUP // + /////////////////////////// + + Vector3<bool> periodicity( true ); + periodicity[2] = false; + + // create domain + shared_ptr< StructuredBlockForest > blocks = blockforest::createUniformBlockGrid( XBlocks, YBlocks, ZBlocks, blockSize, blockSize, blockSize, dx, + 0, false, false, //one block per process! + periodicity[0], periodicity[1], periodicity[2], //periodicity + false ); + + ///////// + // RPD // + ///////// + + const real_t restitutionCoeff = real_t(0.97); + const real_t frictionCoeffStatic = real_t(0.8); + const real_t frictionCoeffDynamic = real_t(0.15); + const real_t collisionTime = real_t(4) * diameter; // from my paper + const real_t poissonsRatio = real_t(0.22); + const real_t kappa = real_t(2) * ( real_t(1) - poissonsRatio ) / ( real_t(2) - poissonsRatio ) ; + + auto rpdDomain = std::make_shared<mesa_pd::domain::BlockForestDomain>(blocks->getBlockForestPointer()); + + //init data structures + auto ps = walberla::make_shared<mesa_pd::data::ParticleStorage>(1); + auto ss = walberla::make_shared<mesa_pd::data::ShapeStorage>(); + using ParticleAccessor_T = mesa_pd::data::ParticleAccessorWithShape; + auto accessor = walberla::make_shared<ParticleAccessor_T >(ps, ss); + + real_t timeStepSizeRPD = real_t(1)/real_t(numRPDSubCycles); + mesa_pd::kernel::VelocityVerletPreForceUpdate vvIntegratorPreForce(timeStepSizeRPD); + mesa_pd::kernel::VelocityVerletPostForceUpdate vvIntegratorPostForce(timeStepSizeRPD); + + // types: 0 = wall, 1: sphere + mesa_pd::kernel::LinearSpringDashpot collisionResponse(2); + collisionResponse.setFrictionCoefficientDynamic(0,1,frictionCoeffDynamic); + collisionResponse.setFrictionCoefficientDynamic(1,1,frictionCoeffDynamic); + collisionResponse.setFrictionCoefficientStatic(0,1,frictionCoeffStatic); + collisionResponse.setFrictionCoefficientStatic(1,1,frictionCoeffStatic); + + const real_t sphereVolume = math::pi / real_t(6) * diameter * diameter * diameter; + const real_t particleMass = densityRatio * sphereVolume; + const real_t effMass_sphereWall = particleMass; + const real_t effMass_sphereSphere = particleMass * particleMass / ( real_t(2) * particleMass ); + collisionResponse.setStiffnessAndDamping(0,1,restitutionCoeff,collisionTime,kappa,effMass_sphereWall); + collisionResponse.setStiffnessAndDamping(1,1,restitutionCoeff,collisionTime,kappa,effMass_sphereSphere); + + mesa_pd::mpi::ReduceProperty reduceProperty; + mesa_pd::mpi::ReduceContactHistory reduceAndSwapContactHistory; + + ////////////// + // COUPLING // + ////////////// + + // connect to pe + const real_t overlap = real_c( 1.5 ) * dx; + + std::function<void(void)> syncCall = [&ps,&rpdDomain,overlap](){ + mesa_pd::mpi::SyncNextNeighbors syncNextNeighborFunc; + syncNextNeighborFunc(*ps, *rpdDomain, overlap); + }; + + auto generationDomain = AABB( real_t(0), real_t(0), real_t(0), real_c(XCells), real_c(YCells), real_c(ZCells) - topWallOffset); + + // create plane at top and bottom + + mesa_pd::data::Particle&& p0 = *ps->create(true); + p0.setPosition(generationDomain.minCorner()); + p0.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,0,1) )); + p0.setOwner(mpi::MPIManager::instance()->rank()); + p0.setType(0); + mesa_pd::data::particle_flags::set(p0.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); + mesa_pd::data::particle_flags::set(p0.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); + + mesa_pd::data::Particle&& p1 = *ps->create(true); + p1.setPosition(generationDomain.maxCorner()); + p1.setShapeID(ss->create<mesa_pd::data::HalfSpace>( Vector3<real_t>(0,0,-1) )); + p1.setOwner(mpi::MPIManager::instance()->rank()); + p1.setType(0); + mesa_pd::data::particle_flags::set(p1.getFlagsRef(), mesa_pd::data::particle_flags::INFINITE); + mesa_pd::data::particle_flags::set(p1.getFlagsRef(), mesa_pd::data::particle_flags::FIXED); + + auto sphereShape = ss->create<mesa_pd::data::Sphere>( diameter * real_t(0.5) ); + ss->shapes[sphereShape]->updateMassAndInertia(densityRatio); + + auto xParticle = real_t(0); + auto yParticle = real_t(0); + auto zParticle = real_t(0); + + auto rank = mpi::MPIManager::instance()->rank(); + + for( uint_t nPart = 0; nPart < numberOfParticles; ++nPart ) + { + + WALBERLA_ROOT_SECTION() + { + xParticle = math::realRandom<real_t>(generationDomain.xMin(), generationDomain.xMax()); + yParticle = math::realRandom<real_t>(generationDomain.yMin(), generationDomain.yMax()); + zParticle = math::realRandom<real_t>(generationDomain.zMin(), generationDomain.zMax()); + + } + + WALBERLA_MPI_SECTION() + { + mpi::broadcastObject( xParticle ); + mpi::broadcastObject( yParticle ); + mpi::broadcastObject( zParticle ); + } + + auto position = Vector3<real_t>( xParticle, yParticle, zParticle ); + //WALBERLA_LOG_INFO_ON_ROOT(position); + + if (!rpdDomain->isContainedInProcessSubdomain(uint_c(rank), position)) continue; + auto p = ps->create(); + p->setPosition(position); + p->setInteractionRadius(diameter * real_t(0.5)); + p->setShapeID(sphereShape); + p->setType(1); + p->setOwner(rank); + } + + syncCall(); + + // resolve possible overlaps of the particles due to the random initialization via a particle-only simulation + + const bool useOpenMP = false; + const real_t dt_RPD_Init = real_t(1); + const auto initialParticleSimSteps = uint_t(20000); + const real_t overlapLimit = real_t(0.001) * diameter; + + auto particleVtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + particleVtkOutput->addOutput<mesa_pd::data::SelectParticleLinearVelocity>("velocity"); + particleVtkOutput->setParticleSelector( [sphereShape](const mesa_pd::data::ParticleStorage::iterator& pIt) {return !mesa_pd::data::particle_flags::isSet(pIt->getFlags(), mesa_pd::data::particle_flags::GHOST) && pIt->getShapeID() == sphereShape;} ); //limit output to local sphere + auto particleVtkWriterInit = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles_init", 1, baseFolder, "simulation_step"); + + for(auto pet = uint_t(0); pet <= initialParticleSimSteps; ++pet ) + { + + + real_t maxPenetrationDepth = 0; + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&collisionResponse, &rpdDomain, &maxPenetrationDepth, dt_RPD_Init] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + maxPenetrationDepth = std::max(maxPenetrationDepth, std::abs(acd.getPenetrationDepth())); + collisionResponse(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), + acd.getContactNormal(), acd.getPenetrationDepth(), dt_RPD_Init); + } + } + }, + *accessor ); + + reduceAndSwapContactHistory(*ps); + + mpi::allReduceInplace(maxPenetrationDepth, mpi::MAX); + + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, mesa_pd::kernel::ExplicitEuler(dt_RPD_Init), *accessor); + syncCall(); + + if( pet % uint_t(20) == uint_t(0) ) + { + if(vtkDuringInit) + { + particleVtkWriterInit->write(); + } + WALBERLA_LOG_INFO_ON_ROOT(pet << " - current max overlap = " << maxPenetrationDepth / diameter * real_t(100) << "%"); + } + + if(maxPenetrationDepth < overlapLimit) break; + + // reset velocites to avoid too large ones + + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [](const size_t idx, ParticleAccessor_T& ac){ + ac.setLinearVelocity(idx, ac.getLinearVelocity(idx) * real_t(0.5)); + ac.setAngularVelocity(idx, ac.getAngularVelocity(idx) * real_t(0.5)); + }, *accessor); + + + } + + + // reset all velocities to zero + Vector3<real_t> initialSphereVelocity(real_t(0)); + + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, [](const size_t idx, ParticleAccessor_T& ac){ + ac.getNewContactHistoryRef(idx).clear(); + ac.getOldContactHistoryRef(idx).clear(); + }, *accessor); + + WALBERLA_LOG_INFO_ON_ROOT("Setting initial velocity " << initialSphereVelocity << " of all spheres"); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, + [initialSphereVelocity](const size_t idx, ParticleAccessor_T& ac){ + ac.setLinearVelocity(idx, initialSphereVelocity); + ac.setAngularVelocity(idx, Vector3<real_t>(real_t(0))); + }, *accessor); + + syncCall(); + + /////////////////////// + // ADD DATA TO BLOCKS // + //////////////////////// + + // create the lattice model + LatticeModel_T latticeModel = LatticeModel_T( lbm::collision_model::TRT::constructWithMagicNumber( omega ) ); + + // add PDF field + BlockDataID pdfFieldID = lbm::addPdfFieldToStorage< LatticeModel_T >( blocks, "pdf field (zyxf)", latticeModel, + Vector3< real_t >( real_t(0) ), real_t(1), + uint_t(1), field::zyxf ); + + // add flag field + BlockDataID flagFieldID = field::addFlagFieldToStorage<FlagField_T>( blocks, "flag field" ); + + // add particle field + BlockDataID particleFieldID = field::addToStorage<lbm_mesapd_coupling::ParticleField_T>( blocks, "particle field", accessor->getInvalidUid(), field::zyxf, FieldGhostLayers ); + + // add boundary handling & initialize outer domain boundaries + using BoundaryHandling_T = MyBoundaryHandling<ParticleAccessor_T>::Type; + BlockDataID boundaryHandlingID = blocks->addStructuredBlockData< BoundaryHandling_T >(MyBoundaryHandling<ParticleAccessor_T>( flagFieldID, pdfFieldID, particleFieldID, accessor, useEntireFieldTraversal), "boundary handling" ); + + Vector3<real_t> gravitationalForce( real_t(0), real_t(0), -(densityRatio - real_t(1)) * gravitationalAcceleration * sphereVolume ); + lbm_mesapd_coupling::AddForceOnParticlesKernel addGravitationalForce(gravitationalForce); + lbm_mesapd_coupling::ResetHydrodynamicForceTorqueKernel resetHydrodynamicForceTorque; + lbm_mesapd_coupling::AverageHydrodynamicForceTorqueKernel averageHydrodynamicForceTorque; + lbm_mesapd_coupling::LubricationCorrectionKernel lubricationCorrectionKernel(viscosity, [](real_t r){return (real_t(0.001 + real_t(0.00007)*r))*r;}); + lbm_mesapd_coupling::ParticleMappingKernel<BoundaryHandling_T> particleMappingKernel(blocks, boundaryHandlingID); + lbm_mesapd_coupling::MovingParticleMappingKernel<BoundaryHandling_T> movingParticleMappingKernel(blocks, boundaryHandlingID, particleFieldID); + + WALBERLA_LOG_INFO_ON_ROOT(" - Lubrication correction:"); + WALBERLA_LOG_INFO_ON_ROOT(" - normal cut off distance = " << lubricationCorrectionKernel.getNormalCutOffDistance()); + WALBERLA_LOG_INFO_ON_ROOT(" - tangential translational cut off distance = " << lubricationCorrectionKernel.getTangentialTranslationalCutOffDistance()); + WALBERLA_LOG_INFO_ON_ROOT(" - tangential rotational cut off distance = " << lubricationCorrectionKernel.getTangentialRotationalCutOffDistance()); + const real_t maximumLubricationCutOffDistance = std::max(lubricationCorrectionKernel.getNormalCutOffDistance(), std::max(lubricationCorrectionKernel.getTangentialRotationalCutOffDistance(), lubricationCorrectionKernel.getTangentialTranslationalCutOffDistance())); + + + // map planes into the LBM simulation -> act as no-slip boundaries + ps->forEachParticle(false, lbm_mesapd_coupling::GlobalParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + + // map particles into the LBM simulation + ps->forEachParticle(false, lbm_mesapd_coupling::RegularParticlesSelector(), *accessor, movingParticleMappingKernel, *accessor, MO_Flag); + + lbm::BlockForestEvaluation<FlagField_T> bfEval(blocks, flagFieldID, Fluid_Flag); + + WALBERLA_LOG_INFO_ON_ROOT(bfEval.loggingString()); + + /////////////// + // TIME LOOP // + /////////////// + + // create the timeloop + SweepTimeloop timeloop( blocks->getBlockStorage(), timesteps ); + + timeloop.addFuncBeforeTimeStep( RemainingTimeLogger( timeloop.getNrOfTimeSteps() ), "Remaining Time Logger" ); + + if( vtkIOFreq != uint_t(0) ) + { + auto particleVtkWriter = vtk::createVTKOutput_PointData(particleVtkOutput, "Particles", vtkIOFreq, baseFolder, "simulation_step"); + timeloop.addFuncBeforeTimeStep( vtk::writeFiles( particleVtkWriter ), "VTK (sphere data)" ); + + // flag field + auto flagFieldVTK = vtk::createVTKOutput_BlockData( blocks, "flag_field", vtkIOFreq, 1, false, baseFolder ); + flagFieldVTK->addCellDataWriter( make_shared< field::VTKWriter< FlagField_T > >( flagFieldID, "FlagField" ) ); + timeloop.addFuncBeforeTimeStep( vtk::writeFiles( flagFieldVTK ), "VTK (flag field data)" ); + + // pdf field + auto pdfFieldVTK = vtk::createVTKOutput_BlockData( blocks, "fluid_field", vtkIOFreq, 0, false, baseFolder ); + + field::FlagFieldCellFilter< FlagField_T > fluidFilter( flagFieldID ); + fluidFilter.addFlag( Fluid_Flag ); + pdfFieldVTK->addCellInclusionFilter( fluidFilter ); + + pdfFieldVTK->addCellDataWriter( make_shared< lbm::VelocityVTKWriter< LatticeModel_T, float > >( pdfFieldID, "VelocityFromPDF" ) ); + pdfFieldVTK->addCellDataWriter( make_shared< lbm::DensityVTKWriter < LatticeModel_T, float > >( pdfFieldID, "DensityFromPDF" ) ); + + timeloop.addFuncBeforeTimeStep( vtk::writeFiles( pdfFieldVTK ), "VTK (fluid field data)" ); + + auto domainDecompVTK = vtk::createVTKOutput_DomainDecomposition(blocks, "domain_decomposition", vtkIOFreq, baseFolder ); + timeloop.addFuncBeforeTimeStep( vtk::writeFiles(domainDecompVTK), "VTK (domain decomposition)"); + } + + + // setup of the LBM communication for synchronizing the pdf field between neighboring blocks + blockforest::communication::UniformBufferedScheme< Stencil_T > optimizedPDFCommunicationScheme( blocks ); + optimizedPDFCommunicationScheme.addPackInfo( make_shared< lbm::PdfFieldPackInfo< LatticeModel_T > >( pdfFieldID ) ); // optimized sync + + auto sweep = lbm::makeCellwiseSweep< LatticeModel_T, FlagField_T >( pdfFieldID, flagFieldID, Fluid_Flag ); + + if( !useFusedStreamCollide ) + { + // Collide + timeloop.add() << Sweep( makeCollideSweep(sweep), "Collide" ); + } + + // add LBM communication function and boundary handling sweep (does the hydro force calculations and the no-slip treatment) + timeloop.add() << BeforeFunction( optimizedPDFCommunicationScheme, "LBM Communication" ) + << Sweep( BoundaryHandling_T::getBlockSweep( boundaryHandlingID ), "Boundary Handling" ); + + if( useFusedStreamCollide ) + { + // streaming & collide + timeloop.add() << Sweep( makeSharedSweep(sweep), "Stream&Collide" ); + } else + { + // streaming + timeloop.add() << Sweep( makeStreamSweep(sweep), "Stream" ); + + } + + SweepTimeloop timeloopAfterParticles( blocks->getBlockStorage(), timesteps ); + + bool conserveMomentum = false; + // sweep for updating the particle mapping into the LBM simulation + timeloopAfterParticles.add() << Sweep( lbm_mesapd_coupling::makeMovingParticleMapping<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID,boundaryHandlingID, particleFieldID, accessor, MO_Flag, FormerMO_Flag, + lbm_mesapd_coupling::RegularParticlesSelector(), conserveMomentum), "Particle Mapping" ); + + bool recomputeTargetDensity = false; + auto gradReconstructor = lbm_mesapd_coupling::makeGradsMomentApproximationReconstructor<BoundaryHandling_T>(blocks, boundaryHandlingID, omega, recomputeTargetDensity,true); + + + blockforest::communication::UniformBufferedScheme< Stencil_T > fullPDFCommunicationScheme( blocks ); + fullPDFCommunicationScheme.addPackInfo( make_shared< field::communication::PackInfo< PdfField_T > >( pdfFieldID ) ); // full sync + + timeloopAfterParticles.add() << BeforeFunction( fullPDFCommunicationScheme, "PDF Communication" ) + << Sweep( makeSharedSweep(lbm_mesapd_coupling::makePdfReconstructionManager<PdfField_T,BoundaryHandling_T>(blocks, pdfFieldID, boundaryHandlingID, particleFieldID, accessor, FormerMO_Flag, Fluid_Flag, + gradReconstructor, conserveMomentum) ), "PDF Restore" ); + + + //////////////////////// + // EXECUTE SIMULATION // + //////////////////////// + + WcTimingPool timeloopTiming; + + std::vector< std::vector<std::string> > timerKeys; + std::vector<std::string> LBMTimer; + LBMTimer.emplace_back("Stream&Collide"); + LBMTimer.emplace_back("Stream"); + LBMTimer.emplace_back("Collide"); + timerKeys.push_back(LBMTimer); + + std::vector<std::string> bhTimer; + bhTimer.emplace_back("Boundary Handling"); + timerKeys.push_back(bhTimer); + + std::vector<std::string> couplingTimer1; + couplingTimer1.emplace_back("Particle Mapping"); + std::vector<std::string> couplingTimer2; + couplingTimer2.emplace_back("PDF Restore"); + timerKeys.push_back(couplingTimer1); + timerKeys.push_back(couplingTimer2); + + std::vector<std::string> rpdTimer; + rpdTimer.emplace_back("RPD Force"); + rpdTimer.emplace_back("RPD VV1"); + rpdTimer.emplace_back("RPD VV2"); + rpdTimer.emplace_back("RPD Lub"); + rpdTimer.emplace_back("RPD Collision"); + timerKeys.push_back(rpdTimer); + + uint_t numCells = uint_t(0); + uint_t numFluidCells = uint_t(0); + uint_t numNBCells = uint_t(0); + uint_t numLocalParticles = uint_t(0); + uint_t numGhostParticles = uint_t(0); + uint_t numContacts = uint_t(0); + + std::vector<double> timings(timerKeys.size()); + + // every rank writes its own file -> numProcesses number of samples! + int myRank = MPIManager::instance()->rank(); + + std::string logFileName = baseFolder + "/load"; + logFileName += "_settling"; + logFileName += "_spheres"; + logFileName += "_d" + std::to_string(int_c(std::ceil(diameter))); + logFileName += "_bs" + std::to_string(blockSize); + logFileName += "_" + std::to_string(myRank) + ".txt"; + + + std::ofstream file; + + if(!noFileOutput) + { + WALBERLA_LOG_INFO_ON_ROOT("Writing load info to file " << logFileName); + file.open( logFileName.c_str()); + file << "# svf = " << solidVolumeFraction << ", d = " << diameter << ", domain = " << XCells << "x" << YCells << "x" << ZCells << "\n"; + } + + + auto timeStepOfFirstTiming = uint_t(50); + + if( timesteps - timeStepOfFirstTiming < numSamples ) + { + WALBERLA_LOG_WARNING_ON_ROOT("Less actual time steps than number of required samples!"); + } + + uint_t nSample( 0 ); // number of current sample + real_t samplingFrequency = real_c(timesteps - timeStepOfFirstTiming) / real_c(numSamples); + + // time loop + for (uint_t i = 0; i < timesteps; ++i ) + { + // perform a single simulation step + + timeloop.singleStep( timeloopTiming ); + + reduceProperty.operator()<mesa_pd::HydrodynamicForceTorqueNotification>(*ps); + + timeloopTiming["RPD Force"].start(); + if( i == 0 ) + { + lbm_mesapd_coupling::InitializeHydrodynamicForceTorqueForAveragingKernel initializeHydrodynamicForceTorqueForAveragingKernel; + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, initializeHydrodynamicForceTorqueForAveragingKernel, *accessor ); + } + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, averageHydrodynamicForceTorque, *accessor ); + timeloopTiming["RPD Force"].end(); + + for(auto subCycle = uint_t(0); subCycle < numRPDSubCycles; ++subCycle ) + { + + timeloopTiming["RPD VV1"].start(); + ps->forEachParticle(useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPreForce, *accessor); + timeloopTiming["RPD VV1"].end(); + + syncCall(); + + // lubrication correction + timeloopTiming["RPD Lub"].start(); + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&lubricationCorrectionKernel,maximumLubricationCutOffDistance, &rpdDomain,&numContacts] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + acd.getContactThreshold() = maximumLubricationCutOffDistance; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + double_cast(acd.getIdx1(), acd.getIdx2(), ac, lubricationCorrectionKernel, ac, acd.getContactNormal(), acd.getPenetrationDepth()); + ++numContacts; // this then also includes all actual contacts since there the contact threshold is smaller + } + } + }, + *accessor ); + timeloopTiming["RPD Lub"].end(); + + // collision response + timeloopTiming["RPD Collision"].start(); + ps->forEachParticlePairHalf(useOpenMP, mesa_pd::kernel::ExcludeInfiniteInfinite(), *accessor, + [&collisionResponse, &rpdDomain, timeStepSizeRPD] + (const size_t idx1, const size_t idx2, auto& ac) + { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, ac, acd, ac )) + { + if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + { + collisionResponse(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), acd.getContactNormal(), acd.getPenetrationDepth(), timeStepSizeRPD); + } + } + }, + *accessor ); + + timeloopTiming["RPD Collision"].end(); + + reduceAndSwapContactHistory(*ps); + + timeloopTiming["RPD Force"].start(); + lbm_mesapd_coupling::AddHydrodynamicInteractionKernel addHydrodynamicInteraction; + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addHydrodynamicInteraction, *accessor ); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, addGravitationalForce, *accessor ); + timeloopTiming["RPD Force"].end(); + + reduceProperty.operator()<mesa_pd::ForceTorqueNotification>(*ps); + + // integration + timeloopTiming["RPD VV2"].start(); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectLocal(), *accessor, vvIntegratorPostForce, *accessor); + timeloopTiming["RPD VV2"].end(); + + syncCall(); + + + } + + timeloopTiming["RPD Force"].start(); + ps->forEachParticle( useOpenMP, mesa_pd::kernel::SelectAll(), *accessor, resetHydrodynamicForceTorque, *accessor ); + timeloopTiming["RPD Force"].end(); + + + // update particle mapping + timeloopAfterParticles.singleStep(timeloopTiming); + + //WALBERLA_LOG_INFO_ON_ROOT(timeloopTiming); + + // check if current time step should be included in sample + if( i >= uint_c( samplingFrequency * real_c(nSample) ) + timeStepOfFirstTiming ) + { + // include -> evaluate all timers and quantities + + evaluateFluidQuantities<BoundaryHandling_T>(blocks, boundaryHandlingID, numCells, numFluidCells, numNBCells); + evaluateRPDQuantities(ps, numLocalParticles, numGhostParticles); + + evaluateTimers(timeloopTiming, timerKeys, timings); + + if(!noFileOutput) + { + auto totalTime = std::accumulate(timings.begin(), timings.end(), 0.0 ); + + file << timeloop.getCurrentTimeStep() << " " << real_c(timeloop.getCurrentTimeStep()) / Tref << " " + << numCells << " " << numFluidCells << " " << numNBCells << " " + << numLocalParticles << " " << numGhostParticles << " " + << real_c(numContacts) / real_c(numRPDSubCycles) << " " << numRPDSubCycles; + for (auto timing : timings) { + file << " " << timing; + } + file << " " << totalTime << "\n"; + } + + ++nSample; + } + + numCells = uint_t(0); + numFluidCells = uint_t(0); + numNBCells = uint_t(0); + numLocalParticles = uint_t(0); + numGhostParticles = uint_t(0); + numContacts = uint_t(0); + + // reset timers to always include only a single time step in them + timeloopTiming.clear(); + } + + if(!noFileOutput) { + file.close(); + } + + WALBERLA_LOG_INFO_ON_ROOT("Simulation finished!"); + + return 0; + +} + +} + +int main( int argc, char **argv ){ + fluid_particle_workload_evaluation::main(argc, argv); +} diff --git a/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/Utility.h b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/Utility.h new file mode 100644 index 000000000..f9e4c05f1 --- /dev/null +++ b/apps/benchmarks/FluidParticleCouplingWithLoadBalancing/Utility.h @@ -0,0 +1,67 @@ +#pragma once + +#include "lbm_mesapd_coupling/amr/BlockInfo.h" + +namespace walberla { +namespace lbm_mesapd_coupling { +namespace amr { + +/* + * Result from the workload evaluation as described in + * Rettinger, Ruede - "Dynamic Load Balancing Techniques for Particulate Flow Simulations", 2019, Computation + */ +real_t fittedLBMWeightEvaluationFunction(const BlockInfo& blockInfo) +{ + uint_t Ce = blockInfo.numberOfCells; + uint_t F = blockInfo.numberOfFluidCells; + real_t weight = real_t(7.597476065046571e-06) * real_c(Ce) + real_t(8.95723566283202e-05) * real_c(F) + real_t(-0.1526111388616016); + return std::max(weight,real_t(0)); +} +real_t fittedBHWeightEvaluationFunction(const BlockInfo& blockInfo) +{ + uint_t Ce = blockInfo.numberOfCells; + uint_t NB = blockInfo.numberOfNearBoundaryCells; + real_t weight = real_t(1.3067711379655123e-07) * real_c(Ce) + real_t(0.0007289549127205142) * real_c(NB) + real_t(-0.1575698071795788); + return std::max(weight,real_t(0)); +} +real_t fittedRPDWeightEvaluationFunction(const BlockInfo& blockInfo) +{ + uint_t Pl = blockInfo.numberOfLocalParticles; + uint_t Pg = blockInfo.numberOfGhostParticles; + uint_t Sc = blockInfo.numberOfRPDSubCycles; + real_t cPlPg2 = real_t(2.402288635599054e-05); + real_t cPl = real_t(0.00040932622363097144); + real_t cPg = real_t(0.0007268941363125683); + real_t c = real_t(2.01883028312316e-19); + real_t weight = real_c(Sc) * ( cPlPg2 * real_c(Pl+Pg) * real_c(Pl+Pg) + cPl * real_c(Pl) + cPg * real_c(Pg) + c ); + return std::max(weight,real_t(0)); +} +real_t fittedCoup1WeightEvaluationFunction(const BlockInfo& blockInfo) +{ + uint_t Ce = blockInfo.numberOfCells; + uint_t F = blockInfo.numberOfFluidCells; + uint_t Pl = blockInfo.numberOfLocalParticles; + uint_t Pg = blockInfo.numberOfGhostParticles; + real_t weight = real_t(5.610203409278647e-06) * real_c(Ce) + real_t(-7.257635845636656e-07) * real_c(F) + real_t(0.02049703546054693) * real_c(Pl) + real_t(0.04248208493809902) * real_c(Pg) + real_t(-0.26609470510074784); + return std::max(weight,real_t(0)); +} +real_t fittedCoup2WeightEvaluationFunction(const BlockInfo& blockInfo) +{ + uint_t Ce = blockInfo.numberOfCells; + uint_t F = blockInfo.numberOfFluidCells; + uint_t Pl = blockInfo.numberOfLocalParticles; + uint_t Pg = blockInfo.numberOfGhostParticles; + real_t weight = real_t(7.198479654682179e-06) * real_c(Ce) + real_t(1.178247475854302e-06) * real_c(F) + real_t(-0.0026401549115124628) * real_c(Pl) + real_t(0.008459646786179298) * real_c(Pg) + real_t(-0.001077320113275954); + return std::max(weight,real_t(0)); +} +real_t fittedTotalWeightEvaluationFunction(const BlockInfo& blockInfo) +{ + return fittedLBMWeightEvaluationFunction(blockInfo) + fittedBHWeightEvaluationFunction(blockInfo) + + fittedRPDWeightEvaluationFunction(blockInfo) + fittedCoup1WeightEvaluationFunction(blockInfo) + + fittedCoup2WeightEvaluationFunction(blockInfo); +} + +} //namespace amr +} //namespace lbm_mesapd_coupling +} //namespace walberla + diff --git a/src/lbm_mesapd_coupling/amr/BlockInfo.h b/src/lbm_mesapd_coupling/amr/BlockInfo.h index 6b3e0706a..f36b491fb 100644 --- a/src/lbm_mesapd_coupling/amr/BlockInfo.h +++ b/src/lbm_mesapd_coupling/amr/BlockInfo.h @@ -28,28 +28,27 @@ namespace walberla { namespace lbm_mesapd_coupling { +namespace amr { struct BlockInfo { // lbm quantities uint_t numberOfCells; uint_t numberOfFluidCells; uint_t numberOfNearBoundaryCells; - // pe quantities + // rpd quantities uint_t numberOfLocalParticles; - uint_t numberOfShadowParticles; - uint_t numberOfContacts; + uint_t numberOfGhostParticles; // coupling quantities - uint_t numberOfMESAPDSubCycles; + uint_t numberOfRPDSubCycles; BlockInfo() : numberOfCells(0), numberOfFluidCells(0), numberOfNearBoundaryCells(0), - numberOfLocalParticles(0), numberOfShadowParticles(0), numberOfContacts(0), numberOfMESAPDSubCycles(0) {} + numberOfLocalParticles(0), numberOfGhostParticles(0), numberOfRPDSubCycles(0) {} BlockInfo(const uint_t numCells, const uint_t numFluidCells, const uint_t numNearBoundaryCells, - const uint_t numLocalBodies, const uint_t numShadowParticles, const uint_t numContacts, - const uint_t numPeSubCycles) + const uint_t numLocalParticles, const uint_t numGhostParticles, const uint_t numRPDSubCycles) : numberOfCells(numCells), numberOfFluidCells(numFluidCells), numberOfNearBoundaryCells(numNearBoundaryCells), - numberOfLocalParticles(numLocalBodies), numberOfShadowParticles(numShadowParticles), numberOfContacts(numContacts), numberOfMESAPDSubCycles(numPeSubCycles) {} + numberOfLocalParticles(numLocalParticles), numberOfGhostParticles(numGhostParticles), numberOfRPDSubCycles(numRPDSubCycles) {} }; @@ -57,19 +56,17 @@ inline std::ostream& operator<<( std::ostream& os, const BlockInfo& bi ) { os << bi.numberOfCells << " / " << bi.numberOfFluidCells << " / " << bi.numberOfNearBoundaryCells << " / " - << bi.numberOfLocalParticles << " / "<< bi.numberOfShadowParticles << " / " << bi.numberOfContacts << " / " - << bi.numberOfMESAPDSubCycles; + << bi.numberOfLocalParticles << " / "<< bi.numberOfGhostParticles << " / " << bi.numberOfRPDSubCycles; return os; } template< typename T, // Element type of SendBuffer - typename G> // Growth policy of SendBuffer + typename G> // Growth policy of SendBuffer mpi::GenericSendBuffer<T,G>& operator<<( mpi::GenericSendBuffer<T,G> & buf, const BlockInfo& info ) { buf.addDebugMarker( "pca" ); buf << info.numberOfCells << info.numberOfFluidCells << info.numberOfNearBoundaryCells - << info.numberOfLocalParticles << info.numberOfShadowParticles << info.numberOfContacts - << info.numberOfMESAPDSubCycles; + << info.numberOfLocalParticles << info.numberOfGhostParticles << info.numberOfRPDSubCycles; return buf; } @@ -78,10 +75,10 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, BlockInf { buf.readDebugMarker( "pca" ); buf >> info.numberOfCells >> info.numberOfFluidCells >> info.numberOfNearBoundaryCells - >> info.numberOfLocalParticles >> info.numberOfShadowParticles >> info.numberOfContacts - >> info.numberOfMESAPDSubCycles; + >> info.numberOfLocalParticles >> info.numberOfGhostParticles >> info.numberOfRPDSubCycles; return buf; } +} // namespace amr } // namespace lbm_mesapd_coupling } // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/InfoCollection.h b/src/lbm_mesapd_coupling/amr/InfoCollection.h index 13f8682d5..f3e596eb7 100644 --- a/src/lbm_mesapd_coupling/amr/InfoCollection.h +++ b/src/lbm_mesapd_coupling/amr/InfoCollection.h @@ -26,20 +26,21 @@ #include "blockforest/BlockID.h" #include "core/mpi/BufferSystem.h" -#include <mesa_pd/data/ParticleStorage.h> +#include "mesa_pd/data/Flags.h" #include <map> namespace walberla { namespace lbm_mesapd_coupling { +namespace amr { -typedef std::map<blockforest::BlockID, BlockInfo> InfoCollection; -typedef std::pair<blockforest::BlockID, BlockInfo> InfoCollectionPair; +using InfoCollection = std::map<blockforest::BlockID, BlockInfo> ; +using InfoCollectionPair = std::pair<blockforest::BlockID, BlockInfo>; template <typename BoundaryHandling_T, typename ParticleAccessor_T> -void createWithNeighborhood(BlockForest& bf, const BlockDataID boundaryHandlingID, - const ParticleAccessor_T& accessor, const uint_t numberOfMESAPDSubCycles, - InfoCollection& ic ) { +void updateAndSyncInfoCollection(BlockForest& bf, const BlockDataID boundaryHandlingID, + const ParticleAccessor_T& accessor, const uint_t numberOfRPDSubCycles, + InfoCollection& ic ) { ic.clear(); mpi::BufferSystem bs( MPIManager::instance()->comm(), 856 ); @@ -66,22 +67,21 @@ void createWithNeighborhood(BlockForest& bf, const BlockDataID boundaryHandlingI } // evaluate MESAPD quantities - // count block local and (possible) shadow particles here - uint_t numLocalParticles = 0, numShadowParticles = 0; + // count block local and (possible) ghost particles here + uint_t numLocalParticles = 0, numGhostParticles = 0; for (size_t idx = 0; idx < accessor.size(); ++idx) { - if (block->getAABB().contains(accessor.getPosition(idx))) { - // a particle within a block on the current process cannot be a ghost particle - WALBERLA_ASSERT(!mesa_pd::data::particle_flags::isSet(accessor.getFlags(idx), mesa_pd::data::particle_flags::GHOST)); + + using namespace walberla::mesa_pd::data::particle_flags; + if( isSet(accessor.getFlags(idx), GLOBAL) ) continue; + + if ( block->getAABB().contains(accessor.getPosition(idx)) ) { numLocalParticles++; } else if (block->getAABB().sqDistance(accessor.getPosition(idx)) < accessor.getInteractionRadius(idx)*accessor.getInteractionRadius(idx)) { - numShadowParticles++; + numGhostParticles++; } } - // count contacts here - const uint_t numContacts = 0; - - BlockInfo blockInfo(numCells, numFluidCells, numNearBoundaryCells, numLocalParticles, numShadowParticles, numContacts, numberOfMESAPDSubCycles); + BlockInfo blockInfo(numCells, numFluidCells, numNearBoundaryCells, numLocalParticles, numGhostParticles, numberOfRPDSubCycles); InfoCollectionPair infoCollectionEntry(block->getId(), blockInfo); ic.insert( infoCollectionEntry ); @@ -102,6 +102,8 @@ void createWithNeighborhood(BlockForest& bf, const BlockDataID boundaryHandlingI bs.setReceiverInfoFromSendBufferState(false, true); bs.sendAll(); + // info collection has to be distirbuted to neighboring processes such that later on when coarsening was applied, + // the weight of the coarsened block can be computed for( auto recvIt = bs.begin(); recvIt != bs.end(); ++recvIt ) { while( !recvIt.buffer().isEmpty() ) @@ -132,7 +134,6 @@ void getBlockInfoFromInfoCollection( const PhantomBlock * block, const shared_pt // check the above mentioned assumptions WALBERLA_ASSERT_EQUAL(infoIt->second.numberOfLocalParticles, uint_t(0)); - WALBERLA_ASSERT_EQUAL(infoIt->second.numberOfContacts, uint_t(0)); blockInfo = infoIt->second; } @@ -168,18 +169,40 @@ void getBlockInfoFromInfoCollection( const PhantomBlock * block, const shared_pt // check above mentioned assumptions WALBERLA_ASSERT_EQUAL(childIt->second.numberOfLocalParticles, uint_t(0)); - WALBERLA_ASSERT_EQUAL(childIt->second.numberOfContacts, uint_t(0)); } // total number of cells remains unchanged combinedInfo.numberOfFluidCells = uint_c(numFluidCells / uint_t(8)); //average combinedInfo.numberOfNearBoundaryCells = uint_c( numNearBoundaryCells / uint_t(8) ); //average combinedInfo.numberOfLocalParticles = uint_t(0); - combinedInfo.numberOfContacts = uint_t(0); //sum - // number of pe sub cycles stays the same + // number of rpd sub cycles stays the same blockInfo = combinedInfo; } } +/* + * Provides mapping from phantom block to weight evaluation via info collection + */ +class WeightEvaluationFunctor +{ +public: + WeightEvaluationFunctor(const shared_ptr<InfoCollection>& ic, + const std::function<real_t(const BlockInfo&)> & weightEvaluationFct) : + ic_(ic), weightEvaluationFct_(weightEvaluationFct) {} + + real_t operator()(const PhantomBlock * block) + { + BlockInfo blockInfo; + getBlockInfoFromInfoCollection(block, ic_, blockInfo); + return weightEvaluationFct_(blockInfo); + } + +private: + shared_ptr<InfoCollection> ic_; + std::function<real_t(const BlockInfo&)> weightEvaluationFct_; +}; + + +} // namepace amr } // namespace lbm_mesapd_coupling } // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.cpp b/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.cpp new file mode 100644 index 000000000..5c33cb777 --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.cpp @@ -0,0 +1,97 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file MetisAssignmentFunctor.cpp +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#include "MetisAssignmentFunctor.h" + +namespace walberla { +namespace lbm_mesapd_coupling { +namespace amr { + +void MetisAssignmentFunctor::operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, + const PhantomBlockForest & /*phantomBlockForest*/) +{ + for (auto &it : blockData) { + const PhantomBlock * block = it.first; + //only change of one level is supported! + WALBERLA_ASSERT_LESS( std::abs(int_c(block->getLevel()) - int_c(block->getSourceLevel())), 2 ); + + std::vector<int64_t> metisVertexWeights(weightEvaluationFctVector_.size()); + + for( auto con = uint_t(0); con < weightEvaluationFctVector_.size(); ++con ) + { + real_t vertexWeight = std::max(weightEvaluationFctVector_[con](block), blockBaseWeight_); + + int64_t metisVertexWeight = int64_c( weightMultiplicator_ * vertexWeight ); + + WALBERLA_ASSERT_GREATER(metisVertexWeight, int64_t(0)); + metisVertexWeights[con] = metisVertexWeight; + } + + blockforest::DynamicParMetisBlockInfo info( metisVertexWeights ); + + info.setVertexCoords(it.first->getAABB().center() ); + + real_t blockVolume = it.first->getAABB().volume(); + real_t approximateEdgeLength = std::cbrt( blockVolume ); + + int64_t faceNeighborWeight = int64_c(approximateEdgeLength * approximateEdgeLength ); //common face + int64_t edgeNeighborWeight = int64_c( approximateEdgeLength ); //common edge + int64_t cornerNeighborWeight = int64_c( 1 ); //common corner + + int64_t vertexSize = int64_c(blockVolume); + WALBERLA_ASSERT_GREATER(vertexSize, int64_t(0)); + info.setVertexSize( vertexSize ); + + for( const uint_t idx : blockforest::getFaceNeighborhoodSectionIndices() ) + { + for( auto nb = uint_t(0); nb < it.first->getNeighborhoodSectionSize(idx); ++nb ) + { + auto neighborBlockID = it.first->getNeighborId(idx,nb); + info.setEdgeWeight(neighborBlockID, faceNeighborWeight ); + } + } + + for( const uint_t idx : blockforest::getEdgeNeighborhoodSectionIndices() ) + { + for( auto nb = uint_t(0); nb < it.first->getNeighborhoodSectionSize(idx); ++nb ) + { + auto neighborBlockID = it.first->getNeighborId(idx,nb); + info.setEdgeWeight(neighborBlockID, edgeNeighborWeight ); + } + } + + for( const uint_t idx : blockforest::getCornerNeighborhoodSectionIndices() ) + { + for( auto nb = uint_t(0); nb < it.first->getNeighborhoodSectionSize(idx); ++nb ) + { + auto neighborBlockID = it.first->getNeighborId(idx,nb); + info.setEdgeWeight(neighborBlockID, cornerNeighborWeight ); + } + } + + it.second = info; + + } +} + + +} // namespace amr +} // namespace lbm_mesapd_coupling +} // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.h b/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.h new file mode 100644 index 000000000..962a6c975 --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/weight_assignment/MetisAssignmentFunctor.h @@ -0,0 +1,66 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file MetisAssignmentFunctor.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "blockforest/PhantomBlockForest.h" +#include "blockforest/PhantomBlock.h" +#include "blockforest/loadbalancing/DynamicParMetis.h" + +#include <functional> +#include <vector> + +namespace walberla { +namespace lbm_mesapd_coupling { +namespace amr { + +class MetisAssignmentFunctor +{ +public: + + using WeightEvaluationFct = std::function<real_t(const PhantomBlock *)>; + + explicit MetisAssignmentFunctor( const WeightEvaluationFct& weightEvaluationFct) + : weightEvaluationFctVector_(1, weightEvaluationFct) {} + + explicit MetisAssignmentFunctor( const std::vector< WeightEvaluationFct > & weightEvaluationFctVector ) + : weightEvaluationFctVector_(weightEvaluationFctVector) {} + + void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & phantomBlockForest); + + uint_t getNumberOfConstrains() const { return weightEvaluationFctVector_.size(); } + + inline void setBlockBaseWeight( const real_t blockBaseWeight ){ blockBaseWeight_ = blockBaseWeight; } + inline real_t getBlockBaseWeight() const { return blockBaseWeight_; } + + inline void setWeightMultiplicator( const real_t weightMultiplicator ){ weightMultiplicator_ = weightMultiplicator; } + +private: + std::vector< WeightEvaluationFct > weightEvaluationFctVector_; + real_t blockBaseWeight_ = real_t(1); + real_t weightMultiplicator_ = real_t(1); +}; + + + +} // namespace amr +} // namespace lbm_mesapd_coupling +} // namespace walberla + diff --git a/src/lbm_mesapd_coupling/amr/weight_assignment/WeightAssignmentFunctor.h b/src/lbm_mesapd_coupling/amr/weight_assignment/WeightAssignmentFunctor.h new file mode 100644 index 000000000..0113d045a --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/weight_assignment/WeightAssignmentFunctor.h @@ -0,0 +1,67 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WeightAssignmentFunctor.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "blockforest/loadbalancing/PODPhantomData.h" +#include "blockforest/PhantomBlockForest.h" +#include "blockforest/PhantomBlock.h" + +#include <functional> + +namespace walberla { +namespace lbm_mesapd_coupling { +namespace amr { + + + +class WeightAssignmentFunctor +{ +public: + using PhantomBlockWeight = walberla::blockforest::PODPhantomWeight<double>; + using WeightEvaluationFct = std::function<real_t(const PhantomBlock *)>; + + explicit WeightAssignmentFunctor( const WeightEvaluationFct & weightEvaluationFct ) : + weightEvaluationFct_(weightEvaluationFct) {} + + void operator()( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, const PhantomBlockForest & ) + { + for (auto &it : blockData) { + const PhantomBlock * block = it.first; + //only change of one level is supported! + WALBERLA_ASSERT_LESS( std::abs(int_c(block->getLevel()) - int_c(block->getSourceLevel())), 2 ); + + real_t blockWeight = std::max(weightEvaluationFct_(block), blockBaseWeight_); + it.second = PhantomBlockWeight( double_c( blockWeight ) ); + } + } + + inline void setBlockBaseWeight( const real_t blockBaseWeight ) { blockBaseWeight_ = blockBaseWeight; } + inline real_t getBlockBaseWeight() const { return blockBaseWeight_; } + +private: + WeightEvaluationFct weightEvaluationFct_; + real_t blockBaseWeight_ = real_t(1); +}; + + +} // namespace amr +} // namespace lbm_mesapd_coupling +} // namespace walberla diff --git a/src/lbm_mesapd_coupling/amr/weight_assignment/WeightEvaluationFunctions.h b/src/lbm_mesapd_coupling/amr/weight_assignment/WeightEvaluationFunctions.h new file mode 100644 index 000000000..6219f4f43 --- /dev/null +++ b/src/lbm_mesapd_coupling/amr/weight_assignment/WeightEvaluationFunctions.h @@ -0,0 +1,36 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file WeightEvaluationFunctions.h +//! \author Christoph Rettinger <christoph.rettinger@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include "blockforest/PhantomBlock.h" + +namespace walberla { +namespace lbm_mesapd_coupling { +namespace amr { + +real_t defaultWeightEvaluationFunction(const PhantomBlock * /*block*/) +{ + return real_t(1); +} + +} // namespace amr +} // namespace lbm_mesapd_coupling +} // namespace walberla -- GitLab From f436f6619f41d8631ca6224672104ea5c177b660 Mon Sep 17 00:00:00 2001 From: Michael Kuron <mkuron@icp.uni-stuttgart.de> Date: Fri, 26 Feb 2021 14:06:25 +0000 Subject: [PATCH 76/83] add headers to SweepInnerOuter template --- python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp b/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp index 6aec87cac..9f032a9ed 100644 --- a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp +++ b/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp @@ -23,6 +23,9 @@ #include "core/DataTypes.h" #include "core/Macros.h" #include "{{class_name}}.h" +{% for header in headers %} +#include {{header}} +{% endfor %} {% if target is equalto 'cpu' -%} -- GitLab From 2ebe093267410224b0c719574eee1521456f80af Mon Sep 17 00:00:00 2001 From: Markus Holzer <markus.holzer@fau.de> Date: Wed, 3 Mar 2021 08:50:45 +0000 Subject: [PATCH 77/83] Merge sweep generation --- python/pystencils_walberla/codegen.py | 43 ++--- .../templates/Sweep.tmpl.cpp | 63 ++++++++ .../templates/Sweep.tmpl.h | 30 +++- .../templates/SweepInnerOuter.tmpl.cpp | 149 ------------------ .../templates/SweepInnerOuter.tmpl.h | 113 ------------- 5 files changed, 107 insertions(+), 291 deletions(-) delete mode 100644 python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp delete mode 100644 python/pystencils_walberla/templates/SweepInnerOuter.tmpl.h diff --git a/python/pystencils_walberla/codegen.py b/python/pystencils_walberla/codegen.py index 896a795cc..44de5c3fb 100644 --- a/python/pystencils_walberla/codegen.py +++ b/python/pystencils_walberla/codegen.py @@ -73,33 +73,22 @@ def generate_sweep(generation_context, class_name, assignments, env = Environment(loader=PackageLoader('pystencils_walberla'), undefined=StrictUndefined) add_pystencils_filters_to_jinja_env(env) - if inner_outer_split is False: - jinja_context = { - 'kernel': KernelInfo(ast, temporary_fields, field_swaps, varying_parameters), - 'namespace': namespace, - 'class_name': class_name, - 'target': create_kernel_params.get("target", "cpu"), - 'headers': get_headers(ast), - 'ghost_layers_to_include': ghost_layers_to_include - } - header = env.get_template("Sweep.tmpl.h").render(**jinja_context) - source = env.get_template("Sweep.tmpl.cpp").render(**jinja_context) - else: - main_kernel_info = KernelInfo(ast, temporary_fields, field_swaps, varying_parameters) - representative_field = {p.field_name for p in main_kernel_info.parameters if p.is_field_parameter} - representative_field = sorted(representative_field)[0] - - jinja_context = { - 'kernel': main_kernel_info, - 'namespace': namespace, - 'class_name': class_name, - 'target': create_kernel_params.get("target", "cpu"), - 'field': representative_field, - 'headers': get_headers(ast), - 'ghost_layers_to_include': 0 - } - header = env.get_template("SweepInnerOuter.tmpl.h").render(**jinja_context) - source = env.get_template("SweepInnerOuter.tmpl.cpp").render(**jinja_context) + main_kernel_info = KernelInfo(ast, temporary_fields, field_swaps, varying_parameters) + representative_field = {p.field_name for p in main_kernel_info.parameters if p.is_field_parameter} + representative_field = sorted(representative_field)[0] + + jinja_context = { + 'kernel': main_kernel_info, + 'namespace': namespace, + 'class_name': class_name, + 'target': create_kernel_params.get("target", "cpu"), + 'field': representative_field, + 'headers': get_headers(ast), + 'ghost_layers_to_include': ghost_layers_to_include, + 'inner_outer_split': inner_outer_split + } + header = env.get_template("Sweep.tmpl.h").render(**jinja_context) + source = env.get_template("Sweep.tmpl.cpp").render(**jinja_context) source_extension = "cpp" if create_kernel_params.get("target", "cpu") == "cpu" else "cu" generation_context.write_file("{}.h".format(class_name), header) diff --git a/python/pystencils_walberla/templates/Sweep.tmpl.cpp b/python/pystencils_walberla/templates/Sweep.tmpl.cpp index b26d9c6db..9711be8cd 100644 --- a/python/pystencils_walberla/templates/Sweep.tmpl.cpp +++ b/python/pystencils_walberla/templates/Sweep.tmpl.cpp @@ -83,6 +83,69 @@ void {{class_name}}::runOnCellInterval( const shared_ptr<StructuredBlockStorage> {{kernel|generate_swaps|indent(4)}} } +{%if inner_outer_split%} +void {{class_name}}::inner( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream{% endif %} ) +{ + {{kernel|generate_block_data_to_field_extraction|indent(4)}} + + CellInterval inner = {{field}}->xyzSize(); + inner.expand(Cell(-outerWidth_[0], -outerWidth_[1], -outerWidth_[2])); + + {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} + {{kernel|generate_call(stream='stream', cell_interval='inner')|indent(4)}} +} + + +void {{class_name}}::outer( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream {% endif %} ) +{ + {{kernel|generate_block_data_to_field_extraction|indent(4)}} + + if( layers_.size() == 0 ) + { + CellInterval ci; + + {{field}}->getSliceBeforeGhostLayer(stencil::T, ci, outerWidth_[2], false); + layers_.push_back(ci); + {{field}}->getSliceBeforeGhostLayer(stencil::B, ci, outerWidth_[2], false); + layers_.push_back(ci); + + {{field}}->getSliceBeforeGhostLayer(stencil::N, ci, outerWidth_[1], false); + ci.expand(Cell(0, 0, -outerWidth_[2])); + layers_.push_back(ci); + {{field}}->getSliceBeforeGhostLayer(stencil::S, ci, outerWidth_[1], false); + ci.expand(Cell(0, 0, -outerWidth_[2])); + layers_.push_back(ci); + + {{field}}->getSliceBeforeGhostLayer(stencil::E, ci, outerWidth_[0], false); + ci.expand(Cell(0, -outerWidth_[1], -outerWidth_[2])); + layers_.push_back(ci); + {{field}}->getSliceBeforeGhostLayer(stencil::W, ci, outerWidth_[0], false); + ci.expand(Cell(0, -outerWidth_[1], -outerWidth_[2])); + layers_.push_back(ci); + } + + {%if target is equalto 'gpu'%} + { + auto parallelSection_ = parallelStreams_.parallelSection( stream ); + for( auto & ci: layers_ ) + { + parallelSection_.run([&]( auto s ) { + {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} + {{kernel|generate_call(stream='s', cell_interval='ci')|indent(16)}} + }); + } + } + {% else %} + for( auto & ci: layers_ ) + { + {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(8) }} + {{kernel|generate_call(cell_interval='ci')|indent(8)}} + } + {% endif %} + + {{kernel|generate_swaps|indent(4)}} +} +{% endif %} } // namespace {{namespace}} } // namespace walberla diff --git a/python/pystencils_walberla/templates/Sweep.tmpl.h b/python/pystencils_walberla/templates/Sweep.tmpl.h index b4db0f35b..9f0711a1e 100644 --- a/python/pystencils_walberla/templates/Sweep.tmpl.h +++ b/python/pystencils_walberla/templates/Sweep.tmpl.h @@ -24,6 +24,9 @@ #include "field/GhostLayerField.h" {%- elif target is equalto 'gpu' -%} #include "cuda/GPUField.h" +{% if inner_outer_split -%} +#include "cuda/ParallelStreams.h" +{%- endif %} {%- endif %} #include "field/SwapableCompare.h" #include "domain_decomposition/BlockDataID.h" @@ -42,6 +45,7 @@ #if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wunused-parameter" +# pragma GCC diagnostic ignored "-Wreorder" #endif namespace walberla { @@ -51,8 +55,8 @@ namespace {{namespace}} { class {{class_name}} { public: - {{class_name}}( {{kernel|generate_constructor_parameters}}) - : {{ kernel|generate_constructor_initializer_list }} + {{class_name}}( {{kernel|generate_constructor_parameters}} {%if inner_outer_split%}, const Cell & outerWidth=Cell(1, 1, 1){% endif %}) + : {{ kernel|generate_constructor_initializer_list }}{%if inner_outer_split%}{% if kernel|generate_constructor_initializer_list|length %},{% endif %} outerWidth_(outerWidth){% endif %} {}; {{ kernel| generate_destructor(class_name) |indent(4) }} @@ -79,7 +83,29 @@ public: }; } +{% if inner_outer_split %} + + void inner( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %} ); + void outer( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %} ); + + void setOuterPriority(int priority ) { + {%if target is equalto 'gpu'%} + parallelStreams_.setStreamPriority(priority); + {%endif%} + } + {{kernel|generate_members|indent(4)}} + +private: + {%if target is equalto 'gpu'%} + cuda::ParallelStreams parallelStreams_; + {% endif %} + + Cell outerWidth_; + std::vector<CellInterval> layers_; + +{%- else -%} {{ kernel|generate_members|indent(4) }} +{% endif -%} }; diff --git a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp b/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp deleted file mode 100644 index 9f032a9ed..000000000 --- a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.cpp +++ /dev/null @@ -1,149 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \\file {{class_name}}.cpp -//! \\ingroup lbm -//! \\author lbmpy -//====================================================================================================================== - -#include <cmath> - -#include "core/DataTypes.h" -#include "core/Macros.h" -#include "{{class_name}}.h" -{% for header in headers %} -#include {{header}} -{% endfor %} - - -{% if target is equalto 'cpu' -%} -#define FUNC_PREFIX -{%- elif target is equalto 'gpu' -%} -#define FUNC_PREFIX __global__ -{%- endif %} - -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wfloat-equal" -# pragma GCC diagnostic ignored "-Wshadow" -# pragma GCC diagnostic ignored "-Wconversion" -#endif - -using namespace std; - -namespace walberla { -namespace {{namespace}} { - -{{kernel|generate_definition(target)}} - -void {{class_name}}::operator() ( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream{% endif %} ) -{ - {{kernel|generate_block_data_to_field_extraction|indent(4)}} - {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} - {{kernel|generate_call(stream='stream')|indent(4)}} - {{kernel|generate_swaps|indent(4)}} -} - - -void {{class_name}}::runOnCellInterval( const shared_ptr<StructuredBlockStorage> & blocks, - const CellInterval & globalCellInterval, - cell_idx_t ghostLayers, - IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream{% endif %} ) -{ - CellInterval ci = globalCellInterval; - CellInterval blockBB = blocks->getBlockCellBB( *block); - blockBB.expand( ghostLayers ); - ci.intersect( blockBB ); - blocks->transformGlobalToBlockLocalCellInterval( ci, *block ); - if( ci.empty() ) - return; - - {{kernel|generate_block_data_to_field_extraction|indent(4)}} - {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} - {{kernel|generate_call(stream='stream', cell_interval='ci')|indent(4)}} - {{kernel|generate_swaps|indent(4)}} -} - - -void {{class_name}}::inner( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream{% endif %} ) -{ - {{kernel|generate_block_data_to_field_extraction|indent(4)}} - - CellInterval inner = {{field}}->xyzSize(); - inner.expand(Cell(-outerWidth_[0], -outerWidth_[1], -outerWidth_[2])); - - {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} - {{kernel|generate_call(stream='stream', cell_interval='inner')|indent(4)}} -} - - -void {{class_name}}::outer( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream {% endif %} ) -{ - {{kernel|generate_block_data_to_field_extraction|indent(4)}} - - if( layers_.size() == 0 ) - { - CellInterval ci; - - {{field}}->getSliceBeforeGhostLayer(stencil::T, ci, outerWidth_[2], false); - layers_.push_back(ci); - {{field}}->getSliceBeforeGhostLayer(stencil::B, ci, outerWidth_[2], false); - layers_.push_back(ci); - - {{field}}->getSliceBeforeGhostLayer(stencil::N, ci, outerWidth_[1], false); - ci.expand(Cell(0, 0, -outerWidth_[2])); - layers_.push_back(ci); - {{field}}->getSliceBeforeGhostLayer(stencil::S, ci, outerWidth_[1], false); - ci.expand(Cell(0, 0, -outerWidth_[2])); - layers_.push_back(ci); - - {{field}}->getSliceBeforeGhostLayer(stencil::E, ci, outerWidth_[0], false); - ci.expand(Cell(0, -outerWidth_[1], -outerWidth_[2])); - layers_.push_back(ci); - {{field}}->getSliceBeforeGhostLayer(stencil::W, ci, outerWidth_[0], false); - ci.expand(Cell(0, -outerWidth_[1], -outerWidth_[2])); - layers_.push_back(ci); - } - - {%if target is equalto 'gpu'%} - { - auto parallelSection_ = parallelStreams_.parallelSection( stream ); - for( auto & ci: layers_ ) - { - parallelSection_.run([&]( auto s ) { - {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(4) }} - {{kernel|generate_call(stream='s', cell_interval='ci')|indent(16)}} - }); - } - } - {% else %} - for( auto & ci: layers_ ) - { - {{kernel|generate_refs_for_kernel_parameters(prefix='this->', ignore_fields=True)|indent(8) }} - {{kernel|generate_call(cell_interval='ci')|indent(8)}} - } - {% endif %} - - {{kernel|generate_swaps|indent(4)}} -} - - -} // namespace {{namespace}} -} // namespace walberla - - -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) -# pragma GCC diagnostic pop -#endif diff --git a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.h b/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.h deleted file mode 100644 index 6f6094d0e..000000000 --- a/python/pystencils_walberla/templates/SweepInnerOuter.tmpl.h +++ /dev/null @@ -1,113 +0,0 @@ -//====================================================================================================================== -// -// This file is part of waLBerla. waLBerla 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 3 of -// the License, or (at your option) any later version. -// -// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. -// -//! \\file {{class_name}}.h -//! \\author pystencils -//====================================================================================================================== - -#pragma once -#include "core/DataTypes.h" - -{% if target is equalto 'cpu' -%} -#include "field/GhostLayerField.h" -{%- elif target is equalto 'gpu' -%} -#include "cuda/GPUField.h" -#include "cuda/ParallelStreams.h" -{%- endif %} -#include "field/SwapableCompare.h" -#include "domain_decomposition/BlockDataID.h" -#include "domain_decomposition/IBlock.h" -#include "domain_decomposition/StructuredBlockStorage.h" -#include <set> - -#ifdef __GNUC__ -#define RESTRICT __restrict__ -#elif _MSC_VER -#define RESTRICT __restrict -#else -#define RESTRICT -#endif - -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Wunused-parameter" -# pragma GCC diagnostic ignored "-Wreorder" -#endif - -namespace walberla { -namespace {{namespace}} { - - -class {{class_name}} -{ -public: - {{class_name}}( {{kernel|generate_constructor_parameters}}, const Cell & outerWidth=Cell(1, 1, 1)) - : {{ kernel|generate_constructor_initializer_list }}{% if kernel|generate_constructor_initializer_list|length %},{% endif %} outerWidth_(outerWidth) - {}; - - {{ kernel| generate_destructor(class_name) |indent(4) }} - - - void operator() ( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %} ); - - void runOnCellInterval(const shared_ptr<StructuredBlockStorage> & blocks, - const CellInterval & globalCellInterval, cell_idx_t ghostLayers, IBlock * block - {%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %}); - - - - static std::function<void (IBlock*)> getSweep(const shared_ptr<{{class_name}}> & kernel) { - return [kernel](IBlock * b) { (*kernel)(b); }; - } - - static std::function<void (IBlock*{%if target is equalto 'gpu'%} , cudaStream_t {% endif %})> - getSweepOnCellInterval(const shared_ptr<{{class_name}}> & kernel, - const shared_ptr<StructuredBlockStorage> & blocks, - const CellInterval & globalCellInterval, - cell_idx_t ghostLayers=1 ) - { - return [kernel, blocks, globalCellInterval, ghostLayers] (IBlock * b{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %}) { - kernel->runOnCellInterval(blocks, globalCellInterval, ghostLayers, b{%if target is equalto 'gpu'%}, stream {% endif %}); - }; - } - - - void inner( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %} ); - void outer( IBlock * block{%if target is equalto 'gpu'%} , cudaStream_t stream = nullptr{% endif %} ); - - void setOuterPriority(int priority ) { - {%if target is equalto 'gpu'%} - parallelStreams_.setStreamPriority(priority); - {%endif%} - } - {{kernel|generate_members|indent(4)}} - -private: - {%if target is equalto 'gpu'%} - cuda::ParallelStreams parallelStreams_; - {% endif %} - - Cell outerWidth_; - std::vector<CellInterval> layers_; -}; - - -} // namespace {{namespace}} -} // namespace walberla - - -#if ( defined WALBERLA_CXX_COMPILER_IS_GNU ) || ( defined WALBERLA_CXX_COMPILER_IS_CLANG ) -# pragma GCC diagnostic pop -#endif -- GitLab From 8df3a2824bea6a0ce3b7762f2ddc98394725b6c7 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 15:07:44 +0100 Subject: [PATCH 78/83] [ADD] kernel for the VBondModel, integrated vdW contact --- src/mesa_pd/kernel/cnt/IntegratedVDWContact.h | 145 ++++++++++++++++++ src/mesa_pd/kernel/cnt/Parameters.h | 14 +- tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/cnt/IntegratedVDWContact.test.cpp | 135 ++++++++++++++++ 4 files changed, 290 insertions(+), 7 deletions(-) create mode 100644 src/mesa_pd/kernel/cnt/IntegratedVDWContact.h create mode 100644 tests/mesa_pd/kernel/cnt/IntegratedVDWContact.test.cpp diff --git a/src/mesa_pd/kernel/cnt/IntegratedVDWContact.h b/src/mesa_pd/kernel/cnt/IntegratedVDWContact.h new file mode 100644 index 000000000..844887f15 --- /dev/null +++ b/src/mesa_pd/kernel/cnt/IntegratedVDWContact.h @@ -0,0 +1,145 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace cnt { + +/** + * vdW Contact with integration + */ +class IntegratedVDWContact +{ +public: + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac); + + static constexpr real_t R_CNT = 6.78_r; ///< CNT radius + static constexpr real_t T = 2_r * R_CNT; ///< Height of a cylindrical segment + static constexpr real_t eps = 0.07124_r; + static constexpr real_t A = 0.0223_r; + static constexpr real_t B = 1.31_r; + static constexpr real_t alpha = 9.5_r; + static constexpr real_t beta = 4.0_r; + + // vdW adhesion + linear repulsion potential. + const real_t r0 = R_CNT * (2_r + std::pow((alpha * A / (beta * B)), 1_r / (alpha - beta))); + const real_t u0 = 4_r * eps * (A / std::pow(r0 / R_CNT - 2_r, (alpha)) - B / std::pow(r0 / R_CNT - 2_r, (beta))); + + auto getLastEnergy() const {return energy_;} +private: + real_t energy_; ///< total potential +}; + + +template<typename Accessor> +inline +void IntegratedVDWContact::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) +{ + constexpr real_t K_n = 200.0_r; // Good for fabrics modeling + + // particle centers + Vec3 O1 = ac.getPosition(p_idx1); + Vec3 O2 = ac.getPosition(p_idx2); + + // axial vectors + Vec3 b1 = ac.getRotation(p_idx1).getMatrix() * Vec3(1_r, 0_r, 0_r); + Vec3 b2 = ac.getRotation(p_idx2).getMatrix() * Vec3(1_r, 0_r, 0_r); + + energy_ = 0_r; + Vec3 force12(0); // Force 12 + Vec3 force21(0); // Force 21 + Vec3 moment12(0); // Total torque 12 + Vec3 moment21(0); // Total torque 21 + + constexpr int Np = 5; // Number of integration points over each axis + constexpr real_t Npinv = 1.0_r / real_t(Np); + for (int i = 0; i < Np; ++i) // integral dl1 + { + for (int j = 0; j < Np; ++j) // integral dl2 + { + // Levers + Vec3 l1 = (-0.5_r * T + (0.5_r + real_t(i)) * T * Npinv) * b1; + Vec3 l2 = (-0.5_r * T + (0.5_r + real_t(j)) * T * Npinv) * b2; + + /// radius vector between dl1 and dl2 + Vec3 R12 = (O2 + l2) - (O1 + l1); + + real_t r12 = R12.length(); + Vec3 n12 = R12 * (1_r / r12); + + real_t dU = 0_r; + Vec3 dforce12(0); + + if (r12 < r0) + { + // elastic interaction + dU = u0 + K_n * (r12 - r0) * (r12 - r0) * Npinv * Npinv; + dforce12 = n12 * K_n * (r12 - r0) * Npinv * Npinv; + } else + { + // vdW interaction + const real_t normDistance = r12 / R_CNT - 2_r; + const real_t powAlpha = std::pow(normDistance, alpha); + const real_t powBeta = std::pow(normDistance, beta); + dU = 4_r * eps * (A / powAlpha - B / powBeta) * Npinv * Npinv; + dforce12 = n12 * 4_r * eps / R_CNT * Npinv * Npinv * + (-(alpha * A) / (powAlpha * normDistance) + (beta * B) / (powBeta * normDistance)); + } + + Vec3 dmoment12 = l2 % dforce12; + Vec3 dmoment21 = l1 % (-dforce12); + + energy_ += dU; + force12 += dforce12; + force21 -= dforce12; + moment12 += dmoment12; + moment21 += dmoment21; + } + } + + addForceAtomic(p_idx1, ac, force12); + addForceAtomic(p_idx2, ac, force21); + addTorqueAtomic(p_idx1, ac, -moment21); + addTorqueAtomic(p_idx2, ac, -moment12); +} + +} //namespace cnt +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/src/mesa_pd/kernel/cnt/Parameters.h b/src/mesa_pd/kernel/cnt/Parameters.h index 63f256a04..c265088ba 100644 --- a/src/mesa_pd/kernel/cnt/Parameters.h +++ b/src/mesa_pd/kernel/cnt/Parameters.h @@ -79,11 +79,11 @@ constexpr auto M_C = 12.011_r; /// Mass of the repetative cell in AMU constexpr auto mass_T = ro * T * M_C * 104.397_r; -// Volume of a capsule -//double vol = (4./3.) * PII * (R_CNT * R_CNT * R_CNT) + PII * R_CNT * R_CNT * T; +/// Volume of a capsule +double vol_capsule = (4_r/3_r) * math::pi * (R_CNT * R_CNT * R_CNT) + math::pi * R_CNT * R_CNT * T; -// Density of a capsule -//double dens = mass_T / vol; +/// Density of a capsule +double dens_capsule = mass_T / vol_capsule; /// V-bond parameter constexpr auto knorm = (En * 0.006242_r) / T; @@ -97,12 +97,12 @@ constexpr auto outer_radius = CutoffFactor * R_CNT; constexpr auto inner_radius = 1.5811_r * R_CNT; // Sphere /// volume of a sphere -constexpr auto vol = (4_r/3_r) * math::pi * (inner_radius * inner_radius * inner_radius); +constexpr auto vol_sphere = (4_r/3_r) * math::pi * (inner_radius * inner_radius * inner_radius); /// density of a sphere -constexpr auto dens = mass_T / vol; +constexpr auto dens_sphere = mass_T / vol_sphere; } //namespace cnt } //namespace kernel } //namespace mesa_pd -} //namespace walberla \ No newline at end of file +} //namespace walberla diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 983cbca6e..4e7985268 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -84,6 +84,9 @@ waLBerla_execute_test( NAME MESA_PD_DropTestGeneral ) waLBerla_compile_test( NAME MESA_PD_Kernel_ClearNextNeighborSync FILES kernel/ClearNextNeighborSync.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_ClearNextNeighborSync PROCESSES 2 ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_IntegratedVDWContact FILES kernel/cnt/IntegratedVDWContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IntegratedVDWContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact FILES kernel/cnt/IsotropicVDWContact.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IsotropicVDWContact ) diff --git a/tests/mesa_pd/kernel/cnt/IntegratedVDWContact.test.cpp b/tests/mesa_pd/kernel/cnt/IntegratedVDWContact.test.cpp new file mode 100644 index 000000000..05bb96c98 --- /dev/null +++ b/tests/mesa_pd/kernel/cnt/IntegratedVDWContact.test.cpp @@ -0,0 +1,135 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "SphericalSegmentAccessor.h" + +#include "mesa_pd/data/Flags.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/cnt/IntegratedVDWContact.h" +#include "mesa_pd/kernel/cnt/ViscousDamping.h" +#include "mesa_pd/kernel/cnt/Parameters.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "core/Environment.h" +#include "core/math/Constants.h" +#include "vtk/VTKOutput.h" + +namespace walberla { +using namespace walberla::mesa_pd; + +int main(int argc, char **argv) +{ + Environment env(argc, argv); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<walberla::real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + logging::Logging::instance()->setStreamLogLevel(logging::Logging::INFO); + logging::Logging::instance()->setFileLogLevel(logging::Logging::INFO); + + WALBERLA_LOG_INFO_ON_ROOT("loading configuration parameters"); + constexpr auto numSimulationSteps = 20000ll; + constexpr auto outputInterval = 100ll; + + WALBERLA_LOG_INFO_ON_ROOT("creating initial particle setup"); + auto ps = std::make_shared<data::ParticleStorage>(10); + auto ac = SphericalSegmentAccessor(ps); + + using namespace kernel::cnt; + data::Particle &&sp1 = *ps->create(); + sp1.setPosition(Vec3(0_r, 0_r, 0_r)); + sp1.setSegmentID(1); + sp1.setClusterID(1); + + data::Particle &&sp2 = *ps->create(); + sp2.setPosition(Vec3(20_r, 20_r, 20_r)); + sp2.setSegmentID(2); + sp2.setClusterID(2); + + WALBERLA_LOG_INFO_ON_ROOT("setting up VTK output"); + auto vtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + vtkOutput->addOutput<data::SelectParticlePosition>("position"); + auto vtkWriter = walberla::vtk::createVTKOutput_PointData(vtkOutput, + "cnt", + 1, + "vtk_integrated", + "particles", + false, + false); + + WALBERLA_LOG_INFO_ON_ROOT("setting up interaction models"); + kernel::cnt::IntegratedVDWContact vdW_integrated; + kernel::cnt::ViscousDamping viscous_damping(0.1_r * 1052.0_r, 0.1_r * 1052.0_r); + kernel::VelocityVerletPreForceUpdate vv_pre(kernel::cnt::dT); + kernel::VelocityVerletPostForceUpdate vv_post(kernel::cnt::dT); + + WALBERLA_LOG_INFO_ON_ROOT("running simulation"); + + real_t U = 0_r; + for (auto i = 0; i < numSimulationSteps; ++i) + { + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_pre, + ac); + + U = 0_r; + ps->forEachParticlePairHalf(false, + kernel::SelectAll(), + ac, + [&](size_t p_idx1, size_t p_idx2) + { + vdW_integrated(p_idx1, p_idx2, ac); + U += vdW_integrated.getLastEnergy(); + viscous_damping(p_idx1, p_idx2, ac); + }); + + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_post, + ac); + + if( i % outputInterval == 0 ) + { +// vtkWriter->write(); +// WALBERLA_LOG_DEVEL(i << " : " << U); + } + } + + WALBERLA_CHECK_LESS(U, -8_r) + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main(int argc, char *argv[]) +{ + return walberla::main(argc, argv); +} -- GitLab From 7cb0420565de4814143bb3e348379fa7599ab96f Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Wed, 3 Mar 2021 10:00:26 +0100 Subject: [PATCH 79/83] enabled showcases in the pipeline --- .gitlab-ci.yml | 1 + .../CombinedResolvedUnresolved.cpp | 6 +++--- apps/showcases/HeatConduction/ContactDetection.h | 2 +- apps/showcases/Mixer/Mixer.cpp | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bb024cdc0..3ce52d224 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,6 +38,7 @@ stages: -DWALBERLA_BUILD_BENCHMARKS=ON -DWALBERLA_BUILD_TUTORIALS=ON -DWALBERLA_BUILD_TOOLS=ON + -DWALBERLA_BUILD_SHOWCASES=ON -DWALBERLA_BUILD_WITH_MPI=$WALBERLA_BUILD_WITH_MPI -DWALBERLA_BUILD_WITH_CUDA=$WALBERLA_BUILD_WITH_CUDA -DWALBERLA_BUILD_WITH_PYTHON=$WALBERLA_BUILD_WITH_PYTHON diff --git a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp index 5f4336e49..e8e27e9cf 100644 --- a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp +++ b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp @@ -543,7 +543,7 @@ int main(int argc, char** argv) // create pe bodies // bounding planes (global) - const auto planeMaterial = pe::createMaterial("planeMaterial", 1000.0, 0.8, 0.1, 0.05, 0.2, 80, 100, 10, 11); + const auto planeMaterial = pe::createMaterial("planeMaterial", 1000_r, 0.8_r, 0.1_r, 0.05_r, 0.2_r, 80_r, 100_r, 10_r, 11_r); pe::createPlane(*globalBodyStorage, 0, Vector3< real_t >(1, 0, 0), Vector3< real_t >(0, 0, 0), planeMaterial); pe::createPlane(*globalBodyStorage, 0, Vector3< real_t >(-1, 0, 0), Vector3< real_t >(real_c(domainSize[0]), 0, 0), planeMaterial); @@ -564,8 +564,8 @@ int main(int argc, char** argv) // add DPM spheres const auto peMaterial_DPM = createSphereMaterial("peMaterial_DPM", diameter_DPM, densityRatio_DPM); createSphereLattice(*blocks, *globalBodyStorage, bodyStorageID, - AABB(real_t(0), real_t(0), real_t(1.0 * real_t(domainSize[2]) / 8.0), real_t(domainSize[0]), - real_t(domainSize[1]), real_t(2.0 * real_t(domainSize[2]) / 8.0)), + AABB(real_t(0), real_t(0), real_t(1.0 * real_t(domainSize[2]) / 8.0_r), real_t(domainSize[0]), + real_t(domainSize[1]), real_t(2.0 * real_t(domainSize[2]) / 8.0_r)), diameter_DPM, real_t(0.15), peMaterial_DPM, real_t(0)); syncCall(); diff --git a/apps/showcases/HeatConduction/ContactDetection.h b/apps/showcases/HeatConduction/ContactDetection.h index c5ed90565..9c812ce47 100644 --- a/apps/showcases/HeatConduction/ContactDetection.h +++ b/apps/showcases/HeatConduction/ContactDetection.h @@ -83,7 +83,7 @@ inline bool ContactDetection::operator()( const size_t idx1, template <typename Accessor> inline bool ContactDetection::operator()( const size_t idx1, const size_t idx2, - const data::Sphere& s, + const data::Sphere& /*s*/, const data::HalfSpace& p, Accessor& ac ) { diff --git a/apps/showcases/Mixer/Mixer.cpp b/apps/showcases/Mixer/Mixer.cpp index 75016f8bd..034156452 100644 --- a/apps/showcases/Mixer/Mixer.cpp +++ b/apps/showcases/Mixer/Mixer.cpp @@ -261,7 +261,7 @@ int main( int argc, char ** argv ) Vec3 origin = simulationDomain.center(); Vec3 dp; - auto mixingBlade = ss->create<data::Box>( Vec3(0.009,simulationDomain.ySize(),simulationDomain.zSize()) ); + auto mixingBlade = ss->create<data::Box>( Vec3(0.009_r, simulationDomain.ySize(), simulationDomain.zSize()) ); ss->shapes[mixingBlade]->updateMassAndInertia(std::numeric_limits<real_t>::infinity()); auto box0 = ps->create(); box0->getPositionRef() = Vec3(simulationDomain.xSize() * real_t(0.5),0.0,0.0); @@ -316,10 +316,10 @@ int main( int argc, char ** argv ) data::particle_flags::set(box3->getFlagsRef(), data::particle_flags::INFINITE); data::particle_flags::set(box3->getFlagsRef(), data::particle_flags::FIXED); data::particle_flags::set(box3->getFlagsRef(), data::particle_flags::NON_COMMUNICATING); - box3->getRotationRef().rotate(Vec3(0,1,0), math::pi * 0.15 ); + box3->getRotationRef().rotate(Vec3(0,1,0), math::pi * 0.15_r ); // box3->getRotationRef().rotate(Vec3(0,0,1), -math::pi * 0.15 ); dp = ( box3->getPosition() - origin ); - dRot = Rot3(Vec3(real_t(0), real_t(0), math::pi * 1.5)); + dRot = Rot3(Vec3(real_t(0), real_t(0), math::pi * 1.5_r)); box3->setPosition( origin + dRot.getMatrix() * dp ); box3->getRotationRef().rotate(dRot); -- GitLab From b3c10dbf2de6cee8a91cb7e86347ced40a093dfd Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Mon, 8 Mar 2021 10:12:21 +0100 Subject: [PATCH 80/83] [CLANG-TIDY] modernize-use-using --- .../AMRSedimentSettling.cpp | 30 +++--- .../AMRSettlingSphere.cpp | 30 +++--- .../WorkloadEvaluation.cpp | 20 ++-- apps/benchmarks/CouetteFlow/CouetteFlow.cpp | 38 ++++---- apps/benchmarks/DEM/DEM.cpp | 2 +- .../ForcesOnSphereNearPlaneInShearFlow.cpp | 12 +-- .../MotionSingleHeavySphere.cpp | 22 ++--- .../NonUniformGrid/NonUniformGrid.cpp | 18 ++-- .../PoiseuilleChannel/PoiseuilleChannel.cpp | 20 ++-- .../SchaeferTurek/SchaeferTurek.cpp | 65 +++++++------ apps/benchmarks/UniformGrid/UniformGrid.cpp | 20 ++-- .../BidisperseFluidizedBedDPM.cpp | 54 +++++------ .../CombinedResolvedUnresolved.cpp | 70 +++++--------- apps/tutorials/basics/03_GameOfLife.cpp | 2 +- apps/tutorials/lbm/01_BasicLBM.cpp | 2 +- .../lbm/02_BasicLBM_ExemplaryExtensions.cpp | 6 +- apps/tutorials/lbm/03_LBLidDrivenCavity.cpp | 6 +- apps/tutorials/pde/01_SolvingPDE.cpp | 2 +- apps/tutorials/pde/02_HeatEquation.cpp | 2 +- .../pde/03_HeatEquation_Extensions.cpp | 2 +- apps/tutorials/pe/01_ConfinedGas.cpp | 2 +- apps/tutorials/pe/02_ConfinedGasExtended.cpp | 2 +- src/blockforest/Block.h | 2 +- src/blockforest/BlockDataHandling.h | 4 +- src/blockforest/BlockForest.h | 1 - src/blockforest/BlockID.h | 2 +- src/blockforest/GlobalLoadBalancing.h | 2 +- src/blockforest/PhantomBlock.h | 2 +- src/blockforest/PhantomBlockForest.h | 19 ++-- src/blockforest/SetupBlockForest.h | 17 ++-- src/blockforest/Types.h | 4 +- .../communication/NonUniformBufferedScheme.h | 10 +- .../communication/UniformBufferedScheme.h | 14 +-- .../communication/UniformDirectScheme.h | 6 +- src/blockforest/loadbalancing/DynamicCurve.h | 14 +-- .../loadbalancing/DynamicParMetis.h | 4 +- src/blockforest/loadbalancing/NoPhantomData.h | 2 +- .../loadbalancing/PODPhantomData.h | 2 +- .../loadbalancing/StaticParMetis.h | 4 +- src/boundary/BoundaryHandling.h | 10 +- src/boundary/BoundaryHandlingCollection.h | 10 +- src/boundary/BoundaryUID.h | 2 +- src/core/Abort.h | 2 +- src/core/AllSet.h | 2 +- src/core/DataTypes.h | 26 ++--- src/core/OpenMP.h | 20 ++-- src/core/Set.h | 6 +- src/core/VectorTrait.h | 4 +- src/core/cell/CellInterval.h | 12 +-- src/core/cell/CellVector.h | 14 +-- src/core/config/Config.h | 26 ++--- src/core/debug/CheckFunctions.impl.h | 40 ++++---- src/core/math/AABBFwd.h | 2 +- src/core/math/GenericAABB.h | 4 +- src/core/math/MathTrait.h | 16 ++-- src/core/math/Matrix2.h | 2 +- src/core/math/Matrix3.h | 2 +- src/core/math/MatrixMxN.h | 8 +- src/core/math/Plane.h | 2 +- src/core/math/Quaternion.h | 14 +-- src/core/math/SqrtTrait.h | 6 +- src/core/math/Uint.h | 10 +- src/core/math/Utility.h | 2 +- src/core/math/Vector2.h | 6 +- src/core/math/Vector3.h | 6 +- .../math/equation_system/EquationSystem.h | 16 ++-- src/core/math/equation_system/FwdEquation.h | 4 +- src/core/math/equation_system/FwdVariable.h | 6 +- src/core/mpi/BufferDataTypeExtensions.h | 4 +- src/core/mpi/BufferSystem.h | 4 +- src/core/mpi/MPIWrapper.h | 20 ++-- src/core/mpi/OpenMPBufferSystem.h | 2 +- src/core/mpi/RecvBuffer.h | 4 +- src/core/mpi/SendBuffer.h | 6 +- src/core/timing/Timer.h | 6 +- src/core/timing/TimingNode.h | 4 +- src/core/timing/TimingPool.h | 8 +- src/core/timing/TimingTree.h | 4 +- src/core/uid/SUID.h | 2 +- src/core/uid/UID.h | 2 +- src/core/uid/UIDGenerators.h | 16 ++-- src/domain_decomposition/BlockDataHandling.h | 6 +- src/domain_decomposition/BlockStorage.h | 2 +- src/domain_decomposition/IBlock.h | 2 +- src/domain_decomposition/IBlockID.h | 2 +- .../StructuredBlockStorage.h | 4 +- src/fft/Fft.h | 2 +- src/field/AccuracyEvaluation.h | 12 +-- src/field/AccuracyEvaluationLinePlot.h | 18 ++-- src/field/Field.h | 26 +++-- src/field/FlagField.h | 22 ++--- src/field/FlagField.impl.h | 4 +- src/field/FlagUID.h | 2 +- src/field/GhostLayerField.h | 23 ++--- src/field/MassEvaluation.h | 12 +-- src/field/StabilityChecker.h | 14 +-- src/field/VolumetricFlowRateEvaluation.h | 20 ++-- src/field/adaptors/AdaptorCreators.h | 4 +- src/field/adaptors/AdaptorIterator.h | 6 +- .../adaptors/ComponentExtractionAdaptor.h | 12 +-- src/field/adaptors/GhostLayerFieldAdaptor.h | 24 ++--- src/field/adaptors/VectorFieldAccessor.h | 4 +- src/field/blockforest/BlockDataHandling.h | 10 +- src/field/communication/MPIDatatypes.impl.h | 4 +- src/field/communication/PackInfo.h | 2 +- src/field/communication/ReducePackInfo.h | 2 +- .../UniformPullReductionPackInfo.h | 2 +- src/field/distributors/DistributorCreators.h | 4 +- src/field/distributors/KernelDistributor.h | 6 +- .../distributors/NearestNeighborDistributor.h | 6 +- .../interpolators/FieldInterpolatorCreators.h | 4 +- .../interpolators/KernelFieldInterpolator.h | 6 +- .../NearestNeighborFieldInterpolator.h | 6 +- .../NearestNeighborInterpolator.h | 2 +- .../TrilinearFieldInterpolator.h | 6 +- src/field/iterators/FieldIterator.h | 10 +- src/field/iterators/FieldIterator.impl.h | 2 +- src/field/iterators/FieldNeighborPointer.h | 2 +- src/field/iterators/FieldPointer.h | 2 +- src/field/vtk/FlagFieldCellFilter.h | 2 +- src/field/vtk/FlagFieldMapping.h | 4 +- src/field/vtk/VTKWriter.h | 8 +- src/gather/FileGatherScheme.h | 2 +- src/gather/MPIGatherScheme.h | 2 +- src/geometry/InitBoundaryHandling.h | 12 +-- src/geometry/containment_octree/BranchNode.h | 10 +- .../containment_octree/ContainmentOctree.h | 24 ++--- .../IndeterminateLeafNode.h | 10 +- .../containment_octree/InsideLeafNode.h | 10 +- src/geometry/containment_octree/LeafNode.h | 10 +- src/geometry/containment_octree/Node.h | 10 +- .../containment_octree/OutsideLeafNode.h | 10 +- src/geometry/initializer/BoundaryFromImage.h | 4 +- .../initializer/BoundaryFromVoxelFile.h | 4 +- .../initializer/InitializationManager.h | 2 +- .../initializer/ScalarFieldFromBody.h | 2 +- src/geometry/mesh/TriangleMesh.h | 8 +- src/geometry/structured/GrayScaleImage.h | 2 +- src/gui/Gui.h | 2 +- src/gui/PropertyTree.h | 2 +- src/lbm/MassEvaluation.h | 24 ++--- src/lbm/blockforest/PostProcessing.h | 12 +-- src/lbm/boundary/Curved.h | 8 +- src/lbm/boundary/DiffusionDirichlet.h | 6 +- src/lbm/boundary/DynamicUBB.h | 6 +- src/lbm/boundary/FreeDiffusion.h | 4 +- src/lbm/boundary/FreeSlip.h | 6 +- src/lbm/boundary/NoDiffusion.h | 2 +- src/lbm/boundary/NoSlip.h | 6 +- src/lbm/boundary/Outlet.h | 6 +- src/lbm/boundary/ParserUBB.h | 10 +- src/lbm/boundary/Pressure.h | 6 +- src/lbm/boundary/SimpleDiffusionDirichlet.h | 4 +- src/lbm/boundary/SimplePAB.h | 8 +- src/lbm/boundary/SimplePressure.h | 6 +- src/lbm/boundary/SimpleUBB.h | 6 +- src/lbm/boundary/SimpleVelocityBoundary.h | 4 +- src/lbm/boundary/UBB.h | 8 +- src/lbm/boundary/VelocityBoundary.h | 6 +- .../factories/DefaultBoundaryHandling.h | 20 ++-- .../DefaultBoundaryHandlingCollection.h | 6 +- .../DefaultDiffusionBoundaryHandling.h | 18 ++-- .../ExtendedBoundaryHandlingFactory.h | 26 ++--- src/lbm/evaluations/Permeability.h | 10 +- src/lbm/field/Adaptors.h | 58 +++++------ src/lbm/field/AddToStorage.h | 4 +- src/lbm/field/DensityAndMomentumDensity.h | 4 +- src/lbm/field/Equilibrium.h | 4 +- src/lbm/field/MomentumDensity.h | 4 +- src/lbm/field/PdfField.h | 22 ++--- src/lbm/field/ShearRate.h | 4 +- .../initializer/ExprSystemInitFunction.h | 6 +- .../field/initializer/PdfFieldInitializer.h | 2 +- .../initializer/PoiseuilleInitializer.h | 2 +- src/lbm/lattice_model/CollisionModel.h | 10 +- src/lbm/lattice_model/D2Q9.h | 8 +- src/lbm/lattice_model/D3Q15.h | 8 +- src/lbm/lattice_model/D3Q19.h | 8 +- src/lbm/lattice_model/D3Q27.h | 8 +- .../lattice_model/EquilibriumDistribution.h | 8 +- src/lbm/lattice_model/ForceModel.h | 38 ++++---- src/lbm/lattice_model/LatticeModelBase.h | 4 +- src/lbm/lattice_model/NeighborsStencil.h | 4 +- src/lbm/lattice_model/SmagorinskyLES.h | 6 +- .../refinement/CurlBasedLevelDetermination.h | 2 +- .../EqualLevelBorderStreamCorrection.h | 8 +- src/lbm/refinement/LinearExplosion.h | 8 +- src/lbm/refinement/PdfFieldPackInfo.h | 4 +- src/lbm/refinement/TimeStep.h | 12 +-- .../VorticityBasedLevelDetermination.h | 2 +- src/lbm/srt/SplitPureSweep.impl.h | 8 +- src/lbm/srt/SplitSweep.impl.h | 8 +- .../AdvectionDiffusionCellOperation.impl.h | 12 +-- .../DefaultCellOperation.impl.h | 16 ++-- src/lbm/sweeps/ActiveCellSweep.h | 2 +- src/lbm/sweeps/CellwiseSweep.h | 8 +- src/lbm/sweeps/FlagFieldSweepBase.h | 4 +- src/lbm/sweeps/StreamPull.h | 32 +++---- src/lbm/sweeps/Streaming.h | 16 ++-- src/lbm/sweeps/SweepBase.h | 2 +- src/lbm/trt/SplitPureSweep.impl.h | 8 +- src/lbm/trt/SplitSweep.impl.h | 8 +- .../DefaultCellOperation.impl.h | 12 +-- src/lbm/vtk/Density.h | 4 +- src/lbm/vtk/NonEquilibrium.h | 4 +- src/lbm/vtk/PressureTensor.h | 2 +- src/lbm/vtk/VTKOutput.h | 6 +- src/lbm/vtk/Velocity.h | 8 +- .../utility/SubCyclingManager.h | 6 +- src/mesa_pd/collision_detection/EPA.h | 6 +- src/pde/sweeps/SweepBase.h | 2 +- src/pe/Materials.h | 2 +- src/pe/Types.h | 96 +++++++++---------- .../MetisAssignmentFunctor.h | 4 +- .../WeightAssignmentFunctor.h | 4 +- src/pe/ccd/HashGrids.h | 8 +- src/pe/collision/EPA.h | 6 +- src/pe/cr/HCSITS.h | 2 +- src/pe/rigidbody/MPIRigidBodyTrait.h | 10 +- src/pe_coupling/amr/InfoCollection.h | 4 +- .../WeightAssignmentFunctor.h | 2 +- .../evaluators/AddedMassForceEvaluator.h | 6 +- .../EffectiveViscosityFieldEvaluator.h | 2 +- .../evaluators/InteractionForceEvaluator.h | 10 +- .../evaluators/LiftForceEvaluator.h | 6 +- .../evaluators/PressureFieldEvaluator.h | 4 +- .../PressureGradientFieldEvaluator.h | 6 +- .../SolidVolumeFractionFieldEvaluator.h | 4 +- .../StressTensorGradientFieldEvaluator.h | 6 +- .../evaluators/VelocityCurlFieldEvaluator.h | 4 +- .../evaluators/VelocityFieldEvaluator.h | 4 +- .../VelocityGradientFieldEvaluator.h | 6 +- ...elocityTotalTimeDerivativeFieldEvaluator.h | 4 +- .../gns_lbm/GNSSweep.h | 10 +- .../GNSExternalForceToForceFieldAdder.h | 4 +- .../utility/GNSPressureFieldEvaluator.h | 4 +- .../gns_lbm/utility/GNSSmagorinskyLESField.h | 6 +- .../utility/GNSVelocityFieldEvaluator.h | 6 +- ...edInteractionForceFieldToForceFieldAdder.h | 2 +- .../utility/BodyVelocityInitializer.h | 4 +- .../utility/ExternalForceToForceFieldAdder.h | 2 +- .../utility/ForceFieldResetter.h | 2 +- .../momentum_exchange_method/BodyMapping.h | 10 +- .../boundary/CurvedLinear.h | 8 +- .../boundary/CurvedQuadratic.h | 8 +- .../boundary/SimpleBB.h | 8 +- .../destruction/Destroyer.h | 2 +- .../ExtrapolationDirectionFinder.h | 2 +- .../restoration/PDFReconstruction.h | 8 +- .../restoration/Reconstructor.h | 12 +-- .../BodyAndVolumeFractionMapping.cpp | 4 +- .../BodyAndVolumeFractionMapping.h | 4 +- .../PSMSweep.h | 12 +-- .../PSMUtility.h | 6 +- .../utility/BodiesForceTorqueContainer.h | 2 +- src/postprocessing/MarchingCubes.impl.h | 2 +- src/stencil/D2CornerStencil.h | 4 +- src/stencil/D2Q4.h | 4 +- src/stencil/D2Q5.h | 4 +- src/stencil/D2Q9.h | 4 +- src/stencil/D3CornerStencil.h | 4 +- src/stencil/D3EdgeCornerStencil.h | 4 +- src/stencil/D3Q15.h | 4 +- src/stencil/D3Q19.h | 4 +- src/stencil/D3Q27.h | 4 +- src/stencil/D3Q6.h | 4 +- src/stencil/D3Q7.h | 4 +- src/stencil/EdgeStencil.h | 4 +- src/timeloop/PerformanceMeter.cpp | 2 +- src/timeloop/PerformanceMeter.h | 2 +- src/timeloop/SelectableFunctionCreators.h | 2 +- src/timeloop/Timeloop.h | 6 +- src/vtk/BlockCellDataWriter.h | 6 +- src/vtk/ChainedFilter.h | 2 +- src/vtk/Initialization.h | 6 +- src/vtk/PolylineDataSource.h | 2 +- src/vtk/VTKOutput.h | 13 ++- 277 files changed, 1173 insertions(+), 1219 deletions(-) diff --git a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSedimentSettling.cpp b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSedimentSettling.cpp index f8b5674df..73e19a030 100644 --- a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSedimentSettling.cpp +++ b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSedimentSettling.cpp @@ -90,25 +90,25 @@ using walberla::uint_t; ////////////// // PDF field, flag field & body field -typedef lbm::D3Q19< lbm::collision_model::TRT, false> LatticeModel_T; -typedef LatticeModel_T::Stencil Stencil_T; -typedef lbm::PdfField< LatticeModel_T > PdfField_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::TRT, false>; +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; -typedef walberla::uint8_t flag_t; -typedef FlagField< flag_t > FlagField_T; -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; -typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; +using VelocityField_T = GhostLayerField<Vector3<real_t>, 1>; const uint_t FieldGhostLayers = 4; // boundary handling -typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MO_T; +using MO_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, MO_T>; -typedef std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane> BodyTypeTuple; +using BodyTypeTuple = std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane>; /////////// // FLAGS // @@ -135,8 +135,8 @@ template< typename LatticeModel_T, typename Filter_T > class VectorGradientRefinement { public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; VectorGradientRefinement( const ConstBlockDataID & fieldID, const Filter_T & filter, const real_t upperLimit, const real_t lowerLimit, const uint_t maxLevel ) : @@ -1504,7 +1504,7 @@ int main( int argc, char **argv ) // add velocity field and utility BlockDataID velocityFieldID = field::addToStorage<VelocityField_T>( blocks, "velocity field", Vector3<real_t>(real_t(0)), field::zyxf, uint_t(2) ); - typedef lbm::VelocityFieldWriter< PdfField_T, VelocityField_T > VelocityFieldWriter_T; + using VelocityFieldWriter_T = lbm::VelocityFieldWriter<PdfField_T, VelocityField_T>; BlockSweepWrapper< VelocityFieldWriter_T > velocityFieldWriter( blocks, VelocityFieldWriter_T( pdfFieldID, velocityFieldID ) ); @@ -1847,7 +1847,7 @@ int main( int argc, char **argv ) "Body Mapping", finestLevel ); // add sweep for restoring PDFs in cells previously occupied by pe bodies - typedef pe_coupling::EquilibriumReconstructor< LatticeModel_T, BoundaryHandling_T > Reconstructor_T; + using Reconstructor_T = pe_coupling::EquilibriumReconstructor<LatticeModel_T, BoundaryHandling_T>; Reconstructor_T reconstructor( blocks, boundaryHandlingID, bodyFieldID ); refinementTimestep->addPostStreamVoidFunction(lbm::refinement::SweepAsFunctorWrapper( pe_coupling::PDFReconstruction< LatticeModel_T, BoundaryHandling_T, Reconstructor_T > ( blocks, pdfFieldID, boundaryHandlingID, bodyStorageID, globalBodyStorage, bodyFieldID, reconstructor, FormerMO_Flag, Fluid_Flag ), blocks ), diff --git a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSettlingSphere.cpp b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSettlingSphere.cpp index 0db5c807d..c13a7c93d 100644 --- a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSettlingSphere.cpp +++ b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/AMRSettlingSphere.cpp @@ -84,25 +84,25 @@ using walberla::uint_t; ////////////// // PDF field, flag field & body field -typedef lbm::D3Q19< lbm::collision_model::TRT, false > LatticeModel_T; -typedef LatticeModel_T::Stencil Stencil_T; -typedef lbm::PdfField< LatticeModel_T > PdfField_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::TRT, false>; +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; -typedef walberla::uint8_t flag_t; -typedef FlagField< flag_t > FlagField_T; -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; -typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; +using VelocityField_T = GhostLayerField<Vector3<real_t>, 1>; const uint_t FieldGhostLayers = 4; // boundary handling -typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MO_T; +using MO_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, MO_T>; -typedef std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane> BodyTypeTuple; +using BodyTypeTuple = std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane>; /////////// // FLAGS // @@ -128,8 +128,8 @@ template< typename LatticeModel_T, typename Filter_T > class VectorGradientRefinement { public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; VectorGradientRefinement( const ConstBlockDataID & fieldID, const Filter_T & filter, const real_t upperLimit, const real_t lowerLimit, const uint_t maxLevel ) : @@ -994,7 +994,7 @@ int main( int argc, char **argv ) // add velocity field and utility BlockDataID velocityFieldID = field::addToStorage<VelocityField_T>( blocks, "velocity field", Vector3<real_t>(real_t(0)), field::zyxf, uint_t(2) ); - typedef lbm::VelocityFieldWriter< PdfField_T, VelocityField_T > VelocityFieldWriter_T; + using VelocityFieldWriter_T = lbm::VelocityFieldWriter<PdfField_T, VelocityField_T>; BlockSweepWrapper< VelocityFieldWriter_T > velocityFieldWriter( blocks, VelocityFieldWriter_T( pdfFieldID, velocityFieldID ) ); @@ -1177,7 +1177,7 @@ int main( int argc, char **argv ) "Body Mapping", finestLevel ); // add sweep for restoring PDFs in cells previously occupied by pe bodies - typedef pe_coupling::EquilibriumReconstructor< LatticeModel_T, BoundaryHandling_T > Reconstructor_T; + using Reconstructor_T = pe_coupling::EquilibriumReconstructor<LatticeModel_T, BoundaryHandling_T>; Reconstructor_T reconstructor( blocks, boundaryHandlingID, bodyFieldID ); refinementTimestep->addPostStreamVoidFunction(lbm::refinement::SweepAsFunctorWrapper( pe_coupling::PDFReconstruction< LatticeModel_T, BoundaryHandling_T, Reconstructor_T > ( blocks, pdfFieldID, boundaryHandlingID, bodyStorageID, globalBodyStorage, bodyFieldID, reconstructor, FormerMO_Flag, Fluid_Flag ), blocks ), diff --git a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/WorkloadEvaluation.cpp b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/WorkloadEvaluation.cpp index 18d93204f..01f0b3f99 100644 --- a/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/WorkloadEvaluation.cpp +++ b/apps/benchmarks/AdaptiveMeshRefinementFluidParticleCoupling/WorkloadEvaluation.cpp @@ -86,23 +86,23 @@ using namespace walberla; using walberla::uint_t; // PDF field, flag field & body field -typedef lbm::D3Q19< lbm::collision_model::TRT, false> LatticeModel_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::TRT, false>; -typedef LatticeModel_T::Stencil Stencil_T; -typedef lbm::PdfField< LatticeModel_T > PdfField_T; +using Stencil_T = LatticeModel_T::Stencil; +using PdfField_T = lbm::PdfField<LatticeModel_T>; -typedef walberla::uint8_t flag_t; -typedef FlagField< flag_t > FlagField_T; -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; +using flag_t = walberla::uint8_t; +using FlagField_T = FlagField<flag_t>; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; const uint_t FieldGhostLayers = 1; // boundary handling -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MO_CLI_T; +using MO_CLI_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, MO_CLI_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, MO_CLI_T>; -typedef std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane> BodyTypeTuple; +using BodyTypeTuple = std::tuple<pe::Sphere, pe::Ellipsoid, pe::Plane>; /////////// // FLAGS // @@ -754,7 +754,7 @@ int main( int argc, char **argv ) << Sweep( pe_coupling::BodyMapping< LatticeModel_T, BoundaryHandling_T >( blocks, pdfFieldID, boundaryHandlingID, bodyStorageID, globalBodyStorage, bodyFieldID, MO_CLI_Flag, FormerMO_Flag, pe_coupling::selectRegularBodies ), "Body Mapping" ); // sweep for restoring PDFs in cells previously occupied by pe bodies - typedef pe_coupling::EquilibriumReconstructor< LatticeModel_T, BoundaryHandling_T > Reconstructor_T; + using Reconstructor_T = pe_coupling::EquilibriumReconstructor<LatticeModel_T, BoundaryHandling_T>; Reconstructor_T reconstructor( blocks, boundaryHandlingID, bodyFieldID); timeloop.add() << Sweep( pe_coupling::PDFReconstruction< LatticeModel_T, BoundaryHandling_T, Reconstructor_T > diff --git a/apps/benchmarks/CouetteFlow/CouetteFlow.cpp b/apps/benchmarks/CouetteFlow/CouetteFlow.cpp index 4bedb5742..b313738d0 100644 --- a/apps/benchmarks/CouetteFlow/CouetteFlow.cpp +++ b/apps/benchmarks/CouetteFlow/CouetteFlow.cpp @@ -118,21 +118,21 @@ using walberla::real_t; // TYPEDEFS // ////////////// -typedef lbm::D3Q15< lbm::collision_model::SRT, false > D3Q15_SRT_INCOMP; -typedef lbm::D3Q15< lbm::collision_model::SRT, true > D3Q15_SRT_COMP; -typedef lbm::D3Q15< lbm::collision_model::TRT, false > D3Q15_TRT_INCOMP; -typedef lbm::D3Q15< lbm::collision_model::TRT, true > D3Q15_TRT_COMP; - -typedef lbm::D3Q19< lbm::collision_model::SRT, false > D3Q19_SRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::SRT, true > D3Q19_SRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, false > D3Q19_TRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, true > D3Q19_TRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::D3Q19MRT, false > D3Q19_MRT_INCOMP; - -typedef lbm::D3Q27< lbm::collision_model::SRT, false > D3Q27_SRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::SRT, true > D3Q27_SRT_COMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, false > D3Q27_TRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, true > D3Q27_TRT_COMP; +using D3Q15_SRT_INCOMP = lbm::D3Q15<lbm::collision_model::SRT, false>; +using D3Q15_SRT_COMP = lbm::D3Q15<lbm::collision_model::SRT, true>; +using D3Q15_TRT_INCOMP = lbm::D3Q15<lbm::collision_model::TRT, false>; +using D3Q15_TRT_COMP = lbm::D3Q15<lbm::collision_model::TRT, true>; + +using D3Q19_SRT_INCOMP = lbm::D3Q19<lbm::collision_model::SRT, false>; +using D3Q19_SRT_COMP = lbm::D3Q19<lbm::collision_model::SRT, true>; +using D3Q19_TRT_INCOMP = lbm::D3Q19<lbm::collision_model::TRT, false>; +using D3Q19_TRT_COMP = lbm::D3Q19<lbm::collision_model::TRT, true>; +using D3Q19_MRT_INCOMP = lbm::D3Q19<lbm::collision_model::D3Q19MRT, false>; + +using D3Q27_SRT_INCOMP = lbm::D3Q27<lbm::collision_model::SRT, false>; +using D3Q27_SRT_COMP = lbm::D3Q27<lbm::collision_model::SRT, true>; +using D3Q27_TRT_INCOMP = lbm::D3Q27<lbm::collision_model::TRT, false>; +using D3Q27_TRT_COMP = lbm::D3Q27<lbm::collision_model::TRT, true>; template< typename LatticeModel_T > struct Types @@ -370,10 +370,10 @@ class MyBoundaryHandling { public: - typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; - typedef lbm::SimpleUBB< LatticeModel_T, flag_t > UBB_T; + using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using UBB_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; - typedef BoundaryHandling< FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T > BoundaryHandling_T; + using BoundaryHandling_T = BoundaryHandling<FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T>; @@ -616,7 +616,7 @@ struct AddRefinementTimeStep } else { - typedef lbm::SplitSweep< LatticeModel_T, FlagField_T > Sweep_T; + using Sweep_T = lbm::SplitSweep<LatticeModel_T, FlagField_T>; auto mySweep = make_shared< Sweep_T >( pdfFieldId, flagFieldId, Fluid_Flag ); addRefinementTimeStep< LatticeModel_T, Sweep_T >( timeloop, blocks, pdfFieldId, boundaryHandlingId, timingPool, levelwiseTimingPool, diff --git a/apps/benchmarks/DEM/DEM.cpp b/apps/benchmarks/DEM/DEM.cpp index a76f4993f..eb892fa4c 100644 --- a/apps/benchmarks/DEM/DEM.cpp +++ b/apps/benchmarks/DEM/DEM.cpp @@ -48,7 +48,7 @@ int main( int argc, char** argv ) using namespace walberla; using namespace walberla::pe; - typedef std::tuple<Sphere, Plane> BodyTuple ; + using BodyTuple = std::tuple<Sphere, Plane> ; walberla::MPIManager::instance()->initializeMPI( &argc, &argv ); diff --git a/apps/benchmarks/ForcesOnSphereNearPlaneInShearFlow/ForcesOnSphereNearPlaneInShearFlow.cpp b/apps/benchmarks/ForcesOnSphereNearPlaneInShearFlow/ForcesOnSphereNearPlaneInShearFlow.cpp index 7e5c37e2e..a01b5210f 100644 --- a/apps/benchmarks/ForcesOnSphereNearPlaneInShearFlow/ForcesOnSphereNearPlaneInShearFlow.cpp +++ b/apps/benchmarks/ForcesOnSphereNearPlaneInShearFlow/ForcesOnSphereNearPlaneInShearFlow.cpp @@ -81,23 +81,23 @@ using walberla::uint_t; ////////////// // PDF field, flag field & body field -typedef lbm::D3Q19< lbm::collision_model::TRT, false > LatticeModel_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::TRT, false>; using Stencil_T = LatticeModel_T::Stencil; using PdfField_T = lbm::PdfField<LatticeModel_T>; using flag_t = walberla::uint8_t; using FlagField_T = FlagField<flag_t>; -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; const uint_t FieldGhostLayers = 4; // boundary handling -typedef pe_coupling::SimpleBB< LatticeModel_T, FlagField_T > MO_SBB_T; -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MO_CLI_T; +using MO_SBB_T = pe_coupling::SimpleBB<LatticeModel_T, FlagField_T>; +using MO_CLI_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, MO_SBB_T, MO_CLI_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, MO_SBB_T, MO_CLI_T>; -typedef std::tuple< pe::Sphere, pe::Plane > BodyTypeTuple; +using BodyTypeTuple = std::tuple<pe::Sphere, pe::Plane>; /////////// // FLAGS // diff --git a/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp b/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp index efeb8186e..293451af2 100644 --- a/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp +++ b/apps/benchmarks/MotionSingleHeavySphere/MotionSingleHeavySphere.cpp @@ -76,29 +76,29 @@ using walberla::uint_t; ////////////// // PDF field, flag field & body field -typedef lbm::D3Q19< lbm::collision_model::TRT, false > LatticeModel_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::TRT, false>; using Stencil_T = LatticeModel_T::Stencil; using PdfField_T = lbm::PdfField<LatticeModel_T>; using flag_t = walberla::uint8_t; using FlagField_T = FlagField<flag_t>; -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; -typedef std::pair< pe::BodyID, real_t > BodyAndVolumeFraction_T; -typedef GhostLayerField< std::vector< BodyAndVolumeFraction_T >, 1 > BodyAndVolumeFractionField_T; +using BodyAndVolumeFraction_T = std::pair<pe::BodyID, real_t>; +using BodyAndVolumeFractionField_T = GhostLayerField<std::vector<BodyAndVolumeFraction_T>, 1>; const uint_t FieldGhostLayers = 1; // boundary handling -typedef lbm::SimpleUBB< LatticeModel_T, flag_t > UBB_T; -typedef lbm::SimplePressure< LatticeModel_T, flag_t > Outlet_T; +using UBB_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; +using Outlet_T = lbm::SimplePressure<LatticeModel_T, flag_t>; -typedef pe_coupling::SimpleBB< LatticeModel_T, FlagField_T > MEM_BB_T; -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MEM_CLI_T; -typedef pe_coupling::CurvedQuadratic< LatticeModel_T, FlagField_T > MEM_MR_T; +using MEM_BB_T = pe_coupling::SimpleBB<LatticeModel_T, FlagField_T>; +using MEM_CLI_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; +using MEM_MR_T = pe_coupling::CurvedQuadratic<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, UBB_T, Outlet_T, MEM_BB_T, MEM_CLI_T, MEM_MR_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, UBB_T, Outlet_T, MEM_BB_T, MEM_CLI_T, MEM_MR_T>; using BodyTypeTuple = std::tuple<pe::Sphere>; @@ -1236,7 +1236,7 @@ int main( int argc, char **argv ) // reconstruct missing PDFs using ExtrapolationFinder_T = pe_coupling::SphereNormalExtrapolationDirectionFinder; ExtrapolationFinder_T extrapolationFinder( blocks, bodyFieldID ); - typedef pe_coupling::ExtrapolationReconstructor< LatticeModel_T, BoundaryHandling_T, ExtrapolationFinder_T > Reconstructor_T; + using Reconstructor_T = pe_coupling::ExtrapolationReconstructor<LatticeModel_T, BoundaryHandling_T, ExtrapolationFinder_T>; Reconstructor_T reconstructor( blocks, boundaryHandlingID, bodyFieldID, extrapolationFinder, true ); timeloop.add() << Sweep( pe_coupling::PDFReconstruction< LatticeModel_T, BoundaryHandling_T, Reconstructor_T > ( blocks, pdfFieldID, boundaryHandlingID, bodyStorageID, globalBodyStorage, bodyFieldID, reconstructor, FormerMEM_Flag, Fluid_Flag ), "PDF Restore" ); diff --git a/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp b/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp index 631625909..817097cca 100644 --- a/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp +++ b/apps/benchmarks/NonUniformGrid/NonUniformGrid.cpp @@ -97,11 +97,11 @@ using walberla::real_t; // TYPEDEFS // ////////////// -typedef lbm::D3Q19< lbm::collision_model::SRT, false > D3Q19_SRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::SRT, true > D3Q19_SRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, false > D3Q19_TRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, true > D3Q19_TRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::D3Q19MRT, false > D3Q19_MRT_INCOMP; +using D3Q19_SRT_INCOMP = lbm::D3Q19<lbm::collision_model::SRT, false>; +using D3Q19_SRT_COMP = lbm::D3Q19<lbm::collision_model::SRT, true>; +using D3Q19_TRT_INCOMP = lbm::D3Q19<lbm::collision_model::TRT, false>; +using D3Q19_TRT_COMP = lbm::D3Q19<lbm::collision_model::TRT, true>; +using D3Q19_MRT_INCOMP = lbm::D3Q19<lbm::collision_model::D3Q19MRT, false>; template< typename LatticeModel_T > struct Types @@ -437,10 +437,10 @@ void ReGrid::operator()( std::vector< std::pair< const Block *, uint_t > > & min template< typename LatticeModel_T > struct MyBoundaryTypes { - typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; - typedef lbm::SimpleUBB< LatticeModel_T, flag_t > UBB_T; + using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using UBB_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; - typedef BoundaryHandling< FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T > BoundaryHandling_T; + using BoundaryHandling_T = BoundaryHandling<FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T>; }; template< typename LatticeModel_T > @@ -632,7 +632,7 @@ struct AddRefinementTimeStep } else { - typedef lbm::SplitSweep< LatticeModel_T, FlagField_T > Sweep_T; + using Sweep_T = lbm::SplitSweep<LatticeModel_T, FlagField_T>; auto mySweep = make_shared< Sweep_T >( pdfFieldId, flagFieldId, Fluid_Flag ); addRefinementTimeStep< LatticeModel_T, Sweep_T >( timeloop, blocks, pdfFieldId, boundaryHandlingId, timingPool, levelwiseTimingPool, diff --git a/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp b/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp index f5695a0f5..9542fad39 100644 --- a/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp +++ b/apps/benchmarks/PoiseuilleChannel/PoiseuilleChannel.cpp @@ -116,15 +116,15 @@ using walberla::real_t; // TYPEDEFS // ////////////// -typedef lbm::D3Q19< lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant > D3Q19_SRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant > D3Q19_SRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant > D3Q19_TRT_INCOMP; +using D3Q19_SRT_INCOMP = lbm::D3Q19<lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant>; +using D3Q19_SRT_COMP = lbm::D3Q19<lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant>; +using D3Q19_TRT_INCOMP = lbm::D3Q19<lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant>; //typedef lbm::D3Q19< lbm::collision_model::TRT, true, lbm::force_model::SimpleConstant > D3Q19_TRT_COMP; -typedef lbm::D3Q27< lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant > D3Q27_SRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant > D3Q27_SRT_COMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant > D3Q27_TRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, true, lbm::force_model::SimpleConstant > D3Q27_TRT_COMP; +using D3Q27_SRT_INCOMP = lbm::D3Q27<lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant>; +using D3Q27_SRT_COMP = lbm::D3Q27<lbm::collision_model::SRT, true, lbm::force_model::SimpleConstant>; +using D3Q27_TRT_INCOMP = lbm::D3Q27<lbm::collision_model::TRT, false, lbm::force_model::SimpleConstant>; +using D3Q27_TRT_COMP = lbm::D3Q27<lbm::collision_model::TRT, true, lbm::force_model::SimpleConstant>; template< typename LatticeModel_T > struct Types @@ -453,10 +453,10 @@ class MyBoundaryHandling { public: - typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; - typedef lbm::Curved< LatticeModel_T, FlagField_T > Curved_T; + using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using Curved_T = lbm::Curved<LatticeModel_T, FlagField_T>; - typedef BoundaryHandling< FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, Curved_T > BoundaryHandling_T; + using BoundaryHandling_T = BoundaryHandling<FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, Curved_T>; diff --git a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp index c49dafff0..cdbd64fbe 100644 --- a/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp +++ b/apps/benchmarks/SchaeferTurek/SchaeferTurek.cpp @@ -133,26 +133,26 @@ using walberla::real_t; // TYPEDEFS // ////////////// -typedef lbm::D2Q9< lbm::collision_model::SRT, false > D2Q9_SRT_INCOMP; -typedef lbm::D2Q9< lbm::collision_model::SRT, true > D2Q9_SRT_COMP; -typedef lbm::D2Q9< lbm::collision_model::TRT, false > D2Q9_TRT_INCOMP; -typedef lbm::D2Q9< lbm::collision_model::TRT, true > D2Q9_TRT_COMP; - -typedef lbm::D3Q15< lbm::collision_model::SRT, false > D3Q15_SRT_INCOMP; -typedef lbm::D3Q15< lbm::collision_model::SRT, true > D3Q15_SRT_COMP; -typedef lbm::D3Q15< lbm::collision_model::TRT, false > D3Q15_TRT_INCOMP; -typedef lbm::D3Q15< lbm::collision_model::TRT, true > D3Q15_TRT_COMP; - -typedef lbm::D3Q19< lbm::collision_model::SRT, false > D3Q19_SRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::SRT, true > D3Q19_SRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, false > D3Q19_TRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, true > D3Q19_TRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::D3Q19MRT, false > D3Q19_MRT_INCOMP; - -typedef lbm::D3Q27< lbm::collision_model::SRT, false > D3Q27_SRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::SRT, true > D3Q27_SRT_COMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, false > D3Q27_TRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::TRT, true > D3Q27_TRT_COMP; +using D2Q9_SRT_INCOMP = lbm::D2Q9<lbm::collision_model::SRT, false>; +using D2Q9_SRT_COMP = lbm::D2Q9<lbm::collision_model::SRT, true>; +using D2Q9_TRT_INCOMP = lbm::D2Q9<lbm::collision_model::TRT, false>; +using D2Q9_TRT_COMP = lbm::D2Q9<lbm::collision_model::TRT, true>; + +using D3Q15_SRT_INCOMP = lbm::D3Q15<lbm::collision_model::SRT, false>; +using D3Q15_SRT_COMP = lbm::D3Q15<lbm::collision_model::SRT, true>; +using D3Q15_TRT_INCOMP = lbm::D3Q15<lbm::collision_model::TRT, false>; +using D3Q15_TRT_COMP = lbm::D3Q15<lbm::collision_model::TRT, true>; + +using D3Q19_SRT_INCOMP = lbm::D3Q19<lbm::collision_model::SRT, false>; +using D3Q19_SRT_COMP = lbm::D3Q19<lbm::collision_model::SRT, true>; +using D3Q19_TRT_INCOMP = lbm::D3Q19<lbm::collision_model::TRT, false>; +using D3Q19_TRT_COMP = lbm::D3Q19<lbm::collision_model::TRT, true>; +using D3Q19_MRT_INCOMP = lbm::D3Q19<lbm::collision_model::D3Q19MRT, false>; + +using D3Q27_SRT_INCOMP = lbm::D3Q27<lbm::collision_model::SRT, false>; +using D3Q27_SRT_COMP = lbm::D3Q27<lbm::collision_model::SRT, true>; +using D3Q27_TRT_INCOMP = lbm::D3Q27<lbm::collision_model::TRT, false>; +using D3Q27_TRT_COMP = lbm::D3Q27<lbm::collision_model::TRT, true>; template< typename LatticeModel_T > struct Types @@ -776,16 +776,15 @@ private: template< typename LatticeModel_T > struct MyBoundaryTypes { - typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; - typedef lbm::NoSlip< LatticeModel_T, flag_t > Obstacle_T; - typedef lbm::Curved< LatticeModel_T, FlagField_T > Curved_T; - typedef lbm::DynamicUBB< LatticeModel_T, flag_t, - SinusInflowVelocity<Is2D< LatticeModel_T >::value> > DynamicUBB_T; - typedef lbm::Outlet< LatticeModel_T, FlagField_T, 2, 1 > Outlet21_T; - typedef lbm::Outlet< LatticeModel_T, FlagField_T, 4, 3 > Outlet43_T; - typedef lbm::SimplePressure< LatticeModel_T, flag_t > PressureOutlet_T; - - typedef BoundaryHandling< FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, Obstacle_T, Curved_T, DynamicUBB_T, Outlet21_T, Outlet43_T, PressureOutlet_T > BoundaryHandling_T; + using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using Obstacle_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using Curved_T = lbm::Curved<LatticeModel_T, FlagField_T>; + using DynamicUBB_T = lbm::DynamicUBB<LatticeModel_T, flag_t, SinusInflowVelocity<Is2D<LatticeModel_T>::value>>; + using Outlet21_T = lbm::Outlet<LatticeModel_T, FlagField_T, 2, 1>; + using Outlet43_T = lbm::Outlet<LatticeModel_T, FlagField_T, 4, 3>; + using PressureOutlet_T = lbm::SimplePressure<LatticeModel_T, flag_t>; + + using BoundaryHandling_T = BoundaryHandling<FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, Obstacle_T, Curved_T, DynamicUBB_T, Outlet21_T, Outlet43_T, PressureOutlet_T>; }; @@ -2285,7 +2284,7 @@ struct AddRefinementTimeStep } else { - typedef lbm::SplitSweep< LatticeModel_T, FlagField_T > Sweep_T; + using Sweep_T = lbm::SplitSweep<LatticeModel_T, FlagField_T>; auto mySweep = make_shared< Sweep_T >( pdfFieldId, flagFieldId, Fluid_Flag ); addRefinementTimeStep< LatticeModel_T, Sweep_T >( timeloop, blocks, pdfFieldId, boundaryHandlingId, timingPool, levelwiseTimingPool, @@ -2365,10 +2364,10 @@ void run( const shared_ptr< Config > & config, const LatticeModel_T & latticeMod // add velocity field + initialize velocity field writer (only used for simulations with an adaptive block structure) - typedef field::GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; + using VelocityField_T = field::GhostLayerField<Vector3<real_t>, 1>; BlockDataID velocityFieldId = field::addToStorage< VelocityField_T >( blocks, "velocity", Vector3<real_t>(0), field::zyxf, FieldGhostLayers, true, None, Empty ); - typedef lbm::VelocityFieldWriter< typename Types<LatticeModel_T>::PdfField_T, VelocityField_T > VelocityFieldWriter_T; + using VelocityFieldWriter_T = lbm::VelocityFieldWriter<typename Types<LatticeModel_T>::PdfField_T, VelocityField_T>; BlockSweepWrapper< VelocityFieldWriter_T > velocityFieldWriter( blocks, VelocityFieldWriter_T( pdfFieldId, velocityFieldId ), None, Empty ); velocityFieldWriter(); diff --git a/apps/benchmarks/UniformGrid/UniformGrid.cpp b/apps/benchmarks/UniformGrid/UniformGrid.cpp index d5d355e49..0a947d20f 100644 --- a/apps/benchmarks/UniformGrid/UniformGrid.cpp +++ b/apps/benchmarks/UniformGrid/UniformGrid.cpp @@ -101,12 +101,12 @@ using walberla::real_t; // TYPEDEFS // ////////////// -typedef lbm::D3Q19< lbm::collision_model::SRT, false > D3Q19_SRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::SRT, true > D3Q19_SRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, false > D3Q19_TRT_INCOMP; -typedef lbm::D3Q19< lbm::collision_model::TRT, true > D3Q19_TRT_COMP; -typedef lbm::D3Q19< lbm::collision_model::D3Q19MRT, false > D3Q19_MRT_INCOMP; -typedef lbm::D3Q27< lbm::collision_model::D3Q27Cumulant, true > D3Q27_CUMULANT_COMP; +using D3Q19_SRT_INCOMP = lbm::D3Q19<lbm::collision_model::SRT, false>; +using D3Q19_SRT_COMP = lbm::D3Q19<lbm::collision_model::SRT, true>; +using D3Q19_TRT_INCOMP = lbm::D3Q19<lbm::collision_model::TRT, false>; +using D3Q19_TRT_COMP = lbm::D3Q19<lbm::collision_model::TRT, true>; +using D3Q19_MRT_INCOMP = lbm::D3Q19<lbm::collision_model::D3Q19MRT, false>; +using D3Q27_CUMULANT_COMP = lbm::D3Q27<lbm::collision_model::D3Q27Cumulant, true>; template< typename LatticeModel_T > @@ -347,10 +347,10 @@ class MyBoundaryHandling { public: - typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; - typedef lbm::SimpleUBB< LatticeModel_T, flag_t > UBB_T; + using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; + using UBB_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; - typedef BoundaryHandling< FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T > BoundaryHandling_T; + using BoundaryHandling_T = BoundaryHandling<FlagField_T, typename Types<LatticeModel_T>::Stencil_T, NoSlip_T, UBB_T>; @@ -565,7 +565,7 @@ struct AddLB } else { - typedef lbm::SplitSweep< LatticeModel_T, FlagField_T > Sweep_T; + using Sweep_T = lbm::SplitSweep<LatticeModel_T, FlagField_T>; auto sweep = make_shared< Sweep_T >( pdfFieldId, flagFieldId, Fluid_Flag ); timeloop.add() << Sweep( lbm::CollideSweep< Sweep_T >( sweep ), "split LB sweep (collide)" ); diff --git a/apps/showcases/BidisperseFluidizedBed/BidisperseFluidizedBedDPM.cpp b/apps/showcases/BidisperseFluidizedBed/BidisperseFluidizedBedDPM.cpp index d3e6fe63a..dad90bc62 100644 --- a/apps/showcases/BidisperseFluidizedBed/BidisperseFluidizedBedDPM.cpp +++ b/apps/showcases/BidisperseFluidizedBed/BidisperseFluidizedBedDPM.cpp @@ -76,12 +76,12 @@ const uint_t FieldGhostLayers( 1 ); //#define OutletBC // PDF field, flag field & body field -typedef GhostLayerField< Matrix3<real_t>, 1 > TensorField_T; -typedef GhostLayerField< Vector3<real_t>, 1 > Vec3Field_T; -typedef GhostLayerField< real_t, 1 > ScalarField_T; +using TensorField_T = GhostLayerField<Matrix3<real_t>, 1>; +using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; +using ScalarField_T = GhostLayerField<real_t, 1>; using ForceModel_T = lbm::force_model::GuoField<Vec3Field_T>; -typedef lbm::D3Q19< lbm::collision_model::SRTField<ScalarField_T>, false, ForceModel_T > LatticeModel_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::SRTField<ScalarField_T>, false, ForceModel_T>; using Stencil_T = LatticeModel_T::Stencil; using PdfField_T = lbm::PdfField<LatticeModel_T>; @@ -89,18 +89,18 @@ using flag_t = walberla::uint8_t; using FlagField_T = FlagField<flag_t>; // boundary handling -typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; -typedef lbm::SimpleUBB< LatticeModel_T, flag_t > Inflow_T; +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; +using Inflow_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; #ifdef OutletBC typedef lbm::Outlet< LatticeModel_T, FlagField_T > Outflow_T; #else -typedef lbm::SimplePressure< LatticeModel_T, flag_t > Outflow_T; +using Outflow_T = lbm::SimplePressure<LatticeModel_T, flag_t>; #endif -typedef BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, Inflow_T, Outflow_T> BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, Inflow_T, Outflow_T>; -typedef std::tuple<pe::Plane, pe::Sphere> BodyTypeTuple ; +using BodyTypeTuple = std::tuple<pe::Plane, pe::Sphere> ; /////////// // FLAGS // @@ -1191,7 +1191,7 @@ int main( int argc, char **argv ) { if( dpm == DPMethod::GNS ) { if (interpol == Interpolation::INearestNeighbor) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1199,7 +1199,7 @@ int main( int argc, char **argv ) { viscosity); dragAndPressureForceEvaluationFunction = std::bind(&IFE_T::operator(), forceEvaluatorPtr); } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1209,7 +1209,7 @@ int main( int argc, char **argv ) { } } else if (interpol == Interpolation::IKernel) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1217,7 +1217,7 @@ int main( int argc, char **argv ) { viscosity); dragAndPressureForceEvaluationFunction = std::bind(&IFE_T::operator(), forceEvaluatorPtr); } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1227,7 +1227,7 @@ int main( int argc, char **argv ) { } } else if (interpol == Interpolation::ITrilinear) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1235,7 +1235,7 @@ int main( int argc, char **argv ) { viscosity); dragAndPressureForceEvaluationFunction = std::bind(&IFE_T::operator(), forceEvaluatorPtr); } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor> IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor>; shared_ptr<IFE_T> forceEvaluatorPtr = make_shared<IFE_T>(blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, @@ -1257,7 +1257,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1265,7 +1265,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1276,7 +1276,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1284,7 +1284,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1295,7 +1295,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1303,7 +1303,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity ); @@ -1317,7 +1317,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); @@ -1325,7 +1325,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); @@ -1336,7 +1336,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); @@ -1344,7 +1344,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); @@ -1355,7 +1355,7 @@ int main( int argc, char **argv ) { { if( dist == Distribution::DNearestNeighbor ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); @@ -1363,7 +1363,7 @@ int main( int argc, char **argv ) { } else if( dist == Distribution::DKernel ) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor > IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::TrilinearFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T > ( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator ); diff --git a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp index e8e27e9cf..5e1074ad0 100644 --- a/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp +++ b/apps/showcases/CombinedResolvedUnresolved/CombinedResolvedUnresolved.cpp @@ -81,13 +81,13 @@ using walberla::uint_t; // PDF field, flag field & body field -typedef GhostLayerField< pe::BodyID, 1 > BodyField_T; -typedef GhostLayerField< Matrix3< real_t >, 1 > TensorField_T; -typedef GhostLayerField< Vector3< real_t >, 1 > Vec3Field_T; -typedef GhostLayerField< real_t, 1 > ScalarField_T; +using BodyField_T = GhostLayerField<pe::BodyID, 1>; +using TensorField_T = GhostLayerField<Matrix3<real_t>, 1>; +using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; +using ScalarField_T = GhostLayerField<real_t, 1>; using ForceModel_T = lbm::force_model::GuoField< Vec3Field_T >; -typedef lbm::D3Q19< lbm::collision_model::SRTField< ScalarField_T >, false, ForceModel_T > LatticeModel_T; +using LatticeModel_T = lbm::D3Q19<lbm::collision_model::SRTField<ScalarField_T>, false, ForceModel_T>; using Stencil_T = LatticeModel_T::Stencil; using PdfField_T = lbm::PdfField< LatticeModel_T >; @@ -97,13 +97,13 @@ using FlagField_T = FlagField< flag_t >; const uint_t FieldGhostLayers = 1; // boundary handling -typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; -typedef pe_coupling::CurvedLinear< LatticeModel_T, FlagField_T > MO_T; +using MO_T = pe_coupling::CurvedLinear<LatticeModel_T, FlagField_T>; -typedef BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, MO_T > BoundaryHandling_T; +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, MO_T>; -typedef std::tuple< pe::Sphere, pe::Plane > BodyTypeTuple; +using BodyTypeTuple = std::tuple<pe::Sphere, pe::Plane>; /////////// // FLAGS // @@ -798,9 +798,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, pressureGradientFieldID, dragCorrelationFunction, viscosity, selectDPMBodies); @@ -808,9 +806,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, pressureGradientFieldID, dragCorrelationFunction, viscosity, selectDPMBodies); @@ -821,9 +817,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, pressureGradientFieldID, dragCorrelationFunction, viscosity, selectDPMBodies); @@ -831,9 +825,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::InteractionForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::InteractionForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, dragForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, svfFieldID, pressureGradientFieldID, dragCorrelationFunction, viscosity, selectDPMBodies); @@ -847,9 +839,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >(blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity, selectDPMBodies); @@ -857,9 +847,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >(blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity, selectDPMBodies); @@ -870,9 +858,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >(blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity, selectDPMBodies); @@ -880,9 +866,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::LiftForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::LiftForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >(blocks, liftForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, velocityFieldID, velocityCurlFieldID, liftCorrelationFunction, viscosity, selectDPMBodies); @@ -896,9 +880,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator, selectDPMBodies); @@ -906,9 +888,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< - FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::NearestNeighborFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator, selectDPMBodies); @@ -919,9 +899,7 @@ int main(int argc, char** argv) { if (dist == Distribution::DNearestNeighbor) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::NearestNeighborDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator, selectDPMBodies); @@ -929,9 +907,7 @@ int main(int argc, char** argv) } else if (dist == Distribution::DKernel) { - typedef pe_coupling::discrete_particle_methods::AddedMassForceEvaluator< - FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor > - IFE_T; + using IFE_T = pe_coupling::discrete_particle_methods::AddedMassForceEvaluator<FlagField_T, field::KernelFieldInterpolator, field::KernelDistributor>; shared_ptr< IFE_T > forceEvaluatorPtr = make_shared< IFE_T >( blocks, amForceFieldID, bodyStorageID, flagFieldID, Fluid_Flag, timeDerivativeVelocityFieldID, addedMassCorrelationFunction, bodyVelocityTimeDerivativeEvaluator, selectDPMBodies); @@ -1216,9 +1192,7 @@ int main(int argc, char** argv) // sweep for restoring PDFs in cells previously occupied by pe bodies pe_coupling::SphereNormalExtrapolationDirectionFinder extrapolationFinder(blocks, bodyFieldID); - typedef pe_coupling::ExtrapolationReconstructor< LatticeModel_T, BoundaryHandling_T, - pe_coupling::SphereNormalExtrapolationDirectionFinder > - Reconstructor_T; + using Reconstructor_T = pe_coupling::ExtrapolationReconstructor<LatticeModel_T, BoundaryHandling_T, pe_coupling::SphereNormalExtrapolationDirectionFinder>; Reconstructor_T reconstructor(blocks, boundaryHandlingID, bodyFieldID, extrapolationFinder, true); timeloop.add() << Sweep(pe_coupling::PDFReconstruction< LatticeModel_T, BoundaryHandling_T, Reconstructor_T >( diff --git a/apps/tutorials/basics/03_GameOfLife.cpp b/apps/tutorials/basics/03_GameOfLife.cpp index 92cc1146b..868e21bcd 100644 --- a/apps/tutorials/basics/03_GameOfLife.cpp +++ b/apps/tutorials/basics/03_GameOfLife.cpp @@ -186,7 +186,7 @@ int main( int argc, char ** argv ) false, // one block per process? - "false" means all blocks to one process false, false, false ); // no periodicity - typedef GhostLayerField<real_t,1> ScalarField; + using ScalarField = GhostLayerField<real_t, 1>; BlockDataID fieldID = field::addToStorage<ScalarField>( blocks, // block storage "My Field", // name real_c(0), // initial value diff --git a/apps/tutorials/lbm/01_BasicLBM.cpp b/apps/tutorials/lbm/01_BasicLBM.cpp index 1380a1f10..ccfd0632d 100644 --- a/apps/tutorials/lbm/01_BasicLBM.cpp +++ b/apps/tutorials/lbm/01_BasicLBM.cpp @@ -69,7 +69,7 @@ int main( int argc, char ** argv ) auto boundariesConfig = walberlaEnv.config()->getOneBlock( "Boundaries" ); - typedef lbm::DefaultBoundaryHandlingFactory< LatticeModel_T, FlagField_T > BHFactory; + using BHFactory = lbm::DefaultBoundaryHandlingFactory<LatticeModel_T, FlagField_T>; BlockDataID boundaryHandlingId = BHFactory::addBoundaryHandlingToStorage( blocks, "boundary handling", flagFieldId, pdfFieldId, fluidFlagUID, boundariesConfig.getParameter< Vector3<real_t> >( "velocity0", Vector3<real_t>() ), diff --git a/apps/tutorials/lbm/02_BasicLBM_ExemplaryExtensions.cpp b/apps/tutorials/lbm/02_BasicLBM_ExemplaryExtensions.cpp index 3f75b9bf6..1c491b90c 100644 --- a/apps/tutorials/lbm/02_BasicLBM_ExemplaryExtensions.cpp +++ b/apps/tutorials/lbm/02_BasicLBM_ExemplaryExtensions.cpp @@ -32,7 +32,7 @@ namespace walberla { -typedef lbm::D2Q9< lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant > LatticeModel_T; +using LatticeModel_T = lbm::D2Q9<lbm::collision_model::SRT, false, lbm::force_model::SimpleConstant>; using Stencil_T = LatticeModel_T::Stencil; using CommunicationStencil_T = LatticeModel_T::CommunicationStencil; @@ -78,7 +78,7 @@ public: return; // data type for storing a position together with a floating point value - typedef std::pair< Cell, real_t > PosValuePair; + using PosValuePair = std::pair<Cell, real_t>; // variables for storing the process local minimum/maximum velocity & density PosValuePair maxVelocity = std::pair< Cell, real_t >( Cell(), real_c(0) ); @@ -582,7 +582,7 @@ int main( int argc, char ** argv ) auto boundariesConfig = walberlaEnv.config()->getOneBlock( "Boundaries" ); - typedef lbm::DefaultBoundaryHandlingFactory< LatticeModel_T, FlagField_T > BHFactory; + using BHFactory = lbm::DefaultBoundaryHandlingFactory<LatticeModel_T, FlagField_T>; BlockDataID boundaryHandlingId = BHFactory::addBoundaryHandlingToStorage( blocks, "boundary handling", flagFieldId, pdfFieldId, fluidFlagUID, boundariesConfig.getParameter< Vector3<real_t> >( "velocity0", Vector3<real_t>() ), boundariesConfig.getParameter< Vector3<real_t> >( "velocity1", Vector3<real_t>() ), diff --git a/apps/tutorials/lbm/03_LBLidDrivenCavity.cpp b/apps/tutorials/lbm/03_LBLidDrivenCavity.cpp index 7aa2e29bc..95f9ef95e 100644 --- a/apps/tutorials/lbm/03_LBLidDrivenCavity.cpp +++ b/apps/tutorials/lbm/03_LBLidDrivenCavity.cpp @@ -75,11 +75,11 @@ using FlagField_T = FlagField<flag_t>; // the flag field: used for marking cells // (also used for distinguishing between different boundary conditions // -> every boundary condition possesses its own, unique flag) -typedef lbm::NoSlip< LatticeModel_T, flag_t > NoSlip_T; // no slip boundary condition -typedef lbm::SimpleUBB< LatticeModel_T, flag_t > UBB_T; // velocity bounce back boundary condition that internally works with one ... +using NoSlip_T = lbm::NoSlip<LatticeModel_T, flag_t>; // no slip boundary condition +using UBB_T = lbm::SimpleUBB<LatticeModel_T, flag_t>; // velocity bounce back boundary condition that internally works with one ... // ... constant velocity that must be set during the setup phase -typedef BoundaryHandling< FlagField_T, Stencil_T, NoSlip_T, UBB_T > BoundaryHandling_T; // the boundary handling, includes a collection of all boundary conditions +using BoundaryHandling_T = BoundaryHandling<FlagField_T, Stencil_T, NoSlip_T, UBB_T>; // the boundary handling, includes a collection of all boundary conditions /////////// // FLAGS // diff --git a/apps/tutorials/pde/01_SolvingPDE.cpp b/apps/tutorials/pde/01_SolvingPDE.cpp index 4b1e7d92f..3091c7597 100644 --- a/apps/tutorials/pde/01_SolvingPDE.cpp +++ b/apps/tutorials/pde/01_SolvingPDE.cpp @@ -39,7 +39,7 @@ namespace walberla { -typedef GhostLayerField<real_t,1> ScalarField; +using ScalarField = GhostLayerField<real_t, 1>; using Stencil_T = stencil::D2Q5; diff --git a/apps/tutorials/pde/02_HeatEquation.cpp b/apps/tutorials/pde/02_HeatEquation.cpp index dea443380..54a13fd9d 100644 --- a/apps/tutorials/pde/02_HeatEquation.cpp +++ b/apps/tutorials/pde/02_HeatEquation.cpp @@ -43,7 +43,7 @@ namespace walberla { -typedef GhostLayerField<real_t,1> ScalarField; +using ScalarField = GhostLayerField<real_t, 1>; using Stencil_T = stencil::D2Q5; diff --git a/apps/tutorials/pde/03_HeatEquation_Extensions.cpp b/apps/tutorials/pde/03_HeatEquation_Extensions.cpp index 9f65e2b12..a1b42906a 100644 --- a/apps/tutorials/pde/03_HeatEquation_Extensions.cpp +++ b/apps/tutorials/pde/03_HeatEquation_Extensions.cpp @@ -44,7 +44,7 @@ namespace walberla { -typedef GhostLayerField<real_t,1> ScalarField; +using ScalarField = GhostLayerField<real_t, 1>; using Stencil_T = stencil::D2Q5; diff --git a/apps/tutorials/pe/01_ConfinedGas.cpp b/apps/tutorials/pe/01_ConfinedGas.cpp index 6e0d1f7ab..df137021b 100644 --- a/apps/tutorials/pe/01_ConfinedGas.cpp +++ b/apps/tutorials/pe/01_ConfinedGas.cpp @@ -35,7 +35,7 @@ namespace walberla { using namespace walberla::pe; //! [BodyTypeTuple] -typedef std::tuple<Sphere, Plane> BodyTypeTuple ; +using BodyTypeTuple = std::tuple<Sphere, Plane> ; //! [BodyTypeTuple] int main( int argc, char ** argv ) diff --git a/apps/tutorials/pe/02_ConfinedGasExtended.cpp b/apps/tutorials/pe/02_ConfinedGasExtended.cpp index 69629eba1..4e0841175 100644 --- a/apps/tutorials/pe/02_ConfinedGasExtended.cpp +++ b/apps/tutorials/pe/02_ConfinedGasExtended.cpp @@ -43,7 +43,7 @@ using namespace walberla::pe; using namespace walberla::timing; using namespace walberla::pe::raytracing; -typedef std::tuple<Sphere, Plane> BodyTuple ; +using BodyTuple = std::tuple<Sphere, Plane> ; int main( int argc, char ** argv ) { diff --git a/src/blockforest/Block.h b/src/blockforest/Block.h index caf87d623..64c7dafa7 100644 --- a/src/blockforest/Block.h +++ b/src/blockforest/Block.h @@ -366,7 +366,7 @@ inline void Block::setTargetLevel( const uint_t tl ) } // namespace blockforest -typedef blockforest::Block Block; +using Block = blockforest::Block; } // namespace walberla diff --git a/src/blockforest/BlockDataHandling.h b/src/blockforest/BlockDataHandling.h index be978d3a8..7f56467c0 100644 --- a/src/blockforest/BlockDataHandling.h +++ b/src/blockforest/BlockDataHandling.h @@ -95,7 +95,7 @@ namespace internal { class BlockDataHandlingWrapper : public domain_decomposition::internal::BlockDataHandlingWrapper { public: - typedef domain_decomposition::internal::BlockData BlockData; + using BlockData = domain_decomposition::internal::BlockData; ~BlockDataHandlingWrapper() override = default; @@ -115,7 +115,7 @@ template< typename T > class BlockDataHandlingHelper : public BlockDataHandlingWrapper { public: - typedef domain_decomposition::internal::BlockData BlockData; + using BlockData = domain_decomposition::internal::BlockData; BlockDataHandlingHelper( const shared_ptr< BlockDataHandling<T> > & dataHandling ) : dataHandling_( dataHandling ) {} ~BlockDataHandlingHelper() override = default; diff --git a/src/blockforest/BlockForest.h b/src/blockforest/BlockForest.h index bd66ced43..0edd764af 100644 --- a/src/blockforest/BlockForest.h +++ b/src/blockforest/BlockForest.h @@ -55,7 +55,6 @@ public: using RefreshCallbackFunction = std::function<void (BlockForest &, const PhantomBlockForest &)>; using SnapshotCreationFunction = std::function<void (std::vector<uint_t> &, std::vector<uint_t> &)>; - [[deprecated("typo: use SnapshotRestoreFunction")]] typedef std::function<uint_t (const uint_t)> SnapshotRestorenFunction; using SnapshotRestoreFunction = std::function<uint_t (const uint_t)>; using SnapshotRestoreCallbackFunction = std::function<void ()>; diff --git a/src/blockforest/BlockID.h b/src/blockforest/BlockID.h index d4efc6bcc..e62d8ff09 100644 --- a/src/blockforest/BlockID.h +++ b/src/blockforest/BlockID.h @@ -385,7 +385,7 @@ void BlockID::fromBuffer( Buffer_T& buffer ) { } // namespace blockforest -typedef blockforest::BlockID BlockID; +using BlockID = blockforest::BlockID; } // namespace walberla diff --git a/src/blockforest/GlobalLoadBalancing.h b/src/blockforest/GlobalLoadBalancing.h index ca7c687a9..ba92b73f2 100644 --- a/src/blockforest/GlobalLoadBalancing.h +++ b/src/blockforest/GlobalLoadBalancing.h @@ -55,7 +55,7 @@ public: class MetisConfiguration { public: - typedef std::function< memory_t ( const BLOCK* const, const BLOCK* const ) > CommunicationFunction; + using CommunicationFunction = std::function<memory_t (const BLOCK *const, const BLOCK *const)>; MetisConfiguration( const bool _includeMetis = false, const bool _forceMetis = false, CommunicationFunction _communicationFunction = nullptr, const real_t _maxUbvec = real_c(1.5), const uint_t _iterations = uint_c(10) ) : diff --git a/src/blockforest/PhantomBlock.h b/src/blockforest/PhantomBlock.h index 2d6c2b6ee..3872a7261 100644 --- a/src/blockforest/PhantomBlock.h +++ b/src/blockforest/PhantomBlock.h @@ -374,6 +374,6 @@ inline const AABB & PhantomBlock::getNeighborAABB( const uint_t index ) const } // namespace blockforest -typedef blockforest::PhantomBlock PhantomBlock; +using PhantomBlock = blockforest::PhantomBlock; } // namespace walberla diff --git a/src/blockforest/PhantomBlockForest.h b/src/blockforest/PhantomBlockForest.h index 1c7285167..92211a7fc 100644 --- a/src/blockforest/PhantomBlockForest.h +++ b/src/blockforest/PhantomBlockForest.h @@ -42,23 +42,16 @@ class PhantomBlockForest { public: - typedef std::function< Set<SUID> ( const std::vector< std::pair< BlockID, Set<SUID> > > & source, const BlockID & destintation ) > - BlockStateDeterminationFunction; + using BlockStateDeterminationFunction = std::function<Set<SUID> (const std::vector<std::pair<BlockID, Set<SUID>>> &, const BlockID &)>; - typedef std::function< void ( std::vector< std::pair< const PhantomBlock *, walberla::any > > & blockData, - const PhantomBlockForest & phantomForest ) > - PhantomBlockDataAssignmentFunction; + using PhantomBlockDataAssignmentFunction = std::function<void (std::vector<std::pair<const PhantomBlock *, walberla::any>> &, const PhantomBlockForest &)>; /// \param iteration execution counter of this callback /// \return should the callback rerun after phantom block migration? - typedef std::function< bool ( std::vector< std::pair< const PhantomBlock *, uint_t > > & targetProcess, - std::set< uint_t > & processesToRecvFrom, - const PhantomBlockForest & phantomForest, - const uint_t iteration ) > - MigrationPreparationFunction; // = load balancing + using MigrationPreparationFunction = std::function<bool (std::vector<std::pair<const PhantomBlock *, uint_t>> &, std::set<uint_t> &, const PhantomBlockForest &, const uint_t)>; // = load balancing - typedef std::function< void ( mpi::SendBuffer & buffer, const PhantomBlock & block ) > PhantomBlockDataPackFunction; - typedef std::function< void ( mpi::RecvBuffer & buffer, const PhantomBlock & block, walberla::any & data ) > PhantomBlockDataUnpackFunction; + using PhantomBlockDataPackFunction = std::function<void (mpi::SendBuffer &, const PhantomBlock &)>; + using PhantomBlockDataUnpackFunction = std::function<void (mpi::RecvBuffer &, const PhantomBlock &, walberla::any &)>; @@ -128,6 +121,6 @@ inline shared_ptr< PhantomBlock > PhantomBlockForest::getBlock( const BlockID & } // namespace blockforest -typedef blockforest::PhantomBlockForest PhantomBlockForest; +using PhantomBlockForest = blockforest::PhantomBlockForest; } // namespace walberla diff --git a/src/blockforest/SetupBlockForest.h b/src/blockforest/SetupBlockForest.h index 2dac1578f..17fd2685a 100644 --- a/src/blockforest/SetupBlockForest.h +++ b/src/blockforest/SetupBlockForest.h @@ -45,8 +45,7 @@ class SetupBlockForest : private NonCopyable { public: - typedef std::function< uint_t ( SetupBlockForest & forest, const uint_t numberOfProcesses, const memory_t perProcessMemoryLimit ) > - TargetProcessAssignmentFunction; // returns number of processes (may be lower than numberOfProcesses) + using TargetProcessAssignmentFunction = std::function<uint_t (SetupBlockForest &, const uint_t, const memory_t)>; // returns number of processes (may be lower than numberOfProcesses) @@ -72,14 +71,14 @@ public: // Do not use a vector of bool's! Due to the implementation of this vector in the standard library, parallel access to a // vector of bool's - even on different elements - is not thread-safe! - typedef std::function< void ( std::vector<uint8_t>& excludeBlock, const RootBlockAABB& aabb ) > RootBlockExclusionFunction; + using RootBlockExclusionFunction = std::function<void (std::vector<uint8_t> &, const RootBlockAABB &)>; - typedef std::function< void ( SetupBlockForest& forest ) > RefinementSelectionFunction; - typedef std::function< void ( SetupBlockForest& forest ) > WorkloadMemorySUIDAssignmentFunction; + using RefinementSelectionFunction = std::function<void (SetupBlockForest &)>; + using WorkloadMemorySUIDAssignmentFunction = std::function<void (SetupBlockForest &)>; - typedef std::vector< std::pair< const SetupBlock*, const SetupBlock* > > CommunicationPairs; - typedef std::vector< real_t > CommunicationWeights; - typedef std::function< void ( const CommunicationPairs &, CommunicationWeights & ) > CommunicationWeightFunction; + using CommunicationPairs = std::vector<std::pair<const SetupBlock *, const SetupBlock *>>; + using CommunicationWeights = std::vector<real_t>; + using CommunicationWeightFunction = std::function<void (const CommunicationPairs &, CommunicationWeights &)>; inline static void NullCommunicationWeightFunction( const CommunicationPairs &, CommunicationWeights & ) { @@ -715,7 +714,7 @@ class RefinementSelectionFunctions { public: - typedef blockforest::SetupBlockForest::RefinementSelectionFunction RefinementSelectionFunction; + using RefinementSelectionFunction = blockforest::SetupBlockForest::RefinementSelectionFunction; void add( const RefinementSelectionFunction & function ) { diff --git a/src/blockforest/Types.h b/src/blockforest/Types.h index 76ab39113..dc61b3551 100644 --- a/src/blockforest/Types.h +++ b/src/blockforest/Types.h @@ -33,8 +33,8 @@ namespace blockforest { // data structure specific types -typedef real_t workload_t; -typedef real_t memory_t; +using workload_t = real_t; +using memory_t = real_t; WALBERLA_STATIC_ASSERT( sizeof( workload_t ) == 4 || sizeof( workload_t ) == 8 ); WALBERLA_STATIC_ASSERT( sizeof( memory_t ) == 4 || sizeof( memory_t ) == 8 ); diff --git a/src/blockforest/communication/NonUniformBufferedScheme.h b/src/blockforest/communication/NonUniformBufferedScheme.h index 3e206f36d..caf91651c 100644 --- a/src/blockforest/communication/NonUniformBufferedScheme.h +++ b/src/blockforest/communication/NonUniformBufferedScheme.h @@ -55,12 +55,12 @@ public: enum INDEX { EQUAL_LEVEL = 0, COARSE_TO_FINE = 1, FINE_TO_COARSE = 2 }; - typedef mpi::SendBuffer SendBuffer; - typedef mpi::RecvBuffer RecvBuffer; + using SendBuffer = mpi::SendBuffer; + using RecvBuffer = mpi::RecvBuffer; - typedef shared_ptr< blockforest::communication::NonUniformPackInfo > PackInfo; - typedef std::function<void ()> VoidFunction; - typedef std::function<void ( SendBuffer & buffer )> SendBufferFunction; + using PackInfo = shared_ptr<blockforest::communication::NonUniformPackInfo>; + using VoidFunction = std::function<void ()>; + using SendBufferFunction = std::function<void (SendBuffer &)>; //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ diff --git a/src/blockforest/communication/UniformBufferedScheme.h b/src/blockforest/communication/UniformBufferedScheme.h index 6ee1be18c..8677b5f83 100644 --- a/src/blockforest/communication/UniformBufferedScheme.h +++ b/src/blockforest/communication/UniformBufferedScheme.h @@ -80,16 +80,16 @@ template< typename Stencil_T > class UniformBufferedScheme { public: - typedef Stencil_T Stencil; - typedef mpi::SendBuffer SendBuffer; - typedef mpi::RecvBuffer RecvBuffer; + using Stencil = Stencil_T; + using SendBuffer = mpi::SendBuffer; + using RecvBuffer = mpi::RecvBuffer; - typedef shared_ptr< walberla::communication::UniformPackInfo > PackInfo; + using PackInfo = shared_ptr<walberla::communication::UniformPackInfo>; - typedef std::function<void ()> VoidFunction; - typedef std::function<void ( SendBuffer & buffer )> SendBufferFunction; + using VoidFunction = std::function<void ()>; + using SendBufferFunction = std::function<void (SendBuffer &)>; - typedef walberla::communication::UniformPackInfo CommunicationItemInfo; + using CommunicationItemInfo = walberla::communication::UniformPackInfo; //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ diff --git a/src/blockforest/communication/UniformDirectScheme.h b/src/blockforest/communication/UniformDirectScheme.h index 7dfa2d781..0d10c2f4c 100644 --- a/src/blockforest/communication/UniformDirectScheme.h +++ b/src/blockforest/communication/UniformDirectScheme.h @@ -48,9 +48,9 @@ template< typename Stencil_T > class UniformDirectScheme { public: - typedef Stencil_T Stencil; - typedef walberla::communication::UniformMPIDatatypeInfo UniformMPIDatatypeInfo; - typedef walberla::communication::UniformMPIDatatypeInfo CommunicationItemInfo; + using Stencil = Stencil_T; + using UniformMPIDatatypeInfo = walberla::communication::UniformMPIDatatypeInfo; + using CommunicationItemInfo = walberla::communication::UniformMPIDatatypeInfo; //**Construction & Destruction*************************************************************************************** /*! \name Construction & Destruction */ diff --git a/src/blockforest/loadbalancing/DynamicCurve.h b/src/blockforest/loadbalancing/DynamicCurve.h index 30724c40f..8b3e5808a 100644 --- a/src/blockforest/loadbalancing/DynamicCurve.h +++ b/src/blockforest/loadbalancing/DynamicCurve.h @@ -53,8 +53,8 @@ template< typename PhantomData_T, typename Value_T, bool weighted = true > class BlockIDSorter { public: - typedef typename PhantomData_T::weight_t weight_t; - typedef std::vector< std::vector< std::pair< BlockID, weight_t > > > Blocks_T; + using weight_t = typename PhantomData_T::weight_t; + using Blocks_T = std::vector<std::vector<std::pair<BlockID, weight_t>>>; BlockIDSorter( const Blocks_T & blocks ) : blocks_( blocks ) {} bool operator()( const Value_T & lhs, const Value_T & rhs ) const { @@ -68,7 +68,7 @@ template< typename PhantomData_T, typename Value_T > class BlockIDSorter< PhantomData_T, Value_T, false > { public: - typedef std::vector< std::vector< BlockID > > Blocks_T; + using Blocks_T = std::vector<std::vector<BlockID>>; BlockIDSorter( const Blocks_T & blocks ) : blocks_( blocks ) {} bool operator()( const Value_T & lhs, const Value_T & rhs ) const { @@ -101,10 +101,10 @@ class DynamicCurveBalance { public: - typedef typename PhantomData_T::weight_t weight_t; - typedef mpi::MPIRank pid_t; - typedef uint16_t idx_t; // limits the maximum number of blocks per process to 65536 - typedef internal::Node< pid_t, idx_t > Node; + using weight_t = typename PhantomData_T::weight_t; + using pid_t = mpi::MPIRank; + using idx_t = uint16_t; // limits the maximum number of blocks per process to 65536 + using Node = internal::Node<pid_t, idx_t>; DynamicCurveBalance( const bool hilbert = true, const bool allGather = true, const bool levelwise = true ) : hilbert_( hilbert ), allGather_( allGather ), levelwise_(levelwise) diff --git a/src/blockforest/loadbalancing/DynamicParMetis.h b/src/blockforest/loadbalancing/DynamicParMetis.h index fa5663db5..f78a4c4c0 100644 --- a/src/blockforest/loadbalancing/DynamicParMetis.h +++ b/src/blockforest/loadbalancing/DynamicParMetis.h @@ -92,8 +92,8 @@ class DynamicParMetisBlockInfo { public: - typedef int64_t weight_t; - typedef int64_t vsize_t; + using weight_t = int64_t; + using vsize_t = int64_t; DynamicParMetisBlockInfo( const weight_t vertexWeight, const uint_t ncon = 1 ) : vertexWeight_(ncon, vertexWeight), vertexSize_(1) diff --git a/src/blockforest/loadbalancing/NoPhantomData.h b/src/blockforest/loadbalancing/NoPhantomData.h index a1662855d..7de1f9aaf 100644 --- a/src/blockforest/loadbalancing/NoPhantomData.h +++ b/src/blockforest/loadbalancing/NoPhantomData.h @@ -31,7 +31,7 @@ namespace blockforest { class NoPhantomData { public: - typedef uint8_t weight_t; + using weight_t = uint8_t; weight_t weight() const { return uint8_t(1); } }; diff --git a/src/blockforest/loadbalancing/PODPhantomData.h b/src/blockforest/loadbalancing/PODPhantomData.h index 2be8c77ce..2b8bc23eb 100644 --- a/src/blockforest/loadbalancing/PODPhantomData.h +++ b/src/blockforest/loadbalancing/PODPhantomData.h @@ -35,7 +35,7 @@ class PODPhantomWeight { public: - typedef T weight_t; + using weight_t = T; PODPhantomWeight( const T _weight ) : weight_( _weight ) {} diff --git a/src/blockforest/loadbalancing/StaticParMetis.h b/src/blockforest/loadbalancing/StaticParMetis.h index 0e77baf45..305d10a6d 100644 --- a/src/blockforest/loadbalancing/StaticParMetis.h +++ b/src/blockforest/loadbalancing/StaticParMetis.h @@ -40,8 +40,8 @@ public: enum Algorithm { PARMETIS_PART_GEOM_KWAY, PARMETIS_PART_KWAY }; enum WeightsToUse { PARMETIS_NO_WEIGHTS = 0, PARMETIS_EDGE_WEIGHTS = 1, PARMETIS_VERTEX_WEIGHTS = 2, PARMETIS_BOTH_WEIGHTS = 3 }; - typedef std::pair< const SetupBlock *, const SetupBlock * > BlockPair; - typedef std::function<void (const std::vector< BlockPair > & edges, std::vector< int64_t > & weights ) > CommWeightFunction; + using BlockPair = std::pair<const SetupBlock *, const SetupBlock *>; + using CommWeightFunction = std::function<void (const std::vector<BlockPair> &, std::vector<int64_t> &)>; StaticLevelwiseParMetis( const Algorithm algorithm = PARMETIS_PART_GEOM_KWAY ) : algorithm_( algorithm ), weightsToUse_( PARMETIS_VERTEX_WEIGHTS ) {} diff --git a/src/boundary/BoundaryHandling.h b/src/boundary/BoundaryHandling.h index 0910be455..9aa5a3439 100644 --- a/src/boundary/BoundaryHandling.h +++ b/src/boundary/BoundaryHandling.h @@ -66,7 +66,7 @@ using std::tuple_size; class BHUIDGenerator : public uid::IndexGenerator< BHUIDGenerator, uint_t >{}; -typedef UID< BHUIDGenerator > BoundaryHandlingUID; +using BoundaryHandlingUID = UID<BHUIDGenerator>; @@ -78,9 +78,9 @@ public: template< typename F, typename... T > friend class BoundaryHandlingCollection; - typedef FlagField_T FlagField; - typedef typename FlagField_T::flag_t flag_t; - typedef typename FlagField_T::const_base_iterator ConstFlagFieldBaseIterator; + using FlagField = FlagField_T; + using flag_t = typename FlagField_T::flag_t; + using ConstFlagFieldBaseIterator = typename FlagField_T::const_base_iterator; enum Mode { OPTIMIZED_SPARSE_TRAVERSAL, ENTIRE_FIELD_TRAVERSAL }; @@ -664,7 +664,7 @@ private: std::vector< std::vector< std::vector< std::pair< Cell, stencil::Direction > > > > cellDirectionPairs_; // 1st vector: numberOfGhostLayersToInclude // 2nd vector: boundary condition index // 3rd vector: vector of cell<->direction pairs - typedef std::tuple<Boundaries...> Tuple; + using Tuple = std::tuple<Boundaries...>; Tuple boundaryConditions_; bool threadSafeBCs_; diff --git a/src/boundary/BoundaryHandlingCollection.h b/src/boundary/BoundaryHandlingCollection.h index 61320c178..7b94d4a0e 100644 --- a/src/boundary/BoundaryHandlingCollection.h +++ b/src/boundary/BoundaryHandlingCollection.h @@ -49,7 +49,7 @@ namespace boundary { class BHCUIDGenerator : public uid::IndexGenerator< BHCUIDGenerator, uint_t >{}; -typedef UID< BHCUIDGenerator > BoundaryHandlingCollectionUID; +using BoundaryHandlingCollectionUID = UID<BHCUIDGenerator>; @@ -58,9 +58,9 @@ class BoundaryHandlingCollection { public: - typedef FlagField_T FlagField; - typedef typename FlagField_T::flag_t flag_t; - typedef typename FlagField_T::const_base_iterator ConstFlagFieldBaseIterator; + using FlagField = FlagField_T; + using flag_t = typename FlagField_T::flag_t; + using ConstFlagFieldBaseIterator = typename FlagField_T::const_base_iterator; @@ -534,7 +534,7 @@ private: const CellInterval outerBB_; - typedef std::tuple<Handlers...> Tuple; + using Tuple = std::tuple<Handlers...>; Tuple boundaryHandlers_; }; // class BoundaryHandlingCollection diff --git a/src/boundary/BoundaryUID.h b/src/boundary/BoundaryUID.h index 3df48a8c8..0f3a86bb1 100644 --- a/src/boundary/BoundaryUID.h +++ b/src/boundary/BoundaryUID.h @@ -29,7 +29,7 @@ namespace boundary { class BUIDGenerator : public uid::IndexGenerator< BUIDGenerator, size_t >{}; -typedef UID< BUIDGenerator > BoundaryUID; +using BoundaryUID = UID<BUIDGenerator>; } // namespace boundary diff --git a/src/core/Abort.h b/src/core/Abort.h index 23b1ef1ff..ee77794f5 100644 --- a/src/core/Abort.h +++ b/src/core/Abort.h @@ -40,7 +40,7 @@ class Abort : public singleton::Singleton<Abort> public: - typedef std::function<void ( const std::string & message, const std::string & callerPath, const int line, bool withDebugInfo )> AbortFunction; + using AbortFunction = std::function<void (const std::string &, const std::string &, const int, bool)>; void resetAbortFunction( const AbortFunction & function = AbortFunction() ) { abortFunction_ = function; } diff --git a/src/core/AllSet.h b/src/core/AllSet.h index 74842fd83..a2c79581b 100644 --- a/src/core/AllSet.h +++ b/src/core/AllSet.h @@ -94,7 +94,7 @@ public: friend inline bool operator==( const AllSet& a, const AllSet& b ) { return setIsEqual(a,b); } ///< compares the content of two sets friend inline bool operator!=( const AllSet& a, const AllSet& b ) { return !setIsEqual(a,b); } ///< compares the content of two sets - typedef typename std::set<T>::const_iterator ConstIter; + using ConstIter = typename std::set<T>::const_iterator; diff --git a/src/core/DataTypes.h b/src/core/DataTypes.h index 121f836c5..8cb35637b 100644 --- a/src/core/DataTypes.h +++ b/src/core/DataTypes.h @@ -86,10 +86,10 @@ inline S numeric_cast( T t ) { // fixed size signed integral types -typedef std::int8_t int8_t; ///< 8 bit signed integer -typedef std::int16_t int16_t; ///< 16 bit signed integer -typedef std::int32_t int32_t; ///< 32 bit signed integer -typedef std::int64_t int64_t; ///< 64 bit signed integer +using int8_t = std::int8_t; ///< 8 bit signed integer +using int16_t = std::int16_t; ///< 16 bit signed integer +using int32_t = std::int32_t; ///< 32 bit signed integer +using int64_t = std::int64_t; ///< 64 bit signed integer template< typename T > inline int8_t int8_c( T t ) { return numeric_cast< int8_t >(t); } ///< cast to type int8_t using "int8_c(x)" template< typename T > inline int16_t int16_c( T t ) { return numeric_cast< int16_t >(t); } ///< cast to type int16_t using "int16_c(x)" @@ -100,12 +100,12 @@ template< typename T > inline int64_t int64_c( T t ) { return numeric_cast< int6 // fixed size unsigned integral types -typedef std::uint8_t uint8_t; ///< 8 bit unsigned integer -typedef std::uint16_t uint16_t; ///< 16 bit unsigned integer -typedef std::uint32_t uint32_t; ///< 32 bit unsigned integer -typedef std::uint64_t uint64_t; ///< 64 bit unsigned integer -typedef uint8_t byte_t; -typedef uint64_t id_t; //sid datatype for pe +using uint8_t = std::uint8_t; ///< 8 bit unsigned integer +using uint16_t = std::uint16_t; ///< 16 bit unsigned integer +using uint32_t = std::uint32_t; ///< 32 bit unsigned integer +using uint64_t = std::uint64_t; ///< 64 bit unsigned integer +using byte_t = uint8_t; +using id_t = uint64_t; //sid datatype for pe template< typename T > inline uint8_t uint8_c( T t ) { return numeric_cast< uint8_t >(t); } ///< cast to type uint8_t using "uint8_c(x)" template< typename T > inline uint16_t uint16_c( T t ) { return numeric_cast< uint16_t >(t); } ///< cast to type uint16_t using "uint16_c(x)" @@ -127,7 +127,7 @@ inline void static_assert_int_t() { // unsigned integral type -typedef size_t uint_t; +using uint_t = size_t; static_assert( std::numeric_limits<uint_t>::is_specialized && std::numeric_limits<uint_t>::is_integer && @@ -144,7 +144,7 @@ inline void static_assert_uint_t() { // data structure specific data types -typedef int cell_idx_t; +using cell_idx_t = int; //typedef int64_t cell_idx_t; WALBERLA_STATIC_ASSERT( std::numeric_limits<cell_idx_t>::is_specialized && @@ -158,7 +158,7 @@ template< typename T > inline cell_idx_t cell_idx_c( T t ) { return numeric_cast // floating point type #ifdef WALBERLA_DOUBLE_ACCURACY -typedef double real_t; +using real_t = double; #else typedef float real_t; #endif diff --git a/src/core/OpenMP.h b/src/core/OpenMP.h index 67d32589a..b8ae3d607 100644 --- a/src/core/OpenMP.h +++ b/src/core/OpenMP.h @@ -48,12 +48,12 @@ namespace walberla { #define WALBERLA_OPENMP_FUNCTION_ERROR WALBERLA_ABORT( "Invalid OpenMP function call! In case of compiling without OpenMP, OpenMP functions are not available and shouldn't be called!" ); /* schedule kind constants */ -typedef enum omp_sched_t { +using omp_sched_t = enum omp_sched_t { omp_sched_static = 1, omp_sched_dynamic = 2, omp_sched_guided = 3, omp_sched_auto = 4 -} omp_sched_t; +}; /* set API functions */ inline void omp_set_num_threads (int) { WALBERLA_OPENMP_FUNCTION_ERROR } @@ -81,9 +81,9 @@ inline void omp_get_schedule (omp_sched_t *, int *) { WALBERLA_OPE inline int omp_get_max_task_priority (void) { WALBERLA_OPENMP_FUNCTION_ERROR } /* lock API functions */ -typedef struct omp_lock_t { +using omp_lock_t = struct omp_lock_t { void * _lk; -} omp_lock_t; +}; inline void omp_init_lock (omp_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } inline void omp_set_lock (omp_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } @@ -92,9 +92,9 @@ inline void omp_destroy_lock (omp_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR inline int omp_test_lock (omp_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } /* nested lock API functions */ -typedef struct omp_nest_lock_t { +using omp_nest_lock_t = struct omp_nest_lock_t { void * _lk; -} omp_nest_lock_t; +}; inline void omp_init_nest_lock (omp_nest_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } inline void omp_set_nest_lock (omp_nest_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } @@ -103,7 +103,7 @@ inline void omp_destroy_nest_lock (omp_nest_lock_t *) { WALBERLA_OPENMP_FUNCT inline int omp_test_nest_lock (omp_nest_lock_t *) { WALBERLA_OPENMP_FUNCTION_ERROR } /* lock hint type for dynamic user lock */ -typedef enum omp_lock_hint_t { +using omp_lock_hint_t = enum omp_lock_hint_t { omp_lock_hint_none = 0, omp_lock_hint_uncontended = 1, omp_lock_hint_contended = (1<<1 ), @@ -112,7 +112,7 @@ typedef enum omp_lock_hint_t { kmp_lock_hint_hle = (1<<16), kmp_lock_hint_rtm = (1<<17), kmp_lock_hint_adaptive = (1<<18) -} omp_lock_hint_t; +}; /* hinted lock initializers */ inline void omp_init_lock_with_hint(omp_lock_t *, omp_lock_hint_t) { WALBERLA_OPENMP_FUNCTION_ERROR } @@ -144,13 +144,13 @@ inline int omp_target_associate_ptr(void *, void *, size_t, size_t, int) { WA inline int omp_target_disassociate_ptr(void *, int) { WALBERLA_OPENMP_FUNCTION_ERROR } /* OpenMP 4.0 affinity API */ -typedef enum omp_proc_bind_t { +using omp_proc_bind_t = enum omp_proc_bind_t { omp_proc_bind_false = 0, omp_proc_bind_true = 1, omp_proc_bind_master = 2, omp_proc_bind_close = 3, omp_proc_bind_spread = 4 -} omp_proc_bind_t; +}; inline omp_proc_bind_t omp_get_proc_bind (void) { WALBERLA_OPENMP_FUNCTION_ERROR } diff --git a/src/core/Set.h b/src/core/Set.h index 7f094ad96..cbc0d5c11 100644 --- a/src/core/Set.h +++ b/src/core/Set.h @@ -85,9 +85,9 @@ template< typename T > class Set { public: - typedef typename std::set<T>::value_type value_type; - typedef typename std::set<T>::const_iterator const_iterator; - typedef typename std::set<T>::iterator iterator; + using value_type = typename std::set<T>::value_type; + using const_iterator = typename std::set<T>::const_iterator; + using iterator = typename std::set<T>::iterator; friend inline Set<T> operator&( const Set& a, const Set& b ) { return setIntersection(a,b); } ///< intersection friend inline Set<T> operator+( const Set& a, const Set& b ) { return setUnion (a,b); } ///< union diff --git a/src/core/VectorTrait.h b/src/core/VectorTrait.h index b050d159e..82d60ef0b 100644 --- a/src/core/VectorTrait.h +++ b/src/core/VectorTrait.h @@ -38,7 +38,7 @@ namespace walberla { template< typename T, class Enable = void > struct VectorTrait { - typedef void OutputType; + using OutputType = void; static const uint_t F_SIZE = 0u; }; @@ -46,7 +46,7 @@ struct VectorTrait template< typename T > struct VectorTrait<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 1u; static T get ( T value, uint_t /*f*/ ) { return value; } diff --git a/src/core/cell/CellInterval.h b/src/core/cell/CellInterval.h index 10f2529aa..4befe87c1 100644 --- a/src/core/cell/CellInterval.h +++ b/src/core/cell/CellInterval.h @@ -50,7 +50,7 @@ class CellIntervalIterator; class CellInterval { public: - typedef CellIntervalIterator const_iterator; + using const_iterator = CellIntervalIterator; CellInterval() : min_( cell_idx_c(0), cell_idx_c(0), cell_idx_c(0) ), max_( cell_idx_c(-1), cell_idx_c(-1), cell_idx_c(-1) ) {} CellInterval( const Cell& _min, const Cell& _max ) : min_( _min ), max_( _max ) {} @@ -132,11 +132,11 @@ inline bool CellInterval::positiveIndicesOnly() const { class CellIntervalIterator { public: - typedef std::bidirectional_iterator_tag iterator_category; - typedef Cell value_type; - typedef ptrdiff_t difference_type; - typedef Cell* pointer; - typedef Cell& reference; + using iterator_category = std::bidirectional_iterator_tag; + using value_type = Cell; + using difference_type = ptrdiff_t; + using pointer = Cell *; + using reference = Cell &; CellIntervalIterator( const CellInterval & ci, const Cell & cell ) : ci_(ci), cell_( cell ) { } diff --git a/src/core/cell/CellVector.h b/src/core/cell/CellVector.h index aa0fdefbd..c05474400 100644 --- a/src/core/cell/CellVector.h +++ b/src/core/cell/CellVector.h @@ -45,13 +45,13 @@ public: /*! \name Standard container typedefs */ //@{ - typedef std::vector<Cell>::iterator iterator; - typedef std::vector<Cell>::const_iterator const_iterator; - typedef std::vector<Cell>::size_type size_type; - typedef std::vector<Cell>::reference reference; - typedef std::vector<Cell>::const_reference const_reference; - typedef std::vector<Cell>::difference_type difference_type; - typedef Cell value_type; + using iterator = std::vector<Cell>::iterator; + using const_iterator = std::vector<Cell>::const_iterator; + using size_type = std::vector<Cell>::size_type; + using reference = std::vector<Cell>::reference; + using const_reference = std::vector<Cell>::const_reference; + using difference_type = std::vector<Cell>::difference_type; + using value_type = Cell; //@} /*! \name Constructors */ diff --git a/src/core/config/Config.h b/src/core/config/Config.h index 056661251..51d16fdee 100644 --- a/src/core/config/Config.h +++ b/src/core/config/Config.h @@ -88,16 +88,16 @@ public: private: //**Type definitions**************************************************************************** - typedef std::string Key; //!< Parameter key. - typedef std::string Value; //!< Parameter value. - typedef std::map<Key,Value, CaseInsensitiveCompare> Map; //!< Parameter map. - typedef std::list<Block> List; //!< List for parameter blocks. - typedef std::map<Value,Value> ValueReplacementMap; //!< Parameter value replacement map - - typedef std::stringstream::pos_type sstreamPos; //!< Stream position. - typedef std::pair<sstreamPos,unsigned int> Pair; //!< Pair consisting of a stream position + using Key = std::string; //!< Parameter key. + using Value = std::string; //!< Parameter value. + using Map = std::map<Key, Value, CaseInsensitiveCompare>; //!< Parameter map. + using List = std::list<Block>; //!< List for parameter blocks. + using ValueReplacementMap = std::map<Value, Value>; //!< Parameter value replacement map + + using sstreamPos = std::stringstream::pos_type; //!< Stream position. + using Pair = std::pair<sstreamPos, unsigned int>; //!< Pair consisting of a stream position //!< and a line number. - typedef std::vector<Pair> LineVector; //!< Vector for Pair. + using LineVector = std::vector<Pair>; //!< Vector for Pair. //******************************************************************************************************************* //**Member constants************************************************************************************************* @@ -106,11 +106,11 @@ private: public: //**Type definitions**************************************************************************** - typedef std::vector<BlockHandle> Blocks; //!< Container for block handles. - typedef List::size_type size_type; //!< Size type for a Block count. + using Blocks = std::vector<BlockHandle>; //!< Container for block handles. + using size_type = List::size_type; //!< Size type for a Block count. - typedef Map::iterator iterator; //!< Iterator over the contained parameters. - typedef Map::const_iterator const_iterator; //!< Constant iterator over the contained parameters. + using iterator = Map::iterator; //!< Iterator over the contained parameters. + using const_iterator = Map::const_iterator; //!< Constant iterator over the contained parameters. //******************************************************************************************************************* //**Error codes****************************************************************************************************** diff --git a/src/core/debug/CheckFunctions.impl.h b/src/core/debug/CheckFunctions.impl.h index e1932fdda..e4615bc0e 100644 --- a/src/core/debug/CheckFunctions.impl.h +++ b/src/core/debug/CheckFunctions.impl.h @@ -61,14 +61,14 @@ inline bool check_not_nullptr( const shared_ptr<T> & p ) template< typename T, typename U > inline bool check_equal( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_equal( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_equal( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) == static_cast<HighType>(rhs); } @@ -81,14 +81,14 @@ inline bool check_equal( const T & lhs, const U & rhs, const std::false_type & ) template< typename T, typename U > inline bool check_unequal( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_unequal( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_unequal( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) != static_cast<HighType>(rhs); } @@ -104,7 +104,7 @@ inline bool check_float_equal( const T & lhs, const U & rhs ) static_assert( std::is_floating_point<T>::value, "First operand type T is not a floating point type!"); static_assert( std::is_floating_point<U>::value, "Second operand type U is not a floating point type!"); - typedef typename math::MathTrait<T,U>::Low LowType; + using LowType = typename math::MathTrait<T, U>::Low; LowType low_lhs = static_cast<LowType>( lhs ); LowType low_rhs = static_cast<LowType>( rhs ); @@ -118,7 +118,7 @@ inline bool check_float_unequal( const T & lhs, const U & rhs ) static_assert( std::is_floating_point<T>::value, "First operand type T is not a floating point type!"); static_assert( std::is_floating_point<U>::value, "Second operand type U is not a floating point type!"); - typedef typename math::MathTrait<T,U>::Low LowType; + using LowType = typename math::MathTrait<T, U>::Low; LowType low_lhs = static_cast<LowType>( lhs ); LowType low_rhs = static_cast<LowType>( rhs ); @@ -133,7 +133,7 @@ inline bool check_float_equal_eps( const T & lhs, const U & rhs, static_assert( std::is_floating_point<T>::value, "First operand type T is not a floating point type!"); static_assert( std::is_floating_point<U>::value, "Second operand type U is not a floating point type!"); - typedef typename math::MathTrait<T,U>::Low LowType; + using LowType = typename math::MathTrait<T, U>::Low; LowType low_lhs = static_cast<LowType>( lhs ); LowType low_rhs = static_cast<LowType>( rhs ); @@ -148,7 +148,7 @@ inline bool check_float_unequal_eps( const T & lhs, const U & rhs, static_assert( std::is_floating_point<T>::value, "First operand type T is not a floating point type!"); static_assert( std::is_floating_point<U>::value, "Second operand type U is not a floating point type!"); - typedef typename math::MathTrait<T,U>::Low LowType; + using LowType = typename math::MathTrait<T, U>::Low; LowType low_lhs = static_cast<LowType>( lhs ); LowType low_rhs = static_cast<LowType>( rhs ); @@ -159,14 +159,14 @@ inline bool check_float_unequal_eps( const T & lhs, const U & rhs, template< typename T, typename U > inline bool check_identical( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_identical( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_identical( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return isIdentical( static_cast<HighType>(lhs), static_cast<HighType>(rhs) ); } @@ -179,14 +179,14 @@ inline bool check_identical( const T & lhs, const U & rhs, const std::false_type template< typename T, typename U > inline bool check_not_identical( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_not_identical( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_not_identical( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return !isIdentical( static_cast<HighType>(lhs), static_cast<HighType>(rhs) ); } @@ -199,14 +199,14 @@ inline bool check_not_identical( const T & lhs, const U & rhs, const std::false_ template< typename T, typename U > inline bool check_less( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_less( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_less( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) < static_cast<HighType>(rhs); } @@ -219,14 +219,14 @@ inline bool check_less( const T & lhs, const U & rhs, const std::false_type & ) template< typename T, typename U > inline bool check_greater( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_greater( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_greater( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) > static_cast<HighType>(rhs); } @@ -239,14 +239,14 @@ inline bool check_greater( const T & lhs, const U & rhs, const std::false_type & template< typename T, typename U > inline bool check_less_equal( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_less_equal( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_less_equal( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) <= static_cast<HighType>(rhs); } @@ -259,14 +259,14 @@ inline bool check_less_equal( const T & lhs, const U & rhs, const std::false_typ template< typename T, typename U > inline bool check_greater_equal( const T & lhs, const U & rhs ) { - typedef std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value> truth_type; + using truth_type = std::integral_constant<bool, std::is_arithmetic<T>::value && std::is_arithmetic<U>::value>; return check_greater_equal( lhs, rhs, truth_type() ); } template< typename T, typename U > inline bool check_greater_equal( const T & lhs, const U & rhs, const std::true_type & ) { - typedef typename math::MathTrait<T,U>::High HighType; + using HighType = typename math::MathTrait<T, U>::High; return static_cast<HighType>(lhs) >= static_cast<HighType>(rhs); } diff --git a/src/core/math/AABBFwd.h b/src/core/math/AABBFwd.h index 9a7593b67..3a51fbd44 100644 --- a/src/core/math/AABBFwd.h +++ b/src/core/math/AABBFwd.h @@ -30,7 +30,7 @@ namespace math { template< typename T > class GenericAABB; -typedef GenericAABB< real_t > AABB; /// see class GenericAABB +using AABB = GenericAABB<real_t>; /// see class GenericAABB } // namespace math diff --git a/src/core/math/GenericAABB.h b/src/core/math/GenericAABB.h index a6e18882a..5d326b5af 100644 --- a/src/core/math/GenericAABB.h +++ b/src/core/math/GenericAABB.h @@ -48,8 +48,8 @@ class GenericAABB public: // Typedefs - typedef T value_type; /// scalar data type - typedef Vector3< T > vector_type; /// data type for three dimensional vectors + using value_type = T; /// scalar data type + using vector_type = Vector3<T>; /// data type for three dimensional vectors // Constructors inline GenericAABB(); diff --git a/src/core/math/MathTrait.h b/src/core/math/MathTrait.h index 3f3332289..492badea4 100644 --- a/src/core/math/MathTrait.h +++ b/src/core/math/MathTrait.h @@ -195,19 +195,19 @@ struct INVALID_NUMERICAL_TYPE; template< typename T1, typename T2 > struct MathTrait { - typedef T1 HighType; - typedef T2 LowType; - typedef T1 High; - typedef T2 Low; + using HighType = T1; + using LowType = T2; + using High = T1; + using Low = T2; }; template< typename T> struct MathTrait< T, T > { - typedef T HighType; - typedef T LowType; - typedef T High; - typedef T Low; + using HighType = T; + using LowType = T; + using High = T; + using Low = T; }; diff --git a/src/core/math/Matrix2.h b/src/core/math/Matrix2.h index a9377506d..7132b05d0 100644 --- a/src/core/math/Matrix2.h +++ b/src/core/math/Matrix2.h @@ -987,7 +987,7 @@ namespace walberla { template<typename T> struct VectorTrait< Matrix2<T> > { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 4u; static T get( const Matrix2<T> & v, uint_t f ) { return v[f]; } diff --git a/src/core/math/Matrix3.h b/src/core/math/Matrix3.h index e8253b4ad..d6020cd53 100644 --- a/src/core/math/Matrix3.h +++ b/src/core/math/Matrix3.h @@ -1694,7 +1694,7 @@ namespace walberla { template<typename T> struct VectorTrait< Matrix3<T> > { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 9u; static T get( const Matrix3<T> & v, uint_t f ) { return v[f]; } diff --git a/src/core/math/MatrixMxN.h b/src/core/math/MatrixMxN.h index 1d633e74e..380baeb32 100644 --- a/src/core/math/MatrixMxN.h +++ b/src/core/math/MatrixMxN.h @@ -96,10 +96,10 @@ class MatrixMxN public: //**Type definitions**************************************************************************** - typedef MatrixMxN<Type> This; //!< Type of this MatrixMxN instance. - typedef This ResultType; //!< Result type for expression template evaluations. - typedef Type ElementType; //!< Type of the matrix elements. - typedef const MatrixMxN& CompositeType; //!< Data type for composite expression templates. + using This = MatrixMxN<Type>; //!< Type of this MatrixMxN instance. + using ResultType = This; //!< Result type for expression template evaluations. + using ElementType = Type; //!< Type of the matrix elements. + using CompositeType = const MatrixMxN &; //!< Data type for composite expression templates. //********************************************************************************************** //**Constructors******************************************************************************** diff --git a/src/core/math/Plane.h b/src/core/math/Plane.h index bab0ac1e8..219a13c39 100644 --- a/src/core/math/Plane.h +++ b/src/core/math/Plane.h @@ -33,7 +33,7 @@ namespace math { class Plane { public: - typedef Vector3<real_t> Vec3Real; + using Vec3Real = Vector3<real_t>; inline Plane(); inline Plane( const Vec3Real & origin, const Vec3Real & _normal ); diff --git a/src/core/math/Quaternion.h b/src/core/math/Quaternion.h index 9ca8c6f53..417e9b793 100644 --- a/src/core/math/Quaternion.h +++ b/src/core/math/Quaternion.h @@ -108,7 +108,7 @@ class Quaternion public: //**Type definitions**************************************************************************** - typedef Type ElementType; //!< Type of the quaternion elements. + using ElementType = Type; //!< Type of the quaternion elements. //********************************************************************************************** //**Constructors******************************************************************************** @@ -659,7 +659,7 @@ template< typename Other> // Data type of the vector inline const Vector3< typename MathTrait<Type,Other>::MultType > Quaternion<Type>::rotate( const Vector3<Other>& v ) const { - typedef typename MathTrait<Type,Other>::MultType MT; + using MT = typename MathTrait<Type, Other>::MultType; // Multiplication in two steps const MT w( v_[1]*v[0] + v_[2]*v[1] + v_[3]*v[2] ); @@ -701,7 +701,7 @@ template< typename Other > // Data type of the matrix inline const Matrix3< typename MathTrait<Type,Other>::MultType > Quaternion<Type>::rotate( const Matrix3<Other>& m ) const { - typedef typename MathTrait<Type,Other>::MultType MT; + using MT = typename MathTrait<Type, Other>::MultType; const Matrix3<MT> R( this->toRotationMatrix() ); return R.rotate( m ); } @@ -725,7 +725,7 @@ template< typename Other > // Data type of the diagonal matrix inline const Matrix3< typename MathTrait<Type,Other>::MultType > Quaternion<Type>::diagRotate( const Matrix3<Other>& m ) const { - typedef typename MathTrait<Type,Other>::MultType MT; + using MT = typename MathTrait<Type, Other>::MultType; const Matrix3<MT> R( this->toRotationMatrix() ); return R.diagRotate( m ); } @@ -743,7 +743,7 @@ template< typename Other > // Data type of the axis inline typename MathTrait<Type,Other>::HighType Quaternion<Type>::calcAngle( const Vector3<Other>& axis ) const { - typedef typename MathTrait<Type,Other>::HighType High; + using High = typename MathTrait<Type, Other>::HighType; const Vector3<High> u( v_[1], v_[2], v_[3] ); const High y ( u.length() ); @@ -1057,7 +1057,7 @@ template< typename T1 // Data type of the left-hand side quaternion inline const Quaternion< typename MathTrait<T1,T2>::MultType > operator*( const Quaternion<T1>& lhs, const Quaternion<T2>& rhs ) { - typedef typename MathTrait<T1,T2>::MultType MT; + using MT = typename MathTrait<T1, T2>::MultType; const MT r( lhs[0]*rhs[0] - lhs[1]*rhs[1] - lhs[2]*rhs[2] - lhs[3]*rhs[3] ); const MT i( lhs[0]*rhs[1] + lhs[1]*rhs[0] + lhs[2]*rhs[3] - lhs[3]*rhs[2] ); @@ -1137,7 +1137,7 @@ using math::Quaternion; template<typename T> struct VectorTrait< Quaternion<T> > { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 4u; static T get( const Quaternion<T> & v, uint_t f ) { return v[f]; } diff --git a/src/core/math/SqrtTrait.h b/src/core/math/SqrtTrait.h index 372eebae1..5712e65a0 100644 --- a/src/core/math/SqrtTrait.h +++ b/src/core/math/SqrtTrait.h @@ -64,7 +64,7 @@ namespace math { template< typename T > struct SqrtTrait { - typedef double Type; //!< Return type of std::sqrt for integral and double arguments. + using Type = double; //!< Return type of std::sqrt for integral and double arguments. }; //********************************************************************************************************************** @@ -77,7 +77,7 @@ struct SqrtTrait template<> struct SqrtTrait<float> { - typedef float Type; //!< Return type of std::sqrt for float arguments. + using Type = float; //!< Return type of std::sqrt for float arguments. }; /*! \endcond */ //********************************************************************************************************************** @@ -91,7 +91,7 @@ struct SqrtTrait<float> template<> struct SqrtTrait<long double> { - typedef long double Type; //!< Return type of std::sqrt for long double arguments. + using Type = long double; //!< Return type of std::sqrt for long double arguments. }; /*! \endcond */ //********************************************************************************************************************** diff --git a/src/core/math/Uint.h b/src/core/math/Uint.h index 3b0ab1721..c5fc28d83 100644 --- a/src/core/math/Uint.h +++ b/src/core/math/Uint.h @@ -194,10 +194,10 @@ template<> inline uint_t uintMSBPosition< uint8_t >( uint8_t value ) { } template< uint_t size > struct uintFromBitWidth; -template<> struct uintFromBitWidth< 8 > { typedef uint8_t type; }; -template<> struct uintFromBitWidth< 16 > { typedef uint16_t type; }; -template<> struct uintFromBitWidth< 32 > { typedef uint32_t type; }; -template<> struct uintFromBitWidth< 64 > { typedef uint64_t type; }; +template<> struct uintFromBitWidth< 8 > { using type = uint8_t; }; +template<> struct uintFromBitWidth< 16 > { using type = uint16_t; }; +template<> struct uintFromBitWidth< 32 > { using type = uint32_t; }; +template<> struct uintFromBitWidth< 64 > { using type = uint64_t; }; constexpr uint_t leastUnsignedIntegerBitWidth( uint_t width ) { @@ -218,7 +218,7 @@ constexpr uint_t leastUnsignedIntegerBitWidth( uint_t width ) template< uint_t minSize > struct leastUnsignedInteger { - typedef typename uintFromBitWidth< leastUnsignedIntegerBitWidth( minSize ) >::type type; + using type = typename uintFromBitWidth<leastUnsignedIntegerBitWidth(minSize)>::type; }; /// \cond internal diff --git a/src/core/math/Utility.h b/src/core/math/Utility.h index b71ea90e0..87300282b 100644 --- a/src/core/math/Utility.h +++ b/src/core/math/Utility.h @@ -346,7 +346,7 @@ inline bool equal_backend<long double>( long double a, long double b ) template< typename T1, typename T2 > inline bool equal( T1 a, T2 b ) { - typedef typename MathTrait<T1,T2>::High High; + using High = typename MathTrait<T1, T2>::High; return equal_backend<High>( a, b ); } //********************************************************************************************************************** diff --git a/src/core/math/Vector2.h b/src/core/math/Vector2.h index c69f7bcc7..00bfabe88 100644 --- a/src/core/math/Vector2.h +++ b/src/core/math/Vector2.h @@ -94,10 +94,10 @@ private: public: //**Type definitions**************************************************************************** - typedef typename SqrtTrait<Type>::Type Length; //!< Vector length return type. + using Length = typename SqrtTrait<Type>::Type; //!< Vector length return type. /*!< Return type of the Vector2<Type>::length function. */ - typedef Type value_type; + using value_type = Type; //******************************************************************************************************************* //**Constructors***************************************************************************************************** @@ -1670,7 +1670,7 @@ namespace walberla { template<typename T> struct VectorTrait< Vector2<T> > { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 2u; static T get( const Vector2<T> & v, uint_t f ) { return v[f]; } diff --git a/src/core/math/Vector3.h b/src/core/math/Vector3.h index 72b6a45fa..c47fd4a66 100644 --- a/src/core/math/Vector3.h +++ b/src/core/math/Vector3.h @@ -94,10 +94,10 @@ private: public: //**Type definitions**************************************************************************** - typedef typename SqrtTrait<Type>::Type Length; //!< Vector length return type. + using Length = typename SqrtTrait<Type>::Type; //!< Vector length return type. /*!< Return type of the Vector3<Type>::length function. */ - typedef Type value_type; + using value_type = Type; //******************************************************************************************************************* //**Constructors***************************************************************************************************** @@ -1926,7 +1926,7 @@ namespace walberla { template<typename T> struct VectorTrait< Vector3<T> > { - typedef T OutputType; + using OutputType = T; static const uint_t F_SIZE = 3u; static T get( const Vector3<T> & v, uint_t f ) { return v[f]; } diff --git a/src/core/math/equation_system/EquationSystem.h b/src/core/math/equation_system/EquationSystem.h index e78df0345..82d17a0f7 100644 --- a/src/core/math/equation_system/EquationSystem.h +++ b/src/core/math/equation_system/EquationSystem.h @@ -67,16 +67,16 @@ namespace math { // forward declaration of EquationParser class friend class EquationParser; - typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS> EqGraph; + using EqGraph = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>; - typedef std::map<std::string, EqGraph::vertex_descriptor> EqVertexMap; - typedef std::map<std::string, EqGraph::vertex_descriptor> VarVertexMap; + using EqVertexMap = std::map<std::string, EqGraph::vertex_descriptor>; + using VarVertexMap = std::map<std::string, EqGraph::vertex_descriptor>; - typedef std::map<std::string, EqGraph::vertex_descriptor>::const_iterator EqVertexMapIt; - typedef std::map<std::string, EqGraph::vertex_descriptor>::const_iterator VarVertexMapIt; + using EqVertexMapIt = std::map<std::string, EqGraph::vertex_descriptor>::const_iterator; + using VarVertexMapIt = std::map<std::string, EqGraph::vertex_descriptor>::const_iterator; - typedef std::map<std::string, EquationPtr> EqMap; - typedef std::map<std::string, EquationPtr>::const_iterator EqMapIt; + using EqMap = std::map<std::string, EquationPtr>; + using EqMapIt = std::map<std::string, EquationPtr>::const_iterator; EqMap eqMap_; EqGraph eqGraph_; @@ -121,7 +121,7 @@ namespace math { }; - typedef shared_ptr< EquationSystem > EquationSystemPtr; + using EquationSystemPtr = shared_ptr<EquationSystem>; } // namespace math } // namespace walberla diff --git a/src/core/math/equation_system/FwdEquation.h b/src/core/math/equation_system/FwdEquation.h index 37787456b..21fbb523c 100644 --- a/src/core/math/equation_system/FwdEquation.h +++ b/src/core/math/equation_system/FwdEquation.h @@ -41,13 +41,13 @@ namespace math { }; class Node; - typedef std::shared_ptr<Node> NodePtr; + using NodePtr = std::shared_ptr<Node>; ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // EQUATION ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// class Equation; - typedef std::shared_ptr< Equation > EquationPtr; + using EquationPtr = std::shared_ptr<Equation>; } // namespace math } // namespace walberla diff --git a/src/core/math/equation_system/FwdVariable.h b/src/core/math/equation_system/FwdVariable.h index 76715f973..bb9e8edf5 100644 --- a/src/core/math/equation_system/FwdVariable.h +++ b/src/core/math/equation_system/FwdVariable.h @@ -33,10 +33,10 @@ namespace math { class Var; - typedef std::shared_ptr<Var> VarPtr; + using VarPtr = std::shared_ptr<Var>; - typedef std::map<std::string, VarPtr> VarMap; - typedef std::map<std::string, VarPtr>::const_iterator VarMapIt; + using VarMap = std::map<std::string, VarPtr>; + using VarMapIt = std::map<std::string, VarPtr>::const_iterator; } // namespace math } // namespace walberla diff --git a/src/core/mpi/BufferDataTypeExtensions.h b/src/core/mpi/BufferDataTypeExtensions.h index 69f3e52e9..0af757246 100644 --- a/src/core/mpi/BufferDataTypeExtensions.h +++ b/src/core/mpi/BufferDataTypeExtensions.h @@ -266,7 +266,7 @@ template< typename T, // Element type of SendBuffer GenericSendBuffer<T,G>& packBoolVectorWithoutSize(GenericSendBuffer<T,G> & buf, const std::vector<bool> & bools ) { // Use an unsigned type at least as large as the SendBuffer base type as container for the bools - typedef typename math::leastUnsignedInteger< std::numeric_limits<T>::digits >::type ContainerType; + using ContainerType = typename math::leastUnsignedInteger<std::numeric_limits<T>::digits>::type; static const size_t NUM_BITS = std::numeric_limits<ContainerType>::digits; auto it = bools.begin(); @@ -287,7 +287,7 @@ template< typename T > // Element type of RecvBuffer GenericRecvBuffer<T>& unpackBoolVectorWithoutSize(GenericRecvBuffer<T> & buf, std::vector<bool> & bools, size_t size ) { // Use an unsigned type at least as large as the RecvBuffer base type as container for the bools - typedef typename math::leastUnsignedInteger<std::numeric_limits<T>::digits>::type ContainerType; + using ContainerType = typename math::leastUnsignedInteger<std::numeric_limits<T>::digits>::type; static const size_t NUM_BITS = std::numeric_limits<ContainerType>::digits; bools.resize(size); diff --git a/src/core/mpi/BufferSystem.h b/src/core/mpi/BufferSystem.h index ea1037b13..f2b0cbf43 100644 --- a/src/core/mpi/BufferSystem.h +++ b/src/core/mpi/BufferSystem.h @@ -211,7 +211,7 @@ public: //* Rank Ranges ************************************************************************************************* /*! \name Rank Ranges */ //@{ - typedef std::set<MPIRank> RankRange; + using RankRange = std::set<MPIRank>; static RankRange noRanks(); static RankRange allRanks(); static RankRange allRanksButRoot(); @@ -264,7 +264,7 @@ protected: int64_t numberOfReceives_ = 0; ///< number of communication partners during last receive }; -typedef GenericBufferSystem<RecvBuffer, SendBuffer> BufferSystem; +using BufferSystem = GenericBufferSystem<RecvBuffer, SendBuffer>; } // namespace mpi } // namespace walberla diff --git a/src/core/mpi/MPIWrapper.h b/src/core/mpi/MPIWrapper.h index 233baa6bb..cd250cb97 100644 --- a/src/core/mpi/MPIWrapper.h +++ b/src/core/mpi/MPIWrapper.h @@ -89,16 +89,16 @@ namespace walberla { namespace mpistubs { -typedef int MPI_Comm; -typedef int MPI_Datatype; -typedef int MPI_Group; -typedef int MPI_Op; -typedef int MPI_Request; -typedef int MPI_File; -typedef int MPI_Offset; -typedef int MPI_Info; -typedef int MPI_Aint; -typedef void (MPI_User_function) (void* a, void* b, int* len, MPI_Datatype*); +using MPI_Comm = int; +using MPI_Datatype = int; +using MPI_Group = int; +using MPI_Op = int; +using MPI_Request = int; +using MPI_File = int; +using MPI_Offset = int; +using MPI_Info = int; +using MPI_Aint = int; +using MPI_User_function = void (void *, void *, int *, MPI_Datatype *); struct MPI_Status { diff --git a/src/core/mpi/OpenMPBufferSystem.h b/src/core/mpi/OpenMPBufferSystem.h index 232f54f42..660a5cceb 100644 --- a/src/core/mpi/OpenMPBufferSystem.h +++ b/src/core/mpi/OpenMPBufferSystem.h @@ -100,7 +100,7 @@ private: void waitSerial(); }; -typedef GenericOpenMPBufferSystem<RecvBuffer, SendBuffer> OpenMPBufferSystem; +using OpenMPBufferSystem = GenericOpenMPBufferSystem<RecvBuffer, SendBuffer>; } // namespace mpi diff --git a/src/core/mpi/RecvBuffer.h b/src/core/mpi/RecvBuffer.h index b3dacb3db..0b3df4abf 100644 --- a/src/core/mpi/RecvBuffer.h +++ b/src/core/mpi/RecvBuffer.h @@ -81,7 +81,7 @@ class GenericRecvBuffer { public: //**Type definitions************************************************************************************************* - typedef T ElementType; //!< Type of the receive buffer elements. + using ElementType = T; //!< Type of the receive buffer elements. //******************************************************************************************************************* //**Constructors***************************************************************************************************** @@ -173,7 +173,7 @@ private: }; //********************************************************************************************************************** -typedef GenericRecvBuffer<> RecvBuffer; +using RecvBuffer = GenericRecvBuffer<>; diff --git a/src/core/mpi/SendBuffer.h b/src/core/mpi/SendBuffer.h index 60d8e471f..3fac958a7 100644 --- a/src/core/mpi/SendBuffer.h +++ b/src/core/mpi/SendBuffer.h @@ -87,7 +87,7 @@ public: { public: static_assert( std::is_fundamental<VT>::value, "only fundamental data types are allowed"); - typedef VT value_type; + using value_type = VT; Ptr(GenericSendBuffer<T, G>& buffer, const std::ptrdiff_t offset, const size_t length) : buffer_(buffer), offset_(offset), length_(length) {} @@ -102,7 +102,7 @@ public: }; //**Type definitions************************************************************************************************* - typedef T ElementType; //!< Type of the receive buffer elements. + using ElementType = T; //!< Type of the receive buffer elements. //******************************************************************************************************************* //**Constructors***************************************************************************************************** @@ -216,7 +216,7 @@ private: }; //********************************************************************************************************************** -typedef GenericSendBuffer<> SendBuffer; +using SendBuffer = GenericSendBuffer<>; //====================================================================================================================== diff --git a/src/core/timing/Timer.h b/src/core/timing/Timer.h index f25602bfa..15a963265 100644 --- a/src/core/timing/Timer.h +++ b/src/core/timing/Timer.h @@ -105,7 +105,7 @@ class Timer friend mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, Timer<TP2> & t ); public: //**Type definitions************************************************************************************************* - typedef TP TimingPolicy; //!< Timing policy of the Timer. + using TimingPolicy = TP; //!< Timing policy of the Timer. //******************************************************************************************************************* //**Constructor****************************************************************************************************** @@ -589,7 +589,7 @@ mpi::GenericRecvBuffer<T>& operator>>( mpi::GenericRecvBuffer<T> & buf, Timer<TP } //namespace timing -typedef timing::Timer<timing::CpuPolicy> CpuTimer; -typedef timing::Timer<timing::WcPolicy> WcTimer; +using CpuTimer = timing::Timer<timing::CpuPolicy>; +using WcTimer = timing::Timer<timing::WcPolicy>; } // namespace walberla diff --git a/src/core/timing/TimingNode.h b/src/core/timing/TimingNode.h index a99dfe05b..6682ab626 100644 --- a/src/core/timing/TimingNode.h +++ b/src/core/timing/TimingNode.h @@ -493,7 +493,7 @@ void addRemainderNodes(timing::TimingNode<TP> &tn) { } /// namespace internal } -typedef timing::TimingNode<timing::WcPolicy> WcTimingNode; -typedef timing::TimingNode<timing::CpuPolicy> CpuTimingNode; +using WcTimingNode = timing::TimingNode<timing::WcPolicy>; +using CpuTimingNode = timing::TimingNode<timing::CpuPolicy>; } diff --git a/src/core/timing/TimingPool.h b/src/core/timing/TimingPool.h index b927151ac..5e41c14d7 100644 --- a/src/core/timing/TimingPool.h +++ b/src/core/timing/TimingPool.h @@ -70,8 +70,8 @@ public: //** Access to Timer Objects **************************************************************************************** /*! \name Access to Timer Objects */ //@{ - typedef typename std::map<std::string, Timer<TP> >::iterator iterator; - typedef typename std::map<std::string, Timer<TP> >::const_iterator const_iterator; + using iterator = typename std::map<std::string, Timer<TP>>::iterator; + using const_iterator = typename std::map<std::string, Timer<TP>>::const_iterator; iterator begin() { return timerMap_.begin(); } const_iterator begin() const { return timerMap_.begin(); } @@ -248,6 +248,6 @@ namespace timing { //====================================================================================================================== namespace walberla { - typedef timing::TimingPool<timing::WcPolicy> WcTimingPool; - typedef timing::TimingPool<timing::CpuPolicy> CpuTimingPool; + using WcTimingPool = timing::TimingPool<timing::WcPolicy>; + using CpuTimingPool = timing::TimingPool<timing::CpuPolicy>; } diff --git a/src/core/timing/TimingTree.h b/src/core/timing/TimingTree.h index 7fe833b1e..e7fcda960 100644 --- a/src/core/timing/TimingTree.h +++ b/src/core/timing/TimingTree.h @@ -251,6 +251,6 @@ TimingTree< TP > TimingTree< TP >::getCopyWithRemainder() const } -typedef timing::TimingTree<timing::WcPolicy> WcTimingTree; -typedef timing::TimingTree<timing::CpuPolicy> CpuTimingTree; +using WcTimingTree = timing::TimingTree<timing::WcPolicy>; +using CpuTimingTree = timing::TimingTree<timing::CpuPolicy>; } diff --git a/src/core/uid/SUID.h b/src/core/uid/SUID.h index 329abb0fa..21b48ca26 100644 --- a/src/core/uid/SUID.h +++ b/src/core/uid/SUID.h @@ -33,7 +33,7 @@ namespace uid { namespace suidgenerator { class S : public IndexGenerator< S, size_t >{}; ///< generator class for unified state/selection UIDs } -typedef UID< suidgenerator::S > SUID; ///< unified state/selection UID +using SUID = UID<suidgenerator::S>; ///< unified state/selection UID } // namespace uid diff --git a/src/core/uid/UID.h b/src/core/uid/UID.h index f90f7f9de..89a270e4c 100644 --- a/src/core/uid/UID.h +++ b/src/core/uid/UID.h @@ -74,7 +74,7 @@ template< typename T > class UID { public: - typedef typename T::uint_type uint_type; + using uint_type = typename T::uint_type; inline UID( const char* const identifier, const bool newUid = false, const bool appendUIDtoIdentifier = false ); diff --git a/src/core/uid/UIDGenerators.h b/src/core/uid/UIDGenerators.h index 0e913b16a..4d4a333f9 100644 --- a/src/core/uid/UIDGenerators.h +++ b/src/core/uid/UIDGenerators.h @@ -87,8 +87,8 @@ template< typename T, typename UINT > class IndexGenerator { public: - typedef UINT uint_type; - typedef index_generated_tag generator_type; + using uint_type = UINT; + using generator_type = index_generated_tag; static uint_type generateUID() { static uint_type uid(0); @@ -123,8 +123,8 @@ template< typename T, typename UINT > class StandardGenerator { public: - typedef UINT uint_type; - typedef standard_generated_tag generator_type; + using uint_type = UINT; + using generator_type = standard_generated_tag; static uint_type generateUID() { static uint_type uid(0); @@ -216,8 +216,8 @@ template< typename T, typename UINT > class BitGenerator { public: - typedef UINT uint_type; - typedef bit_generated_tag generator_type; + using uint_type = UINT; + using generator_type = bit_generated_tag; static uint_type generateUID() { static uint_type uid(1); @@ -262,8 +262,8 @@ template< typename T, typename UINT > class SingletonGenerator { public: - typedef UINT uint_type; - typedef singleton_generated_tag generator_type; + using uint_type = UINT; + using generator_type = singleton_generated_tag; static uint_type generateUID() { static uint_type uid(0); diff --git a/src/domain_decomposition/BlockDataHandling.h b/src/domain_decomposition/BlockDataHandling.h index 4b07594e0..0720eb572 100644 --- a/src/domain_decomposition/BlockDataHandling.h +++ b/src/domain_decomposition/BlockDataHandling.h @@ -45,7 +45,7 @@ template< typename T > class BlockDataHandling { public: - typedef T value_type; + using value_type = T; virtual ~BlockDataHandling() = default; @@ -82,7 +82,7 @@ class BlockDataHandlingFunctionAdaptor : public BlockDataHandling<T> { public: - typedef std::function< T* ( IBlock * const block ) > Function; + using Function = std::function<T *(IBlock *const)>; BlockDataHandlingFunctionAdaptor( const Function & function ) : function_( function ) {} @@ -206,7 +206,7 @@ private: -typedef selectable::SetSelectableObject< shared_ptr< BlockDataHandlingWrapper >, SUID > SelectableBlockDataHandlingWrapper; +using SelectableBlockDataHandlingWrapper = selectable::SetSelectableObject<shared_ptr<BlockDataHandlingWrapper>, SUID>; diff --git a/src/domain_decomposition/BlockStorage.h b/src/domain_decomposition/BlockStorage.h index 0d6dfc6c1..b59f7b30f 100644 --- a/src/domain_decomposition/BlockStorage.h +++ b/src/domain_decomposition/BlockStorage.h @@ -73,7 +73,7 @@ class BlockStorage : private NonCopyable { public: - typedef std::map< IBlockID::IDType, IBlock* > BlockContainerType ; + using BlockContainerType = std::map<IBlockID::IDType, IBlock *> ; class const_iterator; diff --git a/src/domain_decomposition/IBlock.h b/src/domain_decomposition/IBlock.h index 27c0b894f..06e48b690 100644 --- a/src/domain_decomposition/IBlock.h +++ b/src/domain_decomposition/IBlock.h @@ -207,7 +207,7 @@ class IBlock : private NonCopyable { public: - typedef internal::BlockData BlockData; + using BlockData = internal::BlockData; friend class BlockStorage; friend class StructuredBlockStorage; diff --git a/src/domain_decomposition/IBlockID.h b/src/domain_decomposition/IBlockID.h index e73a50101..5e1cb771d 100644 --- a/src/domain_decomposition/IBlockID.h +++ b/src/domain_decomposition/IBlockID.h @@ -44,7 +44,7 @@ class IBlockID { public: /// ID type which can be used as a key in a map - typedef uint64_t IDType; + using IDType = uint64_t; virtual ~IBlockID() = default; diff --git a/src/domain_decomposition/StructuredBlockStorage.h b/src/domain_decomposition/StructuredBlockStorage.h index 8a44ebfd8..574634255 100644 --- a/src/domain_decomposition/StructuredBlockStorage.h +++ b/src/domain_decomposition/StructuredBlockStorage.h @@ -121,8 +121,8 @@ public: internal::SelectableBlockDataHandlingWrapper dataHandling_; }; - typedef BlockStorage::const_iterator const_iterator; - typedef BlockStorage::iterator iterator; + using const_iterator = BlockStorage::const_iterator; + using iterator = BlockStorage::iterator; const BlockStorage& getBlockStorage() const { return *blockStorage_; } BlockStorage& getBlockStorage() { return *blockStorage_; } diff --git a/src/fft/Fft.h b/src/fft/Fft.h index 5e4372b1c..e3219e461 100644 --- a/src/fft/Fft.h +++ b/src/fft/Fft.h @@ -35,7 +35,7 @@ class FourierTransform typedef std::unique_ptr<pfft_complex[], std::function<void(pfft_complex*)> > FFTComplex; typedef std::unique_ptr<std::remove_pointer<pfft_plan>::type, std::function<void(pfft_plan)> > FFTPlan; #else - typedef std::unique_ptr<double[], std::function<void(double*)> > FFTReal; + using FFTReal = std::unique_ptr<double [], std::function<void (double *)>>; typedef std::unique_ptr<fftw_complex[], std::function<void(fftw_complex*)> > FFTComplex; typedef std::unique_ptr<std::remove_pointer<fftw_plan>::type, std::function<void(fftw_plan)> > FFTPlan; #endif diff --git a/src/field/AccuracyEvaluation.h b/src/field/AccuracyEvaluation.h index 036803b43..77fd10c4d 100644 --- a/src/field/AccuracyEvaluation.h +++ b/src/field/AccuracyEvaluation.h @@ -332,7 +332,7 @@ shared_ptr< AccuracyEvaluation< Field_T, SolutionFunction_T > > makeAccuracyEval const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluation< Field_T, SolutionFunction_T > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, plotFrequency, logFrequency, requiredSelectors, incompatibleSelectors ) ); } @@ -345,7 +345,7 @@ makeAccuracyEvaluation( const weak_ptr< StructuredBlockStorage > & blocks, const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluation< Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T> > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T>>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), plotFrequency, logFrequency, requiredSelectors, incompatibleSelectors ) ); } @@ -358,7 +358,7 @@ makeAccuracyEvaluation( const weak_ptr< StructuredBlockStorage > & blocks, const const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluation< Field_T, SolutionFunction_T, Filter_T > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T, Filter_T>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, filter, plotFrequency, logFrequency, requiredSelectors, incompatibleSelectors ) ); } @@ -419,7 +419,7 @@ shared_ptr< AccuracyEvaluation< Field_T, SolutionFunction_T > > makeAccuracyEval const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_CONFIG_PARSER( config ) - typedef AccuracyEvaluation< Field_T, SolutionFunction_T > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, defaultPlotFrequency, defaultLogFrequency, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_SET_AND_RETURN() } @@ -435,7 +435,7 @@ makeAccuracyEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_CONFIG_PARSER( config ) - typedef AccuracyEvaluation< Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T> > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), defaultPlotFrequency, defaultLogFrequency, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_SET_AND_RETURN() @@ -451,7 +451,7 @@ makeAccuracyEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_CONFIG_PARSER( config ) - typedef AccuracyEvaluation< Field_T, SolutionFunction_T, Filter_T > AE_T; + using AE_T = AccuracyEvaluation<Field_T, SolutionFunction_T, Filter_T>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, filter, defaultPlotFrequency, defaultLogFrequency, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_SET_AND_RETURN() diff --git a/src/field/AccuracyEvaluationLinePlot.h b/src/field/AccuracyEvaluationLinePlot.h index 51a18da51..a0c221860 100644 --- a/src/field/AccuracyEvaluationLinePlot.h +++ b/src/field/AccuracyEvaluationLinePlot.h @@ -356,7 +356,7 @@ void AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T, Filter_T >::operat WALBERLA_ROOT_SECTION() { - typedef typename Field_T::value_type Value_T; + using Value_T = typename Field_T::value_type; std::vector< internal::AccuracyEvaluationPlotData<Value_T> > points; while( !buffer.isEmpty() ) @@ -398,7 +398,7 @@ shared_ptr< AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T > > makeAccu const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, yAxis, requiredSelectors, incompatibleSelectors ) ); } @@ -411,7 +411,7 @@ makeAccuracyEvaluationLinePlot( const weak_ptr< StructuredBlockStorage > & block const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T> > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T>>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), yAxis, requiredSelectors, incompatibleSelectors ) ); } @@ -424,7 +424,7 @@ makeAccuracyEvaluationLinePlot( const weak_ptr< StructuredBlockStorage > & block const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T, Filter_T > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T, Filter_T>; return shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, filter, yAxis, requiredSelectors, incompatibleSelectors ) ); } @@ -491,7 +491,7 @@ makeAccuracyEvaluationLinePlot( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_CONFIG_PARSER( config ) - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, defaultYAxis, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_SET_AND_RETURN() } @@ -507,7 +507,7 @@ makeAccuracyEvaluationLinePlot( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_CONFIG_PARSER( config ) - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T> > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T, FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), defaultYAxis, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_SET_AND_RETURN() @@ -523,7 +523,7 @@ makeAccuracyEvaluationLinePlot( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_CONFIG_PARSER( config ) - typedef AccuracyEvaluationLinePlot< Field_T, SolutionFunction_T, Filter_T > AE_T; + using AE_T = AccuracyEvaluationLinePlot<Field_T, SolutionFunction_T, Filter_T>; auto evaluation = shared_ptr< AE_T >( new AE_T( blocks, fieldId, solution, filter, defaultYAxis, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_ACCURACY_EVALUATION_LINE_PLOT_SET_AND_RETURN() } @@ -642,7 +642,7 @@ makeAccuracyEvaluationLinePlotter( const shared_ptr< AccuracyEvaluationLinePlot_ const std::string & filename = internal::accuracyEvaluationLinePlotterFilename, const std::string & fileExtension = internal::accuracyEvaluationLinePlotterExtension ) { - typedef AccuracyEvaluationLinePlotter< AccuracyEvaluationLinePlot_T > AE_T; + using AE_T = AccuracyEvaluationLinePlotter<AccuracyEvaluationLinePlot_T>; return shared_ptr< AE_T >( new AE_T( plot, evaluationFrequency, filename, fileExtension ) ); } @@ -686,7 +686,7 @@ makeAccuracyEvaluationLinePlotter( const Config_T & config, std::string defaultFilename( internal::accuracyEvaluationLinePlotterFilename ); std::string defaultFileExtension( internal::accuracyEvaluationLinePlotterExtension ); internal::accuracyEvaluationLinePlotterConfigParser( config, configBlockName, defaultEvaluationFrequency, defaultFilename, defaultFileExtension ); - typedef AccuracyEvaluationLinePlotter< AccuracyEvaluationLinePlot_T > AE_T; + using AE_T = AccuracyEvaluationLinePlotter<AccuracyEvaluationLinePlot_T>; return shared_ptr< AE_T >( new AE_T( plot, defaultEvaluationFrequency, defaultFilename, defaultFileExtension ) ); } diff --git a/src/field/Field.h b/src/field/Field.h index 7b3103b80..a47fe47e7 100644 --- a/src/field/Field.h +++ b/src/field/Field.h @@ -72,24 +72,21 @@ namespace field { //** Type Definitions ******************************************************************************************* /*! \name Type Definitions */ //@{ - typedef T value_type; + using value_type = T; - typedef ForwardFieldIterator<T,fSize_> iterator; - typedef ForwardFieldIterator<const T,fSize_> const_iterator; + using iterator = ForwardFieldIterator<T, fSize_>; + using const_iterator = ForwardFieldIterator<const T, fSize_>; - typedef ReverseFieldIterator<T,fSize_> reverse_iterator; - typedef ReverseFieldIterator<const T,fSize_> const_reverse_iterator; + using reverse_iterator = ReverseFieldIterator<T, fSize_>; + using const_reverse_iterator = ReverseFieldIterator<const T, fSize_>; - typedef FieldIterator<T,fSize_ > base_iterator; - typedef FieldIterator<const T,fSize_ > const_base_iterator; + using base_iterator = FieldIterator<T, fSize_>; + using const_base_iterator = FieldIterator<const T, fSize_>; - typedef FieldPointer<Field<T,fSize_>, Field<T,fSize_>, T > Ptr; - typedef FieldPointer<Field<T,fSize_>, const Field<T,fSize_>, const T > ConstPtr; + using Ptr = FieldPointer<Field<T, fSize_>, Field<T, fSize_>, T>; + using ConstPtr = FieldPointer<Field<T, fSize_>, const Field<T, fSize_>, const T>; - typedef typename std::conditional<VectorTrait<T>::F_SIZE!=0, - Field<typename VectorTrait<T>::OutputType, VectorTrait<T>::F_SIZE*fSize_>, - Field<T, fSize_> - >::type FlattenedField; + using FlattenedField = typename std::conditional<VectorTrait<T>::F_SIZE != 0, Field<typename VectorTrait<T>::OutputType, VectorTrait<T>::F_SIZE * fSize_>, Field<T, fSize_>>::type; static const uint_t F_SIZE = fSize_; //@} @@ -283,8 +280,7 @@ namespace field { //** Monitoring ************************************************************************************************* /*! \name Monitoring */ //@{ - typedef std::function< void ( cell_idx_t x, cell_idx_t y, - cell_idx_t z, cell_idx_t f, const T & value) > MonitorFunction; + using MonitorFunction = std::function<void (cell_idx_t, cell_idx_t, cell_idx_t, cell_idx_t, const T &)>; void addMonitoringFunction( const MonitorFunction & func ); //@} diff --git a/src/field/FlagField.h b/src/field/FlagField.h index ebf17fb39..a2333770d 100644 --- a/src/field/FlagField.h +++ b/src/field/FlagField.h @@ -86,21 +86,21 @@ public: //** Type Definitions ********************************************************************************************** /*! \name Type Definitions */ //@{ - typedef T flag_t; + using flag_t = T; - typedef typename GhostLayerField<T,1>::value_type value_type; + using value_type = typename GhostLayerField<T, 1>::value_type; - typedef typename GhostLayerField<T,1>::iterator iterator; - typedef typename GhostLayerField<T,1>::const_iterator const_iterator; + using iterator = typename GhostLayerField<T, 1>::iterator; + using const_iterator = typename GhostLayerField<T, 1>::const_iterator; - typedef typename GhostLayerField<T,1>::reverse_iterator reverse_iterator; - typedef typename GhostLayerField<T,1>::const_reverse_iterator const_reverse_iterator; + using reverse_iterator = typename GhostLayerField<T, 1>::reverse_iterator; + using const_reverse_iterator = typename GhostLayerField<T, 1>::const_reverse_iterator; - typedef typename Field<T,1>::base_iterator base_iterator; - typedef typename Field<T,1>::const_base_iterator const_base_iterator; + using base_iterator = typename Field<T, 1>::base_iterator; + using const_base_iterator = typename Field<T, 1>::const_base_iterator; - typedef typename GhostLayerField<T,1>::Ptr Ptr; - typedef typename GhostLayerField<T,1>::ConstPtr ConstPtr; + using Ptr = typename GhostLayerField<T, 1>::Ptr; + using ConstPtr = typename GhostLayerField<T, 1>::ConstPtr; //@} //******************************************************************************************************************* @@ -123,7 +123,7 @@ public: //** Access Functions *********************************************************************************************** /*! \name Access Functions */ //@{ - typedef cell_idx_t idx; + using idx = cell_idx_t; void addMask (idx x, idx y, idx z, flag_t m) { WALBERLA_ASSERT(isRegistered(m)); field::addMask( this->get(x,y,z), m ); } void addFlag (idx x, idx y, idx z, flag_t f) { WALBERLA_ASSERT(isRegistered(f)); field::addFlag( this->get(x,y,z), f ); } diff --git a/src/field/FlagField.impl.h b/src/field/FlagField.impl.h index bc2c5e950..4e32e312c 100644 --- a/src/field/FlagField.impl.h +++ b/src/field/FlagField.impl.h @@ -489,7 +489,7 @@ namespace field { template<class Sten, typename FieldPtrOrIterator> inline bool isFlagInNeighborhood(const FieldPtrOrIterator & i, typename FieldPtrOrIterator::value_type mask) { - typedef typename std::remove_const< typename FieldPtrOrIterator::value_type >::type T; + using T = typename std::remove_const<typename FieldPtrOrIterator::value_type>::type; static_assert( (std::is_same< T,uint8_t >::value || std::is_same< T,uint16_t>::value || @@ -512,7 +512,7 @@ namespace field { inline typename std::remove_const<typename FieldPtrOrIterator::value_type>::type getOredNeighborhood(const FieldPtrOrIterator & i) { - typedef typename std::remove_const<typename FieldPtrOrIterator::value_type>::type RetType; + using RetType = typename std::remove_const<typename FieldPtrOrIterator::value_type>::type; RetType flag = 0; for( auto d = Sten::beginNoCenter(); d != Sten::end(); ++d ) { diff --git a/src/field/FlagUID.h b/src/field/FlagUID.h index 3e97fac54..116cb21d0 100644 --- a/src/field/FlagUID.h +++ b/src/field/FlagUID.h @@ -30,7 +30,7 @@ namespace field { ///\cond internal class FlagUIDGenerator : public uid::IndexGenerator< FlagUIDGenerator, uint_t >{}; -typedef UID< FlagUIDGenerator > FlagUID; +using FlagUID = UID<FlagUIDGenerator>; ///\endcond } // namespace field diff --git a/src/field/GhostLayerField.h b/src/field/GhostLayerField.h index 9a1a57704..381a06ccd 100644 --- a/src/field/GhostLayerField.h +++ b/src/field/GhostLayerField.h @@ -53,24 +53,21 @@ namespace field { //** Type Definitions ******************************************************************************************* /*! \name Type Definitions */ //@{ - typedef typename Field<T,fSize_>::value_type value_type; + using value_type = typename Field<T, fSize_>::value_type; - typedef typename Field<T,fSize_>::iterator iterator; - typedef typename Field<T,fSize_>::const_iterator const_iterator; + using iterator = typename Field<T, fSize_>::iterator; + using const_iterator = typename Field<T, fSize_>::const_iterator; - typedef typename Field<T,fSize_>::reverse_iterator reverse_iterator; - typedef typename Field<T,fSize_>::const_reverse_iterator const_reverse_iterator; + using reverse_iterator = typename Field<T, fSize_>::reverse_iterator; + using const_reverse_iterator = typename Field<T, fSize_>::const_reverse_iterator; - typedef typename Field<T,fSize_>::base_iterator base_iterator; - typedef typename Field<T,fSize_>::const_base_iterator const_base_iterator; + using base_iterator = typename Field<T, fSize_>::base_iterator; + using const_base_iterator = typename Field<T, fSize_>::const_base_iterator; - typedef typename Field<T,fSize_>::Ptr Ptr; - typedef typename Field<T,fSize_>::ConstPtr ConstPtr; + using Ptr = typename Field<T, fSize_>::Ptr; + using ConstPtr = typename Field<T, fSize_>::ConstPtr; - typedef typename std::conditional<VectorTrait<T>::F_SIZE!=0, - GhostLayerField<typename VectorTrait<T>::OutputType, VectorTrait<T>::F_SIZE*fSize_>, - GhostLayerField<T, fSize_> - >::type FlattenedField; + using FlattenedField = typename std::conditional<VectorTrait<T>::F_SIZE != 0, GhostLayerField<typename VectorTrait<T>::OutputType, VectorTrait<T>::F_SIZE * fSize_>, GhostLayerField<T, fSize_>>::type; //@} //**************************************************************************************************************** diff --git a/src/field/MassEvaluation.h b/src/field/MassEvaluation.h index a6aebf96f..0b9ec26a4 100644 --- a/src/field/MassEvaluation.h +++ b/src/field/MassEvaluation.h @@ -297,7 +297,7 @@ shared_ptr< MassEvaluation< DensityField_T > > makeMassEvaluation( const weak_pt const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef MassEvaluation< DensityField_T > ME_T; + using ME_T = MassEvaluation<DensityField_T>; return shared_ptr< ME_T >( new ME_T( blocks, fieldId, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); } @@ -310,7 +310,7 @@ makeMassEvaluation( const weak_ptr< StructuredBlockStorage > & blocks, const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef MassEvaluation< DensityField_T, FlagFieldEvaluationFilter<FlagField_T> > ME_T; + using ME_T = MassEvaluation<DensityField_T, FlagFieldEvaluationFilter<FlagField_T>>; return shared_ptr< ME_T >( new ME_T( blocks, fieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); } @@ -323,7 +323,7 @@ shared_ptr< MassEvaluation< DensityField_T, Filter_T > > makeMassEvaluation( con const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef MassEvaluation< DensityField_T, Filter_T > ME_T; + using ME_T = MassEvaluation<DensityField_T, Filter_T>; return shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); } @@ -385,7 +385,7 @@ shared_ptr< MassEvaluation< DensityField_T > > makeMassEvaluation( const Config_ const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef MassEvaluation< DensityField_T > ME_T; + using ME_T = MassEvaluation<DensityField_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() @@ -401,7 +401,7 @@ makeMassEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef MassEvaluation< DensityField_T, FlagFieldEvaluationFilter<FlagField_T> > ME_T; + using ME_T = MassEvaluation<DensityField_T, FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() @@ -416,7 +416,7 @@ shared_ptr< MassEvaluation< DensityField_T, Filter_T > > makeMassEvaluation( con const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef MassEvaluation< DensityField_T, Filter_T > ME_T; + using ME_T = MassEvaluation<DensityField_T, Filter_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() diff --git a/src/field/StabilityChecker.h b/src/field/StabilityChecker.h index 85a29e725..fbbc530e7 100644 --- a/src/field/StabilityChecker.h +++ b/src/field/StabilityChecker.h @@ -138,7 +138,7 @@ class StabilityChecker { private: - typedef std::map< const IBlock *, std::map< Cell, std::set< cell_idx_t > > > BlockCellsMap; + using BlockCellsMap = std::map<const IBlock *, std::map<Cell, std::set<cell_idx_t>>>; //////////////////////////////// // VTK Output Helper Classes // @@ -510,7 +510,7 @@ shared_ptr< StabilityChecker< Field_T > > makeStabilityChecker( const weak_ptr< const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef StabilityChecker< Field_T > SC_T; + using SC_T = StabilityChecker<Field_T>; return shared_ptr< SC_T >( new SC_T( blocks, fieldId, checkFrequency, outputToStream, outputVTK, requiredSelectors, incompatibleSelectors ) ); } @@ -523,7 +523,7 @@ makeStabilityChecker( const weak_ptr< StructuredBlockStorage > & blocks, const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef StabilityChecker< Field_T, FlagFieldEvaluationFilter<FlagField_T> > SC_T; + using SC_T = StabilityChecker<Field_T, FlagFieldEvaluationFilter<FlagField_T>>; return shared_ptr< SC_T >( new SC_T( blocks, fieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), checkFrequency, outputToStream, outputVTK, requiredSelectors, incompatibleSelectors ) ); } @@ -536,7 +536,7 @@ makeStabilityChecker( const weak_ptr< StructuredBlockStorage > & blocks, const C const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef StabilityChecker< Field_T, Filter_T > SC_T; + using SC_T = StabilityChecker<Field_T, Filter_T>; return shared_ptr< SC_T >( new SC_T( blocks, fieldId, filter, checkFrequency, outputToStream, outputVTK, requiredSelectors, incompatibleSelectors ) ); } @@ -618,7 +618,7 @@ shared_ptr< StabilityChecker< Field_T > > makeStabilityChecker( const Config_T & const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_STABILITY_CHECKER_CONFIG_PARSER( config ) - typedef StabilityChecker< Field_T > SC_T; + using SC_T = StabilityChecker<Field_T>; auto checker = shared_ptr< SC_T >( new SC_T( blocks, fieldId, defaultCheckFrequency, defaultOutputToStream, defaultOutputVTK, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_STABILITY_CHECKER_SET_AND_RETURN() } @@ -633,7 +633,7 @@ makeStabilityChecker( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_STABILITY_CHECKER_CONFIG_PARSER( config ) - typedef StabilityChecker< Field_T, FlagFieldEvaluationFilter<FlagField_T> > SC_T; + using SC_T = StabilityChecker<Field_T, FlagFieldEvaluationFilter<FlagField_T>>; auto checker = shared_ptr< SC_T >( new SC_T( blocks, fieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), defaultCheckFrequency, defaultOutputToStream, defaultOutputVTK, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_STABILITY_CHECKER_SET_AND_RETURN() @@ -648,7 +648,7 @@ makeStabilityChecker( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_STABILITY_CHECKER_CONFIG_PARSER( config ) - typedef StabilityChecker< Field_T, Filter_T > SC_T; + using SC_T = StabilityChecker<Field_T, Filter_T>; auto checker = shared_ptr< SC_T >( new SC_T( blocks, fieldId, filter, defaultCheckFrequency, defaultOutputToStream, defaultOutputVTK, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_STABILITY_CHECKER_SET_AND_RETURN() diff --git a/src/field/VolumetricFlowRateEvaluation.h b/src/field/VolumetricFlowRateEvaluation.h index bbbcc01e0..063bd1518 100644 --- a/src/field/VolumetricFlowRateEvaluation.h +++ b/src/field/VolumetricFlowRateEvaluation.h @@ -48,8 +48,8 @@ namespace field { namespace internal { -typedef std::function< real_t () > FlowRateSolution_T; -typedef std::function< Vector3< real_t > ( const Vector3< real_t > & ) > FlowRateVelocitySolution_T; +using FlowRateSolution_T = std::function<real_t ()>; +using FlowRateVelocitySolution_T = std::function<Vector3<real_t> (const Vector3<real_t> &)>; const std::string volumetricFlowRateEvaluationFilename("flowrate.dat"); const real_t volumetricFlowRateEvaluationNormalization( real_t(1) ); @@ -150,8 +150,8 @@ class VolumetricFlowRateEvaluation { public: - typedef internal::FlowRateSolution_T Solution_T; - typedef internal::FlowRateVelocitySolution_T VelocitySolution_T; + using Solution_T = internal::FlowRateSolution_T; + using VelocitySolution_T = internal::FlowRateVelocitySolution_T; VolumetricFlowRateEvaluation( const weak_ptr< StructuredBlockStorage > & blocks, const ConstBlockDataID & fieldId, const Filter_T & filter, @@ -491,7 +491,7 @@ shared_ptr< VolumetricFlowRateEvaluation< VelocityField_T > > makeVolumetricFlow const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef VolumetricFlowRateEvaluation< VelocityField_T > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T>; return shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, plotFrequency, logFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); } @@ -505,7 +505,7 @@ makeVolumetricFlowRateEvaluation( const weak_ptr< StructuredBlockStorage > & blo const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef VolumetricFlowRateEvaluation< VelocityField_T, FlagFieldEvaluationFilter<FlagField_T> > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T, FlagFieldEvaluationFilter<FlagField_T>>; return shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), plotFrequency, logFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); } @@ -519,7 +519,7 @@ makeVolumetricFlowRateEvaluation( const weak_ptr< StructuredBlockStorage > & blo const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef VolumetricFlowRateEvaluation< VelocityField_T, Filter_T > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T, Filter_T>; return shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, filter, plotFrequency, logFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); } @@ -596,7 +596,7 @@ shared_ptr< VolumetricFlowRateEvaluation< VelocityField_T > > makeVolumetricFlow const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_CONFIG_PARSER( config ) - typedef VolumetricFlowRateEvaluation< VelocityField_T > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T>; auto evaluation = shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, defaultPlotFrequency, defaultLogFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_SET_AND_RETURN() @@ -614,7 +614,7 @@ makeVolumetricFlowRateEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_CONFIG_PARSER( config ) - typedef VolumetricFlowRateEvaluation< VelocityField_T, FlagFieldEvaluationFilter<FlagField_T> > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T, FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, cellsToEvaluate ), defaultPlotFrequency, defaultLogFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_SET_AND_RETURN() @@ -632,7 +632,7 @@ makeVolumetricFlowRateEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_CONFIG_PARSER( config ) - typedef VolumetricFlowRateEvaluation< VelocityField_T, Filter_T > FR_T; + using FR_T = VolumetricFlowRateEvaluation<VelocityField_T, Filter_T>; auto evaluation = shared_ptr< FR_T >( new FR_T( blocks, velocityFieldId, filter, defaultPlotFrequency, defaultLogFrequency, solution, velocitySolution, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_VOLUMETRIC_FLOW_RATE_EVALUATION_SET_AND_RETURN() diff --git a/src/field/adaptors/AdaptorCreators.h b/src/field/adaptors/AdaptorCreators.h index 56bfff201..b6907b2c2 100644 --- a/src/field/adaptors/AdaptorCreators.h +++ b/src/field/adaptors/AdaptorCreators.h @@ -38,14 +38,14 @@ class AdaptorHandling : public blockforest::AlwaysInitializeBlockDataHandling< A { public: - typedef typename Adaptor_T::functor_t AdaptionFunction_T; + using AdaptionFunction_T = typename Adaptor_T::functor_t; AdaptorHandling( const ConstBlockDataID & adaptedFieldId, const AdaptionFunction_T & function ) : adaptedFieldId_( adaptedFieldId ), function_( function ) {} Adaptor_T * initialize( IBlock * const block ) override { - typedef typename Adaptor_T::basefield_t AdaptedField_T; + using AdaptedField_T = typename Adaptor_T::basefield_t; const AdaptedField_T * adaptedField = block->getData< AdaptedField_T >( adaptedFieldId_ ); return new Adaptor_T( *adaptedField, function_ ); } diff --git a/src/field/adaptors/AdaptorIterator.h b/src/field/adaptors/AdaptorIterator.h index b9504ef31..e2da36e2e 100644 --- a/src/field/adaptors/AdaptorIterator.h +++ b/src/field/adaptors/AdaptorIterator.h @@ -43,9 +43,9 @@ template < typename AdaptedIterator, typename FieldAdaptor> class AdaptorIterator { public: - typedef typename FieldAdaptor::value_type T; - typedef typename FieldAdaptor::functor_t Functor; - typedef AdaptorIterator<AdaptedIterator, FieldAdaptor > OwnType; + using T = typename FieldAdaptor::value_type; + using Functor = typename FieldAdaptor::functor_t; + using OwnType = AdaptorIterator<AdaptedIterator, FieldAdaptor>; AdaptorIterator( const AdaptedIterator & baseIterator, const FieldAdaptor * adaptedField ) : base_( baseIterator ), adaptedField_( adaptedField), functor_( adaptedField->getFunctor() ) diff --git a/src/field/adaptors/ComponentExtractionAdaptor.h b/src/field/adaptors/ComponentExtractionAdaptor.h index bfd60854c..12451fcc6 100644 --- a/src/field/adaptors/ComponentExtractionAdaptor.h +++ b/src/field/adaptors/ComponentExtractionAdaptor.h @@ -32,12 +32,12 @@ namespace field { class ComponentExtractionFunction { public: - typedef Field_T basefield_t; - typedef typename Field_T::const_base_iterator basefield_iterator; + using basefield_t = Field_T; + using basefield_iterator = typename Field_T::const_base_iterator; - typedef VectorTrait<typename basefield_t::value_type > OutputTrait; + using OutputTrait = VectorTrait<typename basefield_t::value_type>; - typedef typename OutputTrait::OutputType value_type; + using value_type = typename OutputTrait::OutputType; static const uint_t F_SIZE = 1; @@ -61,8 +61,8 @@ namespace field { class ComponentExtractionAdaptor : public GhostLayerFieldAdaptor< ComponentExtractionFunction<field_t,component,vectorComponent>, 0 > { public: - typedef ComponentExtractionFunction<field_t,component,vectorComponent> Func; - typedef GhostLayerFieldAdaptor< Func, 0 > baseclass; + using Func = ComponentExtractionFunction<field_t, component, vectorComponent>; + using baseclass = GhostLayerFieldAdaptor<Func, 0>; ComponentExtractionAdaptor( const field_t & field, const Func & func = Func() ) : baseclass( field, func) diff --git a/src/field/adaptors/GhostLayerFieldAdaptor.h b/src/field/adaptors/GhostLayerFieldAdaptor.h index 3b22ae6ef..13ac8f0e2 100644 --- a/src/field/adaptors/GhostLayerFieldAdaptor.h +++ b/src/field/adaptors/GhostLayerFieldAdaptor.h @@ -85,23 +85,23 @@ public: //** Type Definitions ********************************************************************************************** /*! \name Type Definitions */ //@{ - typedef Functor functor_t; - typedef typename Functor::basefield_t basefield_t; - typedef typename Functor::value_type value_type; - typedef typename Functor::value_type T; + using functor_t = Functor; + using basefield_t = typename Functor::basefield_t; + using value_type = typename Functor::value_type; + using T = typename Functor::value_type; static const uint_t F_SIZE = Functor::F_SIZE; - typedef typename basefield_t::const_base_iterator adapted_base_iterator; - typedef typename basefield_t::const_iterator adapted_iterator; - typedef typename basefield_t::const_reverse_iterator adapted_reverse_iterator; + using adapted_base_iterator = typename basefield_t::const_base_iterator; + using adapted_iterator = typename basefield_t::const_iterator; + using adapted_reverse_iterator = typename basefield_t::const_reverse_iterator; - typedef GhostLayerFieldAdaptor<Functor,glDecrease> OwnType; - typedef AdaptorIterator<adapted_base_iterator, OwnType > const_base_iterator; - typedef AdaptorIterator<adapted_iterator, OwnType > const_iterator; - typedef AdaptorIterator<adapted_reverse_iterator,OwnType > const_reverse_iterator; + using OwnType = GhostLayerFieldAdaptor<Functor, glDecrease>; + using const_base_iterator = AdaptorIterator<adapted_base_iterator, OwnType>; + using const_iterator = AdaptorIterator<adapted_iterator, OwnType>; + using const_reverse_iterator = AdaptorIterator<adapted_reverse_iterator, OwnType>; - typedef FieldPointer<OwnType, const OwnType, const T > ConstPtr; + using ConstPtr = FieldPointer<OwnType, const OwnType, const T>; //@} //******************************************************************************************************************* diff --git a/src/field/adaptors/VectorFieldAccessor.h b/src/field/adaptors/VectorFieldAccessor.h index e41f4684a..2ba6ca1a2 100644 --- a/src/field/adaptors/VectorFieldAccessor.h +++ b/src/field/adaptors/VectorFieldAccessor.h @@ -36,7 +36,7 @@ namespace field { static_assert( VectorField_T::F_SIZE == 3, "Only valid for Fields with 3 components (F_SIZE==3)" ); static_assert( std::is_same< typename VectorField_T::value_type, real_t >::value, "Only works for real valued fields" ); - typedef Vector3<real_t> vector_or_constRefVector; + using vector_or_constRefVector = Vector3<real_t>; static vector_or_constRefVector get( const VectorField_T * f, cell_idx_t x, cell_idx_t y, cell_idx_t z ) { @@ -56,7 +56,7 @@ namespace field { typename std::enable_if< std::is_same< typename VectorField_T::value_type, Vector3<real_t> >::value >::type > { - typedef const Vector3<real_t> & vector_or_constRefVector; + using vector_or_constRefVector = const Vector3<real_t> &; static vector_or_constRefVector get( const VectorField_T * f, cell_idx_t x, cell_idx_t y, cell_idx_t z ) { diff --git a/src/field/blockforest/BlockDataHandling.h b/src/field/blockforest/BlockDataHandling.h index e0caa9869..293935234 100644 --- a/src/field/blockforest/BlockDataHandling.h +++ b/src/field/blockforest/BlockDataHandling.h @@ -42,8 +42,8 @@ class BlockDataHandling : public blockforest::BlockDataHandling< Field_T > { public: - typedef typename Field_T::value_type Value_T; - typedef std::function< void ( Field_T * field, IBlock * const block ) > InitializationFunction_T; + using Value_T = typename Field_T::value_type; + using InitializationFunction_T = std::function<void (Field_T *, IBlock *const)>; ~BlockDataHandling() override = default; @@ -398,7 +398,7 @@ class DefaultBlockDataHandling : public BlockDataHandling< GhostLayerField_T > { public: - typedef typename GhostLayerField_T::value_type Value_T; + using Value_T = typename GhostLayerField_T::value_type; DefaultBlockDataHandling( const weak_ptr< StructuredBlockStorage > & blocks, const std::function< Vector3< uint_t > ( const shared_ptr< StructuredBlockStorage > &, IBlock * const ) > calculateSize = internal::defaultSize ) : @@ -460,8 +460,8 @@ class AlwaysInitializeBlockDataHandling : public blockforest::AlwaysInitializeBl { public: - typedef typename GhostLayerField_T::value_type Value_T; - typedef std::function< void ( GhostLayerField_T * field, IBlock * const block ) > InitializationFunction_T; + using Value_T = typename GhostLayerField_T::value_type; + using InitializationFunction_T = std::function<void (GhostLayerField_T *, IBlock *const)>; AlwaysInitializeBlockDataHandling( const weak_ptr< StructuredBlockStorage > & blocks, const std::function< Vector3< uint_t > ( const shared_ptr< StructuredBlockStorage > &, IBlock * const ) > calculateSize = internal::defaultSize ) : diff --git a/src/field/communication/MPIDatatypes.impl.h b/src/field/communication/MPIDatatypes.impl.h index 1bb4bf3a6..a21ac75bd 100644 --- a/src/field/communication/MPIDatatypes.impl.h +++ b/src/field/communication/MPIDatatypes.impl.h @@ -33,7 +33,7 @@ MPI_Datatype mpiDatatypeSlice( const Field_T & field, const cell_idx_t xBeg, const cell_idx_t yBeg, const cell_idx_t zBeg, const cell_idx_t fBeg, const cell_idx_t xEnd, const cell_idx_t yEnd, const cell_idx_t zEnd, const cell_idx_t fEnd ) { - typedef typename Field_T::value_type T; + using T = typename Field_T::value_type; int sizes[4]; int subsizes[4]; int starts[4]; @@ -133,7 +133,7 @@ MPI_Datatype mpiDatatypeSliceXYZ( const Field_T & field, const CellInterval & in template<typename Field_T> MPI_Datatype mpiDatatypeSliceXYZ( const Field_T & field, const CellInterval & interval, const std::set<cell_idx_t> & fs ) { - typedef typename Field_T::value_type T; + using T = typename Field_T::value_type; MPI_Datatype newType = MPI_DATATYPE_NULL; diff --git a/src/field/communication/PackInfo.h b/src/field/communication/PackInfo.h index a8e95ce75..108860eb3 100644 --- a/src/field/communication/PackInfo.h +++ b/src/field/communication/PackInfo.h @@ -42,7 +42,7 @@ template<typename GhostLayerField_T> class PackInfo : public walberla::communication::UniformPackInfo { public: - typedef typename GhostLayerField_T::value_type T; + using T = typename GhostLayerField_T::value_type; PackInfo( const BlockDataID & bdId ) : bdId_( bdId ), communicateAllGhostLayers_( true ), numberOfGhostLayers_( 0 ) {} diff --git a/src/field/communication/ReducePackInfo.h b/src/field/communication/ReducePackInfo.h index 135574dcd..532b43724 100644 --- a/src/field/communication/ReducePackInfo.h +++ b/src/field/communication/ReducePackInfo.h @@ -42,7 +42,7 @@ template< template<typename> class ReduceOperation, typename GhostLayerField_T > class ReducePackInfo : public walberla::communication::ReducePackInfo { public: - typedef typename GhostLayerField_T::value_type T; + using T = typename GhostLayerField_T::value_type; ReducePackInfo( const BlockDataID & bdId, T init ) : bdId_(bdId), diff --git a/src/field/communication/UniformPullReductionPackInfo.h b/src/field/communication/UniformPullReductionPackInfo.h index 4233a3d23..aa7ffe1a9 100644 --- a/src/field/communication/UniformPullReductionPackInfo.h +++ b/src/field/communication/UniformPullReductionPackInfo.h @@ -49,7 +49,7 @@ template< template<typename> class ReduceOperation, typename GhostLayerField_T > class UniformPullReductionPackInfo : public walberla::communication::UniformPackInfo { public: - typedef typename GhostLayerField_T::value_type T; + using T = typename GhostLayerField_T::value_type; UniformPullReductionPackInfo( const BlockDataID & bdID ) : bdID_( bdID ), communicateAllGhostLayers_( true ), numberOfGhostLayers_( 0 ) {} diff --git a/src/field/distributors/DistributorCreators.h b/src/field/distributors/DistributorCreators.h index ab555911c..2ff45e304 100644 --- a/src/field/distributors/DistributorCreators.h +++ b/src/field/distributors/DistributorCreators.h @@ -67,8 +67,8 @@ public: Distributor_T * initialize( IBlock * const block ) override { - typedef typename Distributor_T::BaseField_T DistributionDestinationField_T; - typedef typename FlagField_T::flag_t flag_t; + using DistributionDestinationField_T = typename Distributor_T::BaseField_T; + using flag_t = typename FlagField_T::flag_t; DistributionDestinationField_T * distributionDestinationField = block->getData< DistributionDestinationField_T >( distributionDestinationFieldID_ ); const FlagField_T * flagField = block->getData< FlagField_T >( flagFieldID_ ); diff --git a/src/field/distributors/KernelDistributor.h b/src/field/distributors/KernelDistributor.h index 1aed2f2ea..712d9a7b7 100644 --- a/src/field/distributors/KernelDistributor.h +++ b/src/field/distributors/KernelDistributor.h @@ -50,9 +50,9 @@ public: static const uint_t F_SIZE = Field_T::F_SIZE; - typedef Field_T BaseField_T; - typedef typename FlagField_T::flag_t flag_t; - typedef KernelDistributor<Field_T,FlagField_T> OwnType; + using BaseField_T = Field_T; + using flag_t = typename FlagField_T::flag_t; + using OwnType = KernelDistributor<Field_T, FlagField_T>; KernelDistributor( const weak_ptr<StructuredBlockStorage> & blockStorage, const IBlock & block, BaseField_T & baseField, const FlagField_T & flagField, diff --git a/src/field/distributors/NearestNeighborDistributor.h b/src/field/distributors/NearestNeighborDistributor.h index 6aa4ba295..932f443b3 100644 --- a/src/field/distributors/NearestNeighborDistributor.h +++ b/src/field/distributors/NearestNeighborDistributor.h @@ -49,9 +49,9 @@ public: static const uint_t F_SIZE = Field_T::F_SIZE; - typedef Field_T BaseField_T; - typedef typename FlagField_T::flag_t flag_t; - typedef NearestNeighborDistributor<Field_T,FlagField_T> OwnType; + using BaseField_T = Field_T; + using flag_t = typename FlagField_T::flag_t; + using OwnType = NearestNeighborDistributor<Field_T, FlagField_T>; NearestNeighborDistributor( const weak_ptr<StructuredBlockStorage> & blockStorage, const IBlock & block, BaseField_T & baseField, const FlagField_T & flagField, diff --git a/src/field/interpolators/FieldInterpolatorCreators.h b/src/field/interpolators/FieldInterpolatorCreators.h index 760db9b7c..c4bcfafc3 100644 --- a/src/field/interpolators/FieldInterpolatorCreators.h +++ b/src/field/interpolators/FieldInterpolatorCreators.h @@ -66,8 +66,8 @@ public: Interpolator_T * initialize( IBlock * const block ) override { - typedef typename Interpolator_T::BaseField_T InterpolatedField_T; - typedef typename FlagField_T::flag_t flag_t; + using InterpolatedField_T = typename Interpolator_T::BaseField_T; + using flag_t = typename FlagField_T::flag_t; const InterpolatedField_T * interpolatedField = block->getData< InterpolatedField_T >( interpolatedFieldID_ ); const FlagField_T * flagField = block->getData< FlagField_T >( flagFieldID_ ); diff --git a/src/field/interpolators/KernelFieldInterpolator.h b/src/field/interpolators/KernelFieldInterpolator.h index 50dfde0fc..0e59fabf2 100644 --- a/src/field/interpolators/KernelFieldInterpolator.h +++ b/src/field/interpolators/KernelFieldInterpolator.h @@ -92,9 +92,9 @@ public: static const uint_t F_SIZE = Field_T::F_SIZE; - typedef Field_T BaseField_T; - typedef typename FlagField_T::flag_t flag_t; - typedef KernelFieldInterpolator<Field_T,FlagField_T> OwnType; + using BaseField_T = Field_T; + using flag_t = typename FlagField_T::flag_t; + using OwnType = KernelFieldInterpolator<Field_T, FlagField_T>; KernelFieldInterpolator( const weak_ptr<StructuredBlockStorage> & blockStorage, const IBlock & block, const BaseField_T & baseField, const FlagField_T & flagField, diff --git a/src/field/interpolators/NearestNeighborFieldInterpolator.h b/src/field/interpolators/NearestNeighborFieldInterpolator.h index 975c55edb..b5b5cba7f 100644 --- a/src/field/interpolators/NearestNeighborFieldInterpolator.h +++ b/src/field/interpolators/NearestNeighborFieldInterpolator.h @@ -46,9 +46,9 @@ public: static const uint_t F_SIZE = Field_T::F_SIZE; - typedef Field_T BaseField_T; - typedef typename FlagField_T::flag_t flag_t; - typedef NearestNeighborFieldInterpolator<Field_T,FlagField_T> OwnType; + using BaseField_T = Field_T; + using flag_t = typename FlagField_T::flag_t; + using OwnType = NearestNeighborFieldInterpolator<Field_T, FlagField_T>; NearestNeighborFieldInterpolator( const weak_ptr<StructuredBlockStorage> & blockStorage, const IBlock & block, const BaseField_T & baseField, const FlagField_T & flagField, diff --git a/src/field/interpolators/NearestNeighborInterpolator.h b/src/field/interpolators/NearestNeighborInterpolator.h index 0a609dc68..b76c61fa5 100644 --- a/src/field/interpolators/NearestNeighborInterpolator.h +++ b/src/field/interpolators/NearestNeighborInterpolator.h @@ -53,7 +53,7 @@ namespace field { public: static const uint_t F_SIZE = GlField::F_SIZE; - typedef typename GlField::value_type value_type; + using value_type = typename GlField::value_type; NearestNeighborInterpolator( const GlField & fieldToInterpolate ) : field_( fieldToInterpolate ) diff --git a/src/field/interpolators/TrilinearFieldInterpolator.h b/src/field/interpolators/TrilinearFieldInterpolator.h index bdac4ff1a..8eb24a4cf 100644 --- a/src/field/interpolators/TrilinearFieldInterpolator.h +++ b/src/field/interpolators/TrilinearFieldInterpolator.h @@ -48,9 +48,9 @@ public: static const uint_t F_SIZE = Field_T::F_SIZE; - typedef Field_T BaseField_T; - typedef typename FlagField_T::flag_t flag_t; - typedef TrilinearFieldInterpolator<Field_T,FlagField_T> OwnType; + using BaseField_T = Field_T; + using flag_t = typename FlagField_T::flag_t; + using OwnType = TrilinearFieldInterpolator<Field_T, FlagField_T>; TrilinearFieldInterpolator( const weak_ptr<StructuredBlockStorage> & blockStorage, const IBlock & block, const BaseField_T & baseField, const FlagField_T & flagField, diff --git a/src/field/iterators/FieldIterator.h b/src/field/iterators/FieldIterator.h index faecf9822..7557fea2a 100644 --- a/src/field/iterators/FieldIterator.h +++ b/src/field/iterators/FieldIterator.h @@ -75,7 +75,7 @@ namespace field { using pointer = T*; using reference = T&; - typedef Field<typename std::remove_const<T>::type, fieldFSize> FieldType; + using FieldType = Field<typename std::remove_const<T>::type, fieldFSize>; static const uint_t F_SIZE = fieldFSize; @@ -219,8 +219,8 @@ namespace field { class ForwardFieldIterator : public FieldIterator<T,fieldFSize> { public: - typedef FieldIterator<T,fieldFSize> Parent; - typedef Field<typename std::remove_const<T>::type, fieldFSize> FieldType; + using Parent = FieldIterator<T, fieldFSize>; + using FieldType = Field<typename std::remove_const<T>::type, fieldFSize>; //**Constructor/Destructor**************************************************************************************** /*!\name Constructor/Destructor */ @@ -262,8 +262,8 @@ namespace field { class ReverseFieldIterator : public FieldIterator<T,fieldFSize> { public: - typedef FieldIterator<T,fieldFSize> Parent; - typedef Field<typename std::remove_const<T>::type, fieldFSize> FieldType; + using Parent = FieldIterator<T, fieldFSize>; + using FieldType = Field<typename std::remove_const<T>::type, fieldFSize>; //**Constructor/Destructor**************************************************************************************** /*!\name Constructor/Destructor */ diff --git a/src/field/iterators/FieldIterator.impl.h b/src/field/iterators/FieldIterator.impl.h index a643984c8..d2184e9a8 100644 --- a/src/field/iterators/FieldIterator.impl.h +++ b/src/field/iterators/FieldIterator.impl.h @@ -47,7 +47,7 @@ FieldIterator<T,fs>::FieldIterator( const typename FieldIterator<T,fs>::FieldTyp return; } - typedef typename std::remove_const<T>::type NonConstT; + using NonConstT = typename std::remove_const<T>::type; cur_[0] = cur_[1] = cur_[2] = 0; if( f_->layout() == fzyx ) diff --git a/src/field/iterators/FieldNeighborPointer.h b/src/field/iterators/FieldNeighborPointer.h index 9d483d1e9..4ab5a13c0 100644 --- a/src/field/iterators/FieldNeighborPointer.h +++ b/src/field/iterators/FieldNeighborPointer.h @@ -61,7 +61,7 @@ namespace field { { public: - typedef Value_T value_type; + using value_type = Value_T; static const uint_t F_SIZE = Field_T::F_SIZE; FieldNeighborPointer( FieldMember & field, cell_idx_t _x, cell_idx_t _y, cell_idx_t _z, cell_idx_t _f = 0 ) diff --git a/src/field/iterators/FieldPointer.h b/src/field/iterators/FieldPointer.h index ba027faad..b36a19af5 100644 --- a/src/field/iterators/FieldPointer.h +++ b/src/field/iterators/FieldPointer.h @@ -63,7 +63,7 @@ namespace field { class FieldPointer { public: - typedef Value_T value_type; + using value_type = Value_T; static const uint_t F_SIZE = Field_T::F_SIZE; FieldPointer( FieldMember & field, cell_idx_t _x, cell_idx_t _y, cell_idx_t _z, cell_idx_t _f = 0 ) diff --git a/src/field/vtk/FlagFieldCellFilter.h b/src/field/vtk/FlagFieldCellFilter.h index 708c5234e..d82c3a13e 100644 --- a/src/field/vtk/FlagFieldCellFilter.h +++ b/src/field/vtk/FlagFieldCellFilter.h @@ -35,7 +35,7 @@ namespace field { template< typename FlagField_T > class FlagFieldCellFilter { private: - typedef typename FlagField_T::flag_t flag_t; + using flag_t = typename FlagField_T::flag_t; public: FlagFieldCellFilter( const ConstBlockDataID flags ) : flagField_( flags ) {} diff --git a/src/field/vtk/FlagFieldMapping.h b/src/field/vtk/FlagFieldMapping.h index e496657df..f8cb572b5 100644 --- a/src/field/vtk/FlagFieldMapping.h +++ b/src/field/vtk/FlagFieldMapping.h @@ -34,7 +34,7 @@ template< typename FlagField_T, typename T > class FlagFieldMapping : public vtk::BlockCellDataWriter<T,1> { private: - typedef typename FlagField_T::flag_t flag_t; + using flag_t = typename FlagField_T::flag_t; public: FlagFieldMapping( const ConstBlockDataID flagId, const std::string& id ) : @@ -86,7 +86,7 @@ protected: template<typename FieldType, typename TargetType=uint8_t> class BinarizationFieldWriter : public vtk::BlockCellDataWriter<TargetType,1> { - typedef typename FieldType::value_type SrcType; + using SrcType = typename FieldType::value_type; public: BinarizationFieldWriter( const ConstBlockDataID fieldID, const std::string& id, SrcType mask) : diff --git a/src/field/vtk/VTKWriter.h b/src/field/vtk/VTKWriter.h index a86d8fa52..513b920e1 100644 --- a/src/field/vtk/VTKWriter.h +++ b/src/field/vtk/VTKWriter.h @@ -103,9 +103,9 @@ class VTKWriter : public vtk::BlockCellDataWriter< OutputType, VectorTrait<typename Field_T::value_type>::F_SIZE * Field_T::F_SIZE > { public: - typedef VectorTrait<typename Field_T::value_type > OutputTrait; + using OutputTrait = VectorTrait<typename Field_T::value_type>; - typedef vtk::BlockCellDataWriter<OutputType, OutputTrait::F_SIZE * Field_T::F_SIZE> base_t; + using base_t = vtk::BlockCellDataWriter<OutputType, OutputTrait::F_SIZE * Field_T::F_SIZE>; VTKWriter( const ConstBlockDataID bdid, const std::string& id ) : base_t( id ), bdid_( bdid ), field_( nullptr ) {} @@ -192,7 +192,7 @@ inline vtk::VTKOutput::Write createVTKOutput ( const ConstBlockDataID & fieldId const Set<SUID>& incompatibleStates = Set<SUID>::emptySet(), bool useMPIIO = true, const uint_t initialExecutionCount = 0 ) { - typedef typename VectorTrait<typename Field_T::value_type >::OutputType OutputType; + using OutputType = typename VectorTrait<typename Field_T::value_type>::OutputType; return createVTKOutput<Field_T, OutputType> ( fieldId, blocks, identifier, writeFrequency, ghostLayers, forcePVTU, baseFolder,executionFolder, @@ -247,7 +247,7 @@ inline vtk::VTKOutput::Write createScalingVTKOutput ( const ConstBlockDataID & const Set<SUID>& incompatibleStates = Set<SUID>::emptySet(), bool useMPIIO = true, const uint_t initialExecutionCount = 0 ) { - typedef typename VectorTrait<typename Field_T::value_type >::OutputType OutputType; + using OutputType = typename VectorTrait<typename Field_T::value_type>::OutputType; return createScalingVTKOutput<Field_T, OutputType> ( fieldId, blocks, identifier, writeFrequency, factor, ghostLayers, forcePVTU, baseFolder,executionFolder, diff --git a/src/gather/FileGatherScheme.h b/src/gather/FileGatherScheme.h index b7409573f..7a48b0f10 100644 --- a/src/gather/FileGatherScheme.h +++ b/src/gather/FileGatherScheme.h @@ -106,7 +106,7 @@ namespace gather domain_decomposition::BlockStorage & blocks_; - typedef std::vector<shared_ptr<GatherPackInfo> > PackInfoVector; + using PackInfoVector = std::vector<shared_ptr<GatherPackInfo>>; PackInfoVector packInfos_; ///< all registered PackInfos /// To generated unique filenames for every FileCollectorScheme diff --git a/src/gather/MPIGatherScheme.h b/src/gather/MPIGatherScheme.h index 3d06db3ca..e9270289b 100644 --- a/src/gather/MPIGatherScheme.h +++ b/src/gather/MPIGatherScheme.h @@ -102,7 +102,7 @@ class MPIGatherScheme private: - typedef std::vector<shared_ptr<GatherPackInfo> > PackInfoVector; + using PackInfoVector = std::vector<shared_ptr<GatherPackInfo>>; domain_decomposition::BlockStorage & blocks_; PackInfoVector packInfos_; ///< all registered PackInfos diff --git a/src/geometry/InitBoundaryHandling.h b/src/geometry/InitBoundaryHandling.h index 7be3b0271..fe6817d3e 100644 --- a/src/geometry/InitBoundaryHandling.h +++ b/src/geometry/InitBoundaryHandling.h @@ -87,12 +87,12 @@ void initBoundaryHandling( StructuredBlockStorage & blocks, BlockDataID boundary using namespace geometry; using namespace initializer; - typedef BoundaryFromCellInterval <BoundaryHandling> FromCellInterval; - typedef BoundaryFromDomainBorder <BoundaryHandling> FromBorder; - typedef BoundaryFromVoxelFile <BoundaryHandling> FromVoxelFile; - typedef BoundaryFromBody <BoundaryHandling> FromBody; - typedef BoundaryFromImage <BoundaryHandling, GrayScaleImage> FromGrayScaleImage; - typedef BoundaryFromImage <BoundaryHandling, RGBAImage> FromRGBAImage; + using FromCellInterval = BoundaryFromCellInterval<BoundaryHandling>; + using FromBorder = BoundaryFromDomainBorder<BoundaryHandling>; + using FromVoxelFile = BoundaryFromVoxelFile<BoundaryHandling>; + using FromBody = BoundaryFromBody<BoundaryHandling>; + using FromGrayScaleImage = BoundaryFromImage<BoundaryHandling, GrayScaleImage>; + using FromRGBAImage = BoundaryFromImage<BoundaryHandling, RGBAImage>; InitializationManager initManager( blocks.getBlockStorage() ); diff --git a/src/geometry/containment_octree/BranchNode.h b/src/geometry/containment_octree/BranchNode.h index fd5d95077..2b160ad5b 100644 --- a/src/geometry/containment_octree/BranchNode.h +++ b/src/geometry/containment_octree/BranchNode.h @@ -36,12 +36,12 @@ template< typename ContainmentOctreeT > class BranchNode : public Node<ContainmentOctreeT> { public: - typedef typename Node<ContainmentOctreeT>::DistanceObject DistanceObject; - typedef typename Node<ContainmentOctreeT>::Scalar Scalar; - typedef typename Node<ContainmentOctreeT>::Point Point; - typedef typename Node<ContainmentOctreeT>::AABB AABB; + using DistanceObject = typename Node<ContainmentOctreeT>::DistanceObject; + using Scalar = typename Node<ContainmentOctreeT>::Scalar; + using Point = typename Node<ContainmentOctreeT>::Point; + using AABB = typename Node<ContainmentOctreeT>::AABB; - typedef typename Node<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; + using KahanAccumulator = typename Node<ContainmentOctreeT>::KahanAccumulator; inline BranchNode( const shared_ptr<const DistanceObject> & distanceObject, const AABB & aabb, const Scalar epsilon, const uint_t maxDepth, const Scalar minAABBVolume ); diff --git a/src/geometry/containment_octree/ContainmentOctree.h b/src/geometry/containment_octree/ContainmentOctree.h index 96d091c00..d95fa55ce 100644 --- a/src/geometry/containment_octree/ContainmentOctree.h +++ b/src/geometry/containment_octree/ContainmentOctree.h @@ -42,18 +42,18 @@ template< typename DistanceObjectT > class ContainmentOctree { public: - typedef typename DistanceObjectT::Scalar Scalar; - typedef typename DistanceObjectT::Point Point; - typedef math::GenericAABB<Scalar> AABB; - - typedef math::KahanAccumulator<Scalar> KahanAccumulator; - typedef DistanceObjectT DistanceObject; - - typedef containment_octree::Node<ContainmentOctree> Node; - typedef containment_octree::InsideLeafNode<ContainmentOctree> InsideLeafNode; - typedef containment_octree::OutsideLeafNode<ContainmentOctree> OutsideLeafNode; - typedef containment_octree::IndeterminateLeafNode<ContainmentOctree> IndeterminateLeafNode; - typedef containment_octree::BranchNode<ContainmentOctree> BranchNode; + using Scalar = typename DistanceObjectT::Scalar; + using Point = typename DistanceObjectT::Point; + using AABB = math::GenericAABB<Scalar>; + + using KahanAccumulator = math::KahanAccumulator<Scalar>; + using DistanceObject = DistanceObjectT; + + using Node = containment_octree::Node<ContainmentOctree>; + using InsideLeafNode = containment_octree::InsideLeafNode<ContainmentOctree>; + using OutsideLeafNode = containment_octree::OutsideLeafNode<ContainmentOctree>; + using IndeterminateLeafNode = containment_octree::IndeterminateLeafNode<ContainmentOctree>; + using BranchNode = containment_octree::BranchNode<ContainmentOctree>; inline ContainmentOctree( const shared_ptr<const DistanceObject> & distanceObject, const Scalar epsilon = Scalar(0), const uint_t maxDepth = 6u, const Scalar minAABBVolume = Scalar(0) ); diff --git a/src/geometry/containment_octree/IndeterminateLeafNode.h b/src/geometry/containment_octree/IndeterminateLeafNode.h index 977c0a1cb..382620f57 100644 --- a/src/geometry/containment_octree/IndeterminateLeafNode.h +++ b/src/geometry/containment_octree/IndeterminateLeafNode.h @@ -34,12 +34,12 @@ class IndeterminateLeafNode : public LeafNode<ContainmentOctreeT> { public: using LeafNode<ContainmentOctreeT>::numNodes; - typedef typename LeafNode<ContainmentOctreeT>::DistanceObject DistanceObject; - typedef typename LeafNode<ContainmentOctreeT>::Scalar Scalar; - typedef typename LeafNode<ContainmentOctreeT>::Point Point; - typedef typename LeafNode<ContainmentOctreeT>::AABB AABB; + using DistanceObject = typename LeafNode<ContainmentOctreeT>::DistanceObject; + using Scalar = typename LeafNode<ContainmentOctreeT>::Scalar; + using Point = typename LeafNode<ContainmentOctreeT>::Point; + using AABB = typename LeafNode<ContainmentOctreeT>::AABB; - typedef typename LeafNode<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; + using KahanAccumulator = typename LeafNode<ContainmentOctreeT>::KahanAccumulator; IndeterminateLeafNode( const shared_ptr<const DistanceObject> & distanceObject, const Scalar epsilon ) : distanceObject_( distanceObject ), sqEpsilon_( epsilon * epsilon ) { } diff --git a/src/geometry/containment_octree/InsideLeafNode.h b/src/geometry/containment_octree/InsideLeafNode.h index b673d61e1..0c46290f1 100644 --- a/src/geometry/containment_octree/InsideLeafNode.h +++ b/src/geometry/containment_octree/InsideLeafNode.h @@ -34,12 +34,12 @@ class InsideLeafNode : public LeafNode<ContainmentOctreeT> { public: using LeafNode<ContainmentOctreeT>::numNodes; - typedef typename LeafNode<ContainmentOctreeT>::DistanceObject DistanceObject; - typedef typename LeafNode<ContainmentOctreeT>::Scalar Scalar; - typedef typename LeafNode<ContainmentOctreeT>::Point Point; - typedef typename LeafNode<ContainmentOctreeT>::AABB AABB; + using DistanceObject = typename LeafNode<ContainmentOctreeT>::DistanceObject; + using Scalar = typename LeafNode<ContainmentOctreeT>::Scalar; + using Point = typename LeafNode<ContainmentOctreeT>::Point; + using AABB = typename LeafNode<ContainmentOctreeT>::AABB; - typedef typename LeafNode<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; + using KahanAccumulator = typename LeafNode<ContainmentOctreeT>::KahanAccumulator; virtual ~InsideLeafNode() = default; diff --git a/src/geometry/containment_octree/LeafNode.h b/src/geometry/containment_octree/LeafNode.h index 47223f8b5..177a352dc 100644 --- a/src/geometry/containment_octree/LeafNode.h +++ b/src/geometry/containment_octree/LeafNode.h @@ -35,12 +35,12 @@ class LeafNode : public Node<ContainmentOctreeT> { public: using Node<ContainmentOctreeT>::numNodes; - typedef typename Node<ContainmentOctreeT>::DistanceObject DistanceObject; - typedef typename Node<ContainmentOctreeT>::Scalar Scalar; - typedef typename Node<ContainmentOctreeT>::Point Point; - typedef typename Node<ContainmentOctreeT>::AABB AABB; + using DistanceObject = typename Node<ContainmentOctreeT>::DistanceObject; + using Scalar = typename Node<ContainmentOctreeT>::Scalar; + using Point = typename Node<ContainmentOctreeT>::Point; + using AABB = typename Node<ContainmentOctreeT>::AABB; - typedef typename Node<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; + using KahanAccumulator = typename Node<ContainmentOctreeT>::KahanAccumulator; virtual ~LeafNode() = default; diff --git a/src/geometry/containment_octree/Node.h b/src/geometry/containment_octree/Node.h index a1bc9325f..ddc3e15ec 100644 --- a/src/geometry/containment_octree/Node.h +++ b/src/geometry/containment_octree/Node.h @@ -33,12 +33,12 @@ template< typename ContainmentOctreeT > class Node { public: - typedef typename ContainmentOctreeT::Point Point; - typedef typename ContainmentOctreeT::Scalar Scalar; - typedef typename ContainmentOctreeT::AABB AABB; + using Point = typename ContainmentOctreeT::Point; + using Scalar = typename ContainmentOctreeT::Scalar; + using AABB = typename ContainmentOctreeT::AABB; - typedef typename ContainmentOctreeT::DistanceObject DistanceObject; - typedef typename ContainmentOctreeT::KahanAccumulator KahanAccumulator; + using DistanceObject = typename ContainmentOctreeT::DistanceObject; + using KahanAccumulator = typename ContainmentOctreeT::KahanAccumulator; virtual ~Node() = default; virtual bool contains( const Point & p ) const = 0; diff --git a/src/geometry/containment_octree/OutsideLeafNode.h b/src/geometry/containment_octree/OutsideLeafNode.h index b5fc61813..6328ce593 100644 --- a/src/geometry/containment_octree/OutsideLeafNode.h +++ b/src/geometry/containment_octree/OutsideLeafNode.h @@ -35,12 +35,12 @@ class OutsideLeafNode : public LeafNode<ContainmentOctreeT> public: using LeafNode<ContainmentOctreeT>::numNodes; - typedef typename LeafNode<ContainmentOctreeT>::DistanceObject DistanceObject; - typedef typename LeafNode<ContainmentOctreeT>::Scalar Scalar; - typedef typename LeafNode<ContainmentOctreeT>::Point Point; - typedef typename LeafNode<ContainmentOctreeT>::AABB AABB; + using DistanceObject = typename LeafNode<ContainmentOctreeT>::DistanceObject; + using Scalar = typename LeafNode<ContainmentOctreeT>::Scalar; + using Point = typename LeafNode<ContainmentOctreeT>::Point; + using AABB = typename LeafNode<ContainmentOctreeT>::AABB; - typedef typename LeafNode<ContainmentOctreeT>::KahanAccumulator KahanAccumulator; + using KahanAccumulator = typename LeafNode<ContainmentOctreeT>::KahanAccumulator; virtual ~OutsideLeafNode() = default; diff --git a/src/geometry/initializer/BoundaryFromImage.h b/src/geometry/initializer/BoundaryFromImage.h index d19f4dcbe..466af7431 100644 --- a/src/geometry/initializer/BoundaryFromImage.h +++ b/src/geometry/initializer/BoundaryFromImage.h @@ -87,8 +87,8 @@ namespace initializer { class BoundaryFromImage : public Initializer { public: - typedef typename Image_T::pixel_t pixel_t; - typedef std::map<pixel_t, BoundarySetter<BoundaryHandling_T> > BoundarySetters; + using pixel_t = typename Image_T::pixel_t; + using BoundarySetters = std::map<pixel_t, BoundarySetter<BoundaryHandling_T>>; BoundaryFromImage( StructuredBlockStorage & blocks, BlockDataID handlerBlockDataID ); diff --git a/src/geometry/initializer/BoundaryFromVoxelFile.h b/src/geometry/initializer/BoundaryFromVoxelFile.h index 3b0640e33..7987f77f9 100644 --- a/src/geometry/initializer/BoundaryFromVoxelFile.h +++ b/src/geometry/initializer/BoundaryFromVoxelFile.h @@ -58,8 +58,8 @@ struct IBlockIDPtrCompare { bool operator()( const IBlockID * lhs, const IBlockID * rhs ) const; }; -typedef std::map<const IBlockID*, CellInterval, IBlockIDPtrCompare> CellIntervalMap; -typedef std::map<const IBlockID*, std::pair<CellInterval, std::vector<uint8_t> >, IBlockIDPtrCompare> CellIntervalDataMap; +using CellIntervalMap = std::map<const IBlockID *, CellInterval, IBlockIDPtrCompare>; +using CellIntervalDataMap = std::map<const IBlockID *, std::pair<CellInterval, std::vector<uint8_t>>, IBlockIDPtrCompare>; //******************************************************************************************************************* diff --git a/src/geometry/initializer/InitializationManager.h b/src/geometry/initializer/InitializationManager.h index 7c9ac444b..81ed7d68c 100644 --- a/src/geometry/initializer/InitializationManager.h +++ b/src/geometry/initializer/InitializationManager.h @@ -44,7 +44,7 @@ namespace initializer { class Initializer; class InitializerUIDGenerator; - typedef uid::UID< InitializerUIDGenerator > InitializerUID; + using InitializerUID = uid::UID<InitializerUIDGenerator>; //******************************************************************************************************************* diff --git a/src/geometry/initializer/ScalarFieldFromBody.h b/src/geometry/initializer/ScalarFieldFromBody.h index 97ef3cc95..617097ad8 100644 --- a/src/geometry/initializer/ScalarFieldFromBody.h +++ b/src/geometry/initializer/ScalarFieldFromBody.h @@ -77,7 +77,7 @@ namespace initializer { class ScalarFieldFromBody : public Initializer { public: - typedef typename Field_T::value_type Value_T; + using Value_T = typename Field_T::value_type; /*************************************************************************************************************//** * Constructor diff --git a/src/geometry/mesh/TriangleMesh.h b/src/geometry/mesh/TriangleMesh.h index 12501c96c..8f6817c41 100644 --- a/src/geometry/mesh/TriangleMesh.h +++ b/src/geometry/mesh/TriangleMesh.h @@ -54,12 +54,12 @@ namespace geometry { class TriangleMesh { public: - typedef uint32_t index_t; + using index_t = uint32_t; template<typename T> static index_t index_c( T x ) { return numeric_cast<index_t>(x); } - typedef Vector3<real_t> vertex_t; - typedef Vector3<real_t> normal_t; - typedef Vector3<float> color_t; + using vertex_t = Vector3<real_t>; + using normal_t = Vector3<real_t>; + using color_t = Vector3<float>; //** Size Information ******************************************************************************************* /*! \name Size Information */ diff --git a/src/geometry/structured/GrayScaleImage.h b/src/geometry/structured/GrayScaleImage.h index 3361cc90e..43e39359b 100644 --- a/src/geometry/structured/GrayScaleImage.h +++ b/src/geometry/structured/GrayScaleImage.h @@ -44,7 +44,7 @@ namespace geometry { class GrayScaleImage { public: - typedef unsigned char pixel_t; + using pixel_t = unsigned char; GrayScaleImage( uint_t _width, uint_t _height ); GrayScaleImage( const std::string & pngFilename ); diff --git a/src/gui/Gui.h b/src/gui/Gui.h index 1332bb8dc..799060b7a 100644 --- a/src/gui/Gui.h +++ b/src/gui/Gui.h @@ -52,7 +52,7 @@ namespace gui { void registerPropertyTree( const shared_ptr<PropertyTree>& propertyTree ); - typedef std::function< DisplayAdaptor * ( const IBlock &, ConstBlockDataID ) > DisplayAdaptorCreatorFunc; + using DisplayAdaptorCreatorFunc = std::function<DisplayAdaptor *(const IBlock &, ConstBlockDataID)>; void registerDisplayAdaptorCreator( const DisplayAdaptorCreatorFunc & creatorFunc ); static void breakpoint( const std::string & comment, const std::string & file, int line ); diff --git a/src/gui/PropertyTree.h b/src/gui/PropertyTree.h index df1965d7e..30bb247e3 100644 --- a/src/gui/PropertyTree.h +++ b/src/gui/PropertyTree.h @@ -52,7 +52,7 @@ namespace gui { # ifdef WALBERLA_ENABLE_GUI typedef QStandardItem* ItemID; # else - typedef void * ItemID; + using ItemID = void *; # endif PropertyTree(); diff --git a/src/lbm/MassEvaluation.h b/src/lbm/MassEvaluation.h index 5a12f9c13..9757137db 100644 --- a/src/lbm/MassEvaluation.h +++ b/src/lbm/MassEvaluation.h @@ -96,7 +96,7 @@ shared_ptr< walberla::field::MassEvaluation< DensityField_T > > makeMassEvaluati const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); return evaluation; @@ -111,7 +111,7 @@ makeMassEvaluation( const shared_ptr< StructuredBlockStorage > & blocks, const u const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T> > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, walberla::field::FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, fluid ), plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); @@ -126,7 +126,7 @@ shared_ptr< walberla::field::MassEvaluation< DensityField_T, Filter_T > > makeMa const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T, Filter_T > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, Filter_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); return evaluation; @@ -143,7 +143,7 @@ makeMassEvaluation( const shared_ptr< StructuredBlockStorage > & blocks, const u const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T, field::DefaultEvaluationFilter, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, field::DefaultEvaluationFilter, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); return evaluation; @@ -158,7 +158,7 @@ makeMassEvaluation( const shared_ptr< StructuredBlockStorage > & blocks, const u const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, walberla::field::FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, fluid ), plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); @@ -174,7 +174,7 @@ makeMassEvaluation( const shared_ptr< StructuredBlockStorage > & blocks, const u const Set<SUID> & requiredSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { - typedef walberla::field::MassEvaluation< DensityField_T, Filter_T, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, Filter_T, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, plotFrequency, logFrequency, filename, requiredSelectors, incompatibleSelectors ) ); evaluation->setDomainNormalization( internal::massEvaluationDomain( blocks, level ) ); return evaluation; @@ -202,7 +202,7 @@ shared_ptr< walberla::field::MassEvaluation< DensityField_T > > makeMassEvaluati const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() } @@ -217,7 +217,7 @@ makeMassEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T> > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, walberla::field::FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, fluid ), defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() @@ -232,7 +232,7 @@ shared_ptr< walberla::field::MassEvaluation< DensityField_T, Filter_T > > makeMa const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T, Filter_T > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, Filter_T>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() } @@ -249,7 +249,7 @@ makeMassEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T, field::DefaultEvaluationFilter, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, field::DefaultEvaluationFilter, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() } @@ -264,7 +264,7 @@ makeMassEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, walberla::field::FlagFieldEvaluationFilter<FlagField_T>, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, walberla::field::FlagFieldEvaluationFilter<FlagField_T>( flagFieldId, fluid ), defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() @@ -280,7 +280,7 @@ makeMassEvaluation( const Config_T & config, const Set<SUID> & incompatibleSelectors = Set<SUID>::emptySet() ) { WALBERLA_LBM_MAKE_MASS_EVALUATION_CONFIG_PARSER( config ) - typedef walberla::field::MassEvaluation< DensityField_T, Filter_T, Pseudo2D > ME_T; + using ME_T = walberla::field::MassEvaluation<DensityField_T, Filter_T, Pseudo2D>; auto evaluation = shared_ptr< ME_T >( new ME_T( blocks, fieldId, filter, defaultPlotFrequency, defaultLogFrequency, defaultFilename, requiredSelectors, incompatibleSelectors ) ); WALBERLA_FIELD_MAKE_MASS_EVALUATION_SET_AND_RETURN() } diff --git a/src/lbm/blockforest/PostProcessing.h b/src/lbm/blockforest/PostProcessing.h index 361303cc1..e0037f506 100644 --- a/src/lbm/blockforest/PostProcessing.h +++ b/src/lbm/blockforest/PostProcessing.h @@ -36,7 +36,7 @@ namespace lbm { namespace internal { - typedef field::Field< uint8_t, 1 > MarkerField_T; + using MarkerField_T = field::Field<uint8_t, 1>; } @@ -47,9 +47,9 @@ class PostProcessing { public: - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef typename NeighborsStencil<LatticeModel_T>::type NeighborsStencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; + using NeighborsStencil_T = typename NeighborsStencil<LatticeModel_T>::type; PostProcessing( const BlockDataID & pdfFieldId, const BlockDataID & markerFieldId, const Filter_T & filter ) : pdfFieldId_( pdfFieldId ), markerFieldId_( markerFieldId ), filter_( filter ) @@ -316,7 +316,7 @@ class MarkerFieldGenerator { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; MarkerFieldGenerator( const BlockDataID & pdfFieldId, const BlockDataID & markerFieldId, const Filter_T & filter ) : pdfFieldId_( pdfFieldId ), markerFieldId_( markerFieldId ), filter_( filter ) @@ -371,7 +371,7 @@ class MarkerData : public blockforest::BlockDataHandling< internal::MarkerField_ { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; MarkerData( const BlockDataID & pdfFieldId, const Filter_T & filter ) : pdfFieldId_( pdfFieldId ), filter_( filter ) diff --git a/src/lbm/boundary/Curved.h b/src/lbm/boundary/Curved.h index 045a02398..927554389 100644 --- a/src/lbm/boundary/Curved.h +++ b/src/lbm/boundary/Curved.h @@ -48,11 +48,11 @@ namespace lbm { template< typename LatticeModel_T, typename FlagField_T > class Curved : public Boundary< typename FlagField_T::flag_t > { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; - typedef typename FlagField_T::flag_t flag_t; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; - typedef GhostLayerField< shared_ptr< std::array<real_t, Stencil::Size> >, 1 > WeightField; + using WeightField = GhostLayerField<shared_ptr<std::array<real_t, Stencil::Size>>, 1>; public: diff --git a/src/lbm/boundary/DiffusionDirichlet.h b/src/lbm/boundary/DiffusionDirichlet.h index 96a560085..643027743 100644 --- a/src/lbm/boundary/DiffusionDirichlet.h +++ b/src/lbm/boundary/DiffusionDirichlet.h @@ -51,10 +51,10 @@ class DiffusionDirichlet : public Boundary<flag_t> static_assert( LatticeModel_T::compressible, "Only works with compressible models!" ); //static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< real_t, 1 > ScalarField; + using ScalarField = GhostLayerField<real_t, 1>; public: diff --git a/src/lbm/boundary/DynamicUBB.h b/src/lbm/boundary/DynamicUBB.h index 945cc36f3..07aac83ce 100644 --- a/src/lbm/boundary/DynamicUBB.h +++ b/src/lbm/boundary/DynamicUBB.h @@ -54,10 +54,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t, typename VelocityFunctor_T, bool AdaptVelocityToExternalForce = false, bool StoreForce = false > class DynamicUBB : public Boundary<flag_t> { - typedef lbm::PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = lbm::PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField; + using ForceField = GhostLayerField<Vector3<real_t>, 1>; public: diff --git a/src/lbm/boundary/FreeDiffusion.h b/src/lbm/boundary/FreeDiffusion.h index d264eda6d..4e7aab582 100644 --- a/src/lbm/boundary/FreeDiffusion.h +++ b/src/lbm/boundary/FreeDiffusion.h @@ -33,8 +33,8 @@ namespace lbm { template< typename LatticeModel_T, typename FlagField_T > class FreeDiffusion : public FreeSlip< LatticeModel_T, FlagField_T > { protected: - typedef typename FreeSlip< LatticeModel_T, FlagField_T >::flag_t flag_t; - typedef typename FreeSlip< LatticeModel_T, FlagField_T >::PDFField PDFField; + using flag_t = typename FreeSlip<LatticeModel_T, FlagField_T>::flag_t; + using PDFField = typename FreeSlip<LatticeModel_T, FlagField_T>::PDFField; public: FreeDiffusion( const BoundaryUID& boundaryUID, const FlagUID& uid, PDFField* const pdfField, const FlagField_T* const flagField, const flag_t domain ) diff --git a/src/lbm/boundary/FreeSlip.h b/src/lbm/boundary/FreeSlip.h index 14d3cd0f1..1f5a35be9 100644 --- a/src/lbm/boundary/FreeSlip.h +++ b/src/lbm/boundary/FreeSlip.h @@ -46,9 +46,9 @@ template< typename LatticeModel_T, typename FlagField_T > class FreeSlip : public Boundary< typename FlagField_T::flag_t > { protected: - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; - typedef typename FlagField_T::flag_t flag_t; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; public: diff --git a/src/lbm/boundary/NoDiffusion.h b/src/lbm/boundary/NoDiffusion.h index f6bbec40b..fb0e295ce 100644 --- a/src/lbm/boundary/NoDiffusion.h +++ b/src/lbm/boundary/NoDiffusion.h @@ -33,7 +33,7 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t > class NoDiffusion : public NoSlip< LatticeModel_T, flag_t > { protected: - typedef typename NoSlip< LatticeModel_T, flag_t >::PDFField PDFField; + using PDFField = typename NoSlip<LatticeModel_T, flag_t>::PDFField; public: NoDiffusion( const BoundaryUID& boundaryUID, const FlagUID& uid, PDFField* const pdfField ) diff --git a/src/lbm/boundary/NoSlip.h b/src/lbm/boundary/NoSlip.h index dc769d345..3c52f5872 100644 --- a/src/lbm/boundary/NoSlip.h +++ b/src/lbm/boundary/NoSlip.h @@ -47,10 +47,10 @@ class NoSlip : public Boundary<flag_t> { protected: - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField; + using ForceField = GhostLayerField<Vector3<real_t>, 1>; public: diff --git a/src/lbm/boundary/Outlet.h b/src/lbm/boundary/Outlet.h index da59ec47c..c512345b7 100644 --- a/src/lbm/boundary/Outlet.h +++ b/src/lbm/boundary/Outlet.h @@ -47,9 +47,9 @@ template< typename LatticeModel_T, typename FlagField_T, int Numerator = 2, int class Outlet : public Boundary< typename FlagField_T::flag_t > { protected: - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; - typedef typename FlagField_T::flag_t flag_t; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; public: diff --git a/src/lbm/boundary/ParserUBB.h b/src/lbm/boundary/ParserUBB.h index 2ef68c194..98aae788e 100644 --- a/src/lbm/boundary/ParserUBB.h +++ b/src/lbm/boundary/ParserUBB.h @@ -50,10 +50,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t, bool AdaptVelocityToExternalForce = false, bool StoreForce = false > class ParserUBB : public Boundary<flag_t> { - typedef lbm::PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = lbm::PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField; + using ForceField = GhostLayerField<Vector3<real_t>, 1>; public: @@ -108,8 +108,8 @@ public: return velocity != nullptr; } - typedef GhostLayerField< shared_ptr<Parser>, 1 > ParserField; - typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField; + using ParserField = GhostLayerField<shared_ptr<Parser>, 1>; + using VelocityField = GhostLayerField<Vector3<real_t>, 1>; static shared_ptr<Parser> createConfiguration( const Config::BlockHandle & config ) { return make_shared<Parser>( config ); } diff --git a/src/lbm/boundary/Pressure.h b/src/lbm/boundary/Pressure.h index 8dafb7e46..bbb93f770 100644 --- a/src/lbm/boundary/Pressure.h +++ b/src/lbm/boundary/Pressure.h @@ -48,10 +48,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t > class Pressure : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< real_t, 1 > LatticeDensityField; + using LatticeDensityField = GhostLayerField<real_t, 1>; public: diff --git a/src/lbm/boundary/SimpleDiffusionDirichlet.h b/src/lbm/boundary/SimpleDiffusionDirichlet.h index 1aca569bb..e3a6dde2f 100644 --- a/src/lbm/boundary/SimpleDiffusionDirichlet.h +++ b/src/lbm/boundary/SimpleDiffusionDirichlet.h @@ -51,8 +51,8 @@ class SimpleDiffusionDirichlet : public Boundary<flag_t> static_assert( LatticeModel_T::compressible, "Only works with compressible models!" ); //static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; public: diff --git a/src/lbm/boundary/SimplePAB.h b/src/lbm/boundary/SimplePAB.h index b4cd589cf..f35429958 100644 --- a/src/lbm/boundary/SimplePAB.h +++ b/src/lbm/boundary/SimplePAB.h @@ -57,11 +57,11 @@ class SimplePAB : public Boundary<typename FlagFieldT::flag_t> static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; - typedef typename FlagFieldT::flag_t flag_t; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; + using flag_t = typename FlagFieldT::flag_t; - typedef Vector3<real_t> Vec3Real; + using Vec3Real = Vector3<real_t>; public: diff --git a/src/lbm/boundary/SimplePressure.h b/src/lbm/boundary/SimplePressure.h index d7b39045f..543360d91 100644 --- a/src/lbm/boundary/SimplePressure.h +++ b/src/lbm/boundary/SimplePressure.h @@ -48,10 +48,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t > class SimplePressure : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef Vector3<real_t> Vec3Real; + using Vec3Real = Vector3<real_t>; public: diff --git a/src/lbm/boundary/SimpleUBB.h b/src/lbm/boundary/SimpleUBB.h index ba07eedc4..8c1c93af0 100644 --- a/src/lbm/boundary/SimpleUBB.h +++ b/src/lbm/boundary/SimpleUBB.h @@ -48,10 +48,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t, bool AdaptVelocityToExternalForce = false, bool StoreForce = false > class SimpleUBB : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField; + using ForceField = GhostLayerField<Vector3<real_t>, 1>; public: diff --git a/src/lbm/boundary/SimpleVelocityBoundary.h b/src/lbm/boundary/SimpleVelocityBoundary.h index edb6a4d94..1eda8237c 100644 --- a/src/lbm/boundary/SimpleVelocityBoundary.h +++ b/src/lbm/boundary/SimpleVelocityBoundary.h @@ -47,8 +47,8 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t > class SimpleVelocityBoundary : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; public: diff --git a/src/lbm/boundary/UBB.h b/src/lbm/boundary/UBB.h index e2621fb2f..c866776d2 100644 --- a/src/lbm/boundary/UBB.h +++ b/src/lbm/boundary/UBB.h @@ -49,12 +49,12 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t, bool AdaptVelocityToExternalForce = false, bool StoreForce = false > class UBB : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< Vector3<real_t>, 1 > VelField; + using VelField = GhostLayerField<Vector3<real_t>, 1>; - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField; + using ForceField = GhostLayerField<Vector3<real_t>, 1>; public: diff --git a/src/lbm/boundary/VelocityBoundary.h b/src/lbm/boundary/VelocityBoundary.h index 0673f5a28..c5be0e0a6 100644 --- a/src/lbm/boundary/VelocityBoundary.h +++ b/src/lbm/boundary/VelocityBoundary.h @@ -48,10 +48,10 @@ namespace lbm { template< typename LatticeModel_T, typename flag_t > class VelocityBoundary : public Boundary<flag_t> { - typedef PdfField< LatticeModel_T > PDFField; - typedef typename LatticeModel_T::Stencil Stencil; + using PDFField = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; - typedef GhostLayerField< shared_ptr< std::vector<real_t> >, 1 > VelField; + using VelField = GhostLayerField<shared_ptr<std::vector<real_t>>, 1>; public: diff --git a/src/lbm/boundary/factories/DefaultBoundaryHandling.h b/src/lbm/boundary/factories/DefaultBoundaryHandling.h index 328bd1aac..bdd2fb493 100644 --- a/src/lbm/boundary/factories/DefaultBoundaryHandling.h +++ b/src/lbm/boundary/factories/DefaultBoundaryHandling.h @@ -71,16 +71,16 @@ template <typename LatticeModel, typename FlagFieldT > class DefaultBoundaryHandlingFactory { public: - typedef typename FlagFieldT::flag_t flag_t; - typedef typename LatticeModel::Stencil Stencil; - typedef NoSlip< LatticeModel, flag_t > BcNoSlip; - typedef FreeSlip< LatticeModel, FlagFieldT > BcFreeSlip; - typedef SimpleUBB< LatticeModel, flag_t > BcSimpleUBB; - typedef SimplePressure< LatticeModel, flag_t > BcSimplePressure; - typedef Vector3<real_t> Velocity; - typedef PdfField< LatticeModel > PdfFieldLM; - - typedef walberla::boundary::BoundaryHandling< FlagFieldT, Stencil, BcNoSlip, BcFreeSlip, BcSimpleUBB, BcSimpleUBB, BcSimplePressure, BcSimplePressure > BoundaryHandling; + using flag_t = typename FlagFieldT::flag_t; + using Stencil = typename LatticeModel::Stencil; + using BcNoSlip = NoSlip<LatticeModel, flag_t>; + using BcFreeSlip = FreeSlip<LatticeModel, FlagFieldT>; + using BcSimpleUBB = SimpleUBB<LatticeModel, flag_t>; + using BcSimplePressure = SimplePressure<LatticeModel, flag_t>; + using Velocity = Vector3<real_t>; + using PdfFieldLM = PdfField<LatticeModel>; + + using BoundaryHandling = walberla::boundary::BoundaryHandling<FlagFieldT, Stencil, BcNoSlip, BcFreeSlip, BcSimpleUBB, BcSimpleUBB, BcSimplePressure, BcSimplePressure>; static BlockDataID addBoundaryHandlingToStorage( const shared_ptr< StructuredBlockStorage > & bs, const std::string & identifier, BlockDataID flagFieldID, BlockDataID pdfFieldID, const Set< FlagUID > & flagUIDSet, diff --git a/src/lbm/boundary/factories/DefaultBoundaryHandlingCollection.h b/src/lbm/boundary/factories/DefaultBoundaryHandlingCollection.h index 54aafd334..49e77691a 100644 --- a/src/lbm/boundary/factories/DefaultBoundaryHandlingCollection.h +++ b/src/lbm/boundary/factories/DefaultBoundaryHandlingCollection.h @@ -37,11 +37,11 @@ template< typename LatticeModel_T, typename DiffusionLatticeModel_T, typename Fl class DefaultBoundaryHandlingCollectionFactory { private: - typedef typename DefaultBoundaryHandlingFactory < LatticeModel_T, FlagField_T >::BoundaryHandling DefaultBoundaryHandling_T; - typedef typename DefaultDiffusionBoundaryHandlingFactory< DiffusionLatticeModel_T, FlagField_T >::BoundaryHandling_T DefaultDiffusionBoundaryHandlingFactory_T; + using DefaultBoundaryHandling_T = typename DefaultBoundaryHandlingFactory<LatticeModel_T, FlagField_T>::BoundaryHandling; + using DefaultDiffusionBoundaryHandlingFactory_T = typename DefaultDiffusionBoundaryHandlingFactory<DiffusionLatticeModel_T, FlagField_T>::BoundaryHandling_T; public: - typedef BoundaryHandlingCollection< FlagField_T, DefaultBoundaryHandling_T &, DefaultDiffusionBoundaryHandlingFactory_T & > BoundaryHandlingCollection_T; + using BoundaryHandlingCollection_T = BoundaryHandlingCollection<FlagField_T, DefaultBoundaryHandling_T &, DefaultDiffusionBoundaryHandlingFactory_T &>; private: diff --git a/src/lbm/boundary/factories/DefaultDiffusionBoundaryHandling.h b/src/lbm/boundary/factories/DefaultDiffusionBoundaryHandling.h index e32559776..99754f88f 100644 --- a/src/lbm/boundary/factories/DefaultDiffusionBoundaryHandling.h +++ b/src/lbm/boundary/factories/DefaultDiffusionBoundaryHandling.h @@ -44,19 +44,19 @@ template< typename LatticeModel_T, typename FlagField_T > class DefaultDiffusionBoundaryHandlingFactory { private: - typedef typename FlagField_T::flag_t flag_t; + using flag_t = typename FlagField_T::flag_t; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; public: - typedef lbm::DiffusionDirichlet < LatticeModel_T, flag_t > DiffusionDirichlet_T; - typedef lbm::SimpleDiffusionDirichlet< LatticeModel_T, flag_t > SimpleDiffusionDirichlet_T; - typedef lbm::NoDiffusion < LatticeModel_T, flag_t > NoDiffusion_T; - typedef lbm::FreeDiffusion < LatticeModel_T, FlagField_T > FreeDiffusion_T; + using DiffusionDirichlet_T = lbm::DiffusionDirichlet<LatticeModel_T, flag_t>; + using SimpleDiffusionDirichlet_T = lbm::SimpleDiffusionDirichlet<LatticeModel_T, flag_t>; + using NoDiffusion_T = lbm::NoDiffusion<LatticeModel_T, flag_t>; + using FreeDiffusion_T = lbm::FreeDiffusion<LatticeModel_T, FlagField_T>; public: - typedef walberla::boundary::BoundaryHandling< FlagField_T, Stencil, DiffusionDirichlet_T, SimpleDiffusionDirichlet_T, NoDiffusion_T, FreeDiffusion_T, SimpleDiffusionDirichlet_T, SimpleDiffusionDirichlet_T > BoundaryHandling_T; - typedef BoundaryHandling_T BoundaryHandling; + using BoundaryHandling_T = walberla::boundary::BoundaryHandling<FlagField_T, Stencil, DiffusionDirichlet_T, SimpleDiffusionDirichlet_T, NoDiffusion_T, FreeDiffusion_T, SimpleDiffusionDirichlet_T, SimpleDiffusionDirichlet_T>; + using BoundaryHandling = BoundaryHandling_T; const static FlagUID& getDiffusionDirichletFlagUID() { static FlagUID uid( "DiffusionDirichlet" ); return uid; } const static FlagUID& getSimpleDiffusionDirichletFlagUID() { static FlagUID uid( "SimpleDiffusionDirichlet" ); return uid; } @@ -87,7 +87,7 @@ private: static BoundaryHandling_T* createDefaultDiffusionBoundaryHandlingFactory( IBlock* const block, const StructuredBlockStorage* const /*bs*/, const BlockDataID& flagFieldID, const Set< FlagUID > & domainFlagUIDs, const BlockDataID& pdfFieldID, const Set< FlagUID > & initFlagUIDs ) { - typedef lbm::PdfField< LatticeModel_T > PDFField_T; + using PDFField_T = lbm::PdfField<LatticeModel_T>; WALBERLA_ASSERT_NOT_NULLPTR( block ); diff --git a/src/lbm/boundary/factories/ExtendedBoundaryHandlingFactory.h b/src/lbm/boundary/factories/ExtendedBoundaryHandlingFactory.h index 118065cff..730ceb008 100644 --- a/src/lbm/boundary/factories/ExtendedBoundaryHandlingFactory.h +++ b/src/lbm/boundary/factories/ExtendedBoundaryHandlingFactory.h @@ -72,19 +72,19 @@ template <typename LatticeModel, typename FlagFieldT > class ExtendedBoundaryHandlingFactory { public: - typedef typename FlagFieldT::flag_t flag_t; - typedef typename LatticeModel::Stencil Stencil; - typedef Vector3<real_t> Velocity; - typedef PdfField< LatticeModel > PdfFieldLM; - - typedef NoSlip< LatticeModel, flag_t > BcNoSlip; - typedef FreeSlip< LatticeModel, FlagFieldT > BcFreeSlip; - typedef Pressure< LatticeModel, flag_t > BcPressure; - typedef ParserUBB<LatticeModel, flag_t> BcUBB; - typedef Outlet<LatticeModel, FlagFieldT > BcOutlet; - typedef Curved<LatticeModel, FlagFieldT > BcCurved; - - typedef walberla::boundary::BoundaryHandling< FlagFieldT, Stencil, BcNoSlip, BcFreeSlip, BcPressure, BcUBB, BcOutlet, BcCurved > BoundaryHandling; + using flag_t = typename FlagFieldT::flag_t; + using Stencil = typename LatticeModel::Stencil; + using Velocity = Vector3<real_t>; + using PdfFieldLM = PdfField<LatticeModel>; + + using BcNoSlip = NoSlip<LatticeModel, flag_t>; + using BcFreeSlip = FreeSlip<LatticeModel, FlagFieldT>; + using BcPressure = Pressure<LatticeModel, flag_t>; + using BcUBB = ParserUBB<LatticeModel, flag_t>; + using BcOutlet = Outlet<LatticeModel, FlagFieldT>; + using BcCurved = Curved<LatticeModel, FlagFieldT>; + + using BoundaryHandling = walberla::boundary::BoundaryHandling<FlagFieldT, Stencil, BcNoSlip, BcFreeSlip, BcPressure, BcUBB, BcOutlet, BcCurved>; static BlockDataID addBoundaryHandlingToStorage( const shared_ptr< StructuredBlockStorage > & bs, const std::string & identifier, BlockDataID flagFieldID, BlockDataID pdfFieldID, const Set< FlagUID > & flagUIDSet) diff --git a/src/lbm/evaluations/Permeability.h b/src/lbm/evaluations/Permeability.h index 997bda395..94e146f24 100644 --- a/src/lbm/evaluations/Permeability.h +++ b/src/lbm/evaluations/Permeability.h @@ -43,12 +43,12 @@ class Permeability { public: - typedef PdfField_T PdfField; - typedef BoundaryHandling_T BoundaryHandling; + using PdfField = PdfField_T; + using BoundaryHandling = BoundaryHandling_T; - typedef typename PdfField_T::LatticeModel LatticeModel; - typedef typename BoundaryHandling_T::FlagField FlagField; - typedef typename FlagField::flag_t flag_t; + using LatticeModel = typename PdfField_T::LatticeModel; + using FlagField = typename BoundaryHandling_T::FlagField; + using flag_t = typename FlagField::flag_t; Permeability( real_t viscosity, const BlockDataID & pdfFieldId, const BlockDataID & boundaryHandlingId, const FlagUID & fluid, const shared_ptr<blockforest::StructuredBlockForest> blocks ); diff --git a/src/lbm/field/Adaptors.h b/src/lbm/field/Adaptors.h index 4bb36ca5c..f0c7ee172 100644 --- a/src/lbm/field/Adaptors.h +++ b/src/lbm/field/Adaptors.h @@ -37,9 +37,9 @@ template< typename LatticeModel_T > class DensityAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef real_t value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = real_t; static const uint_t F_SIZE = 1u; @@ -62,9 +62,9 @@ template< typename LatticeModel_T > class VelocityVectorAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef Vector3<real_t> value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = Vector3<real_t>; static const uint_t F_SIZE = 1u; @@ -86,11 +86,11 @@ template< typename LatticeModel_T, bool stream = false > class MomentumDensityVectorAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef Vector3<real_t> value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = Vector3<real_t>; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static const uint_t F_SIZE = 1u; @@ -114,9 +114,9 @@ template< typename LatticeModel_T > class VelocityAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef real_t value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = real_t; static const uint_t F_SIZE = 3u; @@ -142,11 +142,11 @@ template< typename LatticeModel_T, bool stream = false > class MomentumDensityAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef real_t value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = real_t; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static const uint_t F_SIZE = 3u; @@ -173,9 +173,9 @@ template< typename LatticeModel_T > class ShearRateAdaptionFunction { public: - typedef PdfField< LatticeModel_T > basefield_t; - typedef typename basefield_t::const_base_iterator basefield_iterator; - typedef real_t value_type; + using basefield_t = PdfField<LatticeModel_T>; + using basefield_iterator = typename basefield_t::const_base_iterator; + using value_type = real_t; static const uint_t F_SIZE = 1u; @@ -199,15 +199,15 @@ public: template< typename LatticeModel_T > struct Adaptor { - typedef field::GhostLayerFieldAdaptor<DensityAdaptionFunction <LatticeModel_T>, 0> Density; - typedef field::GhostLayerFieldAdaptor<VelocityVectorAdaptionFunction<LatticeModel_T>, 0> VelocityVector; - typedef field::GhostLayerFieldAdaptor<VelocityAdaptionFunction <LatticeModel_T>, 0> Velocity; - typedef field::GhostLayerFieldAdaptor<ShearRateAdaptionFunction <LatticeModel_T>, 0> ShearRate; - - typedef field::GhostLayerFieldAdaptor<MomentumDensityVectorAdaptionFunction<LatticeModel_T, true >, 1> StreamMomentumDensityVector; - typedef field::GhostLayerFieldAdaptor<MomentumDensityAdaptionFunction <LatticeModel_T, true >, 1> StreamMomentumDensity; - typedef field::GhostLayerFieldAdaptor<MomentumDensityVectorAdaptionFunction<LatticeModel_T, false>, 0> CollideMomentumDensityVector; - typedef field::GhostLayerFieldAdaptor<MomentumDensityAdaptionFunction <LatticeModel_T, false>, 0> CollideMomentumDensity; + using Density = field::GhostLayerFieldAdaptor<DensityAdaptionFunction<LatticeModel_T>, 0>; + using VelocityVector = field::GhostLayerFieldAdaptor<VelocityVectorAdaptionFunction<LatticeModel_T>, 0>; + using Velocity = field::GhostLayerFieldAdaptor<VelocityAdaptionFunction<LatticeModel_T>, 0>; + using ShearRate = field::GhostLayerFieldAdaptor<ShearRateAdaptionFunction<LatticeModel_T>, 0>; + + using StreamMomentumDensityVector = field::GhostLayerFieldAdaptor<MomentumDensityVectorAdaptionFunction<LatticeModel_T, true>, 1>; + using StreamMomentumDensity = field::GhostLayerFieldAdaptor<MomentumDensityAdaptionFunction<LatticeModel_T, true>, 1>; + using CollideMomentumDensityVector = field::GhostLayerFieldAdaptor<MomentumDensityVectorAdaptionFunction<LatticeModel_T, false>, 0>; + using CollideMomentumDensity = field::GhostLayerFieldAdaptor<MomentumDensityAdaptionFunction<LatticeModel_T, false>, 0>; }; diff --git a/src/lbm/field/AddToStorage.h b/src/lbm/field/AddToStorage.h index 287673ad4..cd3319a8b 100644 --- a/src/lbm/field/AddToStorage.h +++ b/src/lbm/field/AddToStorage.h @@ -40,8 +40,8 @@ class PdfFieldHandling : public field::BlockDataHandling< PdfField<LatticeModel_ { public: - typedef PdfField<LatticeModel_T> PdfField_T; - typedef field::BlockDataHandling< PdfField_T, LatticeModel_T::Stencil::D == 2 > Base_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Base_T = field::BlockDataHandling<PdfField_T, LatticeModel_T::Stencil::D == 2>; PdfFieldHandling( const weak_ptr< StructuredBlockStorage > & blocks, const LatticeModel_T & latticeModel, const bool _initialize, const Vector3<real_t> & initialVelocity, const real_t initialDensity, diff --git a/src/lbm/field/DensityAndMomentumDensity.h b/src/lbm/field/DensityAndMomentumDensity.h index db732eb01..5a1d139b9 100644 --- a/src/lbm/field/DensityAndMomentumDensity.h +++ b/src/lbm/field/DensityAndMomentumDensity.h @@ -112,7 +112,7 @@ real_t getDensityAndMomentumDensityD3Q19( Vector3< real_t > & momentumDensity, c static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "This function works with D3Q19 stencils only!" ); using namespace stencil; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; momentumDensity[0] = it[ Stencil::idx[E] ] + it[ Stencil::idx[NE] ] + it[ Stencil::idx[SE] ] + it[ Stencil::idx[TE] ] + it[ Stencil::idx[BE] ] ; momentumDensity[1] = it[ Stencil::idx[N] ] + it[ Stencil::idx[NW] ] + it[ Stencil::idx[TN] ] + it[ Stencil::idx[BN] ]; @@ -138,7 +138,7 @@ real_t getDensityAndMomentumDensityD3Q19( Vector3< real_t > & momentumDensity, c static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "This function works with D3Q19 stencils only!" ); using namespace stencil; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; const auto & xyz0 = pdf(x,y,z,0); diff --git a/src/lbm/field/Equilibrium.h b/src/lbm/field/Equilibrium.h index 8b6635431..1fcd48033 100644 --- a/src/lbm/field/Equilibrium.h +++ b/src/lbm/field/Equilibrium.h @@ -210,7 +210,7 @@ struct Equilibrium< LatticeModel_T, typename std::enable_if< std::is_same< typen static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; template< typename FieldPtrOrIterator > static void set( FieldPtrOrIterator & it, @@ -359,7 +359,7 @@ struct Equilibrium< LatticeModel_T, typename std::enable_if< std::is_same< typen static_assert( LatticeModel_T::compressible, "Only works with compressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; template< typename FieldPtrOrIterator > static void set( FieldPtrOrIterator & it, diff --git a/src/lbm/field/MomentumDensity.h b/src/lbm/field/MomentumDensity.h index 782e82ef4..0a79a0fdc 100644 --- a/src/lbm/field/MomentumDensity.h +++ b/src/lbm/field/MomentumDensity.h @@ -103,7 +103,7 @@ void getMomentumDensityD3Q19( Vector3< real_t > & momentumDensity, const FieldPt static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "This function works with D3Q19 stencils only!" ); using namespace stencil; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; momentumDensity[0] = it[ Stencil::idx[E] ] + it[ Stencil::idx[NE] ] + it[ Stencil::idx[SE] ] + it[ Stencil::idx[TE] ] + it[ Stencil::idx[BE] ] - it[ Stencil::idx[W] ] - it[ Stencil::idx[NW] ] - it[ Stencil::idx[SW] ] - it[ Stencil::idx[TW] ] - it[ Stencil::idx[BW] ]; @@ -120,7 +120,7 @@ void getMomentumDensityD3Q19( Vector3< real_t > & momentumDensity, const PdfFiel static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "This function works with D3Q19 stencils only!" ); using namespace stencil; - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; const auto & xyz0 = pdf(x,y,z,0); diff --git a/src/lbm/field/PdfField.h b/src/lbm/field/PdfField.h index a9438e42b..178804a88 100644 --- a/src/lbm/field/PdfField.h +++ b/src/lbm/field/PdfField.h @@ -78,22 +78,22 @@ public: //** Type Definitions ********************************************************************************************** /*! \name Type Definitions */ //@{ - typedef LatticeModel_T LatticeModel; - typedef typename LatticeModel_T::Stencil Stencil; + using LatticeModel = LatticeModel_T; + using Stencil = typename LatticeModel_T::Stencil; - typedef typename GhostLayerField< real_t, Stencil::Size >::value_type value_type; + using value_type = typename GhostLayerField<real_t, Stencil::Size>::value_type; - typedef typename GhostLayerField< real_t, Stencil::Size >::iterator iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::const_iterator const_iterator; + using iterator = typename GhostLayerField<real_t, Stencil::Size>::iterator; + using const_iterator = typename GhostLayerField<real_t, Stencil::Size>::const_iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::reverse_iterator reverse_iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::const_reverse_iterator const_reverse_iterator; + using reverse_iterator = typename GhostLayerField<real_t, Stencil::Size>::reverse_iterator; + using const_reverse_iterator = typename GhostLayerField<real_t, Stencil::Size>::const_reverse_iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::base_iterator base_iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::const_base_iterator const_base_iterator; + using base_iterator = typename GhostLayerField<real_t, Stencil::Size>::base_iterator; + using const_base_iterator = typename GhostLayerField<real_t, Stencil::Size>::const_base_iterator; - typedef typename GhostLayerField< real_t, Stencil::Size >::Ptr Ptr; - typedef typename GhostLayerField< real_t, Stencil::Size >::ConstPtr ConstPtr; + using Ptr = typename GhostLayerField<real_t, Stencil::Size>::Ptr; + using ConstPtr = typename GhostLayerField<real_t, Stencil::Size>::ConstPtr; //@} //******************************************************************************************************************* diff --git a/src/lbm/field/ShearRate.h b/src/lbm/field/ShearRate.h index 2352a9782..d98a169a9 100644 --- a/src/lbm/field/ShearRate.h +++ b/src/lbm/field/ShearRate.h @@ -89,8 +89,8 @@ namespace internal { template< typename LatticeModel_T > struct ShearRate { - typedef typename LatticeModel_T::Stencil Stencil; - typedef typename internal::ShearRelaxationParameter<typename LatticeModel_T::CollisionModel> ShearRelaxationParameter; + using Stencil = typename LatticeModel_T::Stencil; + using ShearRelaxationParameter = typename internal::ShearRelaxationParameter<typename LatticeModel_T::CollisionModel>; template< typename FieldPtrOrIterator > static inline real_t get( const LatticeModel_T & latticeModel, const FieldPtrOrIterator & it, diff --git a/src/lbm/field/initializer/ExprSystemInitFunction.h b/src/lbm/field/initializer/ExprSystemInitFunction.h index 4d8557f7c..32d91f43f 100644 --- a/src/lbm/field/initializer/ExprSystemInitFunction.h +++ b/src/lbm/field/initializer/ExprSystemInitFunction.h @@ -43,9 +43,9 @@ class ExprSystemInitFunction { public: - typedef exprtk::symbol_table<real_t> SymbolTable; - typedef exprtk::expression<real_t> Expression; - typedef std::map<std::string, Expression> ExprSystem; + using SymbolTable = exprtk::symbol_table<real_t>; + using Expression = exprtk::expression<real_t>; + using ExprSystem = std::map<std::string, Expression>; ExprSystemInitFunction( const shared_ptr<StructuredBlockForest> & blocks ); ~ExprSystemInitFunction(); diff --git a/src/lbm/field/initializer/PdfFieldInitializer.h b/src/lbm/field/initializer/PdfFieldInitializer.h index 0558b1b52..5a718f8d7 100644 --- a/src/lbm/field/initializer/PdfFieldInitializer.h +++ b/src/lbm/field/initializer/PdfFieldInitializer.h @@ -55,7 +55,7 @@ public: private: - typedef lbm::PdfField<LatticeModel_T> PdfField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; const BlockDataID pdfFieldId_; const shared_ptr<StructuredBlockForest> blocks_; diff --git a/src/lbm/geometry/initializer/PoiseuilleInitializer.h b/src/lbm/geometry/initializer/PoiseuilleInitializer.h index 8f8898556..fa6677a44 100644 --- a/src/lbm/geometry/initializer/PoiseuilleInitializer.h +++ b/src/lbm/geometry/initializer/PoiseuilleInitializer.h @@ -82,7 +82,7 @@ namespace initializer { Z_AXIS=2, INVALID_AXIS=3 };*/ - typedef uint_t Axis; + using Axis = uint_t; static const uint_t X_AXIS; static const uint_t Y_AXIS; static const uint_t Z_AXIS; diff --git a/src/lbm/lattice_model/CollisionModel.h b/src/lbm/lattice_model/CollisionModel.h index c3077e97f..bd521e042 100644 --- a/src/lbm/lattice_model/CollisionModel.h +++ b/src/lbm/lattice_model/CollisionModel.h @@ -81,7 +81,7 @@ class SRT { public: - typedef SRT_tag tag; + using tag = SRT_tag; static const bool constant = true; SRT( const real_t _omega, const uint_t _level = uint_t(0) ) : @@ -138,7 +138,7 @@ class SRTField { public: - typedef SRT_tag tag; + using tag = SRT_tag; static const bool constant = false; SRTField() : @@ -212,7 +212,7 @@ class TRT { public: - typedef TRT_tag tag; + using tag = TRT_tag; static const real_t threeSixteenth; @@ -332,7 +332,7 @@ class D3Q19MRT { public: - typedef MRT_tag tag; + using tag = MRT_tag; static const real_t threeSixteenth; @@ -581,7 +581,7 @@ class D3Q27Cumulant { public: - typedef Cumulant_tag tag; + using tag = Cumulant_tag; /// Initializes all omegas to one except omega1 D3Q27Cumulant( const real_t _omega1, const uint_t _level = uint_t(0) ) : diff --git a/src/lbm/lattice_model/D2Q9.h b/src/lbm/lattice_model/D2Q9.h index 4fe777ead..831159c8f 100644 --- a/src/lbm/lattice_model/D2Q9.h +++ b/src/lbm/lattice_model/D2Q9.h @@ -39,11 +39,11 @@ public: static_assert( ( ! std::is_same< CollisionModel_T, collision_model::D3Q19MRT >::value), "D3Q19MRT only works with D3Q19!" ); - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::CollisionModel CollisionModel; - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::ForceModel ForceModel; + using CollisionModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::CollisionModel; + using ForceModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::ForceModel; - typedef stencil::D2Q9 Stencil; - typedef stencil::D2Q9 CommunicationStencil; + using Stencil = stencil::D2Q9; + using CommunicationStencil = stencil::D2Q9; static const char * NAME; diff --git a/src/lbm/lattice_model/D3Q15.h b/src/lbm/lattice_model/D3Q15.h index a946fce3d..42dc975fd 100644 --- a/src/lbm/lattice_model/D3Q15.h +++ b/src/lbm/lattice_model/D3Q15.h @@ -38,11 +38,11 @@ class D3Q15 : public LatticeModelBase< CollisionModel_T, Compressible, ForceMode { public: - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::CollisionModel CollisionModel; - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::ForceModel ForceModel; + using CollisionModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::CollisionModel; + using ForceModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::ForceModel; - typedef stencil::D3Q15 Stencil; - typedef stencil::D3Q27 CommunicationStencil; + using Stencil = stencil::D3Q15; + using CommunicationStencil = stencil::D3Q27; static const char * NAME; diff --git a/src/lbm/lattice_model/D3Q19.h b/src/lbm/lattice_model/D3Q19.h index d8cfc3dbc..f6decf3cf 100644 --- a/src/lbm/lattice_model/D3Q19.h +++ b/src/lbm/lattice_model/D3Q19.h @@ -37,11 +37,11 @@ class D3Q19 : public LatticeModelBase< CollisionModel_T, Compressible, ForceMode { public: - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::CollisionModel CollisionModel; - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::ForceModel ForceModel; + using CollisionModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::CollisionModel; + using ForceModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::ForceModel; - typedef stencil::D3Q19 Stencil; - typedef stencil::D3Q19 CommunicationStencil; + using Stencil = stencil::D3Q19; + using CommunicationStencil = stencil::D3Q19; static const char * NAME; diff --git a/src/lbm/lattice_model/D3Q27.h b/src/lbm/lattice_model/D3Q27.h index fb8289cbf..e90c078c7 100644 --- a/src/lbm/lattice_model/D3Q27.h +++ b/src/lbm/lattice_model/D3Q27.h @@ -39,11 +39,11 @@ public: static_assert( ( ! std::is_same< CollisionModel_T, collision_model::D3Q19MRT >::value), "D3Q19MRT only works with D3Q19!" ); - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::CollisionModel CollisionModel; - typedef typename LatticeModelBase< CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder >::ForceModel ForceModel; + using CollisionModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::CollisionModel; + using ForceModel = typename LatticeModelBase<CollisionModel_T, Compressible, ForceModel_T, EquilibriumAccuracyOrder>::ForceModel; - typedef stencil::D3Q27 Stencil; - typedef stencil::D3Q27 CommunicationStencil; + using Stencil = stencil::D3Q27; + using CommunicationStencil = stencil::D3Q27; static const char * NAME; diff --git a/src/lbm/lattice_model/EquilibriumDistribution.h b/src/lbm/lattice_model/EquilibriumDistribution.h index 31daeb246..48eab60f5 100644 --- a/src/lbm/lattice_model/EquilibriumDistribution.h +++ b/src/lbm/lattice_model/EquilibriumDistribution.h @@ -71,7 +71,7 @@ public: static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static real_t get( const real_t cx, const real_t cy, const real_t cz, const real_t w, const Vector3< real_t > & velocity = Vector3< real_t >( real_t(0.0) ), const real_t rho = real_t(1.0) ) @@ -127,7 +127,7 @@ public: static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 1, "Only works for lattice models that require the equilibrium distribution to be order 1 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static real_t get( const real_t cx, const real_t cy, const real_t cz, const real_t w, const Vector3< real_t > & velocity = Vector3< real_t >( real_t(0.0) ), const real_t rho = real_t(1.0) ) @@ -176,7 +176,7 @@ public: static_assert( LatticeModel_T::compressible, "Only works with compressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static real_t get( const real_t cx, const real_t cy, const real_t cz, const real_t w, const Vector3< real_t > & velocity = Vector3< real_t >( real_t(0.0) ), const real_t rho = real_t(1.0) ) @@ -231,7 +231,7 @@ public: static_assert( LatticeModel_T::compressible, "Only works with compressible models!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 1, "Only works for lattice models that require the equilibrium distribution to be order 1 accurate!" ); - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static real_t get( const real_t cx, const real_t cy, const real_t cz, const real_t w, const Vector3< real_t > & velocity = Vector3< real_t >( real_t(0.0) ), const real_t rho = real_t(1.0) ) diff --git a/src/lbm/lattice_model/ForceModel.h b/src/lbm/lattice_model/ForceModel.h index b82f05634..0c30441ca 100644 --- a/src/lbm/lattice_model/ForceModel.h +++ b/src/lbm/lattice_model/ForceModel.h @@ -143,8 +143,8 @@ class None { public: - typedef None_tag tag; - typedef NoDirectionIndependentTerms DirectionIndependentTerms_T; + using tag = None_tag; + using DirectionIndependentTerms_T = NoDirectionIndependentTerms; static const bool shiftMacVel = false; static const bool shiftEquVel = false; @@ -180,8 +180,8 @@ class SimpleConstant { public: - typedef Simple_tag tag; - typedef NoDirectionIndependentTerms DirectionIndependentTerms_T; + using tag = Simple_tag; + using DirectionIndependentTerms_T = NoDirectionIndependentTerms; static const bool shiftMacVel = true; static const bool shiftEquVel = false; @@ -277,9 +277,9 @@ private: public: - typedef EDM_tag tag; - typedef real_t DirectionIndependentTerms_T; - typedef ForceField_T ForceField; + using tag = EDM_tag; + using DirectionIndependentTerms_T = real_t; + using ForceField = ForceField_T; static const bool shiftMacVel = true; static const bool shiftEquVel = false; @@ -337,8 +337,8 @@ class LuoConstant { public: - typedef Luo_tag tag; - typedef NoDirectionIndependentTerms DirectionIndependentTerms_T; + using tag = Luo_tag; + using DirectionIndependentTerms_T = NoDirectionIndependentTerms; static const bool shiftMacVel = true; static const bool shiftEquVel = false; @@ -404,9 +404,9 @@ class LuoField { public: - typedef Luo_tag tag; - typedef NoDirectionIndependentTerms DirectionIndependentTerms_T; - typedef ForceField_T ForceField; + using tag = Luo_tag; + using DirectionIndependentTerms_T = NoDirectionIndependentTerms; + using ForceField = ForceField_T; static const bool shiftMacVel = true; static const bool shiftEquVel = false; @@ -460,8 +460,8 @@ class GuoConstant { public: - typedef Guo_tag tag; - typedef Matrix3<real_t> DirectionIndependentTerms_T; + using tag = Guo_tag; + using DirectionIndependentTerms_T = Matrix3<real_t>; static const bool shiftMacVel = true; static const bool shiftEquVel = true; @@ -553,9 +553,9 @@ class GuoField { public: - typedef Guo_tag tag; - typedef Matrix3<real_t> DirectionIndependentTerms_T; - typedef ForceField_T ForceField; + using tag = Guo_tag; + using DirectionIndependentTerms_T = Matrix3<real_t>; + using ForceField = ForceField_T; static const bool shiftMacVel = true; static const bool shiftEquVel = true; @@ -635,8 +635,8 @@ class Correction { public: - typedef Correction_tag tag; - typedef Vector3<real_t> DirectionIndependentTerms_T; + using tag = Correction_tag; + using DirectionIndependentTerms_T = Vector3<real_t>; static const bool shiftMacVel = false; static const bool shiftEquVel = false; diff --git a/src/lbm/lattice_model/LatticeModelBase.h b/src/lbm/lattice_model/LatticeModelBase.h index 82039ee3a..3ded2ae7e 100644 --- a/src/lbm/lattice_model/LatticeModelBase.h +++ b/src/lbm/lattice_model/LatticeModelBase.h @@ -71,8 +71,8 @@ class LatticeModelBase { public: - typedef CollisionModel_T CollisionModel; - typedef ForceModel_T ForceModel; + using CollisionModel = CollisionModel_T; + using ForceModel = ForceModel_T; static const bool compressible = Compressible; static const int equilibriumAccuracyOrder = EquilibriumAccuracyOrder; diff --git a/src/lbm/lattice_model/NeighborsStencil.h b/src/lbm/lattice_model/NeighborsStencil.h index 32badbbd3..823b45383 100644 --- a/src/lbm/lattice_model/NeighborsStencil.h +++ b/src/lbm/lattice_model/NeighborsStencil.h @@ -39,13 +39,13 @@ struct NeighborsStencil; template< typename LatticeModel_T > struct NeighborsStencil< LatticeModel_T, typename std::enable_if< LatticeModel_T::Stencil::D == 2 >::type > { - typedef stencil::D2Q9 type; + using type = stencil::D2Q9; }; template< typename LatticeModel_T > struct NeighborsStencil< LatticeModel_T, typename std::enable_if< LatticeModel_T::Stencil::D == 3 >::type > { - typedef stencil::D3Q27 type; + using type = stencil::D3Q27; }; diff --git a/src/lbm/lattice_model/SmagorinskyLES.h b/src/lbm/lattice_model/SmagorinskyLES.h index 169439e77..167f88e4f 100644 --- a/src/lbm/lattice_model/SmagorinskyLES.h +++ b/src/lbm/lattice_model/SmagorinskyLES.h @@ -44,9 +44,9 @@ class SmagorinskyLES { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using ScalarField_T = GhostLayerField<real_t, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; SmagorinskyLES( weak_ptr< StructuredBlockStorage > blocks, const ConstBlockDataID & pdfFieldId, const BlockDataID & omegaFieldId, const real_t & kinematicViscosity, const real_t & smagorinskyConstant, diff --git a/src/lbm/refinement/CurlBasedLevelDetermination.h b/src/lbm/refinement/CurlBasedLevelDetermination.h index d384449fb..7e9157c31 100644 --- a/src/lbm/refinement/CurlBasedLevelDetermination.h +++ b/src/lbm/refinement/CurlBasedLevelDetermination.h @@ -52,7 +52,7 @@ class CurlBasedLevelDetermination // used as a 'BlockForest::RefreshMinTargetLev public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; CurlBasedLevelDetermination(const ConstBlockDataID & fieldID, const StructuredBlockForest & structuredBlockForest, const Filter_T & filter, const uint_t maxLevel, diff --git a/src/lbm/refinement/EqualLevelBorderStreamCorrection.h b/src/lbm/refinement/EqualLevelBorderStreamCorrection.h index 2cc428b98..957b99adc 100644 --- a/src/lbm/refinement/EqualLevelBorderStreamCorrection.h +++ b/src/lbm/refinement/EqualLevelBorderStreamCorrection.h @@ -47,12 +47,12 @@ struct EdgeCornerStencil; template< typename LatticeModel_T > struct EdgeCornerStencil< LatticeModel_T, typename std::enable_if< LatticeModel_T::Stencil::D == 2 >::type > { - typedef stencil::D2CornerStencil type; + using type = stencil::D2CornerStencil; }; template< typename LatticeModel_T > struct EdgeCornerStencil< LatticeModel_T, typename std::enable_if< LatticeModel_T::Stencil::D == 3 >::type > { - typedef stencil::D3EdgeCornerStencil type; + using type = stencil::D3EdgeCornerStencil; }; } @@ -63,8 +63,8 @@ class EqualLevelBorderStreamCorrection { public: - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename internal::EdgeCornerStencil< LatticeModel_T >::type EdgeCornerStencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using EdgeCornerStencil_T = typename internal::EdgeCornerStencil<LatticeModel_T>::type; EqualLevelBorderStreamCorrection( const BlockDataID & pdfFieldId ) : pdfFieldId_( pdfFieldId ) {} diff --git a/src/lbm/refinement/LinearExplosion.h b/src/lbm/refinement/LinearExplosion.h index c70b7befe..a43f07923 100644 --- a/src/lbm/refinement/LinearExplosion.h +++ b/src/lbm/refinement/LinearExplosion.h @@ -67,12 +67,12 @@ class LinearExplosion { private: - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; - typedef field::GhostLayerField< typename PdfField_T::value_type, PdfField_T::F_SIZE > CoarseField; - typedef field::GhostLayerField< bool, 1 > BoolField; + using CoarseField = field::GhostLayerField<typename PdfField_T::value_type, PdfField_T::F_SIZE>; + using BoolField = field::GhostLayerField<bool, 1>; public: diff --git a/src/lbm/refinement/PdfFieldPackInfo.h b/src/lbm/refinement/PdfFieldPackInfo.h index 7117c64cd..1c1202e4f 100644 --- a/src/lbm/refinement/PdfFieldPackInfo.h +++ b/src/lbm/refinement/PdfFieldPackInfo.h @@ -44,8 +44,8 @@ class PdfFieldPackInfo : public TimeStepPdfPackInfo { public: - typedef PdfField<LatticeModel_T> PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; #ifdef NDEBUG PdfFieldPackInfo( const BlockDataID & pdfFieldId, const bool _optimizedEqualLevelCommunication = true, diff --git a/src/lbm/refinement/TimeStep.h b/src/lbm/refinement/TimeStep.h index 84189ba4b..bafcdcc04 100644 --- a/src/lbm/refinement/TimeStep.h +++ b/src/lbm/refinement/TimeStep.h @@ -53,10 +53,10 @@ class TimeStep { public: - typedef typename NeighborsStencil<LatticeModel_T>::type CommunicationStencil_T; + using CommunicationStencil_T = typename NeighborsStencil<LatticeModel_T>::type; - typedef std::function< void ( const uint_t, const uint_t ) > VoidFunction; // parameters: level, execution count - typedef std::function< void ( IBlock *, const uint_t, const uint_t ) > BlockFunction; // parameters: block, level, execution count + using VoidFunction = std::function<void (const uint_t, const uint_t)>; // parameters: level, execution count + using BlockFunction = std::function<void (IBlock *, const uint_t, const uint_t)>; // parameters: block, level, execution count private: @@ -110,7 +110,7 @@ private: public: - typedef typename LatticeModel_T::Stencil Stencil; + using Stencil = typename LatticeModel_T::Stencil; static const uint_t StreamIncludedGhostLayers = 2; @@ -1726,7 +1726,7 @@ makeTimeStep( weak_ptr< StructuredBlockForest > blocks, shared_ptr< Sweep_T > & const Set<SUID> & requiredBlockSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleBlockSelectors = Set<SUID>::emptySet() ) { - typedef TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T > TS_T; + using TS_T = TimeStep<LatticeModel_T, Sweep_T, BoundaryHandling_T>; return shared_ptr< TS_T >( new TS_T( blocks, sweep, pdfFieldId, boundaryHandlingId, requiredBlockSelectors, incompatibleBlockSelectors ) ); } @@ -1740,7 +1740,7 @@ makeTimeStep( weak_ptr< StructuredBlockForest > blocks, shared_ptr< Sweep_T > & const Set<SUID> & requiredBlockSelectors = Set<SUID>::emptySet(), const Set<SUID> & incompatibleBlockSelectors = Set<SUID>::emptySet() ) { - typedef TimeStep< LatticeModel_T, Sweep_T, BoundaryHandling_T > TS_T; + using TS_T = TimeStep<LatticeModel_T, Sweep_T, BoundaryHandling_T>; return shared_ptr< TS_T >( new TS_T( blocks, sweep, pdfFieldId, boundaryHandlingId, pdfPackInfo, requiredBlockSelectors, incompatibleBlockSelectors ) ); } diff --git a/src/lbm/refinement/VorticityBasedLevelDetermination.h b/src/lbm/refinement/VorticityBasedLevelDetermination.h index c3f4ee20d..2be753c0c 100644 --- a/src/lbm/refinement/VorticityBasedLevelDetermination.h +++ b/src/lbm/refinement/VorticityBasedLevelDetermination.h @@ -49,7 +49,7 @@ class VorticityBasedLevelDetermination // used as a 'BlockForest::RefreshMinTarg public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; VorticityBasedLevelDetermination( const ConstBlockDataID & fieldID, const Filter_T & filter, const real_t upperLimit, const real_t lowerLimit, const uint_t maxLevel ) : diff --git a/src/lbm/srt/SplitPureSweep.impl.h b/src/lbm/srt/SplitPureSweep.impl.h index 3c716216c..e1cfe424b 100644 --- a/src/lbm/srt/SplitPureSweep.impl.h +++ b/src/lbm/srt/SplitPureSweep.impl.h @@ -73,8 +73,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename SweepBase<LatticeModel_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename SweepBase<LatticeModel_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field SplitPureSweep( const BlockDataID & pdfField ) : @@ -768,8 +768,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename SweepBase<LatticeModel_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename SweepBase<LatticeModel_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field SplitPureSweep( const BlockDataID & pdfField ) : diff --git a/src/lbm/srt/SplitSweep.impl.h b/src/lbm/srt/SplitSweep.impl.h index e86dc16b2..b5f6b68fb 100644 --- a/src/lbm/srt/SplitSweep.impl.h +++ b/src/lbm/srt/SplitSweep.impl.h @@ -67,8 +67,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename FlagFieldSweepBase<LatticeModel_T,FlagField_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename FlagFieldSweepBase<LatticeModel_T, FlagField_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field, lbm mask consists of multiple flags SplitSweep( const BlockDataID & pdfField, const ConstBlockDataID & flagField, const Set< FlagUID > & lbmMask ) : @@ -902,8 +902,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename FlagFieldSweepBase<LatticeModel_T,FlagField_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename FlagFieldSweepBase<LatticeModel_T, FlagField_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field, lbm mask consists of multiple flags SplitSweep( const BlockDataID & pdfField, const ConstBlockDataID & flagField, const Set< FlagUID > & lbmMask ) : diff --git a/src/lbm/srt/cell_operations/AdvectionDiffusionCellOperation.impl.h b/src/lbm/srt/cell_operations/AdvectionDiffusionCellOperation.impl.h index 44883340f..f638cf3c9 100644 --- a/src/lbm/srt/cell_operations/AdvectionDiffusionCellOperation.impl.h +++ b/src/lbm/srt/cell_operations/AdvectionDiffusionCellOperation.impl.h @@ -63,9 +63,9 @@ public: static_assert( LM_AdvDiff::compressible, "Only works with compressible models!" ); static_assert( (std::is_same< typename LM_AdvDiff::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); - typedef PdfField< LM_AdvDiff > AdvDiffPdfField_T; - typedef PdfField< LM_Hydro > HydroPdfField_T; - typedef typename LM_AdvDiff::Stencil Stencil; + using AdvDiffPdfField_T = PdfField<LM_AdvDiff>; + using HydroPdfField_T = PdfField<LM_Hydro>; + using Stencil = typename LM_AdvDiff::Stencil; AdvectionDiffusionCellOperation() : omega_( real_t(0) ), advDiffLatticeModel_( NULL ), hydroLatticeModel_(NULL) {} @@ -138,9 +138,9 @@ public: static_assert( LM_AdvDiff::compressible, "Only works with compressible models!" ); static_assert( (std::is_same< typename LM_AdvDiff::ForceModel::tag, force_model::Correction_tag >::value), "Only works with correction force!" ); - typedef PdfField< LM_AdvDiff > AdvDiffPdfField_T; - typedef PdfField< LM_Hydro > HydroPdfField_T; - typedef typename LM_AdvDiff::Stencil Stencil; + using AdvDiffPdfField_T = PdfField<LM_AdvDiff>; + using HydroPdfField_T = PdfField<LM_Hydro>; + using Stencil = typename LM_AdvDiff::Stencil; AdvectionDiffusionCellOperation() : omega_( real_t(0) ), advDiffLatticeModel_( NULL ), hydroLatticeModel_(NULL) {} diff --git a/src/lbm/srt/cell_operations/DefaultCellOperation.impl.h b/src/lbm/srt/cell_operations/DefaultCellOperation.impl.h index 7f1086e77..0cf052e6b 100644 --- a/src/lbm/srt/cell_operations/DefaultCellOperation.impl.h +++ b/src/lbm/srt/cell_operations/DefaultCellOperation.impl.h @@ -65,8 +65,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : omega_( real_t(0) ), latticeModel_( NULL ) {} @@ -136,8 +136,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::Guo_tag >::value), "Only works with Guo constant force model !" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : omega_( real_t(0) ), latticeModel_( NULL ) {} @@ -230,8 +230,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : omega_trm_( real_t(0) ), omega_w0_( real_t(0) ), omega_w1_( real_t(0) ), omega_w2_( real_t(0) ) {} @@ -476,8 +476,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : omega_trm_( real_t(0) ), omega_w0_( real_t(0) ), omega_w1_( real_t(0) ), omega_w2_( real_t(0) ) {} diff --git a/src/lbm/sweeps/ActiveCellSweep.h b/src/lbm/sweeps/ActiveCellSweep.h index cfc3b6d35..4874c36af 100644 --- a/src/lbm/sweeps/ActiveCellSweep.h +++ b/src/lbm/sweeps/ActiveCellSweep.h @@ -35,7 +35,7 @@ class ActiveCellSweep : FlagFieldSweepBase< LatticeModel_T, FlagField_T > { public: - typedef typename FlagFieldSweepBase<LatticeModel_T,FlagField_T>::PdfField_T PdfField_T; + using PdfField_T = typename FlagFieldSweepBase<LatticeModel_T, FlagField_T>::PdfField_T; // block has NO dst pdf field, lbm mask consists of multiple flags ActiveCellSweep( const CellOperation & op, const BlockDataID & pdfField, const ConstBlockDataID & flagField, diff --git a/src/lbm/sweeps/CellwiseSweep.h b/src/lbm/sweeps/CellwiseSweep.h index 2879f19ae..e35e32f64 100644 --- a/src/lbm/sweeps/CellwiseSweep.h +++ b/src/lbm/sweeps/CellwiseSweep.h @@ -410,7 +410,7 @@ shared_ptr< CellwiseSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, Densit makeCellwiseSweep( const BlockDataID & pdfFieldId, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef CellwiseSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T > CS_T; + using CS_T = CellwiseSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>; return shared_ptr< CS_T >( new CS_T( pdfFieldId, filter, densityVelocityIn, densityVelocityOut ) ); } @@ -419,7 +419,7 @@ shared_ptr< CellwiseSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, Densit makeCellwiseSweep( const BlockDataID & src, const BlockDataID & dst, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef CellwiseSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T > CS_T; + using CS_T = CellwiseSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>; return shared_ptr< CS_T >( new CS_T( src, dst, filter, densityVelocityIn, densityVelocityOut ) ); } @@ -520,7 +520,7 @@ shared_ptr< CellwiseSweep< LatticeModel_T, Filter_T, AdvectionDiffusionDensityEq makeCellwiseAdvectionDiffusionSweep( const BlockDataID & pdfFieldId, const ConstBlockDataID & velocityFieldId, const Filter_T & filter, const DensityVelocityOut_T & densityVelocityOut ) { - typedef CellwiseSweep< LatticeModel_T, Filter_T, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>, DensityVelocityOut_T > CS_T; + using CS_T = CellwiseSweep<LatticeModel_T, Filter_T, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>, DensityVelocityOut_T>; return shared_ptr< CS_T >( new CS_T( pdfFieldId, filter, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>( velocityFieldId ), densityVelocityOut ) ); } @@ -530,7 +530,7 @@ shared_ptr< CellwiseSweep< LatticeModel_T, Filter_T, AdvectionDiffusionDensityEq makeCellwiseAdvectionDiffusionSweep( const BlockDataID & src, const BlockDataID & dst, const ConstBlockDataID & velocityFieldId, const Filter_T & filter, const DensityVelocityOut_T & densityVelocityOut ) { - typedef CellwiseSweep< LatticeModel_T, Filter_T, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>, DensityVelocityOut_T > CS_T; + using CS_T = CellwiseSweep<LatticeModel_T, Filter_T, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>, DensityVelocityOut_T>; return shared_ptr< CS_T >( new CS_T( src, dst, filter, AdvectionDiffusionDensityEquilibriumVelocityCalculation<VelocityField_T>( velocityFieldId ), densityVelocityOut ) ); } diff --git a/src/lbm/sweeps/FlagFieldSweepBase.h b/src/lbm/sweeps/FlagFieldSweepBase.h index 3df1dcf95..edf5ed56b 100644 --- a/src/lbm/sweeps/FlagFieldSweepBase.h +++ b/src/lbm/sweeps/FlagFieldSweepBase.h @@ -35,8 +35,8 @@ class FlagFieldSweepBase : public SweepBase<LatticeModel_T> { public: - typedef typename SweepBase< LatticeModel_T >::PdfField_T PdfField_T; - typedef typename FlagField_T::flag_t flag_t; + using PdfField_T = typename SweepBase<LatticeModel_T>::PdfField_T; + using flag_t = typename FlagField_T::flag_t; // block has NO dst pdf field, lbm mask consists of multiple flags FlagFieldSweepBase( const BlockDataID & pdfField, const ConstBlockDataID & flagField, const Set< FlagUID > & lbmMask ) : diff --git a/src/lbm/sweeps/StreamPull.h b/src/lbm/sweeps/StreamPull.h index 136712f8b..fba95f580 100644 --- a/src/lbm/sweeps/StreamPull.h +++ b/src/lbm/sweeps/StreamPull.h @@ -62,8 +62,8 @@ struct StreamPullEverything static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value == false), "There is a specialization for D3Q19!" ); static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q27 >::value == false), "There is a specialization for D3Q27!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; @@ -114,8 +114,8 @@ struct StreamPullEverything< LatticeModel_T, typename std::enable_if< std::is_sa { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D2Q9 >::value), "Only works with D2Q9!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; @@ -177,8 +177,8 @@ struct StreamPullEverything< LatticeModel_T, typename std::enable_if< std::is_sa { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "Only works with D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; @@ -250,8 +250,8 @@ struct StreamPullEverything< LatticeModel_T, typename std::enable_if< std::is_sa { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q27 >::value), "Only works with D3Q27!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; @@ -334,8 +334,8 @@ struct StreamPull static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value == false), "There is a specialization for D3Q19!" ); static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q27 >::value == false), "There is a specialization for D3Q27!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; template< typename Filter_T > static inline void execute( PdfField_T * src, PdfField_T * dst, IBlock * block, Filter_T & filter, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); @@ -392,8 +392,8 @@ struct StreamPull< LatticeModel_T, typename std::enable_if< std::is_same< typena { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D2Q9 >::value), "Only works with D2Q9!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; template< typename Filter_T > static void execute( PdfField_T * src, PdfField_T * dst, IBlock * block, Filter_T & filter, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); @@ -464,8 +464,8 @@ struct StreamPull< LatticeModel_T, typename std::enable_if< std::is_same< typena { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "Only works with D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; template< typename Filter_T > static void execute( PdfField_T * src, PdfField_T * dst, IBlock * block, Filter_T & filter, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); @@ -546,8 +546,8 @@ struct StreamPull< LatticeModel_T, typename std::enable_if< std::is_same< typena { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q27 >::value), "Only works with D3Q27!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; template< typename Filter_T > static void execute( PdfField_T * src, PdfField_T * dst, IBlock * block, Filter_T & filter, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); diff --git a/src/lbm/sweeps/Streaming.h b/src/lbm/sweeps/Streaming.h index f4d87fe4a..b331e72f4 100644 --- a/src/lbm/sweeps/Streaming.h +++ b/src/lbm/sweeps/Streaming.h @@ -57,8 +57,8 @@ struct Stream< LatticeModel_T, FlagField_T, typename std::enable_if< ! std::is_s { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value == false), "There is a specialization for D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const FlagField_T * flagField, const typename FlagField_T::flag_t lbm, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); @@ -99,8 +99,8 @@ struct Stream< LatticeModel_T, FlagField_T, typename std::enable_if< std::is_sam { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "Only works with D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const FlagField_T * flagField, const typename FlagField_T::flag_t lbm, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); @@ -164,8 +164,8 @@ struct StreamEverything< LatticeModel_T, typename std::enable_if< ! std::is_same { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value == false), "There is a specialization for D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; @@ -216,8 +216,8 @@ struct StreamEverything< LatticeModel_T, typename std::enable_if< std::is_same< { static_assert( (std::is_same< typename LatticeModel_T::Stencil, stencil::D3Q19 >::value), "Only works with D3Q19!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; static void execute( PdfField_T * src, PdfField_T * dst, const uint_t numberOfGhostLayersToInclude = uint_t(0) ); }; diff --git a/src/lbm/sweeps/SweepBase.h b/src/lbm/sweeps/SweepBase.h index d3389cc60..f7dbddd12 100644 --- a/src/lbm/sweeps/SweepBase.h +++ b/src/lbm/sweeps/SweepBase.h @@ -47,7 +47,7 @@ class SweepBase { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; // block has NO dst pdf field SweepBase( const BlockDataID & pdfField, diff --git a/src/lbm/trt/SplitPureSweep.impl.h b/src/lbm/trt/SplitPureSweep.impl.h index 84104e092..3594863a9 100644 --- a/src/lbm/trt/SplitPureSweep.impl.h +++ b/src/lbm/trt/SplitPureSweep.impl.h @@ -73,8 +73,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename SweepBase<LatticeModel_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename SweepBase<LatticeModel_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field SplitPureSweep( const BlockDataID & pdfField ) : @@ -866,8 +866,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename SweepBase<LatticeModel_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename SweepBase<LatticeModel_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field SplitPureSweep( const BlockDataID & pdfField ) : diff --git a/src/lbm/trt/SplitSweep.impl.h b/src/lbm/trt/SplitSweep.impl.h index 4439727ca..c46db20a7 100644 --- a/src/lbm/trt/SplitSweep.impl.h +++ b/src/lbm/trt/SplitSweep.impl.h @@ -68,8 +68,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename FlagFieldSweepBase<LatticeModel_T,FlagField_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename FlagFieldSweepBase<LatticeModel_T, FlagField_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field, lbm mask consists of multiple flags SplitSweep( const BlockDataID & pdfField, const ConstBlockDataID & flagField, const Set< FlagUID > & lbmMask ) : @@ -1005,8 +1005,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef typename FlagFieldSweepBase<LatticeModel_T,FlagField_T>::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = typename FlagFieldSweepBase<LatticeModel_T, FlagField_T>::PdfField_T; + using Stencil = typename LatticeModel_T::Stencil; // block has NO dst pdf field, lbm mask consists of multiple flags SplitSweep( const BlockDataID & pdfField, const ConstBlockDataID & flagField, const Set< FlagUID > & lbmMask ) : diff --git a/src/lbm/trt/cell_operations/DefaultCellOperation.impl.h b/src/lbm/trt/cell_operations/DefaultCellOperation.impl.h index 0950f0cca..165e47f68 100644 --- a/src/lbm/trt/cell_operations/DefaultCellOperation.impl.h +++ b/src/lbm/trt/cell_operations/DefaultCellOperation.impl.h @@ -63,8 +63,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : lambda_e_( real_t(0) ), lambda_d_( real_t(0) ), latticeModel_( NULL ) {} @@ -179,8 +179,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : lambda_e_( real_t(0) ), lambda_e_scaled_( real_t(0) ), lambda_d_scaled_( real_t(0) ), @@ -431,8 +431,8 @@ public: static_assert( (std::is_same< typename LatticeModel_T::ForceModel::tag, force_model::None_tag >::value), "Only works without additional forces!" ); static_assert( LatticeModel_T::equilibriumAccuracyOrder == 2, "Only works for lattice models that require the equilibrium distribution to be order 2 accurate!" ); - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; DefaultCellOperation() : lambda_e_( real_t(0) ), lambda_e_scaled_( real_t(0) ), lambda_d_scaled_( real_t(0) ), diff --git a/src/lbm/vtk/Density.h b/src/lbm/vtk/Density.h index 6b7e4ee51..f40bc6359 100644 --- a/src/lbm/vtk/Density.h +++ b/src/lbm/vtk/Density.h @@ -36,7 +36,7 @@ class DensityVTKWriter : public vtk::BlockCellDataWriter< OutputType > { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; DensityVTKWriter( const ConstBlockDataID & pdf, const std::string & id ) : vtk::BlockCellDataWriter< OutputType >( id ), bdid_( pdf ), pdf_( nullptr ) {} @@ -63,7 +63,7 @@ class DensitySIVTKWriter : public vtk::BlockCellDataWriter< OutputType > { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; DensitySIVTKWriter( const ConstBlockDataID & pdf, const real_t rho_SI, const std::string & id ) : vtk::BlockCellDataWriter< OutputType >( id ), bdid_( pdf ), pdf_( NULL ), rho_SI_( rho_SI ) {} diff --git a/src/lbm/vtk/NonEquilibrium.h b/src/lbm/vtk/NonEquilibrium.h index 3754c58dd..4a756dba9 100644 --- a/src/lbm/vtk/NonEquilibrium.h +++ b/src/lbm/vtk/NonEquilibrium.h @@ -41,8 +41,8 @@ class NonEqulibriumVTKWriter : public vtk::BlockCellDataWriter< OutputType, Latt { public: - typedef PdfField< LatticeModel_T > PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil; + using PdfField_T = PdfField<LatticeModel_T>; + using Stencil = typename LatticeModel_T::Stencil; NonEqulibriumVTKWriter( const ConstBlockDataID & pdf, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, Stencil::Size >( id ), bdid_( pdf ), pdf_( nullptr ) {} diff --git a/src/lbm/vtk/PressureTensor.h b/src/lbm/vtk/PressureTensor.h index da09d6664..60c3afe53 100644 --- a/src/lbm/vtk/PressureTensor.h +++ b/src/lbm/vtk/PressureTensor.h @@ -36,7 +36,7 @@ class PressureTensorVTKWriter : public vtk::BlockCellDataWriter< OutputType, 9 > { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; PressureTensorVTKWriter( const ConstBlockDataID & pdfFieldId, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, 9 >( id ), bdid_( pdfFieldId ), pdf_( NULL ) {} diff --git a/src/lbm/vtk/VTKOutput.h b/src/lbm/vtk/VTKOutput.h index e42fb6bd9..9e58cf06f 100644 --- a/src/lbm/vtk/VTKOutput.h +++ b/src/lbm/vtk/VTKOutput.h @@ -79,8 +79,8 @@ class VTKOutput { public: - typedef typename FlagFieldT::flag_t flag_t; - typedef std::map<FlagUID, flag_t> FlagMap; + using flag_t = typename FlagFieldT::flag_t; + using FlagMap = std::map<FlagUID, flag_t>; VTKOutput( const ConstBlockDataID & pdfField, const ConstBlockDataID & flagField, const FlagUID & domainFlagUID, const vtk::VTKOutput::BeforeFunction & ghostLayerSyncFunction, @@ -196,7 +196,7 @@ void VTKOutput<LatticeModel, FlagFieldT>::addToTimeloop( Timeloop & timeloop, co const FlagUID & domainFlagUID, const FlagMap & flagFieldMapping ) { - typedef PdfField< LatticeModel > PdfField_t; + using PdfField_t = PdfField<LatticeModel>; blockforest::communication::UniformBufferedScheme< stencil::D3Q27 > pdfGhostLayerSync( blocks ); pdfGhostLayerSync.addPackInfo( make_shared< field::communication::PackInfo< PdfField_t > >( pdfField ) ); diff --git a/src/lbm/vtk/Velocity.h b/src/lbm/vtk/Velocity.h index 10957ee4a..8a31c07d2 100644 --- a/src/lbm/vtk/Velocity.h +++ b/src/lbm/vtk/Velocity.h @@ -36,7 +36,7 @@ class VelocityVTKWriter : public vtk::BlockCellDataWriter< OutputType, 3 > { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; VelocityVTKWriter( const ConstBlockDataID & pdfFieldId, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, 3 >( id ), bdid_( pdfFieldId ), pdf_( nullptr ) {} @@ -63,7 +63,7 @@ class VelocityMagnitudeVTKWriter : public vtk::BlockCellDataWriter< OutputType, { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; VelocityMagnitudeVTKWriter( const ConstBlockDataID & pdfFieldId, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, 1 >( id ), bdid_( pdfFieldId ), pdf_( nullptr ) {} @@ -90,7 +90,7 @@ class VelocitySIVTKWriter : public vtk::BlockCellDataWriter< OutputType, 3 > { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; VelocitySIVTKWriter( const ConstBlockDataID & pdfFieldId, const real_t dx_SI, const real_t dt_SI, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, 3 >( id ), bdid_( pdfFieldId ), pdf_( NULL ), dxDividedByDt_SI_( dx_SI / dt_SI ) {} @@ -118,7 +118,7 @@ class VelocitySIMagnitudeVTKWriter : public vtk::BlockCellDataWriter< OutputType { public: - typedef PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = PdfField<LatticeModel_T>; VelocitySIMagnitudeVTKWriter( const ConstBlockDataID & pdfFieldId, const real_t dx_SI, const real_t dt_SI, const std::string & id ) : vtk::BlockCellDataWriter< OutputType, 1 >( id ), bdid_( pdfFieldId ), pdf_( NULL ), dxDividedByDt_SI_( dx_SI / dt_SI ) {} diff --git a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h index d001a43ba..b46ed444b 100644 --- a/src/lbm_mesapd_coupling/utility/SubCyclingManager.h +++ b/src/lbm_mesapd_coupling/utility/SubCyclingManager.h @@ -34,7 +34,7 @@ namespace lbm_mesapd_coupling { class SubCyclingManager { public: - typedef std::function<void ()> VoidVoidFunc; + using VoidVoidFunc = std::function<void ()>; /*! \name Construction & Destruction */ //@{ @@ -45,7 +45,7 @@ public: /*! \name Registration Functions */ //@{ - typedef size_t FuncHandle; + using FuncHandle = size_t; FuncHandle addFuncBeforeSubCycles(const VoidVoidFunc &f, const std::string &identifier = "Other"); FuncHandle addFuncDuringSubCycles(const VoidVoidFunc &f, const std::string &identifier = "Other"); @@ -64,7 +64,7 @@ public: //@} private: - typedef std::pair<std::string, VoidVoidFunc> IdentifiedFunc; + using IdentifiedFunc = std::pair<std::string, VoidVoidFunc>; inline void executeBeforeFunctions(); inline void executeDuringFunctions(); diff --git a/src/mesa_pd/collision_detection/EPA.h b/src/mesa_pd/collision_detection/EPA.h index 781196f62..052f6cdf8 100644 --- a/src/mesa_pd/collision_detection/EPA.h +++ b/src/mesa_pd/collision_detection/EPA.h @@ -48,9 +48,9 @@ private : class EPA_Triangle; class EPA_TriangleComp; - typedef std::vector<EPA_Triangle> EPA_EntryBuffer; - typedef std::vector<EPA_Triangle*> EPA_EntryHeap; - typedef std::vector<EPA_Edge> EPA_EdgeBuffer; + using EPA_EntryBuffer = std::vector<EPA_Triangle>; + using EPA_EntryHeap = std::vector<EPA_Triangle *>; + using EPA_EdgeBuffer = std::vector<EPA_Edge>; //********************************************************************************************** public: diff --git a/src/pde/sweeps/SweepBase.h b/src/pde/sweeps/SweepBase.h index 031a3ee59..e8fe9fb43 100644 --- a/src/pde/sweeps/SweepBase.h +++ b/src/pde/sweeps/SweepBase.h @@ -39,7 +39,7 @@ class SweepBase { public: - typedef GhostLayerField< real_t, 1 > Field_T; + using Field_T = GhostLayerField<real_t, 1>; // block has NO dst u field SweepBase( const BlockDataID & uFieldId, const BlockDataID & fFieldId ) : diff --git a/src/pe/Materials.h b/src/pe/Materials.h index d4d54b96c..15863462f 100644 --- a/src/pe/Materials.h +++ b/src/pe/Materials.h @@ -95,7 +95,7 @@ class WALBERLA_PUBLIC Material { private: //**Type definitions**************************************************************************** - typedef Materials::size_type SizeType; //!< Size type of the Material class. + using SizeType = Materials::size_type; //!< Size type of the Material class. //********************************************************************************************** public: diff --git a/src/pe/Types.h b/src/pe/Types.h index d66c9df92..645f16780 100644 --- a/src/pe/Types.h +++ b/src/pe/Types.h @@ -42,12 +42,12 @@ template<typename T> class MatrixMxN; } namespace pe{ -typedef math::Vector2<real_t> Vec2; -typedef math::Vector3<real_t> Vec3; -typedef math::Matrix2<real_t> Mat2; -typedef math::Matrix3<real_t> Mat3; -typedef math::Quaternion<real_t> Quat; -typedef math::MatrixMxN<real_t> MatN; +using Vec2 = math::Vector2<real_t>; +using Vec3 = math::Vector3<real_t>; +using Mat2 = math::Matrix2<real_t>; +using Mat3 = math::Matrix3<real_t>; +using Quat = math::Quaternion<real_t>; +using MatN = math::MatrixMxN<real_t>; using math::AABB; @@ -77,67 +77,67 @@ class TriangleMesh; template <typename... BodyTypes> class Union; -typedef RigidBody BodyType; //!< Type of the rigid bodies. -typedef RigidBody* BodyID; //!< Handle for a rigid body. -typedef const RigidBody* ConstBodyID; //!< Handle for a constant rigid body. +using BodyType = RigidBody; //!< Type of the rigid bodies. +using BodyID = RigidBody *; //!< Handle for a rigid body. +using ConstBodyID = const RigidBody *; //!< Handle for a constant rigid body. using BodyPtr = std::unique_ptr<RigidBody>; -typedef GeomPrimitive* GeomID; -typedef const GeomPrimitive* ConstGeomID; +using GeomID = GeomPrimitive *; +using ConstGeomID = const GeomPrimitive *; -typedef Box BoxType; //!< Type of the box geometric primitive. -typedef Box* BoxID; //!< Handle for a box primitive. -typedef const Box* ConstBoxID; //!< Handle for a constant box primitive. +using BoxType = Box; //!< Type of the box geometric primitive. +using BoxID = Box *; //!< Handle for a box primitive. +using ConstBoxID = const Box *; //!< Handle for a constant box primitive. using BoxPtr = std::unique_ptr<Box>; -typedef Capsule CapsuleType; //!< Type of the capsule geometric primitive. -typedef Capsule* CapsuleID; //!< Handle for a capsule primitive. -typedef const Capsule* ConstCapsuleID; //!< Handle for a constant capsule primitive. +using CapsuleType = Capsule; //!< Type of the capsule geometric primitive. +using CapsuleID = Capsule *; //!< Handle for a capsule primitive. +using ConstCapsuleID = const Capsule *; //!< Handle for a constant capsule primitive. using CapsulePtr = std::unique_ptr<Capsule>; -typedef Cylinder CylinderType; //!< Type of the cylinder geometric primitive. -typedef Cylinder* CylinderID; //!< Handle for a cylinder primitive. -typedef const Cylinder* ConstCylinderID; //!< Handle for a constant cylinder primitive. +using CylinderType = Cylinder; //!< Type of the cylinder geometric primitive. +using CylinderID = Cylinder *; //!< Handle for a cylinder primitive. +using ConstCylinderID = const Cylinder *; //!< Handle for a constant cylinder primitive. using CylinderPtr = std::unique_ptr<Cylinder>; -typedef CylindricalBoundary CylindricalBoundaryType; //!< Type of the cylindrical boundary geometric primitive. -typedef CylindricalBoundary* CylindricalBoundaryID; //!< Handle for a cylindrical boundary primitive. -typedef const CylindricalBoundary* ConstCylindricalBoundaryID; //!< Handle for a constant cylindrical boundary primitive. +using CylindricalBoundaryType = CylindricalBoundary; //!< Type of the cylindrical boundary geometric primitive. +using CylindricalBoundaryID = CylindricalBoundary *; //!< Handle for a cylindrical boundary primitive. +using ConstCylindricalBoundaryID = const CylindricalBoundary *; //!< Handle for a constant cylindrical boundary primitive. using CylindricalBoundaryPtr = std::unique_ptr<CylindricalBoundary>; -typedef Ellipsoid EllipsoidType; //!< Type of the ellipsoid geometric primitive. -typedef Ellipsoid* EllipsoidID; //!< Handle for a ellipsoid primitive. -typedef const Ellipsoid* ConstEllipsoidID; //!< Handle for a constant ellipsoid primitive. +using EllipsoidType = Ellipsoid; //!< Type of the ellipsoid geometric primitive. +using EllipsoidID = Ellipsoid *; //!< Handle for a ellipsoid primitive. +using ConstEllipsoidID = const Ellipsoid *; //!< Handle for a constant ellipsoid primitive. using EllipsoidPtr = std::unique_ptr<Ellipsoid>; -typedef Plane PlaneType; //!< Type of the plane geometric primitive. -typedef Plane* PlaneID; //!< Handle for a plane primitive. -typedef const Plane* ConstPlaneID; //!< Handle for a constant plane primitive. +using PlaneType = Plane; //!< Type of the plane geometric primitive. +using PlaneID = Plane *; //!< Handle for a plane primitive. +using ConstPlaneID = const Plane *; //!< Handle for a constant plane primitive. using PlanePtr = std::unique_ptr<Plane>; -typedef Sphere SphereType; //!< Type of the sphere geometric primitive. -typedef Sphere* SphereID; //!< Handle for a sphere primitive. -typedef const Sphere* ConstSphereID; //!< Handle for a constant sphere primitive. +using SphereType = Sphere; //!< Type of the sphere geometric primitive. +using SphereID = Sphere *; //!< Handle for a sphere primitive. +using ConstSphereID = const Sphere *; //!< Handle for a constant sphere primitive. using SpherePtr = std::unique_ptr<Sphere>; -typedef Squirmer SquirmerType; //!< Type of the squirmer geometric primitive. -typedef Squirmer* SquirmerID; //!< Handle for a squirmer primitive. -typedef const Squirmer* ConstSquirmerID; //!< Handle for a constant squirmer primitive. +using SquirmerType = Squirmer; //!< Type of the squirmer geometric primitive. +using SquirmerID = Squirmer *; //!< Handle for a squirmer primitive. +using ConstSquirmerID = const Squirmer *; //!< Handle for a constant squirmer primitive. using SquirmerPtr = std::unique_ptr<Squirmer>; -typedef TriangleMesh MeshType; //!< Type of the triangle mesh geometric primitive. -typedef TriangleMesh* MeshID; //!< Handle for a triangle mesh primitive. -typedef const TriangleMesh* ConstMeshID; //!< Handle for a constant triangle mesh primitive. +using MeshType = TriangleMesh; //!< Type of the triangle mesh geometric primitive. +using MeshID = TriangleMesh *; //!< Handle for a triangle mesh primitive. +using ConstMeshID = const TriangleMesh *; //!< Handle for a constant triangle mesh primitive. using TriangleMeshPtr = std::unique_ptr<TriangleMesh>; -typedef Contact ContactType; //!< Type of the contacts. -typedef Contact* ContactID; //!< Handle for a contact. -typedef const Contact* ConstContactID; //!< Handle for a constant contact. +using ContactType = Contact; //!< Type of the contacts. +using ContactID = Contact *; //!< Handle for a contact. +using ConstContactID = const Contact *; //!< Handle for a constant contact. -typedef BodyManager* ManagerID; //!< Handle for a BodyManager. -typedef const BodyManager* ConstManagerID; //!< Handle for a constant BodyManager. +using ManagerID = BodyManager *; //!< Handle for a BodyManager. +using ConstManagerID = const BodyManager *; //!< Handle for a constant BodyManager. -typedef std::vector<Material> Materials; //!< Vector for materials. +using Materials = std::vector<Material>; //!< Vector for materials. //************************************************************************************************* @@ -156,14 +156,14 @@ typedef std::vector<Material> Materials; //!< Vector for materials. MaterialID myMaterial = createMaterial( "myMaterial", real_c(2.54), real_c(0.8), real_c(0.1), real_c(0.05) ); \endcode */ -typedef Materials::size_type MaterialID; +using MaterialID = Materials::size_type; //************************************************************************************************* ///Output data type of coarse collision detection module -typedef std::vector<std::pair<BodyID, BodyID> > PossibleContacts; +using PossibleContacts = std::vector<std::pair<BodyID, BodyID>>; ///Output data type of fine collision detection module -typedef std::vector< Contact > Contacts; +using Contacts = std::vector<Contact>; ///Class enum for BodyStorages /// \see Storage @@ -187,7 +187,7 @@ struct StorageSelect }; ///Container for local and shadow body storage -typedef std::array<BodyStorage, 2> Storage; +using Storage = std::array<BodyStorage, 2>; } // namespace pe } // namespace walberla diff --git a/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h b/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h index 4d0aeb411..f0797401e 100644 --- a/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h +++ b/src/pe/amr/weight_assignment/MetisAssignmentFunctor.h @@ -40,9 +40,9 @@ class MetisAssignmentFunctor { public: ///Convenience typedef to be used as PhantomBlock weight in conjunction with this weight assignment functor. - typedef blockforest::DynamicParMetisBlockInfo PhantomBlockWeight; + using PhantomBlockWeight = blockforest::DynamicParMetisBlockInfo; ///Convenience typdef for pack and unpack functions to be used in conjunction with PhantomBlockWeight. - typedef blockforest::DynamicParMetisBlockInfoPackUnpack PhantomBlockWeightPackUnpackFunctor; + using PhantomBlockWeightPackUnpackFunctor = blockforest::DynamicParMetisBlockInfoPackUnpack; MetisAssignmentFunctor( shared_ptr<blockforest::InfoCollection>& ic, const real_t baseWeight = real_t(10.0) ) : ic_(ic), baseWeight_(baseWeight) {} diff --git a/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h b/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h index 66f267af0..069efae7e 100644 --- a/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h +++ b/src/pe/amr/weight_assignment/WeightAssignmentFunctor.h @@ -38,9 +38,9 @@ class WeightAssignmentFunctor { public: ///Convenience typedef to be used as PhantomBlock weight in conjunction with this weight assignment functor. - typedef walberla::blockforest::PODPhantomWeight<double> PhantomBlockWeight; + using PhantomBlockWeight = walberla::blockforest::PODPhantomWeight<double>; ///Convenience typdef for pack and unpack functions to be used in conjunction with PhantomBlockWeight. - typedef walberla::blockforest::PODPhantomWeightPackUnpack<double> PhantomBlockWeightPackUnpackFunctor; + using PhantomBlockWeightPackUnpackFunctor = walberla::blockforest::PODPhantomWeightPackUnpack<double>; WeightAssignmentFunctor( shared_ptr<blockforest::InfoCollection>& ic, const real_t baseWeight = real_t(10.0) ) : ic_(ic), baseWeight_(baseWeight) {} diff --git a/src/pe/ccd/HashGrids.h b/src/pe/ccd/HashGrids.h index 15b2968e3..cbfe0471d 100644 --- a/src/pe/ccd/HashGrids.h +++ b/src/pe/ccd/HashGrids.h @@ -103,7 +103,7 @@ public: private: //**Type definitions**************************************************************************** //! Vector for storing (handles to) rigid bodies. - typedef std::vector<BodyID> BodyVector; + using BodyVector = std::vector<BodyID>; //********************************************************************************************** //********************************************************************************************** @@ -114,7 +114,7 @@ private: private: //**Type definitions************************************************************************* //! The signed integer type that is used for storing offsets to neighboring cells. - typedef long offset_t; + using offset_t = long; //******************************************************************************************* //******************************************************************************************* @@ -139,7 +139,7 @@ private: //**Type definitions************************************************************************* //! Vector for storing pointers to (body-occupied) cells. - typedef std::vector<Cell*> CellVector; + using CellVector = std::vector<Cell *>; //******************************************************************************************* public: @@ -262,7 +262,7 @@ private: //! List for storing all the hash grids that are in use. /*! This data structure is used to represent the grid hierarchy. All hash grids are stored in ascending order by the size of their cells. */ - typedef std::list<HashGrid*> GridList; + using GridList = std::list<HashGrid *>; //********************************************************************************************** public: diff --git a/src/pe/collision/EPA.h b/src/pe/collision/EPA.h index a318e7e57..7bc5840d1 100644 --- a/src/pe/collision/EPA.h +++ b/src/pe/collision/EPA.h @@ -64,9 +64,9 @@ private : class EPA_Triangle; class EPA_TriangleComp; - typedef std::vector<EPA_Triangle> EPA_EntryBuffer; - typedef std::vector<EPA_Triangle*> EPA_EntryHeap; - typedef std::vector<EPA_Edge> EPA_EdgeBuffer; + using EPA_EntryBuffer = std::vector<EPA_Triangle>; + using EPA_EntryHeap = std::vector<EPA_Triangle *>; + using EPA_EdgeBuffer = std::vector<EPA_Edge>; //********************************************************************************************** public: diff --git a/src/pe/cr/HCSITS.h b/src/pe/cr/HCSITS.h index 8cf803c46..93da3f0f2 100644 --- a/src/pe/cr/HCSITS.h +++ b/src/pe/cr/HCSITS.h @@ -270,7 +270,7 @@ private: }; //************************************************************************************************* -typedef HardContactSemiImplicitTimesteppingSolvers HCSITS; +using HCSITS = HardContactSemiImplicitTimesteppingSolvers; //================================================================================================= // diff --git a/src/pe/rigidbody/MPIRigidBodyTrait.h b/src/pe/rigidbody/MPIRigidBodyTrait.h index a8a055e1e..5e24baa29 100644 --- a/src/pe/rigidbody/MPIRigidBodyTrait.h +++ b/src/pe/rigidbody/MPIRigidBodyTrait.h @@ -47,15 +47,15 @@ class MPIRigidBodyTrait { protected: //**Type definitions**************************************************************************** - typedef std::vector<Owner> ShadowOwners; //!< Vector for remote MPI processes the rigid body is contained in. - typedef std::set<BlockID> BlockStates; //!< Stores the information if neighbor block knows about object. + using ShadowOwners = std::vector<Owner>; //!< Vector for remote MPI processes the rigid body is contained in. + using BlockStates = std::set<BlockID>; //!< Stores the information if neighbor block knows about object. //********************************************************************************************** public: //**Type definitions**************************************************************************** - typedef ShadowOwners::iterator ShadowOwnersIterator; //!< Iterator over the connected processes. - typedef ShadowOwners::const_iterator ConstShadowOwnersIterator; //!< ConstIterator over the connected processes. - typedef size_t SizeType; + using ShadowOwnersIterator = ShadowOwners::iterator; //!< Iterator over the connected processes. + using ConstShadowOwnersIterator = ShadowOwners::const_iterator; //!< ConstIterator over the connected processes. + using SizeType = size_t; //********************************************************************************************** //**Constructor********************************************************************************* diff --git a/src/pe_coupling/amr/InfoCollection.h b/src/pe_coupling/amr/InfoCollection.h index 86e508e87..c39d41a6d 100644 --- a/src/pe_coupling/amr/InfoCollection.h +++ b/src/pe_coupling/amr/InfoCollection.h @@ -35,8 +35,8 @@ namespace walberla { namespace pe_coupling { -typedef std::map<blockforest::BlockID, BlockInfo> InfoCollection; -typedef std::pair<blockforest::BlockID, BlockInfo> InfoCollectionPair; +using InfoCollection = std::map<blockforest::BlockID, BlockInfo>; +using InfoCollectionPair = std::pair<blockforest::BlockID, BlockInfo>; template <typename BoundaryHandling_T> void createWithNeighborhood(BlockForest& bf, const BlockDataID boundaryHandlingID, diff --git a/src/pe_coupling/amr/weight_assignment/WeightAssignmentFunctor.h b/src/pe_coupling/amr/weight_assignment/WeightAssignmentFunctor.h index 5fa776362..ad5aa4489 100644 --- a/src/pe_coupling/amr/weight_assignment/WeightAssignmentFunctor.h +++ b/src/pe_coupling/amr/weight_assignment/WeightAssignmentFunctor.h @@ -34,7 +34,7 @@ namespace amr { class WeightAssignmentFunctor { public: - typedef walberla::blockforest::PODPhantomWeight<double> PhantomBlockWeight; + using PhantomBlockWeight = walberla::blockforest::PODPhantomWeight<double>; WeightAssignmentFunctor( const shared_ptr<InfoCollection>& ic, const std::function<real_t(const BlockInfo&)> & weightEvaluationFct ) : diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/AddedMassForceEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/AddedMassForceEvaluator.h index c452f8864..c441e9009 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/AddedMassForceEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/AddedMassForceEvaluator.h @@ -70,9 +70,9 @@ class AddedMassForceEvaluator public: - typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T; - typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T; - typedef Distributor_T<Vec3Field_T, FlagField_T> ForceDistributor_T; + using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; + using Vec3FieldInterpolator_T = FieldInterpolator_T<Vec3Field_T, FlagField_T>; + using ForceDistributor_T = Distributor_T<Vec3Field_T, FlagField_T>; AddedMassForceEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & forceFieldID, const BlockDataID & bodyStorageID, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/EffectiveViscosityFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/EffectiveViscosityFieldEvaluator.h index fc10c9b97..f8039c7e6 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/EffectiveViscosityFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/EffectiveViscosityFieldEvaluator.h @@ -62,7 +62,7 @@ real_t calculateEilersEffectiveViscosity( real_t fluidViscosity, real_t porosity class EffectiveViscosityFieldEvaluator { public: - typedef GhostLayerField< real_t, 1 > ScalarField_T; + using ScalarField_T = GhostLayerField<real_t, 1>; EffectiveViscosityFieldEvaluator( const BlockDataID & omegaFieldID, const ConstBlockDataID & solidVolumeFractionFieldID, const real_t & fluidViscosity, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/InteractionForceEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/InteractionForceEvaluator.h index 11709d1e8..9f5125fc8 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/InteractionForceEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/InteractionForceEvaluator.h @@ -78,11 +78,11 @@ class InteractionForceEvaluator public: - typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T; - typedef GhostLayerField< real_t, 1> ScalarField_T; - typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T; - typedef FieldInterpolator_T<ScalarField_T, FlagField_T> ScalarFieldInterpolator_T; - typedef Distributor_T<Vec3Field_T, FlagField_T> ForceDistributor_T; + using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; + using ScalarField_T = GhostLayerField<real_t, 1>; + using Vec3FieldInterpolator_T = FieldInterpolator_T<Vec3Field_T, FlagField_T>; + using ScalarFieldInterpolator_T = FieldInterpolator_T<ScalarField_T, FlagField_T>; + using ForceDistributor_T = Distributor_T<Vec3Field_T, FlagField_T>; InteractionForceEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & forceFieldID, const BlockDataID & bodyStorageID, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/LiftForceEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/LiftForceEvaluator.h index de8518349..3243b32be 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/LiftForceEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/LiftForceEvaluator.h @@ -65,9 +65,9 @@ class LiftForceEvaluator public: - typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T; - typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T; - typedef Distributor_T<Vec3Field_T, FlagField_T> ForceDistributor_T; + using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; + using Vec3FieldInterpolator_T = FieldInterpolator_T<Vec3Field_T, FlagField_T>; + using ForceDistributor_T = Distributor_T<Vec3Field_T, FlagField_T>; LiftForceEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & forceFieldID, const BlockDataID & bodyStorageID, const BlockDataID & flagFieldID, const Set< FlagUID > & domainFlags, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/PressureFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/PressureFieldEvaluator.h index 61998ae6d..f7a639e55 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/PressureFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/PressureFieldEvaluator.h @@ -39,8 +39,8 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class PressureFieldEvaluator { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using ScalarField_T = GhostLayerField<real_t, 1>; PressureFieldEvaluator( const BlockDataID & pressureFieldID, const ConstBlockDataID & pdfFieldID, const ConstBlockDataID & boundaryHandlingID ) : pressureFieldID_( pressureFieldID ), pdfFieldID_( pdfFieldID ), boundaryHandlingID_( boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/PressureGradientFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/PressureGradientFieldEvaluator.h index 2e8511fca..a206b32ed 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/PressureGradientFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/PressureGradientFieldEvaluator.h @@ -42,9 +42,9 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class PressureGradientFieldEvaluator { public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef GhostLayerField< real_t, 1> ScalarField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using ScalarField_T = GhostLayerField<real_t, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; PressureGradientFieldEvaluator( const BlockDataID & pressureGradientFieldID, const ConstBlockDataID & pressureFieldID, const ConstBlockDataID & boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/SolidVolumeFractionFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/SolidVolumeFractionFieldEvaluator.h index 586b51bc2..0ba419f46 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/SolidVolumeFractionFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/SolidVolumeFractionFieldEvaluator.h @@ -62,8 +62,8 @@ class SolidVolumeFractionFieldEvaluator { public: - typedef GhostLayerField< real_t, 1 > ScalarField_T; - typedef Distributor_T<ScalarField_T, FlagField_T> ScalarDistributor_T; + using ScalarField_T = GhostLayerField<real_t, 1>; + using ScalarDistributor_T = Distributor_T<ScalarField_T, FlagField_T>; SolidVolumeFractionFieldEvaluator( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & solidVolumeFractionFieldID, const BlockDataID & bodyStorageID, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/StressTensorGradientFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/StressTensorGradientFieldEvaluator.h index 29dce0a61..613e2a7c3 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/StressTensorGradientFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/StressTensorGradientFieldEvaluator.h @@ -43,9 +43,9 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class StressTensorGradientFieldEvaluator { public: - typedef GhostLayerField< Matrix3< real_t >, 1> TensorField_T; - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using TensorField_T = GhostLayerField<Matrix3<real_t>, 1>; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; StressTensorGradientFieldEvaluator( const BlockDataID & stressTensorGradientFieldID, const ConstBlockDataID & velocityGradientFieldID, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityCurlFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityCurlFieldEvaluator.h index 0442814db..ed693ff86 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityCurlFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityCurlFieldEvaluator.h @@ -42,8 +42,8 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class VelocityCurlFieldEvaluator { public: - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; VelocityCurlFieldEvaluator( const BlockDataID & velocityCurlFieldID, const ConstBlockDataID & velocityFieldID, const ConstBlockDataID & boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityFieldEvaluator.h index 70d62853b..b82f8fac3 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityFieldEvaluator.h @@ -44,8 +44,8 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class VelocityFieldEvaluator { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using VelocityField_T = GhostLayerField<Vector3<real_t>, 1>; VelocityFieldEvaluator( const BlockDataID & velocityFieldID, const ConstBlockDataID & pdfFieldID, const ConstBlockDataID & boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityGradientFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityGradientFieldEvaluator.h index 9e0397a5a..0f85958ad 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityGradientFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityGradientFieldEvaluator.h @@ -44,9 +44,9 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class VelocityGradientFieldEvaluator { public: - typedef GhostLayerField< Matrix3< real_t >, 1> TensorField_T; - typedef GhostLayerField< Vector3<real_t>, 1 > VectorField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using TensorField_T = GhostLayerField<Matrix3<real_t>, 1>; + using VectorField_T = GhostLayerField<Vector3<real_t>, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; VelocityGradientFieldEvaluator( const BlockDataID & velocityGradientFieldID, const ConstBlockDataID & velocityFieldID, diff --git a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityTotalTimeDerivativeFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityTotalTimeDerivativeFieldEvaluator.h index 62e70f973..2bcbba999 100644 --- a/src/pe_coupling/discrete_particle_methods/evaluators/VelocityTotalTimeDerivativeFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/evaluators/VelocityTotalTimeDerivativeFieldEvaluator.h @@ -46,8 +46,8 @@ using math::Vector3; class VelocityTotalTimeDerivativeFieldEvaluator { public: - typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; - typedef GhostLayerField< Matrix3< real_t >, 1> TensorField_T; + using VelocityField_T = GhostLayerField<Vector3<real_t>, 1>; + using TensorField_T = GhostLayerField<Matrix3<real_t>, 1>; VelocityTotalTimeDerivativeFieldEvaluator( const BlockDataID & totalTimeDerivativeVelocityFieldID, const ConstBlockDataID & currentVelocityFieldID, diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h index 7c62ccb5b..a36e475ef 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/GNSSweep.h @@ -53,9 +53,9 @@ class GNSSweep { public: - typedef typename lbm::SweepBase< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T >::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef GhostLayerField< real_t, 1> ScalarField_T; + using PdfField_T = typename lbm::SweepBase<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>::PdfField_T; + using Stencil_T = typename LatticeModel_T::Stencil; + using ScalarField_T = GhostLayerField<real_t, 1>; static_assert( LatticeModel_T::ForceModel::constant == false, "Only works with non-constant force models!" ); static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); @@ -257,7 +257,7 @@ shared_ptr< GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelo makeGNSSweep( const BlockDataID & pdfFieldID, const BlockDataID & solidVolumeFractionFieldID, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T > Sweep_T; + using Sweep_T = GNSSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>; return shared_ptr< Sweep_T >( new Sweep_T( pdfFieldID, solidVolumeFractionFieldID, filter, densityVelocityIn, densityVelocityOut ) ); } @@ -266,7 +266,7 @@ shared_ptr< GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelo makeGNSSweep( const BlockDataID & srcID, const BlockDataID & dstID, const BlockDataID & solidVolumeFractionFieldID, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef GNSSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T > Sweep_T; + using Sweep_T = GNSSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>; return shared_ptr< Sweep_T >( new Sweep_T( srcID, dstID, solidVolumeFractionFieldID, filter, densityVelocityIn, densityVelocityOut ) ); } diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSExternalForceToForceFieldAdder.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSExternalForceToForceFieldAdder.h index 73fc6f547..9517c8b60 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSExternalForceToForceFieldAdder.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSExternalForceToForceFieldAdder.h @@ -41,8 +41,8 @@ using math::Vector3; class GNSExternalForceToForceFieldAdder { public: - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; + using ForceField_T = GhostLayerField<Vector3<real_t>, 1>; + using ScalarField_T = GhostLayerField<real_t, 1>; GNSExternalForceToForceFieldAdder( const BlockDataID & forceFieldID, const ConstBlockDataID & solidVolumeFractionFieldID, const Vector3<real_t> & externalForce ) : forceFieldID_( forceFieldID ), solidVolumeFractionFieldID_( solidVolumeFractionFieldID ), externalForce_( externalForce ) diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSPressureFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSPressureFieldEvaluator.h index c284db5fd..8ff05a953 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSPressureFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSPressureFieldEvaluator.h @@ -36,8 +36,8 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class GNSPressureFieldEvaluator { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using ScalarField_T = GhostLayerField<real_t, 1>; GNSPressureFieldEvaluator( const BlockDataID & pressureFieldID, const ConstBlockDataID & pdfFieldID, const ConstBlockDataID & solidVolumeFractionFieldID, const ConstBlockDataID & boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSSmagorinskyLESField.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSSmagorinskyLESField.h index 4ae1a67df..f4d8fd414 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSSmagorinskyLESField.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSSmagorinskyLESField.h @@ -64,9 +64,9 @@ class GNSSmagorinskyLESField { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using ScalarField_T = GhostLayerField<real_t, 1>; + using Stencil_T = typename LatticeModel_T::Stencil; static_assert( LatticeModel_T::CollisionModel::constant == false, "Only works with non-constant relaxation time fields!" ); static_assert( LatticeModel_T::compressible == false, "Only works with incompressible models!" ); diff --git a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSVelocityFieldEvaluator.h b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSVelocityFieldEvaluator.h index 157c812b7..d0fcdf110 100644 --- a/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSVelocityFieldEvaluator.h +++ b/src/pe_coupling/discrete_particle_methods/gns_lbm/utility/GNSVelocityFieldEvaluator.h @@ -48,9 +48,9 @@ template <typename LatticeModel_T, typename BoundaryHandling_T> class GNSVelocityFieldEvaluator { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef GhostLayerField< Vector3<real_t>, 1 > VelocityField_T; - typedef GhostLayerField< real_t, 1 > ScalarField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using VelocityField_T = GhostLayerField<Vector3<real_t>, 1>; + using ScalarField_T = GhostLayerField<real_t, 1>; GNSVelocityFieldEvaluator( const BlockDataID & velocityFieldID, const ConstBlockDataID & pdfFieldID, const ConstBlockDataID & solidVolumeFractionFieldID, const ConstBlockDataID & boundaryHandlingID ) diff --git a/src/pe_coupling/discrete_particle_methods/utility/AveragedInteractionForceFieldToForceFieldAdder.h b/src/pe_coupling/discrete_particle_methods/utility/AveragedInteractionForceFieldToForceFieldAdder.h index bffee1573..9d8d5a208 100644 --- a/src/pe_coupling/discrete_particle_methods/utility/AveragedInteractionForceFieldToForceFieldAdder.h +++ b/src/pe_coupling/discrete_particle_methods/utility/AveragedInteractionForceFieldToForceFieldAdder.h @@ -48,7 +48,7 @@ using math::Vector3; class AveragedInteractionForceFieldToForceFieldAdder { public: - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField_T; + using ForceField_T = GhostLayerField<Vector3<real_t>, 1>; AveragedInteractionForceFieldToForceFieldAdder( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & forceFieldID, const ConstBlockDataID & interactionForceFieldID, uint_t maximumAveragingSteps ) diff --git a/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h b/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h index 6ff059c61..575f4cec8 100644 --- a/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h +++ b/src/pe_coupling/discrete_particle_methods/utility/BodyVelocityInitializer.h @@ -60,8 +60,8 @@ class BodyVelocityInitializer public: - typedef GhostLayerField< Vector3<real_t>, 1> Vec3Field_T; - typedef FieldInterpolator_T<Vec3Field_T, FlagField_T> Vec3FieldInterpolator_T; + using Vec3Field_T = GhostLayerField<Vector3<real_t>, 1>; + using Vec3FieldInterpolator_T = FieldInterpolator_T<Vec3Field_T, FlagField_T>; BodyVelocityInitializer( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & bodyStorageID, const BlockDataID & flagFieldID, const Set< FlagUID > & domainFlags, diff --git a/src/pe_coupling/discrete_particle_methods/utility/ExternalForceToForceFieldAdder.h b/src/pe_coupling/discrete_particle_methods/utility/ExternalForceToForceFieldAdder.h index f5e27bc31..b833cae93 100644 --- a/src/pe_coupling/discrete_particle_methods/utility/ExternalForceToForceFieldAdder.h +++ b/src/pe_coupling/discrete_particle_methods/utility/ExternalForceToForceFieldAdder.h @@ -39,7 +39,7 @@ using math::Vector3; class ExternalForceToForceFieldAdder { public: - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField_T; + using ForceField_T = GhostLayerField<Vector3<real_t>, 1>; ExternalForceToForceFieldAdder( const BlockDataID & forceFieldID, const Vector3<real_t> & externalForce ) : forceFieldID_( forceFieldID ), externalForce_( externalForce ) diff --git a/src/pe_coupling/discrete_particle_methods/utility/ForceFieldResetter.h b/src/pe_coupling/discrete_particle_methods/utility/ForceFieldResetter.h index d58e30d51..17278887e 100644 --- a/src/pe_coupling/discrete_particle_methods/utility/ForceFieldResetter.h +++ b/src/pe_coupling/discrete_particle_methods/utility/ForceFieldResetter.h @@ -36,7 +36,7 @@ using math::Vector3; class ForceFieldResetter { public: - typedef GhostLayerField< Vector3<real_t>, 1 > ForceField_T; + using ForceField_T = GhostLayerField<Vector3<real_t>, 1>; ForceFieldResetter( const BlockDataID & forceFieldID ) : forceFieldID_( forceFieldID ) diff --git a/src/pe_coupling/momentum_exchange_method/BodyMapping.h b/src/pe_coupling/momentum_exchange_method/BodyMapping.h index 96cfd1276..c3addc457 100644 --- a/src/pe_coupling/momentum_exchange_method/BodyMapping.h +++ b/src/pe_coupling/momentum_exchange_method/BodyMapping.h @@ -61,10 +61,10 @@ class BodyMapping { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef typename BoundaryHandling_T::FlagField FlagField_T; - typedef typename BoundaryHandling_T::flag_t flag_t; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using FlagField_T = typename BoundaryHandling_T::FlagField; + using flag_t = typename BoundaryHandling_T::flag_t; + using BodyField_T = Field<pe::BodyID, 1>; BodyMapping( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & pdfFieldID, @@ -250,7 +250,7 @@ template< typename BoundaryHandling_T > void mapMovingBody( pe::BodyID body, IBlock & block, StructuredBlockStorage & blockStorage, const BlockDataID & boundaryHandlingID, const BlockDataID & bodyFieldID, const FlagUID & obstacle ) { - typedef Field< pe::BodyID, 1 > BodyField_T; + using BodyField_T = Field<pe::BodyID, 1>; WALBERLA_ASSERT_EQUAL( &block.getBlockStorage(), &(blockStorage.getBlockStorage()) ); diff --git a/src/pe_coupling/momentum_exchange_method/boundary/CurvedLinear.h b/src/pe_coupling/momentum_exchange_method/boundary/CurvedLinear.h index 05fee404d..41dcdf79a 100644 --- a/src/pe_coupling/momentum_exchange_method/boundary/CurvedLinear.h +++ b/src/pe_coupling/momentum_exchange_method/boundary/CurvedLinear.h @@ -64,10 +64,10 @@ namespace pe_coupling { template< typename LatticeModel_T, typename FlagField_T > class CurvedLinear : public Boundary< typename FlagField_T::flag_t > { - typedef lbm::PdfField< LatticeModel_T > PDFField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef typename FlagField_T::flag_t flag_t; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PDFField_T = lbm::PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; + using BodyField_T = Field<pe::BodyID, 1>; public: diff --git a/src/pe_coupling/momentum_exchange_method/boundary/CurvedQuadratic.h b/src/pe_coupling/momentum_exchange_method/boundary/CurvedQuadratic.h index 3ba15e919..4e5e4f9b4 100644 --- a/src/pe_coupling/momentum_exchange_method/boundary/CurvedQuadratic.h +++ b/src/pe_coupling/momentum_exchange_method/boundary/CurvedQuadratic.h @@ -75,10 +75,10 @@ class CurvedQuadratic : public Boundary< typename FlagField_T::flag_t > { static_assert( (std::is_same< typename LatticeModel_T::CollisionModel::tag, lbm::collision_model::TRT_tag >::value), "Only works with TRT!" ); // to access lambda_d - typedef lbm::PdfField< LatticeModel_T > PDFField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef typename FlagField_T::flag_t flag_t; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PDFField_T = lbm::PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; + using BodyField_T = Field<pe::BodyID, 1>; public: diff --git a/src/pe_coupling/momentum_exchange_method/boundary/SimpleBB.h b/src/pe_coupling/momentum_exchange_method/boundary/SimpleBB.h index 0d7af9d9a..d3ee85dec 100644 --- a/src/pe_coupling/momentum_exchange_method/boundary/SimpleBB.h +++ b/src/pe_coupling/momentum_exchange_method/boundary/SimpleBB.h @@ -59,11 +59,11 @@ namespace pe_coupling { template< typename LatticeModel_T, typename FlagField_T > class SimpleBB : public Boundary< typename FlagField_T::flag_t > { - typedef lbm::PdfField< LatticeModel_T > PDFField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef typename FlagField_T::flag_t flag_t; + using PDFField_T = lbm::PdfField<LatticeModel_T>; + using Stencil_T = typename LatticeModel_T::Stencil; + using flag_t = typename FlagField_T::flag_t; - typedef Field< pe::BodyID, 1 > BodyField; + using BodyField = Field<pe::BodyID, 1>; public: diff --git a/src/pe_coupling/momentum_exchange_method/destruction/Destroyer.h b/src/pe_coupling/momentum_exchange_method/destruction/Destroyer.h index 68d9ae2a3..f1f5a366c 100644 --- a/src/pe_coupling/momentum_exchange_method/destruction/Destroyer.h +++ b/src/pe_coupling/momentum_exchange_method/destruction/Destroyer.h @@ -33,7 +33,7 @@ class NaNDestroyer { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; void operator()( const cell_idx_t & x, const cell_idx_t & y, const cell_idx_t & z, IBlock * const /*block*/, PdfField_T * const pdfField ) { for (auto d = uint_t(0); d < LatticeModel_T::Stencil::Size; ++d) diff --git a/src/pe_coupling/momentum_exchange_method/restoration/ExtrapolationDirectionFinder.h b/src/pe_coupling/momentum_exchange_method/restoration/ExtrapolationDirectionFinder.h index 7e9968d83..1cdab1b9c 100644 --- a/src/pe_coupling/momentum_exchange_method/restoration/ExtrapolationDirectionFinder.h +++ b/src/pe_coupling/momentum_exchange_method/restoration/ExtrapolationDirectionFinder.h @@ -118,7 +118,7 @@ class SphereNormalExtrapolationDirectionFinder { public: - typedef Field< pe::BodyID, 1 > BodyField_T; + using BodyField_T = Field<pe::BodyID, 1>; SphereNormalExtrapolationDirectionFinder( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & bodyFieldID ) : blockStorage_( blockStorage ), bodyFieldID_( bodyFieldID ) diff --git a/src/pe_coupling/momentum_exchange_method/restoration/PDFReconstruction.h b/src/pe_coupling/momentum_exchange_method/restoration/PDFReconstruction.h index 0d6dcfe12..6de45fbca 100644 --- a/src/pe_coupling/momentum_exchange_method/restoration/PDFReconstruction.h +++ b/src/pe_coupling/momentum_exchange_method/restoration/PDFReconstruction.h @@ -60,10 +60,10 @@ class PDFReconstruction { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef typename BoundaryHandling_T::FlagField FlagField_T; - typedef typename BoundaryHandling_T::flag_t flag_t; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using FlagField_T = typename BoundaryHandling_T::FlagField; + using flag_t = typename BoundaryHandling_T::flag_t; + using BodyField_T = Field<pe::BodyID, 1>; inline PDFReconstruction( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & pdfFieldID, diff --git a/src/pe_coupling/momentum_exchange_method/restoration/Reconstructor.h b/src/pe_coupling/momentum_exchange_method/restoration/Reconstructor.h index ad2b8adfa..c8ebb191f 100644 --- a/src/pe_coupling/momentum_exchange_method/restoration/Reconstructor.h +++ b/src/pe_coupling/momentum_exchange_method/restoration/Reconstructor.h @@ -73,8 +73,8 @@ class EquilibriumReconstructor { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using BodyField_T = Field<pe::BodyID, 1>; EquilibriumReconstructor( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & boundaryHandlingID, const BlockDataID & bodyFieldID ) @@ -168,8 +168,8 @@ class EquilibriumAndNonEquilibriumReconstructor { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using BodyField_T = Field<pe::BodyID, 1>; EquilibriumAndNonEquilibriumReconstructor( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & boundaryHandlingID, const BlockDataID & bodyFieldID, @@ -259,8 +259,8 @@ class ExtrapolationReconstructor { public: - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef Field< pe::BodyID, 1 > BodyField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using BodyField_T = Field<pe::BodyID, 1>; ExtrapolationReconstructor( const shared_ptr<StructuredBlockStorage> & blockStorage, const BlockDataID & boundaryHandlingID, const BlockDataID & bodyFieldID, diff --git a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.cpp b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.cpp index d0d36a921..9d6511d4d 100644 --- a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.cpp +++ b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.cpp @@ -35,8 +35,8 @@ namespace pe_coupling { void mapPSMBodyAndVolumeFraction( const pe::BodyID body, IBlock & block, StructuredBlockStorage & blockStorage, const BlockDataID bodyAndVolumeFractionFieldID ) { - typedef std::pair< pe::BodyID, real_t > BodyAndVolumeFraction_T; - typedef GhostLayerField< std::vector< BodyAndVolumeFraction_T >, 1 > BodyAndVolumeFractionField_T; + using BodyAndVolumeFraction_T = std::pair<pe::BodyID, real_t>; + using BodyAndVolumeFractionField_T = GhostLayerField<std::vector<BodyAndVolumeFraction_T>, 1>; BodyAndVolumeFractionField_T * bodyAndVolumeFractionField = block.getData< BodyAndVolumeFractionField_T >( bodyAndVolumeFractionFieldID ); WALBERLA_ASSERT_NOT_NULLPTR( bodyAndVolumeFractionField ); diff --git a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h index 59fb85590..56faedf94 100644 --- a/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h +++ b/src/pe_coupling/partially_saturated_cells_method/BodyAndVolumeFractionMapping.h @@ -66,8 +66,8 @@ class BodyAndVolumeFractionMapping { public: - typedef std::pair< pe::BodyID, real_t > BodyAndVolumeFraction_T; - typedef GhostLayerField< std::vector< BodyAndVolumeFraction_T >, 1 > BodyAndVolumeFractionField_T; + using BodyAndVolumeFraction_T = std::pair<pe::BodyID, real_t>; + using BodyAndVolumeFractionField_T = GhostLayerField<std::vector<BodyAndVolumeFraction_T>, 1>; BodyAndVolumeFractionMapping( const shared_ptr<StructuredBlockStorage> & blockStorage, const shared_ptr<pe::BodyStorage> & globalBodyStorage, diff --git a/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h b/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h index 66992d54d..2b326f116 100644 --- a/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h +++ b/src/pe_coupling/partially_saturated_cells_method/PSMSweep.h @@ -66,10 +66,10 @@ class PSMSweep { public: - typedef typename lbm::SweepBase< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T >::PdfField_T PdfField_T; - typedef typename LatticeModel_T::Stencil Stencil_T; - typedef std::pair< pe::BodyID, real_t > BodyAndVolumeFraction_T; - typedef Field< std::vector< BodyAndVolumeFraction_T >, 1 > BodyAndVolumeFractionField_T; + using PdfField_T = typename lbm::SweepBase<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T>::PdfField_T; + using Stencil_T = typename LatticeModel_T::Stencil; + using BodyAndVolumeFraction_T = std::pair<pe::BodyID, real_t>; + using BodyAndVolumeFractionField_T = Field<std::vector<BodyAndVolumeFraction_T>, 1>; PSMSweep( const BlockDataID & pdfFieldID, const BlockDataID & bodyAndVolumeFractionFieldID, @@ -441,7 +441,7 @@ shared_ptr< PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelo makePSMSweep( const BlockDataID & pdfFieldID, const BlockDataID & bodyAndVolumeFractionFieldID, const shared_ptr<StructuredBlockStorage> & blockStorage, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T > PSMS_T; + using PSMS_T = PSMSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T>; return shared_ptr< PSMS_T >( new PSMS_T( pdfFieldID, bodyAndVolumeFractionFieldID, blockStorage, filter, densityVelocityIn, densityVelocityOut ) ); } @@ -450,7 +450,7 @@ shared_ptr< PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelo makePSMSweep( const BlockDataID & srcID, const BlockDataID & dstID, const BlockDataID & bodyAndVolumeFractionFieldID, const shared_ptr<StructuredBlockStorage> & blockStorage, const Filter_T & filter, const DensityVelocityIn_T & densityVelocityIn, const DensityVelocityOut_T & densityVelocityOut ) { - typedef PSMSweep< LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T > PSMS_T; + using PSMS_T = PSMSweep<LatticeModel_T, Filter_T, DensityVelocityIn_T, DensityVelocityOut_T, SolidCollision_T, Weighting_T>; return shared_ptr< PSMS_T >( new PSMS_T( srcID, dstID, bodyAndVolumeFractionFieldID, blockStorage, filter, densityVelocityIn, densityVelocityOut ) ); } diff --git a/src/pe_coupling/partially_saturated_cells_method/PSMUtility.h b/src/pe_coupling/partially_saturated_cells_method/PSMUtility.h index e39c3b7b2..b78a4e45f 100644 --- a/src/pe_coupling/partially_saturated_cells_method/PSMUtility.h +++ b/src/pe_coupling/partially_saturated_cells_method/PSMUtility.h @@ -92,9 +92,9 @@ template < typename LatticeModel_T, int Weighting_T > void initializeDomainForPSM( StructuredBlockStorage & blockStorage, const BlockDataID & pdfFieldID, const BlockDataID & bodyAndVolumeFractionFieldID ) { - typedef lbm::PdfField< LatticeModel_T > PdfField_T; - typedef std::pair< pe::BodyID, real_t > BodyAndVolumeFraction_T; - typedef GhostLayerField< std::vector< BodyAndVolumeFraction_T >, 1 > BodyAndVolumeFractionField_T; + using PdfField_T = lbm::PdfField<LatticeModel_T>; + using BodyAndVolumeFraction_T = std::pair<pe::BodyID, real_t>; + using BodyAndVolumeFractionField_T = GhostLayerField<std::vector<BodyAndVolumeFraction_T>, 1>; // iterate all blocks with an iterator 'block' for( auto blockIt = blockStorage.begin(); blockIt != blockStorage.end(); ++blockIt ) diff --git a/src/pe_coupling/utility/BodiesForceTorqueContainer.h b/src/pe_coupling/utility/BodiesForceTorqueContainer.h index b18d4ec0d..72f6dcc2c 100644 --- a/src/pe_coupling/utility/BodiesForceTorqueContainer.h +++ b/src/pe_coupling/utility/BodiesForceTorqueContainer.h @@ -34,7 +34,7 @@ class BodiesForceTorqueContainer { public: - typedef std::map< walberla::id_t, std::array<real_t,6> > ForceTorqueStorage_T; + using ForceTorqueStorage_T = std::map<walberla::id_t, std::array<real_t, 6>>; BodiesForceTorqueContainer( const shared_ptr<StructuredBlockForest> & blockForest, const BlockDataID & bodyStorageID, const std::function<bool( pe::BodyID)> &bodySelectorFct = selectRegularBodies) diff --git a/src/postprocessing/MarchingCubes.impl.h b/src/postprocessing/MarchingCubes.impl.h index 6f4538742..29f22544f 100644 --- a/src/postprocessing/MarchingCubes.impl.h +++ b/src/postprocessing/MarchingCubes.impl.h @@ -378,7 +378,7 @@ void generateIsoSurface_internal( const Field_T & f, real_t threshold, - typedef Vector3<real_t> RealVec3; + using RealVec3 = Vector3<real_t>; // the field store for every edge the index of the vertex that was computed on it // or -1 for "not yet computed" diff --git a/src/stencil/D2CornerStencil.h b/src/stencil/D2CornerStencil.h index 574da37bc..9d1716100 100644 --- a/src/stencil/D2CornerStencil.h +++ b/src/stencil/D2CornerStencil.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D2CornerStencil> iterator; + using iterator = stencil::Iterator<D2CornerStencil>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D2CornerStencil<> D2CornerStencil; + using D2CornerStencil = internal::D2CornerStencil<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D2Q4.h b/src/stencil/D2Q4.h index 26131a49a..9c1f9b7b7 100644 --- a/src/stencil/D2Q4.h +++ b/src/stencil/D2Q4.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D2Q4> iterator; + using iterator = stencil::Iterator<D2Q4>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D2Q4<> D2Q4; + using D2Q4 = internal::D2Q4<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D2Q5.h b/src/stencil/D2Q5.h index 8547a4747..98cfbb009 100644 --- a/src/stencil/D2Q5.h +++ b/src/stencil/D2Q5.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D2Q5> iterator; + using iterator = stencil::Iterator<D2Q5>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D2Q5<> D2Q5; + using D2Q5 = internal::D2Q5<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D2Q9.h b/src/stencil/D2Q9.h index 4e79ab2fe..4c3dc0cd9 100644 --- a/src/stencil/D2Q9.h +++ b/src/stencil/D2Q9.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D2Q9> iterator; + using iterator = stencil::Iterator<D2Q9>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D2Q9<> D2Q9; + using D2Q9 = internal::D2Q9<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3CornerStencil.h b/src/stencil/D3CornerStencil.h index 21ba0f491..b234a89d0 100644 --- a/src/stencil/D3CornerStencil.h +++ b/src/stencil/D3CornerStencil.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3CornerStencil> iterator; + using iterator = stencil::Iterator<D3CornerStencil>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3CornerStencil<> D3CornerStencil; + using D3CornerStencil = internal::D3CornerStencil<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3EdgeCornerStencil.h b/src/stencil/D3EdgeCornerStencil.h index 8e1045b25..e3e6a2832 100644 --- a/src/stencil/D3EdgeCornerStencil.h +++ b/src/stencil/D3EdgeCornerStencil.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3EdgeCornerStencil> iterator; + using iterator = stencil::Iterator<D3EdgeCornerStencil>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3EdgeCornerStencil<> D3EdgeCornerStencil; + using D3EdgeCornerStencil = internal::D3EdgeCornerStencil<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3Q15.h b/src/stencil/D3Q15.h index ba7fecb5c..896c8c49b 100644 --- a/src/stencil/D3Q15.h +++ b/src/stencil/D3Q15.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3Q15> iterator; + using iterator = stencil::Iterator<D3Q15>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3Q15<> D3Q15; + using D3Q15 = internal::D3Q15<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3Q19.h b/src/stencil/D3Q19.h index 0d4ca0fb8..a7a520f69 100644 --- a/src/stencil/D3Q19.h +++ b/src/stencil/D3Q19.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3Q19> iterator; + using iterator = stencil::Iterator<D3Q19>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3Q19<> D3Q19; + using D3Q19 = internal::D3Q19<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3Q27.h b/src/stencil/D3Q27.h index 644ba99fe..6ba403bd5 100644 --- a/src/stencil/D3Q27.h +++ b/src/stencil/D3Q27.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3Q27> iterator; + using iterator = stencil::Iterator<D3Q27>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3Q27<> D3Q27; + using D3Q27 = internal::D3Q27<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3Q6.h b/src/stencil/D3Q6.h index 5567a7d79..8b9f81d3a 100644 --- a/src/stencil/D3Q6.h +++ b/src/stencil/D3Q6.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3Q6> iterator; + using iterator = stencil::Iterator<D3Q6>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3Q6<> D3Q6; + using D3Q6 = internal::D3Q6<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/D3Q7.h b/src/stencil/D3Q7.h index 672afa9e8..8e14c9b00 100644 --- a/src/stencil/D3Q7.h +++ b/src/stencil/D3Q7.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<D3Q7> iterator; + using iterator = stencil::Iterator<D3Q7>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::D3Q7<> D3Q7; + using D3Q7 = internal::D3Q7<>; } // namespace stencil } // namespace walberla diff --git a/src/stencil/EdgeStencil.h b/src/stencil/EdgeStencil.h index fb35bd948..1c4982c99 100644 --- a/src/stencil/EdgeStencil.h +++ b/src/stencil/EdgeStencil.h @@ -88,7 +88,7 @@ namespace stencil { /*! \name Iteration*/ //@{ - typedef stencil::Iterator<EdgeStencil> iterator; + using iterator = stencil::Iterator<EdgeStencil>; static iterator begin() { return iterator(0); } static iterator beginNoCenter() { return iterator(noCenterFirstIdx); } @@ -239,7 +239,7 @@ namespace stencil { } // namespace internal - typedef internal::EdgeStencil<> EdgeStencil; + using EdgeStencil = internal::EdgeStencil<>; } // namespace stencil } // namespace walberla diff --git a/src/timeloop/PerformanceMeter.cpp b/src/timeloop/PerformanceMeter.cpp index d79863203..98a6fc350 100644 --- a/src/timeloop/PerformanceMeter.cpp +++ b/src/timeloop/PerformanceMeter.cpp @@ -179,7 +179,7 @@ namespace timeloop { *******************************************************************************************************************/ shared_ptr< std::map<std::string, real_t> > PerformanceMeter::getReduced ( int targetRank ) { - typedef std::map<std::string, real_t> ResultMap; + using ResultMap = std::map<std::string, real_t>; shared_ptr < ResultMap > res; std::vector<real_t> totalNrCells; diff --git a/src/timeloop/PerformanceMeter.h b/src/timeloop/PerformanceMeter.h index 0efac6514..e5ccee059 100644 --- a/src/timeloop/PerformanceMeter.h +++ b/src/timeloop/PerformanceMeter.h @@ -70,7 +70,7 @@ namespace timeloop { class PerformanceMeter { public: - typedef std::function< uint_t(const IBlock &) > CountFunction; + using CountFunction = std::function<uint_t (const IBlock &)>; PerformanceMeter( StructuredBlockStorage & blockStorage ); diff --git a/src/timeloop/SelectableFunctionCreators.h b/src/timeloop/SelectableFunctionCreators.h index e3a29325c..965faf627 100644 --- a/src/timeloop/SelectableFunctionCreators.h +++ b/src/timeloop/SelectableFunctionCreators.h @@ -128,7 +128,7 @@ namespace timeloop { Set<SUID> incompatibleSelectors_; }; - typedef FuncCreator<void (IBlock*) > Sweep; + using Sweep = FuncCreator<void (IBlock *)>; template<typename SweepClass> diff --git a/src/timeloop/Timeloop.h b/src/timeloop/Timeloop.h index f1430ec63..48b7de6ce 100644 --- a/src/timeloop/Timeloop.h +++ b/src/timeloop/Timeloop.h @@ -36,7 +36,7 @@ namespace walberla { namespace timeloop { -typedef std::function<void ()> VoidFctNoArguments; +using VoidFctNoArguments = std::function<void ()>; //******************************************************************************************************************* @@ -140,7 +140,7 @@ public: //** Registration Functions ************************************************************************************** /*! \name Registration Functions */ //@{ - typedef size_t FctHandle; + using FctHandle = size_t; FctHandle addFuncBeforeTimeStep(const VoidFctNoArguments & f, @@ -198,7 +198,7 @@ protected: uint_t curTimeStep_; ///< current time step uint_t nrOfTimeSteps_; ///< total number of time steps - typedef selectable::SetSelectableObject<VoidFctNoArguments, SUID> SelectableFunc; + using SelectableFunc = selectable::SetSelectableObject<VoidFctNoArguments, SUID>; std::vector<SelectableFunc> beforeFunctions_; std::vector<SelectableFunc> afterFunctions_; diff --git a/src/vtk/BlockCellDataWriter.h b/src/vtk/BlockCellDataWriter.h index cac2599c7..877b5543b 100644 --- a/src/vtk/BlockCellDataWriter.h +++ b/src/vtk/BlockCellDataWriter.h @@ -197,7 +197,7 @@ inline void BlockCellDataWriter::push( Base64Writer& b64, const cell_idx_t x, co } // namespace internal -typedef internal::BlockCellDataWriter BlockCellDataWriterInterface; +using BlockCellDataWriterInterface = internal::BlockCellDataWriter; @@ -219,7 +219,7 @@ class BlockCellDataWriter : public BlockCellDataWriterInterface public: - typedef T value_type; + using value_type = T; static const uint_t F_SIZE = F_SIZE_ARG; @@ -285,7 +285,7 @@ template< typename T > class BlockCellDataWriterScalingAdapter : public T { public: - typedef typename T::value_type value_type; + using value_type = typename T::value_type; static const uint_t F_SIZE = T::F_SIZE; BlockCellDataWriterScalingAdapter( const std::string& id, const T & base, value_type factor ) diff --git a/src/vtk/ChainedFilter.h b/src/vtk/ChainedFilter.h index 573fff5c1..187486a74 100644 --- a/src/vtk/ChainedFilter.h +++ b/src/vtk/ChainedFilter.h @@ -37,7 +37,7 @@ class ChainedFilter { public: - typedef std::function< void ( CellSet& filteredCells, const IBlock& block, const StructuredBlockStorage& storage, const uint_t ghostLayers ) > CellFilter; + using CellFilter = std::function<void (CellSet &, const IBlock &, const StructuredBlockStorage &, const uint_t)>; void addFilter( const CellFilter& filter ) { filters_.push_back( filter ); } diff --git a/src/vtk/Initialization.h b/src/vtk/Initialization.h index 50fd523c3..43304eac2 100644 --- a/src/vtk/Initialization.h +++ b/src/vtk/Initialization.h @@ -37,7 +37,7 @@ namespace vtk { // For documentation see the documentation of function "initializeVTKOutput" in Initialization.cpp -typedef std::function< void () > OutputFunction; +using OutputFunction = std::function<void ()>; struct SelectableOutputFunction { @@ -76,9 +76,7 @@ void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & ou const std::map< std::string, VTKOutput::CellFilter > & filters, const std::map< std::string, VTKOutput::BeforeFunction > & beforeFunctions ); -typedef std::function< void ( std::vector< shared_ptr< BlockCellDataWriterInterface > > & writers, - std::map< std::string, VTKOutput::CellFilter > & filters, - std::map< std::string, VTKOutput::BeforeFunction > & beforeFunctions ) > RegisterVTKOutputFunction; +using RegisterVTKOutputFunction = std::function<void (std::vector<shared_ptr<BlockCellDataWriterInterface>> &, std::map<std::string, VTKOutput::CellFilter> &, std::map<std::string, VTKOutput::BeforeFunction> &)>; void initializeVTKOutput( std::map< std::string, SelectableOutputFunction > & outputFunctions, const RegisterVTKOutputFunction& registerVTKOutputFunction, const shared_ptr< const StructuredBlockStorage > & storage, const shared_ptr< Config > & config, diff --git a/src/vtk/PolylineDataSource.h b/src/vtk/PolylineDataSource.h index c3b39a18d..af4b8dbaf 100644 --- a/src/vtk/PolylineDataSource.h +++ b/src/vtk/PolylineDataSource.h @@ -49,7 +49,7 @@ public: uint_t components; }; - typedef std::vector< Vector3< real_t > > Polyline; + using Polyline = std::vector<Vector3<real_t>>; virtual ~PolylineDataSource() = default; diff --git a/src/vtk/VTKOutput.h b/src/vtk/VTKOutput.h index dc36ae003..d90586b5c 100644 --- a/src/vtk/VTKOutput.h +++ b/src/vtk/VTKOutput.h @@ -52,12 +52,12 @@ class VTKOutput : public NonCopyable { private: class VTKGEN : public uid::IndexGenerator< VTKGEN, size_t >{}; - typedef UID< VTKGEN > VTKUID; + using VTKUID = UID<VTKGEN>; // types used during vertex-index mapping procedure when writing (P)VTU files - typedef std::tuple< cell_idx_t, cell_idx_t, cell_idx_t > Vertex; - typedef std::tuple< real_t, real_t, real_t > VertexCoord; - typedef int32_t Index; + using Vertex = std::tuple<cell_idx_t, cell_idx_t, cell_idx_t>; + using VertexCoord = std::tuple<real_t, real_t, real_t>; + using Index = int32_t; struct VertexCompare { bool operator()( const Vertex& lhs, const Vertex& rhs ) const @@ -141,9 +141,8 @@ public: const bool continuousNumbering, const bool binary, const bool littleEndian, const bool useMPIIO, const uint_t initialExecutionCount ); - typedef std::function< void () > BeforeFunction; - typedef std::function< void ( CellSet& filteredCells, const IBlock& block, - const StructuredBlockStorage& storage, const uint_t ghostLayers ) > CellFilter; + using BeforeFunction = std::function<void ()>; + using CellFilter = std::function<void (CellSet &, const IBlock &, const StructuredBlockStorage &, const uint_t)>; ~VTKOutput(); -- GitLab From 8b337cdad44689cd91d02dc0c188f01a51ba5f66 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Fri, 18 Dec 2020 16:24:53 +0100 Subject: [PATCH 81/83] [ADD] kernel for the VBondModel, anisotropic vdW contact --- .../kernel/cnt/AnisotropicVDWContact.h | 386 ++++++++++++++++++ tests/mesa_pd/CMakeLists.txt | 3 + .../kernel/cnt/AnisotropicVDWContact.test.cpp | 135 ++++++ 3 files changed, 524 insertions(+) create mode 100644 src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h create mode 100644 tests/mesa_pd/kernel/cnt/AnisotropicVDWContact.test.cpp diff --git a/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h b/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h new file mode 100644 index 000000000..df369216e --- /dev/null +++ b/src/mesa_pd/kernel/cnt/AnisotropicVDWContact.h @@ -0,0 +1,386 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Angles.h> +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace cnt { + +/** + * anisotropic vdW contact + */ +class AnisotropicVDWContact +{ +public: + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac); + + static constexpr real_t eps_ = 0.03733_r; + static constexpr real_t A_ = 0.0223_r; + static constexpr real_t B_ = 1.31_r; + static constexpr real_t alf_ = 9.5_r; + static constexpr real_t bet_ = 4.0_r; + static constexpr real_t Cg_ = 90_r; + static constexpr real_t del_ = -7.5_r; + + static constexpr size_t M = 5; + /// Set of fitted constants, that determine the level of "smoothness" of vdW potential - + /// magnitude of shear forces between sliding CNTs + static constexpr std::array<real_t, M> C = { 0.35819_r, 0.03263_r, -0.00138_r, -0.00017_r, 0.00024_r }; + + /// vdW interaction radius w/r to inertial segment radius + static constexpr real_t CutoffFactor = 4_r; + /// CNT radius + static constexpr real_t R_CNT = 6.78_r; + static constexpr real_t R_ = R_CNT; + static constexpr real_t r_cut_ = CutoffFactor * R_; + + auto isParallel() const {return isParallel_;} + auto getLastEnergy() const {return energy_;} +private: + real_t energy_; ///< total potential + bool isParallel_; +}; + +template<typename Accessor> +inline +void AnisotropicVDWContact::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) +{ + //===Adaptation of PFC5 vdW contact model implementation==== + + // Getting the orientations of segments + Vec3 b1 = ac.getRotation(p_idx1).getMatrix() * Vec3(1.0, 0.0, 0.0); ///< ball 1 axial direction + Vec3 b2 = ac.getRotation(p_idx2).getMatrix() * Vec3(1.0, 0.0, 0.0); ///< ball 2 axial direction + + + // Distance between segments + + Vec3 n = ac.getPosition(p_idx2) - ac.getPosition(p_idx1); ///< contact normal + auto L = n.length(); + n *= (1_r/L); + + + //WALBERLA_LOG_DEVEL( "Normal: n = " << n ); + //WALBERLA_LOG_DEVEL( "Orientation of seg 2: b2 = " << b2 ); + //WALBERLA_LOG_DEVEL( "Orientation of seg 1: b1 = " << b1 ); + //WALBERLA_LOG_DEVEL( "Length of rad vect: L = " << L ); + + + constexpr real_t TOL = 10e-8_r; + //--------------------- + // NORMALS CALCULATION + //--------------------- + // names convention: + // c1 - contact 1-2 normal + // b1 - ball 1 axial direction + // b2 - ball 2 axial direction + // b3 - neytral direction + // g - alighning torque direction + // d - neytral plane normal direction + // s - shear force direction + + // angle gamma - angle between two axial directions + auto cos_gamma = b1 * b2; + + + + // if the angle between two axal directions is blunt, then inverce b2 + if (cos_gamma < 0_r) + { + b2 = -b2; + cos_gamma = -cos_gamma; + } + // check that cosine belongs [-1,1] + cos_gamma = std::min(1.0_r, cos_gamma); + cos_gamma = std::max(-1.0_r, cos_gamma); + isParallel_ = false; + if (L < 20_r && L > 16_r) + { + const auto gamma = acos(cos_gamma); + if (gamma < math::degToRad(10_r) || gamma > math::degToRad(170_r)) + isParallel_ = true; + } + //WALBERLA_LOG_DEVEL( "cos_gamma: = " << cos_gamma ); + + + // calculate functions of double argument + auto sin_gamma = std::sqrt(1.0_r - cos_gamma * cos_gamma); + auto cos_2gamma = cos_gamma * cos_gamma - sin_gamma * sin_gamma; + auto sin_2gamma = 2.0_r * sin_gamma * cos_gamma; + + //WALBERLA_LOG_DEVEL( "sin_gamma: = " << sin_gamma ); + //WALBERLA_LOG_DEVEL( "cos_2gamma: = " << cos_2gamma ); + //WALBERLA_LOG_DEVEL( "sin_2gamma: = " << sin_2gamma ); + + + // g - direction of the aligning torques - b1 X b2 + Vec3 g(0.0, 0.0, 0.0); + if (sin_gamma > TOL) + { + g = b1 % b2; + g = g * (1.0_r / g.length()); + } + //WALBERLA_LOG_DEVEL( "Aligning moment direction: g = " << g ); + + // b3 - vector defining the neutral plane ( plane of shear forces ) + Vec3 b3 = b1 + b2; + b3 = b3 * (1.0_r / b3.length()); + //WALBERLA_LOG_DEVEL( "Neutral plane defined by b3 = " << b3 ); + + // angle theta - angle between b3 and c1 + auto cos_theta = b3 * n; + // check that cosine belongs [-1,1] + cos_theta = std::min(1.0_r, cos_theta); + cos_theta = std::max(-1.0_r, cos_theta); + //WALBERLA_LOG_DEVEL( "cos_theta: = " << cos_theta ); + + // calculation of shear force direction + Vec3 s(0.0, 0.0, 0.0); + Vec3 d(0.0, 0.0, 0.0); + + if ((cos_theta > -1.0 + TOL) || (cos_theta < 1.0 - TOL)) + d = n % b3; + s = n % d; + s = s * (1.0_r / s.length()); + + //WALBERLA_LOG_DEVEL( "Shear force direction: = " << s ); + //-------------------------------- + // NORMALS CALCULATION - END + //-------------------------------- + + // Fast calculation of trigonometric functions ( Chebyshev formulas ) + real_t coss[M], sinn[M]; + real_t sin_theta = std::sqrt(1.0_r - cos_theta * cos_theta); + + coss[0] = cos_theta * cos_theta - sin_theta * sin_theta; + sinn[0] = 2.0_r * sin_theta * cos_theta; + + for (size_t i = 0; i < M - 1; ++i) + { + coss[i + 1] = coss[i] * coss[0] - sinn[i] * sinn[0]; + sinn[i + 1] = sinn[i] * coss[0] + sinn[0] * coss[i]; + } + + //WALBERLA_LOG_DEVEL( "coss: = " << coss[0] <<" "<< coss[1] <<" "<< coss[2] <<" "<< coss[3] <<" "<< coss[4]); + //WALBERLA_LOG_DEVEL( "sinn: = " << sinn[0] <<" "<< sinn[1] <<" "<< sinn[2] <<" "<< sinn[3] <<" "<< sinn[4]); + + //WALBERLA_LOG_DEVEL( "C: = " << C[0] <<" "<< C[1] <<" "<< C[2] <<" "<< C[3] <<" "<< C[4]); + + // Cutoff for theta adjustment + real_t W_th = 1_r; + real_t W_th_L = 0_r; + real_t W_th_LL = 0_r; + + // Adjustment w/r to O + real_t TH = 1_r; + real_t TH_L = 0_r; + real_t TH_LL = 0_r; + real_t TH_O = 0_r; + real_t TH_OO = 0_r; + + real_t sign = 1_r; + for (size_t i = 0; i < M; ++i) + { + TH = TH + W_th * C[i] * (sign + coss[i]); + TH_L = TH_L + W_th_L * C[i] * (sign + coss[i]); + TH_LL = TH_LL + W_th_LL * C[i] * (sign + coss[i]); + TH_O = TH_O - W_th * 2_r * real_t(i + 1) * C[i] * (sinn[i]); + TH_OO = TH_OO - W_th * 4_r * real_t(i + 1) * real_t(i + 1) * C[i] * (coss[i]); + sign *= -1_r; + } + + //WALBERLA_LOG_DEVEL( "TH: = " << TH ); + //WALBERLA_LOG_DEVEL( "TH_L: = " << TH_L ); + //WALBERLA_LOG_DEVEL( "TH_LL: = " << TH_LL ); + //WALBERLA_LOG_DEVEL( "TH_O: = " << TH_O ); + //WALBERLA_LOG_DEVEL( "TH_OO: = " << TH_OO ); + + + //------------------------------------------------------------------ + // THIS BLOCK IMPLEMENTS IF THE DISTANCE L IS WITHIN WORKING RANGE + //------------------------------------------------------------------ + if ((L < 2_r * r_cut_) && (L > 2_r * R_ * 1.2_r * TH)) + { + //-----Constants that appear in the potential-------------------------- + // This set of constants is described in our paper. + //--------------------------------------------------------------------- + + //-----Function D and its derivatives----------------------- + real_t D = L / (R_ * TH) - 2_r; + real_t D_L = 1_r / (R_ * TH) - (L * TH_L) / (R_ * TH * TH); + real_t D_O = -(L * TH_O) / (R_ * TH * TH); + real_t D_LL = -(TH_L) / (R_ * TH * TH); + D_LL = D_LL - ((R_ * TH * TH) * (TH_L + L * TH_LL)) / (R_ * R_ * TH * TH * TH * TH); + D_LL = D_LL + (2_r * R_ * L * TH * TH_L * TH_L) / (R_ * R_ * TH * TH * TH * TH); + real_t D_OO = -(R_ * L * TH_OO * TH * TH) / (R_ * R_ * TH * TH * TH * TH); + D_OO = D_OO + (2_r * R_ * L * TH * TH_O * TH_O) / (R_ * R_ * TH * TH * TH * TH); + //----------------------------------------------------------- + + //WALBERLA_LOG_DEVEL( "D: = " << D ); + //WALBERLA_LOG_DEVEL( "D_L: = " << D_L ); + //WALBERLA_LOG_DEVEL( "D_LL: = " << D_LL ); + //WALBERLA_LOG_DEVEL( "D_O: = " << D_O ); + //WALBERLA_LOG_DEVEL( "D_OO: = " << D_OO ); + + + //----Function Vc and its derivatives--------------------------------------- + const real_t DpowAlpha0 = std::pow(D, -(alf_)); + const real_t DpowAlpha1 = std::pow(D, -(alf_ + 1)); + const real_t DpowAlpha2 = std::pow(D, -(alf_ + 2)); + const real_t DpowBeta0 = std::pow(D, -(bet_)); + const real_t DpowBeta1 = std::pow(D, -(bet_ + 1)); + const real_t DpowBeta2 = std::pow(D, -(bet_ + 2)); + real_t Vc = 4_r * eps_ * (A_ * DpowAlpha0 - B_ * DpowBeta0); + real_t Vc_L = 4_r * eps_ * (-alf_ * A_ * DpowAlpha1 + bet_ * B_ * DpowBeta1) * D_L; + real_t Vc_O = 4_r * eps_ * (-alf_ * A_ * DpowAlpha1 + bet_ * B_ * DpowBeta1) * D_O; + real_t Vc_LL = 4_r * eps_ * (alf_ * (alf_ + 1_r) * A_ * DpowAlpha2 - bet_ * (bet_ + 1_r) * B_ * DpowBeta2) * D_L; + Vc_LL = Vc_LL + 4_r * eps_ * (-alf_ * A_ * DpowAlpha1 + bet_ * B_ * DpowBeta1) * D_LL; + real_t Vc_OO = 4_r * eps_ * (alf_ * (alf_ + 1_r) * A_ * DpowAlpha2 - bet_ * (bet_ + 1_r) * B_ * DpowBeta2) * D_O; + Vc_OO = Vc_OO + 4_r * eps_ * (-alf_ * A_ * DpowAlpha1 + bet_ * B_ * DpowBeta1) * D_OO; + //-------------------------------------------------------------------------- + + //WALBERLA_LOG_DEVEL( "VC = " << Vc ); + //WALBERLA_LOG_DEVEL( "VC_L = " << Vc_L ); + //WALBERLA_LOG_DEVEL( "VC_LL = " << Vc_LL ); + + //WALBERLA_LOG_DEVEL( "VC_O = " << Vc_O ); + //WALBERLA_LOG_DEVEL( "VC_OO = " << Vc_OO ); + + + // Cutoff for u adjustment + real_t W_u = 1_r; + real_t W_u_L = 0_r; + real_t W_u_LL = 0_r; + WALBERLA_UNUSED(W_u_LL); + + // Cubic cutoff function 3T->4T (hardcoded since we do not need to mess w these parameters) + constexpr auto Q1_ = -80.0_r; + constexpr auto Q2_ = 288.0_r; + constexpr auto Q3_ = -336.0_r; + constexpr auto Q4_ = 128.0_r; + const real_t rcut2inv = 1_r / (2.0_r * r_cut_); + real_t nd = L * rcut2inv; + if ((nd > 0.75_r) && (nd < 1.0_r)) + { + W_u = Q1_ + Q2_ * nd + Q3_ * nd * nd + Q4_ * nd * nd * nd; + W_u_L = (Q2_ + 2.0_r * Q3_ * nd + 3.0_r * Q4_ * nd * nd) * rcut2inv; + W_u_LL = (2.0_r * Q3_ + 6.0_r * Q4_ * nd) * rcut2inv * rcut2inv; + } + //-------------------------------------------------------------------------- + + //WALBERLA_LOG_DEVEL( "W_u = " << W_u ); + //WALBERLA_LOG_DEVEL( "W_u_L = " << W_u_L ); + //WALBERLA_LOG_DEVEL( "W_u_LL = " << W_u_LL ); + + + // Cutoff for gamma adjustment + + real_t W_ga, W_ga_L, W_ga_LL; + if (L / R_ > 2.75_r) + { + W_ga = Cg_ * std::pow((L / R_), del_); + W_ga_L = ((del_ * Cg_) / R_) * std::pow((L / R_), del_ - 1_r); + W_ga_LL = ((del_ * (del_ - 1) * Cg_) / (R_ * R_)) * std::pow((L / R_), del_ - 2_r); + } else + { + W_ga = Cg_ * std::pow((2.75_r), del_); + W_ga_L = 0; + W_ga_LL = 0; + } + + //WALBERLA_LOG_DEVEL( "W_ga = " << W_ga ); + //WALBERLA_LOG_DEVEL( "W_ga_L = " << W_ga_L ); + //WALBERLA_LOG_DEVEL( "W_ga_LL = " << W_ga_LL ); + + + real_t GA = 1_r; + real_t GA_L = 0_r; + real_t GA_LL = 0_r; + WALBERLA_UNUSED(GA_LL); + real_t GA_G = 0_r; + real_t GA_GG = 0_r; + WALBERLA_UNUSED(GA_GG); + if (std::abs(sin_gamma) > TOL) + { + GA = 1_r + W_ga * (1_r - cos_2gamma); + GA_L = W_ga_L * (1_r - cos_2gamma); + GA_LL = W_ga_LL * (1_r - cos_2gamma); + GA_G = 2_r * W_ga * sin_2gamma; + GA_GG = 4_r * W_ga * cos_2gamma; + } + + //----Forces and torque----------------------- + real_t FL = -GA_L * W_u * Vc - GA * W_u_L * Vc - GA * W_u * Vc_L; + real_t FO = -(1_r / L) * GA * W_u * Vc_O; + real_t MG = -GA_G * W_u * Vc; + + //WALBERLA_LOG_DEVEL( "FL = " << FL ); + //WALBERLA_LOG_DEVEL( "FO = " << FO ); + //WALBERLA_LOG_DEVEL( "MG = " << MG ); + + + Vec3 force = FL * n + FO * s; + Vec3 moment = MG * g; + + + //WALBERLA_LOG_DEVEL( "Contact force: = " << force ); + //WALBERLA_LOG_DEVEL( "Contact moment: = " << moment ); + + addForceAtomic(p_idx1, ac, -force); + addForceAtomic(p_idx2, ac, force); + + addTorqueAtomic(p_idx1, ac, -moment); + addTorqueAtomic(p_idx2, ac, moment); + + // Potential energy + energy_ = GA * W_u * Vc; + // WALBERLA_LOG_DEVEL( "U_vdw = " << U ); + } else if (L <= 2_r * R_ * 1.2_r * TH) + { // Small distance + //WALBERLA_LOG_DEVEL( "Small distance"); + energy_ = 0_r; + real_t F = -1_r; + addForceAtomic(p_idx1, ac, F * n); + addForceAtomic(p_idx2, ac, -F * n); + } +} + +} //namespace cnt +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index 4e7985268..48c07d87c 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -84,6 +84,9 @@ waLBerla_execute_test( NAME MESA_PD_DropTestGeneral ) waLBerla_compile_test( NAME MESA_PD_Kernel_ClearNextNeighborSync FILES kernel/ClearNextNeighborSync.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_ClearNextNeighborSync PROCESSES 2 ) +waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_AnisotropicVDWContact FILES kernel/cnt/AnisotropicVDWContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_AnisotropicVDWContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_CNT_IntegratedVDWContact FILES kernel/cnt/IntegratedVDWContact.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_CNT_IntegratedVDWContact ) diff --git a/tests/mesa_pd/kernel/cnt/AnisotropicVDWContact.test.cpp b/tests/mesa_pd/kernel/cnt/AnisotropicVDWContact.test.cpp new file mode 100644 index 000000000..9fcde4d9a --- /dev/null +++ b/tests/mesa_pd/kernel/cnt/AnisotropicVDWContact.test.cpp @@ -0,0 +1,135 @@ +//====================================================================================================================== +// +// This file is part of waLBerla. waLBerla 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 3 of +// the License, or (at your option) any later version. +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include "SphericalSegmentAccessor.h" + +#include "mesa_pd/data/Flags.h" +#include "mesa_pd/data/ParticleStorage.h" +#include "mesa_pd/kernel/ParticleSelector.h" +#include "mesa_pd/kernel/cnt/AnisotropicVDWContact.h" +#include "mesa_pd/kernel/cnt/ViscousDamping.h" +#include "mesa_pd/kernel/cnt/Parameters.h" +#include "mesa_pd/kernel/VelocityVerlet.h" +#include "mesa_pd/vtk/ParticleVtkOutput.h" + +#include "core/Environment.h" +#include "core/math/Constants.h" +#include "vtk/VTKOutput.h" + +namespace walberla { +using namespace walberla::mesa_pd; + +int main(int argc, char **argv) +{ + Environment env(argc, argv); + walberla::mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<walberla::real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + logging::Logging::instance()->setStreamLogLevel(logging::Logging::INFO); + logging::Logging::instance()->setFileLogLevel(logging::Logging::INFO); + + WALBERLA_LOG_INFO_ON_ROOT("loading configuration parameters"); + constexpr auto numSimulationSteps = 20000ll; + constexpr auto outputInterval = 100ll; + + WALBERLA_LOG_INFO_ON_ROOT("creating initial particle setup"); + auto ps = std::make_shared<data::ParticleStorage>(10); + auto ac = SphericalSegmentAccessor(ps); + + using namespace kernel::cnt; + data::Particle &&sp1 = *ps->create(); + sp1.setPosition(Vec3(0_r, 0_r, 0_r)); + sp1.setSegmentID(1); + sp1.setClusterID(1); + + data::Particle &&sp2 = *ps->create(); + sp2.setPosition(Vec3(20_r, 20_r, 20_r)); + sp2.setSegmentID(2); + sp2.setClusterID(2); + + WALBERLA_LOG_INFO_ON_ROOT("setting up VTK output"); + auto vtkOutput = make_shared<mesa_pd::vtk::ParticleVtkOutput>(ps); + vtkOutput->addOutput<data::SelectParticlePosition>("position"); + auto vtkWriter = walberla::vtk::createVTKOutput_PointData(vtkOutput, + "cnt", + 1, + "vtk_integrated", + "particles", + false, + false); + + WALBERLA_LOG_INFO_ON_ROOT("setting up interaction models"); + kernel::cnt::AnisotropicVDWContact vdW_anisotropic; + kernel::cnt::ViscousDamping viscous_damping(0.1_r * 1052.0_r, 0.1_r * 1052.0_r); + kernel::VelocityVerletPreForceUpdate vv_pre(kernel::cnt::dT); + kernel::VelocityVerletPostForceUpdate vv_post(kernel::cnt::dT); + + WALBERLA_LOG_INFO_ON_ROOT("running simulation"); + + real_t U = 0_r; + for (auto i = 0; i < numSimulationSteps; ++i) + { + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_pre, + ac); + + U = 0_r; + ps->forEachParticlePairHalf(false, + kernel::SelectAll(), + ac, + [&](size_t p_idx1, size_t p_idx2) + { + vdW_anisotropic(p_idx1, p_idx2, ac); + U += vdW_anisotropic.getLastEnergy(); + viscous_damping(p_idx1, p_idx2, ac); + }); + + ps->forEachParticle(false, + kernel::SelectAll(), + ac, + vv_post, + ac); + + if( i % outputInterval == 0 ) + { +// vtkWriter->write(); +// WALBERLA_LOG_DEVEL(i << " : " << U); + } + } + + WALBERLA_CHECK_LESS(U, -1.16_r) + + return EXIT_SUCCESS; +} +} // namespace walberla + +int main(int argc, char *argv[]) +{ + return walberla::main(argc, argv); +} -- GitLab From a5a0edf728a792d3e03f4eb62ecf2c28b94fd575 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 9 Mar 2021 16:01:03 +0100 Subject: [PATCH 82/83] Mark walberla::geometry::getClosestLineBoxPoints as being wrong! --- src/geometry/GeometricalFunctions.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/geometry/GeometricalFunctions.cpp b/src/geometry/GeometricalFunctions.cpp index e904312d9..3ae39d9ee 100644 --- a/src/geometry/GeometricalFunctions.cpp +++ b/src/geometry/GeometricalFunctions.cpp @@ -64,6 +64,7 @@ namespace geometry { void getClosestLineBoxPoints( const Vector3<real_t>& p1, const Vector3<real_t>& p2, const Vector3<real_t>& c, const Matrix3<real_t>& R, const Vector3<real_t>& side, Vector3<real_t>& lret, Vector3<real_t>& bret ) { + WALBERLA_ABORT("This function produces incorrect results! See https://i10git.cs.fau.de/walberla/walberla/-/issues/25"); using namespace walberla::math; //----- Note: All computations will be performed in the box-relative coordinate-system ----- -- GitLab From 6a8bb6a0d2d798af7199b9b6f1a11ebf17ce6dc5 Mon Sep 17 00:00:00 2001 From: Sebastian Eibl <sebastian.eibl@fau.de> Date: Tue, 16 Mar 2021 16:31:06 +0000 Subject: [PATCH 83/83] [API] TimingTree::getReduced now ensures consistent timing nodes This prevents possible deadlocks during reduction at the cost of an additional communication. --- src/core/timing/TimingTree.h | 45 +++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/src/core/timing/TimingTree.h b/src/core/timing/TimingTree.h index e7fcda960..32ed44549 100644 --- a/src/core/timing/TimingTree.h +++ b/src/core/timing/TimingTree.h @@ -1,15 +1,15 @@ //====================================================================================================================== // -// This file is part of waLBerla. waLBerla is free software: you can +// This file is part of waLBerla. waLBerla 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 3 of +// License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. -// -// waLBerla 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 +// +// waLBerla 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 waLBerla (see COPYING.txt). If not, see <http://www.gnu.org/licenses/>. // @@ -68,16 +68,19 @@ public: /// Resets the the timing hierarchy void reset(); - //** Reduction ****************************************************************************************************** - /*! \name Reduction */ - //@{ /// Collects all the timing data from different processes - TimingTree<TP> getReduced( ReduceType rt = REDUCE_TOTAL, int targetRank = 0 ) const; + /// + /// \param rt type of reduction used + /// \param targetRank + /// \param callSynchronize call synchronize() before doing the reduction + /// \return + /// + /// \attention Setting callSynchronize to false can lead to deadlocks during reduction if different ranks + /// have different timing nodes! Setting it to true causes an additional communication. + TimingTree<TP> getReduced( ReduceType rt = REDUCE_TOTAL, int targetRank = 0, bool callSynchronize = true ) const; /// Adds entries which only exist on other processes. Has to be collectively called on all processes! void synchronize(); - //@} - //******************************************************************************************************************* /// Returns the raw tree data structure const TimingNode<TP>& getRawData() const; @@ -109,15 +112,15 @@ std::ostream& operator<<( std::ostream& os, const TimingTree<TP>& tt ) template< typename TP > // Timing policy TimingTree<TP>::TimingTree() - : current_(&root_) + : current_(&root_) { } template< typename TP > // Timing policy TimingTree<TP>::TimingTree(const TimingTree<TP>& tt) - : root_(tt.root_) - , current_(&root_) + : root_(tt.root_) + , current_(&root_) { WALBERLA_ASSERT_EQUAL(tt.current_, &tt.root_, "Copying is only allowed for stopped TimingTrees!\nTimer still running: " << getCurrentTimerName() ); } @@ -133,8 +136,8 @@ TimingTree<TP>& TimingTree<TP>::operator=(const TimingTree<TP>& tt) template< typename TP > // Timing policy void TimingTree<TP>::swap(TimingTree<TP>& tt) { - std::swap(current_, tt.current_); - std::swap(root_, tt.root_); + std::swap(current_, tt.current_); + std::swap(root_, tt.root_); } /// \param name timer name. '.' is not allowed in the timer name! @@ -189,9 +192,13 @@ void TimingTree<TP>::reset() } template< typename TP > // Timing policy -TimingTree<TP> TimingTree<TP>::getReduced( ReduceType rt, int targetRank ) const +TimingTree<TP> TimingTree<TP>::getReduced( ReduceType rt, int targetRank, bool callSynchronize ) const { TimingTree<TP> tt(*this); + if (callSynchronize) + { + tt.synchronize(); + } reduceInplace( tt.root_, rt, targetRank ); return tt; } -- GitLab