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:31
 
double elapsed() const noexcept
Get elapsed user-time from last reset until now/last stop in seconds.
Definition: timer.hh:67
 
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,...)
Definition: exceptions.hh:314
 
constexpr void forEach(Range &&range, F &&f)
Range based for loop.
Definition: hybridutilities.hh:257
 
constexpr 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