Intrepid2
Intrepid2_CellToolsDefRefToPhys.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_REF_TO_PHYS_HPP__
50#define __INTREPID2_CELLTOOLS_DEF_REF_TO_PHYS_HPP__
51
52// disable clang warnings
53#if defined (__clang__) && !defined (__INTEL_COMPILER)
54#pragma clang system_header
55#endif
56
57namespace Intrepid2 {
58
59 //============================================================================================//
60 // //
61 // Reference-to-physical frame mapping and its inverse //
62 // //
63 //============================================================================================//
64
65 namespace FunctorCellTools {
69 template<typename physPointViewType,
70 typename worksetCellType,
71 typename basisValType>
72 struct F_mapToPhysicalFrame {
73 physPointViewType _physPoints;
74 const worksetCellType _worksetCells;
75 const basisValType _basisVals;
76
77 KOKKOS_INLINE_FUNCTION
78 F_mapToPhysicalFrame( physPointViewType physPoints_,
79 worksetCellType worksetCells_,
80 basisValType basisVals_ )
81 : _physPoints(physPoints_), _worksetCells(worksetCells_), _basisVals(basisVals_) {}
82
83 KOKKOS_INLINE_FUNCTION
84 void operator()(const size_type iter) const {
85 size_type cell, pt;
86 unrollIndex( cell, pt,
87 _physPoints.extent(0),
88 _physPoints.extent(1),
89 iter );
90 auto phys = Kokkos::subdynrankview( _physPoints, cell, pt, Kokkos::ALL());
91
92 const auto valRank = _basisVals.rank();
93 const auto val = ( valRank == 2 ? Kokkos::subdynrankview( _basisVals, Kokkos::ALL(), pt) :
94 Kokkos::subdynrankview( _basisVals, cell, Kokkos::ALL(), pt));
95
96 const ordinal_type dim = phys.extent(0);
97 const ordinal_type cardinality = val.extent(0);
98
99 for (ordinal_type i=0;i<dim;++i) {
100 phys(i) = 0;
101 for (ordinal_type bf=0;bf<cardinality;++bf)
102 phys(i) += _worksetCells(cell, bf, i)*val(bf);
103 }
104 }
105 };
106
107
108 template<typename refSubcellViewType,
109 typename paramPointsViewType,
110 typename subcellMapViewType>
111 struct F_mapReferenceSubcell2 {
112 refSubcellViewType refSubcellPoints_;
113 const paramPointsViewType paramPoints_;
114 const subcellMapViewType subcellMap_;
115 ordinal_type subcellOrd_, dim_;
116
117 KOKKOS_INLINE_FUNCTION
118 F_mapReferenceSubcell2( refSubcellViewType refSubcellPoints,
119 const paramPointsViewType paramPoints,
120 const subcellMapViewType subcellMap,
121 ordinal_type subcellOrd,
122 ordinal_type dim)
123 : refSubcellPoints_(refSubcellPoints), paramPoints_(paramPoints), subcellMap_(subcellMap),
124 subcellOrd_(subcellOrd), dim_(dim){};
125
126 KOKKOS_INLINE_FUNCTION
127 void operator()(const size_type pt) const {
128
129 const auto u = paramPoints_(pt, 0);
130 const auto v = paramPoints_(pt, 1);
131
132 // map_dim(u,v) = c_0(dim) + c_1(dim)*u + c_2(dim)*v because both Quad and Tri ref faces are affine!
133 for (ordinal_type i=0;i<dim_;++i)
134 refSubcellPoints_(pt, i) = subcellMap_(subcellOrd_, i, 0) + ( subcellMap_(subcellOrd_, i, 1)*u +
135 subcellMap_(subcellOrd_, i, 2)*v );
136 }
137 };
138
139 template<typename refSubcellViewType,
140 typename paramPointsViewType,
141 typename subcellMapViewType>
142 struct F_mapReferenceSubcell1 {
143 refSubcellViewType refSubcellPoints_;
144 const paramPointsViewType paramPoints_;
145 const subcellMapViewType subcellMap_;
146 ordinal_type subcellOrd_, dim_;
147
148 KOKKOS_INLINE_FUNCTION
149 F_mapReferenceSubcell1( refSubcellViewType refSubcellPoints,
150 const paramPointsViewType paramPoints,
151 const subcellMapViewType subcellMap,
152 ordinal_type subcellOrd,
153 ordinal_type dim)
154 : refSubcellPoints_(refSubcellPoints), paramPoints_(paramPoints), subcellMap_(subcellMap),
155 subcellOrd_(subcellOrd), dim_(dim){};
156
157 KOKKOS_INLINE_FUNCTION
158 void operator()(const size_type pt) const {
159 const auto u = paramPoints_(pt, 0);
160 for (ordinal_type i=0;i<dim_;++i)
161 refSubcellPoints_(pt, i) = subcellMap_(subcellOrd_, i, 0) + ( subcellMap_(subcellOrd_, i, 1)*u );
162 }
163 };
164 }
165
166 template<typename DeviceType>
167 template<typename physPointValueType, class ...physPointProperties,
168 typename refPointValueType, class ...refPointProperties,
169 typename WorksetType,
170 typename HGradBasisPtrType>
171 void
173 mapToPhysicalFrame( Kokkos::DynRankView<physPointValueType,physPointProperties...> physPoints,
174 const Kokkos::DynRankView<refPointValueType,refPointProperties...> refPoints,
175 const WorksetType worksetCell,
176 const HGradBasisPtrType basis ) {
177#ifdef HAVE_INTREPID2_DEBUG
178 CellTools_mapToPhysicalFrameArgs( physPoints, refPoints, worksetCell, basis->getBaseCellTopology() );
179#endif
180 constexpr bool are_accessible =
181 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
182 typename decltype(physPoints)::memory_space>::accessible &&
183 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
184 typename decltype(refPoints)::memory_space>::accessible;
185
186 static_assert(are_accessible, "CellTools<DeviceType>::mapToPhysicalFrame(..): input/output views' memory spaces are not compatible with DeviceType");
187
188 const auto cellTopo = basis->getBaseCellTopology();
189 const auto numCells = worksetCell.extent(0);
190
191 //points can be rank-2 (P,D), or rank-3 (C,P,D)
192 const auto refPointRank = refPoints.rank();
193 const auto numPoints = (refPointRank == 2 ? refPoints.extent(0) : refPoints.extent(1));
194 const auto basisCardinality = basis->getCardinality();
195 auto vcprop = Kokkos::common_view_alloc_prop(physPoints);
196
197 using physPointViewType =Kokkos::DynRankView<physPointValueType,physPointProperties...>;
198 using valViewType = Kokkos::DynRankView<decltype(basis->getDummyOutputValue()),DeviceType>;
199
200 valViewType vals;
201
202 switch (refPointRank) {
203 case 2: {
204 // refPoints is (P,D): single set of ref. points is mapped to one or multiple physical cells
205 vals = valViewType(Kokkos::view_alloc("CellTools::mapToPhysicalFrame::vals", vcprop), basisCardinality, numPoints);
206 basis->getValues(vals,
207 refPoints,
208 OPERATOR_VALUE);
209 break;
210 }
211 case 3: {
212 // refPoints is (C,P,D): multiple sets of ref. points are mapped to matching number of physical cells.
213 //vals = valViewType("CellTools::mapToPhysicalFrame::vals", numCells, basisCardinality, numPoints);
214 vals = valViewType(Kokkos::view_alloc("CellTools::mapToPhysicalFrame::vals", vcprop), numCells, basisCardinality, numPoints);
215 for (size_type cell=0;cell<numCells;++cell)
216 basis->getValues(Kokkos::subdynrankview( vals, cell, Kokkos::ALL(), Kokkos::ALL() ),
217 Kokkos::subdynrankview( refPoints, cell, Kokkos::ALL(), Kokkos::ALL() ),
218 OPERATOR_VALUE);
219 break;
220 }
221 }
222
224
225 const auto loopSize = physPoints.extent(0)*physPoints.extent(1);
226 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
227 Kokkos::parallel_for( policy, FunctorType(physPoints, worksetCell, vals) );
228 }
229
230 template<typename DeviceType>
231 template<typename refSubcellPointValueType, class ...refSubcellPointProperties,
232 typename paramPointValueType, class ...paramPointProperties>
233 void
235 mapToReferenceSubcell( Kokkos::DynRankView<refSubcellPointValueType,refSubcellPointProperties...> refSubcellPoints,
236 const Kokkos::DynRankView<paramPointValueType,paramPointProperties...> paramPoints,
237 const ordinal_type subcellDim,
238 const ordinal_type subcellOrd,
239 const shards::CellTopology parentCell ) {
240 ordinal_type parentCellDim = parentCell.getDimension();
241#ifdef HAVE_INTREPID2_DEBUG
242 INTREPID2_TEST_FOR_EXCEPTION( !hasReferenceCell(parentCell), std::invalid_argument,
243 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): the specified cell topology does not have a reference cell.");
244
245 INTREPID2_TEST_FOR_EXCEPTION( subcellDim < 1 ||
246 subcellDim > parentCellDim-1, std::invalid_argument,
247 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): method defined only for subcells with dimension greater than 0 and less than the cell dimension");
248
249 INTREPID2_TEST_FOR_EXCEPTION( subcellOrd < 0 ||
250 subcellOrd >= static_cast<ordinal_type>(parentCell.getSubcellCount(subcellDim)), std::invalid_argument,
251 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): subcell ordinal out of range.");
252
253 // refSubcellPoints is rank-2 (P,D1), D1 = cell dimension
254 INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.rank() != 2, std::invalid_argument,
255 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints must have rank 2.");
256 INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.extent(1) != parentCell.getDimension(), std::invalid_argument,
257 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints dimension (1) does not match to parent cell dimension.");
258
259 // paramPoints is rank-2 (P,D2) with D2 = subcell dimension
260 INTREPID2_TEST_FOR_EXCEPTION( paramPoints.rank() != 2, std::invalid_argument,
261 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): paramPoints must have rank 2.");
262 INTREPID2_TEST_FOR_EXCEPTION( static_cast<ordinal_type>(paramPoints.extent(1)) != subcellDim, std::invalid_argument,
263 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): paramPoints dimension (1) does not match to subcell dimension.");
264
265 // cross check: refSubcellPoints and paramPoints: dimension 0 must match
266 INTREPID2_TEST_FOR_EXCEPTION( refSubcellPoints.extent(0) < paramPoints.extent(0), std::invalid_argument,
267 ">>> ERROR (Intrepid2::CellTools::mapToReferenceSubcell): refSubcellPoints dimension (0) does not match to paramPoints dimension(0).");
268#endif
269
270 constexpr bool are_accessible =
271 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
272 typename decltype(refSubcellPoints)::memory_space>::accessible &&
273 Kokkos::Impl::MemorySpaceAccess<MemSpaceType,
274 typename decltype(paramPoints)::memory_space>::accessible;
275
276 static_assert(are_accessible, "CellTools<DeviceType>::mapToReferenceSubcell(..): input/output views' memory spaces are not compatible with DeviceType");
277
278 // Get the subcell map, i.e., the coefficients of the parametrization function for the subcell
279 const auto subcellMap = RefSubcellParametrization<DeviceType>::get(subcellDim, parentCell.getKey());
280
281 const ordinal_type numPts = paramPoints.extent(0);
282
283 //Note: this function has several template parameters and the compiler gets confused if using a lambda function
284 using FunctorType1 = FunctorCellTools::F_mapReferenceSubcell1<decltype(refSubcellPoints), decltype(paramPoints), decltype(subcellMap)>;
285 using FunctorType2 = FunctorCellTools::F_mapReferenceSubcell2<decltype(refSubcellPoints), decltype(paramPoints), decltype(subcellMap)>;
286
287 Kokkos::RangePolicy<ExecSpaceType> policy(0, numPts);
288 // Apply the parametrization map to every point in parameter domain
289 switch (subcellDim) {
290 case 2: {
291 Kokkos::parallel_for( policy, FunctorType2(refSubcellPoints, paramPoints, subcellMap, subcellOrd, parentCellDim) );
292 break;
293 }
294 case 1: {
295 Kokkos::parallel_for( policy, FunctorType1(refSubcellPoints, paramPoints, subcellMap, subcellOrd, parentCellDim) );
296 break;
297 }
298 default: {}
299 }
300 }
301}
302
303#endif
static void CellTools_mapToPhysicalFrameArgs(const physPointViewType physPoints, const refPointViewType refPoints, const worksetCellViewType worksetCell, const shards::CellTopology cellTopo)
Validates arguments to Intrepid2::CellTools::mapToPhysicalFrame.
static void mapToPhysicalFrame(Kokkos::DynRankView< physPointValueType, physPointProperties... > physPoints, const Kokkos::DynRankView< refPointValueType, refPointProperties... > refPoints, const WorksetType worksetCell, const HGradBasisPtrType basis)
Computes F, the reference-to-physical frame map.
static bool hasReferenceCell(const shards::CellTopology cellTopo)
Checks if a cell topology has reference cell.
static void mapToReferenceSubcell(Kokkos::DynRankView< refSubcellPointValueType, refSubcellPointProperties... > refSubcellPoints, const Kokkos::DynRankView< paramPointValueType, paramPointProperties... > paramPoints, const ordinal_type subcellDim, const ordinal_type subcellOrd, const shards::CellTopology parentCell)
Computes parameterization maps of 1- and 2-subcells of reference cells.
static ConstViewType get(const ordinal_type subcellDim, const unsigned parentCellKey)
Returns a Kokkos view with the coefficients of the parametrization maps for the edges or faces of a r...
Functor for mapping reference points to physical frame see Intrepid2::CellTools for more.