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 "SundanceInhomogeneousNodalDOFMap.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 InhomogeneousNodalDOFMap
00058 ::InhomogeneousNodalDOFMap(const Mesh& mesh,
00059 const Array<Map<Set<int>, CellFilter> >& funcSetToDomainMap,
00060 int setupVerb)
00061 : DOFMapBase(mesh, setupVerb),
00062 dim_(mesh.spatialDim()),
00063 basis_(rcp(new Lagrange(1))),
00064 nTotalFuncs_(),
00065 funcDomains_(),
00066 nodeDofs_(),
00067 elemDofs_(),
00068 nodeToFuncSetIndexMap_(mesh.numCells(0)),
00069 elemToFuncSetIndexMap_(mesh.numCells(dim_)),
00070 elemFuncSets_(),
00071 nodalFuncSets_(),
00072 nodeToOffsetMap_(mesh.numCells(0)),
00073 elemToOffsetMap_(mesh.numCells(0)),
00074 funcIndexWithinNodeFuncSet_(),
00075 elemStructure_(),
00076 nodeStructure_()
00077 {
00078 SUNDANCE_MSG1(setupVerb, "in InhomogeneousNodalDOFMap ctor");
00079 SUNDANCE_MSG4(setupVerb, "func set to domain map " << funcSetToDomainMap);
00080
00081
00082 Set<int> allFuncs;
00083 for (int d=dim_; d>=0; d--)
00084 {
00085 for (Map<Set<int>, CellFilter>::const_iterator
00086 i=funcSetToDomainMap[d].begin(); i!=funcSetToDomainMap[d].end(); i++)
00087 {
00088 allFuncs.merge(i->first);
00089 }
00090 }
00091
00092
00093 nTotalFuncs_ = allFuncs.size();
00094 SUNDANCE_MSG2(setupVerb, "found " << nTotalFuncs_ << " functions");
00095
00096
00097
00098 Array<CellFilter> subdomains;
00099 Array<CellFilter> maxSubdomains;
00100 Array<Array<int> > funcArrays;
00101 Array<Set<int> > funcSets;
00102
00103 for (int d=dim_; d>=0; d--)
00104 {
00105 for (Map<Set<int>, CellFilter>::const_iterator
00106 i=funcSetToDomainMap[d].begin(); i!=funcSetToDomainMap[d].end(); i++)
00107 {
00108 subdomains.append(i->second);
00109 if (d==dim_)
00110 {
00111 elemFuncSets_.append(i->first);
00112 maxSubdomains.append(i->second);
00113 }
00114
00115 Array<int> myFuncs = i->first.elements();
00116 funcArrays.append(myFuncs);
00117 funcSets.append(i->first);
00118 }
00119 }
00120
00121
00122
00123
00124
00125
00126 Array<Array<int> > cellLIDs(subdomains.size());
00127 Array<Array<int> > facetLIDs(subdomains.size());
00128 Array<Array<int> > facetOrientations(subdomains.size());
00129 Array<Set<int> > nodeToFuncSetMap(mesh.numCells(0));
00130
00131 for (int r=0; r<subdomains.size(); r++)
00132 {
00133 int d = subdomains[r].dimension(mesh);
00134 CellSet cells = subdomains[r].getCells(mesh);
00135 SUNDANCE_MSG4(setupVerb, "domain " << subdomains[r] << " has functions "
00136 << funcSets[r]);
00137
00138 for (CellIterator c=cells.begin(); c!=cells.end(); c++)
00139 {
00140 int cellLID = *c;
00141 cellLIDs[r].append(cellLID);
00142 }
00143 if (cellLIDs[r].size()==0) continue;
00144 int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);
00145 if (d==0)
00146 {
00147 for (int c=0; c<cellLIDs[r].size(); c++)
00148 {
00149 int fLID = cellLIDs[r][c];
00150 nodeToFuncSetMap[fLID].merge(funcSets[r]);
00151 }
00152 }
00153 else
00154 {
00155 Array<int>& facetLID = facetLIDs[r];
00156 facetLID.resize(nFacets*cellLIDs[r].size());
00157 facetOrientations[r].resize(nFacets*cellLIDs[r].size());
00158 mesh.getFacetLIDs(d, cellLIDs[r], 0, facetLID, facetOrientations[r]);
00159 for (int c=0; c<cellLIDs[r].size(); c++)
00160 {
00161 for (int f=0; f<nFacets; f++)
00162 {
00163 int fLID = facetLID[c*nFacets+f];
00164 nodeToFuncSetMap[fLID].merge(funcSets[r]);
00165 }
00166 }
00167 }
00168 }
00169
00170
00171
00172 Map<Set<int>, int> fsToFSIndexMap;
00173 Array<int> funcSetNodeCounts;
00174 int nNodes = mesh.numCells(0);
00175
00176 for (int n=0; n<nNodes; n++)
00177 {
00178 const Set<int>& f = nodeToFuncSetMap[n];
00179 int funcComboIndex;
00180 if (!fsToFSIndexMap.containsKey(f))
00181 {
00182 funcComboIndex = nodalFuncSets_.size();
00183 fsToFSIndexMap.put(f, funcComboIndex);
00184 nodalFuncSets_.append(f);
00185 funcSetNodeCounts.append(1);
00186 nodeToOffsetMap_[n] = 0;
00187 }
00188 else
00189 {
00190 funcComboIndex = fsToFSIndexMap.get(f);
00191 nodeToOffsetMap_[n] = f.size() * funcSetNodeCounts[funcComboIndex];
00192 funcSetNodeCounts[funcComboIndex]++;
00193 }
00194 nodeToFuncSetIndexMap_[n] = funcComboIndex;
00195 }
00196
00197 SUNDANCE_MSG2(setupVerb, "nodal func sets = " << nodalFuncSets_);
00198
00199 nodeDofs_.resize(nodalFuncSets_.size());
00200 nodeStructure_.resize(nodalFuncSets_.size());
00201 funcIndexWithinNodeFuncSet_.resize(nodalFuncSets_.size());
00202
00203 for (int f=0; f<nodalFuncSets_.size(); f++)
00204 {
00205 Array<int> funcs = nodalFuncSets_[f].elements();
00206 int nFuncs = funcs.size();
00207 funcIndexWithinNodeFuncSet_[f].resize(nTotalFuncs_, -1);
00208 for (int i=0; i<nFuncs; i++)
00209 {
00210 funcIndexWithinNodeFuncSet_[f][funcs[i]] = i;
00211 }
00212 nodeDofs_[f].resize(nFuncs * funcSetNodeCounts[f], -1);
00213 Array<RCP<BasisDOFTopologyBase> > nodeBases = tuple(basis_);
00214 Array<Array<int> > nodeFuncs = tuple(nodalFuncSets_[f].elements());
00215 nodeStructure_[f] = rcp(new MapStructure(nTotalFuncs_,
00216 nodeBases, nodeFuncs));
00217 }
00218
00219
00220
00221
00222 int nextDOF = 0;
00223 Array<int> hasProcessedNode(nNodes);
00224 Array<Array<int> > remoteNodes(mesh.comm().getNProc());
00225
00226 for (int r=0; r<subdomains.size(); r++)
00227 {
00228 int d = subdomains[r].dimension(mesh);
00229
00230 if (cellLIDs[r].size()==0) continue;
00231
00232 if (d==0)
00233 {
00234 for (int c=0; c<cellLIDs[r].size(); c++)
00235 {
00236 int fLID = cellLIDs[r][c];
00237 int funcSetIndex = nodeToFuncSetIndexMap_[fLID];
00238 int nFuncs = nodalFuncSets_[funcSetIndex].size();
00239 int dofOffset = nodeToOffsetMap_[fLID];
00240 if (!hasProcessedNode[fLID])
00241 {
00242 assignNode(fLID, funcSetIndex, dofOffset, nFuncs,
00243 remoteNodes, hasProcessedNode, nextDOF);
00244 }
00245 }
00246 }
00247 else
00248 {
00249 Array<int>& facetLID = facetLIDs[r];
00250 int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);
00251 for (int c=0; c<cellLIDs[r].size(); c++)
00252 {
00253 for (int f=0; f<nFacets; f++)
00254 {
00255 int fLID = facetLID[c*nFacets+f];
00256 int funcSetIndex = nodeToFuncSetIndexMap_[fLID];
00257 int dofOffset = nodeToOffsetMap_[fLID];
00258 int nFuncs = nodalFuncSets_[funcSetIndex].size();
00259 if (!hasProcessedNode[fLID])
00260 {
00261 assignNode(fLID, funcSetIndex, dofOffset, nFuncs,
00262 remoteNodes, hasProcessedNode, nextDOF);
00263 }
00264 }
00265 }
00266 }
00267 }
00268
00269
00270
00271 int localCount = nextDOF;
00272 computeOffsets(localCount);
00273
00274
00275 shareRemoteDOFs(remoteNodes);
00276
00277
00278 elemDofs_.resize(maxSubdomains.size());
00279 int count = 0;
00280 Array<Array<int> > elemFuncArrays;
00281
00282 funcDomains_.resize(nTotalFuncs_);
00283
00284 for (int r=0; r<subdomains.size(); r++)
00285 {
00286 int d = subdomains[r].dimension(mesh);
00287 if (d != dim_) continue;
00288 if (cellLIDs[r].size()==0) continue;
00289 int nFacets = mesh.numFacets(d, cellLIDs[r][0], 0);
00290 Array<int>& facetLID = facetLIDs[r];
00291 Array<Array<int> > dofs(1);
00292 dofs[0].resize(funcArrays[r].size() * cellLIDs[r].size() * nFacets);
00293 getFunctionDofs(d, cellLIDs[r], facetLID, funcArrays[r], dofs);
00294 elemDofs_[count] = dofs[0];
00295 elemFuncArrays.append(funcArrays[r]);
00296 Array<RCP<BasisDOFTopologyBase> > elemBases = tuple(basis_);
00297 Array<Array<int> > elemFuncs = tuple(elemFuncSets_[count].elements());
00298 elemStructure_.append(rcp(new MapStructure(nTotalFuncs_,
00299 elemBases, elemFuncs)));
00300 for (int c=0; c<cellLIDs[r].size(); c++)
00301 {
00302 elemToFuncSetIndexMap_[cellLIDs[r][c]] = count;
00303 }
00304 for (int i=0; i<elemFuncs[0].size(); i++)
00305 {
00306 funcDomains_[elemFuncs[0][i]] = funcDomains_[elemFuncs[0][i]] + subdomains[r];
00307 }
00308 count++;
00309 }
00310
00311 }
00312
00313
00314 void InhomogeneousNodalDOFMap::getFunctionDofs(int cellDim,
00315 const Array<int>& cellLID,
00316 const Array<int>& facetLID,
00317 const Array<int>& funcs,
00318 Array<Array<int> >& dofs) const
00319 {
00320 Array<int>& dofChunk = dofs[0];
00321 dofChunk.clear();
00322
00323 if (cellDim != 0)
00324 {
00325 int nFacets = mesh().numFacets(cellDim, cellLID[0], 0);
00326 dofChunk.resize(funcs.size() * cellLID.size() * nFacets, -1);
00327
00328
00329 for (int c=0; c<cellLID.size(); c++)
00330 {
00331 for (int f=0; f<nFacets; f++)
00332 {
00333 int fLID = facetLID[c*nFacets + f];
00334 int fci = nodeToFuncSetIndexMap_[fLID];
00335 int nodeOffset = nodeToOffsetMap_[fLID];
00336 for (int i=0; i<funcs.size(); i++)
00337 {
00338 int funcIndex = funcIndexWithinNodeFuncSet_[fci][funcs[i]];
00339 if (funcIndex >= 0)
00340 {
00341 dofChunk[(c*funcs.size()+i)*nFacets + f]
00342 = nodeDofs_[fci][nodeOffset+funcIndex];
00343
00344 }
00345 }
00346 }
00347 }
00348 }
00349 else
00350 {
00351 dofChunk.resize(funcs.size() * cellLID.size(), -1);
00352
00353 for (int c=0; c<cellLID.size(); c++)
00354 {
00355 int fci = nodeToFuncSetIndexMap_[cellLID[c]];
00356 int nodeOffset = nodeToOffsetMap_[cellLID[c]];
00357 for (int i=0; i<funcs.size(); i++)
00358 {
00359 int funcIndex = funcIndexWithinNodeFuncSet_[fci][funcs[i]];
00360 if (funcIndex >= 0)
00361 {
00362 dofChunk[c*funcs.size()+ i]
00363 = nodeDofs_[fci][nodeOffset+funcIndex];
00364 }
00365 }
00366 }
00367 }
00368 }
00369
00370 void InhomogeneousNodalDOFMap::assignNode(int fLID,
00371 int funcSetIndex,
00372 int dofOffset,
00373 int nFuncs,
00374 Array<Array<int> >& remoteNodes,
00375 Array<int>& hasProcessedCell,
00376 int& nextDOF)
00377 {
00378
00379 int owner;
00380 if (isRemote(0, fLID, owner))
00381 {
00382 int facetGID
00383 = mesh().mapLIDToGID(0, fLID);
00384 remoteNodes[owner].append(facetGID);
00385
00386 }
00387 else
00388 {
00389
00390 Array<int>& myDofs = nodeDofs_[funcSetIndex];
00391 for (int i=0; i<nFuncs; i++)
00392 {
00393 myDofs[dofOffset + i] = nextDOF;
00394 nextDOF++;
00395 }
00396 }
00397 hasProcessedCell[fLID] = 1;
00398 }
00399
00400 void InhomogeneousNodalDOFMap::computeOffsets(int localCount)
00401 {
00402 TEUCHOS_TEST_FOR_EXCEPTION(mesh().comm().getNProc() != 1,
00403 std::runtime_error,
00404 "parallel inhomogeneous DOF maps not yet supported");
00405
00406 int totalDOFCount = localCount;
00407 int myOffset = 0;
00408 setLowestLocalDOF(myOffset);
00409 setNumLocalDOFs(localCount);
00410 setTotalNumDOFs(totalDOFCount);
00411 }
00412
00413 void InhomogeneousNodalDOFMap::shareRemoteDOFs(const Array<Array<int> >& remoteNodes)
00414 {
00415 TEUCHOS_TEST_FOR_EXCEPTION(mesh().comm().getNProc() != 1,
00416 std::runtime_error,
00417 "parallel inhomogeneous DOF maps not yet supported");
00418 }
00419
00420 RCP<const Set<int> >
00421 InhomogeneousNodalDOFMap::allowedFuncsOnCellBatch(int cellDim,
00422 const Array<int>& cellLID) const
00423 {
00424 Set<int> rtn;
00425
00426 if (cellDim==0)
00427 {
00428 rtn = nodalFuncSets_[nodeToFuncSetIndexMap_[cellLID[0]]];
00429 for (int c=0; c<cellLID.size(); c++)
00430 {
00431 const Set<int>& s = nodalFuncSets_[nodeToFuncSetIndexMap_[cellLID[c]]];
00432 rtn = rtn.intersection(s);
00433 }
00434 }
00435 else if (cellDim==dim_)
00436 {
00437 rtn = elemFuncSets_[elemToFuncSetIndexMap_[cellLID[0]]];
00438 for (int c=0; c<cellLID.size(); c++)
00439 {
00440 const Set<int>& s = elemFuncSets_[elemToFuncSetIndexMap_[cellLID[c]]];
00441 rtn = rtn.intersection(s);
00442 }
00443 }
00444 else
00445 {
00446 Array<int> facetLID;
00447 Array<int> facetOrientations;
00448 mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00449 rtn = nodalFuncSets_[nodeToFuncSetIndexMap_[facetLID[0]]];
00450 for (int f=0; f<facetLID.size(); f++)
00451 {
00452 const Set<int>& s = nodalFuncSets_[nodeToFuncSetIndexMap_[facetLID[f]]];
00453 rtn = rtn.intersection(s);
00454 }
00455 }
00456 return rcp(new Set<int>(rtn));
00457 }
00458
00459
00460 RCP<const MapStructure>
00461 InhomogeneousNodalDOFMap::getDOFsForCellBatch(int cellDim,
00462 const Array<int>& cellLID,
00463 const Set<int>& requestedFuncSet,
00464 Array<Array<int> >& dofs,
00465 Array<int>& nNodes,
00466 int verb) const
00467 {
00468 TimeMonitor timer(batchedDofLookupTimer());
00469 Tabs tab0;
00470
00471 SUNDANCE_MSG2(verb, tab0 << "in InhomNodalDOFMap::getDOFsForCellBatch()");
00472
00473 if (cellDim==0)
00474 {
00475 Tabs tab1;
00476 SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00477 bool isHomogeneous = true;
00478 int firstFuncSet = nodeToFuncSetIndexMap_[cellLID[0]];
00479 for (int c=0; c<cellLID.size(); c++)
00480 {
00481 if (nodeToFuncSetIndexMap_[cellLID[c]] != firstFuncSet)
00482 {
00483 isHomogeneous = false;
00484 break;
00485 }
00486 }
00487
00488 dofs.resize(1);
00489 nNodes.resize(1);
00490 nNodes[0] = 1;
00491 Array<int> dummyFacets;
00492
00493 if (isHomogeneous)
00494 {
00495 const Set<int>& funcSet = nodalFuncSets_[firstFuncSet];
00496 TEUCHOS_TEST_FOR_EXCEPT(requestedFuncSet.setDifference(funcSet).size() != 0);
00497 Array<int> funcs = funcSet.elements();
00498 getFunctionDofs(cellDim, cellLID, dummyFacets, funcs, dofs);
00499 return nodeStructure_[firstFuncSet];
00500 }
00501 else
00502 {
00503 Array<int> funcs = requestedFuncSet.elements();
00504 getFunctionDofs(cellDim, cellLID, dummyFacets, funcs, dofs);
00505 RCP<const MapStructure> rtn
00506 = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00507 return rtn;
00508 }
00509 }
00510 else if (cellDim==dim_)
00511 {
00512 Tabs tab1;
00513 SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00514 bool isHomogeneous = true;
00515 int firstFuncSet = elemToFuncSetIndexMap_[cellLID[0]];
00516 SUNDANCE_MSG2(verb, tab1 << "first func set = " << firstFuncSet);
00517 for (int c=0; c<cellLID.size(); c++)
00518 {
00519 if (elemToFuncSetIndexMap_[cellLID[c]] != firstFuncSet)
00520 {
00521 isHomogeneous = false;
00522 break;
00523 }
00524 }
00525
00526 dofs.resize(1);
00527 nNodes.resize(1);
00528 nNodes[0] = mesh().numFacets(cellDim, cellLID[0], 0);
00529
00530 if (isHomogeneous)
00531 {
00532 Tabs tab2;
00533 Array<int> facetLID;
00534 Array<int> facetOrientations;
00535 mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00536 if (verb >= 2)
00537 {
00538 Out::os() << tab2 << "cellLID = " << cellLID << std::endl;
00539 Out::os() << tab2 << "facetLID = " << facetLID << std::endl;
00540 Out::os() << tab2 << "elem func sets = " << elemFuncSets_ << std::endl;
00541 }
00542 const Set<int>& funcSet = elemFuncSets_[firstFuncSet];
00543 TEUCHOS_TEST_FOR_EXCEPT(requestedFuncSet.setDifference(funcSet).size() != 0);
00544 Array<int> funcs = funcSet.elements();
00545 getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00546 return elemStructure_[firstFuncSet];
00547 }
00548 else
00549 {
00550 Array<int> facetLID;
00551 Array<int> facetOrientations;
00552 mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00553 Array<int> funcs = requestedFuncSet.elements();
00554 getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00555 RCP<const MapStructure> rtn
00556 = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00557 return rtn;
00558 }
00559 }
00560 else
00561 {
00562 Tabs tab1;
00563 SUNDANCE_MSG2(verb, tab1 << "cell dim = " << cellDim);
00564 Array<int> facetLID;
00565 Array<int> facetOrientations;
00566 mesh().getFacetLIDs(cellDim, cellLID, 0, facetLID, facetOrientations);
00567 dofs.resize(1);
00568 nNodes.resize(1);
00569 nNodes[0] = mesh().numFacets(cellDim, cellLID[0], 0);
00570
00571 Array<int> funcs = requestedFuncSet.elements();
00572
00573 getFunctionDofs(cellDim, cellLID, facetLID, funcs, dofs);
00574 RCP<const MapStructure> rtn
00575 = rcp(new MapStructure(nTotalFuncs_, basis_, tuple(funcs)));
00576 return rtn;
00577 }
00578 }
00579
00580
00581
00582 void InhomogeneousNodalDOFMap::print(std::ostream& os) const
00583 {
00584 Tabs tab0;
00585 std::cout << tab0 << "dof map: " << std::endl;
00586 for (int d=0; d<=dim_; d++)
00587 {
00588 Tabs tab1;
00589 std::cout << tab1 << d << "-cells: " << std::endl;
00590 for (int n=0; n<mesh().numCells(d); n++)
00591 {
00592 Tabs tab2;
00593 std::cout << tab2 << "d=" << d << " cell=" << n << std::endl;
00594 RCP<const Set<int> > funcs = allowedFuncsOnCellBatch(d, tuple(n));
00595 for (Set<int>::const_iterator f=funcs->begin(); f!=funcs->end(); f++)
00596 {
00597 Tabs tab3;
00598 Array<int> dofs;
00599 getDOFsForCell(d, n, *f, dofs);
00600 std::cout << tab3 << " f=" << *f << " dofs=" << dofs << std::endl;
00601 }
00602 }
00603 }
00604 }