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