00001
00002
00003 #ifndef DUNE_INTERFACE_HH
00004 #define DUNE_INTERFACE_HH
00005
00006 #if HAVE_MPI
00007
00008 #include "remoteindices.hh"
00009 #include <dune/common/enumset.hh>
00010
00011 namespace Dune
00012 {
00032 class InterfaceBuilder
00033 {
00034 public:
00035 class RemoteIndicesStateError : public InvalidStateException
00036 {};
00037
00038 virtual ~InterfaceBuilder()
00039 {}
00040
00041 protected:
00045 InterfaceBuilder()
00046 {}
00047
00085 template<class R, class T1, class T2, class Op, bool send>
00086 void buildInterface (const R& remoteIndices,
00087 const T1& sourceFlags, const T2& destFlags,
00088 Op& functor) const;
00089 };
00090
00098 class InterfaceInformation
00099 {
00100
00101 public:
00102
00106 size_t size() const
00107 {
00108 return size_;
00109 }
00114 std::size_t& operator[](size_t i)
00115 {
00116 assert(i<size_);
00117 return indices_[i];
00118 }
00123 std::size_t operator[](size_t i) const
00124 {
00125 assert(i<size_);
00126 return indices_[i];
00127 }
00132 void reserve(size_t size)
00133 {
00134 indices_ = new std::size_t[size];
00135 maxSize_ = size;
00136
00137 }
00141 void free()
00142 {
00143 if(indices_)
00144 delete[] indices_;
00145 maxSize_ = 0;
00146 size_=0;
00147 indices_=0;
00148 }
00152 void add(std::size_t index)
00153 {
00154 assert(size_<maxSize_);
00155 indices_[size_++]=index;
00156 }
00157
00158 InterfaceInformation()
00159 : size_(0), maxSize_(0), indices_(0)
00160 {}
00161
00162 virtual ~InterfaceInformation()
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:
00214 typedef std::map<int,std::pair<InterfaceInformation,InterfaceInformation> > InformationMap;
00215
00232 template<typename R, typename T1, typename T2>
00233 void build(const R& remoteIndices, const T1& sourceFlags,
00234 const T2& destFlags);
00235
00239 void free();
00240
00244 MPI_Comm communicator() const;
00245
00254 const InformationMap& interfaces() const;
00255
00256 Interface(MPI_Comm comm)
00257 : communicator_(comm), interfaces_()
00258 {}
00259
00260 Interface()
00261 : communicator_(MPI_COMM_NULL), interfaces_()
00262 {}
00263
00267 void print() const;
00268
00269 bool operator!=(const Interface& o) const
00270 {
00271 return ! operator==(o);
00272 }
00273
00274 bool operator==(const Interface& o) const
00275 {
00276 if(communicator_!=o.communicator_)
00277 return false;
00278 if(interfaces_.size()!=o.interfaces_.size())
00279 return false;
00280 typedef InformationMap::const_iterator MIter;
00281
00282 for(MIter m=interfaces_.begin(), om=o.interfaces_.begin();
00283 m!=interfaces_.end(); ++m, ++om)
00284 {
00285 if(om->first!=m->first)
00286 return false;
00287 if(om->second.first!=om->second.first)
00288 return false;
00289 if(om->second.second!=om->second.second)
00290 return false;
00291 }
00292 return true;
00293 }
00294
00298 virtual ~Interface();
00299
00300 void strip();
00301 protected:
00302
00311 InformationMap& interfaces();
00312
00314 MPI_Comm communicator_;
00315
00316 private:
00324 InformationMap interfaces_;
00325
00326 template<bool send>
00327 class InformationBuilder
00328 {
00329 public:
00330 InformationBuilder(InformationMap& interfaces)
00331 : interfaces_(interfaces)
00332 {}
00333
00334 void reserve(int proc, int size)
00335 {
00336 if(send)
00337 interfaces_[proc].first.reserve(size);
00338 else
00339 interfaces_[proc].second.reserve(size);
00340 }
00341 void add(int proc, std::size_t local)
00342 {
00343 if(send) {
00344 interfaces_[proc].first.add(local);
00345 }else{
00346 interfaces_[proc].second.add(local);
00347 }
00348 }
00349
00350 private:
00351 InformationMap& interfaces_;
00352 };
00353 };
00354
00355 template<class R, class T1, class T2, class Op, bool send>
00356 void InterfaceBuilder::buildInterface(const R& remoteIndices, const T1& sourceFlags, const T2& destFlags, Op& interfaceInformation) const
00357 {
00358
00359 if(!remoteIndices.isSynced())
00360 DUNE_THROW(RemoteIndicesStateError,"RemoteIndices is not in sync with the index set. Call RemoteIndices::rebuild first!");
00361
00362 typedef R RemoteIndices;
00363 typedef typename RemoteIndices::RemoteIndexMap::const_iterator const_iterator;
00364
00365 const const_iterator end=remoteIndices.end();
00366
00367 int rank;
00368
00369 MPI_Comm_rank(remoteIndices.communicator(), &rank);
00370
00371
00372 for(const_iterator process=remoteIndices.begin(); process != end; ++process) {
00373
00374 int size=0;
00375 typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
00376 const RemoteIterator remoteEnd = send ? process->second.first->end() :
00377 process->second.second->end();
00378 RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
00379
00380 while(remote!=remoteEnd) {
00381 if( send ? destFlags.contains(remote->attribute()) :
00382 sourceFlags.contains(remote->attribute())) {
00383
00384
00385 if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
00386 destFlags.contains(remote->localIndexPair().local().attribute()))
00387 ++size;
00388 }
00389 ++remote;
00390 }
00391 interfaceInformation.reserve(process->first, size);
00392 }
00393
00394
00395
00396 for(const_iterator process=remoteIndices.begin(); process != end; ++process) {
00397 typedef typename RemoteIndices::RemoteIndexList::const_iterator RemoteIterator;
00398 const RemoteIterator remoteEnd = send ? process->second.first->end() :
00399 process->second.second->end();
00400 RemoteIterator remote = send ? process->second.first->begin() : process->second.second->begin();
00401
00402 while(remote!=remoteEnd) {
00403 if( send ? destFlags.contains(remote->attribute()) :
00404 sourceFlags.contains(remote->attribute())) {
00405
00406 if( send ? sourceFlags.contains(remote->localIndexPair().local().attribute()) :
00407 destFlags.contains(remote->localIndexPair().local().attribute()))
00408 interfaceInformation.add(process->first,remote->localIndexPair().local().local());
00409 }
00410 ++remote;
00411 }
00412 }
00413 }
00414
00415 inline MPI_Comm Interface::communicator() const
00416 {
00417 return communicator_;
00418
00419 }
00420
00421
00422 inline const std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces() const
00423 {
00424 return interfaces_;
00425 }
00426
00427 inline std::map<int,std::pair<InterfaceInformation,InterfaceInformation> >& Interface::interfaces()
00428 {
00429 return interfaces_;
00430 }
00431
00432 inline void Interface::print() const
00433 {
00434 typedef InformationMap::const_iterator const_iterator;
00435 const const_iterator end=interfaces_.end();
00436 int rank;
00437 MPI_Comm_rank(communicator(), &rank);
00438
00439 for(const_iterator infoPair=interfaces_.begin(); infoPair!=end; ++infoPair) {
00440 {
00441 std::cout<<rank<<": send for process "<<infoPair->first<<": ";
00442 const InterfaceInformation& info(infoPair->second.first);
00443 for(size_t i=0; i < info.size(); i++)
00444 std::cout<<info[i]<<" ";
00445 std::cout<<std::endl;
00446 } {
00447
00448 std::cout<<rank<<": receive for process "<<infoPair->first<<": ";
00449 const InterfaceInformation& info(infoPair->second.second);
00450 for(size_t i=0; i < info.size(); i++)
00451 std::cout<<info[i]<<" ";
00452 std::cout<<std::endl;
00453 }
00454
00455 }
00456 }
00457
00458 template<typename R, typename T1, typename T2>
00459 inline void Interface::build(const R& remoteIndices, const T1& sourceFlags,
00460 const T2& destFlags)
00461 {
00462 communicator_=remoteIndices.communicator();
00463
00464 assert(interfaces_.empty());
00465
00466
00467 InformationBuilder<true> sendInformation(interfaces_);
00468 this->template buildInterface<R,T1,T2,InformationBuilder<true>,true>(remoteIndices, sourceFlags,
00469 destFlags, sendInformation);
00470
00471
00472 InformationBuilder<false> recvInformation(interfaces_);
00473 this->template buildInterface<R,T1,T2,InformationBuilder<false>,false>(remoteIndices,sourceFlags,
00474 destFlags, recvInformation);
00475 strip();
00476 }
00477 inline void Interface::strip()
00478 {
00479 typedef InformationMap::iterator const_iterator;
00480 for(const_iterator interfacePair = interfaces_.begin(); interfacePair != interfaces_.end();)
00481 if(interfacePair->second.first.size()==0 && interfacePair->second.second.size()==0) {
00482 interfacePair->second.first.free();
00483 interfacePair->second.second.free();
00484 const_iterator toerase=interfacePair++;
00485 interfaces_.erase(toerase);
00486 }else
00487 ++interfacePair;
00488 }
00489
00490 inline void Interface::free()
00491 {
00492 typedef InformationMap::iterator iterator;
00493 typedef InformationMap::const_iterator const_iterator;
00494 const const_iterator end = interfaces_.end();
00495 for(iterator interfacePair = interfaces_.begin(); interfacePair != end; ++interfacePair) {
00496 interfacePair->second.first.free();
00497 interfacePair->second.second.free();
00498 }
00499 interfaces_.clear();
00500 }
00501
00502 inline Interface::~Interface()
00503 {
00504 free();
00505 }
00507 }
00508
00509 namespace std
00510 {
00511 inline ostream& operator<<(ostream& os, const Dune::Interface& interface)
00512 {
00513 typedef Dune::Interface::InformationMap InfoMap;
00514 typedef InfoMap::const_iterator Iter;
00515 for(Iter i=interface.interfaces().begin(), end = interface.interfaces().end();
00516 i!=end; ++i)
00517 {
00518 os<<i->first<<": [ source=[";
00519 for(std::size_t j=0; j < i->second.first.size(); ++j)
00520 os<<i->second.first[j]<<" ";
00521 os<<"] size="<<i->second.first.size()<<", target=[";
00522 for(std::size_t j=0; j < i->second.second.size(); ++j)
00523 os<<i->second.second[j]<<" ";
00524 os<<"] size="<<i->second.second.size()<<"\n";
00525 }
00526 return os;
00527 }
00528 }
00529 #endif // HAVE_MPI
00530
00531 #endif