49 #ifndef Intrepid2_TensorTopologyMap_h
50 #define Intrepid2_TensorTopologyMap_h
54 #include "Shards_CellTopology.hpp"
72 shards::CellTopology cellTopo1_;
73 shards::CellTopology cellTopo2_;
74 shards::CellTopology compositeCellTopo_;
76 using Subcell = std::pair<unsigned,unsigned>;
77 using SubcellPair = std::pair<Subcell,Subcell>;
78 std::map<SubcellPair,Subcell> subcellMap_;
94 TensorTopologyMap(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo,
95 std::vector< std::pair<unsigned,unsigned> > nodePairs = std::vector< std::pair<unsigned,unsigned> >())
97 cellTopo1_(cellTopo1),
98 cellTopo2_(cellTopo2),
99 compositeCellTopo_(compositeCellTopo)
101 if (nodePairs.size() == 0)
106 auto spaceDim1 = cellTopo1.getDimension();
107 auto spaceDim2 = cellTopo2.getDimension();
108 auto spaceDim = compositeCellTopo.getDimension();
109 INTREPID2_TEST_FOR_EXCEPTION(spaceDim1 + spaceDim2 != spaceDim, std::invalid_argument,
"incompatible spatial dimensions");
110 std::map<std::pair<unsigned,unsigned>,
unsigned> compositeNodeOrdinalMap;
111 for (
unsigned compositeNodeOrdinal=0; compositeNodeOrdinal<nodePairs.size(); compositeNodeOrdinal++)
113 compositeNodeOrdinalMap[nodePairs[compositeNodeOrdinal]] = compositeNodeOrdinal;
115 for (
unsigned d1=0; d1<=spaceDim1; d1++)
117 unsigned subcellCount1 = cellTopo1.getSubcellCount(d1);
118 for (
unsigned subcellOrdinal1=0; subcellOrdinal1<subcellCount1; subcellOrdinal1++)
120 Subcell subcell1 = {d1, subcellOrdinal1};
121 std::set<unsigned> subcell1Nodes;
122 unsigned nodeCount1 = cellTopo1_.getNodeCount(d1, subcellOrdinal1);
126 subcell1Nodes.insert(subcellOrdinal1);
130 for (
unsigned nodeOrdinal1=0; nodeOrdinal1<nodeCount1; nodeOrdinal1++)
132 subcell1Nodes.insert(cellTopo1_.getNodeMap(d1, subcellOrdinal1, nodeOrdinal1));
135 for (
unsigned d2=0; d2<=spaceDim2; d2++)
137 unsigned subcellCount2 = cellTopo2.getSubcellCount(d2);
138 for (
unsigned subcellOrdinal2=0; subcellOrdinal2<subcellCount2; subcellOrdinal2++)
140 Subcell subcell2 = {d2, subcellOrdinal2};
141 std::set<unsigned> subcell2Nodes;
142 unsigned nodeCount2 = cellTopo2_.getNodeCount(d2, subcellOrdinal2);
146 subcell2Nodes.insert(subcellOrdinal2);
150 for (
unsigned nodeOrdinal2=0; nodeOrdinal2<nodeCount2; nodeOrdinal2++)
152 subcell2Nodes.insert(cellTopo2_.getNodeMap(d2, subcellOrdinal2, nodeOrdinal2));
156 std::set<unsigned> compositeNodes;
157 for (
auto subcellNode1 : subcell1Nodes)
159 for (
auto subcellNode2 : subcell2Nodes)
161 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeOrdinalMap.find({subcellNode1,subcellNode2}) == compositeNodeOrdinalMap.end(),
162 std::invalid_argument,
"Node combination not found in map");
163 compositeNodes.insert(compositeNodeOrdinalMap[{subcellNode1,subcellNode2}]);
168 unsigned compositeSubcellDim = d1 + d2;
169 unsigned compositeSubcellCount = compositeCellTopo.getSubcellCount(compositeSubcellDim);
170 bool compositeSubcellFound =
false;
171 for (
unsigned compositeSubcellOrdinal=0; compositeSubcellOrdinal<compositeSubcellCount; compositeSubcellOrdinal++)
173 unsigned compositeSubcellNodeCount = (compositeSubcellDim > 0) ? compositeCellTopo.getNodeCount(compositeSubcellDim, compositeSubcellOrdinal)
175 if (compositeSubcellNodeCount != compositeNodes.size())
continue;
177 for (
unsigned compositeSubcellNode=0; compositeSubcellNode<compositeSubcellNodeCount; compositeSubcellNode++)
179 unsigned nodeInCell = compositeCellTopo.getNodeMap(compositeSubcellDim, compositeSubcellOrdinal, compositeSubcellNode);
180 if (compositeNodes.find(nodeInCell) == compositeNodes.end())
188 compositeSubcellFound =
true;
189 subcellMap_[{subcell1,subcell2}] = {compositeSubcellDim, compositeSubcellOrdinal};
193 INTREPID2_TEST_FOR_EXCEPTION(!compositeSubcellFound, std::invalid_argument,
"Composite subcell not found");
199 TensorTopologyMap(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2)
201 TensorTopologyMap(cellTopo1, cellTopo2, compositeCellTopology(cellTopo1,cellTopo2)) {}
216 Subcell subcell1 = {subcell1Dim, subcell1Ordinal};
217 Subcell subcell2 = {subcell2Dim, subcell2Ordinal};
218 auto entry = subcellMap_.find({subcell1,subcell2});
219 INTREPID2_TEST_FOR_EXCEPTION(entry == subcellMap_.end(), std::invalid_argument,
"entry not found");
220 auto subcell = entry->second;
221 return subcell.second;
238 std::vector< std::vector<int> > nodes(cellTopo.getVertexCount());
239 auto key = cellTopo.getKey();
242 case shards::Node::key:
245 case shards::Line<2>::key:
249 case shards::Triangle<3>::key:
254 case shards::Quadrilateral<4>::key:
260 case shards::Hexahedron<8>::key:
270 case shards::Wedge<6>::key:
279 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported CellTopology");
297 static std::vector< std::pair<unsigned,unsigned> >
defaultNodePairs(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo)
299 unsigned compositeNodeCount = compositeCellTopo.getVertexCount();
300 unsigned nodeCount1 = cellTopo1.getVertexCount();
301 unsigned nodeCount2 = cellTopo2.getVertexCount();
302 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeCount != nodeCount1 * nodeCount2, std::invalid_argument,
"Incompatible topologies");
303 std::vector< std::pair<unsigned,unsigned> > nodePairs(compositeNodeCount);
304 auto nodes1 = referenceCellGeometry(cellTopo1);
305 auto nodes2 = referenceCellGeometry(cellTopo2);
306 auto compositeNodes = referenceCellGeometry(compositeCellTopo);
307 std::map< std::vector<int>,
unsigned > compositeNodeMap;
308 for (
unsigned compositeNodeOrdinal=0; compositeNodeOrdinal<compositeNodeCount; compositeNodeOrdinal++)
310 compositeNodeMap[compositeNodes[compositeNodeOrdinal]] = compositeNodeOrdinal;
312 for (
unsigned nodeOrdinal1=0; nodeOrdinal1<nodeCount1; nodeOrdinal1++)
314 std::vector<int> node1 = nodes1[nodeOrdinal1];
315 for (
unsigned nodeOrdinal2=0; nodeOrdinal2<nodeCount2; nodeOrdinal2++)
317 std::vector<int> node2 = nodes2[nodeOrdinal2];
318 std::vector<int> compositeNode(node1);
319 compositeNode.insert(compositeNode.end(), node2.begin(), node2.end());
320 auto compositeNodeMapEntry = compositeNodeMap.find(compositeNode);
321 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeMapEntry == compositeNodeMap.end(), std::invalid_argument,
"composite node not found in map");
322 nodePairs[compositeNodeMapEntry->second] = {nodeOrdinal1,nodeOrdinal2};
337 if (cellTopo1.getBaseKey() == shards::Node::key)
341 else if (cellTopo2.getBaseKey() == shards::Node::key)
347 auto key1 = cellTopo1.getBaseKey();
348 auto key2 = cellTopo2.getBaseKey();
351 case shards::Line<2>::key:
354 case shards::Line<2>::key:
355 return shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >() );
356 case shards::Triangle<3>::key:
358 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"line x triangle is not supported at present. Wedge is triangle x line.");
359 case shards::Quadrilateral<4>::key:
360 return shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >() );
362 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
364 case shards::Triangle<3>::key:
367 case shards::Line<2>::key:
368 return shards::CellTopology(shards::getCellTopologyData<shards::Wedge<> >() );
370 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
372 case shards::Quadrilateral<4>::key:
375 case shards::Line<2>::key:
376 return shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >() );
378 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
381 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
static std::vector< std::vector< int > > referenceCellGeometry(shards::CellTopology cellTopo)
A topological representation of the vertex geometries corresponding to a cell topology.
static shards::CellTopology compositeCellTopology(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2)
The composite cell topology generated as the tensor product of the specified component cell topologie...
For two cell topologies whose tensor product is a third, this class establishes a mapping from subcel...
Header function for Intrepid2::Util class and other utility functions.
static std::vector< std::pair< unsigned, unsigned > > defaultNodePairs(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo)
Default node pairs corresponding to the provided component and composite cell topologies.
unsigned getCompositeSubcellOrdinal(unsigned subcell1Dim, unsigned subcell1Ordinal, unsigned subcell2Dim, unsigned subcell2Ordinal)
Map from component subcell ordinals to the corresponding composite subcell ordinal.
TensorTopologyMap(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo, std::vector< std::pair< unsigned, unsigned > > nodePairs=std::vector< std::pair< unsigned, unsigned > >())
Constructor.