16 #ifndef __INTREPID2_CELLTOOLS_DEF_CONTROL_VOLUME_HPP__
17 #define __INTREPID2_CELLTOOLS_DEF_CONTROL_VOLUME_HPP__
20 #if defined (__clang__) && !defined (__INTEL_COMPILER)
21 #pragma clang system_header
32 namespace FunctorCellTools {
38 template<
typename centerViewType,
typename vertViewType>
39 KOKKOS_INLINE_FUNCTION
40 void getBarycenterPolygon2D( centerViewType center,
41 const vertViewType verts) {
43 const ordinal_type nvert = verts.extent(0);
47 typename centerViewType::value_type area = 0;
48 for (ordinal_type i=0;i<nvert;++i) {
49 const ordinal_type j = (i + 1)%nvert;
50 const auto scale = verts(i,0)*verts(j,1) - verts(j,0)*verts(i,1);
51 center(0) += (verts(i,0) + verts(j,0))*scale;
52 center(1) += (verts(i,1) + verts(j,1))*scale;
55 center(0) /= (6.0*area);
56 center(1) /= (6.0*area);
59 template<
typename m
idPo
intViewType,
typename nodeMapViewType,
typename vertViewType>
60 KOKKOS_INLINE_FUNCTION
61 void getMidPoints( midPointViewType midpts,
62 const nodeMapViewType map,
63 const vertViewType verts) {
64 const ordinal_type npts = map.extent(0);
65 const ordinal_type dim = verts.extent(1);
67 for (ordinal_type i=0;i<npts;++i) {
69 const ordinal_type nvert_per_subcell = map(i, 0);
70 for (ordinal_type j=0;j<dim;++j) {
72 for (ordinal_type k=1;k<=nvert_per_subcell;++k)
73 midpts(i,j) += verts(map(i,k),j);
74 midpts(i,j) /= nvert_per_subcell;
79 template<
typename subcvCoordViewType,
80 typename cellCoordViewType,
86 subcvCoordViewType _subcvCoords;
87 const cellCoordViewType _cellCoords;
88 const mapViewType _edgeMap;
90 KOKKOS_INLINE_FUNCTION
92 cellCoordViewType cellCoords_,
93 mapViewType edgeMap_ )
94 : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_) {}
96 KOKKOS_INLINE_FUNCTION
97 void operator()(
const ordinal_type cell)
const {
99 const auto verts = Kokkos::subdynrankview( _cellCoords, cell,
100 Kokkos::ALL(), Kokkos::ALL() );
101 const ordinal_type nvert = verts.extent(0);
102 const ordinal_type dim = verts.extent(1);
105 auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
106 Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
109 typedef typename subcvCoordViewType::value_type value_type;
110 value_type buf_center[2], buf_midpts[4*2];
111 Kokkos::View<value_type*,Kokkos::AnonymousSpace> center(buf_center, 2);
112 Kokkos::View<value_type**,Kokkos::AnonymousSpace> midpts(buf_midpts, 4, 2);
114 getBarycenterPolygon2D(center, verts);
115 getMidPoints(midpts, _edgeMap, verts);
117 for (ordinal_type i=0;i<nvert;++i) {
118 for (ordinal_type j=0;j<dim;++j) {
120 cvCoords(i, 0, j) = verts(i, j);
121 cvCoords(i, 1, j) = midpts(i, j);
122 cvCoords(i, 2, j) = center(j);
123 cvCoords(i, 3, j) = midpts((i+nvert-1)%nvert, j);
129 template<
typename subcvCoordViewType,
130 typename cellCoordViewType,
131 typename mapViewType>
136 subcvCoordViewType _subcvCoords;
137 const cellCoordViewType _cellCoords;
138 const mapViewType _edgeMap, _faceMap;
140 KOKKOS_INLINE_FUNCTION
142 cellCoordViewType cellCoords_,
143 mapViewType edgeMap_,
144 mapViewType faceMap_ )
145 : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_), _faceMap(faceMap_) {}
147 KOKKOS_INLINE_FUNCTION
148 void operator()(
const ordinal_type cell)
const {
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);
156 auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
157 Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
160 typedef typename subcvCoordViewType::value_type value_type;
161 value_type buf_center[3], buf_edge_midpts[12*3], buf_face_midpts[6*3];
162 Kokkos::View<value_type*,Kokkos::AnonymousSpace> center(buf_center, 3);
163 Kokkos::View<value_type**,Kokkos::AnonymousSpace> edge_midpts(buf_edge_midpts, 12, 3);
164 Kokkos::View<value_type**,Kokkos::AnonymousSpace> face_midpts(buf_face_midpts, 6, 3);
168 for (ordinal_type j=0;j<3;++j) {
170 for (ordinal_type i=0;i<nvert;++i)
171 center(j) += verts(i,j);
175 getMidPoints(edge_midpts, _edgeMap, verts);
176 getMidPoints(face_midpts, _faceMap, verts);
178 for (ordinal_type i=0;i<4;++i) {
179 const ordinal_type ii = (i+4-1)%4;
180 for (ordinal_type j=0;j<dim;++j) {
184 cvCoords(i, 0,j) = verts(i, j);
185 cvCoords(i+4,4,j) = verts(i+4,j);
189 cvCoords(i, 1,j) = edge_midpts(i, j);
190 cvCoords(i+4,5,j) = edge_midpts(i+4,j);
194 cvCoords(i, 2,j) = face_midpts(4,j);
195 cvCoords(i+4,6,j) = face_midpts(5,j);
199 cvCoords(i, 3,j) = edge_midpts(ii, j);
200 cvCoords(i+4,7,j) = edge_midpts(ii+4,j);
204 cvCoords(i, 4,j) = edge_midpts(i+8,j);
205 cvCoords(i+4,0,j) = edge_midpts(i+8,j);
209 cvCoords(i, 5,j) = face_midpts(i,j);
210 cvCoords(i+4,1,j) = face_midpts(i,j);
214 cvCoords(i, 6,j) = center(j);
215 cvCoords(i+4,2,j) = center(j);
219 cvCoords(i, 7,j) = face_midpts(ii,j);
220 cvCoords(i+4,3,j) = face_midpts(ii,j);
227 template<
typename subcvCoordViewType,
228 typename cellCoordViewType,
229 typename mapViewType>
234 subcvCoordViewType _subcvCoords;
235 const cellCoordViewType _cellCoords;
236 const mapViewType _edgeMap, _faceMap;
238 KOKKOS_INLINE_FUNCTION
240 cellCoordViewType cellCoords_,
241 mapViewType edgeMap_,
242 mapViewType faceMap_ )
243 : _subcvCoords(subcvCoords_), _cellCoords(cellCoords_), _edgeMap(edgeMap_), _faceMap(faceMap_) {}
245 KOKKOS_INLINE_FUNCTION
246 void operator()(
const ordinal_type cell)
const {
248 const auto verts = Kokkos::subdynrankview( _cellCoords, cell,
249 Kokkos::ALL(), Kokkos::ALL() );
250 const ordinal_type nvert = verts.extent(0);
251 const ordinal_type dim = verts.extent(1);
254 auto cvCoords = Kokkos::subdynrankview( _subcvCoords, cell,
255 Kokkos::ALL(), Kokkos::ALL(), Kokkos::ALL() );
258 typedef typename subcvCoordViewType::value_type value_type;
259 value_type buf_center[3], buf_edge_midpts[6*3], buf_face_midpts[4*3];
260 Kokkos::View<value_type*,Kokkos::AnonymousSpace> center(buf_center, 3);
261 Kokkos::View<value_type**,Kokkos::AnonymousSpace> edge_midpts(buf_edge_midpts, 6, 3);
262 Kokkos::View<value_type**,Kokkos::AnonymousSpace> face_midpts(buf_face_midpts, 4, 3);
265 for (ordinal_type j=0;j<3;++j) {
267 for (ordinal_type i=0;i<nvert;++i)
268 center(j) += verts(i,j);
272 getMidPoints(edge_midpts, _edgeMap, verts);
273 getMidPoints(face_midpts, _faceMap, verts);
275 for (ordinal_type i=0;i<3;++i) {
276 const ordinal_type ii = (i+3-1)%3;
277 for (ordinal_type j=0;j<dim;++j) {
279 cvCoords(i,0,j) = verts(i,j);
282 cvCoords(i,1,j) = edge_midpts(i,j);
285 cvCoords(i,2,j) = face_midpts(3,j);
288 cvCoords(i,3,j) = edge_midpts(ii,j);
291 cvCoords(i,4,j) = edge_midpts(i+3,j);
294 cvCoords(i,5,j) = face_midpts(i,j);
297 cvCoords(i,6,j) = center(j);
300 cvCoords(i,7,j) = face_midpts(ii,j);
304 for (ordinal_type j=0;j<dim;++j) {
307 cvCoords(3,0,j) = verts(3,j);
310 cvCoords(3,1,j) = edge_midpts(3,j);
313 cvCoords(3,2,j) = face_midpts(2,j);
316 cvCoords(3,3,j) = edge_midpts(5,j);
319 cvCoords(3,4,j) = edge_midpts(4,j);
322 cvCoords(3,5,j) = face_midpts(0,j);
325 cvCoords(3,6,j) = center(j);
328 cvCoords(3,7,j) = face_midpts(1,j);
335 template<
typename DeviceType>
336 template<
typename subcvCoordValueType,
class ...subcvCoordProperties,
337 typename cellCoordValueType,
class ...cellCoordProperties>
340 getSubcvCoords( Kokkos::DynRankView<subcvCoordValueType,subcvCoordProperties...> subcvCoords,
341 const Kokkos::DynRankView<cellCoordValueType,cellCoordProperties...> cellCoords,
342 const shards::CellTopology primaryCell ) {
343 #ifdef HAVE_INTREPID2_DEBUG
344 INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(primaryCell), std::invalid_argument,
345 ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): the primary cell must have a reference cell." );
347 INTREPID2_TEST_FOR_EXCEPTION( cellCoords.extent(1) != primaryCell.getVertexCount(), std::invalid_argument,
348 ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): cell coords dimension(1) does not match to # of vertices of the cell." );
350 INTREPID2_TEST_FOR_EXCEPTION( cellCoords.extent(2) != primaryCell.getDimension(), std::invalid_argument,
351 ">>> ERROR (Intrepid2::CellTools::getSubcvCoords): cell coords dimension(2) does not match to the dimension of the cell." );
353 constexpr
bool are_accessible =
354 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
355 typename decltype(subcvCoords)::memory_space>::accessible &&
356 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
357 typename decltype(cellCoords)::memory_space>::accessible;
358 static_assert(are_accessible,
"CellTools<DeviceType>::getSubcvCoords(..): input/output views' memory spaces are not compatible with DeviceType");
362 const ordinal_type numCells = cellCoords.extent(0);
364 const ordinal_type spaceDim = cellCoords.extent(2);
367 const ordinal_type numEdge = primaryCell.getSubcellCount(1);
368 Kokkos::View<ordinal_type**,DeviceType> edgeMap(
"CellTools::getSubcvCoords::edgeMap", numEdge, 3);
369 auto edgeMapHost = Kokkos::create_mirror_view(edgeMap);
370 for (ordinal_type i=0;i<numEdge;++i) {
371 edgeMapHost(i,0) = primaryCell.getNodeCount(1, i);
372 for (ordinal_type j=0;j<edgeMapHost(i,0);++j)
373 edgeMapHost(i,j+1) = primaryCell.getNodeMap(1, i, j);
376 const ordinal_type numFace = (spaceDim > 2 ? primaryCell.getSubcellCount(2) : 0);
377 Kokkos::View<ordinal_type**,DeviceType> faceMap(
"CellTools::getSubcvCoords::faceMap", numFace, 5);
378 auto faceMapHost = Kokkos::create_mirror_view(faceMap);
379 for (ordinal_type i=0;i<numFace;++i) {
380 faceMapHost(i,0) = primaryCell.getNodeCount(2, i);
381 for (ordinal_type j=0;j<faceMapHost(i,0);++j)
382 faceMapHost(i,j+1) = primaryCell.getNodeMap(2, i, j);
385 Kokkos::deep_copy(edgeMap, edgeMapHost);
386 Kokkos::deep_copy(faceMap, faceMapHost);
389 using subcvCoordViewType = decltype(subcvCoords);
390 using cellCoordViewType = decltype(cellCoords);
391 using mapViewType = decltype(edgeMap);
393 const auto loopSize = numCells;
394 Kokkos::RangePolicy<ExecSpaceType, Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
396 switch (primaryCell.getKey()) {
397 case shards::Triangle<3>::key:
398 case shards::Quadrilateral<4>::key: {
401 Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap) );
404 case shards::Hexahedron<8>::key: {
406 Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap, faceMap) );
409 case shards::Tetrahedron<4>::key: {
411 Kokkos::parallel_for( policy, FunctorType(subcvCoords, cellCoords, edgeMap, faceMap) );
415 INTREPID2_TEST_FOR_EXCEPTION(
true, std::invalid_argument,
416 ">>> ERROR (Intrepid2::CellTools::getSubcvCoords: the give cell topology is not supported.");