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 "SundanceInhomogeneousEdgeLocalizedDOFMap.hpp"
00043
00044 #include "SundanceEdgeLocalizedBasis.hpp"
00045 #include "SundanceOrderedTuple.hpp"
00046
00047 #include <numeric>
00048 #include <algorithm>
00049
00050 namespace Sundance {
00051
00052 using Teuchos::null;
00053
00054 InhomogeneousEdgeLocalizedDOFMap::InhomogeneousEdgeLocalizedDOFMap(const Mesh& mesh,
00055 const Array<Map<Set<int>, CellFilter> >& funcSetToDomainMap,
00056 int setupVerb) :
00057 DOFMapBase(mesh, setupVerb),
00058 funcDomains_(),
00059 edgeDofs_()
00060 {
00061 SUNDANCE_MSG1(setupVerb, "in InhomogeneousEdgeLocalizedDOFMap ctor");
00062
00063 TEUCHOS_TEST_FOR_EXCEPTION(mesh.comm().getNProc() != 1,
00064 std::runtime_error,
00065 "distributed inhomogeneous edge localized DOF maps not yet supported");
00066
00067 SUNDANCE_MSG4(setupVerb, "func set to domain map " << funcSetToDomainMap);
00068
00069 TEUCHOS_ASSERT(funcSetToDomainMap.size() > 1);
00070 TEUCHOS_ASSERT(funcSetToDomainMap[0].empty());
00071
00072 TEUCHOS_ASSERT(funcSetToDomainMap.size() <= this->meshDimension() + 1);
00073
00074 Map<int, Array<Array<CellFilter> > > funcFilters;
00075 Map<CellFilter, Array<int> > filterEdges;
00076 for (int dim = 1; dim <= this->meshDimension(); ++dim) {
00077 const Map<Set<int>, CellFilter> &funcsOnDom = funcSetToDomainMap[dim];
00078 for (Map<Set<int>, CellFilter>::const_iterator it = funcsOnDom.begin(),
00079 it_end = funcsOnDom.end();
00080 it != it_end;
00081 ++it)
00082 {
00083 const CellFilter &subdomain = it->second;
00084 filterEdges[subdomain] = getEdgeLIDs(subdomain);
00085
00086 const Set<int> &funcs = it->first;
00087 for (Set<int>::const_iterator jt = funcs.begin(),
00088 jt_end = funcs.end();
00089 jt != jt_end;
00090 ++jt)
00091 {
00092 Array<Array<CellFilter> > &filters = funcFilters[*jt];
00093 filters.resize(this->meshDimension() + 1);
00094 filters[dim].append(subdomain);
00095 }
00096 }
00097 }
00098
00099 SUNDANCE_MSG4(setupVerb, "subdomains to edges " << filterEdges);
00100 SUNDANCE_MSG4(setupVerb, "func ids to subdomains " << funcFilters);
00101
00102 const int functionCount = funcFilters.empty() ? 0 : funcFilters.rbegin()->first + 1;
00103 funcDomains_.resize(functionCount);
00104
00105 for (Map<int, Array<Array<CellFilter> > >::const_iterator funcIt = funcFilters.begin(),
00106 funcItEnd = funcFilters.end();
00107 funcIt != funcItEnd;
00108 ++funcIt)
00109 {
00110 const Array<CellFilter> &maxDimFilters = (funcIt->second)[this->meshDimension()];
00111 funcDomains_[funcIt->first] = std::accumulate(maxDimFilters.begin(), maxDimFilters.end(), CellFilter());
00112 }
00113
00114 SUNDANCE_MSG4(setupVerb, "func ids to max dim subdomains " << funcDomains_);
00115
00116 typedef OrderedPair<int, int> DofId;
00117 Array<DofId> dofSet;
00118 for (Map<int, Array<Array<CellFilter> > >::const_iterator funcIt = funcFilters.begin(),
00119 funcItEnd = funcFilters.end();
00120 funcIt !=funcItEnd;
00121 ++funcIt)
00122 {
00123 const int funcId = funcIt->first;
00124 Set<int> dofBearingEdges;
00125 for (int dim = 1; dim <= this->meshDimension(); ++dim)
00126 {
00127 const Array<CellFilter> &dimFilters = (funcIt->second)[dim];
00128 for (Array<CellFilter>::const_iterator filtIt = dimFilters.begin(),
00129 filtItEnd = dimFilters.end();
00130 filtIt != filtItEnd;
00131 ++filtIt)
00132 {
00133 const Array<int> &edges = filterEdges[*filtIt];
00134 dofBearingEdges.insert(edges.begin(), edges.end());
00135 }
00136 }
00137 for (Set<int>::const_iterator edgeIt = dofBearingEdges.begin(),
00138 edgeItEnd = dofBearingEdges.end();
00139 edgeIt != edgeItEnd;
00140 ++edgeIt)
00141 {
00142 dofSet.push_back(DofId(*edgeIt, funcId));
00143 }
00144 }
00145
00146 const int dofCount = dofSet.size();
00147
00148 SUNDANCE_MSG1(setupVerb, "number of degrees of freedom = " << dofCount);
00149 SUNDANCE_MSG4(setupVerb, "set of degrees of freedom " << dofSet);
00150
00151 const int edgeCount = mesh.numCells(1);
00152 edgeDofs_.resize(edgeCount, Array<int>(functionCount, -1));
00153
00154 std::sort(dofSet.begin(), dofSet.end());
00155 int dofRank = 0;
00156 for (Array<DofId>::const_iterator dofIt = dofSet.begin(),
00157 dofItEnd = dofSet.end();
00158 dofIt != dofItEnd;
00159 ++dofIt)
00160 {
00161 const int edgeId = dofIt->first();
00162 const int funcId = dofIt->second();
00163 edgeDofs_[edgeId][funcId] = dofRank++;
00164 }
00165
00166 SUNDANCE_MSG4(setupVerb, "degrees of freedom on edges " << edgeDofs_);
00167
00168 this->setLowestLocalDOF(0);
00169 this->setNumLocalDOFs(dofCount);
00170 this->setTotalNumDOFs(dofCount);
00171 }
00172
00173 RCP<const MapStructure>
00174 InhomogeneousEdgeLocalizedDOFMap::getDOFsForCellBatch(int cellDim,
00175 const Array<int>& cellLIDs,
00176 const Set<int>& requestedFuncSet,
00177 Array<Array<int> >& dofs,
00178 Array<int>& nNodes,
00179 int verb) const
00180 {
00181 TEUCHOS_ASSERT(requestedFuncSet.setDifference(*this->allowedFuncsOnCellBatch(cellDim, cellLIDs)).empty());
00182
00183 int edgesPerCell;
00184 if (cellDim == 0)
00185 {
00186
00187 edgesPerCell = 0;
00188 const Array<int> empty;
00189 getDOFsForEdgeBatch(empty, requestedFuncSet, dofs, verb);
00190 }
00191 else if (cellDim == 1)
00192 {
00193
00194 edgesPerCell = 1;
00195 getDOFsForEdgeBatch(cellLIDs, requestedFuncSet, dofs, verb);
00196 }
00197 else
00198 {
00199
00200 const int edgeDim = 1;
00201 edgesPerCell = this->mesh().numFacets(cellDim, 0, edgeDim);
00202 Array<int> edgeLIDs;
00203 {
00204 Array<int> dummyOrientations;
00205 this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00206 TEUCHOS_ASSERT(edgeLIDs.size() == edgesPerCell * cellLIDs.size());
00207 }
00208
00209 getDOFsForEdgeBatch(edgeLIDs, requestedFuncSet, dofs, verb);
00210 }
00211
00212 nNodes.resize(1);
00213 nNodes[0] = edgesPerCell;
00214
00215 const Array<int> requestedFuncArray(requestedFuncSet.begin(), requestedFuncSet.end());
00216 return rcp(new MapStructure(requestedFuncSet.size(), rcp(new EdgeLocalizedBasis()), tuple(requestedFuncArray)));
00217 }
00218
00219 void
00220 InhomogeneousEdgeLocalizedDOFMap::getDOFsForEdgeBatch(const Array<int>& edgeLIDs,
00221 const Set<int>& requestedFuncSet,
00222 Array<Array<int> >& dofs,
00223 int verb) const
00224 {
00225 dofs.resize(1);
00226 Array<int> &dofChunk = dofs[0];
00227 dofChunk.resize(edgeLIDs.size() * requestedFuncSet.size());
00228
00229 Array<int>::iterator entryIt = dofChunk.begin();
00230 for (Array<int>::const_iterator edgeIt = edgeLIDs.begin(),
00231 edgeItEnd = edgeLIDs.end();
00232 edgeIt != edgeItEnd;
00233 ++edgeIt)
00234 {
00235 for (Set<int>::const_iterator funcIt = requestedFuncSet.begin(),
00236 funcItEnd = requestedFuncSet.end();
00237 funcIt != funcItEnd;
00238 ++funcIt)
00239 {
00240 (*entryIt++) = edgeDofs_[*edgeIt][*funcIt];
00241 }
00242 }
00243 }
00244
00245 RCP<const Set<int> >
00246 InhomogeneousEdgeLocalizedDOFMap::allowedFuncsOnCellBatch(int cellDim,
00247 const Array<int>& cellLIDs) const
00248 {
00249 if (cellDim == 0)
00250 {
00251
00252 return rcp(new Set<int>());
00253 }
00254
00255 if (cellDim == this->meshDimension())
00256 {
00257
00258
00259 return this->allFuncIDs();
00260 }
00261
00262 const int edgeDim = 1;
00263 if (cellDim == edgeDim)
00264 {
00265
00266 return this->allowedFuncsOnEdgeBatch(cellLIDs);
00267 }
00268
00269
00270 Array<int> edgeLIDs;
00271 Array<int> dummyOrientations;
00272 this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00273 return this->allowedFuncsOnEdgeBatch(edgeLIDs);
00274 }
00275
00276 RCP<Set<int> >
00277 InhomogeneousEdgeLocalizedDOFMap::allowedFuncsOnEdgeBatch(const Array<int> &edgeLIDs) const
00278 {
00279 const RCP<Set<int> > result = this->allFuncIDs();
00280
00281 for (Array<int>::const_iterator edgeIt = edgeLIDs.begin(),
00282 edgeItEnd = edgeLIDs.end();
00283 edgeIt != edgeItEnd;
00284 ++edgeIt)
00285 {
00286 const Array<int> &dofs = edgeDofs_[*edgeIt];
00287
00288 for (Set<int>::iterator it = result->begin(); it != result->end(); )
00289 {
00290 if (dofs[*it] < 0)
00291 {
00292 result->erase(it++);
00293 }
00294 else
00295 {
00296 ++it;
00297 }
00298 }
00299
00300 if (result->empty())
00301 {
00302 break;
00303 }
00304 }
00305
00306 return result;
00307 }
00308
00309 RCP<Set<int> >
00310 InhomogeneousEdgeLocalizedDOFMap::allFuncIDs() const
00311 {
00312 const RCP<Set<int> > result(new Set<int>());
00313 for (int i = 0; i < funcDomains_.size(); ++i)
00314 {
00315 result->insert(result->end(), i);
00316 }
00317 return result;
00318 }
00319
00320 void
00321 InhomogeneousEdgeLocalizedDOFMap::print(std::ostream& os) const
00322 {
00323 os << "InhomogeneousEdgeLocalizedDOFMap\n";
00324 os << "Edges in mesh = " << edgeDofs_.size() << "\n";
00325 os << "Functions = " << funcDomains_.size() << "\n";
00326
00327 for (int dim = 1; dim <= this->meshDimension(); ++dim)
00328 {
00329 os << "Dofs on cells of dimension " << dim << ":\n";
00330 const int cellCount = this->mesh().numCells(dim);
00331 for (int iCell = 0; iCell < cellCount; ++iCell)
00332 {
00333 os << " Cell LID " << iCell << "\n";
00334 const RCP<const Set<int> > funcs = this->allowedFuncsOnCellBatch(dim, tuple(iCell));
00335 for (Set<int>::const_iterator it = funcs->begin(),
00336 it_end = funcs->end();
00337 it != it_end;
00338 ++it)
00339 {
00340 const int funcId = *it;
00341 os << " Function " << funcId << " : {";
00342 Array<int> dofs;
00343 this->getDOFsForCell(dim, iCell, funcId, dofs);
00344 for (Array<int>::const_iterator jt = dofs.begin(),
00345 jt_end = dofs.end();
00346 jt != jt_end;
00347 ++jt)
00348 {
00349 if (jt != dofs.begin())
00350 {
00351 os << ", ";
00352 }
00353 os << *jt;
00354 }
00355 os << "}\n";
00356 }
00357 }
00358 }
00359 }
00360
00361 int
00362 InhomogeneousEdgeLocalizedDOFMap::meshDimension() const
00363 {
00364 return this->mesh().spatialDim();
00365 }
00366
00367 Array<int>
00368 InhomogeneousEdgeLocalizedDOFMap::getEdgeLIDs(const CellFilter &filter) const
00369 {
00370 const int cellDim = filter.dimension(this->mesh());
00371
00372 const int nodeDim = 0;
00373 if (cellDim == nodeDim)
00374 {
00375
00376 return Array<int>();
00377 }
00378
00379 const CellSet cells = filter.getCells(this->mesh());
00380 const Array<int> cellLIDs(cells.begin(), cells.end());
00381
00382 const int edgeDim = 1;
00383 if (cellDim == edgeDim)
00384 {
00385
00386 return cellLIDs;
00387 }
00388
00389
00390 Array<int> edgeLIDs;
00391 Array<int> dummyOrientations;
00392 this->mesh().getFacetLIDs(cellDim, cellLIDs, edgeDim, edgeLIDs, dummyOrientations);
00393
00394 return edgeLIDs;
00395 }
00396
00397 }