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