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<> >());
Implements arbitrary-dimensional extrusion of a base shards::CellTopology.
CellTopoPtr getSide(ordinal_type sideOrdinal) const
Returns a CellTopoPtr for the specified side.
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...
ordinal_type getVertexCount() const
Vertex 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.
static CellTopoPtr cellTopology(const shards::CellTopology &shardsCellTopo, ordinal_type tensorialDegree=0)
static accessor that returns a CellTopoPtr; these are lazily constructed and cached.
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 getNodeCount() const
Node count of this cell topology.
CellTopology(const shards::CellTopology &baseTopo, ordinal_type tensorialDegree)
Constructor.
std::string getName() const
Human-readable name of the CellTopology.
ordinal_type getSubcellCount(const ordinal_type subcell_dim) const
Subcell count of subcells of the given dimension.
ordinal_type getTensorialComponentSideOrdinal(ordinal_type extrusionNodeOrdinal)
Returns the side corresponding to the provided node in the final extrusion dimension.
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 getFaceCount() const
Face (dimension 2) subcell count of this cell topology.
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.
std::pair< ordinal_type, ordinal_type > getKey() const
Key that's unique for standard shards topologies and any tensorial degree.
ordinal_type getSideCount() const
Side (dimension N-1) subcell count of this cell topology.
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.
CellTopoPtr getSubcell(ordinal_type scdim, ordinal_type scord) const
Get the subcell of dimension scdim with ordinal scord.
bool sideIsExtrudedInFinalDimension(ordinal_type sideOrdinal) const
Returns true if the specified side has extension in the final tensorial dimension....
ordinal_type getNodePermutationCount() const
Number of node permutations defined for this cell.
const shards::CellTopology & getBaseTopology() const
Returns the underlying shards CellTopology.
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 getEdgeCount(const ordinal_type subcell_dim, const ordinal_type subcell_ord) const
Edge count of a subcell of the given dimension and ordinal.
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 getNodePermutationInverse(const ordinal_type permutation_ord, const ordinal_type node_ord) const
Inverse permutation of a cell's node ordinals.
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.
CellTopoPtr getTensorialComponent() const
For cell topologies of positive tensorial degree, returns the cell topology of tensorial degree one l...
ordinal_type getEdgeCount() const
Edge (dimension 1) subcell count of this cell topology.
ordinal_type getDimension() const
Dimension of this tensor topology.