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

Site Contact