Intrepid2
Intrepid2_OrientationDef.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), or
38 // Mauro Perego (mperego@sandia.gov)
39 //
40 // ************************************************************************
41 // @HEADER
42 
43 
48 #ifndef __INTREPID2_ORIENTATION_DEF_HPP__
49 #define __INTREPID2_ORIENTATION_DEF_HPP__
50 
51 // disable clang warnings
52 #if defined (__clang__) && !defined (__INTEL_COMPILER)
53 #pragma clang system_header
54 #endif
55 
56 namespace Intrepid2 {
57 
58  // ------------------------------------------------------------------------------------
59  // Orientation
60  //
61  //
62  template<typename cellVertViewType>
63  inline
64  void
65  Orientation::getCellVertexMap(typename cellVertViewType::non_const_value_type *subCellVerts,
66  ordinal_type &numVerts,
67  const shards::CellTopology cellTopo,
68  const cellVertViewType cellVertices,
69  const ordinal_type subCellDim,
70  const ordinal_type subCellOrd) {
71  static_assert(Kokkos::Impl::MemorySpaceAccess
72  <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
73  "host space cannot access cellVertViewType");
74  switch (subCellDim) {
75  case 0: {
76  numVerts = 1;
77  subCellVerts[0] = cellVertices(subCellOrd);
78  break;
79  }
80  default: {
81  numVerts = cellTopo.getVertexCount(subCellDim, subCellOrd);
82  for (ordinal_type i=0;i<numVerts;++i)
83  subCellVerts[i] = cellVertices(cellTopo.getNodeMap(subCellDim, subCellOrd, i));
84  break;
85  }
86  }
87  }
88 
89  template<typename subCellVertType>
90  inline
91  ordinal_type
92  Orientation::getOrientation(const subCellVertType subCellVerts[],
93  const ordinal_type numVerts) {
94  ordinal_type ort = 0;
95  switch (numVerts) {
96  case 2: {// edge
97 #ifdef HAVE_INTREPID2_DEBUG
98  INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ),
99  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
100  "Invalid subCellVerts, same vertex ids are repeated");
101 #endif
102  ort = (subCellVerts[0] > subCellVerts[1]);
103  break;
104  }
105  case 3: {
106 #ifdef HAVE_INTREPID2_DEBUG
107  INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
108  subCellVerts[0] == subCellVerts[2] ||
109  subCellVerts[1] == subCellVerts[2] ),
110  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
111  "Invalid subCellVerts, same vertex ids are repeated");
112 #endif
113  ordinal_type rotation = 0; // find smallest vertex id
114  for (ordinal_type i=1;i<3;++i)
115  rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
116 
117  const ordinal_type axes[][2] = { {1,2}, {2,0}, {0,1} };
118  const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
119 
120  ort = flip*3 + rotation;
121  break;
122  }
123  case 4: {
124 #ifdef HAVE_INTREPID2_DEBUG
125  INTREPID2_TEST_FOR_ABORT( ( subCellVerts[0] == subCellVerts[1] ||
126  subCellVerts[0] == subCellVerts[2] ||
127  subCellVerts[0] == subCellVerts[3] ||
128  subCellVerts[1] == subCellVerts[2] ||
129  subCellVerts[1] == subCellVerts[3] ||
130  subCellVerts[2] == subCellVerts[3] ),
131  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
132  "Invalid subCellVerts, same vertex ids are repeated");
133 #endif
134  ordinal_type rotation = 0; // find smallest vertex id
135  for (ordinal_type i=1;i<4;++i)
136  rotation = ( subCellVerts[i] < subCellVerts[rotation] ? i : rotation );
137 
138  const ordinal_type axes[][2] = { {1,3}, {2,0}, {3,1}, {0,2} };
139  const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
140 
141  ort = flip*4 + rotation;
142  break;
143  }
144  default: {
145  INTREPID2_TEST_FOR_ABORT( true,
146  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
147  "Invalid numVerts (2 (edge),3 (triangle) and 4 (quadrilateral) are allowed)");
148  break;
149  }
150  }
151  return ort;
152  }
153 
154  template<typename cellVertViewType>
155  inline
156  Orientation
157  Orientation::getOrientation(const shards::CellTopology cellTopo,
158  const cellVertViewType cellVertices,
159  bool isSide) {
160  static_assert(Kokkos::Impl::MemorySpaceAccess
161  <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
162  "host space cannot access cellVertViewType");
163 
164  Orientation ort;
165  auto dim = cellTopo.getDimension();
166  const ordinal_type nedge = (isSide && dim==1) ? 1 : cellTopo.getEdgeCount();
167 
168  if (nedge > 0) {
169  typename cellVertViewType::non_const_value_type vertsSubCell[2];
170  ordinal_type orts[12], nvertSubCell;
171  for (ordinal_type i=0;i<nedge;++i) {
172  Orientation::getCellVertexMap(vertsSubCell,
173  nvertSubCell,
174  cellTopo,
175  cellVertices,
176  1, i);
177  orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
178  }
179  ort.setEdgeOrientation(nedge, orts);
180  }
181  const ordinal_type nface = (isSide && dim==2) ? 1 : cellTopo.getFaceCount();
182  if (nface > 0) {
183  typename cellVertViewType::non_const_value_type vertsSubCell[4];
184  ordinal_type orts[6], nvertSubCell;
185  for (ordinal_type i=0;i<nface;++i) {
186  Orientation::getCellVertexMap(vertsSubCell,
187  nvertSubCell,
188  cellTopo,
189  cellVertices,
190  2, i);
191  orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
192  }
193  ort.setFaceOrientation(nface, orts);
194  }
195  return ort;
196  }
197 
198  inline
199  ordinal_type
200  Orientation::getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd,
201  const ordinal_type subcellOrd,
202  const shards::CellTopology cellTopo) {
203  ordinal_type r_val = -1;
204 
205  const auto cellBaseKey = cellTopo.getBaseKey();
206  if (cellBaseKey == shards::Hexahedron<>::key) {
207  INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6) &&
208  !(subsubcellOrd < 4),
209  std::logic_error,
210  "subcell and subsubcell information are not correct" );
211  const int quad_to_hex_edges[6][4] = { { 0, 9, 4, 8 },
212  { 1,10, 5, 9 },
213  { 2,11, 6,10 },
214  { 8, 7,11, 3 },
215  { 3, 2, 1, 0 },
216  { 4, 5, 6, 7 } };
217  r_val = quad_to_hex_edges[subcellOrd][subsubcellOrd];
218  } else if (cellBaseKey == shards::Tetrahedron<>::key) {
219  INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4) &&
220  !(subsubcellOrd < 3),
221  std::logic_error,
222  "subcell and subsubcell information are not correct" );
223  const ordinal_type tri_to_tet_edges[4][3] = { { 0, 4, 3 },
224  { 1, 5, 4 },
225  { 3, 5, 2 },
226  { 2, 1, 0 } };
227  r_val = tri_to_tet_edges[subcellOrd][subsubcellOrd];
228  } else {
229  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
230  "cellTopo is not supported: try TET and HEX" );
231  }
232  return r_val;
233  }
234 
235  KOKKOS_INLINE_FUNCTION
237  : _edgeOrt(0), _faceOrt(0) {}
238 
239  KOKKOS_INLINE_FUNCTION
240  bool
242  return (_edgeOrt == 0 && _faceOrt == 0);
243  }
244 
245  KOKKOS_INLINE_FUNCTION
246  void
247  Orientation::setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[]) {
248 #ifdef HAVE_INTREPID2_DEBUG
249  INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
250  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
251  "Invalid numEdge");
252 #endif
253  _edgeOrt = 0;
254  for (ordinal_type i=0;i<numEdge;++i)
255  _edgeOrt |= (edgeOrt[i] & 1) << i;
256  }
257 
258  KOKKOS_INLINE_FUNCTION
259  void
260  Orientation::getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const {
261 #ifdef HAVE_INTREPID2_DEBUG
262  INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
263  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
264  "Invalid numEdge");
265 #endif
266  for (ordinal_type i=0;i<numEdge;++i)
267  edgeOrt[i] = (_edgeOrt & (1 << i)) >> i;
268  }
269 
270  KOKKOS_INLINE_FUNCTION
271  void
272  Orientation::setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[]) {
273 #ifdef HAVE_INTREPID2_DEBUG
274  INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
275  ">>> ERROR (Intrepid::Orientation::setFaceOrientation): "
276  "Invalid numFace");
277 #endif
278  _faceOrt = 0;
279  for (ordinal_type i=0;i<numFace;++i) {
280  const ordinal_type s = i*3;
281  _faceOrt |= (faceOrt[i] & 7) << s;
282  }
283  }
284 
285  KOKKOS_INLINE_FUNCTION
286  void
287  Orientation::getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const {
288 #ifdef HAVE_INTREPID2_DEBUG
289  INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
290  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): "
291  "Invalid numFace");
292 #endif
293  for (ordinal_type i=0;i<numFace;++i) {
294  const ordinal_type s = i*3;
295  faceOrt[i] = (_faceOrt & (7 << s)) >> s;
296  }
297  }
298 
299  inline std::string Orientation::to_string() const {
300  return "Orientation{ face: " + std::to_string(_faceOrt) + "; edge: " + std::to_string(_edgeOrt) + " }";
301  }
302 }
303 
304 #endif
KOKKOS_INLINE_FUNCTION bool isAlignedToReference() const
KOKKOS_INLINE_FUNCTION void setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[])
Orientation encoding and decoding.
KOKKOS_INLINE_FUNCTION void getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const
KOKKOS_INLINE_FUNCTION void setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[])
static ordinal_type getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd, const ordinal_type subcellOrd, const shards::CellTopology cellTopo)
KOKKOS_INLINE_FUNCTION void getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const
KOKKOS_INLINE_FUNCTION Orientation()