Intrepid2
Intrepid2_HVOL_HEX_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_HEX_CN_FEMDEF_HPP__
16#define __INTREPID2_HVOL_HEX_CN_FEMDEF_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 const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3));
45
46 const ordinal_type dim_s = get_dimension_scalar(input);
47 auto ptr0 = work.data();
48 auto ptr1 = work.data()+cardLine*npts*dim_s;
49 auto ptr2 = work.data()+2*cardLine*npts*dim_s;
50 auto ptr3 = work.data()+3*cardLine*npts*dim_s;
51
52 typedef typename Kokkos::DynRankView<typename InputViewType::value_type, typename WorkViewType::memory_space> ViewType;
53
54 switch (OpType) {
55 case OPERATOR_VALUE: {
56 ViewType work_line = createMatchingUnmanagedView<ViewType>(input, ptr0, cardLine, npts);
57 ViewType output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts);
58 ViewType output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts);
59 ViewType output_z = createMatchingUnmanagedView<ViewType>(input, ptr3, cardLine, npts);
60
61 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
62 getValues(output_x, input_x, work_line, vinv);
63
64 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
65 getValues(output_y, input_y, work_line, vinv);
66
67 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
68 getValues(output_z, input_z, work_line, vinv);
69
70 // tensor product
71 ordinal_type idx = 0;
72 for (ordinal_type k=0;k<cardLine;++k) // z
73 for (ordinal_type j=0;j<cardLine;++j) // y
74 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
75 for (ordinal_type l=0;l<npts;++l)
76 output.access(idx,l) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
77 break;
78 }
79 case OPERATOR_GRAD:
80 case OPERATOR_D1:
81 case OPERATOR_D2:
82 case OPERATOR_D3:
83 case OPERATOR_D4:
84 case OPERATOR_D5:
85 case OPERATOR_D6:
86 case OPERATOR_D7:
87 case OPERATOR_D8:
88 case OPERATOR_D9:
89 case OPERATOR_D10:
90 opDn = getOperatorOrder(OpType);
91 case OPERATOR_Dn: {
92 const ordinal_type dkcard = opDn + 1;
93
94 ordinal_type d = 0;
95 for (ordinal_type l1=0;l1<dkcard;++l1)
96 for (ordinal_type l0=0;l0<(l1+1);++l0) {
97 const ordinal_type mult_x = (opDn - l1);
98 const ordinal_type mult_y = l1 - l0;
99 const ordinal_type mult_z = l0;
100
101 //std::cout << " l0, l1 = " << l0 << " " << l1 << std::endl;
102 //std::cout << " x , y , z = " << mult_x << " " << mult_y << " " << mult_z << std::endl;
103
104 if (mult_x < 0) {
105 // pass
106 } else {
107 ViewType work_line = createMatchingUnmanagedView<ViewType>(input, ptr0, cardLine, npts);
108 decltype(work_line) output_x, output_y, output_z;
109
110 if (mult_x) {
111 output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts, 1);
112 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
113 getValues(output_x, input_x, work_line, vinv, mult_x);
114 } else {
115 output_x = createMatchingUnmanagedView<ViewType>(input, ptr1, cardLine, npts);
116 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
117 getValues(output_x, input_x, work_line, vinv);
118 }
119
120 if (mult_y) {
121 output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts, 1);
122 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
123 getValues(output_y, input_y, work_line, vinv, mult_y);
124 } else {
125 output_y = createMatchingUnmanagedView<ViewType>(input, ptr2, cardLine, npts);
126 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
127 getValues(output_y, input_y, work_line, vinv);
128 }
129
130 if (mult_z) {
131 output_z = createMatchingUnmanagedView<ViewType>(input, ptr3, cardLine, npts, 1);
132 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
133 getValues(output_z, input_z, work_line, vinv, mult_z);
134 } else {
135 output_z = createMatchingUnmanagedView<ViewType>(input, ptr3, cardLine, npts);
136 Impl::Basis_HVOL_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
137 getValues(output_z, input_z, work_line, vinv);
138 }
139
140 // tensor product (extra dimension of ouput x,y and z are ignored)
141 ordinal_type idx = 0;
142 for (ordinal_type k=0;k<cardLine;++k) // z
143 for (ordinal_type j=0;j<cardLine;++j) // y
144 for (ordinal_type i=0;i<cardLine;++i,++idx) // x
145 for (ordinal_type l=0;l<npts;++l)
146 output.access(idx,l,d) = output_x.access(i,l,0)*output_y.access(j,l,0)*output_z.access(k,l,0);
147 ++d;
148 }
149 }
150 break;
151 }
152 default: {
153 INTREPID2_TEST_FOR_ABORT( true ,
154 ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): Operator type not implemented");
155 break;
156 }
157 }
158 }
159
160 template<typename DT, ordinal_type numPtsPerEval,
161 typename outputValueValueType, class ...outputValueProperties,
162 typename inputPointValueType, class ...inputPointProperties,
163 typename vinvValueType, class ...vinvProperties>
164 void
165 Basis_HVOL_HEX_Cn_FEM::
166 getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
167 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
168 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
169 const EOperator operatorType ) {
170 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
171 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
172 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
173 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
174
175 // loopSize corresponds to cardinality
176 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
177 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
178 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
179 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
180
181 const ordinal_type cardinality = outputValues.extent(0);
182 const ordinal_type cardLine = std::cbrt(cardinality);
183 const ordinal_type workSize = 4*cardLine;
184
185 auto work = createMatchingDynRankView(inputPoints, "Basis_HVOL_HEX_Cn_FEM::getValues::work", workSize, inputPoints.extent(0));
186
187 switch (operatorType) {
188 case OPERATOR_VALUE: {
189 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
190 OPERATOR_VALUE,numPtsPerEval> FunctorType;
191 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
192 break;
193 }
194 case OPERATOR_GRAD:
195 case OPERATOR_D1:
196 case OPERATOR_D2:
197 case OPERATOR_D3:
198 case OPERATOR_D4:
199 case OPERATOR_D5:
200 case OPERATOR_D6:
201 case OPERATOR_D7:
202 case OPERATOR_D8:
203 case OPERATOR_D9:
204 case OPERATOR_D10: {
205 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,decltype(work),
206 OPERATOR_Dn,numPtsPerEval> FunctorType;
207 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work,
208 getOperatorOrder(operatorType)) );
209 break;
210 }
211 default: {
212 INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
213 ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): Operator type not implemented" );
214 // break; commented out since exception is thrown
215 }
216 }
217 }
218 }
219
220 // -------------------------------------------------------------------------------------
221 template<typename DT, typename OT, typename PT>
223 Basis_HVOL_HEX_Cn_FEM( const ordinal_type order,
224 const EPointType pointType ) {
225
226 // this should be in host
227 Basis_HVOL_LINE_Cn_FEM<DT,OT,PT> lineBasis( order, pointType );
228 const auto cardLine = lineBasis.getCardinality();
229
230 this->pointType_ = pointType;
231 this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>("HVOL::HEX::Cn::vinv", cardLine, cardLine);
232 lineBasis.getVandermondeInverse(this->vinv_);
233
234 const ordinal_type spaceDim = 3;
235 this->basisCardinality_ = cardLine*cardLine*cardLine;
236 this->basisDegree_ = order;
237 this->basisCellTopologyKey_ = shards::Hexahedron<8>::key;
238 this->basisType_ = BASIS_FEM_LAGRANGIAN;
239 this->basisCoordinates_ = COORDINATES_CARTESIAN;
240 this->functionSpace_ = FUNCTION_SPACE_HVOL;
241
242 // initialize tags
243 {
244 // Basis-dependent initializations
245 const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
246 const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
247 const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
248 const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
249
250 // An array with local DoF tags assigned to the basis functions, in the order of their local enumeration
251 constexpr ordinal_type maxCardLine = Parameters::MaxOrder + 1;
252 ordinal_type tags[maxCardLine*maxCardLine*maxCardLine][4];
253
254 {
255 ordinal_type idx = 0;
256 for (auto k=0;k<cardLine;++k) { // z
257 const auto tag_z = lineBasis.getDofTag(k);
258 for (ordinal_type j=0;j<cardLine;++j) { // y
259 const auto tag_y = lineBasis.getDofTag(j);
260 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
261 const auto tag_x = lineBasis.getDofTag(i);
262
263 // interior
264 tags[idx][0] = 3; // interior dof
265 tags[idx][1] = 0;
266 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2); // local dof id
267 tags[idx][3] = tag_x(3)*tag_y(3)*tag_z(3); // total number of dofs in this vertex
268 }
269 }
270 }
271 }
272
273 OrdinalTypeArray1DHost tagView(&tags[0][0], this->basisCardinality_*4);
274
275 // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
276 // tags are constructed on host
278 this->ordinalToTag_,
279 tagView,
280 this->basisCardinality_,
281 tagSize,
282 posScDim,
283 posScOrd,
284 posDfOrd);
285 }
286
287 // dofCoords on host and create its mirror view to device
288 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
289 dofCoordsHost("dofCoordsHost", this->basisCardinality_, spaceDim);
290
291 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
292 dofCoordsLine("dofCoordsLine", cardLine, 1);
293
294 lineBasis.getDofCoords(dofCoordsLine);
295 auto dofCoordsLineHost = Kokkos::create_mirror_view(Kokkos::HostSpace(), dofCoordsLine);
296 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
297 {
298 ordinal_type idx = 0;
299 for (auto k=0;k<cardLine;++k) { // z
300 for (ordinal_type j=0;j<cardLine;++j) { // y
301 for (ordinal_type i=0;i<cardLine;++i,++idx) { // x
302 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
303 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
304 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
305 }
306 }
307 }
308
309 }
310
311 this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoordsHost);
312 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
313 }
314
315 template<typename DT, typename OT, typename PT>
316 void
317 Basis_HVOL_HEX_Cn_FEM<DT,OT,PT>::getScratchSpaceSize(
318 ordinal_type& perTeamSpaceSize,
319 ordinal_type& perThreadSpaceSize,
320 const PointViewType inputPoints,
321 const EOperator operatorType) const {
322 perTeamSpaceSize = 0;
323 perThreadSpaceSize = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
324 }
325
326 template<typename DT, typename OT, typename PT>
327 KOKKOS_INLINE_FUNCTION
328 void
329 Basis_HVOL_HEX_Cn_FEM<DT,OT,PT>::getValues(
330 OutputViewType outputValues,
331 const PointViewType inputPoints,
332 const EOperator operatorType,
333 const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
334 const typename DT::execution_space::scratch_memory_space & scratchStorage,
335 const ordinal_type subcellDim,
336 const ordinal_type subcellOrdinal) const {
337
338 INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
339 ">>> ERROR: (Intrepid2::Basis_HVOL_HEX_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
340
341 const int numPoints = inputPoints.extent(0);
342 using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
343 using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
344 auto sizePerPoint = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
345 WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
346 using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
347 switch(operatorType) {
348 case OPERATOR_VALUE:
349 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=, &vinv_ = this->vinv_, basisDegree_ = this->basisDegree_] (ordinal_type& pt) {
350 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
351 const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
352 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
353 Impl::Basis_HVOL_HEX_Cn_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, vinv_, basisDegree_);
354 });
355 break;
356 default: {
357 INTREPID2_TEST_FOR_ABORT( true,
358 ">>> ERROR (Basis_HVOL_HEX_Cn_FEM): getValues not implemented for this operator");
359 }
360 }
361 }
362
363} // namespace Intrepid2
364
365#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...
Basis_HVOL_HEX_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
Kokkos::DynRankView< typename ScalarViewType::value_type, DeviceType > vinv_
inverse of Generalized Vandermonde matrix (isotropic order)
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.
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.