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

Site Contact