15 #ifndef Intrepid2_TensorTopologyMap_h
16 #define Intrepid2_TensorTopologyMap_h
20 #include "Shards_CellTopology.hpp"
38 shards::CellTopology cellTopo1_;
39 shards::CellTopology cellTopo2_;
40 shards::CellTopology compositeCellTopo_;
42 using Subcell = std::pair<unsigned,unsigned>;
43 using SubcellPair = std::pair<Subcell,Subcell>;
44 std::map<SubcellPair,Subcell> subcellMap_;
60 TensorTopologyMap(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo,
61 std::vector< std::pair<unsigned,unsigned> > nodePairs = std::vector< std::pair<unsigned,unsigned> >())
63 cellTopo1_(cellTopo1),
64 cellTopo2_(cellTopo2),
65 compositeCellTopo_(compositeCellTopo)
67 if (nodePairs.size() == 0)
72 auto spaceDim1 = cellTopo1.getDimension();
73 auto spaceDim2 = cellTopo2.getDimension();
74 auto spaceDim = compositeCellTopo.getDimension();
75 INTREPID2_TEST_FOR_EXCEPTION(spaceDim1 + spaceDim2 != spaceDim, std::invalid_argument,
"incompatible spatial dimensions");
76 std::map<std::pair<unsigned,unsigned>,
unsigned> compositeNodeOrdinalMap;
77 for (
unsigned compositeNodeOrdinal=0; compositeNodeOrdinal<nodePairs.size(); compositeNodeOrdinal++)
79 compositeNodeOrdinalMap[nodePairs[compositeNodeOrdinal]] = compositeNodeOrdinal;
81 for (
unsigned d1=0; d1<=spaceDim1; d1++)
83 unsigned subcellCount1 = cellTopo1.getSubcellCount(d1);
84 for (
unsigned subcellOrdinal1=0; subcellOrdinal1<subcellCount1; subcellOrdinal1++)
86 Subcell subcell1 = {d1, subcellOrdinal1};
87 std::set<unsigned> subcell1Nodes;
88 unsigned nodeCount1 = cellTopo1_.getNodeCount(d1, subcellOrdinal1);
92 subcell1Nodes.insert(subcellOrdinal1);
96 for (
unsigned nodeOrdinal1=0; nodeOrdinal1<nodeCount1; nodeOrdinal1++)
98 subcell1Nodes.insert(cellTopo1_.getNodeMap(d1, subcellOrdinal1, nodeOrdinal1));
101 for (
unsigned d2=0; d2<=spaceDim2; d2++)
103 unsigned subcellCount2 = cellTopo2.getSubcellCount(d2);
104 for (
unsigned subcellOrdinal2=0; subcellOrdinal2<subcellCount2; subcellOrdinal2++)
106 Subcell subcell2 = {d2, subcellOrdinal2};
107 std::set<unsigned> subcell2Nodes;
108 unsigned nodeCount2 = cellTopo2_.getNodeCount(d2, subcellOrdinal2);
112 subcell2Nodes.insert(subcellOrdinal2);
116 for (
unsigned nodeOrdinal2=0; nodeOrdinal2<nodeCount2; nodeOrdinal2++)
118 subcell2Nodes.insert(cellTopo2_.getNodeMap(d2, subcellOrdinal2, nodeOrdinal2));
122 std::set<unsigned> compositeNodes;
123 for (
auto subcellNode1 : subcell1Nodes)
125 for (
auto subcellNode2 : subcell2Nodes)
127 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeOrdinalMap.find({subcellNode1,subcellNode2}) == compositeNodeOrdinalMap.end(),
128 std::invalid_argument,
"Node combination not found in map");
129 compositeNodes.insert(compositeNodeOrdinalMap[{subcellNode1,subcellNode2}]);
134 unsigned compositeSubcellDim = d1 + d2;
135 unsigned compositeSubcellCount = compositeCellTopo.getSubcellCount(compositeSubcellDim);
136 bool compositeSubcellFound =
false;
137 for (
unsigned compositeSubcellOrdinal=0; compositeSubcellOrdinal<compositeSubcellCount; compositeSubcellOrdinal++)
139 unsigned compositeSubcellNodeCount = (compositeSubcellDim > 0) ? compositeCellTopo.getNodeCount(compositeSubcellDim, compositeSubcellOrdinal)
141 if (compositeSubcellNodeCount != compositeNodes.size())
continue;
143 for (
unsigned compositeSubcellNode=0; compositeSubcellNode<compositeSubcellNodeCount; compositeSubcellNode++)
145 unsigned nodeInCell = compositeCellTopo.getNodeMap(compositeSubcellDim, compositeSubcellOrdinal, compositeSubcellNode);
146 if (compositeNodes.find(nodeInCell) == compositeNodes.end())
154 compositeSubcellFound =
true;
155 subcellMap_[{subcell1,subcell2}] = {compositeSubcellDim, compositeSubcellOrdinal};
159 INTREPID2_TEST_FOR_EXCEPTION(!compositeSubcellFound, std::invalid_argument,
"Composite subcell not found");
165 TensorTopologyMap(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2)
167 TensorTopologyMap(cellTopo1, cellTopo2, compositeCellTopology(cellTopo1,cellTopo2)) {}
182 Subcell subcell1 = {subcell1Dim, subcell1Ordinal};
183 Subcell subcell2 = {subcell2Dim, subcell2Ordinal};
184 auto entry = subcellMap_.find({subcell1,subcell2});
185 INTREPID2_TEST_FOR_EXCEPTION(entry == subcellMap_.end(), std::invalid_argument,
"entry not found");
186 auto subcell = entry->second;
187 return subcell.second;
204 std::vector< std::vector<int> > nodes(cellTopo.getVertexCount());
205 auto key = cellTopo.getKey();
208 case shards::Node::key:
211 case shards::Line<2>::key:
215 case shards::Triangle<3>::key:
220 case shards::Quadrilateral<4>::key:
226 case shards::Hexahedron<8>::key:
236 case shards::Wedge<6>::key:
245 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
"Unsupported CellTopology");
263 static std::vector< std::pair<unsigned,unsigned> >
defaultNodePairs(shards::CellTopology cellTopo1, shards::CellTopology cellTopo2, shards::CellTopology compositeCellTopo)
265 unsigned compositeNodeCount = compositeCellTopo.getVertexCount();
266 unsigned nodeCount1 = cellTopo1.getVertexCount();
267 unsigned nodeCount2 = cellTopo2.getVertexCount();
268 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeCount != nodeCount1 * nodeCount2, std::invalid_argument,
"Incompatible topologies");
269 std::vector< std::pair<unsigned,unsigned> > nodePairs(compositeNodeCount);
270 auto nodes1 = referenceCellGeometry(cellTopo1);
271 auto nodes2 = referenceCellGeometry(cellTopo2);
272 auto compositeNodes = referenceCellGeometry(compositeCellTopo);
273 std::map< std::vector<int>,
unsigned > compositeNodeMap;
274 for (
unsigned compositeNodeOrdinal=0; compositeNodeOrdinal<compositeNodeCount; compositeNodeOrdinal++)
276 compositeNodeMap[compositeNodes[compositeNodeOrdinal]] = compositeNodeOrdinal;
278 for (
unsigned nodeOrdinal1=0; nodeOrdinal1<nodeCount1; nodeOrdinal1++)
280 std::vector<int> node1 = nodes1[nodeOrdinal1];
281 for (
unsigned nodeOrdinal2=0; nodeOrdinal2<nodeCount2; nodeOrdinal2++)
283 std::vector<int> node2 = nodes2[nodeOrdinal2];
284 std::vector<int> compositeNode(node1);
285 compositeNode.insert(compositeNode.end(), node2.begin(), node2.end());
286 auto compositeNodeMapEntry = compositeNodeMap.find(compositeNode);
287 INTREPID2_TEST_FOR_EXCEPTION(compositeNodeMapEntry == compositeNodeMap.end(), std::invalid_argument,
"composite node not found in map");
288 nodePairs[compositeNodeMapEntry->second] = {nodeOrdinal1,nodeOrdinal2};
303 if (cellTopo1.getBaseKey() == shards::Node::key)
307 else if (cellTopo2.getBaseKey() == shards::Node::key)
313 auto key1 = cellTopo1.getBaseKey();
314 auto key2 = cellTopo2.getBaseKey();
317 case shards::Line<2>::key:
320 case shards::Line<2>::key:
321 return shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<> >() );
322 case shards::Triangle<3>::key:
324 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"line x triangle is not supported at present. Wedge is triangle x line.");
325 case shards::Quadrilateral<4>::key:
326 return shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >() );
328 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
330 case shards::Triangle<3>::key:
333 case shards::Line<2>::key:
334 return shards::CellTopology(shards::getCellTopologyData<shards::Wedge<> >() );
336 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
338 case shards::Quadrilateral<4>::key:
341 case shards::Line<2>::key:
342 return shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<> >() );
344 INTREPID2_TEST_FOR_EXCEPTION(
true,std::invalid_argument,
"Unsupported cell topology pair");
347 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.