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 "SundanceMixedDOFMapHN.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 using namespace Sundance;
00042 using namespace Teuchos;
00043
00044 static Time& mixedHNDOFCtorTimer()
00045 {
00046 static RCP<Time> rtn
00047 = TimeMonitor::getNewTimer("mixed hanging-node DOF map init");
00048 return *rtn;
00049 }
00050 static Time& maxDOFBuildTimer()
00051 {
00052 static RCP<Time> rtn
00053 = TimeMonitor::getNewTimer("max-cell dof table init");
00054 return *rtn;
00055 }
00056
00057 MixedDOFMapHN::MixedDOFMapHN(const Mesh& mesh,
00058 const Array<RCP<BasisDOFTopologyBase> >& basis,
00059 const CellFilter& maxCells,
00060 int setupVerb)
00061 : HNDoFMapBase(mesh, basis.size(), setupVerb),
00062 maxCells_(maxCells),
00063 dim_(mesh.spatialDim()),
00064 dofs_(mesh.spatialDim()+1),
00065 maximalDofs_(),
00066 haveMaximalDofs_(false),
00067 localNodePtrs_(),
00068 hasCellHanging_(),
00069 isElementHanging_(mesh.spatialDim()+1),
00070 HN_To_globalFacetsLID_(),
00071 HN_To_globalFacetsDim_(),
00072 HN_To_coeffs_(),
00073 maxCellLIDwithHN_to_TrafoMatrix_(),
00074 matrixStore_(),
00075 nNodesPerCell_(),
00076 totalNNodesPerCell_(),
00077 cellHasAnyDOFs_(dim_+1),
00078 numFacets_(mesh.spatialDim()+1),
00079 originalFacetOrientation_(2),
00080 hasBeenAssigned_(mesh.spatialDim()+1),
00081 structure_(),
00082 nFuncs_()
00083 {
00084 TimeMonitor timer(mixedHNDOFCtorTimer());
00085 Tabs tab;
00086
00087 SUNDANCE_MSG1(setupVerb, tab << "building mixed hanging node DOF map");
00088
00089 Sundance::Map<OrderedHandle<BasisDOFTopologyBase>, int> basisToChunkMap;
00090 Array<RCP<BasisDOFTopologyBase> > chunkBases;
00091 Array<Array<int> > chunkFuncs;
00092
00093 int chunk = 0;
00094 int nBasis = basis.size();
00095 basis_.resize(nBasis);
00096
00097 nPoints_ = mesh.numCells(0);
00098
00099 for (int i=0; i<nBasis; i++)
00100 {
00101 OrderedHandle<BasisDOFTopologyBase> bh = basis[i];
00102 if (!basisToChunkMap.containsKey(bh))
00103 {
00104 chunkBases.append(basis[i]);
00105 basisToChunkMap.put(bh, chunk);
00106 chunkFuncs.append(tuple(i));
00107 basis_[chunk] = rcp_dynamic_cast<BasisFamilyBase>(basis[i]);
00108 chunk++;
00109 }
00110 else
00111 {
00112 int b = basisToChunkMap.get(bh);
00113 chunkFuncs[b].append(i);
00114 }
00115 }
00116 basis_.resize(chunk);
00117
00118
00119 matrixStore_.init(chunk);
00120
00121 Tabs tab1;
00122 SUNDANCE_MSG1(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
00139
00140 SUNDANCE_MSG1(setupVerb, tab << "done building mixed HN DOF map");
00141
00142 }
00143
00144
00145 void MixedDOFMapHN::allocate(const Mesh& mesh)
00146 {
00147 Tabs tab;
00148
00149
00150 SUNDANCE_MSG1(setupVerb(),tab << "grouping like basis functions");
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 SUNDANCE_MSG1(setupVerb(),tab << "working out DOF map node counts");
00171
00172 numFacets_.resize(dim_+1);
00173 isElementHanging_.resize(dim_+1);
00174 hasCellHanging_.resize(mesh.numCells(dim_),false);
00175
00176 for (int d=0; d<=dim_; d++)
00177 {
00178 Tabs tab1;
00179 SUNDANCE_MSG1(setupVerb(),tab << "allocating maps for cell dim=" << d);
00180
00181
00182 numFacets_[d].resize(d);
00183
00184 for (int fd=0; fd<d; fd++) numFacets_[d][fd]=mesh.numFacets(d, 0, fd);
00185 SUNDANCE_MSG1(setupVerb(),tab1 << "num facets for dimension " << d << " is "
00186 << numFacets_[d]);
00187
00188 cellHasAnyDOFs_[d] = false;
00189 dofs_[d].resize(nBasisChunks());
00190
00191 int numCells = mesh.numCells(d);
00192 hasBeenAssigned_[d].resize(numCells);
00193
00194
00195 isElementHanging_[d].resize(numCells,false);
00196 for (int c=0; c<numCells; c++) { isElementHanging_[d][c] = false; }
00197 if (d == dim_){
00198 for (int c=0; c<numCells; c++) { hasCellHanging_[c] = false; }
00199 }
00200
00201 for (int b=0; b<nBasisChunks(); b++)
00202 {
00203 Tabs tab2;
00204 SUNDANCE_MSG2(setupVerb(),tab1 << "basis chunk=" << b);
00205 SUNDANCE_MSG2(setupVerb(),tab2 << "basis=" << basis(b)->description());
00206 int nNodes = basis(b).ptr()->nReferenceDOFsWithFacets(mesh.cellType(dim_), mesh.cellType(d));
00207 SUNDANCE_MSG2(setupVerb(),tab2 << "nNodes per cell=" << nNodes);
00208 if (nNodes == 0)
00209 {
00210 nNodesPerCell_[b][d] = 0;
00211 nDofsPerCell_[b][d] = 0;
00212 }
00213 else
00214 {
00215
00216
00217 basis(b).ptr()->getReferenceDOFs(mesh.cellType(dim_),
00218 mesh.cellType(d),
00219 localNodePtrs_[b][d]);
00220
00221
00222 SUNDANCE_MSG3(setupVerb(),tab2 << "node ptrs are "
00223 << localNodePtrs_[b][d]);
00224
00225
00226
00227 if (localNodePtrs_[b][d][d].size() > 0)
00228 {
00229 nNodesPerCell_[b][d] = localNodePtrs_[b][d][d][0].size();
00230 if (nNodesPerCell_[b][d] > 0) cellHasAnyDOFs_[d] = true;
00231 }
00232 else
00233 {
00234 nNodesPerCell_[b][d] = 0;
00235 }
00236 nDofsPerCell_[b][d] = nNodesPerCell_[b][d] * nFuncs(b);
00237 }
00238
00239
00240
00241
00242
00243 if (nDofsPerCell_[b][d] > 0 && d > 0 && d < mesh.spatialDim())
00244 {
00245 Mesh& tmpMesh = const_cast<Mesh&>(mesh);
00246 tmpMesh.assignIntermediateCellGIDs(d);
00247 }
00248
00249 SUNDANCE_MSG3(setupVerb(),tab2 <<
00250 "num nodes is "
00251 << nNodesPerCell_[b][d]);
00252
00253 totalNNodesPerCell_[b][d] = nNodesPerCell_[b][d];
00254 for (int dd=0; dd<d; dd++)
00255 {
00256 totalNNodesPerCell_[b][d]
00257 += numFacets_[d][dd]*nNodesPerCell_[b][dd];
00258 }
00259 totalNDofsPerCell_[b][d] = totalNNodesPerCell_[b][d] * nFuncs(b);
00260 SUNDANCE_MSG3(setupVerb(),tab2 << "totalNDofsPerCell " << totalNDofsPerCell_[b][d]);
00261
00262 if (nNodes > 0)
00263 {
00264
00265 dofs_[d][b].resize(nDofsPerCell_[b][d] * numCells);
00266
00267
00268 int nDof = dofs_[d][b].size();
00269 Array<int>& dofs = dofs_[d][b];
00270 int marker = uninitializedVal();
00271 for (int i=0; i<nDof; i++)
00272 {
00273 dofs[i] = marker;
00274 }
00275 }
00276
00277 if (d==dim_)
00278 {
00279 maximalDofs_[b].resize(totalNDofsPerCell_[b][d]*numCells);
00280 }
00281 }
00282
00283
00284 if (d > 0 && d < dim_)
00285 {
00286 originalFacetOrientation_[d-1].resize(numCells);
00287 }
00288
00289 }
00290 SUNDANCE_MSG1(setupVerb(),tab << "done allocating DOF map");
00291 }
00292
00293 void MixedDOFMapHN::initMap()
00294 {
00295 Tabs tab;
00296 SUNDANCE_MSG1(setupVerb(),tab << "initializing DOF map");
00297
00298 int nextDOF = 0;
00299
00300
00301
00302
00303 Array<Array<Array<int> > > remoteCells(mesh().spatialDim()+1);
00304
00305 for (int d=0; d<remoteCells.size(); d++)
00306 remoteCells[d].resize(mesh().comm().getNProc());
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 CellSet cells = maxCells_.getCells(mesh());
00317 CellIterator iter;
00318 for (iter=cells.begin(); iter != cells.end(); iter++)
00319 {
00320
00321 int cellLID = *iter;
00322 int owner;
00323
00324 if (cellHasAnyDOFs_[dim_])
00325 {
00326
00327
00328
00329 if (isRemote(dim_, cellLID, owner))
00330 {
00331
00332 int cellGID = mesh().mapLIDToGID(dim_, cellLID);
00333 SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00334 << " thinks d-" << dim_
00335 << " cell GID=" << cellGID
00336 << " is owned remotely by p="
00337 << owner);
00338 remoteCells[dim_][owner].append(cellGID);
00339 }
00340 else
00341
00342 {
00343 for (int b=0; b<nBasisChunks(); b++)
00344 {
00345 setDOFs(b, dim_, cellLID, nextDOF);
00346 }
00347 }
00348 }
00349
00350
00351 for (int d=0; d<dim_; d++)
00352 {
00353 if (cellHasAnyDOFs_[d])
00354 {
00355 int nf = numFacets_[dim_][d];
00356 Array<int> facetLID(nf);
00357 Array<int> facetOrientations(nf);
00358
00359
00360 mesh().getFacetArray(dim_, cellLID, d,
00361 facetLID, facetOrientations);
00362
00363 for (int f=0; f<nf; f++)
00364 {
00365
00366
00367 if (!hasBeenAssigned(d, facetLID[f]))
00368 {
00369 markAsAssigned(d, facetLID[f]);
00370
00371 if ( isRemote(d, facetLID[f], owner) && (!mesh().isElementHangingNode(d,facetLID[f])))
00372 {
00373 int facetGID
00374 = mesh().mapLIDToGID(d, facetLID[f]);
00375 SUNDANCE_MSG4(setupVerb(),"proc=" << comm().getRank()
00376 << " thinks d-" << d
00377 << " cell GID=" << facetGID
00378 << " is owned remotely by p=" << owner);
00379 remoteCells[d][owner].append(facetGID);
00380 }
00381 else
00382 {
00383
00384 for (int b=0; b<nBasisChunks(); b++)
00385 {
00386 setDOFs(b, d, facetLID[f], nextDOF);
00387 }
00388
00389 if (d > 0)
00390 {
00391 originalFacetOrientation_[d-1][facetLID[f]]
00392 = facetOrientations[f];
00393 }
00394 }
00395 }
00396 }
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406 int numLocalDOFs = nextDOF;
00407 if (mesh().comm().getNProc() > 1)
00408 {
00409 for (int d=0; d<=dim_; d++)
00410 {
00411 if (cellHasAnyDOFs_[d])
00412 {
00413 computeOffsets(d, numLocalDOFs);
00414 shareDOFs(d, remoteCells[d]);
00415 }
00416 }
00417 }
00418 else
00419 {
00420 setLowestLocalDOF(0);
00421 setNumLocalDOFs(numLocalDOFs);
00422 setTotalNumDOFs(numLocalDOFs);
00423 }
00424 SUNDANCE_MSG1(setupVerb(),tab << "done initializing DOF map , numLocalDOFs:" << numLocalDOFs);
00425 }
00426
00427
00428 void MixedDOFMapHN::setDOFs(int basisChunk, int cellDim, int cellLID,
00429 int& nextDOF, bool isRemote)
00430 {
00431 int nDofs = nDofsPerCell_[basisChunk][cellDim];
00432 if (nDofs==0) return;
00433 Tabs tab;
00434 SUNDANCE_MSG4(setupVerb(),tab << "setting DOFs for " << cellDim
00435 << "-cell " << cellLID << " , basisChunk:" << basisChunk <<" , nDofs:" <<nDofs << " , nextDOF:" << nextDOF );
00436
00437 int* ptr = getInitialDOFPtrForCell(cellDim, cellLID, basisChunk);
00438
00439
00440
00441
00442 if (isRemote)
00443 {
00444 if (mesh().isElementHangingNode(cellDim, cellLID)){
00445 isElementHanging_[cellDim][cellLID] = true;
00446 for (int i=0; i<nDofs; i++) {
00447 ptr[i] = -1;
00448
00449 }
00450 }
00451 else
00452 {
00453 for (int i=0; i<nDofs; i++, nextDOF++){
00454 ptr[i] = nextDOF;
00455 addGhostIndex(nextDOF);
00456 }
00457 }
00458 }
00459 else
00460 {
00461 if (mesh().isElementHangingNode(cellDim, cellLID)){
00462 isElementHanging_[cellDim][cellLID] = true;
00463 for (int i=0; i<nDofs; i++) {
00464
00465 ptr[i] = -1;
00466 }
00467 }
00468 else
00469 {
00470 for (int i=0; i<nDofs; i++,nextDOF++) {
00471
00472
00473
00474 ptr[i] = nextDOF;
00475 }
00476 }
00477 }
00478 }
00479
00480
00481
00482
00483
00484 void MixedDOFMapHN::shareDOFs(int cellDim,
00485 const Array<Array<int> >& outgoingCellRequests)
00486 {
00487 int np = mesh().comm().getNProc();
00488 int rank = mesh().comm().getRank();
00489
00490 Array<Array<int> > incomingCellRequests;
00491 Array<Array<int> > outgoingDOFs(np);
00492 Array<Array<int> > incomingDOFs;
00493
00494 SUNDANCE_MSG2(setupVerb(),
00495 "p=" << mesh().comm().getRank()
00496 << "synchronizing DOFs for cells of dimension " << cellDim);
00497 SUNDANCE_MSG2(setupVerb(),
00498 "p=" << mesh().comm().getRank()
00499 << " sending cell reqs d=" << cellDim << " GID=" << outgoingCellRequests);
00500
00501
00502 MPIContainerComm<int>::allToAll(outgoingCellRequests,
00503 incomingCellRequests,
00504 mesh().comm());
00505
00506
00507
00508
00509
00510 int blockSize = 0;
00511 bool sendOrientation = false;
00512 for (int b=0; b<nBasisChunks(); b++)
00513 {
00514 int nDofs = nDofsPerCell_[b][cellDim];
00515 if (nDofs > 0) blockSize++;
00516 if (nDofs > 1 && cellDim > 0 && cellDim < dim_) sendOrientation = true;
00517 }
00518 blockSize += sendOrientation;
00519
00520 SUNDANCE_MSG2(setupVerb(),
00521 "p=" << rank
00522 << "recvd DOF requests for cells of dimension " << cellDim
00523 << " GID=" << incomingCellRequests);
00524
00525
00526
00527 for (int p=0; p<np; p++)
00528 {
00529 if (p==rank) continue;
00530 const Array<int>& requestsFromProc = incomingCellRequests[p];
00531 int nReq = requestsFromProc.size();
00532
00533 SUNDANCE_MSG4(setupVerb(),"p=" << mesh().comm().getRank()
00534 << " recv'd from proc=" << p
00535 << " reqs for DOFs for cells "
00536 << requestsFromProc);
00537
00538 outgoingDOFs[p].resize(nReq * blockSize);
00539
00540 for (int c=0; c<nReq; c++)
00541 {
00542 int GID = requestsFromProc[c];
00543 SUNDANCE_MSG3(setupVerb(),
00544 "p=" << rank
00545 << " processing cell with d=" << cellDim
00546 << " GID=" << GID);
00547 int LID = mesh().mapGIDToLID(cellDim, GID);
00548 SUNDANCE_MSG3(setupVerb(),
00549 "p=" << rank
00550 << " LID=" << LID << " dofs=" << dofs_[cellDim]);
00551 int blockOffset = 0;
00552 for (int b=0; b<nBasisChunks(); b++)
00553 {
00554 if (nDofsPerCell_[b][cellDim] == 0) continue;
00555 outgoingDOFs[p][blockSize*c+blockOffset]
00556 = getInitialDOFForCell(cellDim, LID, b);
00557 blockOffset++;
00558 }
00559 if (sendOrientation)
00560 {
00561 outgoingDOFs[p][blockSize*(c+1) - 1]
00562 = originalFacetOrientation_[cellDim-1][LID];
00563 }
00564 SUNDANCE_MSG3(setupVerb(),
00565 "p=" << rank
00566 << " done processing cell with GID=" << GID);
00567 }
00568 }
00569
00570
00571 SUNDANCE_MSG2(setupVerb(),
00572 "p=" << mesh().comm().getRank()
00573 << "answering DOF requests for cells of dimension " << cellDim);
00574
00575
00576 MPIContainerComm<int>::allToAll(outgoingDOFs,
00577 incomingDOFs,
00578 mesh().comm());
00579
00580 SUNDANCE_MSG2(setupVerb(),
00581 "p=" << mesh().comm().getRank()
00582 << "communicated DOF answers for cells of dimension " << cellDim);
00583
00584
00585
00586
00587 for (int p=0; p<mesh().comm().getNProc(); p++)
00588 {
00589 if (p==mesh().comm().getRank()) continue;
00590 const Array<int>& dofsFromProc = incomingDOFs[p];
00591 int numCells = dofsFromProc.size()/blockSize;
00592 for (int c=0; c<numCells; c++)
00593 {
00594 int cellGID = outgoingCellRequests[p][c];
00595 int cellLID = mesh().mapGIDToLID(cellDim, cellGID);
00596 int blockOffset = 0;
00597 for (int b=0; b<nBasisChunks(); b++)
00598 {
00599 if (nDofsPerCell_[b][cellDim] == 0) continue;
00600 int dof = dofsFromProc[blockSize*c+blockOffset];
00601 setDOFs(b, cellDim, cellLID, dof, true);
00602 blockOffset++;
00603 }
00604 if (sendOrientation)
00605 {
00606 originalFacetOrientation_[cellDim-1][cellLID]
00607 = dofsFromProc[blockSize*(c+1)-1];
00608 }
00609 }
00610 }
00611
00612 }
00613
00614
00615 RCP<const MapStructure> MixedDOFMapHN
00616 ::getDOFsForCellBatch(int cellDim,
00617 const Array<int>& cellLID,
00618 const Set<int>& requestedFuncSet,
00619 Array<Array<int> >& dofs,
00620 Array<int>& nNodes,
00621 int verbosity) const
00622 {
00623 TimeMonitor timer(batchedDofLookupTimer());
00624
00625 Tabs tab;
00626 SUNDANCE_MSG2(verbosity,
00627 tab << "getDOFsForCellBatch(): cellDim=" << cellDim
00628 << " cellLID=" << cellLID);
00629
00630 dofs.resize(nBasisChunks());
00631 nNodes.resize(nBasisChunks());
00632
00633 int nCells = cellLID.size();
00634
00635 if (cellDim == dim_)
00636 {
00637 Tabs tab1;
00638
00639 SUNDANCE_MSG4(verbosity,tab1 << "getting dofs for maximal cells : " << cellLID );
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 Array<int>& chunkDofs = dofs[b];
00647
00648
00649
00650 for (int c=0; c<nCells; c++)
00651 {
00652 for (int i=0; i<dofsPerCell; i++)
00653 {
00654 chunkDofs[c*dofsPerCell + i]
00655 = maximalDofs_[b][cellLID[c]*dofsPerCell+i];
00656 }
00657 }
00658 SUNDANCE_MSG3(verbosity,tab1 << "dofs for chunk-" << b << " :" << chunkDofs);
00659 }
00660 }
00661 else
00662 {
00663 Tabs tab1;
00664 SUNDANCE_MSG3(verbosity,tab1 << "getting dofs for non-maximal cells");
00665
00666 static Array<Array<int> > facetLID(3);
00667 static Array<Array<int> > facetOrientations(3);
00668 static Array<int> numFacets(3);
00669
00670 for (int d=0; d<cellDim; d++)
00671 {
00672 numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00673 mesh().getFacetLIDs(cellDim, cellLID, d, facetLID[d],
00674 facetOrientations[d]);
00675 }
00676
00677 for (int b=0; b<nBasisChunks(); b++)
00678 {
00679 nNodes[b] = totalNNodesPerCell_[b][cellDim];
00680 dofs[b].resize(nNodes[b]*nFuncs(b)*nCells);
00681 int dofsPerCell = nFuncs(b)*nNodes[b];
00682
00683 Array<int>& toPtr = dofs[b];
00684 int nf = nFuncs(b);
00685
00686 for (int c=0; c<nCells; c++)
00687 {
00688 Tabs tab2;
00689 SUNDANCE_MSG3(verbosity,tab2 << "cell=" << c << " ,cellLID[c]:" << cellLID[c]);
00690 int offset = dofsPerCell*c;
00691
00692
00693
00694
00695 SUNDANCE_MSG3(verbosity,tab2 << "doing interior nodes");
00696 int nInteriorNodes = nNodesPerCell_[b][cellDim];
00697
00698 if (nInteriorNodes > 0)
00699 {
00700 if (cellDim==0 || nInteriorNodes <= 1)
00701 {
00702
00703 for (int func=0; func<nf; func++)
00704 {
00705 for (int n=0; n<nInteriorNodes; n++)
00706 {
00707 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00708 toPtr[offset + func*nNodes[b] + ptr]
00709 = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00710
00711 }
00712 }
00713 }
00714 else
00715 {
00716 int sign = originalFacetOrientation_[cellDim-1][cellLID[c]];
00717 int nInteriorNodes = localNodePtrs_[b][cellDim][cellDim][0].size();
00718
00719 for (int func=0; func<nf; func++)
00720 {
00721 for (int m=0; m<nInteriorNodes; m++)
00722 {
00723 int n = m;
00724 if (sign<0) n = nInteriorNodes-1-m;
00725 int ptr = localNodePtrs_[b][cellDim][cellDim][0][m];
00726 toPtr[offset + func*nNodes[b] + ptr] = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00727
00728 }
00729 }
00730 }
00731 }
00732
00733
00734 for (int d=0; d<cellDim; d++)
00735 {
00736 Tabs tab2;
00737 SUNDANCE_MSG3(verbosity,tab2 << "facet dim=" << d);
00738 if (nNodesPerCell_[b][d] == 0) continue;
00739 for (int f=0; f<numFacets[d]; f++)
00740 {
00741 Tabs tab3;
00742 int facetID = facetLID[d][c*numFacets[d]+f];
00743 SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID);
00744 if (localNodePtrs_[b][cellDim].size()==0) continue;
00745 int nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00746
00747 int* toPtr1 = &(dofs[b][dofsPerCell*c]);
00748 const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00749
00750
00751
00752 for (int func=0; func<nf; func++)
00753 {
00754 if (d == 0 || nFacetNodes <= 1)
00755 {
00756 for (int n=0; n<nFacetNodes; n++)
00757 {
00758 int ptr = nodePtr[n];
00759 toPtr1[func*nNodes[b] + ptr]
00760 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00761
00762
00763 if (toPtr1[func*nNodes[b] + ptr] < 0 )
00764 {
00765 int fIndex = 1 , tmp1 = 1;
00766
00767 int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00768 Array<int> facetsLIDs;
00769 mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00770
00771 SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
00772 toPtr1[func*nNodes[b] + ptr]
00773 = dofs_[d][b][facetsLIDs[fIndex]*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00774 }
00775 }
00776 }
00777 else
00778 {
00779 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
00780 * originalFacetOrientation_[d-1][facetID];
00781 for (int m=0; m<nFacetNodes; m++)
00782 {
00783 int n = m;
00784 if (facetOrientation<0) n = nFacetNodes-1-m;
00785 int ptr = nodePtr[n];
00786 toPtr1[func*nNodes[b]+ptr]
00787 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00788
00789
00790 if (toPtr1[func*nNodes[b]+ptr] < 0)
00791 {
00792 int fIndex = 1 , tmp1 = 1;
00793
00794 int maxCell = mesh().maxCofacetLID( cellDim , cellLID[c] , 0 , fIndex);
00795 Array<int> facetsLIDs;
00796 mesh().returnParentFacets( maxCell , d , facetsLIDs , tmp1 );
00797
00798
00799 SUNDANCE_MSG3(verbosity,tab2 << "f=" << f << " facetLID=" << facetID << " replaced by facetsLIDs[fIndex]:" << facetsLIDs[fIndex]);
00800 toPtr1[func*nNodes[b] + ptr]
00801 = dofs_[d][b][facetsLIDs[fIndex]*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00802 }
00803 }
00804 }
00805 }
00806 }
00807 }
00808 }
00809 }
00810
00811 }
00812 return structure_;
00813 }
00814
00815 void MixedDOFMapHN::buildMaximalDofTable()
00816 {
00817 TimeMonitor timer(maxDOFBuildTimer());
00818 Tabs tab;
00819 int cellDim = dim_;
00820 int nCells = mesh().numCells(dim_);
00821
00822 SUNDANCE_MSG1(setupVerb(),tab << "building dofs for maximal cells");
00823
00824 Array<Array<int> > facetLID(3);
00825 Array<Array<int> > facetOrientations(3);
00826 Array<int> numFacets(3);
00827
00828 Array<int> cellLID(nCells);
00829
00830 for (int c=0; c<nCells; c++) cellLID[c]=c;
00831
00832 for (int d=0; d<cellDim; d++)
00833 {
00834 numFacets[d] = mesh().numFacets(cellDim, cellLID[0], d);
00835 mesh().getFacetLIDs(cellDim, cellLID, d,
00836 facetLID[d], facetOrientations[d]);
00837 }
00838
00839 Array<int> nInteriorNodes(nBasisChunks());
00840 Array<int> nNodes(nBasisChunks());
00841 for (int b = 0; b<nBasisChunks(); b++)
00842 {
00843
00844 if (localNodePtrs_[b][cellDim].size() != 0)
00845 {
00846 nInteriorNodes[b] = localNodePtrs_[b][cellDim][cellDim][0].size();
00847 }
00848 else
00849 {
00850 nInteriorNodes[b] = 0;
00851 }
00852 nNodes[b] = totalNNodesPerCell_[b][cellDim];
00853 }
00854
00855
00856
00857
00858 Array< Array<Array<int> > >globalDoFs_Cell(nBasisChunks());
00859
00860 Array<Array<double> > trafoMatrix(nBasisChunks());
00861
00862 Array<int> localDoFs;
00863 Array<int> parentFacetDim;
00864 Array<int> parentFacetIndex;
00865 Array<int> parentFacetNode;
00866 Array<int> retFacets;
00867 Array<double> coefs;
00868
00869
00870 for (int c=0; c<nCells; c++)
00871 {
00872
00873
00874 for (int jj = 0 ; jj < numFacets[0] ; jj++){
00875 if (mesh().isElementHangingNode(0,facetLID[0][ c*numFacets[0] + jj])){
00876
00877
00878 hasCellHanging_[cellLID[c]] = true;
00879 break;
00880 }
00881 }
00882
00883 Tabs tab1;
00884 SUNDANCE_MSG3(setupVerb(),tab1 << "working on cell=" << c
00885 << " LID=" << cellLID[c]);
00886
00887
00888 SUNDANCE_MSG3(setupVerb(),tab1 << "doing interior nodes");
00889 for (int b=0; b<nBasisChunks(); b++)
00890 {
00891
00892 if (hasCellHanging_[cellLID[c]]){
00893
00894 globalDoFs_Cell[b].resize( nFuncs(b));
00895 trafoMatrix[b].resize(nNodes[b]*nNodes[b], 0.0);
00896 for (int jj = 0; jj < nNodes[b]*nNodes[b] ; jj++) trafoMatrix[b][jj] = 0.0;
00897 for (int func=0; func<nFuncs(b); func++)
00898 {
00899 globalDoFs_Cell[b][func].resize(nNodes[b]);
00900 for (int kk = 0 ; kk < nNodes[b] ; kk++ ){
00901 globalDoFs_Cell[b][func][kk] = -1;
00902 }
00903 }
00904 }
00905
00906 SUNDANCE_MSG3(setupVerb(),tab1 << "basis chunk=" << b);
00907 if (nInteriorNodes[b]>0)
00908 {
00909 SUNDANCE_MSG3(setupVerb(),tab1<< "nInteriorNodes = " <<nInteriorNodes[b]);
00910 int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00911 int nf = nFuncs(b);
00912 for (int func=0; func<nf; func++)
00913 {
00914 for (int n=0; n<nInteriorNodes[b]; n++)
00915 {
00916
00917
00918
00919
00920
00921
00922 int ptr = localNodePtrs_[b][cellDim][cellDim][0][n];
00923
00924 if (hasCellHanging_[cellLID[c]])
00925 {
00926 SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c]=" << cellLID[c] );
00927 int dof_tmp = dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00928
00929 SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , globalDoFs_Cell[b][func]:"<<globalDoFs_Cell[b][func]<<" dof=" << dof_tmp);
00930 globalDoFs_Cell[b][func][ptr] = dof_tmp;
00931 SUNDANCE_MSG1(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
00932 if (func == 0){
00933 trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
00934 }
00935 }
00936
00937 toPtr[func*nNodes[b] + ptr] =
00938 dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n];
00939 SUNDANCE_MSG1(setupVerb(), tab1 << " dof=" << dofs_[cellDim][b][cellLID[c]*nDofsPerCell_[b][cellDim]+func*nNodesPerCell_[b][cellDim]+n]);
00940 }
00941 }
00942 }
00943 }
00944
00945 SUNDANCE_MSG3(setupVerb(),tab1 << "doing facet nodes");
00946
00947 for (int d=0; d<cellDim; d++)
00948 {
00949 Tabs tab2;
00950 SUNDANCE_MSG3(setupVerb(),tab2 << "facet dim=" << d);
00951
00952 for (int f=0; f<numFacets[d]; f++)
00953 {
00954 Tabs tab3;
00955 int facetID = facetLID[d][c*numFacets[d]+f];
00956 SUNDANCE_MSG3(setupVerb(),tab2 << "f=" << f << " facetLID=" << facetID);
00957
00958 for (int b=0; b<nBasisChunks(); b++)
00959 {
00960 Tabs tab4;
00961 SUNDANCE_MSG3(setupVerb(),tab4 << "basis chunk=" << b);
00962 SUNDANCE_MSG3(setupVerb(),tab4 << "num nodes per cell=" << nNodesPerCell_[b][d]);
00963 int nf = nFuncs(b);
00964 if (nDofsPerCell_[b][d]==0) continue;
00965 int nFacetNodes = 0;
00966 if (localNodePtrs_[b][cellDim].size()!=0)
00967 nFacetNodes = localNodePtrs_[b][cellDim][d][f].size();
00968 if (nFacetNodes == 0) continue;
00969
00970 SUNDANCE_MSG3(setupVerb(),tab4 << "dof table size=" << maximalDofs_[b].size());
00971
00972 int* toPtr = &(maximalDofs_[b][nNodes[b]*nFuncs(b)*cellLID[c]]);
00973
00974 const int* nodePtr = &(localNodePtrs_[b][cellDim][d][f][0]);
00975
00976 for (int func=0; func<nf; func++)
00977 {
00978 Tabs tab5;
00979 SUNDANCE_MSG3(setupVerb(),tab5 << "func=" << func);
00980 if (d == 0 || nFacetNodes <= 1)
00981 {
00982 Tabs tab6;
00983 for (int n=0; n<nFacetNodes; n++)
00984 {
00985 SUNDANCE_MSG3(setupVerb(),tab5 << "n=" << n);
00986 int ptr = nodePtr[n];
00987 SUNDANCE_MSG3(setupVerb(),tab6 << "ptr=" << ptr);
00988
00989
00990
00991
00992 if (hasCellHanging_[cellLID[c]]){
00993 int parentCellLID = 0;
00994 int dof_tmp = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
00995 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
00996 if (dof_tmp < 0){
00997 Array<int> constFacetLID;
00998 Array<int> constFacetDim;
00999
01000 basis_[b]->getConstrainsForHNDoF(
01001 mesh().indexInParent(cellLID[c]), cellDim ,
01002 mesh().maxChildren(), d , f , n,
01003 localDoFs, parentFacetDim,
01004 parentFacetIndex, parentFacetNode, coefs );
01005 SUNDANCE_MSG3(setupVerb(), tab1 << " After basis_[b]->getConstrainsForHNDoF:");
01006 constFacetLID.resize(localDoFs.size());
01007 constFacetDim.resize(localDoFs.size());
01008 for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01009 {
01010
01011 int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01012 [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01013
01014 mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01015 int parFacetLID = retFacets[parentFacetIndex[indexi]];
01016 int parFacetNode = parentFacetNode[indexi];
01017 SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01018 SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01019
01020 constFacetDim[indexi] = parentFacetDim[indexi];
01021 constFacetLID[indexi] = parFacetLID;
01022
01023 dof_tmp = dofs_[parentFacetDim[indexi]][b]
01024 [parFacetLID * nDofsPerCell_[b][parentFacetDim[indexi]]+func*nNodesPerCell_[b][parentFacetDim[indexi]]+parFacetNode];
01025
01026 globalDoFs_Cell[b][func][ptr1] = dof_tmp;
01027
01028 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr << "ptr1=" << ptr1 <<" dof=" << dof_tmp);
01029 if (func == 0){
01030 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01031 }
01032 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , DONE Fill");
01033 }
01034
01035 if ( (d == 0) && (func == 0)) {
01036 HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01037 HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01038 HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01039 }
01040 }else {
01041
01042 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01043
01044
01045
01046
01047 globalDoFs_Cell[b][func][ptr] = dof_tmp;
01048 if (func == 0){
01049 trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01050 }
01051 }
01052 } else {
01053 toPtr[func*nNodes[b] + ptr]
01054 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01055 SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n]);
01056 }
01057 }
01058 }
01059 else
01060 {
01061 int facetOrientation = facetOrientations[d][c*numFacets[d]+f]
01062 * originalFacetOrientation_[d-1][facetID];
01063 for (int m=0; m<nFacetNodes; m++)
01064 {
01065 int n = m;
01066 if (facetOrientation<0) n = nFacetNodes-1-m;
01067 int ptr = nodePtr[m];
01068
01069
01070
01071
01072
01073 if (hasCellHanging_[cellLID[c]])
01074 {
01075 int parentCellLID = 0;
01076 int dof_tmp = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01077 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , d="<<d<<", f="<<f<<", n="<<n<<", dof=" << dof_tmp);
01078 if (dof_tmp < 0){
01079 Array<int> constFacetLID;
01080 Array<int> constFacetDim;
01081
01082 basis_[b]->getConstrainsForHNDoF(
01083 mesh().indexInParent(cellLID[c]), cellDim ,
01084 mesh().maxChildren(), d , f , n,
01085 localDoFs, parentFacetDim,
01086 parentFacetIndex, parentFacetNode, coefs );
01087 SUNDANCE_MSG3(setupVerb(), tab1 << " After basis_[b]->getConstrainsForHNDoF:");
01088 constFacetLID.resize(localDoFs.size());
01089 constFacetDim.resize(localDoFs.size());
01090 for (int indexi = 0 ; indexi < localDoFs.size() ; indexi++)
01091 {
01092
01093 int ptr1 = localNodePtrs_[b][cellDim][parentFacetDim[indexi]]
01094 [parentFacetIndex[indexi]][parentFacetNode[indexi]];
01095
01096 mesh().returnParentFacets(cellLID[c] , parentFacetDim[indexi], retFacets , parentCellLID );
01097 int parFacetLID = retFacets[parentFacetIndex[indexi]];
01098 int parFacetNode = parentFacetNode[indexi];
01099 SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , parFacetLID=" << parFacetLID <<" parFacetNode=" << parFacetNode );
01100 SUNDANCE_MSG3(setupVerb(), tab1 << "returnParentFacets , retFacets=" << retFacets );
01101
01102 constFacetDim[indexi] = parentFacetDim[indexi];
01103 constFacetLID[indexi] = parFacetLID;
01104
01105 dof_tmp = dofs_[parentFacetDim[indexi]][b]
01106 [parFacetLID * nDofsPerCell_[b][parentFacetDim[indexi]]+func*nNodesPerCell_[b][parentFacetDim[indexi]]+parFacetNode];
01107
01108 globalDoFs_Cell[b][func][ptr1] = dof_tmp;
01109
01110 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr1 <<" dof=" << dof_tmp);
01111 if (func == 0){
01112 trafoMatrix[b][nNodes[b]*ptr + ptr1] = coefs[indexi];
01113 }
01114 }
01115
01116 if ( (d == 0) && (func == 0)) {
01117 HN_To_globalFacetsLID_.put( nPoints_*b + facetID , constFacetLID);
01118 HN_To_globalFacetsDim_.put( nPoints_*b + facetID , constFacetDim);
01119 HN_To_coeffs_.put( nPoints_*b + facetID , coefs);
01120 }
01121 }else{
01122
01123
01124 SUNDANCE_MSG3(setupVerb(), tab1 << "Cell has HDoF cellLID[c] , ptr=" << ptr <<" dof=" << dof_tmp);
01125 globalDoFs_Cell[b][func][ptr] = dof_tmp;
01126 if (func == 0){
01127 trafoMatrix[b][nNodes[b]*ptr + ptr] = 1.0;
01128 }
01129 }
01130 } else {
01131 toPtr[func*nNodes[b]+ptr]
01132 = dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n];
01133 SUNDANCE_MSG3(setupVerb(), tab1 << " dof=" << dofs_[d][b][facetID*nDofsPerCell_[b][d]+func*nNodesPerCell_[b][d]+n]);
01134 }
01135 }
01136 }
01137 }
01138 }
01139 }
01140 }
01141
01142
01143 if (hasCellHanging_[cellLID[c]]){
01144
01145 Array<int> matrixIndexes(nBasisChunks());
01146 for (int b=0; b<nBasisChunks(); b++){
01147 matrixIndexes[b] = matrixStore_.addMatrix( b , trafoMatrix[b] );
01148 }
01149 maxCellLIDwithHN_to_TrafoMatrix_.put( cellLID[c] , matrixIndexes );
01150
01151 for (int b=0; b<nBasisChunks(); b++)
01152 {
01153
01154 SUNDANCE_MSG3(setupVerb(), "trafoMatrix[b]=" << trafoMatrix[b]);
01155 for (int func=0; func<nFuncs(b); func++)
01156 {
01157
01158 SUNDANCE_MSG1(setupVerb(), "globalDoFs_Cell[b][func]=" << globalDoFs_Cell[b][func]);
01159 for (int jj=0 ; jj < nNodes[b] ; jj++){
01160
01161 maximalDofs_[b][(cellLID[c]*nFuncs(b) + func)*nNodes[b] + jj] = globalDoFs_Cell[b][func][jj];
01162 }
01163 }
01164 }
01165 }
01166 }
01167
01168 haveMaximalDofs_ = true;
01169
01170 SUNDANCE_MSG1(setupVerb(),tab << "done building dofs for maximal cells");
01171 }
01172
01173
01174 void MixedDOFMapHN::getTrafoMatrixForCell(
01175 int cellLID,
01176 int funcID,
01177 int& trafoMatrixSize,
01178 bool& doTransform,
01179 Array<double>& transfMatrix ) const {
01180
01181 trafoMatrixSize = 0;
01182
01183 if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(cellLID))
01184 {
01185
01186 const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( cellLID );
01187 matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01188
01189
01190 trafoMatrixSize = sqrt(transfMatrix.size());
01191 SUNDANCE_MSG1(setupVerb(), "getTrafoMatrixForCell() cellLID:" << cellLID << ",funcID:" <<
01192 funcID << ",chunkForFuncID(funcID):" << chunkForFuncID(funcID) << ", trafoMatrixSize:" << trafoMatrixSize);
01193
01194 doTransform = true;
01195 }
01196 else
01197 {
01198 doTransform = false;
01199 }
01200 }
01201
01202 void MixedDOFMapHN::getTrafoMatrixForFacet(
01203 int cellDim,
01204 int cellLID,
01205 int facetIndex,
01206 int funcID,
01207 int& trafoMatrixSize,
01208 bool& doTransform,
01209 Array<double>& transfMatrix ) const {
01210
01211 int fIndex;
01212 int maxCellLID;
01213
01214 SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() cellDim :" << cellDim << ", cellLID:" << cellLID);
01215 maxCellLID = mesh().maxCofacetLID( cellDim, cellLID, 0 , fIndex);
01216 SUNDANCE_MSG2(setupVerb() , "NodalDOFMapHN::getTrafoMatrixForFacet() testing :" << maxCellLID);
01217
01218
01219
01220 if (maxCellLIDwithHN_to_TrafoMatrix_.containsKey(maxCellLID))
01221 {
01222 const Array<int> &matrixIndexes = maxCellLIDwithHN_to_TrafoMatrix_.get( maxCellLID );
01223 matrixStore_.getMatrix( chunkForFuncID(funcID) , matrixIndexes[chunkForFuncID(funcID)] , transfMatrix );
01224 doTransform = true;
01225 }
01226 else
01227 {
01228 doTransform = false;
01229 }
01230 }
01231
01232
01233 void MixedDOFMapHN::getDOFsForHNCell(
01234 int cellDim,
01235 int cellLID,
01236 int funcID,
01237 Array<int>& dofs ,
01238 Array<double>& coefs ) const {
01239
01240
01241
01242
01243
01244 if ( (cellDim == 0) && ( HN_To_globalFacetsLID_.containsKey(nPoints_*chunkForFuncID(funcID) + cellLID)) )
01245 {
01246 Array<int> facetLIDs;
01247 Array<int> facetDim;
01248 SUNDANCE_MSG1(setupVerb(), "getDOFsForHNCell() cellDim:"<<cellDim<<" cellLID:"<<
01249 cellLID<<"funcID:" << funcID <<",chunkForFuncID(funcID)" << chunkForFuncID(funcID));
01250 facetLIDs = HN_To_globalFacetsLID_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01251 facetDim = HN_To_globalFacetsDim_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01252 dofs.resize(facetLIDs.size());
01253 int b = chunkForFuncID(funcID);
01254 int func = indexForFuncID(funcID);
01255
01256 for (int ind = 0 ; ind < facetLIDs.size() ; ind++){
01257
01258 dofs[ind] = dofs_[facetDim[ind]][b]
01259 [facetLIDs[ind]*nDofsPerCell_[b][facetDim[ind]]+func*nNodesPerCell_[b][facetDim[ind]] + 0 ];
01260 }
01261
01262 coefs = HN_To_coeffs_.get( nPoints_*chunkForFuncID(funcID) + cellLID );
01263 SUNDANCE_MSG1(setupVerb(), "b=" << b);
01264 SUNDANCE_MSG1(setupVerb(), "func=" << func);
01265 SUNDANCE_MSG1(setupVerb(), "facetLIDs=" << facetLIDs);
01266 SUNDANCE_MSG1(setupVerb(), "facetDim = " << facetDim);
01267 SUNDANCE_MSG1(setupVerb(), "dofs=" << dofs);
01268 SUNDANCE_MSG1(setupVerb(), "coefs = " << coefs);
01269 }
01270 }
01271
01272
01273 void MixedDOFMapHN::computeOffsets(int dim, int localCount)
01274 {
01275 if (setupVerb() > 2)
01276 {
01277 comm().synchronize();
01278 comm().synchronize();
01279 comm().synchronize();
01280 comm().synchronize();
01281 }
01282 SUNDANCE_MSG2(setupVerb(),
01283 "p=" << mesh().comm().getRank()
01284 << " sharing offsets for DOF numbering for dim=" << dim);
01285
01286 SUNDANCE_MSG2(setupVerb(),
01287 "p=" << mesh().comm().getRank()
01288 << " I have " << localCount << " cells");
01289
01290 Array<int> dofOffsets;
01291 int totalDOFCount;
01292 MPIContainerComm<int>::accumulate(localCount, dofOffsets, totalDOFCount,
01293 mesh().comm());
01294 int myOffset = dofOffsets[mesh().comm().getRank()];
01295
01296 SUNDANCE_MSG2(setupVerb(),
01297 "p=" << mesh().comm().getRank()
01298 << " back from MPI accumulate");
01299
01300 if (setupVerb() > 2)
01301 {
01302 comm().synchronize();
01303 comm().synchronize();
01304 comm().synchronize();
01305 comm().synchronize();
01306 }
01307
01308 for (int chunk=0; chunk<dofs_[dim].size(); chunk++)
01309 {
01310 for (int n=0; n<dofs_[dim][chunk].size(); n++)
01311 {
01312
01313 if (dofs_[dim][chunk][n] >= 0) {
01314 dofs_[dim][chunk][n] += myOffset;
01315 }
01316 }
01317 }
01318
01319 setLowestLocalDOF(myOffset);
01320 setNumLocalDOFs(localCount);
01321 setTotalNumDOFs(totalDOFCount);
01322
01323 SUNDANCE_MSG2(setupVerb(),
01324 "p=" << mesh().comm().getRank()
01325 << " done sharing offsets for DOF numbering for dim=" << dim);
01326 if (setupVerb() > 2)
01327 {
01328 comm().synchronize();
01329 comm().synchronize();
01330 comm().synchronize();
01331 comm().synchronize();
01332 }
01333
01334 }
01335
01336
01337
01338 void MixedDOFMapHN::checkTable() const
01339 {
01340 int bad = 0;
01341 for (int d=0; d<dofs_.size(); d++)
01342 {
01343 for (int chunk=0; chunk<dofs_[d].size(); chunk++)
01344 {
01345 const Array<int>& dofs = dofs_[d][chunk];
01346 for (int n=0; n<dofs.size(); n++)
01347 {
01348 if (dofs[n] < 0) bad = 1;
01349 }
01350 }
01351 }
01352
01353 int anyBad = bad;
01354 comm().allReduce((void*) &bad, (void*) &anyBad, 1,
01355 MPIComm::INT, MPIComm::SUM);
01356 TEST_FOR_EXCEPTION(anyBad > 0, RuntimeError, "invalid DOF map");
01357 }