dune-common 2.1.1
|
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