SundancePartialElementDOFMap.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 "SundancePartialElementDOFMap.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 PartialElementDOFMap::PartialElementDOFMap(const Mesh& mesh, 
00044   const CellFilter& subdomain,
00045   int nFuncs,
00046   int setupVerb)
00047   : DOFMapBase(mesh, setupVerb),
00048     dim_(mesh.spatialDim()),
00049     nFuncs_(nFuncs),
00050     nElems_(mesh.numCells(mesh.spatialDim())),
00051     subdomain_(subdomain),
00052     funcDomains_(nFuncs, subdomain),
00053     elemDofs_(nElems_ * nFuncs, -1),
00054     structure_(rcp(new MapStructure(nFuncs_, rcp(new Lagrange(0))))),
00055     allFuncs_()
00056 {
00057   init();
00058   Set<int> tmp;
00059   for (int i=0; i<nFuncs_; i++) tmp.put(i);
00060   allFuncs_ = rcp(new Set<int>(tmp));
00061 }
00062 
00063 
00064 RCP<const MapStructure> 
00065 PartialElementDOFMap::getDOFsForCellBatch(int cellDim,
00066   const Array<int>& cellLID,
00067   const Set<int>& requestedFuncSet,
00068   Array<Array<int> >& dofs,
00069   Array<int>& nNodes,
00070   int verbosity) const
00071 {
00072   TimeMonitor timer(batchedDofLookupTimer());
00073 
00074 
00075   Tabs tab;
00076   SUNDANCE_MSG3(verbosity, 
00077     tab << "PartialElementDOFMap::getDOFsForCellBatch(): cellDim=" 
00078     << cellDim
00079     << " cellLID=" << cellLID);
00080 
00081 
00082   dofs.resize(1);
00083   nNodes.resize(1);
00084   nNodes[0] = 1;
00085 
00086   int nCells = cellLID.size();
00087 
00088 
00089   if (cellDim == dim_)
00090   {
00091     dofs[0].resize(nCells * nFuncs_);
00092     Array<int>& dof0 = dofs[0];
00093       
00094     for (int c=0; c<nCells; c++)
00095     {
00096       for (int i=0; i<nFuncs_; i++)
00097       {
00098         dof0[c*nFuncs_ + i] = elemDofs_[cellLID[c]*nFuncs_+i];
00099       }
00100     }
00101   }
00102   else
00103   {
00104     dofs[0].resize(nCells * nFuncs_);
00105     Array<int> cofacetLIDs(nCells);
00106       
00107     for (int c=0; c<nCells; c++)
00108     {
00109       TEST_FOR_EXCEPTION(mesh().numMaxCofacets(cellDim, cellLID[c]) > 1,
00110         RuntimeError,
00111         "Attempt to do a trace of a L0 basis on a "
00112         "lower-dimensional cell having more than one "
00113         "maximal cofacets");
00114       int myFacetIndex = -1;
00115       cofacetLIDs[c] = mesh().maxCofacetLID(cellDim, cellLID[c],
00116         0, myFacetIndex);
00117     }
00118 
00119     getDOFsForCellBatch(dim_, cofacetLIDs, requestedFuncSet, dofs,
00120       nNodes, verbosity);
00121   }
00122 
00123   return structure_;
00124 }
00125 
00126 
00127 
00128 void PartialElementDOFMap::init() 
00129 { 
00130   Tabs tab;
00131 
00132   SUNDANCE_MSG1(setupVerb(), tab << "initializing element DOF map");
00133 
00134   int cellDim = mesh().spatialDim();
00135 
00136   Array<Array<int> > remoteElems(mesh().comm().getNProc());
00137 
00138   /* start the DOF count at zero. */
00139   int nextDOF = 0;
00140   int owner;
00141 
00142   /* Assign node DOFs for locally owned maximal cells */
00143   CellSet maxCells = subdomain_.getCells(mesh());
00144 
00145   for (CellIterator iter=maxCells.begin(); iter != maxCells.end(); iter++)
00146   {
00147     int cellLID = *iter;
00148     /* the cell may be owned by another processor */
00149     if (isRemote(cellDim, cellLID, owner))
00150     {
00151       int elemGID = mesh().mapLIDToGID(cellDim, cellLID);
00152       remoteElems[owner].append(elemGID);
00153     }                  
00154     else /* we can assign a DOF locally */
00155     {
00156       /* assign DOFs */
00157       for (int i=0; i<nFuncs_; i++)
00158       {
00159         elemDofs_[cellLID*nFuncs_ + i] = nextDOF;
00160         nextDOF++;
00161       }
00162     }
00163   }
00164   
00165   /* Compute offsets for each processor */
00166   int localCount = nextDOF;
00167   computeOffsets(localCount);
00168   
00169   /* Resolve remote DOF numbers */
00170   shareRemoteDOFs(remoteElems);
00171 }
00172 
00173 
00174 RCP<const Set<int> > PartialElementDOFMap
00175 ::allowedFuncsOnCellBatch(int cellDim,
00176   const Array<int>& cellLID) const 
00177 {
00178   static RCP<const Set<int> > empty = rcp(new Set<int>());
00179 
00180   if (cellDim != dim_) return empty;
00181   for (int i=0; i<cellLID.size(); i++)
00182   {
00183     if (elemDofs_[cellLID[i]*nFuncs_] < 0) return empty;
00184   }
00185   return allFuncs_;
00186 }
00187 
00188 
00189 void PartialElementDOFMap::computeOffsets(int localCount)
00190 {
00191   Array<int> dofOffsets;
00192   int totalDOFCount;
00193   int myOffset = 0;
00194   int np = mesh().comm().getNProc();
00195   if (np > 1)
00196   {
00197     MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00198       mesh().comm());
00199     myOffset = dofOffsets[mesh().comm().getRank()];
00200 
00201     int nDofs = nElems_ * nFuncs_;
00202     for (int i=0; i<nDofs; i++)
00203     {
00204       if (elemDofs_[i] >= 0) elemDofs_[i] += myOffset;
00205     }
00206   }
00207   else
00208   {
00209     totalDOFCount = localCount;
00210   }
00211   
00212   setLowestLocalDOF(myOffset);
00213   setNumLocalDOFs(localCount);
00214   setTotalNumDOFs(totalDOFCount);
00215 }
00216 
00217 
00218 void PartialElementDOFMap::shareRemoteDOFs(const Array<Array<int> >& outgoingCellRequests)
00219 {
00220   int cellDim = mesh().spatialDim();
00221 
00222   int np = mesh().comm().getNProc();
00223   if (np==1) return;
00224   int rank = mesh().comm().getRank();
00225 
00226   Array<Array<int> > incomingCellRequests;
00227   Array<Array<int> > outgoingDOFs(np);
00228   Array<Array<int> > incomingDOFs;
00229 
00230   SUNDANCE_MSG2(setupVerb(),  
00231     "p=" << mesh().comm().getRank()
00232     << "synchronizing DOFs for cells of dimension 0");
00233   SUNDANCE_MSG2(setupVerb(),  
00234     "p=" << mesh().comm().getRank()
00235     << " sending cell reqs d=0, GID=" 
00236     << outgoingCellRequests);
00237 
00238   /* share the cell requests */
00239   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00240     incomingCellRequests,
00241     mesh().comm());
00242   
00243   /* get DOF numbers for the zeroth function index on every node that's been 
00244    * requested by someone else */
00245   for (int p=0; p<np; p++)
00246   {
00247     if (p==rank) continue;
00248     const Array<int>& requestsFromProc = incomingCellRequests[p];
00249     int nReq = requestsFromProc.size();
00250 
00251     SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank() 
00252       << " recv'd from proc=" << p
00253       << " reqs for DOFs for cells " 
00254       << requestsFromProc);
00255 
00256     outgoingDOFs[p].resize(nReq);
00257 
00258     for (int c=0; c<nReq; c++)
00259     {
00260       int GID = requestsFromProc[c];
00261       SUNDANCE_MSG3(setupVerb(),  
00262         "p=" << rank
00263         << " processing zero-cell with GID=" << GID); 
00264       int LID = mesh().mapGIDToLID(cellDim, GID);
00265       SUNDANCE_MSG3(setupVerb(),  
00266         "p=" << rank
00267         << " LID=" << LID << " dofs=" 
00268         << elemDofs_[LID*nFuncs_]);
00269       outgoingDOFs[p][c] = elemDofs_[LID*nFuncs_];
00270       SUNDANCE_MSG3(setupVerb(),  
00271         "p=" << rank
00272         << " done processing cell with GID=" << GID);
00273     }
00274   }
00275 
00276   SUNDANCE_MSG2(setupVerb(),  
00277     "p=" << mesh().comm().getRank()
00278     << "answering DOF requests for cells of dimension 0");
00279 
00280   /* share the DOF numbers */
00281   MPIContainerComm<int>::allToAll(outgoingDOFs,
00282     incomingDOFs,
00283     mesh().comm());
00284 
00285   SUNDANCE_MSG2(setupVerb(),  
00286     "p=" << mesh().comm().getRank()
00287     << "communicated DOF answers for cells of dimension 0" );
00288 
00289   
00290   /* now assign the DOFs from the other procs */
00291 
00292   for (int p=0; p<mesh().comm().getNProc(); p++)
00293   {
00294     if (p==mesh().comm().getRank()) continue;
00295     const Array<int>& dofsFromProc = incomingDOFs[p];
00296     int numCells = dofsFromProc.size();
00297     for (int c=0; c<numCells; c++)
00298     {
00299       int cellGID = outgoingCellRequests[p][c];
00300       int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00301       int dof = dofsFromProc[c];
00302       for (int i=0; i<nFuncs_; i++)
00303       {
00304         elemDofs_[cellLID*nFuncs_ + i] = dof+i;
00305         addGhostIndex(dof+i);
00306       }
00307     }
00308   }
00309 }
00310 
00311 
00312 void PartialElementDOFMap::print(std::ostream& os) const
00313 {
00314   os << elemDofs_ << std::endl;
00315 }

Site Contact