SundanceInhomogeneousEdgeLocalizedDOFMap.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 "SundanceInhomogeneousEdgeLocalizedDOFMap.hpp"
00043 
00044 #include "SundanceEdgeLocalizedBasis.hpp"
00045 #include "SundanceOrderedTuple.hpp"
00046 
00047 #include <numeric>
00048 #include <algorithm>
00049 
00050 namespace Sundance {
00051 
00052 using Teuchos::null;
00053 
00054 InhomogeneousEdgeLocalizedDOFMap::InhomogeneousEdgeLocalizedDOFMap(const Mesh& mesh,
00055     const Array<Map<Set<int>, CellFilter> >& funcSetToDomainMap,
00056     int setupVerb) :
00057   DOFMapBase(mesh, setupVerb),
00058   funcDomains_(),
00059   edgeDofs_()
00060 {
00061   SUNDANCE_MSG1(setupVerb, "in InhomogeneousEdgeLocalizedDOFMap ctor");
00062 
00063   TEUCHOS_TEST_FOR_EXCEPTION(mesh.comm().getNProc() != 1,
00064     std::runtime_error,
00065     "distributed inhomogeneous edge localized DOF maps not yet supported");
00066 
00067   SUNDANCE_MSG4(setupVerb, "func set to domain map " << funcSetToDomainMap);
00068 
00069   TEUCHOS_ASSERT(funcSetToDomainMap.size() > 1);
00070   TEUCHOS_ASSERT(funcSetToDomainMap[0].empty());
00071 
00072   TEUCHOS_ASSERT(funcSetToDomainMap.size() <= this->meshDimension() + 1);
00073 
00074   Map<int, Array<Array<CellFilter> > > funcFilters;
00075   Map<CellFilter, Array<int> > filterEdges;
00076   for (int dim = 1; dim <= this->meshDimension(); ++dim) {
00077     const Map<Set<int>, CellFilter> &funcsOnDom = funcSetToDomainMap[dim];
00078     for (Map<Set<int>, CellFilter>::const_iterator it = funcsOnDom.begin(),
00079       it_end = funcsOnDom.end();
00080       it != it_end;
00081       ++it)
00082     {
00083       const CellFilter &subdomain = it->second;
00084       filterEdges[subdomain] = getEdgeLIDs(subdomain);
00085 
00086       const Set<int> &funcs = it->first;
00087       for (Set<int>::const_iterator jt = funcs.begin(),
00088           jt_end = funcs.end();
00089           jt != jt_end;
00090           ++jt)
00091       {
00092         Array<Array<CellFilter> > &filters = funcFilters[*jt];
00093         filters.resize(this->meshDimension() + 1);
00094         filters[dim].append(subdomain);
00095       }
00096     }
00097   }
00098 
00099   SUNDANCE_MSG4(setupVerb, "subdomains to edges " << filterEdges);
00100   SUNDANCE_MSG4(setupVerb, "func ids to subdomains " << funcFilters);
00101 
00102   const int functionCount = funcFilters.empty() ? 0 : funcFilters.rbegin()->first + 1;
00103   funcDomains_.resize(functionCount);
00104 
00105   for (Map<int, Array<Array<CellFilter> > >::const_iterator funcIt = funcFilters.begin(),
00106       funcItEnd = funcFilters.end();
00107       funcIt != funcItEnd;
00108       ++funcIt)
00109   {
00110     const Array<CellFilter> &maxDimFilters = (funcIt->second)[this->meshDimension()];
00111     funcDomains_[funcIt->first] = std::accumulate(maxDimFilters.begin(), maxDimFilters.end(), CellFilter());
00112   }
00113 
00114   SUNDANCE_MSG4(setupVerb, "func ids to max dim subdomains " << funcDomains_);
00115 
00116   typedef OrderedPair<int, int> DofId; // DofId = (EdgeId, FuncId)
00117   Array<DofId> dofSet;
00118   for (Map<int, Array<Array<CellFilter> > >::const_iterator funcIt = funcFilters.begin(),
00119       funcItEnd = funcFilters.end();
00120       funcIt !=funcItEnd;
00121       ++funcIt)
00122   {
00123     const int funcId = funcIt->first;
00124     Set<int> dofBearingEdges;
00125     for (int dim = 1; dim <= this->meshDimension(); ++dim)
00126     {
00127       const Array<CellFilter> &dimFilters = (funcIt->second)[dim];
00128       for (Array<CellFilter>::const_iterator filtIt  = dimFilters.begin(),
00129           filtItEnd = dimFilters.end();
00130           filtIt != filtItEnd;
00131           ++filtIt)
00132       {
00133         const Array<int> &edges = filterEdges[*filtIt];
00134         dofBearingEdges.insert(edges.begin(), edges.end());
00135       }
00136     }
00137     for (Set<int>::const_iterator edgeIt = dofBearingEdges.begin(),
00138          edgeItEnd = dofBearingEdges.end();
00139          edgeIt != edgeItEnd;
00140          ++edgeIt)
00141     {
00142       dofSet.push_back(DofId(*edgeIt, funcId));
00143     }
00144   }
00145 
00146   const int dofCount = dofSet.size();
00147 
00148   SUNDANCE_MSG1(setupVerb, "number of degrees of freedom = " << dofCount);
00149   SUNDANCE_MSG4(setupVerb, "set of degrees of freedom " << dofSet);
00150 
00151   const int edgeCount = mesh.numCells(1);
00152   edgeDofs_.resize(edgeCount, Array<int>(functionCount, -1));
00153 
00154   std::sort(dofSet.begin(), dofSet.end()); // Sort by edge id, then by function id
00155   int dofRank = 0;
00156   for (Array<DofId>::const_iterator dofIt = dofSet.begin(),
00157       dofItEnd = dofSet.end();
00158       dofIt != dofItEnd;
00159       ++dofIt)
00160   {
00161     const int edgeId = dofIt->first();
00162     const int funcId = dofIt->second();
00163     edgeDofs_[edgeId][funcId] = dofRank++;
00164   }
00165 
00166   SUNDANCE_MSG4(setupVerb, "degrees of freedom on edges " << edgeDofs_);
00167 
00168   this->setLowestLocalDOF(0);
00169   this->setNumLocalDOFs(dofCount);
00170   this->setTotalNumDOFs(dofCount);
00171 }
00172 
00173 RCP<const MapStructure>
00174 InhomogeneousEdgeLocalizedDOFMap::getDOFsForCellBatch(int cellDim,
00175     const Array<int>& cellLIDs,
00176     const Set<int>& requestedFuncSet,
00177     Array<Array<int> >& dofs,
00178     Array<int>& nNodes,
00179     int verb) const
00180 {
00181   TEUCHOS_ASSERT(requestedFuncSet.setDifference(*this->allowedFuncsOnCellBatch(cellDim, cellLIDs)).empty());
00182 
00183   int edgesPerCell;
00184   if (cellDim == 0)
00185   {
00186     // No dofs on nodes
00187     edgesPerCell = 0;
00188     const Array<int> empty;
00189     getDOFsForEdgeBatch(empty, requestedFuncSet, dofs, verb);
00190   }
00191   else if (cellDim == 1)
00192   {
00193     // Cells are actually edges
00194     edgesPerCell = 1;
00195     getDOFsForEdgeBatch(cellLIDs, requestedFuncSet, dofs, verb);
00196   }
00197   else
00198   {
00199     // Edges are facets of the cells
00200     const int edgeDim = 1;
00201     edgesPerCell = this->mesh().numFacets(cellDim, 0, edgeDim);
00202     Array<int> edgeLIDs;
00203     {
00204       Array<int> dummyOrientations;
00205       this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00206       TEUCHOS_ASSERT(edgeLIDs.size() == edgesPerCell * cellLIDs.size());
00207     }
00208 
00209     getDOFsForEdgeBatch(edgeLIDs, requestedFuncSet, dofs, verb);
00210   }
00211 
00212   nNodes.resize(1);
00213   nNodes[0] = edgesPerCell;
00214 
00215   const Array<int> requestedFuncArray(requestedFuncSet.begin(), requestedFuncSet.end());
00216   return rcp(new MapStructure(requestedFuncSet.size(), rcp(new EdgeLocalizedBasis()), tuple(requestedFuncArray)));
00217 }
00218 
00219 void
00220 InhomogeneousEdgeLocalizedDOFMap::getDOFsForEdgeBatch(const Array<int>& edgeLIDs,
00221     const Set<int>& requestedFuncSet,
00222     Array<Array<int> >& dofs,
00223     int verb) const
00224 {
00225   dofs.resize(1); // One basis topology only
00226   Array<int> &dofChunk = dofs[0];
00227   dofChunk.resize(edgeLIDs.size() * requestedFuncSet.size());
00228 
00229   Array<int>::iterator entryIt = dofChunk.begin();
00230   for (Array<int>::const_iterator edgeIt = edgeLIDs.begin(),
00231       edgeItEnd = edgeLIDs.end();
00232       edgeIt != edgeItEnd;
00233       ++edgeIt)
00234   {
00235     for (Set<int>::const_iterator funcIt = requestedFuncSet.begin(),
00236         funcItEnd = requestedFuncSet.end();
00237         funcIt != funcItEnd;
00238         ++funcIt)
00239     {
00240       (*entryIt++) = edgeDofs_[*edgeIt][*funcIt];
00241     }
00242   }
00243 }
00244 
00245 RCP<const Set<int> >
00246 InhomogeneousEdgeLocalizedDOFMap::allowedFuncsOnCellBatch(int cellDim,
00247     const Array<int>& cellLIDs) const
00248 {
00249   if (cellDim == 0)
00250   {
00251     // No functions allowed on nodes
00252     return rcp(new Set<int>());
00253   }
00254 
00255   if (cellDim == this->meshDimension())
00256   {
00257     // For compatibility and as a special case,
00258     // allow all functions on cells of maximum dimension
00259     return this->allFuncIDs();
00260   }
00261 
00262   const int edgeDim = 1;
00263   if (cellDim == edgeDim)
00264   {
00265     // Cells are actually edges
00266     return this->allowedFuncsOnEdgeBatch(cellLIDs);
00267   }
00268 
00269   // Edges are facets of the cells
00270   Array<int> edgeLIDs;
00271   Array<int> dummyOrientations;
00272   this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00273   return this->allowedFuncsOnEdgeBatch(edgeLIDs);
00274 }
00275 
00276 RCP<Set<int> >
00277 InhomogeneousEdgeLocalizedDOFMap::allowedFuncsOnEdgeBatch(const Array<int> &edgeLIDs) const
00278 {
00279   const RCP<Set<int> > result = this->allFuncIDs();
00280 
00281   for (Array<int>::const_iterator edgeIt = edgeLIDs.begin(),
00282       edgeItEnd = edgeLIDs.end();
00283       edgeIt != edgeItEnd;
00284       ++edgeIt)
00285   {
00286     const Array<int> &dofs = edgeDofs_[*edgeIt];
00287 
00288     for (Set<int>::iterator it = result->begin(); it != result->end(); /* Nothing */)
00289     {
00290       if (dofs[*it] < 0)
00291       {
00292         result->erase(it++);
00293       }
00294       else
00295       {
00296         ++it;
00297       }
00298     }
00299 
00300     if (result->empty())
00301     {
00302       break;
00303     }
00304   }
00305 
00306   return result;
00307 }
00308 
00309 RCP<Set<int> >
00310 InhomogeneousEdgeLocalizedDOFMap::allFuncIDs() const
00311 {
00312   const RCP<Set<int> > result(new Set<int>());
00313   for (int i = 0; i < funcDomains_.size(); ++i)
00314   {
00315     result->insert(result->end(), i);
00316   }
00317   return result;
00318 }
00319 
00320 void
00321 InhomogeneousEdgeLocalizedDOFMap::print(std::ostream& os) const
00322 {
00323   os << "InhomogeneousEdgeLocalizedDOFMap\n";
00324   os << "Edges in mesh = " << edgeDofs_.size() << "\n";
00325   os << "Functions = " << funcDomains_.size() << "\n";
00326 
00327   for (int dim = 1; dim <= this->meshDimension(); ++dim)
00328   {
00329     os << "Dofs on cells of dimension " << dim << ":\n";
00330     const int cellCount = this->mesh().numCells(dim);
00331     for (int iCell = 0; iCell < cellCount; ++iCell)
00332     {
00333       os << "  Cell LID " << iCell << "\n";
00334       const RCP<const Set<int> > funcs = this->allowedFuncsOnCellBatch(dim, tuple(iCell));
00335       for (Set<int>::const_iterator it = funcs->begin(),
00336           it_end = funcs->end();
00337           it != it_end;
00338           ++it)
00339       {
00340         const int funcId = *it;
00341         os << "    Function " << funcId << " : {";
00342         Array<int> dofs;
00343         this->getDOFsForCell(dim, iCell, funcId, dofs);
00344         for (Array<int>::const_iterator jt = dofs.begin(),
00345             jt_end = dofs.end();
00346             jt != jt_end;
00347             ++jt)
00348         {
00349           if (jt != dofs.begin())
00350           {
00351             os << ", ";
00352           }
00353           os << *jt;
00354         }
00355         os << "}\n";
00356       }
00357     }
00358   }
00359 }
00360 
00361 int
00362 InhomogeneousEdgeLocalizedDOFMap::meshDimension() const
00363 {
00364   return this->mesh().spatialDim();
00365 }
00366 
00367 Array<int>
00368 InhomogeneousEdgeLocalizedDOFMap::getEdgeLIDs(const CellFilter &filter) const
00369 {
00370   const int cellDim = filter.dimension(this->mesh());
00371 
00372   const int nodeDim = 0;
00373   if (cellDim == nodeDim)
00374   {
00375     // Ignore isolated nodes
00376     return Array<int>();
00377   }
00378 
00379   const CellSet cells = filter.getCells(this->mesh());
00380   const Array<int> cellLIDs(cells.begin(), cells.end());
00381 
00382   const int edgeDim = 1;
00383   if (cellDim == edgeDim)
00384   {
00385     // Cells are actually edges
00386     return cellLIDs;
00387   }
00388 
00389   // Edges are cofacets of the cells
00390   Array<int> edgeLIDs;
00391   Array<int> dummyOrientations;
00392   this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00393 
00394   return edgeLIDs;
00395 }
00396 
00397 } // namespace Sundance

Site Contact