From a6e8512bca9409833256074ee120abda0f6fd02e Mon Sep 17 00:00:00 2001 From: Andreas Lauser <and@poware.org> Date: Tue, 10 May 2011 16:20:51 +0000 Subject: [PATCH] make test_impes work in parallel (kind of) there seem to be issues with the accuracy of the linear solver, i.e. the residual reduction needs to be quite large... git-svn-id: svn://svn.iws.uni-stuttgart.de/DUMUX/dumux/trunk@5788 2fb0f335-1f38-0410-981e-8018bf24f1b0 --- .../decoupled/2p/diffusion/fv/fvpressure2p.hh | 9 - dumux/linear/borderindex.hh | 5 + dumux/linear/boxbicgstabilu0solver.hh | 5 +- dumux/linear/domesticoverlapfrombcrsmatrix.hh | 13 +- dumux/linear/elementborderlistfromgrid.hh | 39 ++- dumux/linear/foreignoverlapfrombcrsmatrix.hh | 227 +++++++----------- dumux/linear/globalindices.hh | 117 +++++---- dumux/linear/impetbicgstabilu0solver.hh | 17 +- dumux/linear/overlappingbcrsmatrix.hh | 106 +++++++- dumux/linear/overlappingblockvector.hh | 11 +- dumux/linear/seqsolverbackend.hh | 2 +- dumux/linear/vertexborderlistfromgrid.hh | 12 +- test/decoupled/2p/test_impes.cc | 20 +- 13 files changed, 358 insertions(+), 225 deletions(-) diff --git a/dumux/decoupled/2p/diffusion/fv/fvpressure2p.hh b/dumux/decoupled/2p/diffusion/fv/fvpressure2p.hh index b77cc1e32b..a96a958580 100644 --- a/dumux/decoupled/2p/diffusion/fv/fvpressure2p.hh +++ b/dumux/decoupled/2p/diffusion/fv/fvpressure2p.hh @@ -348,15 +348,6 @@ void FVPressure2P<TypeTag>::assemble(bool first) // cell index int globalIdxI = problem_.variables().index(*eIt); -#if HAVE_MPI - if (eIt->partitionType() != Dune::InteriorEntity) - { - A_[globalIdxI][globalIdxI]=1.0; - f_[globalIdxI]=0; - continue; - } -#endif - // get global coordinate of cell center const GlobalPosition& globalPos = eIt->geometry().center(); diff --git a/dumux/linear/borderindex.hh b/dumux/linear/borderindex.hh index 02bf61860a..8646a130da 100644 --- a/dumux/linear/borderindex.hh +++ b/dumux/linear/borderindex.hh @@ -41,6 +41,11 @@ struct BorderIndex //! Distance to the process border for the peer (in hops) int borderDistance; + + //! True if and only if the entity which corrosponds to the index + //! is in the interior of more than one process (i.e. the entity + //! is completely on the border) + bool isShared; }; }; diff --git a/dumux/linear/boxbicgstabilu0solver.hh b/dumux/linear/boxbicgstabilu0solver.hh index 4e5acab45e..13c17cbd68 100644 --- a/dumux/linear/boxbicgstabilu0solver.hh +++ b/dumux/linear/boxbicgstabilu0solver.hh @@ -66,7 +66,7 @@ class BoxBiCGStabILU0Solver typedef Dune::BiCGSTABSolver<OverlappingVector> Solver; public: - BoxBiCGStabILU0Solver(const Problem &problem, int overlapSize=1) + BoxBiCGStabILU0Solver(const Problem &problem, int overlapSize=3) : problem_(problem) , overlapSize_(overlapSize) { @@ -152,7 +152,8 @@ private: // create the overlapping Jacobian matrix overlapMatrix_ = new OverlappingMatrix (M, - borderListCreator.borderList(), + borderListCreator.foreignBorderList(), + borderListCreator.domesticBorderList(), overlapSize_); // create the overlapping vectors for the residual and the diff --git a/dumux/linear/domesticoverlapfrombcrsmatrix.hh b/dumux/linear/domesticoverlapfrombcrsmatrix.hh index 1cd64366b0..5859f4e17e 100644 --- a/dumux/linear/domesticoverlapfrombcrsmatrix.hh +++ b/dumux/linear/domesticoverlapfrombcrsmatrix.hh @@ -86,8 +86,9 @@ public: */ DomesticOverlapFromBCRSMatrix(const BCRSMatrix &A, const BorderList &borderList, + const BorderList &domesticBorderList, int overlapSize) - : foreignOverlap_(A, borderList, overlapSize) + : foreignOverlap_(A, borderList, domesticBorderList, overlapSize) , globalIndices_(foreignOverlap_) { myRank_ = 0; @@ -257,6 +258,16 @@ public: return foreignOverlap_.masterOf(domesticIdx) == myRank_; }; + /*! + * \brief Return true iff a given index is shared by more than one process + */ + bool isShared(int domesticIdx) const + { + if (!isLocal(domesticIdx)) + return false; + return foreignOverlap_.isShared(domesticIdx); + }; + /*! * \brief Return true iff a given rank is the master of a given * domestic index. diff --git a/dumux/linear/elementborderlistfromgrid.hh b/dumux/linear/elementborderlistfromgrid.hh index 67b1fd3a01..045cd4cd19 100644 --- a/dumux/linear/elementborderlistfromgrid.hh +++ b/dumux/linear/elementborderlistfromgrid.hh @@ -68,9 +68,14 @@ public: const ElementMapper &map) : gv_(gv), map_(map) { + forwardComm_ = true; + gv.communicate(*this, + Dune::InteriorBorder_All_Interface, + Dune::ForwardCommunication); + + forwardComm_ = false; gv.communicate(*this, Dune::InteriorBorder_All_Interface, -// Dune::Overlap_All_Interface, Dune::BackwardCommunication); }; @@ -100,19 +105,39 @@ public: bIdx.localIdx = map_.map(e); buff.read(bIdx.peerRank); buff.read(bIdx.peerIdx); - bIdx.borderDistance = 1; + bIdx.borderDistance = 0; + // this index is not shared between at least two processes + // because an element is always in the interior of exactly one + // process + bIdx.isShared = false; - borderList_.push_back(bIdx); + if (forwardComm_) { + // add the index to the list of indices which we intersect + // with remote processes. + domesticBorderList_.push_back(bIdx); + } + else { + // add the index to the list of remote processes + // intersecting with us. + foreignBorderList_.push_back(bIdx); + } }; - // Access to the initial seed list. - const BorderList &borderList() const - { return borderList_; } + // Access to the initial border list. + const BorderList &foreignBorderList() const + { return foreignBorderList_; } + + // Access to the indices which are on the border but which are in + // the interior of a remote process + const BorderList &domesticBorderList() const + { return domesticBorderList_; } private: const GridView gv_; const ElementMapper &map_; - BorderList borderList_; + bool forwardComm_; + BorderList foreignBorderList_; + BorderList domesticBorderList_; }; } // namespace Dumux diff --git a/dumux/linear/foreignoverlapfrombcrsmatrix.hh b/dumux/linear/foreignoverlapfrombcrsmatrix.hh index f07728eef9..fa5414a74f 100644 --- a/dumux/linear/foreignoverlapfrombcrsmatrix.hh +++ b/dumux/linear/foreignoverlapfrombcrsmatrix.hh @@ -85,9 +85,11 @@ public: * an initial list of border indices. */ ForeignOverlapFromBCRSMatrix(const BCRSMatrix &A, - const BorderList &borderList, + const BorderList &foreignBorderList, + const BorderList &domesticBorderList, int overlapSize) - : borderList_(borderList) + : foreignBorderList_(foreignBorderList) + , domesticBorderList_(domesticBorderList) { overlapSize_ = overlapSize; @@ -101,7 +103,7 @@ public: // calculate the border list. From this, create an initial // seed list of indices which are in the overlap. SeedList initialSeedList; - borderListToSeedList_(initialSeedList, borderList); + borderListToSeedList_(initialSeedList, foreignBorderList); // find the set of processes which have an overlap with the // local processes. (i.e. the set of processes which we will @@ -112,89 +114,24 @@ public: // i.e. find the distance of each row from the seed set. foreignOverlapByIndex_.resize(A.N()); extendForeignOverlap_(A, initialSeedList, overlapSize); + + updateMasterRanks_(foreignBorderList, domesticBorderList); // group foreign overlap by peer process rank groupForeignOverlapByRank_(); } - /*! - * \brief Return the border list. - * - * The border list is the list of (local index, peer index, peer - * rank) triples for all indices on a process border. - */ - const BorderList& borderList() const - { return borderList_; }; - /*! * \brief Returns true iff a local index is a border index. */ bool isBorder(int localIdx) const { return borderIndices_.count(localIdx) > 0; }; - /*! - * \brief Returns true iff a local index is a border index with a given peer. - */ - bool isBorderFor(int peerRank, int localIdx) const - { - typedef std::map<ProcessRank, BorderDistance> BorderDistMap; - const BorderDistMap &borderDist = foreignOverlapByIndex_[localIdx]; - BorderDistMap::const_iterator bdIt = borderDist.find(peerRank); - - if (bdIt == borderDist.end()) - return false; // this index is not seen by the peer - - BorderDistance bDist = bdIt->second; - if (bDist == 0) - // the index is on the border to the peer - return true; - - // at this point, the local index is in the interior of the - // foreign overlap for the peer, so it is a remote index - return false; - }; - - /*! - * \brief Returns true iff a local index is a front index for a given peer. - */ - bool isFrontFor(int peerRank, int localIdx) const - { - typedef std::map<ProcessRank, BorderDistance> BorderDistMap; - const BorderDistMap &borderDist = foreignOverlapByIndex_[localIdx]; - BorderDistMap::const_iterator bdIt = borderDist.find(peerRank); - - if (bdIt == borderDist.end()) - return false; // this index is not seen by the peer - - BorderDistance bDist = bdIt->second; - if (bDist == overlapSize_) - // the index is on the front of the peer - return true; - return false; - }; - /*! * \brief Return the rank of the master process for a local index. */ int masterOf(int localIdx) const - { - if (!isBorder(localIdx)) - return myRank_; // interior index - - // if the local index is a border index, loop over all ranks - // for which this index is also a border index. the lowest - // rank wins! - typedef typename std::map<ProcessRank, BorderDistance>::const_iterator iterator; - iterator it = foreignOverlapByIndex_[localIdx].begin(); - iterator endIt = foreignOverlapByIndex_[localIdx].end(); - LocalIndex masterIdx = myRank_; - for (; it != endIt; ++it) { - if (it->second == 0) - masterIdx = std::min(masterIdx, it->first); - } - - return masterIdx; - }; + { return masterRank_[localIdx]; }; /*! * \brief Return true if the current rank is the "master" of an @@ -207,70 +144,21 @@ public: * rank. */ bool iAmMasterOf(int localIdx) const - { - if (!isBorder(localIdx)) - return true; // interior index - - // if the local index is a border index, loop over all ranks - // for which this index is also a border index. the lowest - // rank wins! - typedef typename std::map<ProcessRank, BorderDistance>::const_iterator iterator; - iterator it = foreignOverlapByIndex_[localIdx].begin(); - iterator endIt = foreignOverlapByIndex_[localIdx].end(); - LocalIndex masterIdx = myRank_; - for (; it != endIt; ++it) { - if (it->first < myRank_ && it->second == 0) - return false; - } - - return masterIdx == myRank_; - }; + { return masterRank_[localIdx] == myRank_; }; /*! - * \brief Return true if a given local index is a remote index for - * a peer. + * \brief Returns the list of indices which intersect the process + * border and are in the interior of the local process. */ - bool isRemoteIndexFor(ProcessRank peerRank, Index localIdx) const - { - typedef std::map<ProcessRank, BorderDistance> BorderDistMap; - const BorderDistMap &borderDist = foreignOverlapByIndex_[localIdx]; - BorderDistMap::const_iterator bdIt = borderDist.find(peerRank); - - if (bdIt == borderDist.end()) - return false; // this index is not seen by the peer - - BorderDistance bDist = bdIt->second; - if (bDist == 0) - // the index is on the border to the peer, so for the peer - // it is a local index. - return false; - - // at this point, the local index is in the interior of the - // foreign overlap for the peer, so it is a remote index - return true; - }; + const BorderList &foreignBorderList() const + { return foreignBorderList_; } /*! - * \brief Return true if a given local index is also a local index - * for a peer. - */ - bool isLocalIndexFor(ProcessRank peerRank, Index localIdx) const - { - if (!isLocal(localIdx)) - // our own remote indices do not count! - return false; - - typedef std::map<ProcessRank, BorderDistance> BorderDistMap; - const BorderDistMap &borderDist = foreignOverlapByIndex_[localIdx]; - BorderDistMap::const_iterator bdIt = borderDist.find(peerRank); - if (bdIt == borderDist.end()) - return false; // this index is not seen by the peer - - // the index is also local for the peer if it an index on the - // border. - BorderDistance bDist = bdIt->second; - return bDist == 0; - }; + * \brief Returns the list of indices which intersect the process + * border and are in the interior of some remote process. + */ + const BorderList &domesticBorderList() const + { return domesticBorderList_; } /*! * \brief Return true if a given local index is a domestic index @@ -329,7 +217,15 @@ public: * \brief Returns true iff a domestic index is local */ bool isLocal(int domesticIdx) const - { return domesticIdx < numLocal(); }; + { + return domesticIdx < numLocal(); + }; + + /*! + * \brief Returns true iff a local index is shared with an other process. + */ + bool isShared(int domesticIdx) const + { return isLocal(domesticIdx) && isShared_[domesticIdx]; } /*! * \brief Return the number of peer ranks for which a given local @@ -382,11 +278,60 @@ protected: initialSeedList.push_back(IndexRankDist(it->localIdx, it->peerRank, it->borderDistance)); - if (it->borderDistance == 0) - borderIndices_.insert(it->localIdx); + borderIndices_.insert(it->localIdx); }; }; + // given a list of border indices and provided that + // borderListToSeedList_() was already called, calculate the + // master process of each local index. + void updateMasterRanks_(const BorderList &foreignBorderList, + const BorderList &domesticBorderList) + { + // determine the minimum rank for all indices + masterRank_.resize(numLocal_, myRank_); + for (int localIdx = 0; localIdx < masterRank_.size(); ++localIdx) { + int masterRank = myRank_; + if (isBorder(localIdx)) { + // if the local index is a border index, loop over all ranks + // for which this index is also a border index. the lowest + // rank wins! + typedef typename std::map<ProcessRank, BorderDistance>::const_iterator iterator; + iterator it = foreignOverlapByIndex_[localIdx].begin(); + iterator endIt = foreignOverlapByIndex_[localIdx].end(); + for (; it != endIt; ++it) { + if (it->second == 0) { + // if the border distance is zero, the rank with the minimum + masterRank = std::min(masterRank, it->first); + } + } + } + masterRank_[localIdx] = masterRank; + } + + // overwrite the master rank of the non-shared border indices + isShared_.resize(numLocal_, false); + BorderList::const_iterator it = foreignBorderList.begin(); + BorderList::const_iterator endIt = foreignBorderList.end(); + for (; it != endIt; ++it) { + if (!it->isShared) + masterRank_[it->localIdx] = myRank_; + else + isShared_[it->localIdx] = true; + }; + + // overwrite the master rank of the non-shared border on the + // domestic overlap + it = domesticBorderList_.begin(); + endIt = domesticBorderList_.end(); + for (; it != endIt; ++it) { + if (!it->isShared) { + masterRank_[it->localIdx] = it->peerRank; + } + }; + } + + // extend the foreign overlaps by one level. this uses a greedy // algorithm. void extendForeignOverlap_(const BCRSMatrix &A, @@ -502,11 +447,21 @@ protected: PeerSet peerSet_; // the list of indices on the border - const BorderList &borderList_; + const BorderList &foreignBorderList_; + const BorderList &domesticBorderList_; + + // an array which contains the rank of the master process for each + // index + std::vector<ProcessRank> masterRank_; + + // an array which stores whether an index is also in the interior + // of some other process + std::vector<bool> isShared_; - // set of all local indices which are on the border + // set of all local indices which are on the border of some remote + // process std::set<LocalIndex> borderIndices_; - + // stores the set of process ranks which are in the overlap for a // given row index "owned" by the current rank. The second value // store the distance from the nearest process border. diff --git a/dumux/linear/globalindices.hh b/dumux/linear/globalindices.hh index a5acd134dc..960b61d6dd 100644 --- a/dumux/linear/globalindices.hh +++ b/dumux/linear/globalindices.hh @@ -205,11 +205,8 @@ public: */ void print() const { - int myRank = 0; -#if HAVE_MPI - MPI_Comm_rank(MPI_COMM_WORLD, &myRank); -#endif // HAVE_MPI - std::cout << "(domestic index, global index, domestic->global->domestic) list for rank " << myRank << "\n"; + std::cout << "(domestic index, global index, domestic->global->domestic) list for rank " << + myRank_ << "\n"; for (int domIdx = 0; domIdx < domesticToGlobal_.size(); ++ domIdx) { std::cout << "(" << domIdx @@ -272,61 +269,87 @@ protected: 0, // tag MPI_COMM_WORLD); // communicator }; + + typename PeerSet::const_iterator peerIt; + typename PeerSet::const_iterator peerEndIt = peerSet_().end(); + // receive the border indices from the lower ranks + peerIt = peerSet_().begin(); + for (; peerIt != peerEndIt; ++peerIt) { + if (*peerIt < myRank_) + receiveBorderFrom_(*peerIt); + } - // retrieve the global indices for which we are not master - // from the processes with lower rank - PeerSet::const_iterator peerIt = peerSet_().begin(); - PeerSet::const_iterator peerEndIt = peerSet_().end(); + // send the border indices to the higher ranks + peerIt = peerSet_().begin(); for (; peerIt != peerEndIt; ++peerIt) { - int peerRank = *peerIt; - if (peerRank > myRank_) - continue; // ignore processes with higher rank - - // receive (local index on myRank, global index) pairs and - // update maps - BorderList::const_iterator borderIt = borderList_().begin(); - BorderList::const_iterator borderEndIt = borderList_().end(); - for (; borderIt != borderEndIt; ++borderIt) { - int borderPeer = borderIt->peerRank; - if (borderPeer != peerRank) - continue; - if (borderIt->borderDistance == 0) - receiveBorderIndex(peerRank); - } + if (*peerIt > myRank_) + sendBorderTo_(*peerIt); } - // send the global indices for which we are master - // to the processes with higher rank + // receive the border indices from the higher ranks peerIt = peerSet_().begin(); - peerEndIt = peerSet_().end(); for (; peerIt != peerEndIt; ++peerIt) { - int peerRank = *peerIt; - if (peerRank < myRank_) - continue; // ignore processes with lower rank - - // send (local index on myRank, global index) pairs to the - // peers - BorderList::const_iterator borderIt = borderList_().begin(); - BorderList::const_iterator borderEndIt = borderList_().end(); - for (; borderIt != borderEndIt; ++borderIt) { - int borderPeer = borderIt->peerRank; - if (borderPeer != peerRank) - continue; - - int localIdx = borderIt->localIdx; - int peerIdx = borderIt->peerIdx; - if (borderIt->borderDistance == 0) - sendBorderIndex(peerRank, localIdx, peerIdx); - } + if (*peerIt > myRank_) + receiveBorderFrom_(*peerIt); + } + + // send the border indices to the lower ranks + peerIt = peerSet_().begin(); + for (; peerIt != peerEndIt; ++peerIt) { + if (*peerIt < myRank_) + sendBorderTo_(*peerIt); } #endif // HAVE_MPI } + void sendBorderTo_(ProcessRank peerRank) + { +#if HAVE_MPI + // send (local index on myRank, global index) pairs to the + // peers + BorderList::const_iterator borderIt = foreignBorderList_().begin(); + BorderList::const_iterator borderEndIt = foreignBorderList_().end(); + for (; borderIt != borderEndIt; ++borderIt) { + int borderPeer = borderIt->peerRank; + if (borderPeer != peerRank) + continue; + + int localIdx = borderIt->localIdx; + int peerIdx = borderIt->peerIdx; + if (foreignOverlap_.iAmMasterOf(borderIt->localIdx)) { + sendBorderIndex(borderPeer, localIdx, peerIdx); + } + } +#endif // HAVE_MPI + } + + void receiveBorderFrom_(ProcessRank peerRank) + { +#if HAVE_MPI + // retrieve the global indices for which we are not master + // from the processes with lower rank + BorderList::const_iterator borderIt = domesticBorderList_().begin(); + BorderList::const_iterator borderEndIt = domesticBorderList_().end(); + for (; borderIt != borderEndIt; ++borderIt) { + int borderPeer = borderIt->peerRank; + if (borderPeer != peerRank) + continue; + + if (foreignOverlap_.masterOf(borderIt->localIdx) == borderPeer) { + receiveBorderIndex(borderPeer); + } + } +#endif // HAVE_MPI + }; + const PeerSet &peerSet_() const { return foreignOverlap_.peerSet(); } - const BorderList &borderList_() const - { return foreignOverlap_.borderList(); } + const BorderList &foreignBorderList_() const + { return foreignOverlap_.foreignBorderList(); } + + const BorderList &domesticBorderList_() const + { return foreignOverlap_.domesticBorderList(); } int myRank_; diff --git a/dumux/linear/impetbicgstabilu0solver.hh b/dumux/linear/impetbicgstabilu0solver.hh index d371610872..0320347368 100644 --- a/dumux/linear/impetbicgstabilu0solver.hh +++ b/dumux/linear/impetbicgstabilu0solver.hh @@ -115,9 +115,9 @@ public: const Vector &b) { int verbosityLevel = GET_PROP_VALUE(TypeTag, PTAG(LSVerbosity)); - static const int maxIter = GET_PROP_VALUE(TypeTag, PTAG(LSMaxIterations)); - static const double residReduction = GET_PROP_VALUE(TypeTag, PTAG(LSResidualReduction)); - static const double relaxation = GET_PROP_VALUE(TypeTag, PTAG(PreconditionerRelaxation)); + static const int maxIter = GET_PROP_VALUE(TypeTag, PTAG(LSMaxIterations)); + static const double residReduction = GET_PROP_VALUE(TypeTag, PTAG(LSResidualReduction)); + static const double relaxation = GET_PROP_VALUE(TypeTag, PTAG(PreconditionerRelaxation)); if (!overlapMatrix_) { // make sure that the overlapping matrix and block vectors @@ -128,10 +128,16 @@ public: // copy the values of the non-overlapping linear system of // equations to the overlapping one. On ther border, we add up // the values of all processes (using the assignAdd() methods) - overlapMatrix_->assignAdd(M); + overlapMatrix_->assignCopy(M); overlapb_->assignAdd(b); (*overlapx_) = 0.0; + /* + overlapMatrix_->print(); + overlapb_->print(); + exit(1); + */ + // create sequential and overlapping preconditioners //SeqPreconditioner seqPreCond(*overlapMatrix_, 1, 1.0); SeqPreconditioner seqPreCond(*overlapMatrix_, relaxation); @@ -168,7 +174,8 @@ private: // create the overlapping Jacobian matrix overlapMatrix_ = new OverlappingMatrix (M, - borderListCreator.borderList(), + borderListCreator.foreignBorderList(), + borderListCreator.domesticBorderList(), overlapSize_); // create the overlapping vectors for the residual and the diff --git a/dumux/linear/overlappingbcrsmatrix.hh b/dumux/linear/overlappingbcrsmatrix.hh index 4e35c90713..5c90d020ab 100644 --- a/dumux/linear/overlappingbcrsmatrix.hh +++ b/dumux/linear/overlappingbcrsmatrix.hh @@ -77,10 +77,11 @@ public: }; OverlappingBCRSMatrix(const BCRSMatrix &M, - const BorderList &borderList, + const BorderList &foreignBorderList, + const BorderList &domesticBorderList, int overlapSize) { - overlap_ = std::shared_ptr<Overlap>(new Overlap(M, borderList, overlapSize)); + overlap_ = std::shared_ptr<Overlap>(new Overlap(M, foreignBorderList, domesticBorderList, overlapSize)); myRank_ = 0; #if HAVE_MPI MPI_Comm_rank(MPI_COMM_WORLD, &myRank_); @@ -150,7 +151,40 @@ public: } // communicate and add the contents of overlapping rows - sync_(); + syncAdd_(); + } + + /*! + * \brief Assign and syncronize the overlapping matrix from a + * non-overlapping one. + * + * The non-master entries are copied from the master + */ + void assignCopy(const BCRSMatrix &M) + { + // first, set everything to 0 + BCRSMatrix::operator=(0.0); + + // assign the local rows + for (int rowIdx = 0; rowIdx < M.N(); ++rowIdx) { + ConstColIterator colIt = M[rowIdx].begin(); + ConstColIterator colEndIt = M[rowIdx].end(); + ColIterator myColIt = (*this)[rowIdx].begin(); + for (; colIt != colEndIt; ++colIt) { + while (true) { + if (myColIt.index() == colIt.index()) + break; + + ++ myColIt; + } + assert(myColIt.index() == colIt.index()); + + (*myColIt) = *colIt; + } + } + + // communicate and add the contents of overlapping rows + syncCopy_(); } void print() const @@ -319,8 +353,9 @@ private: ColIt colEndIt = M[rowIdx].end(); int j = 0; for (; colIt != colEndIt; ++colIt) { - if (overlap_->isDomesticIndexFor(peerRank, colIt.index())) + if (overlap_->isDomesticIndexFor(peerRank, colIt.index())) { ++ j; + } } (*rowSizesSendBuff_[peerRank])[i] = j; @@ -409,7 +444,7 @@ private: }; // communicates and adds up the contents of overlapping rows - void sync_() + void syncAdd_() { // first, send all entries to the peers const PeerSet &peerSet = overlap_->foreignOverlap().peerSet(); @@ -438,6 +473,37 @@ private: } } + // communicates and copies the contents of overlapping rows from + // the master + void syncCopy_() + { + // first, send all entries to the peers + const PeerSet &peerSet = overlap_->foreignOverlap().peerSet(); + typename PeerSet::const_iterator peerIt = peerSet.begin(); + typename PeerSet::const_iterator peerEndIt = peerSet.end(); + for (; peerIt != peerEndIt; ++peerIt) { + int peerRank = *peerIt; + + sendEntries_(peerRank); + } + + // then, receive entries from the peers + peerIt = peerSet.begin(); + for (; peerIt != peerEndIt; ++peerIt) { + int peerRank = *peerIt; + + receiveCopyEntries_(peerRank); + } + + // finally, make sure that everything which we send was + // received by the peers + peerIt = peerSet.begin(); + for (; peerIt != peerEndIt; ++peerIt) { + int peerRank = *peerIt; + entryValuesSendBuff_[peerRank]->wait(); + } + } + void sendEntries_(int peerRank) { #if HAVE_MPI @@ -494,6 +560,36 @@ private: #endif // HAVE_MPI } + void receiveCopyEntries_(int peerRank) + { +#if HAVE_MPI + MpiBuffer<block_type> &mpiRecvBuff = *entryValuesRecvBuff_[peerRank]; + + MpiBuffer<int> &mpiRowIndicesRecvBuff = *rowIndicesRecvBuff_[peerRank]; + MpiBuffer<int> &mpiRowSizesRecvBuff = *rowSizesRecvBuff_[peerRank]; + MpiBuffer<int> &mpiColIndicesRecvBuff = *entryIndicesRecvBuff_[peerRank]; + + mpiRecvBuff.receive(peerRank); + + // retrieve the values from the receive buffer + int k = 0; + for (int i = 0; i < mpiRowIndicesRecvBuff.size(); ++i) { + Index domRowIdx = mpiRowIndicesRecvBuff[i]; + for (int j = 0; j < mpiRowSizesRecvBuff[i]; ++j) { + Index domColIdx = mpiColIndicesRecvBuff[k]; + + if (!overlap_->iAmMasterOf(domRowIdx) || + !overlap_->iAmMasterOf(domColIdx)) + { + (*this)[domRowIdx][domColIdx] = mpiRecvBuff[k]; + } + + ++ k; + } + } +#endif // HAVE_MPI + } + void globalToDomesticBuff_(MpiBuffer<Index> &idxBuff) { for (int i = 0; i < idxBuff.size(); ++i) { diff --git a/dumux/linear/overlappingblockvector.hh b/dumux/linear/overlappingblockvector.hh index 888b7866a7..0111d4714d 100644 --- a/dumux/linear/overlappingblockvector.hh +++ b/dumux/linear/overlappingblockvector.hh @@ -82,12 +82,17 @@ public: */ void assignAdd(const BlockVector &nbv) { - Valgrind::SetDefined(nbv[7]); - // assign the local rows int numLocal = overlap_->numLocal(); for (int rowIdx = 0; rowIdx < numLocal; ++rowIdx) { - (*this)[rowIdx] = nbv[rowIdx]; + if (overlap_->iAmMasterOf(rowIdx) || + overlap_->isShared(rowIdx)) + { + (*this)[rowIdx] = nbv[rowIdx]; + } + else + (*this)[rowIdx] = 0; + } // set the remote indices to 0 diff --git a/dumux/linear/seqsolverbackend.hh b/dumux/linear/seqsolverbackend.hh index c47f1cb3a2..e8fb037851 100644 --- a/dumux/linear/seqsolverbackend.hh +++ b/dumux/linear/seqsolverbackend.hh @@ -59,7 +59,7 @@ SET_PROP_DEFAULT(LSVerbosity) SET_PROP_DEFAULT(LSResidualReduction) {public: - static constexpr double value = 1e-6; + static constexpr double value = 1e-13; }; SET_PROP_DEFAULT(LSMaxIterations) diff --git a/dumux/linear/vertexborderlistfromgrid.hh b/dumux/linear/vertexborderlistfromgrid.hh index c8c0e71275..0716e88ee1 100644 --- a/dumux/linear/vertexborderlistfromgrid.hh +++ b/dumux/linear/vertexborderlistfromgrid.hh @@ -98,12 +98,20 @@ public: buff.read(bIdx.peerRank); buff.read(bIdx.peerIdx); bIdx.borderDistance = 0; + // vertices on the border are always in the interior of more + // than one process which means that they are shared. + bIdx.isShared = true; borderList_.push_back(bIdx); }; - // Access to the initial seed list. - const BorderList &borderList() const + // Access to the foreign border list. + const BorderList &foreignBorderList() const + { return borderList_; } + + // Access to the domestic border list (same as foreign border list + // because all vertices are shared entities) + const BorderList &domesticBorderList() const { return borderList_; } private: diff --git a/test/decoupled/2p/test_impes.cc b/test/decoupled/2p/test_impes.cc index 5e2e910f73..d2ca40caa9 100644 --- a/test/decoupled/2p/test_impes.cc +++ b/test/decoupled/2p/test_impes.cc @@ -91,17 +91,23 @@ int main(int argc, char** argv) //////////////////////////////////////////////////////////// // create the grid //////////////////////////////////////////////////////////// - Dune::FieldVector<int,dim> N(6); N[0] = 30; - Dune::FieldVector<double ,dim> L(0); - Dune::FieldVector<double,dim> H(60); H[0] = 300; + Dune::FieldVector<int,dim> numCells; + numCells[0] = 30; + numCells[1] = 6; + Dune::FieldVector<double,dim> lowerLeft; + lowerLeft[0] = 0; + lowerLeft[1] = 0; + Dune::FieldVector<double,dim> upperRight; + upperRight[0] = 300; + upperRight[1] = 60; Dune::FieldVector<bool,dim> periodic(false); - Grid grid(Dune::MPIHelper::getCommunicator(), H, N, periodic, /*overlap=*/1); - + + Grid grid(Dune::MPIHelper::getCommunicator(), upperRight, numCells, periodic, /*overlap=*/1); + grid.loadBalance(); //////////////////////////////////////////////////////////// // instantiate and run the concrete problem //////////////////////////////////////////////////////////// - - Problem problem(grid.leafView(), L, H); + Problem problem(grid.leafView(), lowerLeft, upperRight); // load restart file if necessarry if (restart) -- GitLab