From b227d4cf9507678f549840bc913e8a391dbe096b Mon Sep 17 00:00:00 2001 From: Sebastian Reuther <sebastian.reuther@tu-dresden.de> Date: Mon, 16 Nov 2015 09:41:34 +0000 Subject: [PATCH] added more synch methods in MeshDistributor --- AMDiS/src/parallel/MeshDistributor.h | 141 +++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/AMDiS/src/parallel/MeshDistributor.h b/AMDiS/src/parallel/MeshDistributor.h index 109e7f54..7e76039f 100644 --- a/AMDiS/src/parallel/MeshDistributor.h +++ b/AMDiS/src/parallel/MeshDistributor.h @@ -282,6 +282,147 @@ namespace AMDiS { namespace Parallel { synchVector(vec); } + /** \brief + * This function must be used if the values of a set of DOFVectors must be + * synchronized over all ranks. That means, that each rank sends the + * values of the DOFs, which are owned by the rank and lie on an interior + * boundary, to all other ranks also having these DOFs. + * + * The synchronization direction is from major to minor rank. This means + * that the value of the rank with the higher number sends its value + * to the rank with the lower number. + */ + // majorRank => minorRank + template<typename T> + void synchVector(std::vector<DOFVector<T>*> &vecs) + { + if (vecs.size() > 0) + { + // get FE space + const FiniteElemSpace *fe = vecs[0]->getFeSpace(); + // TODO: check equal FE space + // The lines below do not work! + // for ( typename std::vector<DOFVector<T>*>::iterator vecIt = vecs.begin(); vecIt != vecs.end(); ++vecIt) + // TEST_EXIT( (*vecIt)->getFeSpace()->getBasisFcts()->getDegree() == fe->getBasisFcts()->getDegree() )("FE space of vectors to synch not equal!\n"); + + MultiLevelDofComm& dofComm = dofComms[fe->getMesh()]; + + int nLevels = levelData.getNumberOfLevels(); + for (int level = nLevels - 1; level >= 0; level--) + { + StdMpi<std::vector<std::vector<T> > > stdMpi(levelData.getMpiComm(level)); + + for (DofComm::Iterator it(dofComm[level].getSendDofs(), fe); !it.end(); it.nextRank()) + { + std::vector<std::vector<T> > dofs; + dofs.reserve(it.getDofs().size()); + for (; !it.endDofIter(); it.nextDof()) + { + std::vector<T> values; + values.reserve(vecs.size()); + for (typename std::vector<DOFVector<T>*>::iterator vecIt = vecs.begin(); vecIt != vecs.end(); ++vecIt ) + values.push_back((**vecIt)[it.getDofIndex()]); + dofs.push_back(values); + } + stdMpi.send(it.getRank(), dofs); + } + + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), fe); !it.end(); it.nextRank()) + stdMpi.recv(it.getRank()); + + stdMpi.startCommunication(); + + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), fe); !it.end(); it.nextRank()) + { + for (; !it.endDofIter(); it.nextDof()) + { + std::vector<T> values = stdMpi.getRecvData(it.getRank())[it.getDofCounter()]; + typename std::vector<DOFVector<T>*>::iterator vecIt = vecs.begin(); + typename std::vector<T>::iterator valuesIt = values.begin(); + for (; vecIt != vecs.end(), valuesIt != values.end(); ++vecIt , ++valuesIt) + (**vecIt)[it.getDofIndex()] = *valuesIt; + } + } + } + } + } + + /** \brief + * Works quite similar to the function \ref synchVector with an operator/ + * assigner for the values on the subdomain boundaries of the DOFVector vec. + * Additionally, the values stored in additionalVecs are synchronized in + * the same way (direction (minor to major or major to minor rank)) as the + * DOFs of the variable vec. + */ + template<typename T, typename Operator> + void synchVectorSameWay(DOFVector<T> &vec, std::vector<DOFVector<T>*> additionalVecs, Operator op) + { + // get FE space and check equal FE space + const FiniteElemSpace *fe = vec.getFeSpace(); + // TODO: check equal FE space + // The lines below do not work! + // for ( typename std::vector<DOFVector<T>*>::iterator vecIt = additionalVecs.begin(); vecIt != additionalVecs.end(); ++vecIt) + // TEST_EXIT( (*vecIt)->getFeSpace()->getBasisFcts()->getDegree() == fe->getBasisFcts()->getDegree() )("FE space of vectors to synch not equal!\n"); + + MultiLevelDofComm& dofComm = dofComms[fe->getMesh()]; + + int nLevels = levelData.getNumberOfLevels(); + for (int level = nLevels - 1; level >= 0; level--) + { + StdMpi < std::vector<std::vector<T> > > stdMpi(levelData.getMpiComm(level)); + + for (DofComm::Iterator it(dofComm[level].getRecvDofs(), fe); !it.end(); it.nextRank()) + { + std::vector<std::vector<T> > dofs; + dofs.reserve(it.getDofs().size()); + for (; !it.endDofIter(); it.nextDof()) + { + std::vector<T> values; + values.reserve(additionalVecs.size() + 1); + values.push_back( vec[it.getDofIndex()] ); + for (typename std::vector<DOFVector<T>*>::iterator vecIt = additionalVecs.begin(); vecIt != additionalVecs.end(); ++vecIt ) + values.push_back( (**vecIt)[it.getDofIndex()] ); + dofs.push_back( values ); + } + stdMpi.send(it.getRank(), dofs); + } + + for (DofComm::Iterator it(dofComm[level].getSendDofs(), fe); !it.end(); it.nextRank()) + stdMpi.recv(it.getRank()); + + stdMpi.startCommunication(); + + for (DofComm::Iterator it(dofComm[level].getSendDofs(), fe); !it.end(); it.nextRank()) + { + for (; !it.endDofIter(); it.nextDof()) + { + DegreeOfFreedom idx = it.getDofIndex(); + std::vector<T> values = stdMpi.getRecvData(it.getRank())[it.getDofCounter()]; + + T minorRankValue = vec[idx]; + T majorRankValue = values[0]; + op(vec[idx], values[0]); + T synchValue = vec[idx]; + + TEST_EXIT(additionalVecs.size() == values.size()-1)("The number of additional vectors and the received values do not match!\n"); + + typename std::vector<DOFVector<T>*>::iterator vecIt = additionalVecs.begin(); + typename std::vector<T>::iterator valuesIt = values.begin(); + ++valuesIt; // exclude the first one since it belongs to the variable vec + for (; vecIt != additionalVecs.end(), valuesIt != values.end(); ++vecIt , ++valuesIt) + if (synchValue == majorRankValue) + (**vecIt)[idx] = *valuesIt; + } + } + } + // call simple sync method + std::vector<DOFVector<T>*> allDOFVectors; + allDOFVectors.push_back(&vec); + for ( int i = 0; i < additionalVecs.size(); ++i ) + allDOFVectors.push_back(additionalVecs[i]); + synchVector(allDOFVectors); + } + /** \brief * This function must be used if the values of a DOFVector must be * synchronised over all ranks. That means, that each rank sends the -- GitLab