dune-common  2.2.0
interface.hh
Go to the documentation of this file.
00001 // $Id$
00002 #ifndef DUNE_INTERFACE_HH
00003 #define DUNE_INTERFACE_HH
00004 
00005 #if HAVE_MPI
00006 
00007 #include"remoteindices.hh"
00008 #include<dune/common/enumset.hh>
00009 
00010 namespace Dune
00011 {
00031   class InterfaceBuilder
00032   {
00033   public: 
00034     class RemotexIndicesStateError : public Exception
00035     {};
00036         
00037     virtual ~InterfaceBuilder()
00038     {}
00039 
00040   protected:
00044     InterfaceBuilder()
00045     {}
00046     
00084     template<class R, class T1, class T2, class Op, bool send>
00085     void buildInterface (const R& remoteIndices, 
00086                          const T1& sourceFlags, const T2& destFlags,
00087                          Op& functor) const;
00088   };
00089   
00097   class InterfaceInformation
00098   {
00099     
00100   public:
00101     
00105     size_t size() const
00106     {
00107       return size_;
00108     }
00113     std::size_t& operator[](size_t i)
00114     {
00115       assert(i<size_);
00116       return indices_[i];
00117     }
00122     std::size_t operator[](size_t i) const
00123     {
00124       assert(i<size_);
00125       return indices_[i];
00126     }
00131     void reserve(size_t size)
00132     {
00133       indices_ = new std::size_t[size];
00134       maxSize_ = size;
00135       
00136     }
00140     void free()
00141     {
00142       if(indices_)
00143         delete[] indices_;
00144       maxSize_ = 0;
00145       size_=0;
00146       indices_=0;
00147     }
00151     void add(std::size_t index)
00152     {
00153       assert(size_<maxSize_);
00154       indices_[size_++]=index;
00155     }
00156     
00157     InterfaceInformation() 
00158       : size_(0), maxSize_(0), indices_(0)
00159     {}
00160     
00161     virtual ~InterfaceInformation()
00162     {
00163     }
00164 
00165     bool operator!=(const InterfaceInformation& o) const
00166     {
00167       return !operator==(o);
00168     }
00169     
00170     bool operator==(const InterfaceInformation& o) const
00171     {
00172       if(size_!=o.size_)
00173         return false;
00174       for(std::size_t i=0; i< size_; ++i)
00175         if(indices_[i]!=o.indices_[i])
00176           return false;
00177       return true;
00178     }
00179     
00180   private:
00184     size_t size_;
00188     size_t maxSize_;
00192     std::size_t* indices_;
00193   };
00194 
00206   class Interface : public InterfaceBuilder
00207   {
00208     
00209   public:
00210     typedef InterfaceInformation Information;
00211 
00212     typedef std::map<int,std::pair<Information,Information> > InformationMap;
00213 
00230     template<typename R, typename T1, typename T2>
00231     void build(const R& remoteIndices, const T1& sourceFlags, 
00232                const T2& destFlags);
00233 
00237     void free();
00238 
00242     MPI_Comm communicator() const;
00243 
00252     const InformationMap& interfaces() const;
00253     
00254     Interface(MPI_Comm comm)
00255       : communicator_(comm), interfaces_()
00256     {}
00257   
00258     Interface()
00259       : communicator_(MPI_COMM_NULL), interfaces_()
00260     {}
00261     
00265     void print() const;
00266 
00267     bool operator!=(const Interface& o) const
00268     {
00269       return ! operator==(o);
00270     }
00271     
00272     bool operator==(const Interface& o) const
00273     {
00274       if(communicator_!=o.communicator_)
00275         return false;
00276       if(interfaces_.size()!=o.interfaces_.size())
00277         return false;
00278       typedef InformationMap::const_iterator MIter;
00279       
00280       for(MIter m=interfaces_.begin(), om=o.interfaces_.begin();
00281           m!=interfaces_.end(); ++m, ++om)
00282         {
00283           if(om->first!=m->first)
00284             return false;
00285           if(om->second.first!=om->second.first)
00286             return false;
00287           if(om->second.second!=om->second.second)
00288             return false;
00289         }
00290       return true;
00291     }
00292       
00296     virtual ~Interface();
00297 
00298     void strip();
00299   protected:
00300     
00309     InformationMap& interfaces();
00310 
00312     MPI_Comm communicator_;
00313         
00314   private:
00322     InformationMap interfaces_;
00323     
00324     template<bool send>
00325     class InformationBuilder
00326     {
00327     public:
00328       InformationBuilder(InformationMap& interfaces)
00329         : interfaces_(interfaces)
00330       {}
00331       
00332       void reserve(int proc, int size)
00333       {
00334         if(send)
00335           interfaces_[proc].first.reserve(size);
00336         else
00337           interfaces_[proc].second.reserve(size);
00338       }
00339       void add(int proc, std::size_t local)
00340       {
00341         if(send){
00342           interfaces_[proc].first.add(local);
00343         }else{
00344           interfaces_[proc].second.add(local);
00345         }
00346       }
00347       
00348     private:
00349       InformationMap& interfaces_;
00350     };
00351   };
00352   
00353   template<class R, class T1, class T2, class Op, bool send>
00354   void InterfaceBuilder::buildInterface(const R& remoteIndices, const T1& sourceFlags, const T2& destFlags, Op& interfaceInformation) const
00355   {
00356 
00357     if(!remoteIndices.isSynced())
00358       DUNE_THROW(RemotexIndicesStateError,"RemoteIndices is not in sync with the index set. Call RemoteIndices::rebuild first!");
00359     // Allocate the memory for the data type construction.
00360     typedef R RemoteIndices;
00361     typedef typename RemoteIndices::RemoteIndexMap::const_iterator const_iterator;
00362     typedef typename RemoteIndices::ParallelIndexSet::const_iterator LocalIterator;
00363 
00364     const const_iterator end=remoteIndices.end();
00365     
00366     int rank;
00367     
00368     MPI_Comm_rank(remoteIndices.communicator(), &rank);
00369     
00370     // Allocate memory for the type construction.
00371     for(const_iterator process=remoteIndices.begin(); process != end; ++process){
00372       // Messure the number of indices send to the remote process first
00373       int size=0;
00374       typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
00375       const RemoteIterator remoteEnd = send ? process->second.first->end() : 
00376         process->second.second->end();
00377       RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
00378         
00379       while(remote!=remoteEnd){
00380           if( send ?  destFlags.contains(remote->attribute()) :
00381               sourceFlags.contains(remote->attribute())){
00382 
00383               // do we send the index?
00384             if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
00385                 destFlags.contains(remote->localIndexPair().local().attribute()))
00386                 ++size;
00387           }
00388           ++remote;
00389       }
00390       interfaceInformation.reserve(process->first, size);
00391     }
00392 
00393     // compare the local and remote indices and set up the types
00394     
00395     for(const_iterator process=remoteIndices.begin(); process != end; ++process){
00396       typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
00397       const RemoteIterator remoteEnd = send ? process->second.first->end() : 
00398         process->second.second->end();
00399       RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
00400         
00401       while(remote!=remoteEnd){
00402           if( send ?  destFlags.contains(remote->attribute()) :
00403               sourceFlags.contains(remote->attribute())){
00404               // do we send the index?
00405             if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
00406                 destFlags.contains(remote->localIndexPair().local().attribute()))
00407               interfaceInformation.add(process->first,remote->localIndexPair().local().local());
00408           }
00409           ++remote;
00410       }
00411     }
00412   }
00413   
00414   inline MPI_Comm Interface::communicator() const
00415   {
00416     return communicator_;
00417     
00418   }
00419   
00420   
00421   inline const std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces() const
00422   {
00423     return interfaces_;
00424   }
00425 
00426   inline std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces()
00427   {
00428     return interfaces_;
00429   }
00430 
00431   inline void Interface::print() const
00432   {
00433     typedef InformationMap::const_iterator const_iterator;
00434     const const_iterator end=interfaces_.end();
00435     int rank;
00436     MPI_Comm_rank(communicator(), &rank);
00437     
00438     for(const_iterator infoPair=interfaces_.begin(); infoPair!=end; ++infoPair){
00439       {
00440         std::cout<<rank<<": send for process "<<infoPair->first<<": ";
00441         const InterfaceInformation& info(infoPair->second.first);
00442         for(size_t i=0; i < info.size(); i++)
00443           std::cout<<info[i]<<" ";
00444         std::cout<<std::endl;
00445       }{
00446         
00447         std::cout<<rank<<": receive for process "<<infoPair->first<<": ";
00448         const InterfaceInformation& info(infoPair->second.second);
00449         for(size_t i=0; i < info.size(); i++)
00450           std::cout<<info[i]<<" ";
00451         std::cout<<std::endl;
00452       }
00453       
00454     }
00455   }
00456   
00457   template<typename R, typename T1, typename T2>
00458   inline void Interface::build(const R& remoteIndices, const T1& sourceFlags, 
00459                           const T2& destFlags)
00460   {
00461     communicator_=remoteIndices.communicator();
00462     
00463     assert(interfaces_.empty());
00464 
00465     // Build the send interface
00466     InformationBuilder<true> sendInformation(interfaces_);
00467     this->template buildInterface<R,T1,T2,InformationBuilder<true>,true>(remoteIndices, sourceFlags, 
00468                                                               destFlags, sendInformation);
00469     
00470     // Build the receive interface
00471     InformationBuilder<false> recvInformation(interfaces_);
00472     this->template buildInterface<R,T1,T2,InformationBuilder<false>,false>(remoteIndices,sourceFlags, 
00473                                                                 destFlags, recvInformation);
00474     strip();
00475   }
00476   inline void Interface::strip()
00477   {
00478     typedef InformationMap::iterator const_iterator;
00479     for(const_iterator interfacePair = interfaces_.begin(); interfacePair != interfaces_.end();)
00480       if(interfacePair->second.first.size()==0 && interfacePair->second.second.size()==0){
00481         interfacePair->second.first.free();
00482         interfacePair->second.second.free();
00483         const_iterator toerase=interfacePair++;
00484         interfaces_.erase(toerase);
00485       }else
00486         ++interfacePair;
00487   }
00488   
00489   inline void Interface::free()
00490   {
00491     typedef InformationMap::iterator iterator;
00492     typedef InformationMap::const_iterator const_iterator;
00493     const const_iterator end = interfaces_.end();
00494     for(iterator interfacePair = interfaces_.begin(); interfacePair != end; ++interfacePair){
00495       interfacePair->second.first.free();
00496       interfacePair->second.second.free();
00497     }
00498     interfaces_.clear();
00499   }
00500 
00501   inline Interface::~Interface()
00502   {
00503     free();
00504   }
00506 }
00507 
00508 namespace std
00509 {
00510   inline ostream& operator<<(ostream& os, const Dune::Interface& interface)
00511   {
00512     typedef Dune::Interface::InformationMap InfoMap;
00513     typedef InfoMap::const_iterator Iter;
00514     for(Iter i=interface.interfaces().begin(), end = interface.interfaces().end();
00515         i!=end; ++i)
00516       {
00517         os<<i->first<<": [ source=[";
00518         for(std::size_t j=0; j < i->second.first.size(); ++j)
00519           os<<i->second.first[j]<<" ";
00520         os<<"] size="<<i->second.first.size()<<", target=[";
00521         for(std::size_t j=0; j < i->second.second.size(); ++j)
00522           os<<i->second.second[j]<<" ";
00523         os<<"] size="<<i->second.second.size()<<"\n";
00524       }
00525     return os;
00526   }
00527 }// end namespace std
00528 #endif // HAVE_MPI
00529 
00530 #endif