3#ifndef DUNE_INDICESSYNCER_HH
4#define DUNE_INDICESSYNCER_HH
52 typedef typename ParallelIndexSet::LocalIndex::Attribute
Attribute;
93 void sync(T1& numberer);
107 char* receiveBuffer_;
113 int receiveBufferSize_;
118 struct MessageInformation
135 class DefaultNumberer
150 MPI_Datatype datatype_;
181 GlobalIndicesMap globalMap_;
224 typedef std::tuple<RemoteIndexModifier,GlobalIndexModifier,BoolListModifier,
225 const ConstRemoteIndexIterator> IteratorTuple;
247 Iterators(RemoteIndexList& remoteIndices, GlobalIndexList& globalIndices,
345 void calculateMessageSizes();
354 void packAndSend(
int destination,
char* buffer,
std::size_t bufferSize, MPI_Request& req);
360 template<
typename T1>
361 void recvAndUnpack(T1& numberer);
366 void registerMessageDatatype();
371 void insertIntoRemoteIndexList(
int process,
378 void resetIteratorsMap();
398 template<
typename TG,
typename TA>
402 return i1.global() < i2.
first ||
403 (i1.global() == i2.
first && i1.local().attribute()<i2.
second);
406 template<
typename TG,
typename TA>
410 return i1.
first < i2.global() ||
411 (i1.
first == i2.global() && i1.
second<i2.local().attribute());
414 template<
typename TG,
typename TA>
418 return (i1.global() == i2.
first && i1.local().attribute()==i2.
second);
421 template<
typename TG,
typename TA>
425 return (i1.global() != i2.
first || i1.local().attribute()!=i2.
second);
428 template<
typename TG,
typename TA>
432 return (i1.global() == i2.
first && i1.local().attribute()==i2.
second);
435 template<
typename TG,
typename TA>
439 return (i1.global() != i2.
first || i1.local().attribute()!=i2.
second);
458 template<
typename T,
typename A,
typename A1>
462 for(
auto remote = remoteIndices.
begin(), end =remoteIndices.
end(); remote != end; ++remote) {
465 GlobalIndexList& global = globalMap[remote->first];
466 RemoteIndexList& rList = *(remote->second.first);
468 for(
auto index = rList.begin(), riEnd = rList.end();
469 index != riEnd; ++index) {
471 index->localIndexPair().local().attribute()));
484 template<
typename T,
typename A,
typename A1>
487 typename T::LocalIndex::Attribute>,A> >& globalMap,
493 auto global = globalMap.begin();
494 auto end = remoteIndices.remoteIndices_.
end();
496 for(
auto remote = remoteIndices.remoteIndices_.
begin(); remote != end; ++remote, ++global) {
497 assert(remote->first==global->first);
498 assert(remote->second.first->size() == global->second.size());
500 auto riEnd = remote->second.first->end();
501 auto rIndex = remote->second.first->begin();
502 auto gIndex = global->second.begin();
503 auto index = indexSet.begin();
505 assert(rIndex==riEnd || gIndex != global->second.end());
506 while(rIndex != riEnd) {
508 assert(gIndex != global->second.end());
510 while(!(index->global() == gIndex->first
511 && index->local().attribute() == gIndex->second)) {
516 if (index->global() > gIndex->first) {
517 index=indexSet.begin();
521 assert(index != indexSet.end() && *index == *gIndex);
523 rIndex->localIndex_ = &(*index);
529 remoteIndices.sourceSeqNo_ = remoteIndices.source_->
seqNo();
530 remoteIndices.destSeqNo_ = remoteIndices.target_->
seqNo();
536 : indexSet_(indexSet), remoteIndices_(remoteIndices)
539 assert(remoteIndices.source_ == remoteIndices.target_);
540 assert(remoteIndices.source_ == &indexSet);
548 : iterators_(remoteIndices.beginModify(), globalIndices.beginModify(),
549 booleans.beginModify(), remoteIndices.end())
560 ++(std::get<0>(iterators_));
561 ++(std::get<1>(iterators_));
562 ++(std::get<2>(iterators_));
570 std::get<0>(iterators_).insert(index);
571 std::get<1>(iterators_).insert(global);
572 std::get<2>(iterators_).insert(
false);
579 return *(std::get<0>(iterators_));
586 return *(std::get<1>(iterators_));
592 return *(std::get<2>(iterators_));
600 std::get<0>(iterators_) = remoteIndices.
beginModify();
601 std::get<1>(iterators_) = globalIndices.
beginModify();
608 return std::get<0>(iterators_) != std::get<3>(iterators_);
614 return std::get<0>(iterators_) == std::get<3>(iterators_);
620 MPI_Datatype type[2] = {MPI_INT, MPI_INT};
621 int blocklength[2] = {1,1};
622 MPI_Aint displacement[2];
626 MessageInformation message;
628 MPI_Get_address( &(message.publish), displacement);
629 MPI_Get_address( &(message.pairs), displacement+1);
632 MPI_Get_address(&message, &base);
633 displacement[0] -= base;
634 displacement[1] -= base;
636 MPI_Type_create_struct( 2, blocklength, displacement, type, &datatype_);
637 MPI_Type_commit(&datatype_);
641 void IndicesSyncer<T>::calculateMessageSizes()
643 auto iEnd = indexSet_.end();
644 auto collIter = remoteIndices_.template iterator<true>();
646 for(
auto index = indexSet_.begin(); index != iEnd; ++index) {
647 collIter.advance(index->global(), index->local().attribute());
651 auto end = collIter.end();
654 for(
auto valid = collIter.begin(); valid !=
end; ++valid) {
659 Dune::dverb<<rank_<<
": publishing "<<knownRemote<<
" for index "<<index->global()<<
" for processes ";
662 for(
auto valid = collIter.begin(); valid !=
end; ++valid) {
663 ++(infoSend_[valid.process()].publish);
664 (infoSend_[valid.process()].pairs) += knownRemote;
666 Dune::dverb<<
"(publish="<<infoSend_[valid.process()].publish<<
", pairs="<<infoSend_[valid.process()].pairs
673 const auto end = infoSend_.
end();
676 MessageInformation dummy;
678 auto messageIter= infoSend_.
begin();
679 const auto rend = remoteIndices_.
end();
682 for(
auto remote = remoteIndices_.
begin(); remote !=
rend; ++remote, ++neighbour) {
683 MessageInformation* message;
684 MessageInformation recv;
686 if(messageIter != end && messageIter->first==remote->first) {
688 message =
const_cast<MessageInformation*
>(&(messageIter->second));
694 sendBufferSizes_[neighbour]=0;
697 MPI_Pack_size(1, MPI_INT,remoteIndices_.
communicator(), &tsize);
698 sendBufferSizes_[neighbour] += tsize;
700 for(
int i=0; i < message->publish; ++i) {
703 sendBufferSizes_[neighbour] += tsize;
705 MPI_Pack_size(1, MPI_CHAR, remoteIndices_.
communicator(), &tsize);
706 sendBufferSizes_[neighbour] += tsize;
708 MPI_Pack_size(1, MPI_INT, remoteIndices_.
communicator(), &tsize);
709 sendBufferSizes_[neighbour] += tsize;
711 for(
int i=0; i < message->pairs; ++i) {
713 MPI_Pack_size(1, MPI_INT, remoteIndices_.
communicator(), &tsize);
714 sendBufferSizes_[neighbour] += tsize;
716 MPI_Pack_size(1, MPI_CHAR, remoteIndices_.
communicator(), &tsize);
717 sendBufferSizes_[neighbour] += tsize;
720 Dune::dverb<<rank_<<
": Buffer (neighbour="<<remote->first<<
") size is "<< sendBufferSizes_[neighbour]<<
" for publish="<<message->publish<<
" pairs="<<message->pairs<<
std::endl;
728 DefaultNumberer numberer;
733 template<
typename T1>
740 const auto end = remoteIndices_.
end();
745 int* oldNeighbours =
new int[noOldNeighbours];
746 sendBufferSizes_ =
new std::size_t[noOldNeighbours];
749 for(
auto remote = remoteIndices_.
begin(); remote != end; ++remote, ++neighbourI) {
750 oldNeighbours[neighbourI] = remote->first;
753 assert(remote->second.first==remote->second.second);
759 BoolList& added = oldMap_[remote->first];
760 auto riEnd = rList.
end();
762 for(
auto index = rList.
begin();
763 index != riEnd; ++index) {
765 index->localIndexPair().local().attribute()));
769 Iterators iterators(rList, global, added);
771 assert(checkReset(iteratorsMap_[remote->first], rList,global,added));
775 calculateMessageSizes();
778 receiveBufferSize_=1;
779 sendBuffers_ =
new char*[noOldNeighbours];
782 sendBuffers_[i] =
new char[sendBufferSizes_[i]];
783 receiveBufferSize_ =
std::max(receiveBufferSize_,
static_cast<int>(sendBufferSizes_[i]));
786 receiveBuffer_=
new char[receiveBufferSize_];
788 indexSet_.beginResize();
797 MPI_Request* requests =
new MPI_Request[noOldNeighbours];
798 MPI_Status* statuses =
new MPI_Status[noOldNeighbours];
802 packAndSend(oldNeighbours[i], sendBuffers_[i], sendBufferSizes_[i], requests[i]);
806 recvAndUnpack(numberer);
813 delete[] receiveBuffer_;
817 if(MPI_SUCCESS!=MPI_Waitall(noOldNeighbours, requests, statuses)) {
820 if(MPI_SUCCESS!=statuses[i].MPI_ERROR)
821 std::cerr<<
"Destination "<<statuses[i].MPI_SOURCE<<
" error code: "<<statuses[i].MPI_ERROR<<
std::endl;
828 delete[] sendBuffers_[i];
830 delete[] sendBuffers_;
831 delete[] sendBufferSizes_;
834 iteratorsMap_.
clear();
836 indexSet_.endResize();
838 delete[] oldNeighbours;
846 remoteIndices_.sourceSeqNo_ = remoteIndices_.destSeqNo_ = indexSet_.seqNo();
852 auto iEnd = indexSet_.end();
857 assert(checkReset());
860 MPI_Pack(&(infoSend_[destination].publish), 1, MPI_INT, buffer, bufferSize, &bpos,
863 for(
auto index = indexSet_.begin(); index != iEnd; ++index) {
865 auto iteratorsEnd = iteratorsMap_.
end();
868 for(
auto iterators = iteratorsMap_.
begin(); iteratorsEnd != iterators; ++iterators) {
869 while(iterators->second.isNotAtEnd() &&
870 iterators->second.globalIndexPair().first < index->global())
871 ++(iterators->second);
872 assert(!iterators->second.isNotAtEnd() || iterators->second.globalIndexPair().first >= index->global());
879 bool knownRemote =
false;
881 for(
auto iterators = iteratorsMap_.
begin(); iteratorsEnd != iterators; ++iterators)
884 if (iterators->second.isNotAtEnd())
886 p = iterators->
second.globalIndexPair();
889 if(iterators->second.isNotAtEnd() && iterators->second.isOld()
890 && iterators->second.globalIndexPair().first == index->global()) {
892 if(destination == iterators->first)
901 Dune::dverb<<rank_<<
": sending "<<indices<<
" for index "<<index->global()<<
" to "<<destination<<
std::endl;
908 char attr = index->local().attribute();
909 MPI_Pack(&attr, 1, MPI_CHAR, buffer, bufferSize, &bpos,
913 MPI_Pack(&indices, 1, MPI_INT, buffer, bufferSize, &bpos,
917 for(
auto iterators = iteratorsMap_.
begin(); iteratorsEnd != iterators; ++iterators)
918 if(iterators->second.isNotAtEnd() && iterators->second.isOld()
919 && iterators->second.globalIndexPair().first == index->global()) {
920 int process = iterators->first;
923 assert(pairs <= infoSend_[destination].pairs);
924 MPI_Pack(&process, 1, MPI_INT, buffer, bufferSize, &bpos,
926 char attr2 = iterators->second.remoteIndex().attribute();
928 MPI_Pack(&attr2, 1, MPI_CHAR, buffer, bufferSize, &bpos,
935 assert(published <= infoSend_[destination].publish);
939 assert(published == infoSend_[destination].publish);
940 assert(pairs == infoSend_[destination].pairs);
945 MPI_Issend(buffer, bpos, MPI_PACKED, destination, 345, remoteIndices_.
communicator(),&request);
949 inline void IndicesSyncer<T>::insertIntoRemoteIndexList(
int process,
959 typename IteratorsMap::iterator found = iteratorsMap_.
find(process);
961 if( found == iteratorsMap_.
end() ) {
963 RemoteIndexList* rlist =
new RemoteIndexList();
965 Iterators iterators = Iterators(*rlist, globalMap_[process], oldMap_[process]);
969 Iterators& iterators = found->second;
972 while(iterators.isNotAtEnd() && iterators.globalIndexPair() < globalPair) {
978 if(iterators.isAtEnd() || iterators.globalIndexPair() != globalPair) {
981 iterators.insert(RemoteIndex(
Attribute(attribute)),globalPair);
986 bool indexIsThere=
false;
987 for(Iterators tmpIterators = iterators;
988 !tmpIterators.isAtEnd() && tmpIterators.globalIndexPair() == globalPair;
991 if(tmpIterators.globalIndexPair().second == attribute) {
999 iterators.insert(RemoteIndex(
Attribute(attribute)),globalPair);
1002 template<
typename T>
1003 template<
typename T1>
1004 void IndicesSyncer<T>::recvAndUnpack(T1& numberer)
1007 auto iEnd = constIndexSet.end();
1008 auto index = constIndexSet.begin();
1012 assert(checkReset());
1017 MPI_Probe(MPI_ANY_SOURCE, 345, remoteIndices_.
communicator(), &status);
1019 int source=
status.MPI_SOURCE;
1021 MPI_Get_count(&status, MPI_PACKED, &count);
1025 if(count>receiveBufferSize_) {
1026 receiveBufferSize_=
count;
1027 delete[] receiveBuffer_;
1028 receiveBuffer_ =
new char[receiveBufferSize_];
1031 MPI_Recv(receiveBuffer_, count, MPI_PACKED, source, 345, remoteIndices_.
communicator(), &status);
1034 MPI_Unpack(receiveBuffer_, count, &bpos, &publish, 1, MPI_INT, remoteIndices_.
communicator());
1041 char sourceAttribute;
1046 MPI_Unpack(receiveBuffer_, count, &bpos, &sourceAttribute, 1, MPI_CHAR,
1048 MPI_Unpack(receiveBuffer_, count, &bpos, &pairs, 1, MPI_INT,
1053 SLList<std::pair<int,Attribute> > sourceAttributeList;
1056 bool foundSelf =
false;
1061 for(; pairs>0; --pairs) {
1065 MPI_Unpack(receiveBuffer_, count, &bpos, &process, 1, MPI_INT,
1068 MPI_Unpack(receiveBuffer_, count, &bpos, &attribute, 1, MPI_CHAR,
1071 if(process==rank_) {
1081 if(pos == iEnd || pos->global() != global) {
1083 indexSet_.add(global,
1084 ParallelLocalIndex<Attribute>(numberer(global),
1085 myAttribute,
true));
1091 bool indexIsThere =
false;
1094 for(; pos->global()==global; ++pos)
1095 if(pos->local().attribute() == myAttribute) {
1097 indexIsThere =
true;
1102 indexSet_.add(global,
1103 ParallelLocalIndex<Attribute>(numberer(global),
1104 myAttribute,
true));
1114 typedef typename SLList<std::pair<int,Attribute> >::const_iterator Iter;
1115 for(Iter i=sourceAttributeList.begin(), end=sourceAttributeList.end();
1117 insertIntoRemoteIndexList(i->first,
std::make_pair(global, myAttribute),
1122 resetIteratorsMap();
1125 template<
typename T>
1126 void IndicesSyncer<T>::resetIteratorsMap(){
1129 const auto remoteEnd = remoteIndices_.remoteIndices_.
end();
1130 auto iterators = iteratorsMap_.
begin();
1131 auto global = globalMap_.
begin();
1132 auto added = oldMap_.
begin();
1134 for(
auto remote = remoteIndices_.remoteIndices_.
begin();
1135 remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1136 iterators->second.reset(*(remote->second.first), global->second, added->second);
1140 template<
typename T>
1141 bool IndicesSyncer<T>::checkReset(
const Iterators& iterators, RemoteIndexList& rList, GlobalIndexList& gList,
1144 if(std::get<0>(iterators.iterators_) != rList.begin())
1146 if(std::get<1>(iterators.iterators_) != gList.begin())
1148 if(std::get<2>(iterators.iterators_) != bList.begin())
1154 template<
typename T>
1155 bool IndicesSyncer<T>::checkReset(){
1158 const auto remoteEnd = remoteIndices_.remoteIndices_.
end();
1159 auto iterators = iteratorsMap_.
begin();
1160 auto global = globalMap_.
begin();
1161 auto added = oldMap_.
begin();
1164 for(
auto remote = remoteIndices_.remoteIndices_.
begin();
1165 remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1166 if(!checkReset(iterators->second, *(remote->second.first), global->second,
Provides a map between global and local indices.
Classes describing a distributed indexset.
Standard Dune debug streams.
Implements a singly linked list together with the necessary iterators.
void push_back(const MemberType &item)
Add a new entry to the end of the list.
Definition sllist.hh:649
SLListIterator< T, A > iterator
The mutable iterator of the list.
Definition sllist.hh:67
iterator end()
Get an iterator pointing to the end of the list.
Definition sllist.hh:780
ModifyIterator beginModify()
Get an iterator capable of deleting and inserting elements.
Definition sllist.hh:793
SLListConstIterator< RemoteIndex, Allocator > const_iterator
The constant iterator of the list.
Definition sllist.hh:72
SLListModifyIterator< T, A > ModifyIterator
The type of the iterator capable of deletion and insertion.
Definition sllist.hh:101
iterator begin()
Get an iterator pointing to the first element in the list.
Definition sllist.hh:768
EnableIfInterOperable< T1, T2, bool >::type operator<(const RandomAccessIteratorFacade< T1, V1, R1, D > &lhs, const RandomAccessIteratorFacade< T2, V2, R2, D > &rhs)
Comparison operator.
Definition iteratorfacades.hh:635
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:235
EnableIfInterOperable< T1, T2, bool >::type operator!=(const ForwardIteratorFacade< T1, V1, R1, D > &lhs, const ForwardIteratorFacade< T2, V2, R2, D > &rhs)
Checks for inequality.
Definition iteratorfacades.hh:257
Iterators()
Default constructor.
Definition indicessyncer.hh:553
Dune::RemoteIndices< ParallelIndexSet > RemoteIndices
Type of the remote indices.
Definition indicessyncer.hh:57
bool isOld() const
Was this entry already in the remote index list before the sync process?
Definition indicessyncer.hh:590
int publish
The number of indices we publish for the other process.
Definition indicessyncer.hh:124
void repairLocalIndexPointers(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, RemoteIndices< T, A1 > &remoteIndices, const T &indexSet)
Repair the pointers to the local indices in the remote indices.
Definition indicessyncer.hh:485
bool isAtEnd() const
Are we at the end of the list?
Definition indicessyncer.hh:612
ParallelIndexSet::GlobalIndex GlobalIndex
Type of the global index used in the index set.
Definition indicessyncer.hh:49
int pairs
The number of pairs (attribute and process number) we publish to the neighbour process.
Definition indicessyncer.hh:129
Attribute & attribute() const
Iterators & operator++()
Increment all iteraors.
Definition indicessyncer.hh:558
ParallelIndexSet::LocalIndex::Attribute Attribute
Type of the attribute used in the index set.
Definition indicessyncer.hh:52
std::pair< GlobalIndex, Attribute > & globalIndexPair() const
Get the global index of the remote index at current position.
Definition indicessyncer.hh:584
IndicesSyncer(ParallelIndexSet &indexSet, RemoteIndices &remoteIndices)
Constructor.
Definition indicessyncer.hh:534
void reset(RemoteIndexList &remoteIndices, GlobalIndexList &globalIndices, BoolList &booleans)
Reset all the underlying iterators.
Definition indicessyncer.hh:596
std::size_t operator()(const GlobalIndex &global)
Provide the lcoal index, always std::numeric_limits<size_t>::max()
Definition indicessyncer.hh:143
T ParallelIndexSet
The type of the index set.
Definition indicessyncer.hh:43
bool isNotAtEnd() const
Are we not at the end of the list?
Definition indicessyncer.hh:606
TG GlobalIndex
the type of the global index. This type has to provide at least a operator< for sorting.
Definition indexset.hh:224
void storeGlobalIndicesOfRemoteIndices(std::map< int, SLList< std::pair< typename T::GlobalIndex, typename T::LocalIndex::Attribute >, A > > &globalMap, const RemoteIndices< T, A1 > &remoteIndices)
Stores the corresponding global indices of the remote index information.
Definition indicessyncer.hh:459
void sync()
Sync the index set.
Definition indicessyncer.hh:726
int seqNo() const
Get the internal sequence number.
ParallelIndexSet::IndexPair IndexPair
The type of the index pair.
Definition indicessyncer.hh:46
RemoteIndex & remoteIndex() const
Get the remote index at current position.
Definition indicessyncer.hh:577
MessageInformation()
Definition indicessyncer.hh:120
void insert(const RemoteIndex &index, const std::pair< GlobalIndex, Attribute > &global)
Insert a new remote index to the underlying remote index list.
Definition indicessyncer.hh:567
DVVerbType dvverb
stream for very verbose output.
DVerbType dverb
Singleton of verbose debug stream.
Dune namespace.
Definition alignedallocator.hh:11
static MPI_Datatype getType()
Definition mpitraits.hh:46
A pair consisting of a global and local index.
Definition indexset.hh:83
Class for recomputing missing indices of a distributed index set.
Definition indicessyncer.hh:39
An index present on the local process with an additional attribute flag.
Definition plocalindex.hh:47
The indices present on remote processes.
Definition remoteindices.hh:187
MPI_Comm communicator() const
Get the mpi communicator used.
Definition remoteindices.hh:1696
const_iterator end() const
Get an iterator over all remote index lists.
Definition remoteindices.hh:1529
int neighbours() const
Get the number of processors we share indices with.
Definition remoteindices.hh:1446
typename std::allocator_traits< A >::template rebind_alloc< RemoteIndex > Allocator
The type of the allocator for the remote index list.
Definition remoteindices.hh:235
const_iterator begin() const
Get an iterator over all remote index lists.
Definition remoteindices.hh:1522
Information about an index residing on another processor.
Definition remoteindices.hh:71
A mutable iterator for the SLList.
Definition sllist.hh:269
A single linked list.
Definition sllist.hh:42