Dune Core Modules (2.4.2)

indicessyncer.hh
Go to the documentation of this file.
1// -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2// vi: set et ts=4 sw=2 sts=2:
3#ifndef DUNE_INDICESSYNCER_HH
4#define DUNE_INDICESSYNCER_HH
5
6#include "indexset.hh"
7#include "remoteindices.hh"
10#include <dune/common/sllist.hh>
11#include <dune/common/unused.hh>
12#include <cassert>
13#include <cmath>
14#include <limits>
15#include <algorithm>
16#include <functional>
17#include <map>
18
19#if HAVE_MPI
20namespace Dune
21{
38 template<typename T>
40 {
41 public:
42
45
48
51
53 typedef typename ParallelIndexSet::LocalIndex::Attribute Attribute;
54
59
70 RemoteIndices& remoteIndices);
71
81 void sync();
82
93 template<typename T1>
94 void sync(T1& numberer);
95
96 private:
97
99 ParallelIndexSet& indexSet_;
100
102 RemoteIndices& remoteIndices_;
103
105 char** sendBuffers_;
106
108 char* receiveBuffer_;
109
111 std::size_t* sendBufferSizes_;
112
114 int receiveBufferSize_; // int because of MPI
115
119 struct MessageInformation
120 {
121 MessageInformation()
122 : publish(), pairs()
123 {}
130 int pairs;
131 };
132
136 class DefaultNumberer
137 {
138 public:
144 std::size_t operator()(const GlobalIndex& global)
145 {
146 DUNE_UNUSED_PARAMETER(global);
147 return std::numeric_limits<size_t>::max();
148 }
149 };
150
152 MPI_Datatype datatype_;
153
155 int rank_;
156
161 typedef SLList<std::pair<GlobalIndex,Attribute>, typename RemoteIndices::Allocator> GlobalIndexList;
162
164 typedef typename GlobalIndexList::ModifyIterator GlobalIndexModifier;
165
170 GlobalIndexIterator;
171
173 typedef std::map<int, GlobalIndexList> GlobalIndicesMap;
174
183 GlobalIndicesMap globalMap_;
184
189
193 typedef typename BoolList::iterator BoolIterator;
194
196 typedef typename BoolList::ModifyIterator BoolListModifier;
197
199 typedef std::map<int,BoolList> BoolMap;
200
205 BoolMap oldMap_;
206
208 std::map<int,MessageInformation> infoSend_;
209
211 typedef typename RemoteIndices::RemoteIndexList RemoteIndexList;
212
214 typedef typename RemoteIndexList::ModifyIterator RemoteIndexModifier;
215
218
220 typedef typename RemoteIndexList::iterator RemoteIndexIterator;
221
223 typedef typename RemoteIndexList::const_iterator ConstRemoteIndexIterator;
224
226 typedef Dune::tuple<RemoteIndexModifier,GlobalIndexModifier,BoolListModifier,
227 const ConstRemoteIndexIterator> IteratorTuple;
228
236 class Iterators
237 {
238 friend class IndicesSyncer<T>;
239 public:
249 Iterators(RemoteIndexList& remoteIndices, GlobalIndexList& globalIndices,
250 BoolList& booleans);
251
255 Iterators();
256
260 Iterators& operator++();
261
267 void insert(const RemoteIndex& index,
268 const std::pair<GlobalIndex,Attribute>& global);
269
274 RemoteIndex& remoteIndex() const;
275
280 std::pair<GlobalIndex,Attribute>& globalIndexPair() const;
281
282 Attribute& attribute() const;
283
289 bool isOld() const;
290
300 void reset(RemoteIndexList& remoteIndices, GlobalIndexList& globalIndices,
301 BoolList& booleans);
302
308 bool isNotAtEnd() const;
309
315 bool isAtEnd() const;
316
317 private:
327 IteratorTuple iterators_;
328 };
329
331 typedef std::map<int,Iterators> IteratorsMap;
332
344 IteratorsMap iteratorsMap_;
345
347 void calculateMessageSizes();
348
356 void packAndSend(int destination, char* buffer, std::size_t bufferSize, MPI_Request& req);
357
362 template<typename T1>
363 void recvAndUnpack(T1& numberer);
364
368 void registerMessageDatatype();
369
373 void insertIntoRemoteIndexList(int process,
374 const std::pair<GlobalIndex,Attribute>& global,
375 char attribute);
376
380 void resetIteratorsMap();
381
386 bool checkReset();
387
396 bool checkReset(const Iterators& iterators, RemoteIndexList& rlist, GlobalIndexList& gList,
397 BoolList& bList);
398 };
399
400 template<typename TG, typename TA>
401 bool operator<(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
402 const std::pair<TG,TA>& i2)
403 {
404 return i1.global() < i2.first ||
405 (i1.global() == i2.first && i1.local().attribute()<i2.second);
406 }
407
408 template<typename TG, typename TA>
409 bool operator<(const std::pair<TG,TA>& i1,
410 const IndexPair<TG,ParallelLocalIndex<TA> >& i2)
411 {
412 return i1.first < i2.global() ||
413 (i1.first == i2.global() && i1.second<i2.local().attribute());
414 }
415
416 template<typename TG, typename TA>
417 bool operator==(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
418 const std::pair<TG,TA>& i2)
419 {
420 return (i1.global() == i2.first && i1.local().attribute()==i2.second);
421 }
422
423 template<typename TG, typename TA>
424 bool operator!=(const IndexPair<TG,ParallelLocalIndex<TA> >& i1,
425 const std::pair<TG,TA>& i2)
426 {
427 return (i1.global() != i2.first || i1.local().attribute()!=i2.second);
428 }
429
430 template<typename TG, typename TA>
431 bool operator==(const std::pair<TG,TA>& i2,
432 const IndexPair<TG,ParallelLocalIndex<TA> >& i1)
433 {
434 return (i1.global() == i2.first && i1.local().attribute()==i2.second);
435 }
436
437 template<typename TG, typename TA>
438 bool operator!=(const std::pair<TG,TA>& i2,
439 const IndexPair<TG,ParallelLocalIndex<TA> >& i1)
440 {
441 return (i1.global() != i2.first || i1.local().attribute()!=i2.second);
442 }
443
460 template<typename T, typename A, typename A1>
461 void storeGlobalIndicesOfRemoteIndices(std::map<int,SLList<std::pair<typename T::GlobalIndex, typename T::LocalIndex::Attribute>,A> >& globalMap,
462 const RemoteIndices<T,A1>& remoteIndices)
463 {
464 typedef typename RemoteIndices<T,A1>::const_iterator RemoteIterator;
465
466 for(RemoteIterator remote = remoteIndices.begin(), end =remoteIndices.end(); remote != end; ++remote) {
467 typedef typename RemoteIndices<T,A1>::RemoteIndexList RemoteIndexList;
468 typedef typename RemoteIndexList::const_iterator RemoteIndexIterator;
470 GlobalIndexList& global = globalMap[remote->first];
471 RemoteIndexList& rList = *(remote->second.first);
472
473 for(RemoteIndexIterator index = rList.begin(), riEnd = rList.end();
474 index != riEnd; ++index) {
475 global.push_back(std::make_pair(index->localIndexPair().global(),
476 index->localIndexPair().local().attribute()));
477 }
478 }
479 }
480
489 template<typename T, typename A, typename A1>
490 inline void repairLocalIndexPointers(std::map<int,
491 SLList<std::pair<typename T::GlobalIndex,
492 typename T::LocalIndex::Attribute>,A> >& globalMap,
493 RemoteIndices<T,A1>& remoteIndices,
494 const T& indexSet)
495 {
496 typedef typename RemoteIndices<T,A1>::RemoteIndexMap::iterator RemoteIterator;
497 typedef typename RemoteIndices<T,A1>::RemoteIndexList::iterator RemoteIndexIterator;
498 typedef typename T::GlobalIndex GlobalIndex;
499 typedef typename T::LocalIndex::Attribute Attribute;
500 typedef std::pair<GlobalIndex,Attribute> GlobalIndexPair;
501 typedef SLList<GlobalIndexPair,A> GlobalIndexPairList;
502 typedef typename GlobalIndexPairList::iterator GlobalIndexIterator;
503
504 assert(globalMap.size()==static_cast<std::size_t>(remoteIndices.neighbours()));
505 // Repair pointers to index set in remote indices.
506 typename std::map<int,GlobalIndexPairList>::iterator global = globalMap.begin();
507 RemoteIterator end = remoteIndices.remoteIndices_.end();
508
509 for(RemoteIterator remote = remoteIndices.remoteIndices_.begin(); remote != end; ++remote, ++global) {
510 typedef typename T::const_iterator IndexIterator;
511
512 assert(remote->first==global->first);
513 assert(remote->second.first->size() == global->second.size());
514
515 RemoteIndexIterator riEnd = remote->second.first->end();
516 RemoteIndexIterator rIndex = remote->second.first->begin();
517 GlobalIndexIterator gIndex = global->second.begin();
518 IndexIterator index = indexSet.begin();
519
520 assert(rIndex==riEnd || gIndex != global->second.end());
521 while(rIndex != riEnd) {
522 // Search for the index in the set.
523 assert(gIndex != global->second.end());
524
525 while(!(index->global() == gIndex->first
526 && index->local().attribute() == gIndex->second)) {
527 ++index;
528 // this is only needed for ALU, where there may exist
529 // more entries with the same global index in the remote index set
530 // than in the index set
531 if (index->global() > gIndex->first) {
532 index=indexSet.begin();
533 }
534 }
535
536 assert(index != indexSet.end() && *index == *gIndex);
537
538 rIndex->localIndex_ = &(*index);
539 ++index;
540 ++rIndex;
541 ++gIndex;
542 }
543 }
544 remoteIndices.sourceSeqNo_ = remoteIndices.source_->seqNo();
545 remoteIndices.destSeqNo_ = remoteIndices.target_->seqNo();
546 }
547
548 template<typename T>
550 RemoteIndices& remoteIndices)
551 : indexSet_(indexSet), remoteIndices_(remoteIndices)
552 {
553 // index sets must match.
554 assert(remoteIndices.source_ == remoteIndices.target_);
555 assert(remoteIndices.source_ == &indexSet);
556 MPI_Comm_rank(remoteIndices_.communicator(), &rank_);
557 }
558
559 template<typename T>
561 GlobalIndexList& globalIndices,
562 BoolList& booleans)
563 : iterators_(remoteIndices.beginModify(), globalIndices.beginModify(),
564 booleans.beginModify(), remoteIndices.end())
565 { }
566
567 template<typename T>
569 : iterators_()
570 {}
571
572 template<typename T>
574 {
575 ++(get<0>(iterators_));
576 ++(get<1>(iterators_));
577 ++(get<2>(iterators_));
578 return *this;
579 }
580
581 template<typename T>
583 const std::pair<GlobalIndex,Attribute>& global)
584 {
585 get<0>(iterators_).insert(index);
586 get<1>(iterators_).insert(global);
587 get<2>(iterators_).insert(false);
588 }
589
590 template<typename T>
591 inline typename IndicesSyncer<T>::RemoteIndex&
593 {
594 return *(get<0>(iterators_));
595 }
596
597 template<typename T>
598 inline std::pair<typename IndicesSyncer<T>::GlobalIndex,typename IndicesSyncer<T>::Attribute>&
600 {
601 return *(get<1>(iterators_));
602 }
603
604 template<typename T>
606 {
607 return *(get<2>(iterators_));
608 }
609
610 template<typename T>
612 GlobalIndexList& globalIndices,
613 BoolList& booleans)
614 {
615 get<0>(iterators_) = remoteIndices.beginModify();
616 get<1>(iterators_) = globalIndices.beginModify();
617 get<2>(iterators_) = booleans.beginModify();
618 }
619
620 template<typename T>
622 {
623 return get<0>(iterators_)!=get<3>(iterators_);
624 }
625
626 template<typename T>
628 {
629 return get<0>(iterators_)==get<3>(iterators_);
630 }
631
632 template<typename T>
634 {
635 MPI_Datatype type[2] = {MPI_INT, MPI_INT};
636 int blocklength[2] = {1,1};
637 MPI_Aint displacement[2];
638 MPI_Aint base;
639
640 // Compute displacement
641 MessageInformation message;
642
643 MPI_Get_address( &(message.publish), displacement);
644 MPI_Get_address( &(message.pairs), displacement+1);
645
646 // Make the displacement relative
647 MPI_Get_address(&message, &base);
648 displacement[0] -= base;
649 displacement[1] -= base;
650
651 MPI_Type_create_struct( 2, blocklength, displacement, type, &datatype_);
652 MPI_Type_commit(&datatype_);
653 }
654
655 template<typename T>
656 void IndicesSyncer<T>::calculateMessageSizes()
657 {
658 typedef typename ParallelIndexSet::const_iterator IndexIterator;
659 typedef CollectiveIterator<T,typename RemoteIndices::Allocator> CollectiveIterator;
660
661 IndexIterator iEnd = indexSet_.end();
662 CollectiveIterator collIter = remoteIndices_.template iterator<true>();
663
664 for(IndexIterator index = indexSet_.begin(); index != iEnd; ++index) {
665 collIter.advance(index->global(), index->local().attribute());
666 if(collIter.empty())
667 break;
668 int knownRemote=0;
669
670 typedef typename CollectiveIterator::iterator ValidIterator;
671 ValidIterator end = collIter.end();
672
673 // Count the remote indices we know.
674 for(ValidIterator valid = collIter.begin(); valid != end; ++valid) {
675 ++knownRemote;
676 }
677
678 if(knownRemote>0) {
679 Dune::dverb<<rank_<<": publishing "<<knownRemote<<" for index "<<index->global()<< " for processes ";
680
681 // Update MessageInformation
682 for(ValidIterator valid = collIter.begin(); valid != end; ++valid) {
683 ++(infoSend_[valid.process()].publish);
684 (infoSend_[valid.process()].pairs) += knownRemote;
685 Dune::dverb<<valid.process()<<" ";
686 Dune::dverb<<"(publish="<<infoSend_[valid.process()].publish<<", pairs="<<infoSend_[valid.process()].pairs
687 <<") ";
688 }
689 Dune::dverb<<std::endl;
690 }
691 }
692
693 typedef typename std::map<int,MessageInformation>::const_iterator
694 MessageIterator;
695
696 const MessageIterator end = infoSend_.end();
697
698 // registerMessageDatatype();
699
700 // Now determine the buffersizes needed for each neighbour using MPI_Pack_size
701 MessageInformation dummy;
702
703 MessageIterator messageIter= infoSend_.begin();
704
705 typedef typename RemoteIndices::RemoteIndexMap::const_iterator RemoteIterator;
706 const RemoteIterator rend = remoteIndices_.end();
707 int neighbour=0;
708
709 for(RemoteIterator remote = remoteIndices_.begin(); remote != rend; ++remote, ++neighbour) {
710 MessageInformation* message;
711 MessageInformation recv;
712
713 if(messageIter != end && messageIter->first==remote->first) {
714 // We want to send message information to that process
715 message = const_cast<MessageInformation*>(&(messageIter->second));
716 ++messageIter;
717 }else
718 // We do not want to send information but the other process might.
719 message = &dummy;
720
721 sendBufferSizes_[neighbour]=0;
722 int tsize;
723 // The number of indices published
724 MPI_Pack_size(1, MPI_INT,remoteIndices_.communicator(), &tsize);
725 sendBufferSizes_[neighbour] += tsize;
726
727 for(int i=0; i < message->publish; ++i) {
728 // The global index
729 MPI_Pack_size(1, MPITraits<GlobalIndex>::getType(), remoteIndices_.communicator(), &tsize);
730 sendBufferSizes_[neighbour] += tsize;
731 // The attribute in the local index
732 MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
733 sendBufferSizes_[neighbour] += tsize;
734 // The number of corresponding remote indices
735 MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
736 sendBufferSizes_[neighbour] += tsize;
737 }
738 for(int i=0; i < message->pairs; ++i) {
739 // The process of the remote index
740 MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
741 sendBufferSizes_[neighbour] += tsize;
742 // The attribute of the remote index
743 MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
744 sendBufferSizes_[neighbour] += tsize;
745 }
746
747 Dune::dverb<<rank_<<": Buffer (neighbour="<<remote->first<<") size is "<< sendBufferSizes_[neighbour]<<" for publish="<<message->publish<<" pairs="<<message->pairs<<std::endl;
748 }
749
750 }
751
752 template<typename T>
754 {
755 DefaultNumberer numberer;
756 sync(numberer);
757 }
758
759 template<typename T>
760 template<typename T1>
761 void IndicesSyncer<T>::sync(T1& numberer)
762 {
763
764 // The pointers to the local indices in the remote indices
765 // will become invalid due to the resorting of the index set.
766 // Therefore store the corresponding global indices.
767 // Mark all indices as not added
768
769 typedef typename RemoteIndices::RemoteIndexMap::const_iterator
770 RemoteIterator;
771
772 const RemoteIterator end = remoteIndices_.end();
773
774 // Number of neighbours might change during the syncing.
775 // save the old neighbours
776 std::size_t noOldNeighbours = remoteIndices_.neighbours();
777 int* oldNeighbours = new int[noOldNeighbours];
778 sendBufferSizes_ = new std::size_t[noOldNeighbours];
779 std::size_t neighbourI = 0;
780
781 for(RemoteIterator remote = remoteIndices_.begin(); remote != end; ++remote, ++neighbourI) {
782 typedef typename RemoteIndices::RemoteIndexList::const_iterator
784
785 oldNeighbours[neighbourI] = remote->first;
786
787 // Make sure we only have one remote index list.
788 assert(remote->second.first==remote->second.second);
789
790 RemoteIndexList& rList = *(remote->second.first);
791
792 // Store the corresponding global indices.
793 GlobalIndexList& global = globalMap_[remote->first];
794 BoolList& added = oldMap_[remote->first];
795 RemoteIndexIterator riEnd = rList.end();
796
797 for(RemoteIndexIterator index = rList.begin();
798 index != riEnd; ++index) {
799 global.push_back(std::make_pair(index->localIndexPair().global(),
800 index->localIndexPair().local().attribute()));
801 added.push_back(true);
802 }
803
804 Iterators iterators(rList, global, added);
805 iteratorsMap_.insert(std::make_pair(remote->first, iterators));
806 assert(checkReset(iteratorsMap_[remote->first], rList,global,added));
807 }
808
809 // Exchange indices with each neighbour
810 calculateMessageSizes();
811
812 // Allocate the buffers
813 receiveBufferSize_=1;
814 sendBuffers_ = new char*[noOldNeighbours];
815
816 for(std::size_t i=0; i<noOldNeighbours; ++i) {
817 sendBuffers_[i] = new char[sendBufferSizes_[i]];
818 receiveBufferSize_ = std::max(receiveBufferSize_, static_cast<int>(sendBufferSizes_[i]));
819 }
820
821 receiveBuffer_=new char[receiveBufferSize_];
822
823 indexSet_.beginResize();
824
825 Dune::dverb<<rank_<<": Neighbours: ";
826
827 for(std::size_t i = 0; i<noOldNeighbours; ++i)
828 Dune::dverb<<oldNeighbours[i]<<" ";
829
830 Dune::dverb<<std::endl;
831
832 MPI_Request* requests = new MPI_Request[noOldNeighbours];
833 MPI_Status* statuses = new MPI_Status[noOldNeighbours];
834
835 // Pack Message data and start the sends
836 for(std::size_t i = 0; i<noOldNeighbours; ++i)
837 packAndSend(oldNeighbours[i], sendBuffers_[i], sendBufferSizes_[i], requests[i]);
838
839 // Probe for incoming messages, receive and unpack them
840 for(std::size_t i = 0; i<noOldNeighbours; ++i)
841 recvAndUnpack(numberer);
842 // }else{
843 // recvAndUnpack(oldNeighbours[i], numberer);
844 // packAndSend(oldNeighbours[i]);
845 // }
846 // }
847
848 delete[] receiveBuffer_;
849
850 // Wait for the completion of the sends
851 // Wait for completion of sends
852 if(MPI_SUCCESS!=MPI_Waitall(noOldNeighbours, requests, statuses)) {
853 std::cerr<<": MPI_Error occurred while sending message"<<std::endl;
854 for(std::size_t i=0; i< noOldNeighbours; i++)
855 if(MPI_SUCCESS!=statuses[i].MPI_ERROR)
856 std::cerr<<"Destination "<<statuses[i].MPI_SOURCE<<" error code: "<<statuses[i].MPI_ERROR<<std::endl;
857 }
858
859 delete[] statuses;
860 delete[] requests;
861
862 for(std::size_t i=0; i<noOldNeighbours; ++i)
863 delete[] sendBuffers_[i];
864
865 delete[] sendBuffers_;
866 delete[] sendBufferSizes_;
867
868 // No need for the iterator tuples any more
869 iteratorsMap_.clear();
870
871 indexSet_.endResize();
872
873 delete[] oldNeighbours;
874
875 repairLocalIndexPointers(globalMap_, remoteIndices_, indexSet_);
876
877 oldMap_.clear();
878 globalMap_.clear();
879
880 // update the sequence number
881 remoteIndices_.sourceSeqNo_ = remoteIndices_.destSeqNo_ = indexSet_.seqNo();
882 }
883
884 template<typename T>
885 void IndicesSyncer<T>::packAndSend(int destination, char* buffer, std::size_t bufferSize, MPI_Request& request)
886 {
887 typedef typename ParallelIndexSet::const_iterator IndexIterator;
888
889 IndexIterator iEnd = indexSet_.end();
890 int bpos = 0;
891 int published = 0;
892 int pairs = 0;
893
894 assert(checkReset());
895
896 // Pack the number of indices we publish
897 MPI_Pack(&(infoSend_[destination].publish), 1, MPI_INT, buffer, bufferSize, &bpos,
898 remoteIndices_.communicator());
899
900 for(IndexIterator index = indexSet_.begin(); index != iEnd; ++index) {
901 // Search for corresponding remote indices in all iterator tuples
902 typedef typename IteratorsMap::iterator Iterator;
903 Iterator iteratorsEnd = iteratorsMap_.end();
904
905 // advance all iterators to a position with global index >= index->global()
906 for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators) {
907 while(iterators->second.isNotAtEnd() &&
908 iterators->second.globalIndexPair().first < index->global())
909 ++(iterators->second);
910 assert(!iterators->second.isNotAtEnd() || iterators->second.globalIndexPair().first >= index->global());
911 }
912
913 // Add all remote indices positioned at global which were already present before calling sync
914 // to the message.
915 // Count how many remote indices we will send
916 int indices = 0;
917 bool knownRemote = false; // Is the remote process supposed to know this index?
918
919 for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
920 {
921 std::pair<GlobalIndex,Attribute> p;
922 if (iterators->second.isNotAtEnd())
923 {
924 p = iterators->second.globalIndexPair();
925 }
926
927 if(iterators->second.isNotAtEnd() && iterators->second.isOld()
928 && iterators->second.globalIndexPair().first == index->global()) {
929 indices++;
930 if(destination == iterators->first)
931 knownRemote = true;
932 }
933 }
934
935 if(!knownRemote)
936 // We do not need to send any indices
937 continue;
938
939 Dune::dverb<<rank_<<": sending "<<indices<<" for index "<<index->global()<<" to "<<destination<<std::endl;
940
941
942 // Pack the global index, the attribute and the number
943 MPI_Pack(const_cast<GlobalIndex*>(&(index->global())), 1, MPITraits<GlobalIndex>::getType(), buffer, bufferSize, &bpos,
944 remoteIndices_.communicator());
945
946 char attr = index->local().attribute();
947 MPI_Pack(&attr, 1, MPI_CHAR, buffer, bufferSize, &bpos,
948 remoteIndices_.communicator());
949
950 // Pack the number of remote indices we send.
951 MPI_Pack(&indices, 1, MPI_INT, buffer, bufferSize, &bpos,
952 remoteIndices_.communicator());
953
954 // Pack the information about the remote indices
955 for(Iterator iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
956 if(iterators->second.isNotAtEnd() && iterators->second.isOld()
957 && iterators->second.globalIndexPair().first == index->global()) {
958 int process = iterators->first;
959
960 ++pairs;
961 assert(pairs <= infoSend_[destination].pairs);
962 MPI_Pack(&process, 1, MPI_INT, buffer, bufferSize, &bpos,
963 remoteIndices_.communicator());
964 char attr2 = iterators->second.remoteIndex().attribute();
965
966 MPI_Pack(&attr2, 1, MPI_CHAR, buffer, bufferSize, &bpos,
967 remoteIndices_.communicator());
968 --indices;
969 }
970 assert(indices==0);
971 ++published;
972 Dune::dvverb<<" (publish="<<published<<", pairs="<<pairs<<")"<<std::endl;
973 assert(published <= infoSend_[destination].publish);
974 }
975
976 // Make sure we send all expected entries
977 assert(published == infoSend_[destination].publish);
978 assert(pairs == infoSend_[destination].pairs);
979 resetIteratorsMap();
980
981 Dune::dverb << rank_<<": Sending message of "<<bpos<<" bytes to "<<destination<<std::endl;
982
983 MPI_Issend(buffer, bpos, MPI_PACKED, destination, 345, remoteIndices_.communicator(),&request);
984 }
985
986 template<typename T>
987 inline void IndicesSyncer<T>::insertIntoRemoteIndexList(int process,
988 const std::pair<GlobalIndex,Attribute>& globalPair,
989 char attribute)
990 {
991 Dune::dverb<<"Inserting from "<<process<<" "<<globalPair.first<<", "<<
992 globalPair.second<<" "<<attribute<<std::endl;
993
994 resetIteratorsMap();
995
996 // There might be cases where there no remote indices for that process yet
997 typename IteratorsMap::iterator found = iteratorsMap_.find(process);
998
999 if( found == iteratorsMap_.end() ) {
1000 Dune::dverb<<"Discovered new neighbour "<<process<<std::endl;
1001 RemoteIndexList* rlist = new RemoteIndexList();
1002 remoteIndices_.remoteIndices_.insert(std::make_pair(process,std::make_pair(rlist,rlist)));
1003 Iterators iterators = Iterators(*rlist, globalMap_[process], oldMap_[process]);
1004 found = iteratorsMap_.insert(std::make_pair(process, iterators)).first;
1005 }
1006
1007 Iterators& iterators = found->second;
1008
1009 // Search for the remote index
1010 while(iterators.isNotAtEnd() && iterators.globalIndexPair() < globalPair) {
1011 // Increment all iterators
1012 ++iterators;
1013
1014 }
1015
1016 if(iterators.isAtEnd() || iterators.globalIndexPair() != globalPair) {
1017 // The entry is not yet known
1018 // Insert in the list and do not change the first iterator.
1019 iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
1020 return;
1021 }
1022
1023 // Global indices match
1024 bool indexIsThere=false;
1025 for(Iterators tmpIterators = iterators;
1026 !tmpIterators.isAtEnd() && tmpIterators.globalIndexPair() == globalPair;
1027 ++tmpIterators)
1028 //entry already exists with the same attribute
1029 if(tmpIterators.globalIndexPair().second == attribute) {
1030 indexIsThere=true;
1031 break;
1032 }
1033
1034 if(!indexIsThere)
1035 // The entry is not yet known
1036 // Insert in the list and do not change the first iterator.
1037 iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
1038 }
1039
1040 template<typename T>
1041 template<typename T1>
1042 void IndicesSyncer<T>::recvAndUnpack(T1& numberer)
1043 {
1044 typedef typename ParallelIndexSet::const_iterator IndexIterator;
1045
1046 IndexIterator iEnd = indexSet_.end();
1047 IndexIterator index = indexSet_.begin();
1048 int bpos = 0;
1049 int publish;
1050
1051 assert(checkReset());
1052
1053 MPI_Status status;
1054
1055 // We have to determine the message size and source before the receive
1056 MPI_Probe(MPI_ANY_SOURCE, 345, remoteIndices_.communicator(), &status);
1057
1058 int source=status.MPI_SOURCE;
1059 int count;
1060 MPI_Get_count(&status, MPI_PACKED, &count);
1061
1062 Dune::dvverb<<rank_<<": Receiving message from "<< source<<" with "<<count<<" bytes"<<std::endl;
1063
1064 if(count>receiveBufferSize_) {
1065 receiveBufferSize_=count;
1066 delete[] receiveBuffer_;
1067 receiveBuffer_ = new char[receiveBufferSize_];
1068 }
1069
1070 MPI_Recv(receiveBuffer_, count, MPI_PACKED, source, 345, remoteIndices_.communicator(), &status);
1071
1072 // How many global entries were published?
1073 MPI_Unpack(receiveBuffer_, count, &bpos, &publish, 1, MPI_INT, remoteIndices_.communicator());
1074
1075 // Now unpack the remote indices and add them.
1076 while(publish>0) {
1077
1078 // Unpack information about the local index on the source process
1079 GlobalIndex global; // global index of the current entry
1080 char sourceAttribute; // Attribute on the source process
1081 int pairs;
1082
1083 MPI_Unpack(receiveBuffer_, count, &bpos, &global, 1, MPITraits<GlobalIndex>::getType(),
1084 remoteIndices_.communicator());
1085 MPI_Unpack(receiveBuffer_, count, &bpos, &sourceAttribute, 1, MPI_CHAR,
1086 remoteIndices_.communicator());
1087 MPI_Unpack(receiveBuffer_, count, &bpos, &pairs, 1, MPI_INT,
1088 remoteIndices_.communicator());
1089
1090 // Insert the entry on the remote process to our
1091 // remote index list
1092 SLList<std::pair<int,Attribute> > sourceAttributeList;
1093 sourceAttributeList.push_back(std::make_pair(source,Attribute(sourceAttribute)));
1094#ifndef NDEBUG
1095 bool foundSelf = false;
1096#endif
1097 Attribute myAttribute=Attribute();
1098
1099 // Unpack the remote indices
1100 for(; pairs>0; --pairs) {
1101 // Unpack the process id that knows the index
1102 int process;
1103 char attribute;
1104 MPI_Unpack(receiveBuffer_, count, &bpos, &process, 1, MPI_INT,
1105 remoteIndices_.communicator());
1106 // Unpack the attribute
1107 MPI_Unpack(receiveBuffer_, count, &bpos, &attribute, 1, MPI_CHAR,
1108 remoteIndices_.communicator());
1109
1110 if(process==rank_) {
1111#ifndef NDEBUG
1112 foundSelf=true;
1113#endif
1114 myAttribute=Attribute(attribute);
1115 // Now we know the local attribute of the global index
1116 //Only add the index if it is unknown.
1117 // Do we know that global index already?
1118 IndexIterator pos = std::lower_bound(index, iEnd, IndexPair(global));
1119
1120 if(pos == iEnd || pos->global() != global) {
1121 // no entry with this global index
1122 indexSet_.add(global,
1123 ParallelLocalIndex<Attribute>(numberer(global),
1124 myAttribute, true));
1125 Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
1126 continue;
1127 }
1128
1129 // because of above the global indices match. Add only if the attribute is different
1130 bool indexIsThere = false;
1131 index=pos;
1132
1133 for(; pos->global()==global; ++pos)
1134 if(pos->local().attribute() == myAttribute) {
1135 Dune::dvverb<<"found "<<global<<" "<<myAttribute<<std::endl;
1136 indexIsThere = true;
1137 break;
1138 }
1139
1140 if(!indexIsThere) {
1141 indexSet_.add(global,
1142 ParallelLocalIndex<Attribute>(numberer(global),
1143 myAttribute, true));
1144 Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
1145 }
1146
1147 }else{
1148 sourceAttributeList.push_back(std::make_pair(process,Attribute(attribute)));
1149 }
1150 }
1151 assert(foundSelf);
1152 // Insert remote indices
1153 typedef typename SLList<std::pair<int,Attribute> >::const_iterator Iter;
1154 for(Iter i=sourceAttributeList.begin(), end=sourceAttributeList.end();
1155 i!=end; ++i)
1156 insertIntoRemoteIndexList(i->first, std::make_pair(global, myAttribute),
1157 i->second);
1158 --publish;
1159 }
1160
1161 resetIteratorsMap();
1162 }
1163
1164 template<typename T>
1165 void IndicesSyncer<T>::resetIteratorsMap(){
1166
1167 // Reset iterators in all tuples.
1168 typedef typename IteratorsMap::iterator Iterator;
1169 typedef typename RemoteIndices::RemoteIndexMap::iterator
1170 RemoteIterator;
1171 typedef typename GlobalIndicesMap::iterator GlobalIterator;
1172 typedef typename BoolMap::iterator BoolIterator;
1173
1174 const RemoteIterator remoteEnd = remoteIndices_.remoteIndices_.end();
1175 Iterator iterators = iteratorsMap_.begin();
1176 GlobalIterator global = globalMap_.begin();
1177 BoolIterator added = oldMap_.begin();
1178
1179 for(RemoteIterator remote = remoteIndices_.remoteIndices_.begin();
1180 remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1181 iterators->second.reset(*(remote->second.first), global->second, added->second);
1182 }
1183 }
1184
1185 template<typename T>
1186 bool IndicesSyncer<T>::checkReset(const Iterators& iterators, RemoteIndexList& rList, GlobalIndexList& gList,
1187 BoolList& bList){
1188
1189 if(get<0>(iterators.iterators_)!=rList.begin())
1190 return false;
1191 if(get<1>(iterators.iterators_)!=gList.begin())
1192 return false;
1193 if(get<2>(iterators.iterators_)!=bList.begin())
1194 return false;
1195 return true;
1196 }
1197
1198
1199 template<typename T>
1200 bool IndicesSyncer<T>::checkReset(){
1201
1202 // Reset iterators in all tuples.
1203 typedef typename IteratorsMap::iterator Iterator;
1204 typedef typename RemoteIndices::RemoteIndexMap::iterator
1205 RemoteIterator;
1206 typedef typename GlobalIndicesMap::iterator GlobalIterator;
1207 typedef typename BoolMap::iterator BoolIterator;
1208
1209 const RemoteIterator remoteEnd = remoteIndices_.remoteIndices_.end();
1210 Iterator iterators = iteratorsMap_.begin();
1211 GlobalIterator global = globalMap_.begin();
1212 BoolIterator added = oldMap_.begin();
1213 bool ret = true;
1214
1215 for(RemoteIterator remote = remoteIndices_.remoteIndices_.begin();
1216 remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1217 if(!checkReset(iterators->second, *(remote->second.first), global->second,
1218 added->second))
1219 ret=false;
1220 }
1221 return ret;
1222 }
1223}
1224
1225#endif
1226#endif
A constant random access iterator for the Dune::ArrayList class.
Definition: arraylist.hh:379
A pair consisting of a global and local index.
Definition: indexset.hh:84
Class for recomputing missing indices of a distributed index set.
Definition: indicessyncer.hh:40
Information about an index residing on another processor.
Definition: remoteindices.hh:66
The indices present on remote processes.
Definition: remoteindices.hh:181
MPI_Comm communicator() const
Get the mpi communicator used.
Definition: remoteindices.hh:1697
const_iterator end() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1524
int neighbours() const
Get the number of processors we share indices with.
Definition: remoteindices.hh:1441
const_iterator begin() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1517
A::template rebind< RemoteIndex >::other Allocator
The type of the allocator for the remote index list.
Definition: remoteindices.hh:229
A mutable iterator for the SLList.
Definition: sllist.hh:269
A single linked list.
Definition: sllist.hh:42
Dune::RemoteIndices< ParallelIndexSet > RemoteIndices
Type of the remote indices.
Definition: indicessyncer.hh:58
ArrayList< IndexPair, N >::const_iterator const_iterator
The constant iterator over the pairs.
Definition: indexset.hh:305
int publish
The number of indices we publish for the other process.
Definition: indicessyncer.hh:125
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:490
ParallelIndexSet::GlobalIndex GlobalIndex
Type of the global index used in the index set.
Definition: indicessyncer.hh:50
int pairs
The number of pairs (attribute and process number) we publish to the neighbour process.
Definition: indicessyncer.hh:130
ParallelIndexSet::LocalIndex::Attribute Attribute
Type of the attribute used in the index set.
Definition: indicessyncer.hh:53
IndicesSyncer(ParallelIndexSet &indexSet, RemoteIndices &remoteIndices)
Constructor.
Definition: indicessyncer.hh:549
std::size_t operator()(const GlobalIndex &global)
Provide the lcoal index, always std::numeric_limits<size_t>::max()
Definition: indicessyncer.hh:144
T ParallelIndexSet
The type of the index set.
Definition: indicessyncer.hh:44
TG GlobalIndex
the type of the global index. This type has to provide at least a operator< for sorting.
Definition: indexset.hh:225
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:461
void sync()
Sync the index set.
Definition: indicessyncer.hh:753
int seqNo() const
Get the internal sequence number.
ParallelIndexSet::IndexPair IndexPair
The type of the index pair.
Definition: indicessyncer.hh:47
void push_back(const MemberType &item)
Add a new entry to the end of the list.
Definition: sllist.hh:657
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:788
ModifyIterator beginModify()
Get an iterator capable of deleting and inserting elements.
Definition: sllist.hh:801
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:776
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:626
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:230
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:252
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:93
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:114
Provides a map between global and local indices.
Dune namespace.
Definition: alignment.hh:10
Classes describing a distributed indexset.
Implements a singly linked list together with the necessary iterators.
Standard Dune debug streams.
Fallback implementation of the std::tuple class.
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentional unused function parameters with.
Definition: unused.hh:18
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.111.3 (Dec 21, 23:30, 2024)