SundanceDOFMapBuilder.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
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     // if the mesh allows hanging nodes then create different DOF Map
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     // the last option inhomogeneous mixed map, which supports hanging nodes
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   /* eliminate overlap between cell filters */
00464   
00465   Sundance::Map<Set<int>, Set<CellFilter> > rtn=tmp;
00466   /*
00467     for (Sundance::Map<Set<int>, Set<CellFilter> >::const_iterator 
00468     i=tmp.begin(); i!=tmp.end(); i++)
00469     {
00470     rtn.put(i->first, reduceCellFilters(mesh, i->second));
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   // make synchronization with the other processors
00567   int omniPresent = rtn;
00568   mesh.comm().allReduce((void*) &omniPresent, (void*) &rtn, 1,
00569     MPIDataType::intType(), MPIOp::sumOp());
00570 
00571   // it is true only when the summed value is zero
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 //  TEUCHOS_TEST_FOR_EXCEPT(true);
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       //         Set<CellFilter> reducedS = reduceCellFilters(mesh(), s);
00657 //          rtn[b].append(reducedS);
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 //          Set<CellFilter> reducedS = reduceCellFilters(mesh(), s);
00686 //          rtn[b].append(reducedS);
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   /* If the input set explicitly contains all maximal cells, we're done */
00727   CellFilter m = new MaximalCellFilter();
00728   if (inputSet.contains(m))
00729   {
00730     rtn.put(m);
00731     return rtn;
00732   }
00733 
00734   /* Next, see if combining the maximal-dimension filters in the
00735    * input set gives us all maximal cells. */
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 //  if (myMax.size() == mesh.numCells(mesh.spatialDim()))
00747 //  {
00748 //    rtn.put(m);
00749 //    return rtn;
00750 //  }
00751 
00752   CellSet allMax = m.getCells(mesh);
00753   CellSet diff = allMax.setDifference(myMax);
00754   /* if the difference between the collected max cell set and the known
00755    * set of all max cells is empty, then we're done */
00756   if (diff.begin() == diff.end())
00757   {
00758     rtn.put(m);
00759     return rtn;
00760   }
00761   
00762   /* Otherwise, we return the remaining max cell filters, and possibly
00763    * some lower-dimensional filters to be identified below. */
00764   if (myMax.begin() != myMax.end()) rtn.put(myMaxFilters);
00765 
00766   /* At this point, we can eliminate as redundant any lower-dimensional
00767    * cell filters all of whose cells are facets of our subset of
00768    * maximal cell filters. Any other lower-dim cell filters must be 
00769    * appended to our list. */
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     /* if we're here, then we have a lower-dimensional cell filter
00778      * whose cells are not facets of cells in our maximal cell filters.
00779      * These will need to be processed separately in assigning DOFs.
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     /* find the cells in this region */
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     /* find the functions that appear in BCs on this region */
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     /* find the cells in this region */
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     /* find the functions that appear in BCs on this region */
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 }        

Site Contact