Skip to content
Snippets Groups Projects
vectorcommunicator.hh 2.95 KiB
Newer Older
  • Learn to ignore specific revisions
  • #ifndef VECTORCOMMUNICATOR_HH
    #define VECTORCOMMUNICATOR_HH
    
    #include <vector>
    
    
    #include <dune/grid/utility/globalindexset.hh>
    
    #include <dune/gfe/parallel/mpifunctions.hh>
    
    
    
    template<typename GUIndex, typename Communicator, typename VectorType>
    
      struct TransferVectorTuple {
        typedef typename VectorType::value_type EntryType;
    
    
        size_t globalIndex_;
        EntryType value_;
    
        TransferVectorTuple(const size_t& r, const EntryType& e)
        : globalIndex_(r),
          value_(e) {}
    
      void transferVector(const VectorType& localVector) {
        // Create vector for transfer data
        std::vector<TransferVectorTuple> localVectorEntries;
    
        // Translate vector entries
    
        for (size_t k=0; k<localVector.size(); k++)
    
            localVectorEntries.push_back(TransferVectorTuple(guIndex.index(k), localVector[k]));
    
    
        // Get number of vector entries on each process
    
        localVectorEntriesSizes = MPIFunctions::shareSizes(communicator_, localVectorEntries.size());
    
    
        // Get vector entries from every process
    
        globalVectorEntries = MPIFunctions::gatherv(communicator_, localVectorEntries, localVectorEntriesSizes, root_rank);
    
    Oliver Sander's avatar
    Oliver Sander committed
    public:
    
      VectorCommunicator(const GUIndex& gi,
                         const Communicator& communicator,
                         const int& root)
      : guIndex(gi), communicator_(communicator), root_rank(root)
    
    Oliver Sander's avatar
    Oliver Sander committed
    
      VectorType reduceAdd(const VectorType& localVector)
      {
        transferVector(localVector);
    
    
        VectorType globalVector(guIndex.nGlobalEntity());
    
    
        for (size_t k = 0; k < globalVectorEntries.size(); ++k)
    
          globalVector[globalVectorEntries[k].globalIndex_] += globalVectorEntries[k].value_;
    
    Oliver Sander's avatar
    Oliver Sander committed
      VectorType reduceCopy(const VectorType& localVector)
      {
        transferVector(localVector);
    
    
        VectorType globalVector(guIndex.nGlobalEntity());
    
        for (size_t k = 0; k < globalVectorEntries.size(); ++k)
    
          globalVector[globalVectorEntries[k].globalIndex_] = globalVectorEntries[k].value_;
    
    Oliver Sander's avatar
    Oliver Sander committed
      VectorType scatter(const VectorType& global)
      {
        for (size_t k = 0; k < globalVectorEntries.size(); ++k)
    
          globalVectorEntries[k].value_ = global[globalVectorEntries[k].globalIndex_];
    
    Oliver Sander's avatar
    Oliver Sander committed
    
    
        const int localSize = localVectorEntriesSizes[communicator_.rank()];
    
    
        // Create vector for transfer data
        std::vector<TransferVectorTuple> localVectorEntries(localSize);
    
    
        MPIFunctions::scatterv(communicator_, localVectorEntries, globalVectorEntries, localVectorEntriesSizes, root_rank);
    
    
        // Create vector for local solution
        VectorType x(localSize);
    
        // And translate solution again
        for (size_t k = 0; k < localVectorEntries.size(); ++k)
    
          x[k] = localVectorEntries[k].value_;
    
    private:
      const GUIndex& guIndex;
    
      const Communicator& communicator_;
    
      int root_rank;
    
      std::vector<int> localVectorEntriesSizes;
      std::vector<TransferVectorTuple> globalVectorEntries;
    };
    
    #endif