...
 
Commits (20)
......@@ -9,7 +9,6 @@
- export NUM_CORES=$(nproc --all)
- export MAX_BUILD_CORES=$(( $(awk '( $1 == "MemTotal:" ) { print $2 }' /proc/meminfo) / ( 4 * 1024 * 1024 ) ))
- "[[ $MAX_BUILD_CORES -lt $NUM_CORES ]] && export NUM_BUILD_CORES=$MAX_BUILD_CORES || export NUM_BUILD_CORES=$NUM_CORES"
- export
- $CXX --version
- cmake --version
- ccache --version
......@@ -698,7 +697,6 @@ cppcheck:
coverage:
image: walberla/coverage
script:
- export
- $CXX --version
- cmake --version
- gcovr --version
......@@ -743,7 +741,6 @@ coverage:
- export OMP_NUM_THREADS=4
- export OMP_WAIT_POLICY="PASSIVE"
- export MSMPI_DISABLE_SHM=1
- export
- cmake --version
- mkdir build
- cd build
......
......@@ -34,7 +34,7 @@ set ( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${walberla_SOURCE_DIR}/cmake )
include ( waLBerlaFunctions )
set_version( 3 0 )
set_version( 3 3 )
if( CMAKE_VERSION VERSION_LESS 2.8.3 )
include( CMakeParseArgumentsCompat )
......@@ -69,7 +69,7 @@ option ( WALBERLA_BUILD_TOOLS "Build Tools"
option ( WALBERLA_BUILD_TUTORIALS "Build Tutorials" ON )
option ( WALBERLA_BUILD_WITH_MPI "Build with MPI" ON )
option ( WALBERLA_BUILD_WITH_METIS "Build with metis graph partitioner" ON )
option ( WALBERLA_BUILD_WITH_METIS "Build with metis graph partitioner" OFF )
option ( WALBERLA_BUILD_WITH_GPROF "Enables gprof" )
option ( WALBERLA_BUILD_WITH_GCOV "Enables gcov" )
......
## This file should be placed in the root directory of your project.
## Then modify the CMakeLists.txt file in the root directory of your
## project to incorporate the testing dashboard.
##
## # The following are required to submit to the CDash dashboard:
## ENABLE_TESTING()
## INCLUDE(CTest)
set(CTEST_PROJECT_NAME "waLBerla")
set(CTEST_NIGHTLY_START_TIME "01:00:00 UTC")
set(CTEST_DROP_METHOD "http")
set(CTEST_DROP_SITE "www10.informatik.uni-erlangen.de")
set(CTEST_DROP_LOCATION "/Research/Projects/walberla/CDash/submit.php?project=waLBerla")
set(CTEST_DROP_SITE_CDASH TRUE)
set (MEMORYCHECK_COMMAND:FILEPATH "/usr/bin/valgrind")
set (MEMORYCHECK_COMMAND_OPTIONS "--show-reachable=no")
set (MEMORYCHECK_SUPPRESSIONS_FILE "${CMAKE_SOURCE_DIR}/openmpi-valgrind.supp")
......@@ -254,7 +254,7 @@ endfunction ( waLBerla_compile_test )
# app or test folder:
# waLBerla_link_files_to_builddir( "*.prm" )
#
# Symlinking works only under linux, when using windows nothing happens..
# Symlinking works only under linux, on windows the files are copied. For in-source builds this does nothing.
#
#######################################################################################################################
......
......@@ -20,6 +20,7 @@
//======================================================================================================================
#include "BlockForest.h"
#include "BlockForestFile.h"
#include "BlockNeighborhoodSection.h"
#include "SetupBlockForest.h"
#include "core/Abort.h"
......@@ -2752,8 +2753,9 @@ void BlockForest::update( PhantomBlockForest & phantomForest )
}
/// ATTENTION: 'suidMap' and 'suidBytes' must be identical for every process!
/// For a description of the file format see BlockForestFile.h
/// \attention 'suidMap' and 'suidBytes' must be identical for every process!
/// \see BlockForestFile.h
void BlockForest::saveToFile( const std::string & filename, FileIOMode fileIOMode,
const std::map< SUID, boost::dynamic_bitset<uint8_t> > & suidMap, const uint_t suidBytes ) const
{
......@@ -2764,7 +2766,7 @@ void BlockForest::saveToFile( const std::string & filename, FileIOMode fileIOMod
uint_t dataSize = uint_t(2) + blocks_.size() * ( blockIdBytes + suidBytes ) + uint_t(2) + neighborhood_.size() * processIdBytes_;
if( MPIManager::instance()->rank() == 0 )
{
dataSize += uint_c(89); // header
dataSize += internal::FILE_HEADER_SIZE; // header
++dataSize; // number of SUIDs
for( auto suid = suidMap.begin(); suid != suidMap.end(); ++suid )
dataSize += uint_t(1) + uint_c( suid->first.getIdentifier().length() );
......@@ -2950,6 +2952,12 @@ void BlockForest::saveToFile( const std::string & filename, FileIOMode fileIOMod
file.close();
}
else
{
// begin()/end() must also be called on each slave process in order to
// properly finalize the communication
WALBERLA_CHECK( bufferSystem.begin() == bufferSystem.end() );
}
}
else
{
......
//======================================================================================================================
//
// 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 BlockForestFile.h
//! \author Florian Schornbaum <florian.schornbaum@fau.de>
//
//======================================================================================================================
#pragma once
#include "core/DataTypes.h"
namespace walberla {
namespace blockforest {
namespace internal {
//**********************************************************************************************************************
/*!
* \file BlockForestFile.h
* \brief Description of the BlockForest save file format.
*
* \section FileFormat File Format
*
* \subsection HEADER HEADER
*
* BYTES | DESCRIPTION
* ---------------------------|-----------------
* 6 x ( 3 + sizeof(real_t) ) | domain AABB
* 3 x 4 | number of coarse/root blocks in each direction ( max 2^32 = 4 294 967 296 )
* 3 x 1 | domain periodicity
* 1 | block forest depth (= number of levels - 1)
* 1 | treeIdDigits (= number of bits used for storing the tree ID [tree ID marker + tree index])
* 1 | processIdBytes (= number of bytes required for storing process IDs)
* 1 | insertBuffersIntoProcessNetwork? ( 0=no, 1=yes )
* 4 | number of processes ( max 2^32 = 4 294 967 296 )
*
* --> 23 + 6 x ( 3 + sizeof(real_t) ) BYTES
*
* \subsection SUID SUID MAPPING:
*
* 1 | number of SUIDs (= #SUIDs)
*
* \code{.unparsed}
* for each SUID:
* 1 | length of the UID identifier string
* length-of-string | UID identifier string
* \endcode
*
* --> 1 + #SUIDs + number-of-characters-of-all-identifiers-combined BYTES
*
* How the mapping works:\n
* SUID #1 is assigned bit #1 ( -> [...]0 0000 0001 )\n
* SUID #2 is assigned bit #2 ( -> [...]0 0000 0010 )\n
* SUID #3 is assigned bit #3 ( -> [...]0 0000 0100 )\n
* ...\n
* For every block a bit mask containing information about all SUIDs (i.e., is the corresponding SUID set at this block?) is saved.
* -> The number of available SUIDs determines the size that is needed to store this bit mask (= SUID-mask-bytes).
* One byte is enough to hold 8 SUIDs, two bytes are enough to hold 16 SUIDs, ...
*
* \subsection BLOCKDATA BLOCK DATA
*
* \code{.unparsed}
* for each process:
* 2 | number of blocks (can be '0' -> buffer process! - 2^16 = 65 536 )
* if( number-of-blocks > 0 ):
* for each block:
* block-ID-bytes | ID of the block (the number of bytes required for storing the block ID largely depends on the size
* of the simulation, the total number of blocks, and the number of refinement levels)
* SUID-mask-bytes | state of the block = bit mask containing information about all SUIDs (see "How the mapping works" for SUIDs,
* SUID-mask-bytes can be equal to 0 bytes if no SUIDs exist!)
* 2 | number of neighbor processes
* for each neighbor process:
* process-ID-bytes | process ID / rank of the neighbor process (one byte if there are less than 257 processes,
* two bytes if there are less than 65 537 processes, ...)
* \endcode
*/
//**********************************************************************************************************************
static const uint_t FILE_HEADER_SIZE = 6 * sizeof( real_t ) + 6 + 12 + 3 * 4 + 3 + 1 + 1 + 1 + 1 + 4;
}
}
}
......@@ -49,6 +49,11 @@
#ifdef WALBERLA_BUILD_WITH_METIS
// external software includes
#include "metis.h"
#include <boost/type_traits/is_same.hpp>
static_assert( boost::is_same< ::real_t, ::walberla::real_t >::value , "The width of waLBerla's real_t data type does not match the width of METIS' real_t data type. " \
"Please adapt either waLBerla's CMake option WALBERLA_DOUBLE_ACCURACY or change REALTYPEWIDTH in metis.h." );
#endif
#ifdef _MSC_VER
......@@ -56,4 +61,4 @@
#pragma pop_macro( "INT64_MIN" )
#pragma pop_macro( "INT32_MAX" )
#pragma pop_macro( "INT32_MIN" )
#endif
#endif
\ No newline at end of file
......@@ -19,6 +19,7 @@
//
//======================================================================================================================
#include "BlockForestFile.h"
#include "BlockNeighborhoodConstruction.h"
#include "BlockNeighborhoodSection.h"
#include "HilbertCurveConstruction.h"
......@@ -1615,57 +1616,9 @@ void SetupBlockForest::calculateProcessDistributionFinalization( const bool reor
//**********************************************************************************************************************
/*!
* File Format:
*
* HEADER:
* -------
* BYTES | DESCRIPTION
* 6 x ( 3 + real_t ) | domain AABB
* 3 x 4 | number of coarse/root blocks in each direction ( max 2^32 = 4 294 967 296 )
* 3 x 1 | domain periodicity
* 1 | block forest depth (= number of levels - 1)
* 1 | treeIdDigits (= number of bits used for storing the tree ID [tree ID marker + tree index])
* 1 | processIdBytes (= number of bytes required for storing process IDs)
* 1 | insertBuffersIntoProcessNetwork? ( 0=no, 1=yes )
* 4 | number of processes ( max 2^32 = 4 294 967 296 )
*
* --> 23 + 6 x ( 3 + real_t ) BYTES
*
* SUID MAPPING:
* -------------
* 1 | number of SUIDs (= #SUIDs)
*
* for each SUID:
* 1 | length of the UID identifier string
* length-of-string | UID identifier string
*
* --> 1 + #SUIDs + number-of-characters-of-all-identifiers-combined BYTES
*
* How the mapping works:
* SUID #1 is assigned bit #1 ( -> [...]0 0000 0001 )
* SUID #2 is assigned bit #2 ( -> [...]0 0000 0010 )
* SUID #3 is assigned bit #3 ( -> [...]0 0000 0100 )
* ...
* For every block a bit mask containing information about all SUIDs (i.e., is the corresponding SUID set at this block?) is saved.
* -> The number of available SUIDs determines the size that is needed to store this bit mask (= SUID-mask-bytes).
* One byte is enough to hold 8 SUIDs, two bytes are enough to hold 16 SUIDs, ...
*
* BLOCK DATA:
* -----------
* for each process:
* 2 | number of blocks (can be '0' -> buffer process! - 2^16 = 65 536 )
* if( number-of-blocks > 0 ):
* for each block:
* block-ID-bytes | ID of the block (the number of bytes required for storing the block ID largely depends on the size
* of the simulation, the total number of blocks, and the number of refinement levels)
* SUID-mask-bytes | state of the block = bit mask containing information about all SUIDs (see "How the mapping works" for SUIDs,
* SUID-mask-bytes can be equal to 0 bytes if no SUIDs exist!)
* 2 | number of neighbor processes
* for each neighbor process:
* process-ID-bytes | process ID / rank of the neighbor process (one byte if there are less than 257 processes,
* two bytes if there are less than 65 537 processes, ...)
*/
/// \brief
///
/// For a description of the file format see BlockForestFile.h \see BlockForestFile.h
//**********************************************************************************************************************
void SetupBlockForest::saveToFile( const char* const filename ) const {
......@@ -1675,7 +1628,7 @@ void SetupBlockForest::saveToFile( const char* const filename ) const {
// HEADER
uint_t offset = 0;
std::vector< uint8_t > buffer( 6 * sizeof( real_t ) + 6 + 12 + 3 * 4 + 3 + 1 + 1 + 1 + 1 + 4 );
std::vector< uint8_t > buffer( internal::FILE_HEADER_SIZE );
// domain AABB
......
......@@ -363,6 +363,12 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterWeighted( std::vector<
balanceWeighted( allBlocks, blocksPerLevel, targets, sender );
}
else
{
// begin()/end() must also be called on each slave process in order to
// properly finalize the communication
WALBERLA_CHECK( bufferSystem.begin() == bufferSystem.end() );
}
masterEnd( targets, sender, targetProcess, processesToRecvFrom );
}
......@@ -430,6 +436,12 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterNoWeight( std::vector<
balanceNoWeight( allBlocks, blocksPerLevel, targets, sender );
}
else
{
// begin()/end() must also be called on each slave process in order to
// properly finalize the communication
WALBERLA_CHECK( bufferSystem.begin() == bufferSystem.end() );
}
masterEnd( targets, sender, targetProcess, processesToRecvFrom );
}
......@@ -865,6 +877,12 @@ void DynamicLevelwiseCurveBalance< PhantomData_T >::masterEnd( std::vector< std:
recvIt.buffer() >> targets[0] >> sender[0];
}
}
else
{
// begin()/end() must also be called on each slave process in order to
// properly finalize the communication
WALBERLA_CHECK( resultsBufferSystem.begin() == resultsBufferSystem.end() );
}
finalAssignment( uint_t(0), targets, sender, targetProcess, processesToRecvFrom );
}
......
......@@ -396,8 +396,8 @@ typename GenericAABB< T >::value_type GenericAABB< T >::zMax() const
template< typename T >
bool GenericAABB< T >::empty() const
{
return walberla::isIdentical( minCorner_[0], maxCorner_[0] ) &&
walberla::isIdentical( minCorner_[1], maxCorner_[1] ) &&
return walberla::isIdentical( minCorner_[0], maxCorner_[0] ) ||
walberla::isIdentical( minCorner_[1], maxCorner_[1] ) ||
walberla::isIdentical( minCorner_[2], maxCorner_[2] );
}
......
......@@ -167,7 +167,7 @@ public:
inline bool isZero() const;
inline const Matrix3 getCholesky() const;
template< typename Other > inline const Vector3<HIGH> solve( const Vector3<Other> &rhs ) const;
inline real_t trace() const;
inline Type trace() const;
//@}
//*******************************************************************************************************************
......@@ -1315,13 +1315,13 @@ inline const Vector3<HIGH> Matrix3<Type>::solve( const Vector3<Other> &rhs ) con
//**********************************************************************************************************************
/*!\fn real_t Matrix3<Type>::trace() const
/*!\fn Type Matrix3<Type>::trace() const
// \brief Computes the trace of the matrix (sum of diagonal elements).
//
// \return The trace of the matrix.
*/
template< typename Type >
inline real_t Matrix3<Type>::trace() const
inline Type Matrix3<Type>::trace() const
{
return v_[0] + v_[4] + v_[8];
}
......
......@@ -22,15 +22,15 @@
#include "BufferSystem.h"
#include "core/logging/Logging.h"
#include "core/mpi/MPIManager.h"
#include "core/debug/CheckFunctions.h"
namespace walberla {
namespace mpi {
#ifndef NDEBUG
std::set<int> BufferSystem::activeTags_;
#endif
//======================================================================================================================
//
......@@ -92,6 +92,50 @@ BufferSystem::BufferSystem( const MPI_Comm & communicator, int tag )
{
}
BufferSystem::BufferSystem( const BufferSystem &other )
: knownSizeComm_ ( other.knownSizeComm_.getCommunicator(), other.knownSizeComm_.getTag() ),
unknownSizeComm_( other.knownSizeComm_.getCommunicator(), other.knownSizeComm_.getTag() ),
noMPIComm_ ( other.knownSizeComm_.getCommunicator(), other.knownSizeComm_.getTag() ),
currentComm_ ( NULL ),
sizeChangesEverytime_( other.sizeChangesEverytime_ ),
communicationRunning_( other.communicationRunning_ ),
recvInfos_( other.recvInfos_ ),
sendInfos_( other.sendInfos_ )
{
WALBERLA_ASSERT( !communicationRunning_, "Can't copy BufferSystem while communication is running" );
if( other.currentComm_ == &other.knownSizeComm_ )
currentComm_ = &knownSizeComm_;
else if ( other.currentComm_ == &other.unknownSizeComm_ )
currentComm_ = &unknownSizeComm_;
else if ( other.currentComm_ == &other.noMPIComm_ )
currentComm_ = &noMPIComm_;
else
currentComm_ = NULL; // receiver information not yet set
}
BufferSystem & BufferSystem::operator=( const BufferSystem & other )
{
WALBERLA_ASSERT( !communicationRunning_, "Can't copy BufferSystem while communication is running" );
sizeChangesEverytime_ = other.sizeChangesEverytime_;
communicationRunning_ = other.communicationRunning_;
recvInfos_ = other.recvInfos_;
sendInfos_ = other.sendInfos_;
if( other.currentComm_ == &other.knownSizeComm_ )
currentComm_ = &knownSizeComm_;
else if ( other.currentComm_ == &other.unknownSizeComm_ )
currentComm_ = &unknownSizeComm_;
else if ( other.currentComm_ == &other.noMPIComm_ )
currentComm_ = &noMPIComm_;
else
currentComm_ = NULL; // receiver information not yet set
return *this;
}
//======================================================================================================================
//
// Receive Information Setup
......@@ -309,14 +353,12 @@ void BufferSystem::send( MPIRank rank )
//**********************************************************************************************************************
void BufferSystem::startCommunication()
{
#ifndef NDEBUG
const auto tag = currentComm_->getTag();
WALBERLA_ASSERT_EQUAL(activeTags_.find(tag), activeTags_.end(),
"Another communication with the same MPI tag is currently in progress.");
activeTags_.insert(tag);
#endif
WALBERLA_CHECK_EQUAL(activeTags_.find(tag), activeTags_.end(),
"Another communication with the same MPI tag is currently in progress.");
activeTags_.insert(tag);
WALBERLA_ASSERT( ! communicationRunning_ );
WALBERLA_CHECK( ! communicationRunning_ );
currentComm_->scheduleReceives( recvInfos_ );
communicationRunning_ = true;
......@@ -334,7 +376,7 @@ void BufferSystem::startCommunication()
//**********************************************************************************************************************
void BufferSystem::endCommunication()
{
WALBERLA_ASSERT( communicationRunning_ );
WALBERLA_CHECK( communicationRunning_ );
currentComm_->waitForSends();
// Clear send buffers
......@@ -355,9 +397,7 @@ void BufferSystem::endCommunication()
communicationRunning_ = false;
#ifndef NDEBUG
activeTags_.erase( activeTags_.find( currentComm_->getTag() ) );
#endif
}
......
......@@ -115,6 +115,8 @@ public:
/*!\name Constructors */
//@{
explicit BufferSystem( const MPI_Comm & communicator, int tag = 0 );
BufferSystem( const BufferSystem & other );
BufferSystem & operator=( const BufferSystem & other );
~BufferSystem() {}
//@}
//*******************************************************************************************************************
......@@ -235,11 +237,9 @@ protected:
};
std::map<MPIRank, SendInfo> sendInfos_;
#ifndef NDEBUG
//stores tags of running communications in debug mode to ensure that
//each concurrently running communication uses different tags
static std::set<int> activeTags_;
#endif
};
......
......@@ -90,7 +90,9 @@ namespace internal {
virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos ) = 0;
virtual int getTag() const { return tag_; }
virtual int getTag() const { return tag_; }
virtual MPI_Comm getCommunicator() const { return communicator_; }
protected:
MPI_Comm communicator_;
......@@ -99,7 +101,6 @@ namespace internal {
class KnownSizeCommunication : public AbstractCommunication
{
public:
......@@ -126,7 +127,6 @@ namespace internal {
class UnknownSizeCommunication : public AbstractCommunication
{
public:
......@@ -138,7 +138,7 @@ namespace internal {
virtual void send( MPIRank receiver, const SendBuffer & sendBuffer );
virtual void waitForSends();
virtual void scheduleReceives ( std::map<MPIRank, ReceiveInfo> & recvInfos );
virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos );
/// size field of recvInfos can be invalid, is filled in with the actual message size
virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos );
......@@ -156,6 +156,7 @@ namespace internal {
};
class NoMPICommunication : public AbstractCommunication
{
public:
......@@ -167,7 +168,7 @@ namespace internal {
virtual void send( MPIRank receiver, const SendBuffer & sendBuffer );
virtual void waitForSends();
virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos );
virtual void scheduleReceives( std::map<MPIRank, ReceiveInfo> & recvInfos );
/// size field of recvInfos can be invalid, is filled in with the actual message size
virtual MPIRank waitForNextReceive( std::map<MPIRank, ReceiveInfo> & recvInfos );
......
......@@ -39,6 +39,11 @@ namespace mpi {
template<>
std::vector< std::string > gatherv( const std::vector< std::string > & values, int recvRank, MPI_Comm comm )
{
WALBERLA_NON_MPI_SECTION()
{
return std::vector< std::string >( values );
}
mpi::SendBuffer sb;
mpi::RecvBuffer rb;
sb << values;
......
......@@ -198,6 +198,7 @@ inline int MPI_Cart_create( MPI_Comm, int, int*, int*, int, MPI_Comm* ) { WALBER
inline int MPI_Dims_create( int, int, int* ) { WALBERLA_MPI_FUNCTION_ERROR }
inline int MPI_Cart_coords( MPI_Comm, int, int, int* ) { WALBERLA_MPI_FUNCTION_ERROR }
inline int MPI_Cart_rank ( MPI_Comm, int*, int* ) { WALBERLA_MPI_FUNCTION_ERROR }
inline int MPI_Cart_shift ( MPI_Comm, int, int, int*, int*) { WALBERLA_MPI_FUNCTION_ERROR }
inline int MPI_Irecv( void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request* ) { WALBERLA_MPI_FUNCTION_ERROR }
inline int MPI_Isend( void*, int, MPI_Datatype, int, int, MPI_Comm, MPI_Request* ) { WALBERLA_MPI_FUNCTION_ERROR }
......
......@@ -148,7 +148,7 @@ namespace field {
//check that mask contains only registered bits
WALBERLA_ASSERT( ! ( mask & (~ data_->usedMask) ));
for( auto i = this->beginInner(); i != this->end(); ++i)
for( auto i = this->begin(); i != this->end(); ++i)
if(*i & mask )
cv.push_back(Cell(i.x(),i.y(), i.z() ));
}
......
......@@ -535,7 +535,7 @@ namespace field {
return ForwardFieldIterator<const T,fSize_>( this,
ci.xMin(),ci.yMin(), ci.zMin(), f,
ci.xSize(), ci.ySize(), ci.zSize(), f+1 );
ci.xSize(), ci.ySize(), ci.zSize(), uint_c( f + cell_idx_t(1) ) );
}
//*******************************************************************************************************************
......@@ -550,7 +550,7 @@ namespace field {
return ForwardFieldIterator<T,fSize_>( this,
ci.xMin(),ci.yMin(), ci.zMin(), f,
ci.xSize(), ci.ySize(), ci.zSize(), uint_c(f+1) );
ci.xSize(), ci.ySize(), ci.zSize(), uint_c( f + cell_idx_t(1) ) );
}
......@@ -567,7 +567,7 @@ namespace field {
return ForwardFieldIterator<const T,fSize_>( this,
ci.xMin(),ci.yMin(), ci.zMin(), f,
ci.xSize(), ci.ySize(), ci.zSize(), f+1 );
ci.xSize(), ci.ySize(), ci.zSize(), uint_c( f + cell_idx_t(1) ) );
}
......@@ -616,7 +616,7 @@ namespace field {
return ForwardFieldIterator<T,fSize_>( this,
ci.xMin(),ci.yMin(), ci.zMin(), f,
ci.xSize(), ci.ySize(), ci.zSize(), f+1 );
ci.xSize(), ci.ySize(), ci.zSize(), uint_c( f + cell_idx_t(1) ) );
}
......@@ -633,7 +633,7 @@ namespace field {
return ForwardFieldIterator<const T,fSize_>( this,
ci.xMin(),ci.yMin(), ci.zMin(), f,
ci.xSize(), ci.ySize(), ci.zSize(), uint_c(f+1) );
ci.xSize(), ci.ySize(), ci.zSize(), uint_c( f + cell_idx_t(1) ) );
}
//*******************************************************************************************************************
......
......@@ -62,7 +62,7 @@ public:
private:
enum Mode { MIN, MAX, AVG, LAST };
real_t getTiming( Mode mode ) const;
double getTiming( Mode mode ) const;
PerformanceEvaluation<FlagField_T> performanceEvaluation_;
uint_t interval_;
......@@ -85,7 +85,7 @@ PerformanceLogger<FlagField_T>::PerformanceLogger( const shared_ptr< StructuredB
template< typename FlagField_T >
real_t PerformanceLogger<FlagField_T>::getTiming( Mode mode ) const
double PerformanceLogger<FlagField_T>::getTiming( Mode mode ) const
{
switch( mode )
{
......@@ -99,7 +99,7 @@ real_t PerformanceLogger<FlagField_T>::getTiming( Mode mode ) const
return timer_.last();
default:
WALBERLA_ASSERT( false );
return std::numeric_limits< real_t >::signaling_NaN();
return std::numeric_limits< double >::signaling_NaN();
}
}
......
......@@ -42,6 +42,13 @@
namespace walberla {
namespace lbm {
template< typename LM_AdvDiff, typename VelocityAdapter_T, typename FlagField_T, typename VectorField_T, class Enable = void >
class AdvectionDiffusionSweep
{
static_assert(never_true<LM_AdvDiff>::value, "Instantiating 'lbm::AdvectionDiffusionSweep' failed");
};
template< typename LM_AdvDiff, typename VelocityAdapter_T, typename FlagField_T, typename VectorField_T >
class AdvectionDiffusionSweep< LM_AdvDiff, VelocityAdapter_T, FlagField_T, VectorField_T,
......
......@@ -325,6 +325,38 @@ void selfSend()
}
}
void copyTest()
{
int rank = MPIManager::instance()->worldRank();
BufferSystem bs1( MPI_COMM_WORLD, 3 );
{
BufferSystem bs2( MPI_COMM_WORLD, 7 );
bs2.sendBuffer(rank) << int(42);
bs2.setReceiverInfoFromSendBufferState( true, false );
bs2.sendAll();
for ( auto i = bs2.begin(); i != bs2.end(); ++i )
{
int messageContent;
i.buffer() >> messageContent;
WALBERLA_CHECK_EQUAL(messageContent, 42);
}
bs1 = bs2;
}
bs1.sendBuffer(rank) << int(42);
bs1.sendAll();
for ( auto i = bs1.begin(); i != bs1.end(); ++i )
{
int messageContent;
i.buffer() >> messageContent;
WALBERLA_CHECK_EQUAL(messageContent, 42);
}
}
int main(int argc, char**argv)
{
......@@ -340,21 +372,23 @@ int main(int argc, char**argv)
return 1;
}
WALBERLA_ROOT_SECTION() { WALBERLA_LOG_INFO("Testing Symmetric Communication..." ); }
WALBERLA_LOG_INFO_ON_ROOT("Testing Symmetric Communication...");
symmetricCommunication();
WALBERLA_ROOT_SECTION() { WALBERLA_LOG_INFO("Testing Asymmetric Communication..."); }
WALBERLA_LOG_INFO_ON_ROOT("Testing Asymmetric Communication...");
asymmetricCommunication();
WALBERLA_ROOT_SECTION() { WALBERLA_LOG_INFO("Testing time-varying Communication..."); }
WALBERLA_LOG_INFO_ON_ROOT("Testing time-varying Communication...");
timeVaryingCommunication();
WALBERLA_ROOT_SECTION() { WALBERLA_LOG_INFO("Testing Gather Operation..."); }
WALBERLA_LOG_INFO_ON_ROOT("Testing Gather Operation...");
gatherUsingAsymmetricCommunication();
WALBERLA_ROOT_SECTION() { WALBERLA_LOG_INFO("Testing selfsend..."); }
WALBERLA_LOG_INFO_ON_ROOT("Testing self-send...");
selfSend();
WALBERLA_LOG_INFO_ON_ROOT("Testing Buffer System copy...");
copyTest();
return EXIT_SUCCESS;
}
......@@ -29,18 +29,17 @@
#include "blockforest/Initialization.h"
#include "blockforest/python/Exports.h"
#include "field/python/Exports.h"
#include "field/iterators/IteratorMacros.h"
#include "python_coupling/Manager.h"
#include "python_coupling/PythonCallback.h"
#include "python_coupling/DictWrapper.h"
#include "stencil/D2Q9.h"
#include <boost/mpl/vector.hpp>
using namespace walberla;
int main( int argc, char ** argv )
{
debug::enterTestMode();
......@@ -86,6 +85,7 @@ int main( int argc, char ** argv )
cb.data().exposeValue("blocks", blocks);
cb();
// check for equivalence
for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt )
{
......@@ -95,20 +95,24 @@ int main( int argc, char ** argv )
auto vec3Field = blockIt->getData<GhostLayerField<Vector3<int>,1 > >( vec3FieldID );
{
forAllCells2(scaIt, sca2Field, vecIt, vec2Field) {
WALBERLA_ASSERT_EQUAL(scaIt[0], (*vecIt)[0]);
WALBERLA_ASSERT_EQUAL(scaIt[1], (*vecIt)[1]);
}
}
{
forAllCells2(scaIt, sca3Field, vecIt, vec3Field) {
WALBERLA_ASSERT_EQUAL(scaIt[0], (*vecIt)[0]);
WALBERLA_ASSERT_EQUAL(scaIt[1], (*vecIt)[1]);
WALBERLA_ASSERT_EQUAL(scaIt[2], (*vecIt)[2]);
}
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)
{
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] );
}
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)
{
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] );
}
}
}
return 0;
}