Intrepid2
Intrepid2_HCURL_TRI_In_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 
16 #ifndef __INTREPID2_HCURL_TRI_IN_FEM_DEF_HPP__
17 #define __INTREPID2_HCURL_TRI_IN_FEM_DEF_HPP__
18 
21 
22 namespace Intrepid2 {
23 
24  // -------------------------------------------------------------------------------------
25 
26  namespace Impl {
27 
28  template<EOperator OpType>
29  template<typename OutputViewType,
30  typename InputViewType,
31  typename WorkViewType,
32  typename VinvViewType>
33  KOKKOS_INLINE_FUNCTION
34  void
35  Basis_HCURL_TRI_In_FEM::Serial<OpType>::
36  getValues( OutputViewType output,
37  const InputViewType input,
38  WorkViewType work,
39  const VinvViewType coeffs ) {
40 
41  constexpr ordinal_type spaceDim = 2;
42  const ordinal_type
43  cardPn = coeffs.extent(0)/spaceDim,
44  card = coeffs.extent(1),
45  npts = input.extent(0);
46 
47  // compute order
48  ordinal_type order = 0;
49  for (ordinal_type p=0;p<=Parameters::MaxOrder;++p) {
50  if (card == CardinalityHCurlTri(p)) {
51  order = p;
52  break;
53  }
54  }
55 
56  typedef typename Kokkos::DynRankView<typename InputViewType::value_type, typename WorkViewType::memory_space> ViewType;
57  auto vcprop = Kokkos::common_view_alloc_prop(input);
58  auto ptr = work.data();
59 
60  switch (OpType) {
61  case OPERATOR_VALUE: {
62  const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts), dummyView;
63 
64  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::
65  Serial<OpType>::getValues(phis, input, dummyView, order);
66 
67  for (ordinal_type i=0;i<card;++i)
68  for (ordinal_type j=0;j<npts;++j)
69  for (ordinal_type d=0;d<spaceDim;++d) {
70  output.access(i,j,d) = 0.0;
71  for (ordinal_type k=0;k<cardPn;++k)
72  output.access(i,j,d) += coeffs(k+d*cardPn,i) * phis(k,j);
73  }
74  break;
75  }
76  case OPERATOR_CURL: {
77  const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, spaceDim);
78  ptr += card*npts*spaceDim*get_dimension_scalar(input);
79  const ViewType workView(Kokkos::view_wrap(ptr, vcprop), card, npts, spaceDim+1);
80 
81  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::
82  Serial<OPERATOR_GRAD>::getValues(phis, input, workView, order);
83 
84  for (ordinal_type i=0;i<card;++i)
85  for (ordinal_type j=0;j<npts;++j) {
86  output.access(i,j) = 0.0;
87  for (ordinal_type k=0; k<cardPn; ++k)
88  output.access(i,j) += - coeffs(k,i)*phis(k,j,1) // - dy of x component
89  + coeffs(k+cardPn,i)*phis(k,j,0); // dx of y component
90  }
91  break;
92  }
93  default: {
94  INTREPID2_TEST_FOR_ABORT( true,
95  ">>> ERROR (Basis_HCURL_TRI_In_FEM): Operator type not implemented");
96  }
97  }
98  }
99 
100  template<typename DT, ordinal_type numPtsPerEval,
101  typename outputValueValueType, class ...outputValueProperties,
102  typename inputPointValueType, class ...inputPointProperties,
103  typename vinvValueType, class ...vinvProperties>
104  void
105  Basis_HCURL_TRI_In_FEM::
106  getValues( const typename DT::execution_space& space,
107  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
108  const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
109  const Kokkos::DynRankView<vinvValueType, vinvProperties...> coeffs,
110  const EOperator operatorType) {
111  typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
112  typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
113  typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
114  typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
115 
116  // loopSize corresponds to cardinality
117  const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
118  const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
119  const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
120  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(space, 0, loopSize);
121 
122  typedef typename inputPointViewType::value_type inputPointType;
123 
124  const ordinal_type cardinality = outputValues.extent(0);
125  const ordinal_type spaceDim = 2;
126 
127  auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
128  typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
129 
130  switch (operatorType) {
131  case OPERATOR_VALUE: {
132  workViewType work(Kokkos::view_alloc(space, "Basis_HCURL_TRI_In_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0));
133  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
134  OPERATOR_VALUE,numPtsPerEval> FunctorType;
135  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, coeffs, work) );
136  break;
137  }
138  case OPERATOR_CURL: {
139  workViewType work(Kokkos::view_alloc(space, "Basis_HCURL_TRI_In_FEM::getValues::work", vcprop), cardinality*(2*spaceDim+1), inputPoints.extent(0));
140  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
141  OPERATOR_CURL,numPtsPerEval> FunctorType;
142  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, coeffs, work) );
143  break;
144  }
145  default: {
146  INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
147  ">>> ERROR (Basis_HCURL_TRI_In_FEM): Operator type not implemented" );
148  }
149  }
150  }
151  }
152 
153  // -------------------------------------------------------------------------------------
154  template<typename DT, typename OT, typename PT>
156  Basis_HCURL_TRI_In_FEM( const ordinal_type order,
157  const EPointType pointType ) {
158 
159  constexpr ordinal_type spaceDim = 2;
160  this->basisCardinality_ = CardinalityHCurlTri(order);
161  this->basisDegree_ = order; // small n
162  this->basisCellTopologyKey_ = shards::Triangle<3>::key;
163  this->basisType_ = BASIS_FEM_LAGRANGIAN;
164  this->basisCoordinates_ = COORDINATES_CARTESIAN;
165  this->functionSpace_ = FUNCTION_SPACE_HCURL;
166  pointType_ = (pointType == POINTTYPE_DEFAULT) ? POINTTYPE_EQUISPACED : pointType;
167 
168  const ordinal_type card = this->basisCardinality_;
169 
170  const ordinal_type cardPn = Intrepid2::getPnCardinality<spaceDim>(order); // dim of (P_{n}) -- smaller space
171  const ordinal_type cardPnm1 = Intrepid2::getPnCardinality<spaceDim>(order-1); // dim of (P_{n-1}) -- smaller space
172  const ordinal_type cardPnm2 = Intrepid2::getPnCardinality<spaceDim>(order-2); // dim of (P_{n-2}) -- smaller space
173  const ordinal_type cardVecPn = spaceDim*cardPn; // dim of (P_{n})^2 -- larger space
174  const ordinal_type cardVecPnm1 = spaceDim*cardPnm1; // dim of (P_{n-1})^2 -- smaller space
175 
176  // Note: the only reason why equispaced can't support higher order than Parameters::MaxOrder appears to be the fact that the tags below get stored into a fixed-length array.
177  // TODO: relax the maximum order requirement by setting up tags in a different container, perhaps directly into an OrdinalTypeArray1DHost (tagView, below). (As of this writing (1/25/22), looks like other nodal bases do this in a similar way -- those should be fixed at the same time; maybe search for Parameters::MaxOrder.)
178  INTREPID2_TEST_FOR_EXCEPTION( order > Parameters::MaxOrder, std::invalid_argument, "polynomial order exceeds the max supported by this class");
179 
180  // Basis-dependent initializations
181  constexpr ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
182  constexpr ordinal_type maxCard = CardinalityHCurlTri(Parameters::MaxOrder);
183  ordinal_type tags[maxCard][tagSize];
184 
185  // points are computed in the host and will be copied
186  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
187  dofCoords("Hcurl::Tri::In::dofCoords", card, spaceDim);
188 
189  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
190  coeffs("Hcurl::Tri::In::coeffs", cardVecPn, card);
191 
192  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
193  dofCoeffs("Hcurl::Tri::In::dofCoeffs", card, spaceDim);
194 
195  // first, need to project the basis for RT space onto the
196  // orthogonal basis of degree n
197  // get coefficients of PkHx
198 
199  const ordinal_type lwork = card*card;
200  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
201  V1("Hcurl::Tri::In::V1", cardVecPn, card);
202 
203  // basis for the space is
204  // { (phi_i,0) }_{i=0}^{cardPnm1-1} ,
205  // { (0,phi_i) }_{i=0}^{cardPnm1-1} ,
206  // { (x,y) \times phi_i}_{i=cardPnm2}^{cardPnm1-1}
207  // { (x,y) \times phi = (y phi , -x \phi)
208  // columns of V1 are expansion of this basis in terms of the basis
209  // for P_{n}^2
210 
211  // these two loops get the first two sets of basis functions
212  for (ordinal_type i=0;i<cardPnm1;i++)
213  for (ordinal_type d=0;d<spaceDim;d++)
214  V1(d*cardPn+i,d*cardPnm1+i) = 1.0;
215 
216 
217  // now I need to integrate { (x,y) \times phi } against the big basis
218  // first, get a cubature rule.
220  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> cubPoints("Hcurl::Tri::In::cubPoints", myCub.getNumPoints() , spaceDim );
221  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> cubWeights("Hcurl::Tri::In::cubWeights", myCub.getNumPoints() );
222  myCub.getCubature( cubPoints , cubWeights );
223 
224  // tabulate the scalar orthonormal basis at cubature points
225  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> phisAtCubPoints("Hcurl::Tri::In::phisAtCubPoints", cardPn , myCub.getNumPoints() );
226  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::getValues<Kokkos::HostSpace::execution_space,Parameters::MaxNumPtsPerBasisEval>(typename Kokkos::HostSpace::execution_space{},
227  phisAtCubPoints,
228  cubPoints,
229  order,
230  OPERATOR_VALUE);
231 
232  // now do the integration
233  for (ordinal_type i=0;i<order;i++) {
234  for (ordinal_type j=0;j<cardPn;j++) { // int (x,y) phi_i \cdot (phi_j,phi_{j+cardPn})
235  for (ordinal_type k=0;k<myCub.getNumPoints();k++) {
236  V1(j,cardVecPnm1+i) -=
237  cubWeights(k) * cubPoints(k,1)
238  * phisAtCubPoints(cardPnm2+i,k)
239  * phisAtCubPoints(j,k);
240  V1(j+cardPn,cardVecPnm1+i) +=
241  cubWeights(k) * cubPoints(k,0)
242  * phisAtCubPoints(cardPnm2+i,k)
243  * phisAtCubPoints(j,k);
244  }
245  }
246  }
247 
248  // next, apply the RT nodes (rows) to the basis for (P_n)^2 (columns)
249  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
250  V2("Hcurl::Tri::In::V2", card ,cardVecPn);
251 
252  const shards::CellTopology cellTopo(shards::getCellTopologyData<shards::Triangle<3>>());
253  const ordinal_type numEdges = cellTopo.getEdgeCount();
254 
255  shards::CellTopology edgeTopo(shards::getCellTopologyData<shards::Line<2> >() );
256 
257  const int numPtsPerEdge = PointTools::getLatticeSize( edgeTopo ,
258  order+1 ,
259  1 );
260 
261  // first numEdges * degree nodes are tangents at each edge
262  // get the points on the line
263  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> linePts("Hcurl::Tri::In::linePts", numPtsPerEdge , 1 );
264 
265  // construct lattice
266  const ordinal_type offset = 1;
267  PointTools::getLattice( linePts,
268  edgeTopo,
269  order+1, offset,
270  pointType_ );
271 
272  // holds the image of the line points
273  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> edgePts("Hcurl::Tri::In::edgePts", numPtsPerEdge , spaceDim );
274  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> phisAtEdgePoints("Hcurl::Tri::In::phisAtEdgePoints", cardPn , numPtsPerEdge );
275  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace> edgeTan("Hcurl::Tri::In::edgeTan", spaceDim );
276 
277  // these are tangents scaled by the appropriate edge lengths.
278  for (ordinal_type edge=0;edge<numEdges;edge++) { // loop over edges
280  edge ,
281  cellTopo );
282 
284  linePts ,
285  1 ,
286  edge ,
287  cellTopo );
288 
289  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::getValues<Kokkos::HostSpace::execution_space,Parameters::MaxNumPtsPerBasisEval>(typename Kokkos::HostSpace::execution_space{},
290  phisAtEdgePoints,
291  edgePts,
292  order,
293  OPERATOR_VALUE);
294 
295  // loop over points (rows of V2)
296  for (ordinal_type j=0;j<numPtsPerEdge;j++) {
297 
298  const ordinal_type i_card = numPtsPerEdge*edge+j;
299 
300  // loop over orthonormal basis functions (columns of V2)
301  for (ordinal_type k=0;k<cardPn;k++) {
302  V2(i_card,k) = edgeTan(0) * phisAtEdgePoints(k,j);
303  V2(i_card,k+cardPn) = edgeTan(1) * phisAtEdgePoints(k,j);
304  }
305 
306 
307  //save dof coordinates
308  for(ordinal_type k=0; k<spaceDim; ++k) {
309  dofCoords(i_card,k) = edgePts(j,k);
310  dofCoeffs(i_card,k) = edgeTan(k);
311  }
312 
313  tags[i_card][0] = 1; // edge dof
314  tags[i_card][1] = edge; // edge id
315  tags[i_card][2] = j; // local dof id
316  tags[i_card][3] = numPtsPerEdge; // total edge dof
317 
318  }
319 
320 
321  }
322 
323  // remaining nodes are x- and y- components at internal points (this code is same as HDIV).
324  //These are evaluated at the interior of a lattice of degree + 1, For then
325  // the degree == 1 space corresponds classicaly to RT0 and so gets
326  // no internal nodes, and degree == 2 corresponds to RT1 and needs
327  // one internal node per vector component.
328  const ordinal_type numPtsPerCell = PointTools::getLatticeSize( cellTopo ,
329  order + 1 ,
330  1 );
331 
332  if (numPtsPerCell > 0) {
333  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
334  internalPoints( "Hcurl::Tri::In::internalPoints", numPtsPerCell , spaceDim );
335  PointTools::getLattice( internalPoints ,
336  cellTopo ,
337  order + 1 ,
338  1 ,
339  pointType_ );
340 
341  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
342  phisAtInternalPoints("Hcurl::Tri::In::phisAtInternalPoints", cardPn , numPtsPerCell );
343  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::getValues<Kokkos::HostSpace::execution_space,Parameters::MaxNumPtsPerBasisEval>(typename Kokkos::HostSpace::execution_space{},
344  phisAtInternalPoints,
345  internalPoints,
346  order,
347  OPERATOR_VALUE);
348 
349  // copy values into right positions of V2
350  for (ordinal_type j=0;j<numPtsPerCell;j++) {
351 
352  const ordinal_type i_card = numEdges*order+spaceDim*j;
353 
354  for (ordinal_type k=0;k<cardPn;k++) {
355  // x component
356  V2(i_card,k) = phisAtInternalPoints(k,j);
357  // y component
358  V2(i_card+1,cardPn+k) = phisAtInternalPoints(k,j);
359  }
360 
361  //save dof coordinates
362  for(ordinal_type d=0; d<spaceDim; ++d) {
363  for(ordinal_type dim=0; dim<spaceDim; ++dim) {
364  dofCoords(i_card+d,dim) = internalPoints(j,dim);
365  dofCoeffs(i_card+d,dim) = (d==dim);
366  }
367 
368  tags[i_card+d][0] = spaceDim; // elem dof
369  tags[i_card+d][1] = 0; // elem id
370  tags[i_card+d][2] = spaceDim*j+d; // local dof id
371  tags[i_card+d][3] = spaceDim*numPtsPerCell; // total vert dof
372  }
373  }
374  }
375 
376  // form Vandermonde matrix. Actually, this is the transpose of the VDM,
377  // so we transpose on copy below.
378  Kokkos::DynRankView<scalarType,Kokkos::LayoutLeft,Kokkos::HostSpace>
379  vmat("Hcurl::Tri::In::vmat", card, card),
380  work("Hcurl::Tri::In::work", lwork),
381  ipiv("Hcurl::Tri::In::ipiv", card);
382 
383  //vmat' = V2*V1;
384  for(ordinal_type i=0; i< card; ++i) {
385  for(ordinal_type j=0; j< card; ++j) {
386  scalarType s=0;
387  for(ordinal_type k=0; k< cardVecPn; ++k)
388  s += V2(i,k)*V1(k,j);
389  vmat(i,j) = s;
390  }
391  }
392 
393  ordinal_type info = 0;
394  Teuchos::LAPACK<ordinal_type,scalarType> lapack;
395 
396  lapack.GETRF(card, card,
397  vmat.data(), vmat.stride_1(),
398  (ordinal_type*)ipiv.data(),
399  &info);
400 
401  INTREPID2_TEST_FOR_EXCEPTION( info != 0,
402  std::runtime_error ,
403  ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_In_FEM) lapack.GETRF returns nonzero info." );
404 
405  lapack.GETRI(card,
406  vmat.data(), vmat.stride_1(),
407  (ordinal_type*)ipiv.data(),
408  work.data(), lwork,
409  &info);
410 
411  INTREPID2_TEST_FOR_EXCEPTION( info != 0,
412  std::runtime_error ,
413  ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_In_FEM) lapack.GETRI returns nonzero info." );
414 
415  for (ordinal_type i=0;i<cardVecPn;++i)
416  for (ordinal_type j=0;j<card;++j){
417  scalarType s=0;
418  for(ordinal_type k=0; k< card; ++k)
419  s += V1(i,k)*vmat(k,j);
420  coeffs(i,j) = s;
421  }
422 
423  this->coeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), coeffs);
424  Kokkos::deep_copy(this->coeffs_ , coeffs);
425 
426  this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords);
427  Kokkos::deep_copy(this->dofCoords_, dofCoords);
428 
429  this->dofCoeffs_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoeffs);
430  Kokkos::deep_copy(this->dofCoeffs_, dofCoeffs);
431 
432 
433  // set tags
434  {
435  // Basis-dependent initializations
436  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
437  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
438  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
439 
440  OrdinalTypeArray1DHost tagView(&tags[0][0], card*tagSize);
441 
442  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
443  // tags are constructed on host
444  this->setOrdinalTagData(this->tagToOrdinal_,
445  this->ordinalToTag_,
446  tagView,
447  this->basisCardinality_,
448  tagSize,
449  posScDim,
450  posScOrd,
451  posDfOrd);
452  }
453  }
454 
455  template<typename DT, typename OT, typename PT>
456  void
458  ordinal_type& perTeamSpaceSize,
459  ordinal_type& perThreadSpaceSize,
460  const PointViewType inputPoints,
461  const EOperator operatorType) const {
462  perTeamSpaceSize = 0;
463  ordinal_type scalarWorkViewExtent = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_;
464  perThreadSpaceSize = scalarWorkViewExtent*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
465  }
466 
467  template<typename DT, typename OT, typename PT>
468  KOKKOS_INLINE_FUNCTION
469  void
471  OutputViewType outputValues,
472  const PointViewType inputPoints,
473  const EOperator operatorType,
474  const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
475  const typename DT::execution_space::scratch_memory_space & scratchStorage,
476  const ordinal_type subcellDim,
477  const ordinal_type subcellOrdinal) const {
478 
479  INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
480  ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_In_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
481 
482  const int numPoints = inputPoints.extent(0);
483  using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
484  using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
485  ordinal_type scalarSizePerPoint = (operatorType == OPERATOR_VALUE) ? this->basisCardinality_ : 5*this->basisCardinality_;
486  ordinal_type sizePerPoint = scalarSizePerPoint*get_dimension_scalar(inputPoints);
487  WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
488  using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
489 
490  switch(operatorType) {
491  case OPERATOR_VALUE:
492  Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
493  auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
494  const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
495  WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
496  Impl::Basis_HCURL_TRI_In_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, this->coeffs_ );
497  });
498  break;
499  case OPERATOR_CURL:
500  Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
501  auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type(pt,pt+1), Kokkos::ALL() );
502  const auto input = Kokkos::subview( inputPoints, range_type(pt,pt+1), Kokkos::ALL() );
503  WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
504  Impl::Basis_HCURL_TRI_In_FEM::Serial<OPERATOR_CURL>::getValues( output, input, work, this->coeffs_ );
505  });
506  break;
507  default: {
508  INTREPID2_TEST_FOR_ABORT( true,
509  ">>> ERROR (Basis_HCURL_TRI_In_FEM): getValues not implemented for this operator");
510  }
511  }
512  }
513 
514 } // namespace Intrepid2
515 
516 #endif
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.
Header file for the Intrepid2::Basis_HGRAD_TRI_Cn_FEM_ORTH class.
virtual void getCubature(PointViewType cubPoints, weightViewType cubWeights) const override
Returns cubature points and weights (return arrays must be pre-sized/pre-allocated).
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
Basis_HCURL_TRI_In_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.
static void getLattice(Kokkos::DynRankView< pointValueType, pointProperties...> points, const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0, const EPointType pointType=POINTTYPE_EQUISPACED)
Computes a lattice of points of a given order on a reference simplex, quadrilateral or hexahedron (cu...
virtual ordinal_type getNumPoints() const override
Returns the number of cubature points.
static void getReferenceEdgeTangent(RefEdgeTangentViewType refEdgeTangent, const ordinal_type edgeOrd, const shards::CellTopology parentCell)
Computes constant tangent vectors to edges of 2D or 3D reference cells.
virtual void getScratchSpaceSize(ordinal_type &perTeamSpaceSize, ordinal_type &perThreadSpaceSize, const PointViewType inputPointsconst, 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...
Header file for the Intrepid2::CubatureDirectTrisymPos class.
static void mapToReferenceSubcell(refSubcellViewType refSubcellPoints, const paramPointViewType paramPoints, const ordinal_type subcellDim, const ordinal_type subcellOrd, const shards::CellTopology parentCell)
Computes parameterization maps of 1- and 2-subcells of reference cells.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
ScalarTraits< pointValueType >::scalar_type scalarType
Scalar type for point values.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.
static ordinal_type getLatticeSize(const shards::CellTopology cellType, const ordinal_type order, const ordinal_type offset=0)
Computes the number of points in a lattice of a given order on a simplex (currently disabled for othe...