Dune Core Modules (2.9.0)

communication.hh
1#ifndef DUNE_SPGRID_COMMUNICATION_HH
2#define DUNE_SPGRID_COMMUNICATION_HH
3
4#include <dune/common/hybridutilities.hh>
9
10#include <dune/grid/common/exceptions.hh>
12
13#include <dune/grid/spgrid/iterator.hh>
14#include <dune/grid/spgrid/messagebuffer.hh>
15
16namespace Dune
17{
18
19 // SPCommunicationTraits
20 // ---------------------
21
22 template< class Comm >
23 struct SPCommunicationTraits
24 {
25 typedef Dune::Communication< Comm > Communication;
26
27 template< class C >
28 static Communication comm ( const C & )
29 {
30 return defaultComm();
31 }
32
33 static Communication defaultComm ()
34 {
35 return Communication();
36 }
37 };
38
39#if HAVE_MPI
40 template<>
41 struct SPCommunicationTraits< MPI_Comm >
42 {
43 typedef Dune::Communication< MPI_Comm > Communication;
44
45 static Communication comm ( const MPI_Comm &mpiComm )
46 {
47 return Communication( mpiComm );
48 }
49
50 static Communication defaultComm ()
51 {
52 return comm( MPI_COMM_WORLD );
53 }
54 };
55#endif // #if HAVE_MPI
56
57
58
59 namespace __SPGrid
60 {
61
62 DUNE_EXPORT inline int getCommTag ()
63 {
64 static unsigned char counter = 0;
65 return int( counter++ ) + 1536;
66 }
67
68 } // namespace __SPGrid
69
70
71
72 // SPCommunication
73 // ---------------
74
75 template< class Grid, class DataHandle >
76 struct SPCommunication
77 {
78 static const int dimension = Grid::dimension;
79
80 typedef SPGridLevel< Grid > GridLevel;
81 typedef SPPartitionList< dimension > PartitionList;
82
83 typedef typename DataHandle::DataType DataType;
84
85 typedef typename GridLevel::CommInterface Interface;
86
87 private:
88 typedef SPPackedMessageWriteBuffer< typename Grid::Communication > WriteBuffer;
89 typedef SPPackedMessageReadBuffer< typename Grid::Communication > ReadBuffer;
90
91 public:
92 SPCommunication ( const GridLevel &gridLevel, DataHandle &dataHandle,
94
95 SPCommunication ( const SPCommunication & ) = delete;
96 SPCommunication ( SPCommunication &&other );
97
98 ~SPCommunication () { wait(); }
99
100 bool ready () const { return !( bool( interface_ )); }
101
102 void wait ();
103
104 [[deprecated]]
105 bool pending () const { return !ready(); }
106 private:
107 const GridLevel &gridLevel_;
108 DataHandle &dataHandle_;
109 const Interface *interface_;
111 int tag_;
112 bool fixedSize_;
113 std::vector< WriteBuffer > writeBuffers_;
114 std::vector< ReadBuffer > readBuffers_;
115 };
116
117
118
119 // Implementation of SPCommunication
120 // ---------------------------------
121
122 template< class Grid, 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 ) ),
129 dir_( dir ),
130 tag_( __SPGrid::getCommTag() ),
131 fixedSize_( true )
132 {
133 for( int codim = 0; codim <= dimension; ++codim )
134 fixedSize_ &= !dataHandle_.contains( dimension, codim ) || dataHandle_.fixedSize( dimension, codim );
135
136 const std::size_t numLinks = interface_->size();
137 readBuffers_.reserve( numLinks );
138
139 if( fixedSize_ )
140 {
141 for( typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
142 {
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;
148
149 if( !dataHandle_.contains( dimension, codim ) )
150 return;
151
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 );
155 } );
156 size *= sizeof( DataType );
157 readBuffers_.back().receive( it->rank(), tag_, size );
158 }
159 }
160
161 writeBuffers_.reserve( numLinks );
162 for( typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
163 {
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;
168
169 if( !dataHandle_.contains( dimension, codim ) )
170 return;
171
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 )
175 {
176 const auto &entity = *it;
177 if( !fixedSize )
178 writeBuffers_.back().write( static_cast< int >( dataHandle_.size( entity ) ) );
179#ifndef NDEBUG
180 const std::size_t posBeforeGather = writeBuffers_.back().position();
181#endif // #ifndef NDEBUG
182 dataHandle_.gather( writeBuffers_.back(), entity );
183#ifndef NDEBUG
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 << ")" );
188#endif // #ifndef NDEBUG
189 }
190 } );
191 writeBuffers_.back().send( it->rank(), tag_ );
192 }
193 }
194
195
196 template< class Grid, class DataHandle >
197 inline SPCommunication< Grid, DataHandle >::SPCommunication ( SPCommunication &&other )
198 : gridLevel_( other.gridLevel_ ),
199 dataHandle_( other.dataHandle_ ),
200 interface_( other.interface_ ),
201 dir_( other.dir_ ),
202 tag_( other.tag_ ),
203 fixedSize_( other.fixedSize_ ),
204 writeBuffers_( std::move( other.writeBuffers_ ) ),
205 readBuffers_( std::move( other.readBuffers_ ) )
206 {
207 other.interface_ = nullptr;
208 }
209
210
211 template< class Grid, class DataHandle >
212 inline void SPCommunication< Grid, DataHandle >::wait ()
213 {
214 if( ready() )
215 return;
216
217 const std::size_t numLinks = interface_->size();
218
219 if( !fixedSize_ )
220 {
221 for( std::size_t i = 0; i < numLinks; ++i )
222 {
223 readBuffers_.emplace_back( gridLevel_.grid().comm() );
224 readBuffers_.back().receive( tag_ );
225 }
226 }
227
228 for( std::size_t i = 0; i < numLinks; ++i )
229 {
230 const typename std::vector< ReadBuffer >::iterator buffer = waitAny( readBuffers_ );
231 for( typename Interface::Iterator it = interface_->begin(); it != interface_->end(); ++it )
232 {
233 if( it->rank() == buffer->rank() )
234 {
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;
238
239 if( !dataHandle_.contains( dimension, codim ) )
240 return;
241
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 )
245 {
246 const auto &entity = *it;
247
248 int size;
249 if( !fixedSize )
250 buffer->read( size );
251 else
252 size = dataHandle_.size( entity );
253#ifndef NDEBUG
254 const std::size_t posBeforeGather = buffer->position();
255#endif // #ifndef NDEBUG
256 dataHandle_.scatter( *buffer, entity, size );
257#ifndef NDEBUG
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 << ")" );
262#endif // #ifndef NDEBUG
263 }
264 } );
265 break;
266 }
267 }
268 }
269 readBuffers_.clear();
270
271 for( typename std::vector< WriteBuffer >::iterator it = writeBuffers_.begin(); it != writeBuffers_.end(); ++it )
272 it->wait();
273 writeBuffers_.clear();
274
275 interface_ = nullptr;
276 }
277
278} // namespace Dune
279
280#endif // #ifndef DUNE_SPGRID_COMMUNICATION_HH
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
CommunicationDirection
Define a type for communication direction parameter.
Definition: gridenums.hh:170
InterfaceType
Parameter to be used for the communication functions.
Definition: gridenums.hh:86
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
STL namespace.
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
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Jul 15, 22:36, 2024)