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
57namespace Intrepid2
58{
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 */
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.