1#ifndef DUNE_FEM_CACHED_COMMUNICATION_MANAGER_HH
2#define DUNE_FEM_CACHED_COMMUNICATION_MANAGER_HH
9#include <unordered_map>
10#include <unordered_set>
23#include <dune/grid/utility/entitycommhelper.hh>
27#include <dune/alugrid/3d/alu3dinclude.hh>
31#include <dune/fem/common/hybrid.hh>
32#include <dune/fem/storage/singletonlist.hh>
33#include <dune/fem/space/common/commoperations.hh>
34#include <dune/fem/space/common/commindexmap.hh>
35#include <dune/fem/misc/functor.hh>
36#include <dune/fem/misc/mpimanager.hh>
37#include <dune/fem/misc/capabilities.hh>
48 template<
class DiscreteFunctionSpace >
49 class PetscDiscreteFunction;
51 class IsDiscreteFunction;
69 template<
class BlockMapper >
75 typedef BlockMapper BlockMapperType;
79 typedef CommunicationIndexMap IndexMapType;
82 typedef std::vector< IndexMapType > IndexMapVectorType;
85 typedef std :: set< int > LinkStorageType;
88 typedef ALU3DSPACE ObjectStream ObjectStreamType;
91 typedef ALU3DSPACE MpAccessLocal MPAccessInterfaceType;
93 typedef ALU3DSPACE MpAccessMPI MPAccessImplType;
96 typedef std :: vector< ObjectStreamType > ObjectStreamVectorType;
102 LinkStorageType linkStorage_;
104 IndexMapVectorType recvIndexMap_;
105 IndexMapVectorType sendIndexMap_;
108 std::unique_ptr< MPAccessInterfaceType > mpAccess_;
111 double exchangeTime_;
118 int nonBlockingObjects_ ;
121 template<
class Communication,
class LinkStorage,
129 class NonBlockingCommunication
131 typedef DependencyCache < BlockMapper > DependencyCacheType;
134 typedef MPAccessInterfaceType :: NonBlockingExchange NonBlockingExchange;
136 template <
class DiscreteFunction>
137 class Pack :
public NonBlockingExchange :: DataHandleIF
140 NonBlockingCommunication& commObj_;
141 const DiscreteFunction& discreteFunction_;
144 Pack( NonBlockingCommunication& commObj,
const DiscreteFunction& df )
145 : commObj_( commObj ), discreteFunction_( df )
148 void pack(
const int link, ObjectStreamType& buffer )
150 commObj_.pack( link, buffer, discreteFunction_ );
153 void unpack(
const int link, ObjectStreamType& buffer )
155 DUNE_THROW(InvalidStateException,
"Pack::unpack should not be called!");
159 template <
class DiscreteFunction,
class Operation>
160 class Unpack :
public NonBlockingExchange :: DataHandleIF
163 NonBlockingCommunication& commObj_;
164 DiscreteFunction& discreteFunction_;
167 const Operation operation_;
170 Unpack( NonBlockingCommunication& commObj, DiscreteFunction& df )
171 : commObj_( commObj ), discreteFunction_( df ), operation_()
174 void pack(
const int link, ObjectStreamType& buffer )
176 DUNE_THROW(InvalidStateException,
"Unpack::pack should not be called!");
179 void unpack(
const int link, ObjectStreamType& buffer )
181 commObj_.unpack( link, buffer, discreteFunction_, operation_ );
185 typedef int NonBlockingExchange;
189 static const int initialTagCounter = 665 ;
195 static int16_t tagCounter = initialTagCounter ;
202 int16_t& tagCounter = getMTagRef() ;
209 tagCounter = initialTagCounter ;
212 return int(tagCounter);
216 template <
class Space>
217 NonBlockingCommunication(
const Space& space,
218 DependencyCacheType& dependencyCache )
219 : dependencyCache_( dependencyCache ),
220 nonBlockingExchange_(),
222 exchangeTime_( 0.0 ),
223 mySize_( space.gridPart().comm().
size() )
226 dependencyCache_.rebuild( space );
229 dependencyCache_.attachComm();
233 NonBlockingCommunication(
const NonBlockingCommunication& other )
234 : dependencyCache_( other.dependencyCache_ ),
235 nonBlockingExchange_(),
237 exchangeTime_( 0.0 ),
238 mySize_( other.mySize_ )
241 dependencyCache_.attachComm();
244 ~NonBlockingCommunication()
247 assert( ! nonBlockingExchange_ );
249 dependencyCache_.detachComm() ;
253 template <
class DiscreteFunction,
class Comm >
254 static bool skip(
const DiscreteFunction&,
const Comm& comm )
256 return comm.size() <= 1;
260 template <
class DiscreteFunctionSpace,
class Comm>
261 static bool skip(
const PetscDiscreteFunction< DiscreteFunctionSpace >&,
const Comm& )
266 template <
class DiscreteFunctionSpace >
267 void send(
const PetscDiscreteFunction< DiscreteFunctionSpace >& discreteFunction )
272 template <
class DiscreteFunction >
273 void send(
const DiscreteFunction& discreteFunction )
276 assert( ! nonBlockingExchange_ );
279 if( mySize_ <= 1 )
return;
285 const int nLinks = dependencyCache_.nlinks();
288 buffer_.resize( nLinks );
292 nonBlockingExchange_.reset( dependencyCache_.mpAccess().nonBlockingExchange( getMessageTag() ) );
295 Pack< DiscreteFunction > packData( *
this, discreteFunction );
298 nonBlockingExchange_->send( buffer_, packData );
301 for(
int link = 0; link < nLinks; ++link )
302 pack( link, buffer_[ link ], discreteFunction );
306 exchangeTime_ = sendTimer.
elapsed();
310 template <
class DiscreteFunctionSpace,
class Operation >
311 double receive( PetscDiscreteFunction< DiscreteFunctionSpace >& discreteFunction,
312 const Operation& operation )
318 discreteFunction.dofVector().communicateNow( operation );
324 template <
class DiscreteFunction,
class Operation >
325 double receive( DiscreteFunction& discreteFunction,
const Operation& operation )
328 if( mySize_ <= 1 )
return 0.0;
335 Unpack< DiscreteFunction, Operation > unpackData( *
this, discreteFunction );
338 nonBlockingExchange_->receive( unpackData );
341 buffer_ = dependencyCache_.mpAccess().exchange( buffer_ );
344 const int nLinks = buffer_.size();
347 for(
int link = 0; link < nLinks; ++link )
348 unpack( link, buffer_[ link ], discreteFunction, operation );
352 exchangeTime_ += recvTimer.
elapsed();
356 nonBlockingExchange_.reset();
358 return exchangeTime_;
362 template <
class DiscreteFunction >
363 double receive( DiscreteFunction& discreteFunction )
366 typedef typename DiscreteFunction :: DiscreteFunctionSpaceType
367 :: template CommDataHandle< DiscreteFunction > :: OperationType DefaultOperationType;
368 DefaultOperationType operation;
369 return receive( discreteFunction, operation );
373 template <
class DiscreteFunction>
374 void pack(
const int link, ObjectStreamType& buffer,
const DiscreteFunction& discreteFunction )
379 dependencyCache_.writeBuffer( link, buffer, discreteFunction );
382 template <
class DiscreteFunction,
class Operation>
383 void unpack(
const int link, ObjectStreamType& buffer,
384 DiscreteFunction& discreteFunction,
const Operation& operation )
387 dependencyCache_.readBuffer( link, buffer, discreteFunction, operation );
391 DependencyCacheType& dependencyCache_;
392 std::unique_ptr< NonBlockingExchange > nonBlockingExchange_ ;
393 ObjectStreamVectorType buffer_;
394 double exchangeTime_ ;
399 typedef NonBlockingCommunication NonBlockingCommunicationType;
402 template <
class Space>
403 NonBlockingCommunicationType nonBlockingCommunication(
const Space& space )
406 return NonBlockingCommunicationType( space, *
this );
414 : interface_( interface ),
417 recvIndexMap_( nProcs ),
418 sendIndexMap_( nProcs ),
420 exchangeTime_( 0.0 ),
423 nonBlockingObjects_( 0 )
427 template <
class Communication>
428 void init(
const Communication& comm )
432 mpAccess_.reset(
new MPAccessImplType( comm ) );
437 DependencyCache(
const DependencyCache & ) =
delete;
452 double buildTime()
const
458 double exchangeTime()
const
460 return exchangeTime_;
466 ++nonBlockingObjects_;
472 --nonBlockingObjects_;
473 assert( nonBlockingObjects_ >= 0 );
476 bool noOpenCommunications()
const
483 template <
class Space >
484 inline void buildMaps(
const Space& space );
487 inline void checkConsistency();
489 template<
class Space,
class Comm,
class LS,
class IMV, InterfaceType CI >
490 inline void buildMaps(
const Space& space, LinkBuilder< Comm, LS, IMV, CI > &handle );
494 inline int dest(
const int link )
const
496 return mpAccess().dest()[ link ];
500 inline int nlinks()
const
502 return mpAccess().nlinks();
508 template <
class Space>
509 inline void rebuild(
const Space& space )
511 const auto& comm = space.gridPart().comm();
512 const int spcSequence = space.sequence();
515 if( comm.size() <= 1 )
return;
518 assert( noOpenCommunications() );
522 int willRebuild = (sequence_ != spcSequence) ? 1 : 0;
523 const int myRebuild = willRebuild;
526 comm.broadcast( &willRebuild, 1 , 0);
528 assert( willRebuild == myRebuild );
532 if( sequence_ != spcSequence )
540 sequence_ = spcSequence;
543 buildTime_ = buildTime.
elapsed();
548 template<
class Space,
class DiscreteFunction,
class Operation >
549 inline void exchange(
const Space& space, DiscreteFunction &discreteFunction,
const Operation& operation );
552 template<
class DiscreteFunction >
553 inline void writeBuffer( ObjectStreamVectorType &osv,
const DiscreteFunction &discreteFunction )
const;
556 template<
class DiscreteFunctionType,
class Operation >
557 inline void readBuffer( ObjectStreamVectorType &osv,
559 const Operation& operation )
const;
562 inline MPAccessInterfaceType &mpAccess()
569 inline const MPAccessInterfaceType &mpAccess()
const
577 template<
class DiscreteFunctionSpace >
578 inline void writeBuffer(
const int link,
579 ObjectStreamType &str,
580 const PetscDiscreteFunction< DiscreteFunctionSpace > &discreteFunction )
const
582 DUNE_THROW(NotImplemented,
"writeBuffer not implemented for PetscDiscteteFunction" );
587 template<
class Data >
588 inline void writeBuffer(
const int link,
589 ObjectStreamType &str,
590 const Data &data )
const
592 const auto &indexMap = sendIndexMap_[ dest( link ) ];
593 const int size = indexMap.size();
594 typedef typename Data :: DofType DofType;
597 if constexpr ( std::is_base_of< IsDiscreteFunction, Data >::value )
599 assert( sequence_ == data.space().sequence() );
601 typename Data::DiscreteFunctionSpaceType::LocalBlockIndices localBlockIndices;
602 str.reserve(
size * Hybrid::size( localBlockIndices ) *
sizeof( DofType ) );
603 for(
int i = 0; i <
size; ++i )
605 const auto &block = data.dofVector()[ indexMap[ i ] ];
606 Hybrid::forEach( localBlockIndices, [ &str, &block ] (
auto &&k ) { str.writeUnchecked( block[ k ] ); } );
611 if constexpr ( std::is_base_of< IsBlockVector, Data > :: value )
613 static const int blockSize = Data::blockSize;
614 str.reserve(
size * blockSize *
sizeof( DofType ) );
615 for(
int i = 0; i <
size; ++i )
617 const auto &block = data[ indexMap[ i ] ];
618 for(
int k=0; k<blockSize; ++k )
619 str.writeUnchecked( block[ k ] );
626 template<
class DiscreteFunctionSpace,
class Operation >
627 inline void readBuffer(
const int link,
628 ObjectStreamType &str,
629 PetscDiscreteFunction< DiscreteFunctionSpace > &discreteFunction,
630 const Operation& )
const
632 DUNE_THROW(NotImplemented,
"readBuffer not implemented for PetscDiscteteFunction" );
637 template<
class Data,
class Operation >
638 inline void readBuffer(
const int link,
639 ObjectStreamType &str,
641 const Operation& operation )
const
643 static_assert( ! std::is_pointer< Operation > :: value,
644 "DependencyCache::readBuffer: Operation needs to be a reference!");
647 const auto &indexMap = recvIndexMap_[ dest( link ) ];
648 const int size = indexMap.size();
649 typedef typename Data :: DofType DofType;
652 if constexpr ( std::is_base_of< IsDiscreteFunction, Data >::value )
654 assert( sequence_ == data.space().sequence() );
657 typename Data::DiscreteFunctionSpaceType::LocalBlockIndices localBlockIndices;
658 assert(
static_cast< std::size_t
>(
size * Hybrid::size( localBlockIndices ) *
sizeof( DofType ) ) <=
static_cast< std::size_t
>( str.size() ) );
659 for(
int i = 0; i <
size; ++i )
661 auto &&block = data.dofVector()[ indexMap[ i ] ];
662 Hybrid::forEach( localBlockIndices, [ &str, &operation, &block ] (
auto &&k ) {
665 str.readUnchecked( value );
670 operation( value, block[ k ] );
676 if constexpr ( std::is_base_of< IsBlockVector, Data > :: value )
678 static const int blockSize = Data::blockSize;
679 assert(
static_cast< std::size_t
>(
size * blockSize *
sizeof( DofType ) ) <=
static_cast< std::size_t
>( str.size() ) );
680 for(
int i = 0; i <
size; ++i )
682 auto &&block = data[ indexMap[ i ] ];
683 for(
int k=0; k<blockSize; ++k )
687 str.readUnchecked( value );
692 operation( value, block[ k ] );
700 template<
class BlockMapper >
701 template<
class Communication,
class LinkStorage,
class IndexMapVector, InterfaceType CommInterface >
702 class DependencyCache< BlockMapper > :: LinkBuilder
703 :
public CommDataHandleIF
704 < LinkBuilder< Communication, LinkStorage, IndexMapVector, CommInterface >,
705 typename BlockMapper :: GlobalKeyType >
708 typedef Communication CommunicationType;
709 typedef BlockMapper BlockMapperType;
711 typedef typename BlockMapperType :: GlobalKeyType GlobalKeyType;
713 typedef LinkStorage LinkStorageType;
714 typedef IndexMapVector IndexMapVectorType;
716 typedef GlobalKeyType DataType;
719 const CommunicationType& comm_;
720 const BlockMapperType &blockMapper_;
722 const GlobalKeyType myRank_;
723 const GlobalKeyType mySize_;
725 LinkStorageType &linkStorage_;
727 IndexMapVectorType &sendIndexMap_;
728 IndexMapVectorType &recvIndexMap_;
730 typedef typename BlockMapper::GridPartType::GridType GridType;
731 static constexpr bool isMMesh = Capabilities::isMMesh<GridType>::v;
734 LinkBuilder(
const CommunicationType& comm,
735 const BlockMapperType& blockMapper,
736 LinkStorageType &linkStorage,
737 IndexMapVectorType &sendIdxMap,
738 IndexMapVectorType &recvIdxMap )
740 blockMapper_( blockMapper ),
741 myRank_( comm.rank() ),
742 mySize_( comm.
size() ),
743 linkStorage_( linkStorage ),
744 sendIndexMap_( sendIdxMap ),
745 recvIndexMap_( recvIdxMap )
749 void sendBackSendMaps()
752 MPAccessImplType mpAccess( comm_ );
755 mpAccess.removeLinkage();
757 mpAccess.insertRequestSymetric( linkStorage_ );
759 std::vector<int> dest = mpAccess.dest();
761 const int nlinks = mpAccess.nlinks();
764 ObjectStreamVectorType osv( nlinks );
766 const int codimensions = BlockMapper::GridPartType::dimension;
767 int hasHigherCodims = 0;
768 for(
int c=1; c<=codimensions; ++c )
769 hasHigherCodims +=
int(blockMapper_.contains( c ));
773 if( hasHigherCodims > 0 )
775 typedef typename IndexMapVectorType::value_type::IndexType IndexType;
776 for(
int link=0; link<nlinks; ++link)
778 std::unordered_map< IndexType, std::unordered_set<IndexType> > uniqueRecvIndicesForSendIndex;
779 auto& sendMap = sendIndexMap_[ dest[link] ];
780 auto& recvMap = recvIndexMap_[ dest[link] ];
781 assert( sendMap.size() == recvMap.size() );
783 const size_t size = sendMap.size();
784 for(
size_t i=0; i<
size; ++i )
786 auto& uniqueRecvIndices = uniqueRecvIndicesForSendIndex[ sendMap[ i ] ];
787 if( uniqueRecvIndices.count( recvMap[ i ] ) == 0 )
788 uniqueRecvIndices.insert( recvMap[ i ] );
809 for(
int link=0; link<nlinks; ++link)
810 sendIndexMap_[ dest[link] ].writeToBuffer( osv[link] );
813 osv = mpAccess.exchange( osv );
816 for(
int link=0; link<nlinks; ++link)
817 sendIndexMap_[ dest[link] ].readFromBuffer( osv[link] );
828 bool contains(
int dim,
int codim )
const
830 return blockMapper_.contains( codim );
834 bool fixedSize(
int dim,
int codim )
const
840 template<
class MessageBuffer,
class Entity >
841 void gather( MessageBuffer &buffer,
const Entity &entity )
const
844 const auto myPartitionType = entity.partitionType();
846 const bool send = EntityCommHelper< CommInterface > :: send( myPartitionType );
848 if constexpr (isMMesh)
851 buffer.write( myRank_ );
857 if constexpr (!isMMesh)
860 buffer.write( myRank_ );
863 const int numDofs = blockMapper_.numEntityDofs( entity );
865 typedef std::vector< GlobalKeyType > IndicesType ;
866 IndicesType indices( numDofs );
869 blockMapper_.mapEachEntityDof( entity, AssignFunctor< IndicesType >( indices ) );
872 for(
int i = 0; i < numDofs; ++i )
873 buffer.write( indices[ i ] );
878 template<
class MessageBuffer,
class Entity >
879 void scatter( MessageBuffer &buffer,
const Entity &entity,
const size_t dataSize )
887 assert( (rank >= 0) && (rank < mySize_) );
890 const auto myPartitionType = entity.partitionType();
892 const bool receive = EntityCommHelper< CommInterface > :: receive( myPartitionType );
895 linkStorage_.insert( rank );
898 typedef std::vector< GlobalKeyType > IndicesType ;
899 IndicesType indices( dataSize - 1 );
900 for(
size_t i=0; i<dataSize-1; ++i)
901 buffer.read( indices[i] );
916 sendIndexMap_[ rank ].insert( indices );
919 const int numDofs = blockMapper_.numEntityDofs( entity );
920 indices.resize( numDofs );
923 blockMapper_.mapEachEntityDof( entity, AssignFunctor< IndicesType >( indices ) );
926 recvIndexMap_[ rank ].insert( indices );
932 template<
class Entity >
933 size_t size(
const Entity &entity )
const
935 const PartitionType myPartitionType = entity.partitionType();
936 const bool send = EntityCommHelper< CommInterface > :: send( myPartitionType );
937 return (send) ? (blockMapper_.numEntityDofs( entity ) + 1) : isMMesh;
943 template<
class BlockMapper >
944 template<
class Space >
945 inline void DependencyCache< BlockMapper > :: buildMaps(
const Space& space )
947 typedef typename Space::GridPartType::CommunicationType CommunicationType;
950 LinkBuilder< CommunicationType, LinkStorageType, IndexMapVectorType,
952 handle( space.gridPart().comm(),
954 linkStorage_, sendIndexMap_, recvIndexMap_ );
955 buildMaps( space, handle );
959 LinkBuilder< CommunicationType, LinkStorageType, IndexMapVectorType,
961 handle( space.gridPart().comm(),
963 linkStorage_, sendIndexMap_, recvIndexMap_ );
964 buildMaps( space, handle );
968 LinkBuilder< CommunicationType, LinkStorageType, IndexMapVectorType, All_All_Interface >
969 handle( space.gridPart().comm(),
971 linkStorage_, sendIndexMap_, recvIndexMap_ );
972 buildMaps( space, handle );
975 DUNE_THROW( NotImplemented,
"DependencyCache for the given interface has not been implemented, yet." );
983 template<
class BlockMapper >
984 template<
class Space,
class Comm,
class LS,
class IMV, InterfaceType CI >
985 inline void DependencyCache< BlockMapper >
986 :: buildMaps(
const Space& space, LinkBuilder< Comm, LS, IMV, CI > &handle )
988 linkStorage_.clear();
989 const size_t size = recvIndexMap_.size();
990 for(
size_t i = 0; i <
size; ++i )
992 recvIndexMap_[ i ].clear();
993 sendIndexMap_[ i ].clear();
1000 mpAccess().removeLinkage();
1002 mpAccess().insertRequestSymetric( linkStorage_ );
1005 template<
class BlockMapper >
1006 inline void DependencyCache< BlockMapper > :: checkConsistency()
1008 const int nLinks = nlinks();
1010 ObjectStreamVectorType buffer( nLinks );
1013 for(
int l=0; l<nLinks; ++l)
1016 const int sendSize = sendIndexMap_[ dest( l ) ].size();
1017 buffer[l].write( sendSize );
1018 for(
int i=0; i<sendSize; ++i)
1019 buffer[l].write( i );
1023 buffer = mpAccess().exchange( buffer );
1026 for(
int l=0; l<nLinks; ++l)
1028 const int recvSize = recvIndexMap_[ dest( l ) ].size();
1030 buffer[l].read( sendedSize );
1033 if( recvSize != sendedSize )
1035 DUNE_THROW(InvalidStateException,
"Sizes do not match!" << sendedSize <<
" o|r " << recvSize);
1038 for(
int i=0; i<recvSize; ++i)
1041 buffer[l].read( idx );
1046 DUNE_THROW(InvalidStateException,
"Wrong ordering of send and recv maps!");
1052 template<
class BlockMapper >
1053 template<
class Space,
class DiscreteFunction,
class Operation >
1054 inline void DependencyCache< BlockMapper >
1055 :: exchange(
const Space& space, DiscreteFunction &discreteFunction,
const Operation& operation )
1058 if( NonBlockingCommunicationType::skip( discreteFunction, space.gridPart().comm() ) )
1062 NonBlockingCommunicationType nbc( space, *
this );
1065 nbc.send( discreteFunction );
1068 exchangeTime_ = nbc.receive( discreteFunction, operation );
1071 template<
class BlockMapper >
1072 template<
class DiscreteFunction >
1073 inline void DependencyCache< BlockMapper >
1074 :: writeBuffer( ObjectStreamVectorType &osv,
1075 const DiscreteFunction &discreteFunction )
const
1077 const int numLinks = nlinks();
1078 for(
int link = 0; link < numLinks; ++link )
1079 writeBuffer( link, osv[ link ], discreteFunction );
1082 template<
class BlockMapper >
1083 template<
class DiscreteFunction,
class Operation >
1084 inline void DependencyCache< BlockMapper >
1085 :: readBuffer( ObjectStreamVectorType &osv,
1086 DiscreteFunction &discreteFunction,
1087 const Operation& operation )
const
1089 const int numLinks = nlinks();
1090 for(
int link = 0; link < numLinks; ++link )
1091 readBuffer( link, osv[ link ], discreteFunction, operation );
1095 template <
class BlockMapper >
1096 class CommManagerSingletonKey
1098 const BlockMapper& blockMapper_;
1104 CommManagerSingletonKey(
const int pSize,
1105 const BlockMapper& blockMapper,
1108 : blockMapper_( blockMapper ),
1109 interface_(interface), dir_(dir), pSize_( pSize )
1113 CommManagerSingletonKey(
const CommManagerSingletonKey & org) =
default;
1116 bool operator == (
const CommManagerSingletonKey & otherKey)
const
1119 return (&(blockMapper_) == &(otherKey.blockMapper_) );
1135 int pSize ()
const {
return pSize_; }
1140 template <
class KeyImp,
class ObjectImp>
1141 class CommManagerFactory
1145 static ObjectImp * createObject(
const KeyImp & key )
1147 return new ObjectImp(key.pSize(), key.interface(), key.direction());
1151 static void deleteObject( ObjectImp * obj )
1158 template <
class SpaceImp>
1159 class CommunicationManager
1161 typedef CommunicationManager<SpaceImp> ThisType;
1163 typedef typename SpaceImp::BlockMapperType BlockMapperType;
1166 typedef DependencyCache< BlockMapperType > DependencyCacheType;
1168 typedef CommManagerSingletonKey< BlockMapperType > KeyType;
1169 typedef CommManagerFactory<KeyType, DependencyCacheType> FactoryType;
1171 typedef SingletonList< KeyType , DependencyCacheType , FactoryType > CommunicationProviderType;
1176 typedef ALU3DSPACE MpAccessLocal MPAccessInterfaceType;
1179 std::unique_ptr< DependencyCacheType, typename CommunicationProviderType::Deleter > cache_;
1182 CommunicationManager(
const ThisType& org) =
delete;
1185 typedef typename DependencyCacheType :: NonBlockingCommunicationType NonBlockingCommunicationType;
1188 CommunicationManager(
const SpaceType& space,
1193 , cache_( &CommunicationProviderType::getObject(
1194 KeyType( space.gridPart().comm().
size(), space_.blockMapper(), interface,dir) ) )
1197 cache().init( space.gridPart().comm() );
1203 CommunicationManager(
const SpaceType& space)
1207 DependencyCacheType& cache ()
const { assert( cache_ );
return *cache_; }
1212 return cache().communicationInterface();
1218 return cache().communicationDirection();
1224 return cache().buildTime();
1230 return cache().exchangeTime();
1233 MPAccessInterfaceType& mpAccess()
1235 return cache().mpAccess();
1241 return cache().nonBlockingCommunication( space_ );
1246 template <
class DiscreteFunctionType>
1250 typedef typename DiscreteFunctionType :: DiscreteFunctionSpaceType
1251 :: template CommDataHandle< DiscreteFunctionType > :: OperationType DefaultOperationType;
1254 DefaultOperationType operation;
1261 template <
class DiscreteFunctionType,
class Operation>
1264 cache().exchange( df.
space(), df, operation );
1269 template <
class Vector,
class Operation>
1270 void exchange(
const SpaceType& space, Vector& v,
const Operation& operation )
const
1272 static_assert( std::is_base_of< IsBlockVector, Vector > :: value,
"exchange needs BlockVectorInterface and derived");
1273 cache().exchange( space, v, operation );
1277 template <
class ObjectStreamVectorType,
class DiscreteFunctionType>
1280 cache().writeBuffer( osv, df );
1284 template <
class ObjectStreamVectorType,
class DiscreteFunctionType>
1287 typedef typename DiscreteFunctionType :: DiscreteFunctionSpaceType
1288 :: template CommDataHandle<DiscreteFunctionType> :: OperationType OperationType;
1291 OperationType operation;
1293 readBuffer( osv, df, operation );
1297 template <
class ObjectStreamVectorType,
class DiscreteFunctionType,
class OperationType>
1298 void readBuffer(ObjectStreamVectorType& osv,
DiscreteFunctionType & df,
const OperationType& operation)
const
1300 cache().readBuffer( osv, df , operation);
1306 cache().rebuild( space_ );
1311 class CommunicationManagerList
1314 template <
class MPAccessType,
class ObjectStreamVectorType>
1315 class DiscreteFunctionCommunicatorInterface
1318 DiscreteFunctionCommunicatorInterface()
1321 virtual ~DiscreteFunctionCommunicatorInterface()
1324 virtual MPAccessType& mpAccess() = 0;
1325 virtual void writeBuffer(ObjectStreamVectorType&)
const = 0;
1326 virtual void readBuffer(ObjectStreamVectorType&) = 0;
1327 virtual void rebuildCache() = 0;
1329 virtual bool handles ( IsDiscreteFunction &df )
const = 0;
1335 template <
class DiscreteFunctionImp,
1337 class ObjectStreamVectorType,
1338 class OperationType >
1339 class DiscreteFunctionCommunicator
1340 :
public DiscreteFunctionCommunicatorInterface<MPAccessType,ObjectStreamVectorType>
1345 typedef CommunicationManager<DiscreteFunctionSpaceType> CommunicationManagerType;
1350 CommunicationManagerType comm_;
1353 const OperationType operation_;
1357 : df_(df), comm_(df_.space()), operation_( op )
1361 virtual MPAccessType& mpAccess()
1363 return comm_.mpAccess();
1367 virtual void writeBuffer(ObjectStreamVectorType& osv)
const
1369 comm_.writeBuffer(osv,df_);
1373 virtual void readBuffer(ObjectStreamVectorType& osv)
1375 comm_.readBuffer(osv, df_, operation_ );
1379 virtual void rebuildCache()
1381 comm_.rebuildCache();
1384 virtual bool handles ( IsDiscreteFunction &df )
const {
return (&
static_cast< IsDiscreteFunction &
>( df_ ) == &df); }
1388 typedef ALU3DSPACE ObjectStream ObjectStreamType;
1391 typedef std::vector< ObjectStreamType > ObjectStreamVectorType;
1394 typedef ALU3DSPACE MpAccessLocal MPAccessInterfaceType;
1397 typedef DiscreteFunctionCommunicatorInterface<MPAccessInterfaceType,ObjectStreamVectorType>
1398 CommObjInterfaceType;
1401 typedef std::list < std::unique_ptr< CommObjInterfaceType > > CommObjListType;
1402 CommObjListType objList_;
1409 template <
class CombinedObjectType>
1410 CommunicationManagerList(CombinedObjectType& cObj) :
1414 cObj.addToList(*
this);
1418 CommunicationManagerList()
1422 CommunicationManagerList (
const CommunicationManagerList & ) =
delete;
1425 template <
class DiscreteFunctionImp,
class Operation>
1426 void addToList(DiscreteFunctionImp &df,
const Operation& operation )
1429 typedef DiscreteFunctionCommunicator<DiscreteFunctionImp,
1430 MPAccessInterfaceType,
1431 ObjectStreamVectorType,
1432 Operation > CommObj;
1433 CommObj * obj =
new CommObj(df, operation);
1434 objList_.push_back( std::unique_ptr< CommObjInterfaceType > (obj) );
1440 MPAccessInterfaceType& mpAccess = objList_.front()->mpAccess();
1443 mySize_ = mpAccess.psize();
1448 template <
class DiscreteFunctionImp>
1451 DFCommunicationOperation::Copy operation;
1455 template<
class DiscreteFunction >
1456 void removeFromList ( DiscreteFunction &df )
1458 const auto handles = [ &df ] (
const std::unique_ptr< CommObjInterfaceType > &commObj ) { assert( commObj );
return commObj->handles( df ); };
1459 CommObjListType::reverse_iterator pos = std::find_if( objList_.rbegin(), objList_.rend(), handles );
1460 if( pos != objList_.rend() )
1461 objList_.erase( --pos.base() );
1463 DUNE_THROW( RangeError,
"Trying to remove discrete function that was never added" );
1471 if( mySize_ <= 1 ) return ;
1474 if(objList_.size() > 0)
1477 for(
auto& elem : objList_)
1478 elem->rebuildCache();
1481 auto& mpAccess = objList_.front()->mpAccess();
1484 ObjectStreamVectorType osv( mpAccess.nlinks() );
1487 for(
auto& elem : objList_)
1488 elem->writeBuffer(osv);
1491 osv = mpAccess.exchange(osv);
1494 for(
auto& elem : objList_)
1495 elem->readBuffer(osv);
A vector valued function space.
Definition: functionspace.hh:60
forward declaration
Definition: discretefunction.hh:51
const DiscreteFunctionSpaceType & space() const
obtain a reference to the corresponding DiscreteFunctionSpace
Definition: discretefunction.hh:709
TupleDiscreteFunctionSpace< typename DiscreteFunctions::DiscreteFunctionSpaceType ... > DiscreteFunctionSpaceType
type for the discrete function space this function lives in
Definition: discretefunction.hh:69
A simple stop watch.
Definition: timer.hh:43
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:77
Different resources needed by all grid implementations.
Describes the parallel communication interface class for MessageBuffers and DataHandles.
double buildTime() const
return time needed for last build
Definition: communicationmanager.hh:203
InterfaceType communicationInterface() const
return communication interface
Definition: communicationmanager.hh:189
void exchange() const
Definition: communicationmanager.hh:391
void exchange(DiscreteFunction &discreteFunction) const
exchange data for a discrete function using the copy operation
Definition: communicationmanager.hh:225
CommunicationDirection communicationDirection() const
return communication direction
Definition: communicationmanager.hh:194
NonBlockingCommunicationType nonBlockingCommunication() const
return object for non-blocking communication
Definition: communicationmanager.hh:215
double exchangeTime() const
return time needed for last exchange of data
Definition: communicationmanager.hh:209
void addToList(DiscreteFunctionImp &df, const Operation &operation)
add discrete function to communication list
Definition: communicationmanager.hh:363
#define DUNE_THROW(E, m)
Definition: exceptions.hh:218
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:256
EnableIfInterOperable< T1, T2, bool >::type operator==(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for equality.
Definition: iteratorfacades.hh:238
Some useful basic math stuff.
Dune namespace.
Definition: alignedallocator.hh:13
constexpr std::integral_constant< std::size_t, sizeof...(II)> size(std::integer_sequence< T, II... >)
Return the size of the sequence.
Definition: integersequence.hh:75
constexpr std::bool_constant<((II==value)||...)> contains(std::integer_sequence< T, II... >, std::integral_constant< T, value >)
Checks whether or not a given sequence contains a value.
Definition: integersequence.hh:137
std::size_t fixedSize
The number of data items per index if it is fixed, 0 otherwise.
Definition: variablesizecommunicator.hh:264
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