SundanceNodalDOFMap.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 "SundanceMap.hpp"
00032 #include "SundanceTabs.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "SundanceOrderedTuple.hpp"
00035 #include "SundanceNodalDOFMap.hpp"
00036 #include "SundanceLagrange.hpp"
00037 #include "Teuchos_MPIContainerComm.hpp"
00038 #include "Teuchos_TimeMonitor.hpp"
00039 
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042 
00043 NodalDOFMap::NodalDOFMap(const Mesh& mesh, 
00044   int nFuncs, 
00045   const CellFilter& maxCellFilter,
00046   int setupVerb)
00047   : SpatiallyHomogeneousDOFMapBase(mesh, nFuncs, setupVerb),
00048     maxCellFilter_(maxCellFilter),
00049     dim_(mesh.spatialDim()),
00050     nFuncs_(nFuncs),
00051     nElems_(mesh.numCells(mesh.spatialDim())),
00052     nNodes_(mesh.numCells(0)),
00053     nNodesPerElem_(mesh.numFacets(mesh.spatialDim(),0,0)),
00054     elemDofs_(nElems_ * nFuncs * nNodesPerElem_),
00055     nodeDofs_(mesh.numCells(0)*nFuncs_, -1),
00056     structure_(rcp(new MapStructure(nFuncs_, rcp(new Lagrange(1)))))
00057 {
00058   init();
00059 }
00060 
00061 
00062 RCP<const MapStructure> 
00063 NodalDOFMap::getDOFsForCellBatch(int cellDim,
00064   const Array<int>& cellLID,
00065   const Set<int>& requestedFuncSet,
00066   Array<Array<int> >& dofs,
00067   Array<int>& nNodes,
00068   int verbosity) const
00069 {
00070   TimeMonitor timer(batchedDofLookupTimer());
00071 
00072   Tabs tab;
00073   SUNDANCE_MSG3(verbosity, 
00074                tab << "NodalDOFMap::getDOFsForCellBatch(): cellDim=" << cellDim
00075                << " cellLID=" << cellLID);
00076 
00077 
00078   dofs.resize(1);
00079   nNodes.resize(1);
00080 
00081   int nCells = cellLID.size();
00082 
00083 
00084   if (cellDim == dim_)
00085     {
00086       int dofsPerElem = nFuncs_ * nNodesPerElem_;
00087       nNodes[0] = nNodesPerElem_;
00088       dofs[0].resize(nCells * dofsPerElem);
00089       Array<int>& dof0 = dofs[0];
00090       
00091       for (int c=0; c<nCells; c++)
00092         {
00093           for (int i=0; i<dofsPerElem; i++)
00094             {
00095               dof0[c*dofsPerElem + i] = elemDofs_[cellLID[c]*dofsPerElem+i];
00096             }
00097         }
00098     }
00099   else if (cellDim == 0)
00100     {
00101       nNodes[0] = 1;
00102       dofs[0].resize(nCells * nFuncs_);
00103       Array<int>& dof0 = dofs[0];
00104       
00105       for (int c=0; c<nCells; c++)
00106         {
00107           for (int i=0; i<nFuncs_; i++)
00108             {
00109               dof0[c*nFuncs_ + i] = nodeDofs_[cellLID[c]*nFuncs_+i];
00110             }
00111         }
00112     }
00113   else
00114     {
00115       int nFacets = mesh().numFacets(cellDim, cellLID[0], 0);
00116       nNodes[0] = nFacets;
00117       int dofsPerCell = nFuncs_ * nNodes[0];
00118       dofs[0].resize(nCells * dofsPerCell);
00119       Array<int>& dof0 = dofs[0];
00120       Array<int> facetLIDs(nCells * nNodes[0]);
00121       Array<int> dummy(nCells * nNodes[0]);
00122       mesh().getFacetLIDs(cellDim, cellLID, 0, facetLIDs, dummy);
00123 
00124       for (int c=0; c<nCells; c++)
00125         {
00126           for (int f=0; f<nFacets; f++)
00127             {
00128               int facetCellLID = facetLIDs[c*nFacets+f];
00129               for (int i=0; i<nFuncs_; i++)
00130                 {
00131                   dof0[(c*nFuncs_+i)*nFacets + f] 
00132                     = nodeDofs_[facetCellLID*nFuncs_+i];
00133                 }
00134             }
00135         }
00136     }
00137 
00138   return structure_;
00139 }
00140 
00141 
00142 
00143 void NodalDOFMap::init() 
00144 { 
00145   Tabs tab;
00146 
00147   SUNDANCE_MSG1(setupVerb(), tab << "initializing nodal DOF map");
00148 
00149   Array<Array<int> > remoteNodes(mesh().comm().getNProc());
00150   Array<int> hasProcessedCell(nNodes_, 0);
00151 
00152   /* start the DOF count at zero. */
00153   int nextDOF = 0;
00154   int owner;
00155 
00156   int nFacets = mesh().numFacets(dim_, 0, 0);
00157   Array<int> elemLID(nElems_);
00158   Array<int> facetLID(nFacets*nElems_);
00159   Array<int> facetOrientations(nFacets*nElems_);
00160 
00161   /* Assign node DOFs for locally owned 0-cells */
00162   CellSet maxCells = maxCellFilter_.getCells(mesh());
00163 
00164   int cc = 0;
00165   for (CellIterator iter=maxCells.begin(); iter != maxCells.end(); iter++, cc++)
00166     {
00167       int c = *iter;
00168       elemLID[cc] = c;
00169     }
00170   /* look up the LIDs of the facets */
00171   mesh().getFacetLIDs(dim_, elemLID, 0, facetLID, facetOrientations);
00172   
00173   for (int c=0; c<nElems_; c++)
00174     {
00175       /* for each facet, process its DOFs */
00176       for (int f=0; f<nFacets; f++)
00177         {
00178           /* if the facet's DOFs have been assigned already,
00179            * we're done */
00180           int fLID = facetLID[c*nFacets+f];
00181           if (hasProcessedCell[fLID] == 0)
00182             {
00183               /* the facet may be owned by another processor */
00184               if (isRemote(0, fLID, owner))
00185                 {
00186                   int facetGID 
00187                     = mesh().mapLIDToGID(0, fLID);
00188                   remoteNodes[owner].append(facetGID);
00189                   
00190                 }
00191               else /* we can assign a DOF locally */
00192                 {
00193                   /* assign DOFs */
00194                   for (int i=0; i<nFuncs_; i++)
00195                     {
00196                       nodeDofs_[fLID*nFuncs_ + i] = nextDOF;
00197                       nextDOF++;
00198                     }
00199                 }
00200               hasProcessedCell[fLID] = 1;
00201             }
00202         }
00203     }
00204 
00205   
00206   /* Compute offsets for each processor */
00207   int localCount = nextDOF;
00208   computeOffsets(localCount);
00209   
00210   /* Resolve remote DOF numbers */
00211   shareRemoteDOFs(remoteNodes);
00212 
00213 
00214   /* Assign DOFs for elements */
00215   for (int c=0; c<nElems_; c++)
00216     {
00217       /* set the element DOFs given the dofs of the facets */
00218       for (int f=0; f<nFacets; f++)
00219         {
00220           int fLID = facetLID[c*nFacets+f];
00221           for (int i=0; i<nFuncs_; i++)
00222             {
00223               elemDofs_[(c*nFuncs_+i)*nFacets + f] = nodeDofs_[fLID*nFuncs_ + i]; 
00224             }
00225         }
00226     }
00227 
00228 }
00229 
00230 
00231 void NodalDOFMap::computeOffsets(int localCount)
00232 {
00233   Array<int> dofOffsets;
00234   int totalDOFCount;
00235   int myOffset = 0;
00236   int np = mesh().comm().getNProc();
00237   if (np > 1)
00238     {
00239       MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00240                                         mesh().comm());
00241       myOffset = dofOffsets[mesh().comm().getRank()];
00242 
00243       int nDofs = nNodes_ * nFuncs_;
00244       for (int i=0; i<nDofs; i++)
00245         {
00246           if (nodeDofs_[i] >= 0) nodeDofs_[i] += myOffset;
00247         }
00248     }
00249   else
00250     {
00251       totalDOFCount = localCount;
00252     }
00253   
00254   setLowestLocalDOF(myOffset);
00255   setNumLocalDOFs(localCount);
00256   setTotalNumDOFs(totalDOFCount);
00257 }
00258 
00259 
00260 void NodalDOFMap::shareRemoteDOFs(const Array<Array<int> >& outgoingCellRequests)
00261 {
00262   int np = mesh().comm().getNProc();
00263   if (np==1) return;
00264   int rank = mesh().comm().getRank();
00265 
00266   Array<Array<int> > incomingCellRequests;
00267   Array<Array<int> > outgoingDOFs(np);
00268   Array<Array<int> > incomingDOFs;
00269 
00270   SUNDANCE_MSG2(setupVerb(),  
00271                "p=" << mesh().comm().getRank()
00272                << "synchronizing DOFs for cells of dimension 0");
00273   SUNDANCE_MSG2(setupVerb(),  
00274                "p=" << mesh().comm().getRank()
00275                << " sending cell reqs d=0, GID=" 
00276                << outgoingCellRequests);
00277 
00278   /* share the cell requests */
00279   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00280                                   incomingCellRequests,
00281                                   mesh().comm());
00282   
00283   /* get DOF numbers for the zeroth function index on every node that's been 
00284    * requested by someone else */
00285   for (int p=0; p<np; p++)
00286     {
00287       if (p==rank) continue;
00288       const Array<int>& requestsFromProc = incomingCellRequests[p];
00289       int nReq = requestsFromProc.size();
00290 
00291       SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank() 
00292                             << " recv'd from proc=" << p
00293                             << " reqs for DOFs for cells " 
00294                             << requestsFromProc);
00295 
00296       outgoingDOFs[p].resize(nReq);
00297 
00298       for (int c=0; c<nReq; c++)
00299         {
00300           int GID = requestsFromProc[c];
00301           SUNDANCE_MSG3(setupVerb(),  
00302                        "p=" << rank
00303                        << " processing zero-cell with GID=" << GID); 
00304           int LID = mesh().mapGIDToLID(0, GID);
00305           SUNDANCE_MSG3(setupVerb(),  
00306                        "p=" << rank
00307                        << " LID=" << LID << " dofs=" 
00308                        << nodeDofs_[LID*nFuncs_]);
00309           outgoingDOFs[p][c] = nodeDofs_[LID*nFuncs_];
00310           SUNDANCE_MSG3(setupVerb(),  
00311                        "p=" << rank
00312                        << " done processing cell with GID=" << GID);
00313         }
00314     }
00315 
00316   SUNDANCE_MSG2(setupVerb(),  
00317                "p=" << mesh().comm().getRank()
00318                << "answering DOF requests for cells of dimension 0");
00319 
00320   /* share the DOF numbers */
00321   MPIContainerComm<int>::allToAll(outgoingDOFs,
00322                                   incomingDOFs,
00323                                   mesh().comm());
00324 
00325   SUNDANCE_MSG2(setupVerb(),  
00326                "p=" << mesh().comm().getRank()
00327                << "communicated DOF answers for cells of dimension 0" );
00328 
00329   
00330   /* now assign the DOFs from the other procs */
00331 
00332   for (int p=0; p<mesh().comm().getNProc(); p++)
00333     {
00334       if (p==mesh().comm().getRank()) continue;
00335       const Array<int>& dofsFromProc = incomingDOFs[p];
00336       int numCells = dofsFromProc.size();
00337       for (int c=0; c<numCells; c++)
00338         {
00339           int cellGID = outgoingCellRequests[p][c];
00340           int cellLID = mesh().mapGIDToLID(0, cellGID);
00341           int dof = dofsFromProc[c];
00342           for (int i=0; i<nFuncs_; i++)
00343             {
00344               nodeDofs_[cellLID*nFuncs_ + i] = dof+i;
00345               addGhostIndex(dof+i);
00346             }
00347         }
00348     }
00349 }

Site Contact