Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

space/domainDecomp.hh
Go to the documentation of this file.
00001 
00004 #ifndef spcDomainDecomp_hh
00005 #define spcDomainDecomp_hh
00006 
00007 #include "basics/debug.hh"
00008 #include "geometry/boundaryConditions.hh"
00009 #include "geometry/cellConditions.hh"
00010 #include "geometry/mesh.hh"
00011 #include "space/space.hh"
00012 #include "space/spaceSet.hh"
00013 #include "toolbox/hashMap.hh"
00014 #include "toolbox/scannerConnectors.hh"
00015 #include "toolbox/sequence.hh"
00016 #include "toolbox/set.hh"
00017 
00018 #define DDSpaceConstr_D 0
00019 #define DDSpaceDestr_D 0
00020 #define DDSpaceRebuild_D 0
00021 #define DDSpaceGetIndices_D 0
00022 #define DDSpaceInfoIndices_D 0
00023 
00024 namespace concepts {
00025 
00026   // *************************************************************** DDSpace **
00027 
00028   template<class F>
00029   class DDSpace : public Space<F> {
00030   public:
00032     DDSpace(uint domains = 0) : domains_(domains) {}
00033     virtual ~DDSpace() {}
00035     const uint domains() const { return domains_; }
00037     virtual const Space<F>& space(uint i) const = 0;
00039     virtual const Set<IndexRange> indicesI(uint i) const = 0;
00041 //     virtual const Sequence<Set<IndexRange> >& indicesI() const {
00042 //       return indicesI_; }
00044     virtual const Set<IndexRange> indicesB(uint i) const = 0;
00046 //     virtual const Sequence<Set<IndexRange> >& indicesB() const { 
00047 //       return indicesB_; }
00048   protected:
00049     virtual std::ostream& info(std::ostream& os) const;
00050 
00052     uint domains_;
00054     Sequence<Set<IndexRange> > indicesI_, indicesB_;
00055   };
00056 
00057   template<class F>
00058   std::ostream& DDSpace<F>::info(std::ostream& os) const {
00059     return os << "DDSpace(" << domains_ << " domains)";
00060   }
00061 
00062   // ********************************************************** DomainDecomp **
00063 
00069   template<class F>
00070   class DomainDecomp : public DDSpace<typename F::t_type>, public Subspace {
00071   public:
00076     typedef concepts::Element<typename F::t_type> Element;
00077     typedef concepts::Scan<Element> Scan;
00078 
00090     template<class G>
00091     DomainDecomp(G& prebuild, Sequence<Set<uint> > domains,
00092                  BoundaryConditions* bc = 0, CellConditions* cc = 0,
00093                  uint spcNo = 0, uint* offset = 0);
00094     virtual ~DomainDecomp();
00095 
00097     void rebuild();
00105     bool available() const;
00106 
00107     inline virtual uint dim() const;
00108     inline virtual uint nelm() const;
00109     inline virtual Scan* scan() const;
00110 //     inline Scan* scan();
00111 
00113     virtual uint& lastIdx();
00115     virtual uint offset() const;
00117     virtual const F& space(uint i) const;
00118     F& space(uint i);
00120     virtual const Set<IndexRange> indicesI(uint i) const;
00121 //     const Sequence<Set<IndexRange> >& indicesI() const { return indicesI_; }
00123     virtual const Set<IndexRange> indicesB(uint i) const;
00124 //     const Sequence<Set<IndexRange> >& indicesB() const { return indicesB_; }
00125   protected:
00126     virtual std::ostream& info(std::ostream& os) const;
00127   private:
00132     uint spcNo_;
00134     Sequence<F*> spaces_;
00136     Array<uint> spcBuild_;
00138     Sequence<CellConditions> cc_;
00139 
00141     HashMap<uint> attrToDomain_;
00142 
00148     concepts::Joiner<Element*, 1>* elm_;
00150     uint nelm_;
00151 
00152     uint idx_;
00153 
00154     template<class G, class H>
00155     void getIndices_(const G& prebuild, const H& cntr,
00156                      Set<IndexRange>& indices);
00157   };
00158 
00159   template<class F>
00160   template<class G>
00161   DomainDecomp<F>::DomainDecomp(G& prebuild, Sequence<Set<uint> > domains,
00162                                 BoundaryConditions* bc, CellConditions* cc,
00163                                 uint spcNo, uint* offset) : 
00164     DDSpace<typename F::t_type>(), spcNo_(spcNo), spcBuild_(0),
00165     elm_(0), nelm_(0) {
00166     // collect all attributes of coarse mesh
00167     Set<uint> attributes, tmp;
00168     std::auto_ptr<concepts::Scan2> sc(prebuild.mesh().scan());
00169     while (*sc) {
00170       const Attribute& attr = (*sc)++.connector().attrib();
00171       if (!cc || ((*cc)(attr).type() != CellCondition::INACTIVE))
00172         attributes.insert(attr);
00173     }
00174     tmp = attributes;
00175     DEBUGL(DDSpaceConstr_D, "attributes in mesh = " << attributes);
00176 
00177 
00178     // collect all attributes and delete empty domains
00179     Sequence<Set<uint> >::iterator i = domains.begin();
00180     for (; i != domains.end(); ) {
00181       // set difference with valid attributes
00182       Set<uint> nonvalid = *i - tmp;
00183       // there are only valid attributes given
00184       conceptsAssert3(nonvalid.empty(), Assertion(), "non valid attributes " <<
00185                       nonvalid << " in given domain " << *i);
00186 
00187       if ((*i).empty())
00188         i = domains.erase(i);             // delete empty domain
00189       else {
00190         // contribute to mapping from attribute to domain
00191         for(Set<uint>::const_iterator j = (*i).begin(); j != (*i).end(); ++j)
00192           attrToDomain_[*j] = this->domains_;
00193         tmp = tmp - *i++;                 // erase attributes from set
00194         ++this->domains_;                 // count non-empty domains
00195       }
00196     }
00197 
00198     // rest of attributes to a new domain
00199     if (!tmp.empty()) {
00200       domains.push_back(tmp);
00201       // contribute to mapping from attribute to domain
00202       for(Set<uint>::const_iterator j = tmp.begin(); j != tmp.end(); ++j)
00203         attrToDomain_[*j] = this->domains_;
00204       ++this->domains_;
00205     }
00206     
00207     DEBUGL(DDSpaceConstr_D, "domains = " << domains);
00208 
00209     // set the number of builds to zero
00210     spcBuild_.resize(this->domains_);
00211     spcBuild_.zeros();
00212 
00213     i = domains.begin();
00214     for (; i != domains.end(); ) {
00215 
00216       // create for each domain a entrance
00217       cc_.insert(cc_.end(), this->domains_, CellConditions());
00218 
00219       i = domains.begin();
00220       for (Sequence<CellConditions>::iterator j = cc_.begin(); j != cc_.end();
00221            ++j, ++i) {
00222         // set difference with valid attributes
00223         const Set<uint> nonactiv = attributes - *i;
00224         for (Set<uint>::const_iterator k = nonactiv.begin();
00225              k != nonactiv.end(); ++k)
00226           (*j).add(*k, CellCondition::INACTIVE);
00227       }
00228     }
00229     DEBUGL(DDSpaceConstr_D, "cell conditions of domains = " << cc_);
00230 
00231     // create spaces
00232     uint* idx = 0;
00233     F* spc;
00234     for (Sequence<CellConditions>::iterator j = cc_.begin(); j != cc_.end(); ++j)
00235       {
00236         spaces_.push_back(spc = new F(prebuild, bc, &*j, spcNo_, offset, idx));
00237         idx = &spc->lastIdx();
00238       }
00239     DEBUGL(DDSpaceConstr_D, "spaces of domains = " << spaces_);
00240     
00241     // reserve space for index sets for each sub domains
00242     this->indicesI_.resize(this->domains_, Set<IndexRange>());
00243     this->indicesB_.resize(this->domains_, Set<IndexRange>());
00244   }
00245 
00246   template<class F>
00247   DomainDecomp<F>::~DomainDecomp() {
00248     // deletes in reverse order, because the first space holds the
00249     // pointer to the index
00250     uint k = this->domains();
00251     typename Sequence<F*>::reverse_iterator i = spaces_.rbegin();
00252     for (; i != spaces_.rend(); ++i) {
00253       DEBUGL(DDSpaceDestr_D, "Try to delete Space(" << k-- << ") = " << **i);
00254       delete *i;
00255     }
00256     concepts::Joiner<Element*, 1>::destructor(elm_, false);
00257     DEBUGL(DDSpaceDestr_D, "done");
00258   }
00259 
00260   template<class F>
00261   std::ostream& DomainDecomp<F>::info(std::ostream& os) const {
00262     os << "DomainDecomp(" << this->domains_ << " domains, ";
00263     if (!available())
00264       os << "not built";
00265     else {
00266       os << "dim = " << dim() << ", nelm = " << nelm() << ", ";
00267       for (uint i = 0; i < spaces_.size();) {
00268         os << "space(" << i << ") = " << space(i);
00269 #if DDSpaceInfoIndices_D
00270         os << ", I(" << i << ") = " << indicesI(i)
00271            << ", B(" << i << ") = " << indicesB(i);
00272 #else
00273         os << ", I(" << i << ").dim = " << indicesI(i).dim()
00274            << ", B(" << i << ").dim = " << indicesB(i).dim();
00275 #endif
00276         if (++i < spaces_.size()) os << ", ";
00277       }
00278     }
00279     return os << ")";
00280   }
00281 
00282   template<class F>
00283   void DomainDecomp<F>::rebuild() {
00284     DEBUGL(DDSpaceRebuild_D, "Start rebuilding");
00285     // If nothing to do, do nothing
00286     if (available()) {
00287       DEBUGL(DDSpaceRebuild_D, "space already built - nothing to do");
00288       return;
00289     }
00290 
00291     // Remove old list, but not elements. They are removed in spaces
00292     // itself.
00293     concepts::Joiner<Element*, 1>::destructor(elm_, false);
00294     nelm_ = 0;
00295 
00296     // Rebuild all spaces, but don't refresh own array of all
00297     // elements. That is done in method scan(), because the
00298     // rebuild()-method of the spaces could be called also directly.
00299     uint k = 0;
00300     typename Sequence<F*>::iterator i = spaces_.begin();
00301     // reset the index counter (identical for all spaces/domains)
00302     (*i)->lastIdx() = (*i)->offset();
00303     // clear all indices
00304     (*i)->prebuild().clearAllIndices(spcNo_);
00305     uint* b = spcBuild_;
00306     for (; i != spaces_.end(); ++i) {
00307       (*i)->rebuild(true);
00308       DEBUGL(DDSpaceRebuild_D, "Space(" << k++ << ") = " << **i);
00309       // space should be available now
00310       conceptsAssert((*i)->available().first, Assertion());
00311       // memorize number of the build
00312       *b++ = (*i)->available().second;
00313       conceptsAssert(nelm_ == 0 || (*i)->nelm() == nelm_, Assertion());
00314       nelm_ = (*i)->nelm();
00315       DEBUGL(DDSpaceRebuild_D, "nelm = " << nelm_);
00316     }
00317 
00318     // fill list of elements
00319     uint j = 0;
00320     std::auto_ptr<typename Space<typename F::t_type>::Scanner> sc(0);
00321     for (i = spaces_.begin(); i != spaces_.end(); ++i) {
00322       sc.reset((*i)->scan());
00323       while (*sc) {
00324         Element* elm = &(*sc)++;
00325         DEBUGL(DDSpaceRebuild_D, "Element = " << elm);
00326         DEBUGL(DDSpaceRebuild_D, "Element = " << *elm);
00327         if (elm->T().n() > 0) {
00328           DEBUGL(DDSpaceRebuild_D, "Element(" << j << ") = " << *elm);
00329           elm_ = new concepts::Joiner<Element*, 1>(elm, elm_);
00330           ++j;
00331         }
00332       }
00333     }
00334     conceptsAssert(j == nelm_, Assertion());
00335 
00336     for(uint j = 0; j < this->domains_; ++j) {
00337       this->indicesI_[j].clear();
00338       this->indicesB_[j].clear();
00339     }
00340 
00341     // collect all index ranges into this set to determine if a index
00342     // range occurs at least two times
00343     Set<IndexRange> indices;
00344     std::auto_ptr<concepts::Scan2> se(spaces_[0]->prebuild().mesh().scan());
00345     while (*se)
00346       getIndices_(spaces_[0]->prebuild(), (*se)++.connector(), indices);
00347 
00348 #if DDSpaceRebuild_D
00349     for(uint j = 0; j < this->domains_; ++j) {
00350       DEBUGL(1, "indicesI_[" << j << "] = " << this->indicesI_[j]);
00351       DEBUGL(1, "indicesB_[" << j << "] = " << this->indicesB_[j]);
00352     }
00353 
00354     i = spaces_.begin(); k = 0;
00355     for (; i != spaces_.end(); ++i)
00356       DEBUGL(1, "Space(" << k++ << ") = " << **i);
00357 #endif
00358   }
00359 
00360   template<class F>
00361   bool DomainDecomp<F>::available() const {
00362 //     uint build;
00363     const uint* b = spcBuild_;
00364     typename Sequence<F*>::const_iterator i = spaces_.begin();
00365     while(i != spaces_.end() && (*i)->available().first && 
00366     (*i)->available().second == *b++) ++i;
00367     return i == spaces_.end();
00368   }
00369 
00370   template<class F>
00371   uint DomainDecomp<F>::dim() const {
00372     if (!available())
00373       throw conceptsException(concepts::SpaceNotBuilt());
00374     // dimension is for the spaces of all domains the same, they live
00375     // on the same index range
00376     return (*spaces_.begin())->dim();
00377   }
00378 
00379   template<class F>
00380   uint DomainDecomp<F>::nelm() const {
00381     if (!available())
00382       throw conceptsException(concepts::SpaceNotBuilt());
00383     return nelm_;
00384   }
00385 
00386   template<class F>
00387   typename DomainDecomp<F>::Scan* DomainDecomp<F>::scan() const {
00388     if (!available())
00389       throw conceptsException(concepts::SpaceNotBuilt());
00390     return new concepts::PListScan<Element>(*elm_);
00391   }
00392 
00393   template<class F>
00394   uint& DomainDecomp<F>::lastIdx() {
00395     return (*spaces_.begin())->lastIdx();
00396   }
00397 
00398   template<class F>
00399   uint DomainDecomp<F>::offset() const {
00400     return (*spaces_.begin())->offset();
00401   }
00402 
00403   template<class F>
00404   const F& DomainDecomp<F>::space(uint i) const {
00405     conceptsAssert(i < this->domains_, Assertion());
00406     return *spaces_[i];
00407   }
00408 
00409   template<class F>
00410   F& DomainDecomp<F>::space(uint i) {
00411     conceptsAssert(i < this->domains_, Assertion());
00412     return *spaces_[i];
00413   }
00414 
00415   template<class F>
00416   const Set<IndexRange> DomainDecomp<F>::indicesI(uint i) const {
00417     conceptsAssert(i < this->domains_, Assertion());
00418     if (!available())
00419       throw conceptsException(concepts::SpaceNotBuilt());
00420     return this->indicesI_[i];
00421   }
00422 
00423   template<class F>
00424   const Set<IndexRange> DomainDecomp<F>::indicesB(uint i) const {
00425     conceptsAssert(i < this->domains_, Assertion());
00426     if (!available())
00427       throw conceptsException(concepts::SpaceNotBuilt());
00428     return this->indicesB_[i];
00429   }
00430 
00431   template<class F>
00432   template<class G, class H>
00433   void DomainDecomp<F>::getIndices_(const G& prebuild, const H& cntr,
00434                                     Set<IndexRange>& indices)
00435   {
00436     DEBUGL(DDSpaceGetIndices_D, "cntr = " << cntr);
00437     HashMap<uint>::const_iterator i = attrToDomain_.find(cntr.attrib());
00438     conceptsAssert(i != attrToDomain_.end(), Assertion());
00439     // domain
00440     uint d = i->second;
00441     DEBUGL(DDSpaceGetIndices_D, "domain = " << d);
00442 
00443     Set<IndexRange> &indicesB = this->indicesB_[d],
00444       &indicesI = this->indicesI_[d];
00445 
00446     uint dim = 0;
00447     try {
00448       while(1) {
00449         // Index ranges of this cell of entities of dimension dim. 
00450         // Throws an exception if dimension is to high and leaves the
00451         // while loop.
00452         const Set<IndexRange> idx = prebuild.indices(dim, cntr, spcNo_);
00453         if (!idx.empty()) {
00454           DEBUGL(DDSpaceGetIndices_D,
00455                  cntr.key() << " - dim = " << dim << ", idx = " << idx);
00456           DEBUGL(DDSpaceGetIndices_D, "indices = " << indices);
00457           // Indices, which occur first time or lie the interior this domain.
00458           Set<IndexRange> recent = idx - (indices - indicesI);
00459           // already occured indices
00460           Set<IndexRange> occured = idx - recent;
00461           DEBUGL(DDSpaceGetIndices_D,
00462                  "recent = " << recent << ", occured = " << occured);
00463           if (!occured.empty()) {
00464             // its on the boundary of this domain
00465             indicesB = indicesB || occured;
00466             DEBUGL(DDSpaceGetIndices_D, "indicesB = " << indicesB);
00467             // Delete it from index set inside other domains, could be
00468             // counted there
00469             for(uint j = 0; j < this->domains_; ++j)
00470               if (j != d) {
00471                 Set<IndexRange> occuredDomain = occured && this->indicesI_[j];
00472                 this->indicesI_[j] = this->indicesI_[j] - occuredDomain;
00473                 this->indicesB_[j] = this->indicesB_[j] || occuredDomain;
00474               }
00475           }
00476           if (!recent.empty()) {
00477             indicesI = indicesI || recent;
00478             DEBUGL(DDSpaceGetIndices_D, "indicesI = " << indicesI);
00479           }
00480           indices = indices || idx;
00481           // set difference with index ranges at boundary are inside domain
00482           DEBUGL(DDSpaceGetIndices_D,
00483                  "indicesI_[" << d << "] = " << this->indicesI_[d]);
00484           DEBUGL(DDSpaceGetIndices_D,
00485                  "indicesB_[" << d << "] = " << this->indicesB_[d]);
00486         } // idx not empty
00487         ++dim;
00488         DEBUGL(DDSpaceGetIndices_D, "dim = " << dim);
00489       } // while (1)
00490     }
00491     catch (concepts::MissingFeature& e) {}
00492 
00493     DEBUGL(DDSpaceGetIndices_D, "done for " << cntr);
00494     const H* chld = 0;
00495     for(uint j = 0; (chld = cntr.child(j)) != 0; ++j)
00496       getIndices_(prebuild, *chld, indices);
00497   }
00498 
00499 } // namespace concepts
00500 
00501 #endif

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)