1#ifndef DUNE_SPGRID_COMMUNICATION_HH
2#define DUNE_SPGRID_COMMUNICATION_HH
4#include <dune/common/hybridutilities.hh>
10#include <dune/grid/common/exceptions.hh>
13#include <dune/grid/spgrid/iterator.hh>
14#include <dune/grid/spgrid/messagebuffer.hh>
22 template<
class Comm >
23 struct SPCommunicationTraits
28 static Communication comm (
const C & )
33 static Communication defaultComm ()
35 return Communication();
41 struct SPCommunicationTraits< MPI_Comm >
45 static Communication comm (
const MPI_Comm &mpiComm )
47 return Communication( mpiComm );
50 static Communication defaultComm ()
52 return comm( MPI_COMM_WORLD );
64 static unsigned char counter = 0;
65 return int( counter++ ) + 1536;
75 template<
class Gr
id,
class DataHandle >
76 struct SPCommunication
80 typedef SPGridLevel< Grid > GridLevel;
81 typedef SPPartitionList< dimension > PartitionList;
83 typedef typename DataHandle::DataType DataType;
85 typedef typename GridLevel::CommInterface Interface;
88 typedef SPPackedMessageWriteBuffer< typename Grid::Communication > WriteBuffer;
89 typedef SPPackedMessageReadBuffer< typename Grid::Communication > ReadBuffer;
92 SPCommunication (
const GridLevel &gridLevel, DataHandle &dataHandle,
95 SPCommunication (
const SPCommunication & ) =
delete;
96 SPCommunication ( SPCommunication &&other );
98 ~SPCommunication () { wait(); }
100 bool ready ()
const {
return !( bool( interface_ )); }
105 bool pending ()
const {
return !ready(); }
107 const GridLevel &gridLevel_;
108 DataHandle &dataHandle_;
109 const Interface *interface_;
113 std::vector< WriteBuffer > writeBuffers_;
114 std::vector< ReadBuffer > readBuffers_;
122 template<
class Gr
id,
class DataHandle >
123 inline SPCommunication< Grid, DataHandle >
124 ::SPCommunication (
const GridLevel &gridLevel, DataHandle &dataHandle,
126 : gridLevel_( gridLevel ),
127 dataHandle_( dataHandle ),
128 interface_( &gridLevel.commInterface( iftype ) ),
130 tag_( __SPGrid::getCommTag() ),
133 for(
int codim = 0; codim <= dimension; ++codim )
134 fixedSize_ &= !dataHandle_.contains( dimension, codim ) || dataHandle_.fixedSize( dimension, codim );
136 const std::size_t numLinks = interface_->size();
137 readBuffers_.reserve( numLinks );
141 for(
typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
143 readBuffers_.emplace_back( gridLevel.grid().comm() );
144 std::size_t size = 0;
145 const PartitionList &partitionList = it->receiveList( dir );
146 Hybrid::forEach( std::make_integer_sequence< int, dimension+1 >(), [
this, &partitionList, &size ] (
auto codim ) {
147 typedef SPPartitionIterator< codim, const Grid > Iterator;
149 if( !dataHandle_.contains( dimension, codim ) )
152 const Iterator end( gridLevel_, partitionList,
typename Iterator::End() );
153 for( Iterator it( gridLevel_, partitionList,
typename Iterator::Begin() ); it != end; ++it )
154 size += dataHandle_.size( *it );
156 size *=
sizeof( DataType );
157 readBuffers_.back().receive( it->rank(), tag_, size );
161 writeBuffers_.reserve( numLinks );
162 for(
typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
164 writeBuffers_.emplace_back( gridLevel.grid().comm() );
165 const PartitionList &partitionList = it->sendList( dir );
166 Hybrid::forEach( std::make_integer_sequence< int, dimension+1 >(), [
this, &partitionList ] (
auto codim ) {
167 typedef SPPartitionIterator< codim, const Grid > Iterator;
169 if( !dataHandle_.contains( dimension, codim ) )
172 const bool fixedSize = dataHandle_.fixedSize( dimension, codim );
173 const Iterator end( gridLevel_, partitionList,
typename Iterator::End() );
174 for( Iterator it( gridLevel_, partitionList,
typename Iterator::Begin() ); it != end; ++it )
176 const auto &entity = *it;
178 writeBuffers_.back().write(
static_cast< int >( dataHandle_.size( entity ) ) );
180 const std::size_t posBeforeGather = writeBuffers_.back().position();
182 dataHandle_.gather( writeBuffers_.back(), entity );
184 const std::size_t posAfterGather = writeBuffers_.back().position();
185 const std::size_t sizeInBytes = dataHandle_.size( entity ) *
sizeof( DataType );
186 if( posAfterGather - posBeforeGather != sizeInBytes )
187 DUNE_THROW( GridError,
"Number of bytes written (" << (posAfterGather - posBeforeGather) <<
") does not coincide with reported size (" << sizeInBytes <<
")" );
191 writeBuffers_.back().send( it->rank(), tag_ );
196 template<
class Gr
id,
class DataHandle >
197 inline SPCommunication< Grid, DataHandle >::SPCommunication ( SPCommunication &&other )
198 : gridLevel_( other.gridLevel_ ),
199 dataHandle_( other.dataHandle_ ),
200 interface_( other.interface_ ),
203 fixedSize_( other.fixedSize_ ),
204 writeBuffers_(
std::move( other.writeBuffers_ ) ),
205 readBuffers_(
std::move( other.readBuffers_ ) )
207 other.interface_ =
nullptr;
211 template<
class Gr
id,
class DataHandle >
212 inline void SPCommunication< Grid, DataHandle >::wait ()
217 const std::size_t numLinks = interface_->size();
221 for( std::size_t i = 0; i < numLinks; ++i )
223 readBuffers_.emplace_back( gridLevel_.grid().comm() );
224 readBuffers_.back().receive( tag_ );
228 for( std::size_t i = 0; i < numLinks; ++i )
230 const typename std::vector< ReadBuffer >::iterator buffer = waitAny( readBuffers_ );
231 for(
typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
233 if( it->rank() == buffer->rank() )
235 const PartitionList &partitionList = it->receiveList( dir_ );
236 Hybrid::forEach( std::make_integer_sequence< int, dimension+1 >(), [
this, &partitionList, buffer ] (
auto codim ) {
237 typedef SPPartitionIterator< codim, const Grid > Iterator;
239 if( !dataHandle_.contains( dimension, codim ) )
242 const bool fixedSize = dataHandle_.fixedSize( dimension, codim );
243 const Iterator end( gridLevel_, partitionList,
typename Iterator::End() );
244 for( Iterator it( gridLevel_, partitionList,
typename Iterator::Begin() ); it != end; ++it )
246 const auto &entity = *it;
250 buffer->read( size );
252 size = dataHandle_.size( entity );
254 const std::size_t posBeforeGather = buffer->position();
256 dataHandle_.scatter( *buffer, entity, size );
258 const std::size_t posAfterGather = buffer->position();
259 const std::size_t sizeInBytes =
static_cast< std::size_t
>( size ) *
sizeof( DataType );
260 if( posAfterGather - posBeforeGather != sizeInBytes )
261 DUNE_THROW( GridError,
"Number of bytes read (" << (posAfterGather - posBeforeGather) <<
") does not coincide with reported size (" << sizeInBytes <<
")" );
269 readBuffers_.clear();
271 for(
typename std::vector< WriteBuffer >::iterator it = writeBuffers_.begin(); it != writeBuffers_.end(); ++it )
273 writeBuffers_.clear();
275 interface_ =
nullptr;
Specialization of Communication for MPI.
Definition: mpicommunication.hh:108
Collective communication interface and sequential default implementation.
Definition: communication.hh:100
static constexpr int dimension
The dimension of the grid.
Definition: grid.hh:387
Describes the parallel communication interface class for MessageBuffers and DataHandles.
Implements an utility class that provides collective communication methods for sequential programs.
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:268
Implements an utility class that provides MPI's collective communication methods.
Traits classes for mapping types onto MPI_Datatype.
Dune namespace.
Definition: alignedallocator.hh:13
std::size_t fixedSize
The number of data items per index if it is fixed, 0 otherwise.
Definition: variablesizecommunicator.hh:265
Definition of macros controlling symbol visibility at the ABI level.
#define DUNE_EXPORT
Export a symbol as part of the public ABI.
Definition: visibility.hh:20