Dune Core Modules (2.6.0)

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"
9 #include <dune/common/sllist.hh>
10 #include <dune/common/unused.hh>
11 #include <cassert>
12 #include <cmath>
13 #include <limits>
14 #include <algorithm>
15 #include <functional>
16 #include <map>
17 #include <tuple>
18 
19 #if HAVE_MPI
20 namespace Dune
21 {
38  template<typename T>
40  {
41  public:
42 
44  typedef T ParallelIndexSet;
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  {}
125  int publish;
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 std::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  ++(std::get<0>(iterators_));
576  ++(std::get<1>(iterators_));
577  ++(std::get<2>(iterators_));
578  return *this;
579  }
580 
581  template<typename T>
583  const std::pair<GlobalIndex,Attribute>& global)
584  {
585  std::get<0>(iterators_).insert(index);
586  std::get<1>(iterators_).insert(global);
587  std::get<2>(iterators_).insert(false);
588  }
589 
590  template<typename T>
591  inline typename IndicesSyncer<T>::RemoteIndex&
593  {
594  return *(std::get<0>(iterators_));
595  }
596 
597  template<typename T>
598  inline std::pair<typename IndicesSyncer<T>::GlobalIndex,typename IndicesSyncer<T>::Attribute>&
600  {
601  return *(std::get<1>(iterators_));
602  }
603 
604  template<typename T>
606  {
607  return *(std::get<2>(iterators_));
608  }
609 
610  template<typename T>
612  GlobalIndexList& globalIndices,
613  BoolList& booleans)
614  {
615  std::get<0>(iterators_) = remoteIndices.beginModify();
616  std::get<1>(iterators_) = globalIndices.beginModify();
617  std::get<2>(iterators_) = booleans.beginModify();
618  }
619 
620  template<typename T>
622  {
623  return std::get<0>(iterators_) != std::get<3>(iterators_);
624  }
625 
626  template<typename T>
628  {
629  return std::get<0>(iterators_) == std::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(std::get<0>(iterators.iterators_) != rList.begin())
1190  return false;
1191  if(std::get<1>(iterators.iterators_) != gList.begin())
1192  return false;
1193  if(std::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:71
The indices present on remote processes.
Definition: remoteindices.hh:187
MPI_Comm communicator() const
Get the mpi communicator used.
Definition: remoteindices.hh:1709
const_iterator end() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1536
int neighbours() const
Get the number of processors we share indices with.
Definition: remoteindices.hh:1453
const_iterator begin() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1529
A::template rebind< RemoteIndex >::other Allocator
The type of the allocator for the remote index list.
Definition: remoteindices.hh:235
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:307
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< T, A > 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
#define DUNE_UNUSED_PARAMETER(parm)
A macro to mark intentionally unused function parameters with.
Definition: unused.hh:25
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:255
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:629
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:233
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: alignedallocator.hh:10
Classes describing a distributed indexset.
Implements a singly linked list together with the necessary iterators.
Standard Dune debug streams.
Definition of the DUNE_UNUSED macro for the case that config.h is not available.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (Apr 26, 22:29, 2024)