Dune Core Modules (2.9.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 // SPDX-FileCopyrightInfo: Copyright (C) DUNE Project contributors, see file LICENSE.md in module root
4 // SPDX-License-Identifier: LicenseRef-GPL-2.0-only-with-DUNE-exception
5 #ifndef DUNE_INDICESSYNCER_HH
6 #define DUNE_INDICESSYNCER_HH
7 
8 #include "indexset.hh"
9 #include "remoteindices.hh"
11 #include <dune/common/sllist.hh>
12 #include <cassert>
13 #include <cmath>
14 #include <limits>
15 #include <algorithm>
16 #include <functional>
17 #include <map>
18 #include <tuple>
19 
20 #if HAVE_MPI
21 namespace Dune
22 {
39  template<typename T>
41  {
42  public:
43 
45  typedef T ParallelIndexSet;
46 
49 
52 
54  typedef typename ParallelIndexSet::LocalIndex::Attribute Attribute;
55 
60 
71  RemoteIndices& remoteIndices);
72 
82  void sync();
83 
94  template<typename T1>
95  void sync(T1& numberer);
96 
97  private:
98 
100  ParallelIndexSet& indexSet_;
101 
103  RemoteIndices& remoteIndices_;
104 
106  char** sendBuffers_;
107 
109  char* receiveBuffer_;
110 
112  std::size_t* sendBufferSizes_;
113 
115  int receiveBufferSize_; // int because of MPI
116 
120  struct MessageInformation
121  {
122  MessageInformation()
123  : publish(), pairs()
124  {}
126  int publish;
131  int pairs;
132  };
133 
137  class DefaultNumberer
138  {
139  public:
145  std::size_t operator()([[maybe_unused]] const GlobalIndex& global)
146  {
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  for(auto remote = remoteIndices.begin(), end =remoteIndices.end(); remote != end; ++remote) {
465  typedef typename RemoteIndices<T,A1>::RemoteIndexList RemoteIndexList;
467  GlobalIndexList& global = globalMap[remote->first];
468  RemoteIndexList& rList = *(remote->second.first);
469 
470  for(auto index = rList.begin(), riEnd = rList.end();
471  index != riEnd; ++index) {
472  global.push_back(std::make_pair(index->localIndexPair().global(),
473  index->localIndexPair().local().attribute()));
474  }
475  }
476  }
477 
486  template<typename T, typename A, typename A1>
487  inline void repairLocalIndexPointers(std::map<int,
488  SLList<std::pair<typename T::GlobalIndex,
489  typename T::LocalIndex::Attribute>,A> >& globalMap,
490  RemoteIndices<T,A1>& remoteIndices,
491  const T& indexSet)
492  {
493  assert(globalMap.size()==static_cast<std::size_t>(remoteIndices.neighbours()));
494  // Repair pointers to index set in remote indices.
495  auto global = globalMap.begin();
496  auto end = remoteIndices.remoteIndices_.end();
497 
498  for(auto remote = remoteIndices.remoteIndices_.begin(); remote != end; ++remote, ++global) {
499  assert(remote->first==global->first);
500  assert(remote->second.first->size() == global->second.size());
501 
502  auto riEnd = remote->second.first->end();
503  auto rIndex = remote->second.first->begin();
504  auto gIndex = global->second.begin();
505  auto index = indexSet.begin();
506 
507  assert(rIndex==riEnd || gIndex != global->second.end());
508  while(rIndex != riEnd) {
509  // Search for the index in the set.
510  assert(gIndex != global->second.end());
511 
512  while(!(index->global() == gIndex->first
513  && index->local().attribute() == gIndex->second)) {
514  ++index;
515  // this is only needed for ALU, where there may exist
516  // more entries with the same global index in the remote index set
517  // than in the index set
518  if (index->global() > gIndex->first) {
519  index=indexSet.begin();
520  }
521  }
522 
523  assert(index != indexSet.end() && *index == *gIndex);
524 
525  rIndex->localIndex_ = &(*index);
526  ++index;
527  ++rIndex;
528  ++gIndex;
529  }
530  }
531  remoteIndices.sourceSeqNo_ = remoteIndices.source_->seqNo();
532  remoteIndices.destSeqNo_ = remoteIndices.target_->seqNo();
533  }
534 
535  template<typename T>
537  RemoteIndices& remoteIndices)
538  : indexSet_(indexSet), remoteIndices_(remoteIndices)
539  {
540  // index sets must match.
541  assert(remoteIndices.source_ == remoteIndices.target_);
542  assert(remoteIndices.source_ == &indexSet);
543  MPI_Comm_rank(remoteIndices_.communicator(), &rank_);
544  }
545 
546  template<typename T>
548  GlobalIndexList& globalIndices,
549  BoolList& booleans)
550  : iterators_(remoteIndices.beginModify(), globalIndices.beginModify(),
551  booleans.beginModify(), remoteIndices.end())
552  { }
553 
554  template<typename T>
556  : iterators_()
557  {}
558 
559  template<typename T>
561  {
562  ++(std::get<0>(iterators_));
563  ++(std::get<1>(iterators_));
564  ++(std::get<2>(iterators_));
565  return *this;
566  }
567 
568  template<typename T>
570  const std::pair<GlobalIndex,Attribute>& global)
571  {
572  std::get<0>(iterators_).insert(index);
573  std::get<1>(iterators_).insert(global);
574  std::get<2>(iterators_).insert(false);
575  }
576 
577  template<typename T>
578  inline typename IndicesSyncer<T>::RemoteIndex&
580  {
581  return *(std::get<0>(iterators_));
582  }
583 
584  template<typename T>
585  inline std::pair<typename IndicesSyncer<T>::GlobalIndex,typename IndicesSyncer<T>::Attribute>&
587  {
588  return *(std::get<1>(iterators_));
589  }
590 
591  template<typename T>
593  {
594  return *(std::get<2>(iterators_));
595  }
596 
597  template<typename T>
599  GlobalIndexList& globalIndices,
600  BoolList& booleans)
601  {
602  std::get<0>(iterators_) = remoteIndices.beginModify();
603  std::get<1>(iterators_) = globalIndices.beginModify();
604  std::get<2>(iterators_) = booleans.beginModify();
605  }
606 
607  template<typename T>
609  {
610  return std::get<0>(iterators_) != std::get<3>(iterators_);
611  }
612 
613  template<typename T>
615  {
616  return std::get<0>(iterators_) == std::get<3>(iterators_);
617  }
618 
619  template<typename T>
621  {
622  MPI_Datatype type[2] = {MPI_INT, MPI_INT};
623  int blocklength[2] = {1,1};
624  MPI_Aint displacement[2];
625  MPI_Aint base;
626 
627  // Compute displacement
628  MessageInformation message;
629 
630  MPI_Get_address( &(message.publish), displacement);
631  MPI_Get_address( &(message.pairs), displacement+1);
632 
633  // Make the displacement relative
634  MPI_Get_address(&message, &base);
635  displacement[0] -= base;
636  displacement[1] -= base;
637 
638  MPI_Type_create_struct( 2, blocklength, displacement, type, &datatype_);
639  MPI_Type_commit(&datatype_);
640  }
641 
642  template<typename T>
643  void IndicesSyncer<T>::calculateMessageSizes()
644  {
645  auto iEnd = indexSet_.end();
646  auto collIter = remoteIndices_.template iterator<true>();
647 
648  for(auto index = indexSet_.begin(); index != iEnd; ++index) {
649  collIter.advance(index->global(), index->local().attribute());
650  if(collIter.empty())
651  break;
652  int knownRemote=0;
653  auto end = collIter.end();
654 
655  // Count the remote indices we know.
656  for(auto valid = collIter.begin(); valid != end; ++valid) {
657  ++knownRemote;
658  }
659 
660  if(knownRemote>0) {
661  Dune::dverb<<rank_<<": publishing "<<knownRemote<<" for index "<<index->global()<< " for processes ";
662 
663  // Update MessageInformation
664  for(auto valid = collIter.begin(); valid != end; ++valid) {
665  ++(infoSend_[valid.process()].publish);
666  (infoSend_[valid.process()].pairs) += knownRemote;
667  Dune::dverb<<valid.process()<<" ";
668  Dune::dverb<<"(publish="<<infoSend_[valid.process()].publish<<", pairs="<<infoSend_[valid.process()].pairs
669  <<") ";
670  }
671  Dune::dverb<<std::endl;
672  }
673  }
674 
675  const auto end = infoSend_.end();
676 
677  // Now determine the buffersizes needed for each neighbour using MPI_Pack_size
678  MessageInformation dummy;
679 
680  auto messageIter= infoSend_.begin();
681  const auto rend = remoteIndices_.end();
682  int neighbour=0;
683 
684  for(auto remote = remoteIndices_.begin(); remote != rend; ++remote, ++neighbour) {
685  MessageInformation* message;
686  MessageInformation recv;
687 
688  if(messageIter != end && messageIter->first==remote->first) {
689  // We want to send message information to that process
690  message = const_cast<MessageInformation*>(&(messageIter->second));
691  ++messageIter;
692  }else
693  // We do not want to send information but the other process might.
694  message = &dummy;
695 
696  sendBufferSizes_[neighbour]=0;
697  int tsize;
698  // The number of indices published
699  MPI_Pack_size(1, MPI_INT,remoteIndices_.communicator(), &tsize);
700  sendBufferSizes_[neighbour] += tsize;
701 
702  for(int i=0; i < message->publish; ++i) {
703  // The global index
704  MPI_Pack_size(1, MPITraits<GlobalIndex>::getType(), remoteIndices_.communicator(), &tsize);
705  sendBufferSizes_[neighbour] += tsize;
706  // The attribute in the local index
707  MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
708  sendBufferSizes_[neighbour] += tsize;
709  // The number of corresponding remote indices
710  MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
711  sendBufferSizes_[neighbour] += tsize;
712  }
713  for(int i=0; i < message->pairs; ++i) {
714  // The process of the remote index
715  MPI_Pack_size(1, MPI_INT, remoteIndices_.communicator(), &tsize);
716  sendBufferSizes_[neighbour] += tsize;
717  // The attribute of the remote index
718  MPI_Pack_size(1, MPI_CHAR, remoteIndices_.communicator(), &tsize);
719  sendBufferSizes_[neighbour] += tsize;
720  }
721 
722  Dune::dverb<<rank_<<": Buffer (neighbour="<<remote->first<<") size is "<< sendBufferSizes_[neighbour]<<" for publish="<<message->publish<<" pairs="<<message->pairs<<std::endl;
723  }
724 
725  }
726 
727  template<typename T>
729  {
730  DefaultNumberer numberer;
731  sync(numberer);
732  }
733 
734  template<typename T>
735  template<typename T1>
736  void IndicesSyncer<T>::sync(T1& numberer)
737  {
738  // The pointers to the local indices in the remote indices
739  // will become invalid due to the resorting of the index set.
740  // Therefore store the corresponding global indices.
741  // Mark all indices as not added
742  const auto end = remoteIndices_.end();
743 
744  // Number of neighbours might change during the syncing.
745  // save the old neighbours
746  std::size_t noOldNeighbours = remoteIndices_.neighbours();
747  int* oldNeighbours = new int[noOldNeighbours];
748  sendBufferSizes_ = new std::size_t[noOldNeighbours];
749  std::size_t neighbourI = 0;
750 
751  for(auto remote = remoteIndices_.begin(); remote != end; ++remote, ++neighbourI) {
752  oldNeighbours[neighbourI] = remote->first;
753 
754  // Make sure we only have one remote index list.
755  assert(remote->second.first==remote->second.second);
756 
757  RemoteIndexList& rList = *(remote->second.first);
758 
759  // Store the corresponding global indices.
760  GlobalIndexList& global = globalMap_[remote->first];
761  BoolList& added = oldMap_[remote->first];
762  auto riEnd = rList.end();
763 
764  for(auto index = rList.begin();
765  index != riEnd; ++index) {
766  global.push_back(std::make_pair(index->localIndexPair().global(),
767  index->localIndexPair().local().attribute()));
768  added.push_back(true);
769  }
770 
771  Iterators iterators(rList, global, added);
772  iteratorsMap_.insert(std::make_pair(remote->first, iterators));
773  assert(checkReset(iteratorsMap_[remote->first], rList,global,added));
774  }
775 
776  // Exchange indices with each neighbour
777  calculateMessageSizes();
778 
779  // Allocate the buffers
780  receiveBufferSize_=1;
781  sendBuffers_ = new char*[noOldNeighbours];
782 
783  for(std::size_t i=0; i<noOldNeighbours; ++i) {
784  sendBuffers_[i] = new char[sendBufferSizes_[i]];
785  receiveBufferSize_ = std::max(receiveBufferSize_, static_cast<int>(sendBufferSizes_[i]));
786  }
787 
788  receiveBuffer_=new char[receiveBufferSize_];
789 
790  indexSet_.beginResize();
791 
792  Dune::dverb<<rank_<<": Neighbours: ";
793 
794  for(std::size_t i = 0; i<noOldNeighbours; ++i)
795  Dune::dverb<<oldNeighbours[i]<<" ";
796 
797  Dune::dverb<<std::endl;
798 
799  MPI_Request* requests = new MPI_Request[noOldNeighbours];
800  MPI_Status* statuses = new MPI_Status[noOldNeighbours];
801 
802  // Pack Message data and start the sends
803  for(std::size_t i = 0; i<noOldNeighbours; ++i)
804  packAndSend(oldNeighbours[i], sendBuffers_[i], sendBufferSizes_[i], requests[i]);
805 
806  // Probe for incoming messages, receive and unpack them
807  for(std::size_t i = 0; i<noOldNeighbours; ++i)
808  recvAndUnpack(numberer);
809  // }else{
810  // recvAndUnpack(oldNeighbours[i], numberer);
811  // packAndSend(oldNeighbours[i]);
812  // }
813  // }
814 
815  delete[] receiveBuffer_;
816 
817  // Wait for the completion of the sends
818  // Wait for completion of sends
819  if(MPI_SUCCESS!=MPI_Waitall(noOldNeighbours, requests, statuses)) {
820  std::cerr<<": MPI_Error occurred while sending message"<<std::endl;
821  for(std::size_t i=0; i< noOldNeighbours; i++)
822  if(MPI_SUCCESS!=statuses[i].MPI_ERROR)
823  std::cerr<<"Destination "<<statuses[i].MPI_SOURCE<<" error code: "<<statuses[i].MPI_ERROR<<std::endl;
824  }
825 
826  delete[] statuses;
827  delete[] requests;
828 
829  for(std::size_t i=0; i<noOldNeighbours; ++i)
830  delete[] sendBuffers_[i];
831 
832  delete[] sendBuffers_;
833  delete[] sendBufferSizes_;
834 
835  // No need for the iterator tuples any more
836  iteratorsMap_.clear();
837 
838  indexSet_.endResize();
839 
840  delete[] oldNeighbours;
841 
842  repairLocalIndexPointers(globalMap_, remoteIndices_, indexSet_);
843 
844  oldMap_.clear();
845  globalMap_.clear();
846 
847  // update the sequence number
848  remoteIndices_.sourceSeqNo_ = remoteIndices_.destSeqNo_ = indexSet_.seqNo();
849  }
850 
851  template<typename T>
852  void IndicesSyncer<T>::packAndSend(int destination, char* buffer, std::size_t bufferSize, MPI_Request& request)
853  {
854  auto iEnd = indexSet_.end();
855  int bpos = 0;
856  int published = 0;
857  int pairs = 0;
858 
859  assert(checkReset());
860 
861  // Pack the number of indices we publish
862  MPI_Pack(&(infoSend_[destination].publish), 1, MPI_INT, buffer, bufferSize, &bpos,
863  remoteIndices_.communicator());
864 
865  for(auto index = indexSet_.begin(); index != iEnd; ++index) {
866  // Search for corresponding remote indices in all iterator tuples
867  auto iteratorsEnd = iteratorsMap_.end();
868 
869  // advance all iterators to a position with global index >= index->global()
870  for(auto iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators) {
871  while(iterators->second.isNotAtEnd() &&
872  iterators->second.globalIndexPair().first < index->global())
873  ++(iterators->second);
874  assert(!iterators->second.isNotAtEnd() || iterators->second.globalIndexPair().first >= index->global());
875  }
876 
877  // Add all remote indices positioned at global which were already present before calling sync
878  // to the message.
879  // Count how many remote indices we will send
880  int indices = 0;
881  bool knownRemote = false; // Is the remote process supposed to know this index?
882 
883  for(auto iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
884  {
885  std::pair<GlobalIndex,Attribute> p;
886  if (iterators->second.isNotAtEnd())
887  {
888  p = iterators->second.globalIndexPair();
889  }
890 
891  if(iterators->second.isNotAtEnd() && iterators->second.isOld()
892  && iterators->second.globalIndexPair().first == index->global()) {
893  indices++;
894  if(destination == iterators->first)
895  knownRemote = true;
896  }
897  }
898 
899  if(!knownRemote)
900  // We do not need to send any indices
901  continue;
902 
903  Dune::dverb<<rank_<<": sending "<<indices<<" for index "<<index->global()<<" to "<<destination<<std::endl;
904 
905 
906  // Pack the global index, the attribute and the number
907  MPI_Pack(const_cast<GlobalIndex*>(&(index->global())), 1, MPITraits<GlobalIndex>::getType(), buffer, bufferSize, &bpos,
908  remoteIndices_.communicator());
909 
910  char attr = index->local().attribute();
911  MPI_Pack(&attr, 1, MPI_CHAR, buffer, bufferSize, &bpos,
912  remoteIndices_.communicator());
913 
914  // Pack the number of remote indices we send.
915  MPI_Pack(&indices, 1, MPI_INT, buffer, bufferSize, &bpos,
916  remoteIndices_.communicator());
917 
918  // Pack the information about the remote indices
919  for(auto iterators = iteratorsMap_.begin(); iteratorsEnd != iterators; ++iterators)
920  if(iterators->second.isNotAtEnd() && iterators->second.isOld()
921  && iterators->second.globalIndexPair().first == index->global()) {
922  int process = iterators->first;
923 
924  ++pairs;
925  assert(pairs <= infoSend_[destination].pairs);
926  MPI_Pack(&process, 1, MPI_INT, buffer, bufferSize, &bpos,
927  remoteIndices_.communicator());
928  char attr2 = iterators->second.remoteIndex().attribute();
929 
930  MPI_Pack(&attr2, 1, MPI_CHAR, buffer, bufferSize, &bpos,
931  remoteIndices_.communicator());
932  --indices;
933  }
934  assert(indices==0);
935  ++published;
936  Dune::dvverb<<" (publish="<<published<<", pairs="<<pairs<<")"<<std::endl;
937  assert(published <= infoSend_[destination].publish);
938  }
939 
940  // Make sure we send all expected entries
941  assert(published == infoSend_[destination].publish);
942  assert(pairs == infoSend_[destination].pairs);
943  resetIteratorsMap();
944 
945  Dune::dverb << rank_<<": Sending message of "<<bpos<<" bytes to "<<destination<<std::endl;
946 
947  MPI_Issend(buffer, bpos, MPI_PACKED, destination, 345, remoteIndices_.communicator(),&request);
948  }
949 
950  template<typename T>
951  inline void IndicesSyncer<T>::insertIntoRemoteIndexList(int process,
952  const std::pair<GlobalIndex,Attribute>& globalPair,
953  char attribute)
954  {
955  Dune::dverb<<"Inserting from "<<process<<" "<<globalPair.first<<", "<<
956  globalPair.second<<" "<<attribute<<std::endl;
957 
958  resetIteratorsMap();
959 
960  // There might be cases where there no remote indices for that process yet
961  typename IteratorsMap::iterator found = iteratorsMap_.find(process);
962 
963  if( found == iteratorsMap_.end() ) {
964  Dune::dverb<<"Discovered new neighbour "<<process<<std::endl;
965  RemoteIndexList* rlist = new RemoteIndexList();
966  remoteIndices_.remoteIndices_.insert(std::make_pair(process,std::make_pair(rlist,rlist)));
967  Iterators iterators = Iterators(*rlist, globalMap_[process], oldMap_[process]);
968  found = iteratorsMap_.insert(std::make_pair(process, iterators)).first;
969  }
970 
971  Iterators& iterators = found->second;
972 
973  // Search for the remote index
974  while(iterators.isNotAtEnd() && iterators.globalIndexPair() < globalPair) {
975  // Increment all iterators
976  ++iterators;
977 
978  }
979 
980  if(iterators.isAtEnd() || iterators.globalIndexPair() != globalPair) {
981  // The entry is not yet known
982  // Insert in the list and do not change the first iterator.
983  iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
984  return;
985  }
986 
987  // Global indices match
988  bool indexIsThere=false;
989  for(Iterators tmpIterators = iterators;
990  !tmpIterators.isAtEnd() && tmpIterators.globalIndexPair() == globalPair;
991  ++tmpIterators)
992  //entry already exists with the same attribute
993  if(tmpIterators.globalIndexPair().second == attribute) {
994  indexIsThere=true;
995  break;
996  }
997 
998  if(!indexIsThere)
999  // The entry is not yet known
1000  // Insert in the list and do not change the first iterator.
1001  iterators.insert(RemoteIndex(Attribute(attribute)),globalPair);
1002  }
1003 
1004  template<typename T>
1005  template<typename T1>
1006  void IndicesSyncer<T>::recvAndUnpack(T1& numberer)
1007  {
1008  const ParallelIndexSet& constIndexSet = indexSet_;
1009  auto iEnd = constIndexSet.end();
1010  auto index = constIndexSet.begin();
1011  int bpos = 0;
1012  int publish;
1013 
1014  assert(checkReset());
1015 
1016  MPI_Status status;
1017 
1018  // We have to determine the message size and source before the receive
1019  MPI_Probe(MPI_ANY_SOURCE, 345, remoteIndices_.communicator(), &status);
1020 
1021  int source=status.MPI_SOURCE;
1022  int count;
1023  MPI_Get_count(&status, MPI_PACKED, &count);
1024 
1025  Dune::dvverb<<rank_<<": Receiving message from "<< source<<" with "<<count<<" bytes"<<std::endl;
1026 
1027  if(count>receiveBufferSize_) {
1028  receiveBufferSize_=count;
1029  delete[] receiveBuffer_;
1030  receiveBuffer_ = new char[receiveBufferSize_];
1031  }
1032 
1033  MPI_Recv(receiveBuffer_, count, MPI_PACKED, source, 345, remoteIndices_.communicator(), &status);
1034 
1035  // How many global entries were published?
1036  MPI_Unpack(receiveBuffer_, count, &bpos, &publish, 1, MPI_INT, remoteIndices_.communicator());
1037 
1038  // Now unpack the remote indices and add them.
1039  while(publish>0) {
1040 
1041  // Unpack information about the local index on the source process
1042  GlobalIndex global; // global index of the current entry
1043  char sourceAttribute; // Attribute on the source process
1044  int pairs;
1045 
1046  MPI_Unpack(receiveBuffer_, count, &bpos, &global, 1, MPITraits<GlobalIndex>::getType(),
1047  remoteIndices_.communicator());
1048  MPI_Unpack(receiveBuffer_, count, &bpos, &sourceAttribute, 1, MPI_CHAR,
1049  remoteIndices_.communicator());
1050  MPI_Unpack(receiveBuffer_, count, &bpos, &pairs, 1, MPI_INT,
1051  remoteIndices_.communicator());
1052 
1053  // Insert the entry on the remote process to our
1054  // remote index list
1055  SLList<std::pair<int,Attribute> > sourceAttributeList;
1056  sourceAttributeList.push_back(std::make_pair(source,Attribute(sourceAttribute)));
1057 #ifndef NDEBUG
1058  bool foundSelf = false;
1059 #endif
1060  Attribute myAttribute=Attribute();
1061 
1062  // Unpack the remote indices
1063  for(; pairs>0; --pairs) {
1064  // Unpack the process id that knows the index
1065  int process;
1066  char attribute;
1067  MPI_Unpack(receiveBuffer_, count, &bpos, &process, 1, MPI_INT,
1068  remoteIndices_.communicator());
1069  // Unpack the attribute
1070  MPI_Unpack(receiveBuffer_, count, &bpos, &attribute, 1, MPI_CHAR,
1071  remoteIndices_.communicator());
1072 
1073  if(process==rank_) {
1074 #ifndef NDEBUG
1075  foundSelf=true;
1076 #endif
1077  myAttribute=Attribute(attribute);
1078  // Now we know the local attribute of the global index
1079  //Only add the index if it is unknown.
1080  // Do we know that global index already?
1081  auto pos = std::lower_bound(index, iEnd, IndexPair(global));
1082 
1083  if(pos == iEnd || pos->global() != global) {
1084  // no entry with this global index
1085  indexSet_.add(global,
1086  ParallelLocalIndex<Attribute>(numberer(global),
1087  myAttribute, true));
1088  Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
1089  continue;
1090  }
1091 
1092  // because of above the global indices match. Add only if the attribute is different
1093  bool indexIsThere = false;
1094  index=pos;
1095 
1096  for(; pos->global()==global; ++pos)
1097  if(pos->local().attribute() == myAttribute) {
1098  Dune::dvverb<<"found "<<global<<" "<<myAttribute<<std::endl;
1099  indexIsThere = true;
1100  break;
1101  }
1102 
1103  if(!indexIsThere) {
1104  indexSet_.add(global,
1105  ParallelLocalIndex<Attribute>(numberer(global),
1106  myAttribute, true));
1107  Dune::dvverb << "Adding "<<global<<" "<<myAttribute<<std::endl;
1108  }
1109 
1110  }else{
1111  sourceAttributeList.push_back(std::make_pair(process,Attribute(attribute)));
1112  }
1113  }
1114  assert(foundSelf);
1115  // Insert remote indices
1116  typedef typename SLList<std::pair<int,Attribute> >::const_iterator Iter;
1117  for(Iter i=sourceAttributeList.begin(), end=sourceAttributeList.end();
1118  i!=end; ++i)
1119  insertIntoRemoteIndexList(i->first, std::make_pair(global, myAttribute),
1120  i->second);
1121  --publish;
1122  }
1123 
1124  resetIteratorsMap();
1125  }
1126 
1127  template<typename T>
1128  void IndicesSyncer<T>::resetIteratorsMap(){
1129 
1130  // Reset iterators in all tuples.
1131  const auto remoteEnd = remoteIndices_.remoteIndices_.end();
1132  auto iterators = iteratorsMap_.begin();
1133  auto global = globalMap_.begin();
1134  auto added = oldMap_.begin();
1135 
1136  for(auto remote = remoteIndices_.remoteIndices_.begin();
1137  remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1138  iterators->second.reset(*(remote->second.first), global->second, added->second);
1139  }
1140  }
1141 
1142  template<typename T>
1143  bool IndicesSyncer<T>::checkReset(const Iterators& iterators, RemoteIndexList& rList, GlobalIndexList& gList,
1144  BoolList& bList){
1145 
1146  if(std::get<0>(iterators.iterators_) != rList.begin())
1147  return false;
1148  if(std::get<1>(iterators.iterators_) != gList.begin())
1149  return false;
1150  if(std::get<2>(iterators.iterators_) != bList.begin())
1151  return false;
1152  return true;
1153  }
1154 
1155 
1156  template<typename T>
1157  bool IndicesSyncer<T>::checkReset(){
1158 
1159  // Reset iterators in all tuples.
1160  const auto remoteEnd = remoteIndices_.remoteIndices_.end();
1161  auto iterators = iteratorsMap_.begin();
1162  auto global = globalMap_.begin();
1163  auto added = oldMap_.begin();
1164  bool ret = true;
1165 
1166  for(auto remote = remoteIndices_.remoteIndices_.begin();
1167  remote != remoteEnd; ++remote, ++global, ++added, ++iterators) {
1168  if(!checkReset(iterators->second, *(remote->second.first), global->second,
1169  added->second))
1170  ret=false;
1171  }
1172  return ret;
1173  }
1174 }
1175 
1176 #endif
1177 #endif
A pair consisting of a global and local index.
Definition: indexset.hh:85
Class for recomputing missing indices of a distributed index set.
Definition: indicessyncer.hh:41
Information about an index residing on another processor.
Definition: remoteindices.hh:73
The indices present on remote processes.
Definition: remoteindices.hh:189
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:237
const_iterator begin() const
Get an iterator over all remote index lists.
Definition: remoteindices.hh:1522
A mutable iterator for the SLList.
Definition: sllist.hh:271
A single linked list.
Definition: sllist.hh:44
std::size_t operator()([[maybe_unused]] const GlobalIndex &global)
Provide the local index, always std::numeric_limits<size_t>::max()
Definition: indicessyncer.hh:145
Dune::RemoteIndices< ParallelIndexSet > RemoteIndices
Type of the remote indices.
Definition: indicessyncer.hh:59
int publish
The number of indices we publish for the other process.
Definition: indicessyncer.hh:126
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:487
ParallelIndexSet::GlobalIndex GlobalIndex
Type of the global index used in the index set.
Definition: indicessyncer.hh:51
int pairs
The number of pairs (attribute and process number) we publish to the neighbour process.
Definition: indicessyncer.hh:131
ParallelIndexSet::LocalIndex::Attribute Attribute
Type of the attribute used in the index set.
Definition: indicessyncer.hh:54
IndicesSyncer(ParallelIndexSet &indexSet, RemoteIndices &remoteIndices)
Constructor.
Definition: indicessyncer.hh:536
T ParallelIndexSet
The type of the index set.
Definition: indicessyncer.hh:45
TG GlobalIndex
the type of the global index. This type has to provide at least a operator< for sorting.
Definition: indexset.hh:226
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:728
int seqNo() const
Get the internal sequence number.
ParallelIndexSet::IndexPair IndexPair
The type of the index pair.
Definition: indicessyncer.hh:48
void push_back(const MemberType &item)
Add a new entry to the end of the list.
Definition: sllist.hh:643
SLListIterator< T, A > iterator
The mutable iterator of the list.
Definition: sllist.hh:69
iterator end()
Get an iterator pointing to the end of the list.
Definition: sllist.hh:774
ModifyIterator beginModify()
Get an iterator capable of deleting and inserting elements.
Definition: sllist.hh:787
SLListConstIterator< T, A > const_iterator
The constant iterator of the list.
Definition: sllist.hh:74
SLListModifyIterator< T, A > ModifyIterator
The type of the iterator capable of deletion and insertion.
Definition: sllist.hh:103
iterator begin()
Get an iterator pointing to the first element in the list.
Definition: sllist.hh:762
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:259
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:637
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:237
auto max(ADLTag< 0 >, const V &v1, const V &v2)
implements binary Simd::max()
Definition: defaults.hh:81
DVVerbType dvverb(std::cout)
stream for very verbose output.
Definition: stdstreams.hh:95
DVerbType dverb(std::cout)
Singleton of verbose debug stream.
Definition: stdstreams.hh:116
Dune namespace.
Definition: alignedallocator.hh:13
Classes describing a distributed indexset.
Implements a singly linked list together with the necessary iterators.
Standard Dune debug streams.
Creative Commons License   |  Legal Statements / Impressum  |  Hosted by TU Dresden  |  generated with Hugo v0.80.0 (May 4, 22:30, 2024)