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

Site Contact