SundanceDOFMapBuilder.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
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     // if the mesh allows hanging nodes then create different DOF Map
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     // the last option inhomogeneous mixed map, which supports hanging nodes
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   /* eliminate overlap between cell filters */
00453   
00454   Sundance::Map<Set<int>, Set<CellFilter> > rtn=tmp;
00455   /*
00456     for (Sundance::Map<Set<int>, Set<CellFilter> >::const_iterator 
00457     i=tmp.begin(); i!=tmp.end(); i++)
00458     {
00459     rtn.put(i->first, reduceCellFilters(mesh, i->second));
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   // make synchronization with the other processors
00556   int omniPresent = rtn;
00557   mesh.comm().allReduce((void*) &omniPresent, (void*) &rtn, 1,
00558     MPIDataType::intType(), MPIOp::sumOp());
00559 
00560   // it is true only when the summed value is zero
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 //  TEUCHOS_TEST_FOR_EXCEPT(true);
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       //         Set<CellFilter> reducedS = reduceCellFilters(mesh(), s);
00646 //          rtn[b].append(reducedS);
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 //          Set<CellFilter> reducedS = reduceCellFilters(mesh(), s);
00675 //          rtn[b].append(reducedS);
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   /* If the input set explicitly contains all maximal cells, we're done */
00716   CellFilter m = new MaximalCellFilter();
00717   if (inputSet.contains(m))
00718   {
00719     rtn.put(m);
00720     return rtn;
00721   }
00722 
00723   /* Next, see if combining the maximal-dimension filters in the
00724    * input set gives us all maximal cells. */
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 //  if (myMax.size() == mesh.numCells(mesh.spatialDim()))
00736 //  {
00737 //    rtn.put(m);
00738 //    return rtn;
00739 //  }
00740 
00741   CellSet allMax = m.getCells(mesh);
00742   CellSet diff = allMax.setDifference(myMax);
00743   /* if the difference between the collected max cell set and the known
00744    * set of all max cells is empty, then we're done */
00745   if (diff.begin() == diff.end())
00746   {
00747     rtn.put(m);
00748     return rtn;
00749   }
00750   
00751   /* Otherwise, we return the remaining max cell filters, and possibly
00752    * some lower-dimensional filters to be identified below. */
00753   if (myMax.begin() != myMax.end()) rtn.put(myMaxFilters);
00754 
00755   /* At this point, we can eliminate as redundant any lower-dimensional
00756    * cell filters all of whose cells are facets of our subset of
00757    * maximal cell filters. Any other lower-dim cell filters must be 
00758    * appended to our list. */
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     /* if we're here, then we have a lower-dimensional cell filter
00767      * whose cells are not facets of cells in our maximal cell filters.
00768      * These will need to be processed separately in assigning DOFs.
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     /* find the cells in this region */
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     /* find the functions that appear in BCs on this region */
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     /* find the cells in this region */
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     /* find the functions that appear in BCs on this region */
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 }        

Site Contact