SundanceInhomogeneousNodalDOFMap.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 "SundanceMap.hpp"
00043 #include "PlayaTabs.hpp"
00044 #include "SundanceOut.hpp"
00045 #include "SundanceOrderedTuple.hpp"
00046 #include "SundanceInhomogeneousNodalDOFMap.hpp"
00047 #include "SundanceLagrange.hpp"
00048 #include "PlayaMPIContainerComm.hpp"
00049 #include "Teuchos_TimeMonitor.hpp"
00050 
00051 using namespace Sundance;
00052 using namespace Teuchos;
00053 using Playa::MPIComm;
00054 using Playa::MPIContainerComm;
00055 
00056 
00057 InhomogeneousNodalDOFMap
00058 ::InhomogeneousNodalDOFMap(const Mesh& mesh, 
00059   const Array<Map<Set<int>, CellFilter> >& funcSetToDomainMap,
00060   int setupVerb)
00061   : DOFMapBase(mesh, setupVerb),
00062     dim_(mesh.spatialDim()),
00063     basis_(rcp(new Lagrange(1))),
00064     nTotalFuncs_(),
00065     funcDomains_(),
00066     nodeDofs_(),
00067     elemDofs_(),
00068     nodeToFuncSetIndexMap_(mesh.numCells(0)),
00069     elemToFuncSetIndexMap_(mesh.numCells(dim_)),
00070     elemFuncSets_(),
00071     nodalFuncSets_(),
00072     nodeToOffsetMap_(mesh.numCells(0)),
00073     elemToOffsetMap_(mesh.numCells(0)),
00074     funcIndexWithinNodeFuncSet_(),
00075     elemStructure_(),
00076     nodeStructure_()
00077 {
00078   SUNDANCE_MSG1(setupVerb, "in InhomogeneousNodalDOFMap ctor");
00079   SUNDANCE_MSG4(setupVerb, "func set to domain map " << funcSetToDomainMap);
00080 
00081   /* count the total number of functions across all subdomains */
00082   Set<int> allFuncs;
00083   for (int d=dim_; d>=0; d--)
00084   {
00085     for (Map<Set<int>, CellFilter>::const_iterator 
00086            i=funcSetToDomainMap[d].begin(); i!=funcSetToDomainMap[d].end(); i++)
00087     {
00088       allFuncs.merge(i->first);
00089     }
00090   }
00091 
00092   
00093   nTotalFuncs_ = allFuncs.size();
00094   SUNDANCE_MSG2(setupVerb, "found " << nTotalFuncs_ << " functions");
00095   
00096 
00097   /* get flat arrays of subdomains and function arrays */
00098   Array<CellFilter> subdomains;
00099   Array<CellFilter> maxSubdomains;
00100   Array<Array<int> > funcArrays;
00101   Array<Set<int> > funcSets;
00102 
00103   for (int d=dim_; d>=0; d--)
00104   {
00105     for (Map<Set<int>, CellFilter>::const_iterator 
00106            i=funcSetToDomainMap[d].begin(); i!=funcSetToDomainMap[d].end(); i++)
00107     {
00108       subdomains.append(i->second);
00109       if (d==dim_) 
00110       {
00111         elemFuncSets_.append(i->first);
00112         maxSubdomains.append(i->second);
00113       }
00114 
00115       Array<int> myFuncs = i->first.elements();
00116       funcArrays.append(myFuncs);
00117       funcSets.append(i->first);
00118     }
00119   }
00120 
00121 
00122   /* determine the functions appearing at each node */
00123 
00124 
00125 
00126   Array<Array<int> > cellLIDs(subdomains.size());
00127   Array<Array<int> > facetLIDs(subdomains.size());
00128   Array<Array<int> > facetOrientations(subdomains.size());
00129   Array<Set<int> > nodeToFuncSetMap(mesh.numCells(0));
00130 
00131   for (int r=0; r<subdomains.size(); r++)
00132   {
00133     int d = subdomains[r].dimension(mesh);
00134     CellSet cells = subdomains[r].getCells(mesh);
00135     SUNDANCE_MSG4(setupVerb, "domain " << subdomains[r] << " has functions "
00136       << funcSets[r]);
00137       
00138     for (CellIterator c=cells.begin(); c!=cells.end(); c++)
00139     {
00140       int cellLID = *c;
00141       cellLIDs[r].append(cellLID);
00142     }
00143     if (cellLIDs[r].size()==0) continue; 
00144     int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);
00145     if (d==0)
00146     {
00147       for (int c=0; c<cellLIDs[r].size(); c++)
00148       {
00149         int fLID = cellLIDs[r][c];
00150         nodeToFuncSetMap[fLID].merge(funcSets[r]);
00151       }
00152     }
00153     else
00154     {
00155       Array<int>& facetLID = facetLIDs[r];
00156       facetLID.resize(nFacets*cellLIDs[r].size());
00157       facetOrientations[r].resize(nFacets*cellLIDs[r].size());
00158       mesh.getFacetLIDs(d, cellLIDs[r], 0, facetLID, facetOrientations[r]);
00159       for (int c=0; c<cellLIDs[r].size(); c++)
00160       {
00161         for (int f=0; f<nFacets; f++)
00162         {
00163           int fLID = facetLID[c*nFacets+f];
00164           nodeToFuncSetMap[fLID].merge(funcSets[r]);
00165         }
00166       }
00167     }
00168   }
00169 
00170   /* find the distinct combinations of functions at the nodes */
00171 
00172   Map<Set<int>, int> fsToFSIndexMap;
00173   Array<int> funcSetNodeCounts;
00174   int nNodes = mesh.numCells(0);
00175 
00176   for (int n=0; n<nNodes; n++)
00177   {
00178     const Set<int>& f = nodeToFuncSetMap[n];
00179     int funcComboIndex;
00180     if (!fsToFSIndexMap.containsKey(f)) 
00181     {
00182       funcComboIndex = nodalFuncSets_.size();
00183       fsToFSIndexMap.put(f, funcComboIndex);
00184       nodalFuncSets_.append(f);
00185       funcSetNodeCounts.append(1);
00186       nodeToOffsetMap_[n] = 0;
00187     }
00188     else
00189     {
00190       funcComboIndex = fsToFSIndexMap.get(f);
00191       nodeToOffsetMap_[n] = f.size() * funcSetNodeCounts[funcComboIndex];
00192       funcSetNodeCounts[funcComboIndex]++;
00193     }
00194     nodeToFuncSetIndexMap_[n] = funcComboIndex;
00195   }
00196 
00197   SUNDANCE_MSG2(setupVerb, "nodal func sets = " << nodalFuncSets_);
00198 
00199   nodeDofs_.resize(nodalFuncSets_.size());
00200   nodeStructure_.resize(nodalFuncSets_.size());
00201   funcIndexWithinNodeFuncSet_.resize(nodalFuncSets_.size());
00202 
00203   for (int f=0; f<nodalFuncSets_.size(); f++)
00204   {
00205     Array<int> funcs = nodalFuncSets_[f].elements();
00206     int nFuncs = funcs.size();
00207     funcIndexWithinNodeFuncSet_[f].resize(nTotalFuncs_, -1);
00208     for (int i=0; i<nFuncs; i++)
00209     {
00210       funcIndexWithinNodeFuncSet_[f][funcs[i]] = i;
00211     }
00212     nodeDofs_[f].resize(nFuncs * funcSetNodeCounts[f], -1);
00213     Array<RCP<BasisDOFTopologyBase> > nodeBases = tuple(basis_);
00214     Array<Array<int> > nodeFuncs = tuple(nodalFuncSets_[f].elements());
00215     nodeStructure_[f] = rcp(new MapStructure(nTotalFuncs_, 
00216         nodeBases, nodeFuncs));
00217   }
00218 
00219 
00220 
00221   /* second pass to assign node DOFs */
00222   int nextDOF = 0;
00223   Array<int> hasProcessedNode(nNodes);
00224   Array<Array<int> > remoteNodes(mesh.comm().getNProc());
00225 
00226   for (int r=0; r<subdomains.size(); r++)
00227   {
00228     int d = subdomains[r].dimension(mesh);
00229 
00230     if (cellLIDs[r].size()==0) continue; 
00231 
00232     if (d==0)
00233     {
00234       for (int c=0; c<cellLIDs[r].size(); c++)
00235       {
00236         int fLID = cellLIDs[r][c];
00237         int funcSetIndex = nodeToFuncSetIndexMap_[fLID];
00238         int nFuncs = nodalFuncSets_[funcSetIndex].size();
00239         int dofOffset = nodeToOffsetMap_[fLID];
00240         if (!hasProcessedNode[fLID])
00241         {
00242           assignNode(fLID, funcSetIndex, dofOffset, nFuncs,
00243             remoteNodes, hasProcessedNode, nextDOF);
00244         }
00245       }
00246     }
00247     else
00248     {
00249       Array<int>& facetLID = facetLIDs[r];
00250       int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);      
00251       for (int c=0; c<cellLIDs[r].size(); c++)
00252       {
00253         for (int f=0; f<nFacets; f++)
00254         {
00255           int fLID = facetLID[c*nFacets+f];
00256           int funcSetIndex = nodeToFuncSetIndexMap_[fLID];
00257           int dofOffset = nodeToOffsetMap_[fLID];
00258           int nFuncs = nodalFuncSets_[funcSetIndex].size();
00259           if (!hasProcessedNode[fLID])
00260           {
00261             assignNode(fLID, funcSetIndex, dofOffset, nFuncs,
00262               remoteNodes, hasProcessedNode, nextDOF);
00263           }
00264         }
00265       }
00266     }
00267   }
00268 
00269 
00270   /* Compute offsets for each processor */
00271   int localCount = nextDOF;
00272   computeOffsets(localCount);
00273   
00274   /* Resolve remote DOF numbers */
00275   shareRemoteDOFs(remoteNodes);
00276 
00277   /* Build dof tables for elements */
00278   elemDofs_.resize(maxSubdomains.size());
00279   int count = 0;
00280   Array<Array<int> > elemFuncArrays;
00281   
00282   funcDomains_.resize(nTotalFuncs_);
00283 
00284   for (int r=0; r<subdomains.size(); r++)
00285   {
00286     int d = subdomains[r].dimension(mesh);
00287     if (d != dim_) continue;
00288     if (cellLIDs[r].size()==0) continue; 
00289     int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);      
00290     Array<int>& facetLID = facetLIDs[r];
00291     Array<Array<int> > dofs(1);
00292     dofs[0].resize(funcArrays[r].size() * cellLIDs[r].size() * nFacets);
00293     getFunctionDofs(d, cellLIDs[r], facetLID, funcArrays[r], dofs);
00294     elemDofs_[count] = dofs[0];
00295     elemFuncArrays.append(funcArrays[r]);
00296     Array<RCP<BasisDOFTopologyBase> > elemBases = tuple(basis_);
00297     Array<Array<int> > elemFuncs = tuple(elemFuncSets_[count].elements());
00298     elemStructure_.append(rcp(new MapStructure(nTotalFuncs_, 
00299           elemBases, elemFuncs)));
00300     for (int c=0; c<cellLIDs[r].size(); c++)
00301     {
00302       elemToFuncSetIndexMap_[cellLIDs[r][c]] = count;
00303     }
00304     for (int i=0; i<elemFuncs[0].size(); i++)
00305     {
00306       funcDomains_[elemFuncs[0][i]] = funcDomains_[elemFuncs[0][i]] + subdomains[r];
00307     }
00308     count++;
00309   }
00310   
00311 }
00312 
00313 
00314 void InhomogeneousNodalDOFMap::getFunctionDofs(int cellDim,
00315   const Array<int>& cellLID,
00316   const Array<int>& facetLID,
00317   const Array<int>& funcs,
00318   Array<Array<int> >& dofs) const
00319 {
00320   Array<int>& dofChunk = dofs[0];
00321   dofChunk.clear();
00322 
00323   if (cellDim != 0)
00324   {
00325     int nFacets = mesh().numFacets(cellDim, cellLID[0], 0);
00326     dofChunk.resize(funcs.size() * cellLID.size() * nFacets, -1);
00327       
00328       
00329     for (int c=0; c<cellLID.size(); c++)
00330     {
00331       for (int f=0; f<nFacets; f++)
00332       {
00333         int fLID = facetLID[c*nFacets + f];
00334         int fci = nodeToFuncSetIndexMap_[fLID];
00335         int nodeOffset = nodeToOffsetMap_[fLID];
00336         for (int i=0; i<funcs.size(); i++)
00337         {
00338           int funcIndex = funcIndexWithinNodeFuncSet_[fci][funcs[i]];
00339           if (funcIndex >= 0)
00340           {
00341             dofChunk[(c*funcs.size()+i)*nFacets + f] 
00342             = nodeDofs_[fci][nodeOffset+funcIndex];
00343         
00344           }
00345         }
00346       }
00347     }
00348   }
00349   else
00350   {
00351     dofChunk.resize(funcs.size() * cellLID.size(), -1);
00352 
00353     for (int c=0; c<cellLID.size(); c++)
00354     {
00355       int fci = nodeToFuncSetIndexMap_[cellLID[c]];
00356       int nodeOffset = nodeToOffsetMap_[cellLID[c]];
00357       for (int i=0; i<funcs.size(); i++)
00358       {
00359         int funcIndex = funcIndexWithinNodeFuncSet_[fci][funcs[i]];
00360         if (funcIndex >= 0)
00361         {
00362           dofChunk[c*funcs.size()+ i] 
00363             = nodeDofs_[fci][nodeOffset+funcIndex];
00364         }
00365       }
00366     }
00367   }
00368 }
00369 
00370 void InhomogeneousNodalDOFMap::assignNode(int fLID,
00371   int funcSetIndex,
00372   int dofOffset,
00373   int nFuncs,
00374   Array<Array<int> >& remoteNodes,
00375   Array<int>& hasProcessedCell,
00376   int& nextDOF)
00377 {
00378   /* the facet may be owned by another processor */
00379   int owner;
00380   if (isRemote(0, fLID, owner))
00381   {
00382     int facetGID 
00383       = mesh().mapLIDToGID(0, fLID);
00384     remoteNodes[owner].append(facetGID);
00385       
00386   }
00387   else /* we can assign a DOF locally */
00388   {
00389     /* assign DOFs */
00390     Array<int>& myDofs = nodeDofs_[funcSetIndex];
00391     for (int i=0; i<nFuncs; i++)
00392     {
00393       myDofs[dofOffset + i] = nextDOF;
00394       nextDOF++;
00395     }
00396   }
00397   hasProcessedCell[fLID] = 1;
00398 }
00399 
00400 void InhomogeneousNodalDOFMap::computeOffsets(int localCount)
00401 {
00402   TEUCHOS_TEST_FOR_EXCEPTION(mesh().comm().getNProc() != 1,
00403     std::runtime_error,
00404     "parallel inhomogeneous DOF maps not yet supported");
00405   
00406   int totalDOFCount = localCount;
00407   int myOffset = 0;
00408   setLowestLocalDOF(myOffset);
00409   setNumLocalDOFs(localCount);
00410   setTotalNumDOFs(totalDOFCount);
00411 }
00412 
00413 void InhomogeneousNodalDOFMap::shareRemoteDOFs(const Array<Array<int> >& remoteNodes)
00414 {
00415   TEUCHOS_TEST_FOR_EXCEPTION(mesh().comm().getNProc() != 1,
00416     std::runtime_error,
00417     "parallel inhomogeneous DOF maps not yet supported");
00418 }
00419 
00420 RCP<const Set<int> >
00421 InhomogeneousNodalDOFMap::allowedFuncsOnCellBatch(int cellDim,
00422   const Array<int>& cellLID) const 
00423 {
00424   Set<int> rtn;
00425 
00426   if (cellDim==0)
00427   {
00428     rtn = nodalFuncSets_[nodeToFuncSetIndexMap_[cellLID[0]]];
00429     for (int c=0; c<cellLID.size(); c++) 
00430     {
00431       const Set<int>& s = nodalFuncSets_[nodeToFuncSetIndexMap_[cellLID[c]]];
00432       rtn = rtn.intersection(s);
00433     }
00434   }
00435   else if (cellDim==dim_)
00436   {
00437     rtn = elemFuncSets_[elemToFuncSetIndexMap_[cellLID[0]]];
00438     for (int c=0; c<cellLID.size(); c++) 
00439     {
00440       const Set<int>& s = elemFuncSets_[elemToFuncSetIndexMap_[cellLID[c]]];
00441       rtn = rtn.intersection(s);
00442     }
00443   }
00444   else
00445   {
00446     Array<int> facetLID;
00447     Array<int> facetOrientations;
00448     mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00449     rtn = nodalFuncSets_[nodeToFuncSetIndexMap_[facetLID[0]]];
00450     for (int f=0; f<facetLID.size(); f++)
00451     {
00452       const Set<int>& s = nodalFuncSets_[nodeToFuncSetIndexMap_[facetLID[f]]];
00453       rtn = rtn.intersection(s);
00454     }
00455   }
00456   return rcp(new Set<int>(rtn));
00457 }
00458 
00459 
00460 RCP<const MapStructure> 
00461 InhomogeneousNodalDOFMap::getDOFsForCellBatch(int cellDim,
00462   const Array<int>& cellLID,
00463   const Set<int>& requestedFuncSet,
00464   Array<Array<int> >& dofs,
00465   Array<int>& nNodes,
00466   int verb) const 
00467 {
00468   TimeMonitor timer(batchedDofLookupTimer());
00469   Tabs tab0;
00470 
00471   SUNDANCE_MSG2(verb, tab0 << "in InhomNodalDOFMap::getDOFsForCellBatch()");
00472 
00473   if (cellDim==0)
00474   {
00475     Tabs tab1;
00476     SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00477     bool isHomogeneous = true;
00478     int firstFuncSet = nodeToFuncSetIndexMap_[cellLID[0]];
00479     for (int c=0; c<cellLID.size(); c++)
00480     {
00481       if (nodeToFuncSetIndexMap_[cellLID[c]] != firstFuncSet) 
00482       {
00483         isHomogeneous = false;
00484         break;
00485       }
00486     }
00487 
00488     dofs.resize(1);
00489     nNodes.resize(1);
00490     nNodes[0] = 1;
00491     Array<int> dummyFacets;
00492 
00493     if (isHomogeneous)
00494     {
00495       const Set<int>& funcSet = nodalFuncSets_[firstFuncSet];
00496       TEUCHOS_TEST_FOR_EXCEPT(requestedFuncSet.setDifference(funcSet).size() != 0);
00497       Array<int> funcs = funcSet.elements();
00498       getFunctionDofs(cellDim, cellLID, dummyFacets, funcs, dofs);
00499       return nodeStructure_[firstFuncSet];
00500     }
00501     else
00502     {
00503       Array<int> funcs = requestedFuncSet.elements();
00504       getFunctionDofs(cellDim, cellLID, dummyFacets, funcs, dofs);
00505       RCP<const MapStructure> rtn 
00506         = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00507       return rtn;
00508     }
00509   }
00510   else if (cellDim==dim_)
00511   {
00512     Tabs tab1;
00513     SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00514     bool isHomogeneous = true;
00515     int firstFuncSet = elemToFuncSetIndexMap_[cellLID[0]];
00516     SUNDANCE_MSG2(verb, tab1 << "first func set = " << firstFuncSet);
00517     for (int c=0; c<cellLID.size(); c++)
00518     {
00519       if (elemToFuncSetIndexMap_[cellLID[c]] != firstFuncSet) 
00520       {
00521         isHomogeneous = false;
00522         break;
00523       }
00524     }
00525 
00526     dofs.resize(1);
00527     nNodes.resize(1);
00528     nNodes[0] = mesh().numFacets(cellDim, cellLID[0], 0);
00529 
00530     if (isHomogeneous)
00531     {
00532       Tabs tab2;
00533       Array<int> facetLID;
00534       Array<int> facetOrientations;
00535       mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00536       if (verb >= 2)
00537       {
00538         Out::os() << tab2 << "cellLID = " << cellLID << std::endl;
00539         Out::os() << tab2 << "facetLID = " << facetLID << std::endl;
00540         Out::os() << tab2 << "elem func sets = " << elemFuncSets_ << std::endl;
00541       }
00542       const Set<int>& funcSet = elemFuncSets_[firstFuncSet];
00543       TEUCHOS_TEST_FOR_EXCEPT(requestedFuncSet.setDifference(funcSet).size() != 0);
00544       Array<int> funcs = funcSet.elements();
00545       getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00546       return elemStructure_[firstFuncSet];
00547     }
00548     else
00549     {
00550       Array<int> facetLID;
00551       Array<int> facetOrientations;
00552       mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00553       Array<int> funcs = requestedFuncSet.elements();
00554       getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00555       RCP<const MapStructure> rtn 
00556         = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00557       return rtn;
00558     }
00559   }
00560   else
00561   {
00562     Tabs tab1;
00563     SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00564     Array<int> facetLID;
00565     Array<int> facetOrientations;
00566     mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00567     dofs.resize(1);
00568     nNodes.resize(1);
00569     nNodes[0] = mesh().numFacets(cellDim, cellLID[0], 0);
00570 
00571     Array<int> funcs = requestedFuncSet.elements();
00572 
00573     getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00574     RCP<const MapStructure> rtn 
00575       = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00576     return rtn;
00577   }
00578 }
00579 
00580 
00581 
00582 void InhomogeneousNodalDOFMap::print(std::ostream& os) const
00583 {
00584   Tabs tab0;
00585   std::cout << tab0 << "dof map: " << std::endl;
00586   for (int d=0; d<=dim_; d++)
00587   {
00588     Tabs tab1;
00589     std::cout << tab1 << d << "-cells: " << std::endl;
00590     for (int n=0; n<mesh().numCells(d); n++)
00591     {
00592       Tabs tab2;
00593       std::cout << tab2 << "d=" << d << " cell=" << n << std::endl;
00594       RCP<const Set<int> > funcs = allowedFuncsOnCellBatch(d, tuple(n));
00595       for (Set<int>::const_iterator f=funcs->begin(); f!=funcs->end(); f++)
00596       {
00597         Tabs tab3;
00598         Array<int> dofs;
00599         getDOFsForCell(d, n, *f, dofs);
00600         std::cout << tab3 << " f=" << *f << " dofs=" << dofs << std::endl;
00601       }
00602     }
00603   }
00604 }

Site Contact