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
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
00042
00044 virtual const Set<IndexRange> indicesB(uint i) const = 0;
00046
00047
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
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
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
00123 virtual const Set<IndexRange> indicesB(uint i) const;
00124
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
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
00179 Sequence<Set<uint> >::iterator i = domains.begin();
00180 for (; i != domains.end(); ) {
00181
00182 Set<uint> nonvalid = *i - tmp;
00183
00184 conceptsAssert3(nonvalid.empty(), Assertion(), "non valid attributes " <<
00185 nonvalid << " in given domain " << *i);
00186
00187 if ((*i).empty())
00188 i = domains.erase(i);
00189 else {
00190
00191 for(Set<uint>::const_iterator j = (*i).begin(); j != (*i).end(); ++j)
00192 attrToDomain_[*j] = this->domains_;
00193 tmp = tmp - *i++;
00194 ++this->domains_;
00195 }
00196 }
00197
00198
00199 if (!tmp.empty()) {
00200 domains.push_back(tmp);
00201
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
00210 spcBuild_.resize(this->domains_);
00211 spcBuild_.zeros();
00212
00213 i = domains.begin();
00214 for (; i != domains.end(); ) {
00215
00216
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
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
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
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
00249
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
00286 if (available()) {
00287 DEBUGL(DDSpaceRebuild_D, "space already built - nothing to do");
00288 return;
00289 }
00290
00291
00292
00293 concepts::Joiner<Element*, 1>::destructor(elm_, false);
00294 nelm_ = 0;
00295
00296
00297
00298
00299 uint k = 0;
00300 typename Sequence<F*>::iterator i = spaces_.begin();
00301
00302 (*i)->lastIdx() = (*i)->offset();
00303
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
00310 conceptsAssert((*i)->available().first, Assertion());
00311
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
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
00342
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
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
00375
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
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
00450
00451
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
00458 Set<IndexRange> recent = idx - (indices - indicesI);
00459
00460 Set<IndexRange> occured = idx - recent;
00461 DEBUGL(DDSpaceGetIndices_D,
00462 "recent = " << recent << ", occured = " << occured);
00463 if (!occured.empty()) {
00464
00465 indicesB = indicesB || occured;
00466 DEBUGL(DDSpaceGetIndices_D, "indicesB = " << indicesB);
00467
00468
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
00482 DEBUGL(DDSpaceGetIndices_D,
00483 "indicesI_[" << d << "] = " << this->indicesI_[d]);
00484 DEBUGL(DDSpaceGetIndices_D,
00485 "indicesB_[" << d << "] = " << this->indicesB_[d]);
00486 }
00487 ++dim;
00488 DEBUGL(DDSpaceGetIndices_D, "dim = " << dim);
00489 }
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 }
00500
00501 #endif