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 
96 #ifdef HAVE_INTREPID2_DEBUG
97  for(ordinal_type i=0;i<numVerts-1;++i)
98  for(ordinal_type j=i+1;j<numVerts;++j)
99  INTREPID2_TEST_FOR_ABORT( ( subCellVerts[i] == subCellVerts[j] ),
100  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
101  "Invalid subCellVerts, some vertex ids are repeated");
102 #endif
103 
104  ordinal_type rotation = 0; // find smallest vertex id
105  for (ordinal_type i=1;i<numVerts;++i)
106  rotation = (subCellVerts[i] < subCellVerts[rotation]) ? i : rotation;
107 
108  switch (numVerts) {
109  case 2: {// edge
110  ort = rotation;
111  break;
112  }
113  case 3: {
114  const ordinal_type axes[][2] = { {1,2}, {2,0}, {0,1} };
115  const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
116 
117  ort = flip*3 + rotation;
118  break;
119  }
120  case 4: {
121  const ordinal_type axes[][2] = { {1,3}, {2,0}, {3,1}, {0,2} };
122  const ordinal_type flip = (subCellVerts[axes[rotation][0]] > subCellVerts[axes[rotation][1]]);
123 
124  ort = flip*4 + rotation;
125  break;
126  }
127  default: {
128  INTREPID2_TEST_FOR_ABORT( true,
129  ">>> ERROR (Intrepid::Orientation::getOrientation): " \
130  "Invalid numVerts (2 (edge),3 (triangle) and 4 (quadrilateral) are allowed)");
131  break;
132  }
133  }
134  return ort;
135  }
136 
137  template<typename cellVertViewType>
138  inline
139  Orientation
140  Orientation::getOrientation(const shards::CellTopology cellTopo,
141  const cellVertViewType cellVertices,
142  bool isSide) {
143  static_assert(Kokkos::Impl::MemorySpaceAccess
144  <Kokkos::HostSpace,typename cellVertViewType::device_type::memory_space>::accessible,
145  "host space cannot access cellVertViewType");
146 
147  Orientation ort;
148  auto dim = cellTopo.getDimension();
149  const ordinal_type nedge = (isSide && dim==1) ? 1 : cellTopo.getEdgeCount();
150 
151  if (nedge > 0) {
152  typename cellVertViewType::non_const_value_type vertsSubCell[2];
153  ordinal_type orts[12], nvertSubCell;
154  for (ordinal_type i=0;i<nedge;++i) {
155  Orientation::getCellVertexMap(vertsSubCell,
156  nvertSubCell,
157  cellTopo,
158  cellVertices,
159  1, i);
160  orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
161  }
162  ort.setEdgeOrientation(nedge, orts);
163  }
164  const ordinal_type nface = (isSide && dim==2) ? 1 : cellTopo.getFaceCount();
165  if (nface > 0) {
166  typename cellVertViewType::non_const_value_type vertsSubCell[4];
167  ordinal_type orts[6], nvertSubCell;
168  for (ordinal_type i=0;i<nface;++i) {
169  Orientation::getCellVertexMap(vertsSubCell,
170  nvertSubCell,
171  cellTopo,
172  cellVertices,
173  2, i);
174  orts[i] = Orientation::getOrientation(vertsSubCell, nvertSubCell);
175  }
176  ort.setFaceOrientation(nface, orts);
177  }
178  return ort;
179  }
180 
181  inline
182  ordinal_type
183  Orientation::getEdgeOrdinalOfFace(const ordinal_type subsubcellOrd,
184  const ordinal_type subcellOrd,
185  const shards::CellTopology cellTopo) {
186  ordinal_type r_val = -1;
187 
188  const auto cellBaseKey = cellTopo.getBaseKey();
189  if (cellBaseKey == shards::Hexahedron<>::key) {
190  INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 6) &&
191  !(subsubcellOrd < 4),
192  std::logic_error,
193  "subcell and subsubcell information are not correct" );
194  const int quad_to_hex_edges[6][4] = { { 0, 9, 4, 8 },
195  { 1,10, 5, 9 },
196  { 2,11, 6,10 },
197  { 8, 7,11, 3 },
198  { 3, 2, 1, 0 },
199  { 4, 5, 6, 7 } };
200  r_val = quad_to_hex_edges[subcellOrd][subsubcellOrd];
201  } else if (cellBaseKey == shards::Tetrahedron<>::key) {
202  INTREPID2_TEST_FOR_EXCEPTION( !(subcellOrd < 4) &&
203  !(subsubcellOrd < 3),
204  std::logic_error,
205  "subcell and subsubcell information are not correct" );
206  const ordinal_type tri_to_tet_edges[4][3] = { { 0, 4, 3 },
207  { 1, 5, 4 },
208  { 3, 5, 2 },
209  { 2, 1, 0 } };
210  r_val = tri_to_tet_edges[subcellOrd][subsubcellOrd];
211  } else {
212  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
213  "cellTopo is not supported: try TET and HEX" );
214  }
215  return r_val;
216  }
217 
218  KOKKOS_INLINE_FUNCTION
220  : _edgeOrt(0), _faceOrt(0) {}
221 
222  KOKKOS_INLINE_FUNCTION
223  bool
225  return (_edgeOrt == 0 && _faceOrt == 0);
226  }
227 
228  KOKKOS_INLINE_FUNCTION
229  void
230  Orientation::setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[]) {
231 #ifdef HAVE_INTREPID2_DEBUG
232  INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
233  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
234  "Invalid numEdge");
235 #endif
236  _edgeOrt = 0;
237  for (ordinal_type i=0;i<numEdge;++i)
238  _edgeOrt |= (edgeOrt[i] & 1) << i;
239  }
240 
241  KOKKOS_INLINE_FUNCTION
242  void
243  Orientation::getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const {
244 #ifdef HAVE_INTREPID2_DEBUG
245  INTREPID2_TEST_FOR_ABORT( !((numEdge == 1) || (3 <= numEdge && numEdge <= 12 )),
246  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): " \
247  "Invalid numEdge");
248 #endif
249  for (ordinal_type i=0;i<numEdge;++i)
250  edgeOrt[i] = (_edgeOrt & (1 << i)) >> i;
251  }
252 
253  KOKKOS_INLINE_FUNCTION
254  void
255  Orientation::setFaceOrientation(const ordinal_type numFace, const ordinal_type faceOrt[]) {
256 #ifdef HAVE_INTREPID2_DEBUG
257  INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
258  ">>> ERROR (Intrepid::Orientation::setFaceOrientation): "
259  "Invalid numFace");
260 #endif
261  _faceOrt = 0;
262  for (ordinal_type i=0;i<numFace;++i) {
263  const ordinal_type s = i*3;
264  _faceOrt |= (faceOrt[i] & 7) << s;
265  }
266  }
267 
268  KOKKOS_INLINE_FUNCTION
269  void
270  Orientation::getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const {
271 #ifdef HAVE_INTREPID2_DEBUG
272  INTREPID2_TEST_FOR_ABORT( !((numFace == 1) || (4 <= numFace && numFace <= 6 )),
273  ">>> ERROR (Intrepid::Orientation::setEdgeOrientation): "
274  "Invalid numFace");
275 #endif
276  for (ordinal_type i=0;i<numFace;++i) {
277  const ordinal_type s = i*3;
278  faceOrt[i] = (_faceOrt & (7 << s)) >> s;
279  }
280  }
281 
282  inline std::string Orientation::to_string() const {
283  return "Orientation{ face: " + std::to_string(_faceOrt) + "; edge: " + std::to_string(_edgeOrt) + " }";
284  }
285 }
286 
287 #endif
KOKKOS_INLINE_FUNCTION void getFaceOrientation(ordinal_type *faceOrt, const ordinal_type numFace) const
KOKKOS_INLINE_FUNCTION void setEdgeOrientation(const ordinal_type numEdge, const ordinal_type edgeOrt[])
Orientation encoding and decoding.
KOKKOS_INLINE_FUNCTION bool isAlignedToReference() 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 getEdgeOrientation(ordinal_type *edgeOrt, const ordinal_type numEdge) const
KOKKOS_INLINE_FUNCTION Orientation()