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 "SundanceMixedDOFMap.hpp"
00043 #include "SundanceBasisDOFTopologyBase.hpp"
00044 #include "SundanceCellFilter.hpp"
00045 #include "SundanceMaximalCellFilter.hpp"
00046 #include "PlayaMPIContainerComm.hpp"
00047 #include "SundanceOut.hpp"
00048 #include "PlayaTabs.hpp"
00049 #include "Teuchos_Time.hpp"
00050 #include "Teuchos_TimeMonitor.hpp"
00051
00052
00053 using namespace Sundance;
00054 using namespace Teuchos;
00055 using Playa::MPIComm;
00056 using Playa::MPIContainerComm;
00057 using Playa::MPIDataType;
00058 using Playa::MPIOp;
00059
00060
00061 static Time& mixedDOFCtorTimer()
00062 {
00063 static RCP<Time> rtn
00064 = TimeMonitor::getNewTimer("mixed DOF map init");
00065 return *rtn;
00066 }
00067 static Time& maxDOFBuildTimer()
00068 {
00069 static RCP<Time> rtn
00070 = TimeMonitor::getNewTimer("max-cell dof table init");
00071 return *rtn;
00072 }
00073
00074 MixedDOFMap::MixedDOFMap(const Mesh& mesh,
00075 const Array<RCP<BasisDOFTopologyBase> >& basis,
00076 const CellFilter& maxCells,
00077 int setupVerb)
00078 : SpatiallyHomogeneousDOFMapBase(mesh, basis.size(), setupVerb),
00079 maxCells_(maxCells),
00080 dim_(mesh.spatialDim()),
00081 dofs_(mesh.spatialDim()+1),
00082 maximalDofs_(),
00083 haveMaximalDofs_(false),
00084 localNodePtrs_(),
00085 nNodesPerCell_(),
00086 totalNNodesPerCell_(),
00087 cellHasAnyDOFs_(dim_+1),
00088 numFacets_(mesh.spatialDim()+1),
00089 originalFacetOrientation_(2),
00090 hasBeenAssigned_(mesh.spatialDim()+1),
00091 structure_(),
00092 nFuncs_()
00093 {
00094 TimeMonitor timer(mixedDOFCtorTimer());
00095 Tabs tab;
00096 SUNDANCE_MSG1(setupVerb, tab << "building mixed DOF map");
00097
00098 Sundance::Map<OrderedHandle<BasisDOFTopologyBase>, int> basisToChunkMap;
00099 Array<RCP<BasisDOFTopologyBase> > chunkBases;
00100 Array<Array<int> > chunkFuncs;
00101
00102 int chunk = 0;
00103 int nBasis = basis.size();
00104 for (int i=0; i<nBasis; i++)
00105 {
00106 OrderedHandle<BasisDOFTopologyBase> bh = basis[i];
00107 if (!basisToChunkMap.containsKey(bh))
00108 {
00109 chunkBases.append(basis[i]);
00110 basisToChunkMap.put(bh, chunk);
00111 chunkFuncs.append(tuple(i));
00112 chunk++;
00113 }
00114 else
00115 {
00116 int b = basisToChunkMap.get(bh);
00117 chunkFuncs[b].append(i);
00118 }
00119 }
00120
00121 Tabs tab1;
00122 SUNDANCE_MSG2(setupVerb, tab1 << "basis to chunk map = " << basisToChunkMap);
00123
00124
00125 structure_ = rcp(new MapStructure(basis.size(), chunkBases, chunkFuncs));
00126
00127 nFuncs_.resize(chunkBases.size());
00128 for (int i=0; i<nFuncs_.size(); i++)
00129 nFuncs_[i] = chunkFuncs[i].size();
00130
00131 allocate(mesh);
00132
00133 initMap();
00134
00135 buildMaximalDofTable();
00136
00137
00138 checkTable();
00139
00140 SUNDANCE_MSG1(setupVerb, tab << "done building mixed DOF map");
00141 }
00142
00143
00144 void MixedDOFMap::allocate(const Mesh& mesh)
00145 {
00146 Tabs tab;
00147
00148
00149 SUNDANCE_MSG1(setupVerb(), tab << "grouping like basis functions");
00150
00151
00152
00153 localNodePtrs_.resize(nBasisChunks());
00154 nNodesPerCell_.resize(nBasisChunks());
00155 totalNNodesPerCell_.resize(nBasisChunks());
00156 nDofsPerCell_.resize(nBasisChunks());
00157 totalNDofsPerCell_.resize(nBasisChunks());
00158 maximalDofs_.resize(nBasisChunks());
00159
00160 for (int b=0; b<nBasisChunks(); b++)
00161 {
00162 localNodePtrs_[b].resize(mesh.spatialDim()+1);
00163 nNodesPerCell_[b].resize(mesh.spatialDim()+1);
00164 totalNNodesPerCell_[b].resize(mesh.spatialDim()+1);
00165 nDofsPerCell_[b].resize(mesh.spatialDim()+1);
00166 totalNDofsPerCell_[b].resize(mesh.spatialDim()+1);
00167 }
00168
00169
00170
00171 SUNDANCE_MSG1(setupVerb(), tab << "working out DOF map node counts");
00172
00173 numFacets_.resize(dim_+1);
00174
00175 for (int d=0; d<=dim_; d++)
00176 {
00177 Tabs tab1;
00178 SUNDANCE_MSG2(setupVerb(), tab << "allocating maps for cell dim=" << d);
00179
00180
00181 numFacets_[d].resize(d);
00182 for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00183 SUNDANCE_MSG3(setupVerb(), tab1 << "num facets for dimension " << d << " is "
00184 << numFacets_[d]);
00185
00186 cellHasAnyDOFs_[d] = false;
00187 dofs_[d].resize(nBasisChunks());
00188
00189 int numCells = mesh.numCells(d);
00190 hasBeenAssigned_[d].resize(numCells);
00191
00192 for (int b=0; b<nBasisChunks(); b++)
00193 {
00194 Tabs tab2;
00195 SUNDANCE_MSG2(setupVerb(), tab1 << "basis chunk=" << b);
00196 SUNDANCE_MSG2(setupVerb(), tab2 << "basis=" << basis(b)->description());
00197 int nNodes = basis(b).ptr()->nReferenceDOFsWithFacets(mesh.cellType(dim_), mesh.cellType(d));
00198 SUNDANCE_MSG2(setupVerb(), tab2 << "nNodes per cell=" << nNodes);
00199 if (nNodes == 0)
00200 {
00201 nNodesPerCell_[b][d] = 0;
00202 nDofsPerCell_[b][d] = 0;
00203 }
00204 else
00205 {
00206
00207
00208 basis(b).ptr()->getReferenceDOFs(mesh.cellType(dim_),
00209 mesh.cellType(d),
00210 localNodePtrs_[b][d]);
00211
00212
00213 SUNDANCE_MSG3(setupVerb(), tab2 << "node ptrs are "
00214 << localNodePtrs_[b][d]);
00215
00216
00217
00218 if (localNodePtrs_[b][d][d].size() > 0)
00219 {
00220 nNodesPerCell_[b][d] = localNodePtrs_[b][d][d][0].size();
00221 if (nNodesPerCell_[b][d] > 0) cellHasAnyDOFs_[d] = true;
00222 }
00223 else
00224 {
00225 nNodesPerCell_[b][d] = 0;
00226 }
00227 nDofsPerCell_[b][d] = nNodesPerCell_[b][d] * nFuncs(b);
00228 }
00229
00230
00231
00232
00233
00234 if (nDofsPerCell_[b][d] > 0 && d > 0 && d < mesh.spatialDim())
00235 {
00236 Mesh& tmpMesh = const_cast<Mesh&>(mesh);
00237 tmpMesh.assignIntermediateCellGIDs(d);
00238 }
00239
00240 SUNDANCE_MSG3(setupVerb(), tab2 <<
00241 "num nodes is "
00242 << nNodesPerCell_[b][d]);
00243
00244 totalNNodesPerCell_[b][d] = nNodesPerCell_[b][d];
00245 for (int dd=0; dd<d; dd++)
00246 {
00247 totalNNodesPerCell_[b][d]
00248 += numFacets_[d][dd]*nNodesPerCell_[b][dd];
00249 }
00250 totalNDofsPerCell_[b][d] = totalNNodesPerCell_[b][d] * nFuncs(b);
00251 SUNDANCE_MSG3(setupVerb(), tab2 << "totalNDofsPerCell " << totalNDofsPerCell_[b][d]);
00252
00253 if (nNodes > 0)
00254 {
00255
00256 dofs_[d][b].resize(nDofsPerCell_[b][d] * numCells);
00257
00258
00259 int nDof = dofs_[d][b].size();
00260 Array<int>& dofs = dofs_[d][b];
00261 int marker = uninitializedVal();
00262 for (int i=0; i<nDof; i++)
00263 {
00264 dofs[i] = marker;
00265 }
00266 }
00267
00268 if (d==dim_)
00269 {
00270 maximalDofs_[b].resize(totalNDofsPerCell_[b][d]*numCells);
00271 }
00272 }
00273
00274
00275 if (d > 0 && d < dim_)
00276 {
00277 originalFacetOrientation_[d-1].resize(numCells);
00278 }
00279
00280 }
00281 SUNDANCE_MSG1(setupVerb(), tab << "done allocating DOF map");
00282 }
00283
00284 void MixedDOFMap::initMap()
00285 {
00286 Tabs tab;
00287 SUNDANCE_MSG1(setupVerb(), tab << "initializing DOF map");
00288
00289 int nextDOF = 0;
00290
00291
00292
00293
00294 Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1);
00295
00296 for (int d=0; d<remoteCells.size(); d++)
00297 remoteCells[d].resize(mesh().comm().getNProc());
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 CellSet cells = maxCells_.getCells(mesh());
00308 CellIterator iter;
00309 for (iter=cells.begin(); iter != cells.end(); iter++)
00310 {
00311
00312 int cellLID = *iter;
00313 int owner;
00314
00315 if (cellHasAnyDOFs_[dim_])
00316 {
00317
00318
00319
00320 if (isRemote(dim_, cellLID, owner))
00321 {
00322 int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00323 SUNDANCE_MSG4(setupVerb(), "proc=" << comm().getRank()
00324 << " thinks d-" << dim_
00325 << " cell GID=" << cellGID
00326 << " is owned remotely by p="
00327 << owner);
00328 remoteCells[dim_][owner].append(cellGID);
00329 }
00330 else
00331
00332 {
00333 for (int b=0; b<nBasisChunks(); b++)
00334 {
00335 setDOFs(b, dim_, cellLID, nextDOF);
00336 }
00337 }
00338 }
00339
00340
00341 for (int d=0; d<dim_; d++)
00342 {
00343 if (cellHasAnyDOFs_[d])
00344 {
00345 int nf = numFacets_[dim_][d];
00346 Array<int> facetLID(nf);
00347 Array<int> facetOrientations(nf);
00348
00349 mesh().getFacetArray(dim_, cellLID, d,
00350 facetLID, facetOrientations);
00351
00352 for (int f=0; f<nf; f++)
00353 {
00354
00355
00356 if (!hasBeenAssigned(d, facetLID[f]))
00357 {
00358 markAsAssigned(d, facetLID[f]);
00359
00360 if (isRemote(d, facetLID[f], owner))
00361 {
00362 int facetGID
00363 = mesh().mapLIDToGID(d, facetLID[f]);
00364 SUNDANCE_MSG4(setupVerb(), "proc=" << comm().getRank()
00365 << " thinks d-" << d
00366 << " cell GID=" << facetGID
00367 << " is owned remotely by p=" << owner);
00368 remoteCells[d][owner].append(facetGID);
00369 }
00370 else
00371 {
00372
00373 for (int b=0; b<nBasisChunks(); b++)
00374 {
00375 setDOFs(b, d, facetLID[f], nextDOF);
00376 }
00377
00378 if (d > 0)
00379 {
00380 originalFacetOrientation_[d-1][facetLID[f]]
00381 = facetOrientations[f];
00382 }
00383 }
00384 }
00385 }
00386 }
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395 int numLocalDOFs = nextDOF;
00396 if (mesh().comm().getNProc() > 1)
00397 {
00398 for (int d=0; d<=dim_; d++)
00399 {
00400 if (cellHasAnyDOFs_[d])
00401 {
00402 computeOffsets(d, numLocalDOFs);
00403 shareDOFs(d, remoteCells[d]);
00404 }
00405 }
00406 }
00407 else
00408 {
00409 setLowestLocalDOF(0);
00410 setNumLocalDOFs(numLocalDOFs);
00411 setTotalNumDOFs(numLocalDOFs);
00412 }
00413 SUNDANCE_MSG1(setupVerb(), tab << "done initializing DOF map");
00414 }
00415
00416 void MixedDOFMap::shareDOFs(int cellDim,
00417 const Array<Array<int> >& outgoingCellRequests)
00418 {
00419 int np = mesh().comm().getNProc();
00420 int rank = mesh().comm().getRank();
00421
00422 Array<Array<int> > incomingCellRequests;
00423 Array<Array<int> > outgoingDOFs(np);
00424 Array<Array<int> > incomingDOFs;
00425
00426 SUNDANCE_MSG2(setupVerb(),
00427 "p=" << mesh().comm().getRank()
00428 << "synchronizing DOFs for cells of dimension " << cellDim);
00429 SUNDANCE_MSG2(setupVerb(),
00430 "p=" << mesh().comm().getRank()
00431 << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00432
00433
00434 MPIContainerComm<int>::allToAll(outgoingCellRequests,
00435 incomingCellRequests,
00436 mesh().comm());
00437
00438
00439
00440
00441
00442 int blockSize = 0;
00443 bool sendOrientation = false;
00444 for (int b=0; b<nBasisChunks(); b++)
00445 {
00446 int nDofs = nDofsPerCell_[b][cellDim];
00447 if (nDofs > 0) blockSize++;
00448 if (nDofs > 1 && cellDim > 0 && cellDim < dim_) sendOrientation = true;
00449 }
00450 blockSize += sendOrientation;
00451
00452 SUNDANCE_MSG2(setupVerb(),
00453 "p=" << rank
00454 << "recvd DOF requests for cells of dimension " << cellDim
00455 << " GID=" << incomingCellRequests);
00456
00457
00458
00459 for (int p=0; p<np; p++)
00460 {
00461 if (p==rank) continue;
00462 const Array<int>& requestsFromProc = incomingCellRequests[p];
00463 int nReq = requestsFromProc.size();
00464
00465 SUNDANCE_MSG4(setupVerb(), "p=" << mesh().comm().getRank()
00466 << " recv'd from proc=" << p
00467 << " reqs for DOFs for cells "
00468 << requestsFromProc);
00469
00470 outgoingDOFs[p].resize(nReq * blockSize);
00471
00472 for (int c=0; c<nReq; c++)
00473 {
00474 int GID = requestsFromProc[c];
00475 SUNDANCE_MSG3(setupVerb(),
00476 "p=" << rank
00477 << " processing cell with d=" << cellDim
00478 << " GID=" << GID);
00479 int LID = mesh().mapGIDToLID(cellDim, GID);
00480 SUNDANCE_MSG3(setupVerb(),
00481 "p=" << rank
00482 << " LID=" << LID << " dofs=" << dofs_[cellDim]);
00483 int blockOffset = 0;
00484 for (int b=0; b<nBasisChunks(); b++)
00485 {
00486 if (nDofsPerCell_[b][cellDim] == 0) continue;
00487 outgoingDOFs[p][blockSize*c+blockOffset]
00488 = getInitialDOFForCell(cellDim, LID, b);
00489 blockOffset++;
00490 }
00491 if (sendOrientation)
00492 {
00493 outgoingDOFs[p][blockSize*(c+1) - 1]
00494 = originalFacetOrientation_[cellDim-1][LID];
00495 }
00496 SUNDANCE_MSG3(setupVerb(),
00497 "p=" << rank
00498 << " done processing cell with GID=" << GID);
00499 }
00500 }
00501
00502
00503 SUNDANCE_MSG2(setupVerb(),
00504 "p=" << mesh().comm().getRank()
00505 << "answering DOF requests for cells of dimension " << cellDim);
00506
00507
00508 MPIContainerComm<int>::allToAll(outgoingDOFs,
00509 incomingDOFs,
00510 mesh().comm());
00511
00512 SUNDANCE_MSG2(setupVerb(),
00513 "p=" << mesh().comm().getRank()
00514 << "communicated DOF answers for cells of dimension " << cellDim);
00515
00516
00517
00518
00519 for (int p=0; p<mesh().comm().getNProc(); p++)
00520 {
00521 if (p==mesh().comm().getRank()) continue;
00522 const Array<int>& dofsFromProc = incomingDOFs[p];
00523 int numCells = dofsFromProc.size()/blockSize;
00524 for (int c=0; c<numCells; c++)
00525 {
00526 int cellGID = outgoingCellRequests[p][c];
00527 int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00528 int blockOffset = 0;
00529 for (int b=0; b<nBasisChunks(); b++)
00530 {
00531 if (nDofsPerCell_[b][cellDim] == 0) continue;
00532 int dof = dofsFromProc[blockSize*c+blockOffset];
00533 setDOFs(b, cellDim, cellLID, dof, true);
00534 blockOffset++;
00535 }
00536 if (sendOrientation)
00537 {
00538 originalFacetOrientation_[cellDim-1][cellLID]
00539 = dofsFromProc[blockSize*(c+1)-1];
00540 }
00541 }
00542 }
00543
00544 }
00545
00546
00547
00548 void MixedDOFMap::setDOFs(int basisChunk, int cellDim, int cellLID,
00549 int& nextDOF, bool isRemote)
00550 {
00551 Tabs tab;
00552 SUNDANCE_MSG3(setupVerb(), tab << "setting DOFs for " << cellDim
00553 << "-cell " << cellLID);
00554 int nDofs = nDofsPerCell_[basisChunk][cellDim];
00555 if (nDofs==0) return;
00556
00557 int* ptr = getInitialDOFPtrForCell(cellDim, cellLID, basisChunk);
00558
00559 if (isRemote)
00560 {
00561 for (int i=0; i<nDofs; i++, nextDOF++)
00562 {
00563 ptr[i] = nextDOF;;
00564 addGhostIndex(nextDOF);
00565 }
00566 }
00567 else
00568 {
00569 for (int i=0; i<nDofs; i++,nextDOF++)
00570 {
00571 ptr[i] = nextDOF;
00572 }
00573 }
00574 }
00575
00576
00577
00578 RCP<const MapStructure> MixedDOFMap
00579 ::getDOFsForCellBatch(int cellDim,
00580 const Array<int>& cellLID,
00581 const Set<int>& requestedFuncSet,
00582 Array<Array<int> >& dofs,
00583 Array<int>& nNodes,
00584 int verbosity) const
00585 {
00586 TimeMonitor timer(batchedDofLookupTimer());
00587
00588 Tabs tab;
00589 SUNDANCE_MSG3(verbosity,
00590 tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00591 << " cellLID=" << cellLID);
00592
00593 dofs.resize(nBasisChunks());
00594 nNodes.resize(nBasisChunks());
00595
00596 int nCells = cellLID.size();
00597
00598 if (cellDim == dim_)
00599 {
00600 Tabs tab1;
00601
00602 if (!haveMaximalDofs_)
00603 {
00604 buildMaximalDofTable();
00605 }
00606
00607 SUNDANCE_MSG4(verbosity, tab1 << "getting dofs for maximal cells");
00608
00609 for (int b=0; b<nBasisChunks(); b++)
00610 {
00611 nNodes[b] = totalNNodesPerCell_[b][cellDim];
00612 dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00613 int dofsPerCell = nFuncs(b)*nNodes[b];
00614 Array<int>& chunkDofs = dofs[b];
00615 for (int c=0; c<nCells; c++)
00616 {
00617 for (int i=0; i<dofsPerCell; i++)
00618 {
00619 chunkDofs[c*dofsPerCell + i]
00620 = maximalDofs_[b][cellLID[c]*dofsPerCell+i];
00621 }
00622 }
00623 }
00624 }
00625 else
00626 {
00627 Tabs tab1;
00628 SUNDANCE_MSG4(verbosity, tab1 << "getting dofs for non-maximal cells");
00629
00630 static Array<Array<int> > facetLID(3);
00631 static Array<Array<int> > facetOrientations(3);
00632 static Array<int> numFacets(3);
00633
00634 for (int d=0; d<cellDim; d++)
00635 {
00636 numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00637 mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d],
00638 facetOrientations[d]);
00639 }
00640
00641 for (int b=0; b<nBasisChunks(); b++)
00642 {
00643 nNodes[b] = totalNNodesPerCell_[b][cellDim];
00644 dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00645 int dofsPerCell = nFuncs(b)*nNodes[b];
00646
00647 Array<int>& toPtr = dofs[b];
00648 int nf = nFuncs(b);
00649
00650 for (int c=0; c<nCells; c++)
00651 {
00652 Tabs tab2;
00653 SUNDANCE_MSG4(verbosity, tab2 << "cell=" << c);
00654 int offset = dofsPerCell*c;
00655
00656
00657
00658 SUNDANCE_MSG4(verbosity, tab2 << "doing interior nodes");
00659 int nInteriorNodes = nNodesPerCell_[b][cellDim];
00660
00661 if (nInteriorNodes > 0)
00662 {
00663 if (cellDim==0 || nInteriorNodes <= 1)
00664 {
00665
00666
00667
00668 for (int func=0; func<nf; func++)
00669 {
00670 for (int n=0; n<nInteriorNodes; n++)
00671 {
00672 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00673 toPtr[offset + func*nNodes[b] + ptr]
00674 = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00675
00676 }
00677 }
00678 }
00679 else
00680 {
00681 int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00682 int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00683
00684
00685
00686 for (int func=0; func<nf; func++)
00687 {
00688 for (int m=0; m<nInteriorNodes; m++)
00689 {
00690 int n = m;
00691 if (sign<0) n = nInteriorNodes-1-m;
00692 int ptr = localNodePtrs_[b][cellDim][cellDim][0][m];
00693 toPtr[offset + func*nNodes[b] + ptr] = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00694
00695 }
00696 }
00697 }
00698 }
00699
00700
00701 for (int d=0; d<cellDim; d++)
00702 {
00703 Tabs tab2;
00704 SUNDANCE_MSG4(verbosity, tab2 << "facet dim=" << d);
00705 if (nNodesPerCell_[b][d] == 0) continue;
00706 for (int f=0; f<numFacets[d]; f++)
00707 {
00708 Tabs tab3;
00709 int facetID = facetLID[d][c*numFacets[d]+f];
00710 SUNDANCE_MSG4(verbosity, tab2 << "f=" << f << " facetLID=" << facetID);
00711 if (localNodePtrs_[b][cellDim].size()==0) continue;
00712 int nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00713
00714 int* toPtr1 = &(dofs[b][dofsPerCell*c]);
00715 const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00716 for (int func=0; func<nf; func++)
00717 {
00718 if (d == 0 || nFacetNodes <= 1)
00719 {
00720 for (int n=0; n<nFacetNodes; n++)
00721 {
00722 int ptr = nodePtr[n];
00723 toPtr1[func*nNodes[b] + ptr]
00724 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00725 }
00726 }
00727 else
00728 {
00729 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00730 * originalFacetOrientation_[d-1][facetID];
00731 for (int m=0; m<nFacetNodes; m++)
00732 {
00733 int n = m;
00734 if (facetOrientation<0) n = nFacetNodes-1-m;
00735 int ptr = nodePtr[n];
00736 toPtr1[func*nNodes[b]+ptr]
00737 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00738
00739 }
00740 }
00741 }
00742 }
00743 }
00744 }
00745 }
00746 }
00747 return structure_;
00748 }
00749
00750 void MixedDOFMap::buildMaximalDofTable() const
00751 {
00752 TimeMonitor timer(maxDOFBuildTimer());
00753 Tabs tab;
00754 int cellDim = dim_;
00755 int nCells = mesh().numCells(dim_);
00756
00757 SUNDANCE_MSG2(setupVerb(), tab << "building dofs for maximal cells");
00758
00759 Array<Array<int> > facetLID(3);
00760 Array<Array<int> > facetOrientations(3);
00761 Array<int> numFacets(3);
00762
00763 Array<int> cellLID(nCells);
00764
00765 for (int c=0; c<nCells; c++) cellLID[c]=c;
00766
00767 for (int d=0; d<cellDim; d++)
00768 {
00769 numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00770 mesh().getFacetLIDs(cellDim, cellLID, d,
00771 facetLID[d], facetOrientations[d]);
00772 }
00773
00774 Array<int> nInteriorNodes(nBasisChunks());
00775 Array<int> nNodes(nBasisChunks());
00776 for (int b = 0; b<nBasisChunks(); b++)
00777 {
00778 if (localNodePtrs_[b][cellDim].size() != 0)
00779 {
00780 nInteriorNodes[b] = localNodePtrs_[b][cellDim][cellDim][0].size();
00781 }
00782 else
00783 {
00784 nInteriorNodes[b] = 0;
00785 }
00786 nNodes[b] = totalNNodesPerCell_[b][cellDim];
00787 }
00788
00789 for (int c=0; c<nCells; c++)
00790 {
00791 Tabs tab1;
00792 SUNDANCE_MSG4(setupVerb(), tab1 << "working on cell=" << c
00793 << " LID=" << cellLID[c]);
00794
00795
00796 SUNDANCE_MSG4(setupVerb(), tab1 << "doing interior nodes");
00797 for (int b=0; b<nBasisChunks(); b++)
00798 {
00799 SUNDANCE_MSG4(setupVerb(), tab1 << "basis chunk=" << b);
00800 if (nInteriorNodes[b]>0)
00801 {
00802 SUNDANCE_MSG4(setupVerb(), tab1<< "nInteriorNodes = " <<nInteriorNodes[b]);
00803
00804 int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00805 int nf = nFuncs(b);
00806 for (int func=0; func<nf; func++)
00807 {
00808 for (int n=0; n<nInteriorNodes[b]; n++)
00809 {
00810
00811 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00812 toPtr[func*nNodes[b] + ptr] =
00813 dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00814 }
00815 }
00816 }
00817 }
00818
00819 SUNDANCE_MSG4(setupVerb(), tab1 << "doing facet nodes");
00820
00821 for (int d=0; d<cellDim; d++)
00822 {
00823 Tabs tab2;
00824 SUNDANCE_MSG4(setupVerb(), tab2 << "facet dim=" << d);
00825
00826 for (int f=0; f<numFacets[d]; f++)
00827 {
00828 Tabs tab3;
00829 int facetID = facetLID[d][c*numFacets[d]+f];
00830 SUNDANCE_MSG4(setupVerb(), tab2 << "f=" << f << " facetLID=" << facetID);
00831
00832 for (int b=0; b<nBasisChunks(); b++)
00833 {
00834 Tabs tab4;
00835 SUNDANCE_MSG4(setupVerb(), tab4 << "basis chunk=" << b);
00836 SUNDANCE_MSG4(setupVerb(), tab4 << "num nodes per cell=" << nNodesPerCell_[b][d]);
00837 int nf = nFuncs(b);
00838 if (nDofsPerCell_[b][d]==0) continue;
00839 int nFacetNodes = 0;
00840 if (localNodePtrs_[b][cellDim].size()!=0)
00841 nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00842 if (nFacetNodes == 0) continue;
00843
00844 SUNDANCE_MSG4(setupVerb(), tab4 << "dof table size=" << maximalDofs_[b].size());
00845 int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00846 const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00847 for (int func=0; func<nf; func++)
00848 {
00849 Tabs tab5;
00850 SUNDANCE_MSG4(setupVerb(), tab5 << "func=" << func);
00851 if (d == 0 || nFacetNodes <= 1)
00852 {
00853 Tabs tab6;
00854 for (int n=0; n<nFacetNodes; n++)
00855 {
00856 SUNDANCE_MSG4(setupVerb(), tab5 << "n=" << n);
00857 int ptr = nodePtr[n];
00858 SUNDANCE_MSG4(setupVerb(), tab6 << "ptr=" << ptr);
00859
00860 toPtr[func*nNodes[b] + ptr]
00861 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00862
00863 }
00864 }
00865 else
00866 {
00867 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00868 * originalFacetOrientation_[d-1][facetID];
00869 for (int m=0; m<nFacetNodes; m++)
00870 {
00871 int n = m;
00872 if (facetOrientation<0) n = nFacetNodes-1-m;
00873 int ptr = nodePtr[m];
00874 toPtr[func*nNodes[b]+ptr]
00875 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00876
00877 }
00878 }
00879 }
00880 }
00881 }
00882 }
00883 }
00884
00885 haveMaximalDofs_ = true;
00886
00887 SUNDANCE_MSG2(setupVerb(), tab << "done building dofs for maximal cells");
00888 }
00889
00890
00891
00892
00893
00894 void MixedDOFMap::computeOffsets(int dim, int localCount)
00895 {
00896 if (setupVerb() > 2)
00897 {
00898 comm().synchronize();
00899 comm().synchronize();
00900 comm().synchronize();
00901 comm().synchronize();
00902 }
00903 SUNDANCE_MSG2(setupVerb(),
00904 "p=" << mesh().comm().getRank()
00905 << " sharing offsets for DOF numbering for dim=" << dim);
00906
00907 SUNDANCE_MSG2(setupVerb(),
00908 "p=" << mesh().comm().getRank()
00909 << " I have " << localCount << " cells");
00910
00911 Array<int> dofOffsets;
00912 int totalDOFCount;
00913 MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
00914 mesh().comm());
00915 int myOffset = dofOffsets[mesh().comm().getRank()];
00916
00917 SUNDANCE_MSG2(setupVerb(),
00918 "p=" << mesh().comm().getRank()
00919 << " back from MPI accumulate");
00920
00921 if (setupVerb() > 2)
00922 {
00923 comm().synchronize();
00924 comm().synchronize();
00925 comm().synchronize();
00926 comm().synchronize();
00927 }
00928
00929 for (int chunk=0; chunk<dofs_[dim].size(); chunk++)
00930 {
00931 for (int n=0; n<dofs_[dim][chunk].size(); n++)
00932 {
00933 if (dofs_[dim][chunk][n] >= 0) dofs_[dim][chunk][n] += myOffset;
00934 }
00935 }
00936
00937 setLowestLocalDOF(myOffset);
00938 setNumLocalDOFs(localCount);
00939 setTotalNumDOFs(totalDOFCount);
00940
00941 SUNDANCE_MSG2(setupVerb(),
00942 "p=" << mesh().comm().getRank()
00943 << " done sharing offsets for DOF numbering for dim=" << dim);
00944 if (setupVerb() > 2)
00945 {
00946 comm().synchronize();
00947 comm().synchronize();
00948 comm().synchronize();
00949 comm().synchronize();
00950 }
00951
00952 }
00953
00954
00955
00956 void MixedDOFMap::checkTable() const
00957 {
00958 int bad = 0;
00959 for (int d=0; d<dofs_.size(); d++)
00960 {
00961 for (int chunk=0; chunk<dofs_[d].size(); chunk++)
00962 {
00963 const Array<int>& dofs = dofs_[d][chunk];
00964 for (int n=0; n<dofs.size(); n++)
00965 {
00966 if (dofs[n] < 0) bad = 1;
00967 }
00968 }
00969 }
00970
00971 int anyBad = bad;
00972 comm().allReduce((void*) &bad, (void*) &anyBad, 1,
00973 MPIDataType::intType(), MPIOp::sumOp());
00974 TEUCHOS_TEST_FOR_EXCEPTION(anyBad > 0, std::runtime_error, "invalid DOF map");
00975 }