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