16 #ifndef __INTREPID2_HGRAD_HEX_CN_FEMDEF_HPP__
17 #define __INTREPID2_HGRAD_HEX_CN_FEMDEF_HPP__
24 template<EOperator opType>
25 template<
typename OutputViewType,
26 typename inputViewType,
27 typename workViewType,
28 typename vinvViewType>
29 KOKKOS_INLINE_FUNCTION
31 Basis_HGRAD_HEX_Cn_FEM::Serial<opType>::
32 getValues( OutputViewType output,
33 const inputViewType input,
35 const vinvViewType vinv,
36 const ordinal_type operatorDn ) {
37 ordinal_type opDn = operatorDn;
39 const ordinal_type cardLine = vinv.extent(0);
40 const ordinal_type npts = input.extent(0);
42 typedef Kokkos::pair<ordinal_type,ordinal_type> range_type;
43 const auto input_x = Kokkos::subview(input, Kokkos::ALL(), range_type(0,1));
44 const auto input_y = Kokkos::subview(input, Kokkos::ALL(), range_type(1,2));
45 const auto input_z = Kokkos::subview(input, Kokkos::ALL(), range_type(2,3));
47 const ordinal_type dim_s = get_dimension_scalar(input);
48 auto ptr0 = work.data();
49 auto ptr1 = work.data()+cardLine*npts*dim_s;
50 auto ptr2 = work.data()+2*cardLine*npts*dim_s;
51 auto ptr3 = work.data()+3*cardLine*npts*dim_s;
53 typedef typename Kokkos::DynRankView<typename inputViewType::value_type, typename workViewType::memory_space> viewType;
54 auto vcprop = Kokkos::common_view_alloc_prop(input);
57 case OPERATOR_VALUE: {
58 viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
59 viewType output_x(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
60 viewType output_y(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
61 viewType output_z(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts);
63 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
64 getValues(output_x, input_x, work_line, vinv);
66 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
67 getValues(output_y, input_y, work_line, vinv);
69 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
70 getValues(output_z, input_z, work_line, vinv);
74 for (ordinal_type k=0;k<cardLine;++k)
75 for (ordinal_type j=0;j<cardLine;++j)
76 for (ordinal_type i=0;i<cardLine;++i,++idx)
77 for (ordinal_type l=0;l<npts;++l)
78 output.access(idx,l) = output_x.access(i,l)*output_y.access(j,l)*output_z.access(k,l);
92 opDn = getOperatorOrder(opType);
94 const ordinal_type dkcard = opDn + 1;
97 for (ordinal_type l1=0;l1<dkcard;++l1)
98 for (ordinal_type l0=0;l0<(l1+1);++l0) {
99 const ordinal_type mult_x = (opDn - l1);
100 const ordinal_type mult_y = l1 - l0;
101 const ordinal_type mult_z = l0;
109 viewType work_line(Kokkos::view_wrap(ptr0, vcprop), cardLine, npts);
110 decltype(work_line) output_x, output_y, output_z;
113 output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts, 1);
114 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
115 getValues(output_x, input_x, work_line, vinv, mult_x);
117 output_x = viewType(Kokkos::view_wrap(ptr1, vcprop), cardLine, npts);
118 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
119 getValues(output_x, input_x, work_line, vinv);
123 output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts, 1);
124 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
125 getValues(output_y, input_y, work_line, vinv, mult_y);
127 output_y = viewType(Kokkos::view_wrap(ptr2, vcprop), cardLine, npts);
128 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
129 getValues(output_y, input_y, work_line, vinv);
133 output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts, 1);
134 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_Dn>::
135 getValues(output_z, input_z, work_line, vinv, mult_z);
137 output_z = viewType(Kokkos::view_wrap(ptr3, vcprop), cardLine, npts);
138 Impl::Basis_HGRAD_LINE_Cn_FEM::Serial<OPERATOR_VALUE>::
139 getValues(output_z, input_z, work_line, vinv);
143 ordinal_type idx = 0;
144 for (ordinal_type k=0;k<cardLine;++k)
145 for (ordinal_type j=0;j<cardLine;++j)
146 for (ordinal_type i=0;i<cardLine;++i,++idx)
147 for (ordinal_type l=0;l<npts;++l)
148 output.access(idx,l,d) = output_x.access(i,l,0)*output_y.access(j,l,0)*output_z.access(k,l,0);
155 INTREPID2_TEST_FOR_ABORT(
true ,
156 ">>> ERROR (Basis_HGRAD_HEX_Cn_FEM): Operator type not implemented");
162 template<
typename DT, ordinal_type numPtsPerEval,
163 typename outputValueValueType,
class ...outputValueProperties,
164 typename inputPointValueType,
class ...inputPointProperties,
165 typename vinvValueType,
class ...vinvProperties>
167 Basis_HGRAD_HEX_Cn_FEM::
168 getValues(
const typename DT::execution_space& space,
169 Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
170 const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
171 const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
172 const EOperator operatorType ) {
173 typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
174 typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
175 typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
176 typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
179 const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
180 const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
181 const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
182 Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(space, 0, loopSize);
184 typedef typename inputPointViewType::value_type inputPointType;
186 const ordinal_type cardinality = outputValues.extent(0);
187 const ordinal_type cardLine = std::cbrt(cardinality);
188 const ordinal_type workSize = 4*cardLine;
190 auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
191 typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
192 workViewType work(Kokkos::view_alloc(space,
"Basis_HGRAD_HEX_Cn_FEM::getValues::work", vcprop), workSize, inputPoints.extent(0));
194 switch (operatorType) {
195 case OPERATOR_VALUE: {
196 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,workViewType,
197 OPERATOR_VALUE,numPtsPerEval> FunctorType;
198 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
201 case OPERATOR_CURL: {
202 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,workViewType,
203 OPERATOR_CURL,numPtsPerEval> FunctorType;
204 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
218 typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,workViewType,
219 OPERATOR_Dn,numPtsPerEval> FunctorType;
220 Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work,
221 getOperatorOrder(operatorType)) );
225 INTREPID2_TEST_FOR_EXCEPTION(
true , std::invalid_argument,
226 ">>> ERROR (Basis_HGRAD_HEX_Cn_FEM): Operator type not implemented" );
234 template<
typename DT,
typename OT,
typename PT>
237 const EPointType pointType ) {
243 this->vinv_ = Kokkos::DynRankView<typename ScalarViewType::value_type,DT>(
"Hgrad::HEX::Cn::vinv", cardLine, cardLine);
244 lineBasis.getVandermondeInverse(this->vinv_);
246 const ordinal_type spaceDim = 3;
247 this->basisCardinality_ = cardLine*cardLine*cardLine;
248 this->basisDegree_ = order;
249 this->basisCellTopologyKey_ = shards::Hexahedron<8>::key;
250 this->basisType_ = BASIS_FEM_LAGRANGIAN;
251 this->basisCoordinates_ = COORDINATES_CARTESIAN;
252 this->functionSpace_ = FUNCTION_SPACE_HGRAD;
253 pointType_ = pointType;
258 const ordinal_type tagSize = 4;
259 const ordinal_type posScDim = 0;
260 const ordinal_type posScOrd = 1;
261 const ordinal_type posDfOrd = 2;
265 INTREPID2_TEST_FOR_EXCEPTION( order >
Parameters::MaxOrder, std::invalid_argument,
"polynomial order exceeds the max supported by this class");
269 ordinal_type tags[maxCardLine*maxCardLine*maxCardLine][4];
271 const ordinal_type vert[2][2][2] = { { {0,1}, {3,2} },
274 const ordinal_type edge_x[2][2] = { {0, 4}, {2, 6} };
275 const ordinal_type edge_y[2][2] = { {3, 7}, {1, 5} };
276 const ordinal_type edge_z[2][2] = { {8,11}, {9,10} };
278 const ordinal_type face_yz[2] = {3, 1};
279 const ordinal_type face_xz[2] = {0, 2};
280 const ordinal_type face_xy[2] = {4, 5};
283 ordinal_type idx = 0;
284 for (
auto k=0;k<cardLine;++k) {
285 const auto tag_z = lineBasis.
getDofTag(k);
286 for (ordinal_type j=0;j<cardLine;++j) {
287 const auto tag_y = lineBasis.
getDofTag(j);
288 for (ordinal_type i=0;i<cardLine;++i,++idx) {
289 const auto tag_x = lineBasis.
getDofTag(i);
291 if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 0) {
294 tags[idx][1] = vert[tag_z(1)][tag_y(1)][tag_x(1)];
297 }
else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 0) {
300 tags[idx][1] = edge_x[tag_y(1)][tag_z(1)];
301 tags[idx][2] = tag_x(2);
302 tags[idx][3] = tag_x(3);
303 }
else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 0) {
306 tags[idx][1] = edge_y[tag_x(1)][tag_z(1)];
307 tags[idx][2] = tag_y(2);
308 tags[idx][3] = tag_y(3);
309 }
else if (tag_x(0) == 0 && tag_y(0) == 0 && tag_z(0) == 1) {
312 tags[idx][1] = edge_z[tag_x(1)][tag_y(1)];
313 tags[idx][2] = tag_z(2);
314 tags[idx][3] = tag_z(3);
315 }
else if (tag_x(0) == 0 && tag_y(0) == 1 && tag_z(0) == 1) {
318 tags[idx][1] = face_yz[tag_x(1)];
319 tags[idx][2] = tag_y(2) + tag_y(3)*tag_z(2);
320 tags[idx][3] = tag_y(3)*tag_z(3);
321 }
else if (tag_x(0) == 1 && tag_y(0) == 0 && tag_z(0) == 1) {
324 tags[idx][1] = face_xz[tag_y(1)];
325 tags[idx][2] = tag_x(2) + tag_x(3)*tag_z(2);
326 tags[idx][3] = tag_x(3)*tag_z(3);
327 }
else if (tag_x(0) == 1 && tag_y(0) == 1 && tag_z(0) == 0) {
330 tags[idx][1] = face_xy[tag_z(1)];
331 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2);
332 tags[idx][3] = tag_x(3)*tag_y(3);
337 tags[idx][2] = tag_x(2) + tag_x(3)*tag_y(2) + tag_x(3)*tag_y(3)*tag_z(2);
338 tags[idx][3] = tag_x(3)*tag_y(3)*tag_z(3);
349 this->setOrdinalTagData(this->tagToOrdinal_,
352 this->basisCardinality_,
360 Kokkos::DynRankView<typename ScalarViewType::value_type,typename DT::execution_space::array_layout,Kokkos::HostSpace>
361 dofCoordsHost(
"dofCoordsHost", this->basisCardinality_, spaceDim);
363 Kokkos::DynRankView<typename ScalarViewType::value_type,DT>
364 dofCoordsLine(
"dofCoordsLine", cardLine, 1);
367 auto dofCoordsLineHost = Kokkos::create_mirror_view(dofCoordsLine);
368 Kokkos::deep_copy(dofCoordsLineHost, dofCoordsLine);
370 ordinal_type idx = 0;
371 for (
auto k=0;k<cardLine;++k) {
372 for (ordinal_type j=0;j<cardLine;++j) {
373 for (ordinal_type i=0;i<cardLine;++i,++idx) {
374 dofCoordsHost(idx,0) = dofCoordsLineHost(i,0);
375 dofCoordsHost(idx,1) = dofCoordsLineHost(j,0);
376 dofCoordsHost(idx,2) = dofCoordsLineHost(k,0);
382 this->dofCoords_ = Kokkos::create_mirror_view(
typename DT::memory_space(), dofCoordsHost);
383 Kokkos::deep_copy(this->dofCoords_, dofCoordsHost);
386 template<
typename DT,
typename OT,
typename PT>
389 ordinal_type& perTeamSpaceSize,
390 ordinal_type& perThreadSpaceSize,
392 const EOperator operatorType)
const {
394 perTeamSpaceSize = 0;
395 perThreadSpaceSize = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*
sizeof(
typename BasisBase::scalarType);
398 template<
typename DT,
typename OT,
typename PT>
399 KOKKOS_INLINE_FUNCTION
402 OutputViewType outputValues,
403 const PointViewType inputPoints,
404 const EOperator operatorType,
405 const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
406 const typename DT::execution_space::scratch_memory_space & scratchStorage,
407 const ordinal_type subcellDim,
408 const ordinal_type subcellOrdinal)
const {
410 INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
411 ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
413 const int numPoints = inputPoints.extent(0);
414 using ScalarType =
typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
415 using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
416 ordinal_type sizePerPoint = 4*this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
417 WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
418 using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
420 switch(operatorType) {
422 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
423 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
424 const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
425 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
430 Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
431 auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() );
432 const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() );
433 WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
434 Impl::Basis_HGRAD_HEX_Cn_FEM::Serial<OPERATOR_GRAD>::getValues( output, input, work, this->vinv_ );
438 INTREPID2_TEST_FOR_ABORT(
true,
439 ">>> ERROR (Basis_HGRAD_TET_Cn_FEM): getValues not implemented for this operator");
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
ordinal_type getCardinality() const
Returns cardinality of the basis.
ScalarTraits< pointValueType >::scalar_type scalarType
Scalar type for point values.
virtual void getValues(const ExecutionSpace &space, OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
See Intrepid2::Basis_HGRAD_HEX_Cn_FEM.
virtual void getScratchSpaceSize(ordinal_type &perTeamSpaceSize, ordinal_type &perThreadSpaceSize, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Return the size of the scratch space, in bytes, needed for using the team-level implementation of get...
Basis_HGRAD_HEX_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
virtual void getDofCoords(ScalarViewType dofCoords) const override
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
Implementation of the locally H(grad)-compatible FEM basis of variable order on the [-1...
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.