Intrepid2
Intrepid2_HVOL_TRI_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 
15 #ifndef __INTREPID2_HVOL_TRI_CN_FEM_DEF_HPP__
16 #define __INTREPID2_HVOL_TRI_CN_FEM_DEF_HPP__
17 
19 
20 namespace Intrepid2 {
21 
22 // -------------------------------------------------------------------------------------
23 namespace Impl {
24 
25  template<EOperator OpType>
26  template<typename OutputViewType,
27  typename InputViewType,
28  typename WorkViewType,
29  typename VinvViewType>
30  KOKKOS_INLINE_FUNCTION
31  void
32  Basis_HVOL_TRI_Cn_FEM::Serial<OpType>::
33  getValues( OutputViewType output,
34  const InputViewType input,
35  WorkViewType work,
36  const VinvViewType vinv ) {
37 
38  constexpr ordinal_type spaceDim = 2;
39  const ordinal_type
40  card = vinv.extent(0),
41  npts = input.extent(0);
42 
43  // compute order
44  ordinal_type order = 0;
45  for (ordinal_type p=0;p<=Parameters::MaxOrder;++p) {
46  if (card == Intrepid2::getPnCardinality<spaceDim>(p) ) {
47  order = p;
48  break;
49  }
50  }
51 
52  typedef typename Kokkos::DynRankView<typename InputViewType::value_type, typename WorkViewType::memory_space> ViewType;
53  auto vcprop = Kokkos::common_view_alloc_prop(input);
54  auto ptr = work.data();
55 
56  switch (OpType) {
57  case OPERATOR_VALUE: {
58  const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts);
59  ViewType dummyView;
60 
61  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::
62  Serial<OpType>::getValues(phis, input, dummyView, order);
63 
64  for (ordinal_type i=0;i<card;++i)
65  for (ordinal_type j=0;j<npts;++j) {
66  output.access(i,j) = 0.0;
67  for (ordinal_type k=0;k<card;++k)
68  output.access(i,j) += vinv(k,i)*phis.access(k,j);
69  }
70  break;
71  }
72  case OPERATOR_GRAD:
73  case OPERATOR_D1: {
74  const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, spaceDim);
75  ptr += card*npts*spaceDim*get_dimension_scalar(input);
76  const ViewType workView(Kokkos::view_wrap(ptr, vcprop), card, npts, spaceDim+1);
77  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::
78  Serial<OpType>::getValues(phis, input, workView, order);
79 
80  for (ordinal_type i=0;i<card;++i)
81  for (ordinal_type j=0;j<npts;++j)
82  for (ordinal_type k=0;k<spaceDim;++k) {
83  output.access(i,j,k) = 0.0;
84  for (ordinal_type l=0;l<card;++l)
85  output.access(i,j,k) += vinv(l,i)*phis.access(l,j,k);
86  }
87  break;
88  }
89  case OPERATOR_D2:
90  case OPERATOR_D3:
91  case OPERATOR_D4:
92  case OPERATOR_D5:
93  case OPERATOR_D6:
94  case OPERATOR_D7:
95  case OPERATOR_D8:
96  case OPERATOR_D9:
97  case OPERATOR_D10: {
98  const ordinal_type dkcard = getDkCardinality<OpType,spaceDim>(); //(orDn + 1);
99  const ViewType phis(Kokkos::view_wrap(ptr, vcprop), card, npts, dkcard);
100  ViewType dummyView;
101 
102  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::
103  Serial<OpType>::getValues(phis, input, dummyView, order);
104 
105  for (ordinal_type i=0;i<card;++i)
106  for (ordinal_type j=0;j<npts;++j)
107  for (ordinal_type k=0;k<dkcard;++k) {
108  output.access(i,j,k) = 0.0;
109  for (ordinal_type l=0;l<card;++l)
110  output.access(i,j,k) += vinv(l,i)*phis.access(l,j,k);
111  }
112  break;
113  }
114  default: {
115  INTREPID2_TEST_FOR_ABORT( true,
116  ">>> ERROR (Basis_HVOL_TRI_Cn_FEM): Operator type not implemented");
117  }
118  }
119 }
120 
121 template<typename DT, ordinal_type numPtsPerEval,
122 typename outputValueValueType, class ...outputValueProperties,
123 typename inputPointValueType, class ...inputPointProperties,
124 typename vinvValueType, class ...vinvProperties>
125 void
126 Basis_HVOL_TRI_Cn_FEM::
127 getValues( Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValues,
128  const Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPoints,
129  const Kokkos::DynRankView<vinvValueType, vinvProperties...> vinv,
130  const EOperator operatorType) {
131  typedef Kokkos::DynRankView<outputValueValueType,outputValueProperties...> outputValueViewType;
132  typedef Kokkos::DynRankView<inputPointValueType, inputPointProperties...> inputPointViewType;
133  typedef Kokkos::DynRankView<vinvValueType, vinvProperties...> vinvViewType;
134  typedef typename ExecSpace<typename inputPointViewType::execution_space,typename DT::execution_space>::ExecSpaceType ExecSpaceType;
135 
136  // loopSize corresponds to cardinality
137  const auto loopSizeTmp1 = (inputPoints.extent(0)/numPtsPerEval);
138  const auto loopSizeTmp2 = (inputPoints.extent(0)%numPtsPerEval != 0);
139  const auto loopSize = loopSizeTmp1 + loopSizeTmp2;
140  Kokkos::RangePolicy<ExecSpaceType,Kokkos::Schedule<Kokkos::Static> > policy(0, loopSize);
141 
142  typedef typename inputPointViewType::value_type inputPointType;
143 
144  const ordinal_type cardinality = outputValues.extent(0);
145  const ordinal_type spaceDim = 2;
146 
147  auto vcprop = Kokkos::common_view_alloc_prop(inputPoints);
148  typedef typename Kokkos::DynRankView< inputPointType, typename inputPointViewType::memory_space> workViewType;
149 
150  switch (operatorType) {
151  case OPERATOR_VALUE: {
152  workViewType work(Kokkos::view_alloc("Basis_HVOL_TRI_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0));
153  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
154  OPERATOR_VALUE,numPtsPerEval> FunctorType;
155  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
156  break;
157  }
158  case OPERATOR_GRAD:
159  case OPERATOR_D1: {
160  workViewType work(Kokkos::view_alloc("Basis_HVOL_TRI_Cn_FEM::getValues::work", vcprop), cardinality*(2*spaceDim+1), inputPoints.extent(0));
161  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
162  OPERATOR_D1,numPtsPerEval> FunctorType;
163  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
164  break;
165  }
166  case OPERATOR_D2: {
167  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType, workViewType,
168  OPERATOR_D2,numPtsPerEval> FunctorType;
169  workViewType work(Kokkos::view_alloc("Basis_HVOL_TRI_Cn_FEM::getValues::work", vcprop), cardinality*outputValues.extent(2), inputPoints.extent(0));
170  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
171  break;
172  }
173  /* case OPERATOR_D3: {
174  typedef Functor<outputValueViewType,inputPointViewType,vinvViewType,
175  OPERATOR_D3,numPtsPerEval> FunctorType;
176  workViewType work(Kokkos::view_alloc("Basis_HVOL_TRI_Cn_FEM::getValues::work", vcprop), cardinality, inputPoints.extent(0), outputValues.extent(2));
177  Kokkos::parallel_for( policy, FunctorType(outputValues, inputPoints, vinv, work) );
178  break;
179  }*/
180  default: {
181  INTREPID2_TEST_FOR_EXCEPTION( true , std::invalid_argument,
182  ">>> ERROR (Basis_HVOL_TRI_Cn_FEM): Operator type not implemented" );
183  }
184  }
185 }
186 }
187 
188 // -------------------------------------------------------------------------------------
189 template<typename DT, typename OT, typename PT>
191 Basis_HVOL_TRI_Cn_FEM( const ordinal_type order,
192  const EPointType pointType ) {
193 
194  constexpr ordinal_type spaceDim = 2;
195 
196  this->pointType_ = (pointType == POINTTYPE_DEFAULT) ? POINTTYPE_EQUISPACED : pointType;
197  this->basisCardinality_ = Intrepid2::getPnCardinality<spaceDim>(order); // bigN
198  this->basisDegree_ = order; // small n
199  this->basisCellTopologyKey_ = shards::Triangle<3>::key;
200  this->basisType_ = BASIS_FEM_LAGRANGIAN;
201  this->basisCoordinates_ = COORDINATES_CARTESIAN;
202  this->functionSpace_ = FUNCTION_SPACE_HVOL;
203 
204  const ordinal_type card = this->basisCardinality_;
205 
206  // points are computed in the host and will be copied
207  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
208  dofCoords("HVOL::Tri::Cn::dofCoords", card, spaceDim);
209 
210  // construct lattice (only internal nodes for HVOL element)
211  const ordinal_type offset = 1;
212  const shards::CellTopology cellTopo(shards::getCellTopologyData<shards::Triangle<3> >());
213  PointTools::getLattice( dofCoords,
214  cellTopo,
215  order+spaceDim+offset, offset,
216  this->pointType_ );
217 
218  this->dofCoords_ = Kokkos::create_mirror_view(typename DT::memory_space(), dofCoords);
219  Kokkos::deep_copy(this->dofCoords_, dofCoords);
220 
221  // form Vandermonde matrix. Actually, this is the transpose of the VDM,
222  // so we transpose on copy below.
223  const ordinal_type lwork = card*card;
224  Kokkos::DynRankView<scalarType,Kokkos::LayoutLeft,Kokkos::HostSpace>
225  vmat("HVOL::Tri::Cn::vmat", card, card),
226  work("HVOL::Tri::Cn::work", lwork),
227  ipiv("HVOL::Tri::Cn::ipiv", card);
228 
229  Impl::Basis_HGRAD_TRI_Cn_FEM_ORTH::getValues<Kokkos::HostSpace::execution_space,Parameters::MaxNumPtsPerBasisEval>(typename Kokkos::HostSpace::execution_space{},
230  vmat,
231  dofCoords,
232  order,
233  OPERATOR_VALUE);
234 
235  ordinal_type info = 0;
236  Teuchos::LAPACK<ordinal_type,scalarType> lapack;
237 
238  lapack.GETRF(card, card,
239  vmat.data(), vmat.stride_1(),
240  (ordinal_type*)ipiv.data(),
241  &info);
242 
243  INTREPID2_TEST_FOR_EXCEPTION( info != 0,
244  std::runtime_error ,
245  ">>> ERROR: (Intrepid2::Basis_HVOL_TRI_Cn_FEM) lapack.GETRF returns nonzero info." );
246 
247  lapack.GETRI(card,
248  vmat.data(), vmat.stride_1(),
249  (ordinal_type*)ipiv.data(),
250  work.data(), lwork,
251  &info);
252 
253  INTREPID2_TEST_FOR_EXCEPTION( info != 0,
254  std::runtime_error ,
255  ">>> ERROR: (Intrepid2::Basis_HVOL_TRI_Cn_FEM) lapack.GETRI returns nonzero info." );
256 
257  // create host mirror
258  Kokkos::DynRankView<scalarType,typename DT::execution_space::array_layout,Kokkos::HostSpace>
259  vinv("HVOL::Line::Cn::vinv", card, card);
260 
261  for (ordinal_type i=0;i<card;++i)
262  for (ordinal_type j=0;j<card;++j)
263  vinv(i,j) = vmat(j,i);
264 
265  this->vinv_ = Kokkos::create_mirror_view(typename DT::memory_space(), vinv);
266  Kokkos::deep_copy(this->vinv_ , vinv);
267 
268  // initialize tags
269  {
270  // Basis-dependent initializations
271  constexpr ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
272  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
273  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
274  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
275 
276  constexpr ordinal_type maxCard = Intrepid2::getPnCardinality<spaceDim, Parameters::MaxOrder>();
277  ordinal_type tags[maxCard][tagSize];
278 
279  const ordinal_type
280  numElemDof = this->basisCardinality_; //all the degrees of freedom are internal.
281 
282  ordinal_type elemId = 0;
283  for (ordinal_type i=0;i<this->basisCardinality_;++i) {
284  // elem
285  tags[i][0] = spaceDim; // intr dof
286  tags[i][1] = 0; // intr id
287  tags[i][2] = elemId++; // local dof id
288  tags[i][3] = numElemDof; // total vert dof
289  }
290 
291  OrdinalTypeArray1DHost tagView(&tags[0][0], card*tagSize);
292 
293  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
294  // tags are constructed on host
295  this->setOrdinalTagData(this->tagToOrdinal_,
296  this->ordinalToTag_,
297  tagView,
298  this->basisCardinality_,
299  tagSize,
300  posScDim,
301  posScOrd,
302  posDfOrd);
303  }
304 }
305 
306  template<typename DT, typename OT, typename PT>
307  void
309  ordinal_type& perTeamSpaceSize,
310  ordinal_type& perThreadSpaceSize,
311  const PointViewType inputPoints,
312  const EOperator operatorType) const {
313  perTeamSpaceSize = 0;
314  perThreadSpaceSize = this->vinv_.extent(0)*get_dimension_scalar(inputPoints)*sizeof(typename BasisBase::scalarType);
315  }
316 
317  template<typename DT, typename OT, typename PT>
318  KOKKOS_INLINE_FUNCTION
319  void
321  OutputViewType outputValues,
322  const PointViewType inputPoints,
323  const EOperator operatorType,
324  const typename Kokkos::TeamPolicy<typename DT::execution_space>::member_type& team_member,
325  const typename DT::execution_space::scratch_memory_space & scratchStorage,
326  const ordinal_type subcellDim,
327  const ordinal_type subcellOrdinal) const {
328 
329  INTREPID2_TEST_FOR_ABORT( !((subcellDim == -1) && (subcellOrdinal == -1)),
330  ">>> ERROR: (Intrepid2::Basis_HVOL_TRI_Cn_FEM::getValues), The capability of selecting subsets of basis functions has not been implemented yet.");
331 
332  const int numPoints = inputPoints.extent(0);
333  using ScalarType = typename ScalarTraits<typename PointViewType::value_type>::scalar_type;
334  using WorkViewType = Kokkos::DynRankView< ScalarType,typename DT::execution_space::scratch_memory_space,Kokkos::MemoryTraits<Kokkos::Unmanaged> >;
335  auto sizePerPoint = this->vinv_.extent(0)*get_dimension_scalar(inputPoints);
336  WorkViewType workView(scratchStorage, sizePerPoint*team_member.team_size());
337  using range_type = Kokkos::pair<ordinal_type,ordinal_type>;
338  switch(operatorType) {
339  case OPERATOR_VALUE:
340  Kokkos::parallel_for (Kokkos::TeamThreadRange (team_member, numPoints), [=] (ordinal_type& pt) {
341  auto output = Kokkos::subview( outputValues, Kokkos::ALL(), range_type (pt,pt+1), Kokkos::ALL() );
342  const auto input = Kokkos::subview( inputPoints, range_type(pt, pt+1), Kokkos::ALL() );
343  WorkViewType work(workView.data() + sizePerPoint*team_member.team_rank(), sizePerPoint);
344  Impl::Basis_HVOL_TRI_Cn_FEM::Serial<OPERATOR_VALUE>::getValues( output, input, work, this->vinv_);
345  });
346  break;
347  default: {
348  INTREPID2_TEST_FOR_ABORT( true,
349  ">>> ERROR (Basis_HVOL_TRI_Cn_FEM): getValues not implemented for this operator");
350  }
351  }
352  }
353 
354 } // namespace Intrepid2
355 #endif
ScalarTraits< pointValueType >::scalar_type scalarType
Scalar type for point values.
Header file for the Intrepid2::Basis_HGRAD_TRI_Cn_FEM_ORTH class.
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
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 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...
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
static constexpr ordinal_type MaxOrder
The maximum reconstruction order.
Basis_HVOL_TRI_Cn_FEM(const ordinal_type order, const EPointType pointType=POINTTYPE_EQUISPACED)
Constructor.