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