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 "SundanceTabs.hpp"
00033 #include "SundanceOut.hpp"
00034 #include "SundanceOrderedTuple.hpp"
00035 #include "SundanceNodalDOFMap.hpp"
00036 #include "SundanceLagrange.hpp"
00037 #include "Teuchos_MPIContainerComm.hpp"
00038 #include "Teuchos_TimeMonitor.hpp"
00039
00040 using namespace Sundance;
00041 using namespace Teuchos;
00042
00043 NodalDOFMap::NodalDOFMap(const Mesh& mesh,
00044 int nFuncs,
00045 const CellFilter& maxCellFilter,
00046 int setupVerb)
00047 : SpatiallyHomogeneousDOFMapBase(mesh, nFuncs, setupVerb),
00048 maxCellFilter_(maxCellFilter),
00049 dim_(mesh.spatialDim()),
00050 nFuncs_(nFuncs),
00051 nElems_(mesh.numCells(mesh.spatialDim())),
00052 nNodes_(mesh.numCells(0)),
00053 nNodesPerElem_(mesh.numFacets(mesh.spatialDim(),0,0)),
00054 elemDofs_(nElems_ * nFuncs * nNodesPerElem_),
00055 nodeDofs_(mesh.numCells(0)*nFuncs_, -1),
00056 structure_(rcp(new MapStructure(nFuncs_, rcp(new Lagrange(1)))))
00057 {
00058 init();
00059 }
00060
00061
00062 RCP<const MapStructure>
00063 NodalDOFMap::getDOFsForCellBatch(int cellDim,
00064 const Array<int>& cellLID,
00065 const Set<int>& requestedFuncSet,
00066 Array<Array<int> >& dofs,
00067 Array<int>& nNodes,
00068 int verbosity) const
00069 {
00070 TimeMonitor timer(batchedDofLookupTimer());
00071
00072 Tabs tab;
00073 SUNDANCE_MSG3(verbosity,
00074 tab << "NodalDOFMap::getDOFsForCellBatch(): cellDim=" << cellDim
00075 << " cellLID=" << cellLID);
00076
00077
00078 dofs.resize(1);
00079 nNodes.resize(1);
00080
00081 int nCells = cellLID.size();
00082
00083
00084 if (cellDim == dim_)
00085 {
00086 int dofsPerElem = nFuncs_ * nNodesPerElem_;
00087 nNodes[0] = nNodesPerElem_;
00088 dofs[0].resize(nCells * dofsPerElem);
00089 Array<int>& dof0 = dofs[0];
00090
00091 for (int c=0; c<nCells; c++)
00092 {
00093 for (int i=0; i<dofsPerElem; i++)
00094 {
00095 dof0[c*dofsPerElem + i] = elemDofs_[cellLID[c]*dofsPerElem+i];
00096 }
00097 }
00098 }
00099 else if (cellDim == 0)
00100 {
00101 nNodes[0] = 1;
00102 dofs[0].resize(nCells * nFuncs_);
00103 Array<int>& dof0 = dofs[0];
00104
00105 for (int c=0; c<nCells; c++)
00106 {
00107 for (int i=0; i<nFuncs_; i++)
00108 {
00109 dof0[c*nFuncs_ + i] = nodeDofs_[cellLID[c]*nFuncs_+i];
00110 }
00111 }
00112 }
00113 else
00114 {
00115 int nFacets = mesh().numFacets(cellDim, cellLID[0], 0);
00116 nNodes[0] = nFacets;
00117 int dofsPerCell = nFuncs_ * nNodes[0];
00118 dofs[0].resize(nCells * dofsPerCell);
00119 Array<int>& dof0 = dofs[0];
00120 Array<int> facetLIDs(nCells * nNodes[0]);
00121 Array<int> dummy(nCells * nNodes[0]);
00122 mesh().getFacetLIDs(cellDim, cellLID, 0, facetLIDs, dummy);
00123
00124 for (int c=0; c<nCells; c++)
00125 {
00126 for (int f=0; f<nFacets; f++)
00127 {
00128 int facetCellLID = facetLIDs[c*nFacets+f];
00129 for (int i=0; i<nFuncs_; i++)
00130 {
00131 dof0[(c*nFuncs_+i)*nFacets + f]
00132 = nodeDofs_[facetCellLID*nFuncs_+i];
00133 }
00134 }
00135 }
00136 }
00137
00138 return structure_;
00139 }
00140
00141
00142
00143 void NodalDOFMap::init()
00144 {
00145 Tabs tab;
00146
00147 SUNDANCE_MSG1(setupVerb(), tab << "initializing nodal DOF map");
00148
00149 Array<Array<int> > remoteNodes(mesh().comm().getNProc());
00150 Array<int> hasProcessedCell(nNodes_, 0);
00151
00152
00153 int nextDOF = 0;
00154 int owner;
00155
00156 int nFacets = mesh().numFacets(dim_, 0, 0);
00157 Array<int> elemLID(nElems_);
00158 Array<int> facetLID(nFacets*nElems_);
00159 Array<int> facetOrientations(nFacets*nElems_);
00160
00161
00162 CellSet maxCells = maxCellFilter_.getCells(mesh());
00163
00164 int cc = 0;
00165 for (CellIterator iter=maxCells.begin(); iter != maxCells.end(); iter++, cc++)
00166 {
00167 int c = *iter;
00168 elemLID[cc] = c;
00169 }
00170
00171 mesh().getFacetLIDs(dim_, elemLID, 0, facetLID, facetOrientations);
00172
00173 for (int c=0; c<nElems_; c++)
00174 {
00175
00176 for (int f=0; f<nFacets; f++)
00177 {
00178
00179
00180 int fLID = facetLID[c*nFacets+f];
00181 if (hasProcessedCell[fLID] == 0)
00182 {
00183
00184 if (isRemote(0, fLID, owner))
00185 {
00186 int facetGID
00187 = mesh().mapLIDToGID(0, fLID);
00188 remoteNodes[owner].append(facetGID);
00189
00190 }
00191 else
00192 {
00193
00194 for (int i=0; i<nFuncs_; i++)
00195 {
00196 nodeDofs_[fLID*nFuncs_ + i] = nextDOF;
00197 nextDOF++;
00198 }
00199 }
00200 hasProcessedCell[fLID] = 1;
00201 }
00202 }
00203 }
00204
00205
00206
00207 int localCount = nextDOF;
00208 computeOffsets(localCount);
00209
00210
00211 shareRemoteDOFs(remoteNodes);
00212
00213
00214
00215 for (int c=0; c<nElems_; c++)
00216 {
00217
00218 for (int f=0; f<nFacets; f++)
00219 {
00220 int fLID = facetLID[c*nFacets+f];
00221 for (int i=0; i<nFuncs_; i++)
00222 {
00223 elemDofs_[(c*nFuncs_+i)*nFacets + f] = nodeDofs_[fLID*nFuncs_ + i];
00224 }
00225 }
00226 }
00227
00228 }
00229
00230
00231 void NodalDOFMap::computeOffsets(int localCount)
00232 {
00233 Array<int> dofOffsets;
00234 int totalDOFCount;
00235 int myOffset = 0;
00236 int np = mesh().comm().getNProc();
00237 if (np > 1)
00238 {
00239 MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00240 mesh().comm());
00241 myOffset = dofOffsets[mesh().comm().getRank()];
00242
00243 int nDofs = nNodes_ * nFuncs_;
00244 for (int i=0; i<nDofs; i++)
00245 {
00246 if (nodeDofs_[i] >= 0) nodeDofs_[i] += myOffset;
00247 }
00248 }
00249 else
00250 {
00251 totalDOFCount = localCount;
00252 }
00253
00254 setLowestLocalDOF(myOffset);
00255 setNumLocalDOFs(localCount);
00256 setTotalNumDOFs(totalDOFCount);
00257 }
00258
00259
00260 void NodalDOFMap::shareRemoteDOFs(const Array<Array<int> >& outgoingCellRequests)
00261 {
00262 int np = mesh().comm().getNProc();
00263 if (np==1) return;
00264 int rank = mesh().comm().getRank();
00265
00266 Array<Array<int> > incomingCellRequests;
00267 Array<Array<int> > outgoingDOFs(np);
00268 Array<Array<int> > incomingDOFs;
00269
00270 SUNDANCE_MSG2(setupVerb(),
00271 "p=" << mesh().comm().getRank()
00272 << "synchronizing DOFs for cells of dimension 0");
00273 SUNDANCE_MSG2(setupVerb(),
00274 "p=" << mesh().comm().getRank()
00275 << " sending cell reqs d=0, GID="
00276 << outgoingCellRequests);
00277
00278
00279 MPIContainerComm<int>::allToAll(outgoingCellRequests,
00280 incomingCellRequests,
00281 mesh().comm());
00282
00283
00284
00285 for (int p=0; p<np; p++)
00286 {
00287 if (p==rank) continue;
00288 const Array<int>& requestsFromProc = incomingCellRequests[p];
00289 int nReq = requestsFromProc.size();
00290
00291 SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank()
00292 << " recv'd from proc=" << p
00293 << " reqs for DOFs for cells "
00294 << requestsFromProc);
00295
00296 outgoingDOFs[p].resize(nReq);
00297
00298 for (int c=0; c<nReq; c++)
00299 {
00300 int GID = requestsFromProc[c];
00301 SUNDANCE_MSG3(setupVerb(),
00302 "p=" << rank
00303 << " processing zero-cell with GID=" << GID);
00304 int LID = mesh().mapGIDToLID(0, GID);
00305 SUNDANCE_MSG3(setupVerb(),
00306 "p=" << rank
00307 << " LID=" << LID << " dofs="
00308 << nodeDofs_[LID*nFuncs_]);
00309 outgoingDOFs[p][c] = nodeDofs_[LID*nFuncs_];
00310 SUNDANCE_MSG3(setupVerb(),
00311 "p=" << rank
00312 << " done processing cell with GID=" << GID);
00313 }
00314 }
00315
00316 SUNDANCE_MSG2(setupVerb(),
00317 "p=" << mesh().comm().getRank()
00318 << "answering DOF requests for cells of dimension 0");
00319
00320
00321 MPIContainerComm<int>::allToAll(outgoingDOFs,
00322 incomingDOFs,
00323 mesh().comm());
00324
00325 SUNDANCE_MSG2(setupVerb(),
00326 "p=" << mesh().comm().getRank()
00327 << "communicated DOF answers for cells of dimension 0" );
00328
00329
00330
00331
00332 for (int p=0; p<mesh().comm().getNProc(); p++)
00333 {
00334 if (p==mesh().comm().getRank()) continue;
00335 const Array<int>& dofsFromProc = incomingDOFs[p];
00336 int numCells = dofsFromProc.size();
00337 for (int c=0; c<numCells; c++)
00338 {
00339 int cellGID = outgoingCellRequests[p][c];
00340 int cellLID = mesh().mapGIDToLID(0, cellGID);
00341 int dof = dofsFromProc[c];
00342 for (int i=0; i<nFuncs_; i++)
00343 {
00344 nodeDofs_[cellLID*nFuncs_ + i] = dof+i;
00345 addGhostIndex(dof+i);
00346 }
00347 }
00348 }
00349 }