Skip to content
Snippets Groups Projects
Commit 10d7138a authored by Christoph Rettinger's avatar Christoph Rettinger
Browse files

Added new communication pack info and test case to field module

parent 2a822a7c
Branches
Tags
No related merge requests found
//======================================================================================================================
//
// 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 UniformPullReductionPackInfo.h
//! \ingroup field
//! \author Tobias Schruff <schruff@iww.rwth-aachen.de>
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//
//======================================================================================================================
#pragma once
#include "communication/UniformPackInfo.h"
#include "core/debug/Debug.h"
#include "field/GhostLayerField.h"
#include "stencil/Directions.h"
namespace walberla {
namespace field {
namespace communication {
/**
* Data packing/unpacking for ghost layer based communication of a single walberla::field::Field
*
* \ingroup comm
*
* template ReduceOperation is e.g. std::plus
*
* This pack info is used to apply a given reduce operation (e.g. +) to the values in the interior of a ghost layer field
* together with the values coming from the sender's ghost layer.
*/
template< template<typename> class ReduceOperation, typename GhostLayerField_T >
class UniformPullReductionPackInfo : public walberla::communication::UniformPackInfo
{
public:
typedef typename GhostLayerField_T::value_type T;
UniformPullReductionPackInfo( const BlockDataID & bdID ) : bdID_( bdID ), communicateAllGhostLayers_( true ),
numberOfGhostLayers_( 0 ) {}
UniformPullReductionPackInfo( const BlockDataID & bdID, const uint_t numberOfGhostLayers ) : bdID_( bdID ),
communicateAllGhostLayers_( false ), numberOfGhostLayers_( numberOfGhostLayers ) {}
virtual ~UniformPullReductionPackInfo() {}
bool constantDataExchange() const { return mpi::BufferSizeTrait<T>::constantSize; }
bool threadsafeReceiving() const { return true; }
void unpackData(IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer);
void communicateLocal(const IBlock * sender, IBlock * receiver, stencil::Direction dir);
protected:
void packDataImpl(const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer) const;
uint_t numberOfGhostLayersToCommunicate( const GhostLayerField_T * const field ) const;
const BlockDataID bdID_;
bool communicateAllGhostLayers_;
uint_t numberOfGhostLayers_;
ReduceOperation<T> op_;
};
template< template<typename> class ReduceOperation, typename GhostLayerField_T >
void UniformPullReductionPackInfo<ReduceOperation, GhostLayerField_T>::unpackData( IBlock * receiver, stencil::Direction dir, mpi::RecvBuffer & buffer )
{
GhostLayerField_T * f = receiver->getData< GhostLayerField_T >( bdID_ );
WALBERLA_ASSERT_NOT_NULLPTR(f);
cell_idx_t nrOfGhostLayers = cell_idx_c( numberOfGhostLayersToCommunicate( f ) );
T buf( 0 );
for( auto i = f->beginSliceBeforeGhostLayer( dir, nrOfGhostLayers ); i != f->end(); ++i ) {
buffer >> buf;
*i = op_( *i, buf );
}
}
template< template<typename> class ReduceOperation, typename GhostLayerField_T>
void UniformPullReductionPackInfo<ReduceOperation, GhostLayerField_T>::communicateLocal( const IBlock * sender, IBlock * receiver, stencil::Direction dir )
{
const GhostLayerField_T * sf = sender ->getData< GhostLayerField_T >( bdID_ );
GhostLayerField_T * rf = receiver->getData< GhostLayerField_T >( bdID_ );
WALBERLA_ASSERT_EQUAL(sf->xSize(), rf->xSize());
WALBERLA_ASSERT_EQUAL(sf->ySize(), rf->ySize());
WALBERLA_ASSERT_EQUAL(sf->zSize(), rf->zSize());
uint_t nrOfGhostLayers = numberOfGhostLayersToCommunicate( sf );
auto srcIter = sf->beginGhostLayerOnly( nrOfGhostLayers, dir );
auto dstIter = rf->beginSliceBeforeGhostLayer( stencil::inverseDir[dir], cell_idx_c( nrOfGhostLayers ) );
while( srcIter != sf->end() ) {
*dstIter = op_( *srcIter, *dstIter );
++srcIter;
++dstIter;
}
WALBERLA_ASSERT(srcIter == sf->end() && dstIter == rf->end());
}
template< template<typename> class ReduceOperation, typename GhostLayerField_T>
void UniformPullReductionPackInfo<ReduceOperation, GhostLayerField_T>::packDataImpl( const IBlock * sender, stencil::Direction dir, mpi::SendBuffer & outBuffer ) const
{
const GhostLayerField_T * f = sender->getData< GhostLayerField_T >( bdID_ );
WALBERLA_ASSERT_NOT_NULLPTR(f);
uint_t nrOfGhostLayers = numberOfGhostLayersToCommunicate( f );
for( auto i = f->beginGhostLayerOnly( nrOfGhostLayers, dir ); i != f->end(); ++i )
outBuffer << *i;
}
template< template<typename> class ReduceOperation, typename GhostLayerField_T>
uint_t UniformPullReductionPackInfo<ReduceOperation, GhostLayerField_T>::numberOfGhostLayersToCommunicate( const GhostLayerField_T * const field ) const
{
if( communicateAllGhostLayers_ )
{
return field->nrOfGhostLayers();
}
else
{
WALBERLA_ASSERT_LESS_EQUAL( numberOfGhostLayers_, field->nrOfGhostLayers() );
return numberOfGhostLayers_;
}
}
} // namespace communication
} // namespace field
} // namespace walberla
...@@ -27,3 +27,4 @@ ...@@ -27,3 +27,4 @@
#include "MPIDatatypes.h" #include "MPIDatatypes.h"
#include "ReducePackInfo.h" #include "ReducePackInfo.h"
#include "UniformMPIDatatypeInfo.h" #include "UniformMPIDatatypeInfo.h"
#include "UniformPullReductionPackInfo.h"
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
//! \file FieldPackInfoTest.cpp //! \file FieldPackInfoTest.cpp
//! \ingroup field //! \ingroup field
//! \author Martin Bauer <martin.bauer@fau.de> //! \author Martin Bauer <martin.bauer@fau.de>
//! \author Christoph Rettinger <christoph.rettinger@fau.de>
//! \brief Tests if a Field is correctly packed into buffers //! \brief Tests if a Field is correctly packed into buffers
// //
//====================================================================================================================== //======================================================================================================================
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
#include "field/AddToStorage.h" #include "field/AddToStorage.h"
#include "field/GhostLayerField.h" #include "field/GhostLayerField.h"
#include "field/communication/PackInfo.h" #include "field/communication/PackInfo.h"
#include "field/communication/UniformPullReductionPackInfo.h"
#include "blockforest/Initialization.h" #include "blockforest/Initialization.h"
...@@ -85,9 +87,60 @@ void testScalarField( IBlock * block, BlockDataID fieldId ) ...@@ -85,9 +87,60 @@ void testScalarField( IBlock * block, BlockDataID fieldId )
WALBERLA_CHECK_EQUAL ( field(1,1,+2), 4 ); WALBERLA_CHECK_EQUAL ( field(1,1,+2), 4 );
} }
void testScalarFieldPullReduction( IBlock * block, BlockDataID fieldId )
{
GhostLayerField<int,1> & field = *(block->getData<GhostLayerField<int,1> > (fieldId));
field.setWithGhostLayer( 0 );
WALBERLA_CHECK_EQUAL(field.xSize(), 2);
WALBERLA_CHECK_EQUAL(field.ySize(), 2);
WALBERLA_CHECK_EQUAL(field.zSize(), 2);
// initialize the bottom ghost layer cells
field(0,0,-1) = 1;
field(0,1,-1) = 2;
field(1,0,-1) = 3;
field(1,1,-1) = 4;
// initialize the top interior cells
field(0,0,1) = 1;
field(0,1,1) = 1;
field(1,0,1) = 1;
field(1,1,1) = 1;
// communicate periodic from bottom to top with uniform pull scheme
field::communication::UniformPullReductionPackInfo<std::plus, GhostLayerField<int,1> > pi1 (fieldId);
pi1.communicateLocal( block, block, stencil::B );
// check values in top ghost layer
WALBERLA_CHECK_EQUAL ( field(0,0,2), 0 );
WALBERLA_CHECK_EQUAL ( field(0,1,2), 0 );
WALBERLA_CHECK_EQUAL ( field(1,0,2), 0 );
WALBERLA_CHECK_EQUAL ( field(1,1,2), 0 );
// check values in top interior cells
WALBERLA_CHECK_EQUAL ( field(0,0,1), 2 );
WALBERLA_CHECK_EQUAL ( field(0,1,1), 3 );
WALBERLA_CHECK_EQUAL ( field(1,0,1), 4 );
WALBERLA_CHECK_EQUAL ( field(1,1,1), 5 );
// communicate periodic from top to bottom with standard form to sync ghost layers
field::communication::PackInfo< GhostLayerField<int,1> > pi2 (fieldId);
pi2.communicateLocal( block, block, stencil::T );
// check values in bottom ghost layer
WALBERLA_CHECK_EQUAL ( field(0,0,-1), 2 );
WALBERLA_CHECK_EQUAL ( field(0,1,-1), 3 );
WALBERLA_CHECK_EQUAL ( field(1,0,-1), 4 );
WALBERLA_CHECK_EQUAL ( field(1,1,-1), 5 );
// check values in top interior cells
WALBERLA_CHECK_EQUAL ( field(0,0,1), 2 );
WALBERLA_CHECK_EQUAL ( field(0,1,1), 3 );
WALBERLA_CHECK_EQUAL ( field(1,0,1), 4 );
WALBERLA_CHECK_EQUAL ( field(1,1,1), 5 );
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
...@@ -127,7 +180,8 @@ int main(int argc, char **argv) ...@@ -127,7 +180,8 @@ int main(int argc, char **argv)
for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) // block loop for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) // block loop
testScalarField( &(*blockIt), scalarFieldId ); testScalarField( &(*blockIt), scalarFieldId );
for( auto blockIt = blocks->begin(); blockIt != blocks->end(); ++blockIt ) // block loop
testScalarFieldPullReduction( &(*blockIt), scalarFieldId );
return 0; return 0;
} }
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment