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