Intrepid2
Intrepid2_HVOL_QUAD_Cn_FEMDef.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Intrepid2 Package
4//
5// Copyright 2007 NTESS and the Intrepid2 contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
14
15#ifndef __INTREPID2_HVOL_QUAD_CN_FEM_DEF_HPP__
16#define __INTREPID2_HVOL_QUAD_CN_FEM_DEF_HPP__
17
18namespace Intrepid2 {
19
20 // -------------------------------------------------------------------------------------
21 namespace Impl {
22
23 template<EOperator OpType>
24 template<typename OutputViewType,
25 typename InputViewType,
26 typename WorkViewType,
27 typename VinvViewType>
28 KOKKOS_INLINE_FUNCTION
29 void
31 getValues( OutputViewType output,
32 const InputViewType input,
33 WorkViewType work,
34 const VinvViewType vinv,
35 const ordinal_type operatorDn ) {
36 ordinal_type opDn = operatorDn;
37
38 const ordinal_type cardLine = vinv.extent(0);
39 const ordinal_type npts = input.extent(0);
40
41 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
42 const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1));
43 const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2));
44
45 const ordinal_type dim_s = get_dimension_scalar(input);
46 auto ptr0 = work.data();
47 auto ptr1 = work.data()+cardLine*npts*dim_s;
48 auto ptr2 = work.data()+2*cardLine*npts*dim_s;
49
50 typedef typename Kokkos::DynRankView<typename InputViewType::value_type, typename WorkViewType::memory_space> ViewType;
51
52 switch (OpType) {
53 case OPERATOR_VALUE: {
54 ViewType work_line = createMatchingUnmanagedView<ViewType>(input, ptr0, cardLine, npts);
55 ViewType output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts);
56 ViewType output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts);
57
58 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
59 getValues(output_x, input_x, work_line, vinv);
60
61 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
62 getValues(output_y, input_y, work_line, vinv);
63
64 // tensor product
65 ordinal_type idx = 0;
66 for (ordinal_type j=0;j<cardLine;++j) // y
67 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
68 for (ordinal_type k=0;k<npts;++k)
69 output.access(idx,k) = output_x.access(i,k)*output_y.access(j,k);
70 break;
71 }
72 case OPERATOR_GRAD:
73 case OPERATOR_D1:
74 case OPERATOR_D2:
75 case OPERATOR_D3:
76 case OPERATOR_D4:
77 case OPERATOR_D5:
78 case OPERATOR_D6:
79 case OPERATOR_D7:
80 case OPERATOR_D8:
81 case OPERATOR_D9:
82 case OPERATOR_D10:
83 opDn = getOperatorOrder(OpType);
84 case OPERATOR_Dn: {
85 const auto dkcard = opDn + 1;
86 for (auto l=0;l<dkcard;++l) {
87 ViewType work_line = createMatchingUnmanagedView<ViewType>(input, ptr0, cardLine, npts);
88
89 ViewType output_x, output_y;
90
91 const auto mult_x = opDn - l;
92 const auto mult_y = l;
93
94 if (mult_x) {
95 output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts, 1);
96 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
97 getValues(output_x, input_x, work_line, vinv, mult_x);
98 } else {
99 output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts);
100 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
101 getValues(output_x, input_x, work_line, vinv);
102 }
103
104 if (mult_y) {
105 output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts, 1);
106 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
107 getValues(output_y, input_y, work_line, vinv, mult_y);
108 } else {
109 output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts);
110 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
111 getValues(output_y, input_y, work_line, vinv);
112 }
113
114 // tensor product (extra dimension of ouput x and y are ignored)
115 ordinal_type idx = 0;
116 for (ordinal_type j=0;j<cardLine;++j) // y
117 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
118 for (ordinal_type k=0;k<npts;++k)
119 output.access(idx,k,l) = output_x.access(i,k,0)*output_y.access(j,k,0);
120 }
121 break;
122 }
123 default: {
124 INTREPID2_TEST_FOR_ABORT( true,
125 ">>> ERROR: (Intrepid2::Basis_HVOL_QUAD_Cn_FEM::Serial::getValues) operator is not supported" );
126 }
127 }
128 }
129
130 template<typename DT, ordinal_type numPtsPerEval,
131 typename outputValueValueType, class ...outputValueProperties,
132 typename inputPointValueType, class ...inputPointProperties,
133 typename vinvValueType, class ...vinvProperties>
134 void
135 Basis_HVOL_QUAD_Cn_FEM::
136 getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
137 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
138 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
139 const EOperator operatorType ) {
140 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
141 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
142 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
143 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
144
145 // loopSize corresponds to cardinality
146 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
147 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
148 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
149 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
150
151 //typedef typename inputPointViewType::value_type inputPointType;
152
153 const ordinal_type cardinality = outputValues.extent(0);
154 const ordinal_type cardLine = std::sqrt(cardinality);
155 const ordinal_type workSize = 3*cardLine;
156
157 auto work = createMatchingDynRankView(inputPoints, "Basis_HVOL_QUAD_Cn_FEM::getValues::work", workSize, inputPoints.extent(0));
158
159 switch (operatorType) {
160 case OPERATOR_VALUE: {
161 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
162 OPERATOR_VALUE,numPtsPerEval> FunctorType;
163 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
164 break;
165 }
166 case OPERATOR_GRAD:
167 case OPERATOR_D1:
168 case OPERATOR_D2:
169 case OPERATOR_D3:
170 case OPERATOR_D4:
171 case OPERATOR_D5:
172 case OPERATOR_D6:
173 case OPERATOR_D7:
174 case OPERATOR_D8:
175 case OPERATOR_D9:
176 case OPERATOR_D10: {
177 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
178 OPERATOR_Dn,numPtsPerEval> FunctorType;
179 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work,
180 getOperatorOrder(operatorType)) );
181 break;
182 }
183 default: {
184 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
185 ">>> ERROR (Basis_HVOL_QUAD_Cn_FEM): Operator type not implemented" );
186 // break;commented out because exception
187 }
188 }
189 }
190 }
191
192 // -------------------------------------------------------------------------------------
193 template<typename DT, typename OT, typename PT>
195 Basis_HVOL_QUAD_Cn_FEM( const ordinal_type order,
196 const EPointType pointType ) {
197 // INTREPID2_TEST_FOR_EXCEPTION( !(pointType == POINTTYPE_EQUISPACED ||
198 // pointType == POINTTYPE_WARPBLEND), std::invalid_argument,
199 // ">>> ERROR (Basis_HVOL_QUAD_Cn_FEM): pointType must be either equispaced or warpblend." );
200
201 // this should be in host
202 Basis_HVOL_LINE_Cn_FEM<DT,OT,PT> lineBasis( order, pointType );
203 const auto cardLine = lineBasis.getCardinality();
204
205 this->pointType_ = pointType;
206 this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>("HVOL::Quad::Cn::vinv", cardLine, cardLine);
207 lineBasis.getVandermondeInverse(this->vinv_);
208
209 const ordinal_type spaceDim = 2;
210 this->basisCardinality_ = cardLine*cardLine;
211 this->basisDegree_ = order;
212 this->basisCellTopologyKey_ = shards::Quadrilateral<4>::key;
213 this->basisType_ = BASIS_FEM_LAGRANGIAN;
214 this->basisCoordinates_ = COORDINATES_CARTESIAN;
215 this->functionSpace_ = FUNCTION_SPACE_HVOL;
216
217 // initialize tags
218 {
219 // Basis-dependent initializations
220 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
221 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
222 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
223 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
224
225 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
226 constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
227 ordinal_type tags[maxCardLine*maxCardLine][4];
228
229 {
230 ordinal_type idx = 0;
231 for (ordinal_type j=0;j<cardLine;++j) { // y
232 const auto tag_y = lineBasis.getDofTag(j);
233 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
234 const auto tag_x = lineBasis.getDofTag(i);
235
236 // interior
237 tags[idx][0] = 2; // interior dof
238 tags[idx][1] = 0;
239 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2); // local dof id
240 tags[idx][3] = tag_x(3)*tag_y(3); // total number of dofs in this vertex
241 }
242 }
243 }
244
245 OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
246
247 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
248 // tags are constructed on host
250 this->ordinalToTag_,
251 tagView,
252 this->basisCardinality_,
253 tagSize,
254 posScDim,
255 posScOrd,
256 posDfOrd);
257 }
258
259 // dofCoords on host and create its mirror view to device
260 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
261 dofCoordsHost("dofCoordsHost", this->basisCardinality_, spaceDim);
262
263 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
264 dofCoordsLine("dofCoordsLine", cardLine, 1);
265
266 lineBasis.getDofCoords(dofCoordsLine);
267 auto dofCoordsLineHost = Kokkos::create_mirror_view(dofCoordsLine);
268 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
269 {
270 ordinal_type idx = 0;
271 for (ordinal_type j=0;j<cardLine;++j) { // y
272 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
273 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
274 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
275 }
276 }
277 }
278
279 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost);
280 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
281 }
282
283 template<typename DT, typename OT, typename PT>
284 void
285 Basis_HVOL_QUAD_Cn_FEM<DT,OT,PT>::getScratchSpaceSize(
286 ordinal_type& perTeamSpaceSize,
287 ordinal_type& perThreadSpaceSize,
288 const PointViewType inputPoints,
289 const EOperator operatorType) const {
290 perTeamSpaceSize = 0;
291 perThreadSpaceSize = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
292 }
293
294 template<typename DT, typename OT, typename PT>
295 KOKKOS_INLINE_FUNCTION
296 void
297 Basis_HVOL_QUAD_Cn_FEM<DT,OT,PT>::getValues(
298 OutputViewType outputValues,
299 const PointViewType inputPoints,
300 const EOperator operatorType,
301 const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
302 const typename DT::execution_space::scratch_memory_space & scratchStorage,
303 const ordinal_type subcellDim,
304 const ordinal_type subcellOrdinal) const {
305
306 INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
307 ">>> ERROR: (Intrepid2::Basis_HVOL_QUAD_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
308
309 const int numPoints = inputPoints.extent(0);
310 using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
311 using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
312 auto sizePerPoint = 3*this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
313 WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
314 using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
315 switch(operatorType) {
316 case OPERATOR_VALUE:
317 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_, basisDegree_ = this->basisDegree_] (ordinal_type& pt) {
318 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
319 const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
320 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
321 Impl::Basis_HVOL_QUAD_Cn_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, vinv_, basisDegree_);
322 });
323 break;
324 default: {
325 INTREPID2_TEST_FOR_ABORT( true,
326 ">>> ERROR (Basis_HVOL_QUAD_Cn_FEM): getValues not implemented for this operator");
327 }
328 }
329 }
330
331} // namespace Intrepid2
332
333#endif
KOKKOS_INLINE_FUNCTION ordinal_type getOperatorOrder(const EOperator operatorType)
Returns order of an operator.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_pointer_v< CtorProp > &&!std::is_convertible_v< CtorProp, constchar * >, OutViewType >::type createMatchingUnmanagedView(const InViewType &view, const CtorProp &data, const Dims... dims)
Creates an unmanaged view that matches the value_type of the provided view The type of the output vie...
DeduceDynRankView< InViewType >::type createMatchingDynRankView(const InViewType &view, const CtorProp &prop, const Dims... dims)
Creates and returns a view that matches the value_type of the provided view The output view type is d...
Implementation of the locally HVOL-compatible FEM basis of variable order on the [-1,...
virtual void getDofCoords(ScalarViewType dofCoords) const override
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
Kokkos::DynRankView< typename ScalarViewType::value_type, DeviceType > vinv_
inverse of Generalized Vandermonde matrix (isotropic order)
Basis_HVOL_QUAD_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
void setOrdinalTagData(OrdinalTypeView3D &tagToOrdinal, OrdinalTypeView2D &ordinalToTag, const OrdinalTypeView1D tags, const ordinal_type basisCard, const ordinal_type tagSize, const ordinal_type posScDim, const ordinal_type posScOrd, const ordinal_type posDfOrd)
ordinal_type getCardinality() const
Returns cardinality of the basis.
Kokkos::DynRankView< scalarType, DeviceType > dofCoords_
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.