18 #ifndef Intrepid2_CellTopology_h
19 #define Intrepid2_CellTopology_h
21 #include <Shards_CellTopology.hpp>
30 using CellTopoPtr = Teuchos::RCP<CellTopology>;
31 using CellTopologyKey = std::pair<ordinal_type,ordinal_type>;
33 shards::CellTopology shardsBaseTopology_;
34 ordinal_type tensorialDegree_;
38 std::vector< std::vector<CellTopoPtr> > subcells_;
47 CellTopology(
const shards::CellTopology &baseTopo, ordinal_type tensorialDegree)
49 shardsBaseTopology_(baseTopo),
50 tensorialDegree_(tensorialDegree)
53 if (tensorialDegree_ == 0)
55 name_ = baseTopo.getName();
59 std::ostringstream nameStream;
60 nameStream << baseTopo.getName();
61 for (
int tensorialOrdinal = 0; tensorialOrdinal < tensorialDegree; tensorialOrdinal++)
63 nameStream <<
" x Line_2";
65 name_ = nameStream.str();
68 int baseDim = baseTopo.getDimension();
69 vector<ordinal_type> subcellCounts = vector<ordinal_type>(baseDim + tensorialDegree_ + 1);
70 subcells_ = vector< vector< CellTopoPtr > >(baseDim + tensorialDegree_ + 1);
72 if (tensorialDegree_==0)
74 for (
int d=0; d<=baseDim; d++)
76 subcellCounts[d] =
static_cast<ordinal_type
>(baseTopo.getSubcellCount(d));
82 subcellCounts[0] = 2 * tensorComponentTopo->getSubcellCount(0);
83 for (
int d=1; d < baseDim+tensorialDegree_; d++)
85 subcellCounts[d] = 2 * tensorComponentTopo->getSubcellCount(d) + tensorComponentTopo->getSubcellCount(d-1);
87 subcellCounts[baseDim + tensorialDegree_] = 1;
89 for (
int d=0; d<baseDim+tensorialDegree_; d++)
91 subcells_[d] = vector< CellTopoPtr >(subcellCounts[d]);
92 int subcellCount = subcells_[d].size();
93 for (
int scord=0; scord<subcellCount; scord++)
98 subcells_[baseDim+tensorialDegree_] = vector<CellTopoPtr>(1);
99 subcells_[baseDim+tensorialDegree_][0] = Teuchos::rcp(
this,
false);
105 return shardsBaseTopology_;
111 return tensorialDegree_;
117 return shardsBaseTopology_.getDimension() + tensorialDegree_;
120 static ordinal_type
getNodeCount(
const shards::CellTopology &shardsTopo)
122 if (shardsTopo.getDimension()==0)
return 1;
123 return shardsTopo.getNodeCount();
129 ordinal_type two_pow = 1 << tensorialDegree_;
161 int sideDim = spaceDim - 1;
168 std::pair<ordinal_type,ordinal_type>
getKey()
const
170 return std::make_pair(static_cast<ordinal_type>(shardsBaseTopology_.getKey()), tensorialDegree_);
178 const ordinal_type subcell_ord )
const
180 return subcells_[subcell_dim][subcell_ord]->getNodeCount();
195 const ordinal_type subcell_ord )
const
197 return subcells_[subcell_dim][subcell_ord]->getVertexCount();
205 const ordinal_type subcell_ord )
const
207 return subcells_[subcell_dim][subcell_ord]->getEdgeCount();
218 const ordinal_type subcell_ord_in_component_topo )
const
223 if (tensorialDegree_==0)
225 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"getExtrudedSubcellOrdinal() is not valid for un-extruded topologies");
229 ordinal_type componentSubcellCount =
getTensorialComponent()->getSubcellCount(subcell_dim_in_component_topo + 1);
230 return subcell_ord_in_component_topo + componentSubcellCount * 2;
239 const ordinal_type subcell_ord )
const
241 return subcells_[subcell_dim][subcell_ord]->getSideCount();
250 if (subcell_dim >= ordinal_type(subcells_.size()))
return 0;
251 else return subcells_[subcell_dim].size();
260 if (ordinal_type(tensorComponentNodes.size()) != tensorialDegree_ + 1)
262 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"tensorComponentNodes.size() != _tensorialDegree + 1");
274 ordinal_type node = 0;
275 CellTopoPtr line = CellTopology::line();
276 std::vector<CellTopoPtr> componentTopos(tensorialDegree_ + 1, line);
278 for (
int i=tensorComponentNodes.size()-1; i >= 0; i--)
280 ordinal_type componentNode = tensorComponentNodes[i];
281 node *= componentTopos[i]->getNodeCount();
282 node += componentNode;
294 const ordinal_type subcell_ord ,
295 const ordinal_type subcell_node_ord )
const
300 if (subcell_ord != 0)
302 TEUCHOS_TEST_FOR_EXCEPTION(subcell_ord != 0, std::invalid_argument,
"subcell ordinal out of bounds");
304 return subcell_node_ord;
306 else if (subcell_dim==0)
309 if (subcell_node_ord != 0)
311 TEUCHOS_TEST_FOR_EXCEPTION(subcell_node_ord != 0, std::invalid_argument,
"subcell node ordinal out of bounds");
315 if (tensorialDegree_==0)
317 return shardsBaseTopology_.getNodeMap(subcell_dim, subcell_ord, subcell_node_ord);
322 ordinal_type componentSubcellCount = tensorComponentTopo->getSubcellCount(subcell_dim);
323 if (subcell_ord < componentSubcellCount * 2)
325 ordinal_type subcell_ord_comp = subcell_ord % componentSubcellCount;
326 ordinal_type compOrdinal = subcell_ord / componentSubcellCount;
327 ordinal_type mappedNodeInsideComponentTopology = tensorComponentTopo->getNodeMap(subcell_dim, subcell_ord_comp, subcell_node_ord);
328 return mappedNodeInsideComponentTopology + compOrdinal * tensorComponentTopo->getNodeCount();
333 ordinal_type subcell_ord_comp = subcell_ord - componentSubcellCount * 2;
334 ordinal_type subcell_dim_comp = subcell_dim - 1;
335 CellTopoPtr subcellTensorComponent = tensorComponentTopo->getSubcell(subcell_dim_comp, subcell_ord_comp);
337 ordinal_type scCompOrdinal = subcell_node_ord / subcellTensorComponent->getNodeCount();
339 ordinal_type scCompNodeOrdinal = subcell_node_ord % subcellTensorComponent->getNodeCount();
340 ordinal_type mappedNodeInsideComponentTopology = tensorComponentTopo->getNodeMap(subcell_dim_comp, subcell_ord_comp, scCompNodeOrdinal);
341 return mappedNodeInsideComponentTopology + scCompOrdinal * tensorComponentTopo->getNodeCount();
354 const ordinal_type node_ord )
const;
361 const ordinal_type node_ord )
const;
365 CellTopoPtr
getSide( ordinal_type sideOrdinal )
const;
376 CellTopoPtr
getSubcell( ordinal_type scdim, ordinal_type scord )
const
378 if (tensorialDegree_==0)
380 return cellTopology(shardsBaseTopology_.getCellTopologyData(scdim, scord), 0);
385 ordinal_type componentSubcellCount = tensorComponentTopo->getSubcellCount(scdim);
386 if (scord < componentSubcellCount * 2)
388 scord = scord % componentSubcellCount;
389 return tensorComponentTopo->getSubcell(scdim, scord);
392 scord = scord - componentSubcellCount * 2;
394 CellTopoPtr subcellTensorComponent = tensorComponentTopo->getSubcell(scdim, scord);
395 return cellTopology(subcellTensorComponent->getBaseTopology(), subcellTensorComponent->getTensorialDegree() + 1);
403 static ordinal_type
getSubcellOrdinalMap(CellTopoPtr cellTopo, ordinal_type subcdim, ordinal_type subcord, ordinal_type subsubcdim, ordinal_type subsubcord)
409 typedef ordinal_type SubcellOrdinal;
410 typedef ordinal_type SubcellDimension;
411 typedef ordinal_type SubSubcellOrdinal;
412 typedef ordinal_type SubSubcellDimension;
413 typedef ordinal_type SubSubcellOrdinalInCellTopo;
414 typedef std::pair< SubcellDimension, SubcellOrdinal > SubcellIdentifier;
415 typedef std::pair< SubSubcellDimension, SubSubcellOrdinal > SubSubcellIdentifier;
416 typedef std::map< SubcellIdentifier, std::map< SubSubcellIdentifier, SubSubcellOrdinalInCellTopo > > OrdinalMap;
417 static std::map< CellTopologyKey, OrdinalMap > ordinalMaps;
419 if (subsubcdim==subcdim)
427 std::cout <<
"request for subsubcell of the same dimension as subcell, but with subsubcord > 0.\n";
428 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"request for subsubcell of the same dimension as subcell, but with subsubcord > 0.");
432 if (subcdim==cellTopo->getDimension())
440 std::cout <<
"request for subcell of the same dimension as cell, but with subsubcord > 0.\n";
441 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"request for subcell of the same dimension as cell, but with subsubcord > 0.");
445 CellTopologyKey key = cellTopo->getKey();
446 if (ordinalMaps.find(key) == ordinalMaps.end())
449 OrdinalMap ordinalMap;
450 ordinal_type sideDim = cellTopo->getDimension() - 1;
451 typedef ordinal_type NodeOrdinal;
452 std::map< std::set<NodeOrdinal>, SubcellIdentifier > subcellMap;
454 for (ordinal_type d=1; d<=sideDim; d++)
456 ordinal_type subcellCount = cellTopo->getSubcellCount(d);
457 for (ordinal_type subcellOrdinal=0; subcellOrdinal<subcellCount; subcellOrdinal++)
459 std::set<NodeOrdinal> nodes;
460 ordinal_type nodeCount = cellTopo->getNodeCount(d, subcellOrdinal);
461 for (NodeOrdinal subcNode=0; subcNode<nodeCount; subcNode++)
463 nodes.insert(cellTopo->getNodeMap(d, subcellOrdinal, subcNode));
465 SubcellIdentifier subcell = std::make_pair(d, subcellOrdinal);
466 subcellMap[nodes] = subcell;
468 CellTopoPtr subcellTopo = cellTopo->getSubcell(d, subcellOrdinal);
470 for (ordinal_type subsubcellDim=0; subsubcellDim<d; subsubcellDim++)
472 ordinal_type subsubcellCount = subcellTopo->getSubcellCount(subsubcellDim);
473 for (ordinal_type subsubcellOrdinal=0; subsubcellOrdinal<subsubcellCount; subsubcellOrdinal++)
475 SubSubcellIdentifier subsubcell = std::make_pair(subsubcellDim,subsubcellOrdinal);
476 if (subsubcellDim==0)
478 ordinalMap[subcell][subsubcell] = cellTopo->getNodeMap(subcell.first, subcell.second, subsubcellOrdinal);
481 ordinal_type nodeCount_inner = subcellTopo->getNodeCount(subsubcellDim, subsubcellOrdinal);
482 std::set<NodeOrdinal> subcellNodes;
483 for (NodeOrdinal subsubcNode=0; subsubcNode<nodeCount_inner; subsubcNode++)
485 NodeOrdinal subcNode = subcellTopo->getNodeMap(subsubcellDim, subsubcellOrdinal, subsubcNode);
486 NodeOrdinal node = cellTopo->getNodeMap(d, subcellOrdinal, subcNode);
487 subcellNodes.insert(node);
490 SubcellIdentifier subsubcellInCellTopo = subcellMap[subcellNodes];
491 ordinalMap[ subcell ][ subsubcell ] = subsubcellInCellTopo.second;
498 ordinalMaps[key] = ordinalMap;
500 SubcellIdentifier subcell = std::make_pair(subcdim, subcord);
501 SubSubcellIdentifier subsubcell = std::make_pair(subsubcdim, subsubcord);
502 if (ordinalMaps[key][subcell].find(subsubcell) != ordinalMaps[key][subcell].end())
504 return ordinalMaps[key][subcell][subsubcell];
508 std::cout <<
"For topology " << cellTopo->getName() <<
" and subcell " << subcord <<
" of dim " << subcdim;
509 std::cout <<
", subsubcell " << subsubcord <<
" of dim " << subsubcdim <<
" not found.\n";
510 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"subsubcell not found");
520 if (tensorialDegree_ > 0)
522 return cellTopology(shardsBaseTopology_, tensorialDegree_ - 1);
526 return Teuchos::null;
536 return extrusionNodeOrdinal;
545 if (tensorialDegree_ == 0)
return false;
547 return (sideOrdinal > 1) && (sideOrdinal < sideCount);
554 static CellTopoPtr
cellTopology(
const shards::CellTopology &shardsCellTopo, ordinal_type tensorialDegree = 0)
556 ordinal_type shardsKey =
static_cast<ordinal_type
>(shardsCellTopo.getBaseKey());
557 std::pair<ordinal_type,ordinal_type> key = std::make_pair(shardsKey, tensorialDegree);
559 static std::map< CellTopologyKey, CellTopoPtr > tensorizedShardsTopologies;
561 if (tensorizedShardsTopologies.find(key) == tensorizedShardsTopologies.end())
563 tensorizedShardsTopologies[key] = Teuchos::rcp(
new CellTopology(shardsCellTopo, tensorialDegree));
565 return tensorizedShardsTopologies[key];
568 static CellTopoPtr point()
570 return cellTopology(shards::getCellTopologyData<shards::Node >());
573 static CellTopoPtr line()
575 return cellTopology(shards::getCellTopologyData<shards::Line<> >());
578 static CellTopoPtr quad()
580 return cellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >());
583 static CellTopoPtr hexahedron()
585 return cellTopology(shards::getCellTopologyData<shards::Hexahedron<> >());
588 static CellTopoPtr triangle()
590 return cellTopology(shards::getCellTopologyData<shards::Triangle<> >());
593 static CellTopoPtr tetrahedron()
595 return cellTopology(shards::getCellTopologyData<shards::Tetrahedron<> >());
598 static CellTopoPtr wedge()
600 return cellTopology(shards::getCellTopologyData<shards::Wedge<> >());
ordinal_type getFaceCount() const
Face (dimension 2) subcell count of this cell topology.
std::pair< ordinal_type, ordinal_type > getKey() const
Key that's unique for standard shards topologies and any tensorial degree.
ordinal_type getNodePermutationInverse(const ordinal_type permutation_ord, const ordinal_type node_ord) const
Inverse permutation of a cell's node ordinals.
ordinal_type getNodePermutationCount() const
Number of node permutations defined for this cell.
ordinal_type getEdgeCount() const
Edge (dimension 1) subcell count of this cell topology.
ordinal_type getDimension() const
Dimension of this tensor topology.
ordinal_type getTensorialDegree() const
The number of times we have taken a tensor product between a line topology and the shards topology to...
ordinal_type getVertexCount(const ordinal_type subcell_dim, const ordinal_type subcell_ord) const
Vertex count of a subcell of the given dimension and ordinal.
ordinal_type getNodeMap(const ordinal_type subcell_dim, const ordinal_type subcell_ord, const ordinal_type subcell_node_ord) const
Mapping from a subcell's node ordinal to a node ordinal of this parent cell topology.
ordinal_type getVertexCount() const
Vertex count of this cell topology.
const shards::CellTopology & getBaseTopology() const
Returns the underlying shards CellTopology.
ordinal_type getNodeCount() const
Node count of this cell topology.
ordinal_type getNodePermutation(const ordinal_type permutation_ord, const ordinal_type node_ord) const
Permutation of a cell's node ordinals.
std::string getName() const
Human-readable name of the CellTopology.
ordinal_type getNodeCount(const ordinal_type subcell_dim, const ordinal_type subcell_ord) const
Node count of a subcell of the given dimension and ordinal.
ordinal_type getExtrudedSubcellOrdinal(const ordinal_type subcell_dim_in_component_topo, const ordinal_type subcell_ord_in_component_topo) const
Mapping from the tensorial component CellTopology's subcell ordinal to the corresponding subcell ordi...
bool sideIsExtrudedInFinalDimension(ordinal_type sideOrdinal) const
Returns true if the specified side has extension in the final tensorial dimension. For topologies with zero tensorialDegree_, returns false.
CellTopology(const shards::CellTopology &baseTopo, ordinal_type tensorialDegree)
Constructor.
ordinal_type getSideCount() const
Side (dimension N-1) subcell count of this cell topology.
CellTopoPtr getSubcell(ordinal_type scdim, ordinal_type scord) const
Get the subcell of dimension scdim with ordinal scord.
ordinal_type getEdgeCount(const ordinal_type subcell_dim, const ordinal_type subcell_ord) const
Edge count of a subcell of the given dimension and ordinal.
Implements arbitrary-dimensional extrusion of a base shards::CellTopology.
CellTopoPtr getTensorialComponent() const
For cell topologies of positive tensorial degree, returns the cell topology of tensorial degree one l...
ordinal_type getNodeFromTensorialComponentNodes(const std::vector< ordinal_type > &tensorComponentNodes) const
Mapping from the tensorial component node ordinals to the node ordinal of this tensor cell topology...
ordinal_type getTensorialComponentSideOrdinal(ordinal_type extrusionNodeOrdinal)
Returns the side corresponding to the provided node in the final extrusion dimension.
ordinal_type getSideCount(const ordinal_type subcell_dim, const ordinal_type subcell_ord) const
Side count of a subcell of the given dimension and ordinal.
static CellTopoPtr cellTopology(const shards::CellTopology &shardsCellTopo, ordinal_type tensorialDegree=0)
static accessor that returns a CellTopoPtr; these are lazily constructed and cached.
CellTopoPtr getSide(ordinal_type sideOrdinal) const
Returns a CellTopoPtr for the specified side.
static ordinal_type getSubcellOrdinalMap(CellTopoPtr cellTopo, ordinal_type subcdim, ordinal_type subcord, ordinal_type subsubcdim, ordinal_type subsubcord)
Maps the from a subcell within a subcell of the present CellTopology to the subcell in the present Ce...
ordinal_type getSubcellCount(const ordinal_type subcell_dim) const
Subcell count of subcells of the given dimension.