00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "SundanceDOFMapBuilder.hpp"
00032 #include "SundanceOut.hpp"
00033 #include "PlayaTabs.hpp"
00034 #include "SundanceBasisFamily.hpp"
00035 #include "SundanceLagrange.hpp"
00036 #include "SundanceEdgeLocalizedBasis.hpp"
00037 #include "SundanceMixedDOFMap.hpp"
00038 #include "SundanceMixedDOFMapHN.hpp"
00039 #include "SundanceNodalDOFMap.hpp"
00040 #include "SundanceNodalDOFMapHN.hpp"
00041 #include "SundancePartialElementDOFMap.hpp"
00042 #include "SundanceMaximalCellFilter.hpp"
00043 #include "SundanceInhomogeneousNodalDOFMap.hpp"
00044 #include "SundanceInhomogeneousEdgeLocalizedDOFMap.hpp"
00045 #include "SundanceInhomogeneousDOFMapHN.hpp"
00046 #include "SundanceCellFilter.hpp"
00047 #include "SundanceDimensionalCellFilter.hpp"
00048 #include "SundanceCellSet.hpp"
00049 #include "SundanceCFMeshPair.hpp"
00050 #include "Teuchos_Time.hpp"
00051 #include "Teuchos_TimeMonitor.hpp"
00052
00053
00054 using namespace Sundance;
00055 using namespace Teuchos;
00056 using Playa::MPIComm;
00057 using Playa::MPIDataType;
00058 using Playa::MPIOp;
00059
00060 static Time& DOFBuilderCtorTimer()
00061 {
00062 static RCP<Time> rtn
00063 = TimeMonitor::getNewTimer("DOF map building");
00064 return *rtn;
00065 }
00066
00067 static Time& cellFilterReductionTimer()
00068 {
00069 static RCP<Time> rtn
00070 = TimeMonitor::getNewTimer("cell filter reduction");
00071 return *rtn;
00072 }
00073
00074 static Time& findFuncDomainTimer()
00075 {
00076 static RCP<Time> rtn
00077 = TimeMonitor::getNewTimer("finding func domains");
00078 return *rtn;
00079 }
00080
00081 DOFMapBuilder::DOFMapBuilder(const Mesh& mesh,
00082 const RCP<FunctionSupportResolver>& fsr, bool findBCCols,
00083 int setupVerb)
00084 : verb_(setupVerb),
00085 mesh_(mesh),
00086 fsr_(fsr),
00087 rowMap_(),
00088 colMap_(),
00089 isBCRow_(),
00090 isBCCol_(),
00091 remoteBCCols_()
00092 {
00093 init(findBCCols);
00094 }
00095
00096 DOFMapBuilder::DOFMapBuilder(int setupVerb)
00097 : verb_(setupVerb),
00098 mesh_(),
00099 fsr_(),
00100 rowMap_(),
00101 colMap_(),
00102 isBCRow_(),
00103 isBCCol_(),
00104 remoteBCCols_()
00105 {}
00106
00107 RCP<DOFMapBase> DOFMapBuilder::makeMap(const Mesh& mesh,
00108 const Array<RCP<BasisDOFTopologyBase> >& basis,
00109 const Array<Set<CellFilter> >& filters)
00110 {
00111 TimeMonitor timer(DOFBuilderCtorTimer());
00112 SUNDANCE_MSG1(verb_, "in DOFMapBuilder::makeMap()");
00113 for (int i=0; i<basis.size(); i++)
00114 {
00115 SUNDANCE_MSG2(verb_, "i=" << i
00116 << " basis=" << basis[i]->description()
00117 << " filters=" << filters[i]);
00118 }
00119
00120 RCP<DOFMapBase> rtn;
00121
00122 if (allowNodalMap() && hasOmnipresentNodalMap(basis, mesh, filters))
00123 {
00124 SUNDANCE_MSG2(verb_, "creating omnipresent nodal map");
00125 CellFilter maxCells = getMaxCellFilter(filters);
00126
00127 if (mesh.allowsHangingHodes()){
00128 rtn = rcp(new NodalDOFMapHN(mesh, basis.size(), maxCells, verb_));
00129 }
00130 else {
00131 rtn = rcp(new NodalDOFMap(mesh, basis.size(), maxCells, verb_));
00132 }
00133 }
00134 else if (hasCellBasis(basis) && hasCommonDomain(filters))
00135 {
00136 TEUCHOS_TEST_FOR_EXCEPTION(filters[0].size() != 1, std::runtime_error,
00137 "only a single domain expected in construction of an element "
00138 "DOF map");
00139 rtn = rcp(new PartialElementDOFMap(mesh, *filters[0].begin(), basis.size(), verb_));
00140 }
00141 else if (allFuncsAreOmnipresent(mesh, filters))
00142 {
00143 SUNDANCE_MSG2(verb_, "creating omnipresent mixed map");
00144 CellFilter maxCells = getMaxCellFilter(filters);
00145 if (mesh.allowsHangingHodes()){
00146 rtn = rcp(new MixedDOFMapHN(mesh, basis, maxCells, verb_));
00147 }else
00148 {
00149 rtn = rcp(new MixedDOFMap(mesh, basis, maxCells, verb_));
00150 }
00151 }
00152 else if ( hasNodalBasis(basis) && (!mesh.allowsHangingHodes()) )
00153 {
00154 SUNDANCE_MSG2(verb_, "creating inhomogeneous nodal map");
00155 Sundance::Map<CellFilter, Set<int> > fmap = domainToFuncSetMap(filters);
00156 Sundance::Map<CellFilter, Sundance::Map<Set<int>, CellSet> > inputChildren;
00157
00158 Array<Sundance::Map<Set<int>, CellFilter> > disjoint
00159 = DOFMapBuilder::funcDomains(mesh, fmap, inputChildren);
00160
00161 rtn = rcp(new InhomogeneousNodalDOFMap(mesh, disjoint, verb_));
00162 }
00163 else if ( hasEdgeLocalizedBasis(basis) && (!mesh.allowsHangingHodes()) )
00164 {
00165 SUNDANCE_MSG2(verb_, "creating inhomogeneous edge-localized map");
00166
00167 Sundance::Map<CellFilter, Set<int> > fmap = domainToFuncSetMap(filters);
00168
00169 Sundance::Map<CellFilter, Sundance::Map<Set<int>, CellSet> > inputChildren;
00170 Array<Sundance::Map<Set<int>, CellFilter> > disjoint
00171 = DOFMapBuilder::funcDomains(mesh, fmap, inputChildren);
00172
00173 rtn = rcp(new InhomogeneousEdgeLocalizedDOFMap(mesh, disjoint, verb_));
00174 }
00175 else
00176 {
00177 SUNDANCE_MSG2(verb_, "creating inhomogeneous HN map (the last possibility)");
00178 Sundance::Map<CellFilter, Set<int> > fmap = domainToFuncSetMap(filters);
00179 Sundance::Map<CellFilter, Sundance::Map<Set<int>, CellSet> > inputChildren;
00180
00181 Array<Sundance::Map<Set<int>, CellFilter> > disjoint
00182 = DOFMapBuilder::funcDomains(mesh, fmap, inputChildren);
00183
00184 rtn = rcp(new InhomogeneousDOFMapHN(mesh, basis , disjoint, verb_));
00185 }
00186
00187 if (verb_ > 0)
00188 {
00189 Out::os() << "done building DOF map" << std::endl;
00190 if (verb_ > 1) Out::os() << "num DOFs" << rtn->numDOFs() << std::endl;
00191 if (verb_ > 1) Out::os() << "num local DOFs"
00192 << rtn->numLocalDOFs() << std::endl;
00193 if (verb_ > 4) rtn->print(Out::os());
00194 }
00195 return rtn;
00196 }
00197
00198
00199 Sundance::Map<CellFilter, Set<int> > DOFMapBuilder::domainToFuncSetMap(const Array<Set<CellFilter> >& filters) const
00200 {
00201 SUNDANCE_MSG2(verb_, "in DOFMapBuilder::domainToFuncSetMap()");
00202 Map<CellFilter, Set<int> > rtn;
00203 for (int i=0; i<filters.size(); i++)
00204 {
00205 const Set<CellFilter>& s = filters[i];
00206 for (Set<CellFilter>::const_iterator j=s.begin(); j!=s.end(); j++)
00207 {
00208 const CellFilter& cf = *j;
00209 if (rtn.containsKey(cf))
00210 {
00211 rtn[cf].put(i);
00212 }
00213 else
00214 {
00215
00216 rtn.put(cf, makeSet((int) i));
00217 }
00218 }
00219 }
00220 for (Map<CellFilter, Set<int> >::const_iterator
00221 i=rtn.begin(); i!=rtn.end(); i++)
00222 {
00223 SUNDANCE_MSG2(verb_, "subdomain=" << i->first << ", functions="
00224 << i->second);
00225 }
00226 return rtn;
00227 }
00228
00229
00230 void DOFMapBuilder
00231 ::getSubdomainUnkFuncMatches(const FunctionSupportResolver& fsr,
00232 Array<Sundance::Map<CellFilter, Set<int> > >& fmap) const
00233 {
00234 fmap.resize(fsr.numUnkBlocks());
00235
00236 for (int r=0; r<fsr.numRegions(); r++)
00237 {
00238 CellFilter subreg = fsr.region(r);
00239 Set<int> funcs = fsr.unksOnRegion(r).setUnion(fsr.bcUnksOnRegion(r));
00240 for (Set<int>::const_iterator i=funcs.begin(); i!=funcs.end(); i++)
00241 {
00242 int block = fsr.blockForUnkID(*i);
00243 if (fmap[block].containsKey(subreg))
00244 {
00245 fmap[block][subreg].put(*i);
00246 }
00247 else
00248 {
00249 fmap[block].put(subreg, makeSet(*i));
00250 }
00251 }
00252 }
00253 }
00254
00255 void DOFMapBuilder
00256 ::getSubdomainVarFuncMatches(const FunctionSupportResolver& fsr,
00257 Array<Sundance::Map<CellFilter, Set<int> > >& fmap) const
00258 {
00259 fmap.resize(fsr.numVarBlocks());
00260
00261 for (int r=0; r<fsr.numRegions(); r++)
00262 {
00263 CellFilter subreg = fsr.region(r);
00264 Set<int> funcs = fsr.varsOnRegion(r).setUnion(fsr.bcVarsOnRegion(r));
00265 for (Set<int>::const_iterator i=funcs.begin(); i!=funcs.end(); i++)
00266 {
00267 int block = fsr.blockForVarID(*i);
00268 if (fmap[block].containsKey(subreg))
00269 {
00270 fmap[block][subreg].put(*i);
00271 }
00272 else
00273 {
00274 fmap[block].put(subreg, makeSet(*i));
00275 }
00276 }
00277 }
00278 }
00279
00280 Array<Sundance::Map<Set<int>, CellFilter> > DOFMapBuilder
00281 ::funcDomains(const Mesh& mesh,
00282 const Sundance::Map<CellFilter, Set<int> >& fmap,
00283 Sundance::Map<CellFilter, Sundance::Map<Set<int>, CellSet> >& inputToChildrenMap) const
00284 {
00285 TimeMonitor timer(findFuncDomainTimer());
00286 Array<Array<CellFilter> > filters(mesh.spatialDim()+1);
00287 Array<Array<Set<int> > > funcs(mesh.spatialDim()+1);
00288
00289 for (Sundance::Map<CellFilter, Set<int> >::const_iterator
00290 i=fmap.begin(); i!=fmap.end(); i++)
00291 {
00292 int d = i->first.dimension(mesh);
00293 filters[d].append(i->first);
00294 funcs[d].append(i->second);
00295 }
00296 Array<Array<CFMeshPair> > tmp(mesh.spatialDim()+1);
00297 for (int d=0; d<tmp.size(); d++)
00298 {
00299 if (filters[d].size() != 0)
00300 tmp[d] = findDisjointFilters(filters[d], funcs[d], mesh);
00301 }
00302
00303 for (int d=0; d<tmp.size(); d++)
00304 {
00305 for (int r=0; r<tmp[d].size(); r++)
00306 {
00307 for (int p=0; p<filters[d].size(); p++)
00308 {
00309 if (tmp[d][r].filter().isSubsetOf(filters[d][p], mesh))
00310 {
00311 if (inputToChildrenMap.containsKey(filters[d][p]))
00312 {
00313 Sundance::Map<Set<int>, CellSet>& m
00314 = inputToChildrenMap[filters[d][p]];
00315 if (m.containsKey(tmp[d][r].funcs()))
00316 {
00317 m.put(tmp[d][r].funcs(), m[tmp[d][r].funcs()].setUnion(tmp[d][r].cellSet()));
00318 }
00319 else
00320 {
00321 m.put(tmp[d][r].funcs(), tmp[d][r].cellSet());
00322 }
00323 }
00324 else
00325 {
00326 Sundance::Map<Set<int>, CellSet> m;
00327 m.put(tmp[d][r].funcs(), tmp[d][r].cellSet());
00328 inputToChildrenMap.put(filters[d][p], m);
00329 }
00330 }
00331 }
00332 }
00333 }
00334
00335 Array<Sundance::Map<Set<int>, CellFilter> > rtn(mesh.spatialDim()+1);
00336 for (int d=0; d<tmp.size(); d++)
00337 {
00338 if (tmp[d].size() == 0) continue;
00339 for (int i=0; i<tmp[d].size(); i++)
00340 {
00341 const Set<int>& f = tmp[d][i].funcs();
00342 const CellFilter& cf = tmp[d][i].filter();
00343 if (rtn[d].containsKey(f))
00344 {
00345 rtn[d].put(f, rtn[d][f] + cf);
00346 }
00347 else
00348 {
00349 rtn[d].put(f, cf);
00350 }
00351 }
00352 }
00353
00354 return rtn;
00355 }
00356
00357
00358 void DOFMapBuilder::init(bool findBCCols)
00359 {
00360 SUNDANCE_MSG1(verb_, "in DOFMapBuilder::init()");
00361 SUNDANCE_MSG2(verb_, "num var blocks=" << fsr_->numVarBlocks());
00362 SUNDANCE_MSG2(verb_, "num unk blocks=" << fsr_->numUnkBlocks());
00363
00364 rowMap_.resize(fsr_->numVarBlocks());
00365 colMap_.resize(fsr_->numUnkBlocks());
00366 isBCRow_.resize(fsr_->numVarBlocks());
00367 isBCCol_.resize(fsr_->numUnkBlocks());
00368
00369 Array<Array<RCP<BasisDOFTopologyBase> > > testBasis = testBasisTopologyArray();
00370 Array<Array<Set<CellFilter> > > testRegions = testCellFilters();
00371
00372 for (int br=0; br<fsr_->numVarBlocks(); br++)
00373 {
00374 SUNDANCE_MSG2(verb_, "making map for block row=" << br);
00375 rowMap_[br] = makeMap(mesh_, testBasis[br], testRegions[br]);
00376 SUNDANCE_MSG2(verb_, "marking BC rows for block row=" << br);
00377 markBCRows(br);
00378 }
00379
00380
00381 Array<Array<RCP<BasisDOFTopologyBase> > > unkBasis = unkBasisTopologyArray();
00382 Array<Array<Set<CellFilter> > > unkRegions = unkCellFilters();
00383
00384 for (int bc=0; bc<fsr_->numUnkBlocks(); bc++)
00385 {
00386 if (isSymmetric(bc))
00387 {
00388 colMap_[bc] = rowMap_[bc];
00389 }
00390 else
00391 {
00392 SUNDANCE_MSG2(verb_, "making map for block col=" << bc);
00393 colMap_[bc] = makeMap(mesh_, unkBasis[bc], unkRegions[bc]);
00394 }
00395 SUNDANCE_MSG2(verb_, "marking BC cols for block col=" << bc);
00396 if (findBCCols) markBCCols(bc);
00397 }
00398 }
00399
00400 void DOFMapBuilder::extractUnkSetsFromFSR(const FunctionSupportResolver& fsr,
00401 Array<Set<int> >& funcSets,
00402 Array<CellFilter>& regions) const
00403 {
00404 funcSets.resize(fsr.numRegions());
00405 regions.resize(fsr.numRegions());
00406 for (int r=0; r<fsr.numRegions(); r++)
00407 {
00408 regions[r] = fsr.region(r);
00409 funcSets[r] = fsr.unksOnRegion(r).setUnion(fsr.bcUnksOnRegion(r));
00410 }
00411 }
00412
00413 void DOFMapBuilder::extractVarSetsFromFSR(const FunctionSupportResolver& fsr,
00414 Array<Set<int> >& funcSets,
00415 Array<CellFilter>& regions) const
00416 {
00417 funcSets.resize(fsr.numRegions());
00418 regions.resize(fsr.numRegions());
00419 for (int r=0; r<fsr.numRegions(); r++)
00420 {
00421 regions[r] = fsr.region(r);
00422 funcSets[r] = fsr.varsOnRegion(r).setUnion(fsr.bcVarsOnRegion(r));
00423 }
00424 }
00425
00426 Sundance::Map<Set<int>, Set<CellFilter> >
00427 DOFMapBuilder::buildFuncSetToCFSetMap(const Array<Set<int> >& funcSets,
00428 const Array<CellFilter>& regions,
00429 const Mesh& mesh) const
00430 {
00431 Sundance::Map<Set<int>, Set<CellFilter> > tmp;
00432
00433 for (int r=0; r<regions.size(); r++)
00434 {
00435 const CellFilter& reg = regions[r];
00436 if (!tmp.containsKey(funcSets[r]))
00437 {
00438 tmp.put(funcSets[r], Set<CellFilter>());
00439 }
00440 tmp[funcSets[r]].put(reg);
00441 }
00442
00443
00444
00445 Sundance::Map<Set<int>, Set<CellFilter> > rtn=tmp;
00446
00447
00448
00449
00450
00451
00452
00453 return rtn;
00454 }
00455
00456 bool DOFMapBuilder::hasOmnipresentNodalMap(const Array<RCP<BasisDOFTopologyBase> >& basis,
00457 const Mesh& mesh,
00458 const Array<Set<CellFilter> >& filters) const
00459 {
00460 return hasNodalBasis(basis) && allFuncsAreOmnipresent(mesh, filters);
00461 }
00462
00463
00464
00465 bool DOFMapBuilder::hasCommonDomain(const Array<Set<CellFilter> >& filters) const
00466 {
00467 Set<CellFilter> first = filters[0];
00468 for (int i=1; i<filters.size(); i++)
00469 {
00470 if (! (filters[i] == first) ) return false;
00471 }
00472 return true;
00473 }
00474
00475 bool DOFMapBuilder::hasNodalBasis(const Array<RCP<BasisDOFTopologyBase> >& basis) const
00476 {
00477 for (int i=0; i<basis.size(); i++)
00478 {
00479 const Lagrange* lagr
00480 = dynamic_cast<const Lagrange*>(basis[i].get());
00481 if (lagr==0 || lagr->order()!=1) return false;
00482 }
00483 return true;
00484 }
00485
00486 bool DOFMapBuilder::hasEdgeLocalizedBasis(const Array<RCP<BasisDOFTopologyBase> >& basis) const
00487 {
00488 for (int i=0; i<basis.size(); i++)
00489 {
00490 const RCP<const EdgeLocalizedBasis> downcasted = rcp_dynamic_cast<EdgeLocalizedBasis>(basis[i]);
00491 if (is_null(downcasted)) return false;
00492 }
00493 return true;
00494 }
00495
00496 bool DOFMapBuilder::hasCellBasis(const Array<RCP<BasisDOFTopologyBase> >& basis) const
00497 {
00498 for (int i=0; i<basis.size(); i++)
00499 {
00500 const Lagrange* lagr
00501 = dynamic_cast<const Lagrange*>(basis[i].get());
00502 if (lagr==0 || lagr->order()!=0) return false;
00503 }
00504 return true;
00505 }
00506
00507 bool DOFMapBuilder::allFuncsAreOmnipresent(const Mesh& mesh,
00508 const Array<Set<CellFilter> >& filters) const
00509 {
00510 int rtn = 0;
00511
00512 int maxFilterDim = 0;
00513 Set<Set<CellFilter> > distinctSets;
00514 for (int i=0; i<filters.size(); i++)
00515 {
00516 for (Set<CellFilter>::const_iterator iter=filters[i].begin();
00517 iter != filters[i].end(); iter++)
00518 {
00519 int dim = iter->dimension(mesh);
00520 if (dim > maxFilterDim) maxFilterDim = dim;
00521 }
00522 distinctSets.put(filters[i]);
00523 }
00524
00525 for (Set<Set<CellFilter> >::const_iterator
00526 iter=distinctSets.begin(); iter != distinctSets.end(); iter++)
00527 {
00528 if (!isWholeDomain(mesh, maxFilterDim, *iter)) rtn = 1;
00529 }
00530
00531
00532 int omniPresent = rtn;
00533 mesh.comm().allReduce((void*) &omniPresent, (void*) &rtn, 1,
00534 MPIDataType::intType(), MPIOp::sumOp());
00535
00536
00537 return (rtn < 1);
00538 }
00539
00540 bool DOFMapBuilder::isWholeDomain(const Mesh& mesh,
00541 int maxFilterDim,
00542 const Set<CellFilter>& filters) const
00543 {
00544 CellFilter allMax;
00545 if (maxFilterDim==mesh.spatialDim()) allMax = new MaximalCellFilter();
00546 else allMax = new DimensionalCellFilter(maxFilterDim);
00547
00548 CellSet remainder = allMax.getCells(mesh);
00549
00550 for (Set<CellFilter>::const_iterator
00551 i=filters.begin(); i!=filters.end(); i++)
00552 {
00553 const CellFilter& cf = *i;
00554 if (maxFilterDim==mesh.spatialDim())
00555 {
00556 if (0 != dynamic_cast<const MaximalCellFilter*>(cf.ptr().get()))
00557 {
00558 return true;
00559 }
00560 }
00561 else
00562 {
00563 const DimensionalCellFilter* dcf
00564 = dynamic_cast<const DimensionalCellFilter*>(cf.ptr().get());
00565 if (0 != dcf && dcf->dimension(mesh) == maxFilterDim)
00566 {
00567 return true;
00568 }
00569 }
00570 if (cf.dimension(mesh) != maxFilterDim) continue;
00571 CellSet cells = cf.getCells(mesh);
00572 SUNDANCE_MSG2(verb_, "found " << cells.numCells() << " in CF " << cf);
00573 remainder = remainder.setDifference(cells);
00574 if (remainder.begin() == remainder.end()) return true;
00575 }
00576
00577 SUNDANCE_MSG2(verb_, "num remaining cells: " << remainder.numCells());
00578
00579 return false;
00580 }
00581
00582
00583
00584 CellFilter DOFMapBuilder::getMaxCellFilter(const Array<Set<CellFilter> >& filters) const
00585 {
00586 for (int i=0; i<filters.size(); i++)
00587 {
00588 const Set<CellFilter>& cfs = filters[i];
00589 if (cfs.size() != 1) continue;
00590 const CellFilter& cf = *cfs.begin();
00591 if (0 != dynamic_cast<const MaximalCellFilter*>(cf.ptr().get()))
00592 return cf;
00593 }
00594
00595 return new MaximalCellFilter();
00596 }
00597
00598
00599
00600 Array<Array<Set<CellFilter> > > DOFMapBuilder::testCellFilters() const
00601 {
00602 Array<Array<Set<CellFilter> > > rtn(fsr_->numVarBlocks());
00603
00604 for (int b=0; b<fsr_->numVarBlocks(); b++)
00605 {
00606 for (int i=0; i<fsr_->numVarIDs(b); i++)
00607 {
00608 int testID = fsr_->unreducedVarID(b, i);
00609 Set<CellFilter> s;
00610 const Set<OrderedHandle<CellFilterStub> >& cfs
00611 = fsr_->regionsForTestFunc(testID);
00612 for (Set<OrderedHandle<CellFilterStub> >::const_iterator
00613 j=cfs.begin(); j!=cfs.end(); j++)
00614 {
00615 RCP<CellFilterBase> cfb
00616 = rcp_dynamic_cast<CellFilterBase>(j->ptr());
00617 TEUCHOS_TEST_FOR_EXCEPT(cfb.get()==0);
00618 CellFilter cf = j->ptr();
00619 s.put(cf);
00620 }
00621
00622
00623 rtn[b].append(s);
00624 }
00625 }
00626 return rtn;
00627 }
00628
00629 Array<Array<Set<CellFilter> > > DOFMapBuilder::unkCellFilters() const
00630 {
00631 Array<Array<Set<CellFilter> > > rtn(fsr_->numUnkBlocks());
00632
00633 for (int b=0; b<fsr_->numUnkBlocks(); b++)
00634 {
00635 for (int i=0; i<fsr_->numUnkIDs(b); i++)
00636 {
00637 int unkID = fsr_->unreducedUnkID(b, i);
00638 Set<CellFilter> s;
00639 const Set<OrderedHandle<CellFilterStub> >& cfs
00640 = fsr_->regionsForUnkFunc(unkID);
00641 for (Set<OrderedHandle<CellFilterStub> >::const_iterator
00642 j=cfs.begin(); j!=cfs.end(); j++)
00643 {
00644 RCP<CellFilterBase> cfb
00645 = rcp_dynamic_cast<CellFilterBase>(j->ptr());
00646 TEUCHOS_TEST_FOR_EXCEPT(cfb.get()==0);
00647 CellFilter cf = j->ptr();
00648 s.put(cf);
00649 }
00650
00651
00652 rtn[b].append(s);
00653 }
00654 }
00655 return rtn;
00656 }
00657
00658 Array<Array<RCP<BasisDOFTopologyBase> > > DOFMapBuilder::testBasisTopologyArray() const
00659 {
00660 Array<Array<RCP<BasisDOFTopologyBase> > > rtn(fsr_->numVarBlocks());
00661 for (int b=0; b<fsr_->numVarBlocks(); b++)
00662 {
00663 for (int i=0; i<fsr_->numVarIDs(b); i++)
00664 {
00665 rtn[b].append(BasisFamily::getBasisTopology(fsr_->varFuncData(b, i)));
00666 }
00667 }
00668 return rtn;
00669 }
00670
00671 Array<Array<RCP<BasisDOFTopologyBase> > > DOFMapBuilder::unkBasisTopologyArray() const
00672 {
00673 Array<Array<RCP<BasisDOFTopologyBase> > > rtn(fsr_->numUnkBlocks());
00674 for (int b=0; b<fsr_->numUnkBlocks(); b++)
00675 {
00676 for (int i=0; i<fsr_->numUnkIDs(b); i++)
00677 {
00678 rtn[b].append(BasisFamily::getBasisTopology(fsr_->unkFuncData(b, i)));
00679 }
00680 }
00681 return rtn;
00682 }
00683
00684
00685 Set<CellFilter> DOFMapBuilder
00686 ::reduceCellFilters(const Mesh& mesh,
00687 const Set<CellFilter>& inputSet) const
00688 {
00689 TimeMonitor timer(cellFilterReductionTimer());
00690 Set<CellFilter> rtn;
00691
00692 CellFilter m = new MaximalCellFilter();
00693 if (inputSet.contains(m))
00694 {
00695 rtn.put(m);
00696 return rtn;
00697 }
00698
00699
00700
00701 CellFilter myMaxFilters;
00702 for (Set<CellFilter>::const_iterator
00703 i=inputSet.begin(); i!=inputSet.end(); i++)
00704 {
00705 CellFilter f = *i;
00706 if (f.dimension(mesh) != mesh.spatialDim()) continue;
00707 myMaxFilters = myMaxFilters + f;
00708 }
00709
00710 CellSet myMax = myMaxFilters.getCells(mesh);
00711
00712
00713
00714
00715
00716
00717 CellSet allMax = m.getCells(mesh);
00718 CellSet diff = allMax.setDifference(myMax);
00719
00720
00721 if (diff.begin() == diff.end())
00722 {
00723 rtn.put(m);
00724 return rtn;
00725 }
00726
00727
00728
00729 if (myMax.begin() != myMax.end()) rtn.put(myMaxFilters);
00730
00731
00732
00733
00734
00735 for (Set<CellFilter>::const_iterator
00736 i=inputSet.begin(); i!=inputSet.end(); i++)
00737 {
00738 CellFilter f = *i;
00739 if (f.dimension(mesh) == mesh.spatialDim()) continue;
00740 CellSet s = f.getCells(mesh);
00741 if (s.areFacetsOf(myMax)) continue;
00742
00743
00744
00745
00746 rtn.put(f);
00747 }
00748 return rtn;
00749 }
00750
00751
00752 bool DOFMapBuilder::isSymmetric(int b) const
00753 {
00754 if ((int)fsr_->numVarBlocks() < b || (int)fsr_->numUnkBlocks() < b) return false;
00755
00756 if (fsr_->numVarIDs(b) != fsr_->numUnkIDs(b)) return false;
00757
00758 for (int i=0; i<fsr_->numVarIDs(b); i++)
00759 {
00760 BasisFamily basis1 = BasisFamily::getBasis(fsr_->varFuncData(b,i));
00761 BasisFamily basis2 = BasisFamily::getBasis(fsr_->unkFuncData(b,i));
00762 if (!(basis1 == basis2)) return false;
00763 }
00764 return true;
00765 }
00766
00767 bool DOFMapBuilder::regionIsMaximal(int r) const
00768 {
00769 const CellFilterStub* reg = fsr_->region(r).get();
00770 return (dynamic_cast<const MaximalCellFilter*>(reg) != 0);
00771 }
00772
00773 void DOFMapBuilder::markBCRows(int block)
00774 {
00775 isBCRow_[block] = rcp(new Array<int>(rowMap_[block]->numLocalDOFs()));
00776 int ndof = rowMap_[block]->numLocalDOFs();
00777 Array<int>& isBC = *isBCRow_[block];
00778 for (int i=0; i<ndof; i++) isBC[i] = false;
00779
00780 RCP<Array<int> > cellLID = rcp(new Array<int>());
00781 Array<RCP<Array<int> > > cellBatches;
00782 const RCP<DOFMapBase>& rowMap = rowMap_[block];
00783
00784 for (int r=0; r<fsr_->numRegions(); r++)
00785 {
00786
00787 CellFilter region = fsr_->region(r);
00788
00789 if (!fsr_->isBCRegion(r)) continue;
00790
00791 int dim = region.dimension(mesh_);
00792 CellSet cells = region.getCells(mesh_);
00793 cellLID->resize(0);
00794 for (CellIterator c=cells.begin(); c != cells.end(); c++)
00795 {
00796 cellLID->append(*c);
00797 }
00798 if (cellLID->size() == 0) continue;
00799
00800
00801 const Set<int>& allBcFuncs = fsr_->bcVarsOnRegion(r);
00802
00803 Set<int> bcFuncs;
00804 for (Set<int>::const_iterator
00805 i=allBcFuncs.begin(); i != allBcFuncs.end(); i++)
00806 {
00807 if (block == fsr_->blockForVarID(*i))
00808 {
00809 bcFuncs.put(fsr_->reducedVarID(*i));
00810 }
00811 }
00812 if (bcFuncs.size()==0) continue;
00813 Array<int> bcFuncID = bcFuncs.elements();
00814
00815 Array<Array<int> > dofs;
00816 Array<int> nNodes;
00817
00818 RCP<const MapStructure> s
00819 = rowMap->getDOFsForCellBatch(dim, *cellLID, bcFuncs, dofs, nNodes,0);
00820 int offset = rowMap->lowestLocalDOF();
00821 int high = offset + rowMap->numLocalDOFs();
00822
00823 for (int c=0; c<cellLID->size(); c++)
00824 {
00825 for (int b=0; b< s->numBasisChunks(); b++)
00826 {
00827 int nFuncs = s->numFuncs(b);
00828 for (int n=0; n<nNodes[b]; n++)
00829 {
00830 for (int f=0; f<bcFuncID.size(); f++)
00831 {
00832 int chunk = s->chunkForFuncID(bcFuncID[f]);
00833 if (chunk != b) continue;
00834 int funcOffset = s->indexForFuncID(bcFuncID[f]);
00835 int dof = dofs[b][(c*nFuncs + funcOffset)*nNodes[b]+n];
00836 if (dof < offset || dof >= high) continue;
00837 (*isBCRow_[block])[dof-offset]=true;
00838 }
00839 }
00840 }
00841 }
00842 }
00843 }
00844
00845
00846
00847 void DOFMapBuilder::markBCCols(int block)
00848 {
00849 isBCCol_[block] = rcp(new Array<int>(colMap_[block]->numLocalDOFs()));
00850 int ndof = colMap_[block]->numLocalDOFs();
00851 Array<int>& isBC = *isBCCol_[block];
00852 for (int i=0; i<ndof; i++) isBC[i] = false;
00853
00854 RCP<Array<int> > cellLID = rcp(new Array<int>());
00855 Array<RCP<Array<int> > > cellBatches;
00856 const RCP<DOFMapBase>& colMap = colMap_[block];
00857
00858 for (int r=0; r<fsr_->numRegions(); r++)
00859 {
00860
00861 CellFilter region = fsr_->region(r);
00862
00863 if (!fsr_->isBCRegion(r)) continue;
00864
00865 int dim = region.dimension(mesh_);
00866 CellSet cells = region.getCells(mesh_);
00867 cellLID->resize(0);
00868 for (CellIterator c=cells.begin(); c != cells.end(); c++)
00869 {
00870 cellLID->append(*c);
00871 }
00872 if (cellLID->size() == 0) continue;
00873
00874
00875 const Set<int>& allBcFuncs = fsr_->bcUnksOnRegion(r);
00876
00877 Set<int> bcFuncs;
00878 for (Set<int>::const_iterator
00879 i=allBcFuncs.begin(); i != allBcFuncs.end(); i++)
00880 {
00881 if (block == fsr_->blockForUnkID(*i))
00882 {
00883 bcFuncs.put(fsr_->reducedUnkID(*i));
00884 }
00885 }
00886 if (bcFuncs.size()==0) continue;
00887 Array<int> bcFuncID = bcFuncs.elements();
00888
00889 Array<Array<int> > dofs;
00890 Array<int> nNodes;
00891
00892 RCP<const MapStructure> s
00893 = colMap->getDOFsForCellBatch(dim, *cellLID, bcFuncs, dofs, nNodes,0);
00894 int offset = colMap->lowestLocalDOF();
00895 int high = offset + colMap->numLocalDOFs();
00896
00897 for (int c=0; c<cellLID->size(); c++)
00898 {
00899 for (int b=0; b< s->numBasisChunks(); b++)
00900 {
00901 int nFuncs = s->numFuncs(b);
00902 for (int n=0; n<nNodes[b]; n++)
00903 {
00904 for (int f=0; f<bcFuncID.size(); f++)
00905 {
00906 int chunk = s->chunkForFuncID(bcFuncID[f]);
00907 if (chunk != b) continue;
00908 int funcOffset = s->indexForFuncID(bcFuncID[f]);
00909 int dof = dofs[b][(c*nFuncs + funcOffset)*nNodes[b]+n];
00910 if (dof < offset || dof >= high)
00911 {
00912 remoteBCCols_[block]->insert(dof);
00913 }
00914 else
00915 {
00916 (*isBCCol_[block])[dof-offset]=true;
00917 }
00918 }
00919 }
00920 }
00921 }
00922 }
00923 }
00924
00925
00926
00927 namespace Sundance
00928 {
00929
00930 Array<Array<BasisFamily> > testBasisArray(const RCP<FunctionSupportResolver>& fsr)
00931 {
00932 Array<Array<BasisFamily> > rtn(fsr->numVarBlocks());
00933 for (int b=0; b<fsr->numVarBlocks(); b++)
00934 {
00935 for (int i=0; i<fsr->numVarIDs(b); i++)
00936 {
00937 rtn[b].append(BasisFamily::getBasis(fsr->varFuncData(b, i)));
00938 }
00939 }
00940 return rtn;
00941 }
00942
00943
00944 Array<Array<BasisFamily> > unkBasisArray(const RCP<FunctionSupportResolver>& fsr)
00945 {
00946 Array<Array<BasisFamily> > rtn(fsr->numUnkBlocks());
00947 for (int b=0; b<fsr->numUnkBlocks(); b++)
00948 {
00949 for (int i=0; i<fsr->numUnkIDs(b); i++)
00950 {
00951 rtn[b].append(BasisFamily::getBasis(fsr->unkFuncData(b, i)));
00952 }
00953 }
00954 return rtn;
00955 }
00956
00957
00958 }