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

Site Contact