Intrepid2
Intrepid2_CellToolsDefControlVolume.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 
49 #ifndef __INTREPID2_CELLTOOLS_DEF_CONTROL_VOLUME_HPP__
50 #define __INTREPID2_CELLTOOLS_DEF_CONTROL_VOLUME_HPP__
51 
52 // disable clang warnings
53 #if defined (__clang__) && !defined (__INTEL_COMPILER)
54 #pragma clang system_header
55 #endif
56 
57 namespace Intrepid2 {
58 
59  //============================================================================================//
60  // //
61  // Control Volume Coordinates //
62  // //
63  //============================================================================================//
64 
65  namespace FunctorCellTools {
66 
71  template<typename centerViewType, typename vertViewType>
72  KOKKOS_INLINE_FUNCTION
73  void getBaryCenter( centerViewType center,
74  const vertViewType verts) {
75  // the enumeration already assumes the ordering of vertices (circling around the polygon)
76  const ordinal_type nvert = verts.extent(0);
77  const ordinal_type dim = verts.extent(1);
78 
79  switch (dim) {
80  case 2: {
81  center(0) = 0;
82  center(1) = 0;
83  typename centerViewType::value_type area = 0;
84  for (ordinal_type i=0;i<nvert;++i) {
85  const ordinal_type j = (i + 1)%nvert;
86  const auto scale = verts(i,0)*verts(j,1) - verts(j,0)*verts(i,1);
87  center(0) += (verts(i,0) + verts(j,0))*scale;
88  center(1) += (verts(i,1) + verts(j,1))*scale;
89  area += 0.5*scale;
90  }
91  center(0) /= (6.0*area);
92  center(1) /= (6.0*area);
93  break;
94  }
95  case 3: {
96  // This method works fine for simplices, but for other 3-d shapes
97  // is not precisely accurate. Could replace with approximate integration
98  // perhaps.
99  for (ordinal_type j=0;j<dim;++j) {
100  center(j) = 0;
101  for (ordinal_type i=0;i<nvert;++i)
102  center(j) += verts(i,j);
103  center(j) /= nvert;
104  }
105  break;
106  }
107  }
108  }
109 
110  template<typename midPointViewType, typename nodeMapViewType, typename vertViewType>
111  KOKKOS_INLINE_FUNCTION
112  void getMidPoints( midPointViewType midpts,
113  const nodeMapViewType map,
114  const vertViewType verts) {
115  const ordinal_type npts = map.extent(0);
116  const ordinal_type dim = verts.extent(1);
117 
118  for (ordinal_type i=0;i<npts;++i) {
119  // first entry is the number of subcell vertices
120  const ordinal_type nvert_per_subcell = map(i, 0);
121  for (ordinal_type j=0;j<dim;++j) {
122  midpts(i,j) = 0;
123  for (ordinal_type k=1;k<=nvert_per_subcell;++k)
124  midpts(i,j) += verts(map(i,k),j);
125  midpts(i,j) /= nvert_per_subcell;
126  }
127  }
128  }
129 
130  template<typename subcvCoordViewType,
131  typename cellCoordViewType,
132  typename mapViewType>
137  subcvCoordViewType _subcvCoords;
138  const cellCoordViewType _cellCoords;
139  const mapViewType _edgeMap;
140 
141  KOKKOS_INLINE_FUNCTION
142  F_getSubcvCoords_Polygon2D( subcvCoordViewType subcvCoords_,
143  cellCoordViewType cellCoords_,
144  mapViewType edgeMap_ )
145  : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_) {}
146 
147  KOKKOS_INLINE_FUNCTION
148  void operator()(const ordinal_type cell) const {
149  // vertices of cell (P,D)
150  const auto verts = Kokkos::subdynrankview( _cellCoords, cell,
151  Kokkos::ALL(), Kokkos::ALL() );
152  const ordinal_type nvert = verts.extent(0);
153  const ordinal_type dim = verts.extent(1);
154 
155  // control volume coords (N,P,D), here N corresponds to cell vertices
156  auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
157  Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
158 
159  // work space for barycenter and midpoints on edges
160  typedef typename subcvCoordViewType::value_type value_type;
161  value_type buf_center[2], buf_midpts[4*2];
162  Kokkos::View<value_type*,Kokkos::Impl::ActiveExecutionMemorySpace> center(buf_center, 2);
163  Kokkos::View<value_type**,Kokkos::Impl::ActiveExecutionMemorySpace> midpts(buf_midpts, 4, 2);
164 
165  getBaryCenter(center, verts);
166  getMidPoints(midpts, _edgeMap, verts);
167 
168  for (ordinal_type i=0;i<nvert;++i) {
169  for (ordinal_type j=0;j<dim;++j) {
170  // control volume is always quad
171  cvCoords(i, 0, j) = verts(i, j);
172  cvCoords(i, 1, j) = midpts(i, j);
173  cvCoords(i, 2, j) = center(j);
174  cvCoords(i, 3, j) = midpts((i+nvert-1)%nvert, j);
175  }
176  }
177  }
178  };
179 
180  template<typename subcvCoordViewType,
181  typename cellCoordViewType,
182  typename mapViewType>
187  subcvCoordViewType _subcvCoords;
188  const cellCoordViewType _cellCoords;
189  const mapViewType _edgeMap, _faceMap;
190 
191  KOKKOS_INLINE_FUNCTION
192  F_getSubcvCoords_Hexahedron( subcvCoordViewType subcvCoords_,
193  cellCoordViewType cellCoords_,
194  mapViewType edgeMap_,
195  mapViewType faceMap_ )
196  : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_), _faceMap(faceMap_) {}
197 
198  KOKKOS_INLINE_FUNCTION
199  void operator()(const ordinal_type cell) const {
200  // vertices of cell (P,D)
201  const auto verts = Kokkos::subdynrankview( _cellCoords, cell,
202  Kokkos::ALL(), Kokkos::ALL() );
203  // const ordinal_type nvert = verts.extent(0);
204  const ordinal_type dim = verts.extent(1);
205 
206  // control volume coords (N,P,D), here N corresponds to cell vertices
207  auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
208  Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
209 
210  // work space for barycenter and midpoints on edges
211  typedef typename subcvCoordViewType::value_type value_type;
212  value_type buf_center[3], buf_edge_midpts[12*3], buf_face_midpts[6*3];
213  Kokkos::View<value_type*,Kokkos::Impl::ActiveExecutionMemorySpace> center(buf_center, 3);
214  Kokkos::View<value_type**,Kokkos::Impl::ActiveExecutionMemorySpace> edge_midpts(buf_edge_midpts, 12, 3);
215  Kokkos::View<value_type**,Kokkos::Impl::ActiveExecutionMemorySpace> face_midpts(buf_face_midpts, 6, 3);
216 
217  getBaryCenter(center, verts);
218  getMidPoints(edge_midpts, _edgeMap, verts);
219  getMidPoints(face_midpts, _faceMap, verts);
220 
221  for (ordinal_type i=0;i<4;++i) {
222  const ordinal_type ii = (i+4-1)%4;
223  for (ordinal_type j=0;j<dim;++j) {
224 
225  // set first node of bottom hex to primary cell node
226  // and fifth node of upper hex
227  cvCoords(i, 0,j) = verts(i, j);
228  cvCoords(i+4,4,j) = verts(i+4,j);
229 
230  // set second node of bottom hex to adjacent edge midpoint
231  // and sixth node of upper hex
232  cvCoords(i, 1,j) = edge_midpts(i, j);
233  cvCoords(i+4,5,j) = edge_midpts(i+4,j);
234 
235  // set third node of bottom hex to bottom face midpoint (number 4)
236  // and seventh node of upper hex to top face midpoint
237  cvCoords(i, 2,j) = face_midpts(4,j);
238  cvCoords(i+4,6,j) = face_midpts(5,j);
239 
240  // set fourth node of bottom hex to other adjacent edge midpoint
241  // and eight node of upper hex to other adjacent edge midpoint
242  cvCoords(i, 3,j) = edge_midpts(ii, j);
243  cvCoords(i+4,7,j) = edge_midpts(ii+4,j);
244 
245  // set fifth node to vertical edge
246  // same as first node of upper hex
247  cvCoords(i, 4,j) = edge_midpts(i+8,j);
248  cvCoords(i+4,0,j) = edge_midpts(i+8,j);
249 
250  // set sixth node to adjacent face midpoint
251  // same as second node of upper hex
252  cvCoords(i, 5,j) = face_midpts(i,j);
253  cvCoords(i+4,1,j) = face_midpts(i,j);
254 
255  // set seventh node to barycenter
256  // same as third node of upper hex
257  cvCoords(i, 6,j) = center(j);
258  cvCoords(i+4,2,j) = center(j);
259 
260  // set eighth node to other adjacent face midpoint
261  // same as fourth node of upper hex
262  cvCoords(i, 7,j) = face_midpts(ii,j);
263  cvCoords(i+4,3,j) = face_midpts(ii,j);
264  }
265  }
266  }
267  };
268 
269 
270  template<typename subcvCoordViewType,
271  typename cellCoordViewType,
272  typename mapViewType>
277  subcvCoordViewType _subcvCoords;
278  const cellCoordViewType _cellCoords;
279  const mapViewType _edgeMap, _faceMap;
280 
281  KOKKOS_INLINE_FUNCTION
282  F_getSubcvCoords_Tetrahedron( subcvCoordViewType subcvCoords_,
283  cellCoordViewType cellCoords_,
284  mapViewType edgeMap_,
285  mapViewType faceMap_ )
286  : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_), _faceMap(faceMap_) {}
287 
288  KOKKOS_INLINE_FUNCTION
289  void operator()(const ordinal_type cell) const {
290  // ** vertices of cell (P,D)
291  const auto verts = Kokkos::subdynrankview( _cellCoords, cell,
292  Kokkos::ALL(), Kokkos::ALL() );
293  //const ordinal_type nvert = verts.extent(0);
294  const ordinal_type dim = verts.extent(1);
295 
296  // control volume coords (N,P,D), here N corresponds to cell vertices
297  auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
298  Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
299 
300  // work space for barycenter and midpoints on edges
301  typedef typename subcvCoordViewType::value_type value_type;
302  value_type buf_center[3], buf_edge_midpts[6*3], buf_face_midpts[4*3];
303  Kokkos::View<value_type*,Kokkos::Impl::ActiveExecutionMemorySpace> center(buf_center, 3);
304  Kokkos::View<value_type**,Kokkos::Impl::ActiveExecutionMemorySpace> edge_midpts(buf_edge_midpts, 6, 3);
305  Kokkos::View<value_type**,Kokkos::Impl::ActiveExecutionMemorySpace> face_midpts(buf_face_midpts, 4, 3);
306 
307  getBaryCenter(center, verts);
308  getMidPoints(edge_midpts, _edgeMap, verts);
309  getMidPoints(face_midpts, _faceMap, verts);
310 
311  for (ordinal_type i=0;i<3;++i) {
312  const ordinal_type ii = (i+3-1)%3;
313  for (ordinal_type j=0;j<dim;++j) {
314  // set first node of bottom hex to primary cell node
315  cvCoords(i,0,j) = verts(i,j);
316 
317  // set second node of bottom hex to adjacent edge midpoint
318  cvCoords(i,1,j) = edge_midpts(i,j);
319 
320  // set third node of bottom hex to bottom face midpoint (number 3)
321  cvCoords(i,2,j) = face_midpts(3,j);
322 
323  // set fourth node of bottom hex to other adjacent edge midpoint
324  cvCoords(i,3,j) = edge_midpts(ii,j);
325 
326  // set fifth node to vertical edge
327  cvCoords(i,4,j) = edge_midpts(i+3,j);
328 
329  // set sixth node to adjacent face midpoint
330  cvCoords(i,5,j) = face_midpts(i,j);
331 
332  // set seventh node to barycenter
333  cvCoords(i,6,j) = center(j);
334 
335  // set eighth node to other adjacent face midpoint
336  cvCoords(i,7,j) = face_midpts(ii,j);
337  }
338  }
339 
340  for (ordinal_type j=0;j<dim;++j) {
341  // Control volume attached to fourth node
342  // set first node of bottom hex to primary cell node
343  cvCoords(3,0,j) = verts(3,j);
344 
345  // set second node of bottom hex to adjacent edge midpoint
346  cvCoords(3,1,j) = edge_midpts(3,j);
347 
348  // set third node of bottom hex to bottom face midpoint (number 3)
349  cvCoords(3,2,j) = face_midpts(2,j);
350 
351  // set fourth node of bottom hex to other adjacent edge midpoint
352  cvCoords(3,3,j) = edge_midpts(5,j);
353 
354  // set fifth node to vertical edge
355  cvCoords(3,4,j) = edge_midpts(4,j);
356 
357  // set sixth node to adjacent face midpoint
358  cvCoords(3,5,j) = face_midpts(0,j);
359 
360  // set seventh node to barycenter
361  cvCoords(3,6,j) = center(j);
362 
363  // set eighth node to other adjacent face midpoint
364  cvCoords(3,7,j) = face_midpts(1,j);
365  }
366  }
367  };
368 
369  }
370 
371  template<typename SpT>
372  template<typename subcvCoordValueType, class ...subcvCoordProperties,
373  typename cellCoordValueType, class ...cellCoordProperties>
374  void
376  getSubcvCoords( Kokkos::DynRankView<subcvCoordValueType,subcvCoordProperties...> subcvCoords,
377  const Kokkos::DynRankView<cellCoordValueType,cellCoordProperties...> cellCoords,
378  const shards::CellTopology primaryCell ) {
379 #ifdef HAVE_INTREPID2_DEBUG
380  INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(primaryCell), std::invalid_argument,
381  ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): the primary cell must have a reference cell." );
382 
383  INTREPID2_TEST_FOR_EXCEPTION( cellCoords.extent(1) != primaryCell.getVertexCount(), std::invalid_argument,
384  ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): cell coords dimension(1) does not match to # of vertices of the cell." );
385 
386  INTREPID2_TEST_FOR_EXCEPTION( cellCoords.extent(2) != primaryCell.getDimension(), std::invalid_argument,
387  ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): cell coords dimension(2) does not match to the dimension of the cell." );
388 #endif
389 
390  // get array dimensions
391  const ordinal_type numCells = cellCoords.extent(0);
392  //const ordinal_type numVerts = cellCoords.extent(1);
393  const ordinal_type spaceDim = cellCoords.extent(2);
394 
395  // construct edge and face map for the cell type
396  const ordinal_type numEdge = primaryCell.getSubcellCount(1);
397  Kokkos::View<ordinal_type**,Kokkos::LayoutRight,Kokkos::HostSpace> edgeMapHost("CellTools::getSubcvCoords::edgeMapHost", numEdge, 3);
398  for (ordinal_type i=0;i<numEdge;++i) {
399  edgeMapHost(i,0) = primaryCell.getNodeCount(1, i);
400  for (ordinal_type j=0;j<edgeMapHost(i,0);++j)
401  edgeMapHost(i,j+1) = primaryCell.getNodeMap(1, i, j);
402  }
403 
404  const ordinal_type numFace = (spaceDim > 2 ? primaryCell.getSubcellCount(2) : 0);
405  Kokkos::View<ordinal_type**,Kokkos::LayoutRight,Kokkos::HostSpace> faceMapHost("CellTools::getSubcvCoords::faceMapHost", numFace, 5);
406  for (ordinal_type i=0;i<numFace;++i) {
407  faceMapHost(i,0) = primaryCell.getNodeCount(2, i);
408  for (ordinal_type j=0;j<faceMapHost(i,0);++j)
409  faceMapHost(i,j+1) = primaryCell.getNodeMap(2, i, j);
410  }
411 
412  // create mirror to device
413  auto edgeMap = Kokkos::create_mirror_view(typename SpT::memory_space(), edgeMapHost);
414  auto faceMap = Kokkos::create_mirror_view(typename SpT::memory_space(), faceMapHost);
415 
416  Kokkos::deep_copy(edgeMap, edgeMapHost);
417  Kokkos::deep_copy(faceMap, faceMapHost);
418 
419  // parallel run
420  typedef Kokkos::DynRankView<subcvCoordValueType,subcvCoordProperties...> subcvCoordViewType;
421  typedef Kokkos::DynRankView<cellCoordValueType,cellCoordProperties...> cellCoordViewType;
422  typedef Kokkos::View<ordinal_type**,Kokkos::LayoutRight,SpT> mapViewType;
423 
424  typedef typename ExecSpace<typename subcvCoordViewType::execution_space,SpT>::ExecSpaceType ExecSpaceType;
425 
426  const auto loopSize = numCells;
427  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
428 
429  switch (primaryCell.getKey()) {
430  case shards::Triangle<3>::key:
431  case shards::Quadrilateral<4>::key: {
432  // 2D polygon
434  Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap) );
435  break;
436  }
437  case shards::Hexahedron<8>::key: {
439  Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap, faceMap) );
440  break;
441  }
442  case shards::Tetrahedron<4>::key: {
444  Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap, faceMap) );
445  break;
446  }
447  default: {
448  INTREPID2_TEST_FOR_EXCEPTION( true, std::invalid_argument,
449  ">>> ERROR (Intrepid2::CellTools::getSubcvCoords: the give cell topology is not supported.");
450  }
451  }
452  }
453 }
454 
455 #endif
static void getSubcvCoords(Kokkos::DynRankView< subcvCoordValueType, subcvCoordProperties...> subcvCoords, const Kokkos::DynRankView< cellCoordValueType, cellCoordProperties...> cellCoords, const shards::CellTopology primaryCell)
Computes coordinates of sub-control volumes in each primary cell.
Functor for calculation of sub-control volume coordinates on hexahedra see Intrepid2::CellTools for m...
Functor for calculation of sub-control volume coordinates on polygons see Intrepid2::CellTools for mo...
Functor for calculation of sub-control volume coordinates on tetrahedra see Intrepid2::CellTools for ...