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 "SundanceSubmaximalNodalDOFMap.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 
00046 SubmaximalNodalDOFMap
00047 ::SubmaximalNodalDOFMap(const Mesh& mesh, 
00048   const CellFilter& cf,
00049   int nFuncs,
00050   int setupVerb)
00051   : DOFMapBase(mesh, setupVerb),
00052     dim_(0),
00053     nTotalFuncs_(nFuncs),
00054     domain_(cf),
00055     domains_(tuple(cf)),
00056     nodeLIDs_(),
00057     nodeDOFs_(),
00058     lidToPtrMap_(),
00059     mapStructure_()
00060 {
00061   Tabs tab0(0);
00062   SUNDANCE_MSG1(setupVerb, tab0 << "in SubmaximalNodalDOFMap ctor");
00063   Tabs tab1;
00064   SUNDANCE_MSG2(setupVerb, tab1 << "domain " << domain_);
00065   SUNDANCE_MSG2(setupVerb, tab1 << "N funcs " << nFuncs);
00066 
00067   const MPIComm& comm = mesh.comm();
00068   int rank = comm.getRank();
00069   int nProc = comm.getNProc();
00070   
00071   dim_ = cf.dimension(mesh);  
00072   TEUCHOS_TEST_FOR_EXCEPT(dim_ != 0);
00073 
00074   CellSet nodes = cf.getCells(mesh);
00075   int nc = nodes.numCells();
00076   nodeLIDs_.reserve(nc);
00077   nodeDOFs_.reserve(nc);
00078 
00079   Array<Array<int> > remoteNodes(nProc);
00080   
00081   int nextDOF = 0;
00082   int k=0; 
00083   for (CellIterator c=nodes.begin(); c!=nodes.end(); c++, k++)
00084   {
00085     int nodeLID = *c;
00086     lidToPtrMap_.put(nodeLID, k);
00087     nodeLIDs_.append(nodeLID);
00088     int remoteOwner = rank;
00089     if (isRemote(0, nodeLID, remoteOwner))
00090     {
00091       int GID = mesh.mapLIDToGID(0, nodeLID);
00092       remoteNodes[remoteOwner].append(GID);
00093       for (int f=0; f<nFuncs; f++) nodeDOFs_.append(-1);
00094     }
00095     else
00096     {
00097       for (int f=0; f<nFuncs; f++) nodeDOFs_.append(nextDOF++);
00098     }
00099   }
00100 
00101   
00102   int localCount = nextDOF;
00103   computeOffsets(localCount);
00104   
00105   
00106   shareRemoteDOFs(remoteNodes);
00107 
00108   BasisFamily basis = new Lagrange(1);
00109   mapStructure_ = rcp(new MapStructure(nTotalFuncs_, basis.ptr()));
00110 }
00111 
00112 void SubmaximalNodalDOFMap::computeOffsets(int localCount)
00113 {
00114   Array<int> dofOffsets;
00115   int totalDOFCount;
00116   int myOffset = 0;
00117   int np = mesh().comm().getNProc();
00118   if (np > 1)
00119   {
00120     MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00121       mesh().comm());
00122     myOffset = dofOffsets[mesh().comm().getRank()];
00123     
00124     int nDofs = nodeDOFs_.size();
00125     for (int i=0; i<nDofs; i++)
00126     {
00127       if (nodeDOFs_[i] >= 0) nodeDOFs_[i] += myOffset;
00128     }
00129   }
00130   else
00131   {
00132     totalDOFCount = localCount;
00133   }
00134   
00135   setLowestLocalDOF(myOffset);
00136   setNumLocalDOFs(localCount);
00137   setTotalNumDOFs(totalDOFCount);
00138 }
00139 
00140 
00141 void SubmaximalNodalDOFMap::shareRemoteDOFs(
00142   const Array<Array<int> >& outgoingNodeRequests)
00143 {
00144   int np = mesh().comm().getNProc();
00145   if (np==1) return;
00146   int rank = mesh().comm().getRank();
00147 
00148   int nFuncs = nTotalFuncs_;
00149 
00150   Array<Array<int> > incomingNodeRequests;
00151   Array<Array<int> > outgoingDOFs(np);
00152   Array<Array<int> > incomingDOFs;
00153 
00154   SUNDANCE_MSG2(setupVerb(),  
00155     "p=" << mesh().comm().getRank()
00156     << "synchronizing DOFs for cells of dimension 0");
00157   SUNDANCE_MSG2(setupVerb(),  
00158     "p=" << mesh().comm().getRank()
00159     << " sending cell reqs d=0, GID=" 
00160     << outgoingNodeRequests);
00161 
00162   
00163   MPIContainerComm<int>::allToAll(outgoingNodeRequests, 
00164     incomingNodeRequests,
00165     mesh().comm());
00166   
00167   
00168 
00169   for (int p=0; p<np; p++)
00170   {
00171     if (p==rank) continue;
00172     const Array<int>& requestsFromProc = incomingNodeRequests[p];
00173     int nReq = requestsFromProc.size();
00174 
00175     SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank() 
00176       << " recv'd from proc=" << p
00177       << " reqs for DOFs for cells " 
00178       << requestsFromProc);
00179 
00180     outgoingDOFs[p].resize(nReq);
00181 
00182     for (int c=0; c<nReq; c++)
00183     {
00184       int GID = requestsFromProc[c];
00185       SUNDANCE_MSG3(setupVerb(),  
00186         "p=" << rank
00187         << " processing zero-cell with GID=" << GID); 
00188       int LID = mesh().mapGIDToLID(0, GID);
00189       SUNDANCE_MSG3(setupVerb(),  
00190         "p=" << rank
00191         << " LID=" << LID << " dofs=" 
00192         << nodeDOFs_[LID*nFuncs]);
00193       outgoingDOFs[p][c] = nodeDOFs_[LID*nFuncs];
00194       SUNDANCE_MSG3(setupVerb(),  
00195         "p=" << rank
00196         << " done processing cell with GID=" << GID);
00197     }
00198   }
00199 
00200   SUNDANCE_MSG2(setupVerb(),  
00201     "p=" << mesh().comm().getRank()
00202     << "answering DOF requests for cells of dimension 0");
00203 
00204   
00205   MPIContainerComm<int>::allToAll(outgoingDOFs,
00206     incomingDOFs,
00207     mesh().comm());
00208 
00209   SUNDANCE_MSG2(setupVerb(),  
00210     "p=" << mesh().comm().getRank()
00211     << "communicated DOF answers for cells of dimension 0" );
00212 
00213   
00214   
00215 
00216   for (int p=0; p<mesh().comm().getNProc(); p++)
00217   {
00218     if (p==mesh().comm().getRank()) continue;
00219     const Array<int>& dofsFromProc = incomingDOFs[p];
00220     int numCells = dofsFromProc.size();
00221     for (int c=0; c<numCells; c++)
00222     {
00223       int cellGID = outgoingNodeRequests[p][c];
00224       int cellLID = mesh().mapGIDToLID(0, cellGID);
00225       int dof = dofsFromProc[c];
00226       for (int i=0; i<nFuncs; i++)
00227       {
00228         nodeDOFs_[cellLID*nFuncs + i] = dof+i;
00229         addGhostIndex(dof+i);
00230       }
00231     }
00232   }
00233 }
00234 
00235 
00236 
00237 RCP<const Set<int> >
00238 SubmaximalNodalDOFMap::allowedFuncsOnCellBatch(int cellDim,
00239   const Array<int>& cellLID) const 
00240 {
00241   Set<int> rtn;
00242   for (int f=0; f<nTotalFuncs_; f++) rtn.put(f);
00243   return rcp(new Set<int>(rtn));
00244 }
00245 
00246 
00247 RCP<const MapStructure> 
00248 SubmaximalNodalDOFMap::getDOFsForCellBatch(int cellDim,
00249   const Array<int>& cellLID,
00250   const Set<int>& requestedFuncSet,
00251   Array<Array<int> >& dofs,
00252   Array<int>& nNodes,
00253   int verb) const 
00254 {
00255   TimeMonitor timer(batchedDofLookupTimer());
00256   Tabs tab0;
00257 
00258   SUNDANCE_MSG2(verb, tab0 << "in SubmaximalNodalDOFMap::getDOFsForCellBatch()");
00259 
00260   TEUCHOS_TEST_FOR_EXCEPT(cellDim != 0);
00261 
00262   dofs.resize(1);
00263   nNodes.resize(1);
00264   nNodes[0] = 1;
00265 
00266   dofs[0].reserve(cellLID.size()*nTotalFuncs_);
00267 
00268   for (int c=0; c<cellLID.size(); c++)
00269   {
00270     int lid = cellLID[c];
00271     int ptr = lidToPtrMap_.get(lid);
00272     for (int f=0; f<nTotalFuncs_; f++)
00273     {
00274       int q = ptr*nTotalFuncs_;
00275       dofs[0].append(nodeDOFs_[q + f]);
00276     }
00277   }
00278 
00279   return mapStructure_;
00280 }
00281 
00282 
00283 
00284 void SubmaximalNodalDOFMap::print(std::ostream& os) const
00285 {
00286   Tabs tab0(0);
00287   Out::os() << tab0 << "submaximal nodal dof map: " << std::endl;
00288   Tabs tab1;
00289   Out::os() << tab1 << "0-cells: " << std::endl;
00290   for (int c=0; c<nodeLIDs_.size(); c++)
00291   {
00292     Tabs tab2;
00293     int gid = mesh().mapLIDToGID(0, nodeLIDs_[c]);
00294     Out::os() << tab2 << "G=" << gid << " dofs={";
00295     for (int f=0; f<nTotalFuncs_; f++)
00296     {
00297       if (f != 0) Out::os() << ", ";
00298       Out::os() << nodeDOFs_[c*nTotalFuncs_ + f];
00299     }
00300     Out::os() << "}" << std::endl;
00301   }
00302 }