00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
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   
00141   int nextDOF = 0;
00142   int owner;
00143 
00144   
00145   CellSet maxCells = subdomain_.getCells(mesh());
00146 
00147   for (CellIterator iter=maxCells.begin(); iter != maxCells.end(); iter++)
00148   {
00149     int cellLID = *iter;
00150     
00151     if (isRemote(cellDim, cellLID, owner))
00152     {
00153       int elemGID = mesh().mapLIDToGID(cellDim, cellLID);
00154       remoteElems[owner].append(elemGID);
00155     }                  
00156     else 
00157     {
00158       
00159       for (int i=0; i<nFuncs_; i++)
00160       {
00161         elemDofs_[cellLID*nFuncs_ + i] = nextDOF;
00162         nextDOF++;
00163       }
00164     }
00165   }
00166   
00167   
00168   int localCount = nextDOF;
00169   computeOffsets(localCount);
00170   
00171   
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   
00241   MPIContainerComm<int>::allToAll(outgoingCellRequests, 
00242     incomingCellRequests,
00243     mesh().comm());
00244   
00245   
00246 
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   
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   
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 }