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 "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
00113 int localCount = nextDOF;
00114 computeOffsets(localCount);
00115
00116
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
00174 MPIContainerComm<int>::allToAll(outgoingNodeRequests,
00175 incomingNodeRequests,
00176 mesh().comm());
00177
00178
00179
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
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
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 }