Intrepid2
Intrepid2_CellTopology.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid2 Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kyungjoo Kim (kyukim@sandia.gov),
38 // Mauro Perego (mperego@sandia.gov), or
39 // Nate Roberts (nvrober@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
52 #ifndef Intrepid2_CellTopology_h
53 #define Intrepid2_CellTopology_h
54 
55 #include <Shards_CellTopology.hpp>
56 
57 namespace Intrepid2
58 {
62  class CellTopology {
63  public:
64  using CellTopoPtr = Teuchos::RCP<CellTopology>;
65  using CellTopologyKey = std::pair<ordinal_type,ordinal_type>;
66  protected:
67  shards::CellTopology shardsBaseTopology_;
68  ordinal_type tensorialDegree_; // number of tensorial extrusions of the base topology
69 
70  std::string name_;
71 
72  std::vector< std::vector<CellTopoPtr> > subcells_; // ordered by dimension, then ordinal
73  public:
81  CellTopology(const shards::CellTopology &baseTopo, ordinal_type tensorialDegree)
82  :
83  shardsBaseTopology_(baseTopo),
84  tensorialDegree_(tensorialDegree)
85  {
86  using std::vector;
87  if (tensorialDegree_ == 0)
88  {
89  name_ = baseTopo.getName();
90  }
91  else
92  {
93  std::ostringstream nameStream;
94  nameStream << baseTopo.getName();
95  for (int tensorialOrdinal = 0; tensorialOrdinal < tensorialDegree; tensorialOrdinal++)
96  {
97  nameStream << " x Line_2";
98  }
99  name_ = nameStream.str();
100  }
101 
102  int baseDim = baseTopo.getDimension();
103  vector<ordinal_type> subcellCounts = vector<ordinal_type>(baseDim + tensorialDegree_ + 1);
104  subcells_ = vector< vector< CellTopoPtr > >(baseDim + tensorialDegree_ + 1);
105 
106  if (tensorialDegree_==0)
107  {
108  for (int d=0; d<=baseDim; d++)
109  {
110  subcellCounts[d] = static_cast<ordinal_type>(baseTopo.getSubcellCount(d));
111  }
112  }
113  else
114  {
115  CellTopoPtr tensorComponentTopo = getTensorialComponent();
116  subcellCounts[0] = 2 * tensorComponentTopo->getSubcellCount(0);
117  for (int d=1; d < baseDim+tensorialDegree_; d++)
118  {
119  subcellCounts[d] = 2 * tensorComponentTopo->getSubcellCount(d) + tensorComponentTopo->getSubcellCount(d-1);
120  }
121  subcellCounts[baseDim + tensorialDegree_] = 1; // the volume topology
122  }
123  for (int d=0; d<baseDim+tensorialDegree_; d++)
124  {
125  subcells_[d] = vector< CellTopoPtr >(subcellCounts[d]);
126  int subcellCount = subcells_[d].size();
127  for (int scord=0; scord<subcellCount; scord++)
128  {
129  subcells_[d][scord] = getSubcell(d, scord);
130  }
131  }
132  subcells_[baseDim+tensorialDegree_] = vector<CellTopoPtr>(1);
133  subcells_[baseDim+tensorialDegree_][0] = Teuchos::rcp(this, false); // false: does not own memory (self-reference)
134  }
135 
137  const shards::CellTopology & getBaseTopology() const
138  {
139  return shardsBaseTopology_;
140  }
141 
143  ordinal_type getTensorialDegree() const
144  {
145  return tensorialDegree_;
146  }
147 
149  ordinal_type getDimension() const
150  {
151  return shardsBaseTopology_.getDimension() + tensorialDegree_;
152  }
153 
154  static ordinal_type getNodeCount(const shards::CellTopology &shardsTopo)
155  {
156  if (shardsTopo.getDimension()==0) return 1; // Node topology; by my lights shards returns the wrong thing (0) here
157  return shardsTopo.getNodeCount();
158  }
159 
161  ordinal_type getNodeCount() const
162  {
163  ordinal_type two_pow = 1 << tensorialDegree_;
164  return getNodeCount(shardsBaseTopology_) * two_pow;
165  }
166 
168  ordinal_type getVertexCount() const
169  {
170  return getNodeCount();
171  }
172 
174  ordinal_type getEdgeCount() const
175  {
176  return getSubcellCount(1);
177  }
178 
180  ordinal_type getFaceCount() const
181  {
182  return getSubcellCount(2);
183  }
184 
186  ordinal_type getSideCount() const
187  {
188  ordinal_type spaceDim = getDimension();
189  if (spaceDim == 0)
190  {
191  return 0;
192  }
193  else
194  {
195  int sideDim = spaceDim - 1;
196  return getSubcellCount(sideDim);
197  }
198  }
199 
202  std::pair<ordinal_type,ordinal_type> getKey() const
203  {
204  return std::make_pair(static_cast<ordinal_type>(shardsBaseTopology_.getKey()), tensorialDegree_);
205  }
206 
211  ordinal_type getNodeCount( const ordinal_type subcell_dim ,
212  const ordinal_type subcell_ord ) const
213  {
214  return subcells_[subcell_dim][subcell_ord]->getNodeCount();
215  }
216 
219  std::string getName() const
220  {
221  return name_;
222  }
223 
228  ordinal_type getVertexCount( const ordinal_type subcell_dim ,
229  const ordinal_type subcell_ord ) const
230  {
231  return subcells_[subcell_dim][subcell_ord]->getVertexCount();
232  }
233 
238  ordinal_type getEdgeCount( const ordinal_type subcell_dim ,
239  const ordinal_type subcell_ord ) const
240  {
241  return subcells_[subcell_dim][subcell_ord]->getEdgeCount();
242  }
243 
251  ordinal_type getExtrudedSubcellOrdinal( const ordinal_type subcell_dim_in_component_topo ,
252  const ordinal_type subcell_ord_in_component_topo ) const
253  {
254  // The rule is that the two copies (unextruded) of subcells of dimension
255  // (subcell_dim_in_component_topo + 1) come first, and then the ones built from the extrusion of
256  // subcells of dimension subcell_dim_in_component_topo in the component topology.
257  if (tensorialDegree_==0)
258  {
259  INTREPID2_TEST_FOR_EXCEPTION(true, std::invalid_argument, "getExtrudedSubcellOrdinal() is not valid for un-extruded topologies");
260  }
261  else
262  {
263  ordinal_type componentSubcellCount = getTensorialComponent()->getSubcellCount(subcell_dim_in_component_topo + 1);
264  return subcell_ord_in_component_topo + componentSubcellCount * 2;
265  }
266  }
267 
272  ordinal_type getSideCount( const ordinal_type subcell_dim ,
273  const ordinal_type subcell_ord ) const
274  {
275  return subcells_[subcell_dim][subcell_ord]->getSideCount();
276  }
277 
278 
282  ordinal_type getSubcellCount( const ordinal_type subcell_dim ) const
283  {
284  if (subcell_dim >= ordinal_type(subcells_.size())) return 0;
285  else return subcells_[subcell_dim].size();
286  }
287 
292  ordinal_type getNodeFromTensorialComponentNodes(const std::vector<ordinal_type> &tensorComponentNodes) const
293  {
294  if (ordinal_type(tensorComponentNodes.size()) != tensorialDegree_ + 1)
295  {
296  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "tensorComponentNodes.size() != _tensorialDegree + 1");
297  }
298  /*
299  Example: we have a base topology of 4 nodes x line x line. Read addresses from right to left.
300 
301  address (1,0,0) --> 0 * (2 * 4) + 0 * 4 + 1 = 1
302  address (0,1,0) --> 0 * (2 * 4) + 1 * 4 + 0 = 4
303  address (0,0,1) --> 1 * (2 * 4) + 0 * 4 + 0 = 8
304  address (0,1,1) --> 1 * (2 * 4) + 1 * 4 + 0 = 12
305 
306  */
307 
308  ordinal_type node = 0;
309  CellTopoPtr line = CellTopology::line();
310  std::vector<CellTopoPtr> componentTopos(tensorialDegree_ + 1, line);
311  componentTopos[0] = cellTopology(shardsBaseTopology_);
312  for (int i=tensorComponentNodes.size()-1; i >= 0; i--)
313  {
314  ordinal_type componentNode = tensorComponentNodes[i];
315  node *= componentTopos[i]->getNodeCount();
316  node += componentNode;
317  }
318  return node;
319  }
320 
327  ordinal_type getNodeMap( const ordinal_type subcell_dim ,
328  const ordinal_type subcell_ord ,
329  const ordinal_type subcell_node_ord ) const
330  {
331  if (subcell_dim == getDimension())
332  {
333  // map from topology to itself
334  if (subcell_ord != 0)
335  {
336  TEUCHOS_TEST_FOR_EXCEPTION(subcell_ord != 0, std::invalid_argument, "subcell ordinal out of bounds");
337  }
338  return subcell_node_ord;
339  }
340  else if (subcell_dim==0)
341  {
342  // mapping a node--the subcell_node_ord must be 0, then, and we should just return the subcell_ord (which is the node ordinal)
343  if (subcell_node_ord != 0)
344  {
345  TEUCHOS_TEST_FOR_EXCEPTION(subcell_node_ord != 0, std::invalid_argument, "subcell node ordinal out of bounds");
346  }
347  return subcell_ord;
348  }
349  if (tensorialDegree_==0)
350  {
351  return shardsBaseTopology_.getNodeMap(subcell_dim, subcell_ord, subcell_node_ord);
352  }
353  else
354  {
355  CellTopoPtr tensorComponentTopo = CellTopology::cellTopology(shardsBaseTopology_, tensorialDegree_ - 1);
356  ordinal_type componentSubcellCount = tensorComponentTopo->getSubcellCount(subcell_dim);
357  if (subcell_ord < componentSubcellCount * 2) // subcell belongs to one of the two component topologies
358  {
359  ordinal_type subcell_ord_comp = subcell_ord % componentSubcellCount; // subcell ordinal in the component topology
360  ordinal_type compOrdinal = subcell_ord / componentSubcellCount; // which component topology? 0 or 1.
361  ordinal_type mappedNodeInsideComponentTopology = tensorComponentTopo->getNodeMap(subcell_dim, subcell_ord_comp, subcell_node_ord);
362  return mappedNodeInsideComponentTopology + compOrdinal * tensorComponentTopo->getNodeCount();
363  }
364  else
365  {
366  // otherwise, the subcell is a tensor product of a component's (subcell_dim-1)-dimensional subcell with the line topology.
367  ordinal_type subcell_ord_comp = subcell_ord - componentSubcellCount * 2;
368  ordinal_type subcell_dim_comp = subcell_dim - 1;
369  CellTopoPtr subcellTensorComponent = tensorComponentTopo->getSubcell(subcell_dim_comp, subcell_ord_comp);
370  // which of the two copies of the subcell tensor component owns the node subcell_node_ord?
371  ordinal_type scCompOrdinal = subcell_node_ord / subcellTensorComponent->getNodeCount(); // 0 or 1
372  // what's the node ordinal inside the subcell component?
373  ordinal_type scCompNodeOrdinal = subcell_node_ord % subcellTensorComponent->getNodeCount();
374  ordinal_type mappedNodeInsideComponentTopology = tensorComponentTopo->getNodeMap(subcell_dim_comp, subcell_ord_comp, scCompNodeOrdinal);
375  return mappedNodeInsideComponentTopology + scCompOrdinal * tensorComponentTopo->getNodeCount();
376  }
377  }
378  }
379 
381  ordinal_type getNodePermutationCount() const;
382 
387  ordinal_type getNodePermutation( const ordinal_type permutation_ord ,
388  const ordinal_type node_ord ) const;
389 
394  ordinal_type getNodePermutationInverse( const ordinal_type permutation_ord ,
395  const ordinal_type node_ord ) const;
396 
399  CellTopoPtr getSide( ordinal_type sideOrdinal ) const;
400 
410  CellTopoPtr getSubcell( ordinal_type scdim, ordinal_type scord ) const
411  {
412  if (tensorialDegree_==0)
413  {
414  return cellTopology(shardsBaseTopology_.getCellTopologyData(scdim, scord), 0);
415  }
416  else
417  {
418  CellTopoPtr tensorComponentTopo = getTensorialComponent();
419  ordinal_type componentSubcellCount = tensorComponentTopo->getSubcellCount(scdim);
420  if (scord < componentSubcellCount * 2)
421  {
422  scord = scord % componentSubcellCount;
423  return tensorComponentTopo->getSubcell(scdim, scord);
424  }
425  // otherwise, the subcell is a tensor product of one of the components (scdim-1)-dimensional subcells with the line topology.
426  scord = scord - componentSubcellCount * 2;
427  scdim = scdim - 1;
428  CellTopoPtr subcellTensorComponent = tensorComponentTopo->getSubcell(scdim, scord);
429  return cellTopology(subcellTensorComponent->getBaseTopology(), subcellTensorComponent->getTensorialDegree() + 1);
430  }
431  }
432 
437  static ordinal_type getSubcellOrdinalMap(CellTopoPtr cellTopo, ordinal_type subcdim, ordinal_type subcord, ordinal_type subsubcdim, ordinal_type subsubcord)
438  {
439  // static map<> …
440  // TODO: implement this method
441 
442  // maps from a subcell's ordering of its subcells (the sub-subcells) to the cell topology's ordering of those subcells.
443  typedef ordinal_type SubcellOrdinal;
444  typedef ordinal_type SubcellDimension;
445  typedef ordinal_type SubSubcellOrdinal;
446  typedef ordinal_type SubSubcellDimension;
447  typedef ordinal_type SubSubcellOrdinalInCellTopo;
448  typedef std::pair< SubcellDimension, SubcellOrdinal > SubcellIdentifier; // dim, ord in cellTopo
449  typedef std::pair< SubSubcellDimension, SubSubcellOrdinal > SubSubcellIdentifier; // dim, ord in subcell
450  typedef std::map< SubcellIdentifier, std::map< SubSubcellIdentifier, SubSubcellOrdinalInCellTopo > > OrdinalMap;
451  static std::map< CellTopologyKey, OrdinalMap > ordinalMaps;
452 
453  if (subsubcdim==subcdim)
454  {
455  if (subsubcord==0) // i.e. the "subsubcell" is really just the subcell
456  {
457  return subcord;
458  }
459  else
460  {
461  std::cout << "request for subsubcell of the same dimension as subcell, but with subsubcord > 0.\n";
462  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "request for subsubcell of the same dimension as subcell, but with subsubcord > 0.");
463  }
464  }
465 
466  if (subcdim==cellTopo->getDimension())
467  {
468  if (subcord==0) // i.e. the subcell is the cell itself
469  {
470  return subsubcord;
471  }
472  else
473  {
474  std::cout << "request for subcell of the same dimension as cell, but with subsubcord > 0.\n";
475  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "request for subcell of the same dimension as cell, but with subsubcord > 0.");
476  }
477  }
478 
479  CellTopologyKey key = cellTopo->getKey();
480  if (ordinalMaps.find(key) == ordinalMaps.end())
481  {
482  // then we construct the map for this cellTopo
483  OrdinalMap ordinalMap;
484  ordinal_type sideDim = cellTopo->getDimension() - 1;
485  typedef ordinal_type NodeOrdinal;
486  std::map< std::set<NodeOrdinal>, SubcellIdentifier > subcellMap; // given set of nodes in cellTopo, what subcell is it?)
487 
488  for (ordinal_type d=1; d<=sideDim; d++) // only things of dimension >= 1 will have subcells
489  {
490  ordinal_type subcellCount = cellTopo->getSubcellCount(d);
491  for (ordinal_type subcellOrdinal=0; subcellOrdinal<subcellCount; subcellOrdinal++)
492  {
493  std::set<NodeOrdinal> nodes;
494  ordinal_type nodeCount = cellTopo->getNodeCount(d, subcellOrdinal);
495  for (NodeOrdinal subcNode=0; subcNode<nodeCount; subcNode++)
496  {
497  nodes.insert(cellTopo->getNodeMap(d, subcellOrdinal, subcNode));
498  }
499  SubcellIdentifier subcell = std::make_pair(d, subcellOrdinal);
500  subcellMap[nodes] = subcell;
501 
502  CellTopoPtr subcellTopo = cellTopo->getSubcell(d, subcellOrdinal);
503  // now, go over all the subsubcells, and look them up...
504  for (ordinal_type subsubcellDim=0; subsubcellDim<d; subsubcellDim++)
505  {
506  ordinal_type subsubcellCount = subcellTopo->getSubcellCount(subsubcellDim);
507  for (ordinal_type subsubcellOrdinal=0; subsubcellOrdinal<subsubcellCount; subsubcellOrdinal++)
508  {
509  SubSubcellIdentifier subsubcell = std::make_pair(subsubcellDim,subsubcellOrdinal);
510  if (subsubcellDim==0) // treat vertices separately
511  {
512  ordinalMap[subcell][subsubcell] = cellTopo->getNodeMap(subcell.first, subcell.second, subsubcellOrdinal);
513  continue;
514  }
515  ordinal_type nodeCount_inner = subcellTopo->getNodeCount(subsubcellDim, subsubcellOrdinal);
516  std::set<NodeOrdinal> subcellNodes; // NodeOrdinals index into cellTopo, though!
517  for (NodeOrdinal subsubcNode=0; subsubcNode<nodeCount_inner; subsubcNode++)
518  {
519  NodeOrdinal subcNode = subcellTopo->getNodeMap(subsubcellDim, subsubcellOrdinal, subsubcNode);
520  NodeOrdinal node = cellTopo->getNodeMap(d, subcellOrdinal, subcNode);
521  subcellNodes.insert(node);
522  }
523 
524  SubcellIdentifier subsubcellInCellTopo = subcellMap[subcellNodes];
525  ordinalMap[ subcell ][ subsubcell ] = subsubcellInCellTopo.second;
526  // cout << "ordinalMap( (" << subcell.first << "," << subcell.second << "), (" << subsubcell.first << "," << subsubcell.second << ") ) ";
527  // cout << " ---> " << subsubcellInCellTopo.second << endl;
528  }
529  }
530  }
531  }
532  ordinalMaps[key] = ordinalMap;
533  }
534  SubcellIdentifier subcell = std::make_pair(subcdim, subcord);
535  SubSubcellIdentifier subsubcell = std::make_pair(subsubcdim, subsubcord);
536  if (ordinalMaps[key][subcell].find(subsubcell) != ordinalMaps[key][subcell].end())
537  {
538  return ordinalMaps[key][subcell][subsubcell];
539  }
540  else
541  {
542  std::cout << "For topology " << cellTopo->getName() << " and subcell " << subcord << " of dim " << subcdim;
543  std::cout << ", subsubcell " << subsubcord << " of dim " << subsubcdim << " not found.\n";
544  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "subsubcell not found");
545  return -1; // NOT FOUND
546  }
547  }
548 
552  CellTopoPtr getTensorialComponent() const
553  {
554  if (tensorialDegree_ > 0)
555  {
556  return cellTopology(shardsBaseTopology_, tensorialDegree_ - 1);
557  }
558  else
559  {
560  return Teuchos::null;
561  }
562  }
563 
567  ordinal_type getTensorialComponentSideOrdinal(ordinal_type extrusionNodeOrdinal)
568  {
569  // our ordering places the "copies" of the tensorial component first, so these have side ordinal 0 or 1.
570  return extrusionNodeOrdinal;
571  }
572 
576  bool sideIsExtrudedInFinalDimension( ordinal_type sideOrdinal ) const
577  {
578  int sideCount = getSideCount();
579  if (tensorialDegree_ == 0) return false;
580 
581  return (sideOrdinal > 1) && (sideOrdinal < sideCount);
582  }
583 
588  static CellTopoPtr cellTopology(const shards::CellTopology &shardsCellTopo, ordinal_type tensorialDegree = 0)
589  {
590  ordinal_type shardsKey = static_cast<ordinal_type>(shardsCellTopo.getBaseKey());
591  std::pair<ordinal_type,ordinal_type> key = std::make_pair(shardsKey, tensorialDegree);
592 
593  static std::map< CellTopologyKey, CellTopoPtr > tensorizedShardsTopologies; // (shards key, n) --> our CellTopoPtr for that cellTopo's nth-order tensor product with a line topology. I.e. (shard::CellTopology::Line<2>::key, 2) --> a tensor-product hexahedron. (This differs from the Shards hexahedron, because the enumeration of the sides of the quad in Shards goes counter-clockwise.)
594 
595  if (tensorizedShardsTopologies.find(key) == tensorizedShardsTopologies.end())
596  {
597  tensorizedShardsTopologies[key] = Teuchos::rcp( new CellTopology(shardsCellTopo, tensorialDegree));
598  }
599  return tensorizedShardsTopologies[key];
600  }
601 
602  static CellTopoPtr point()
603  {
604  return cellTopology(shards::getCellTopologyData<shards::Node >());
605  }
606 
607  static CellTopoPtr line()
608  {
609  return cellTopology(shards::getCellTopologyData<shards::Line<> >());
610  }
611 
612  static CellTopoPtr quad()
613  {
614  return cellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >());
615  }
616 
617  static CellTopoPtr hexahedron()
618  {
619  return cellTopology(shards::getCellTopologyData<shards::Hexahedron<> >());
620  }
621 
622  static CellTopoPtr triangle()
623  {
624  return cellTopology(shards::getCellTopologyData<shards::Triangle<> >());
625  }
626 
627  static CellTopoPtr tetrahedron()
628  {
629  return cellTopology(shards::getCellTopologyData<shards::Tetrahedron<> >());
630  }
631 
632  static CellTopoPtr wedge()
633  {
634  return cellTopology(shards::getCellTopologyData<shards::Wedge<> >());
635  }
636  };
637 }
638 
639 #endif /* Intrepid2_CellTopology_h */
ordinal_type getFaceCount() const
Face (dimension 2) subcell count of this cell topology.
std::pair< ordinal_type, ordinal_type > getKey() const
Key that&#39;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&#39;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&#39;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&#39;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&#39;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.