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