Intrepid2
Intrepid2_LegendreBasis_HVOL_LINE.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_LegendreBasis_HVOL_LINE_h
16 #define Intrepid2_LegendreBasis_HVOL_LINE_h
17 
18 #include <Kokkos_DynRankView.hpp>
19 
20 #include <Intrepid2_config.h>
21 
22 // Sacado header that defines some fad sizing…
23 #ifdef HAVE_INTREPID2_SACADO
24 #include <KokkosExp_View_Fad.hpp>
25 #endif
26 
27 #include "Intrepid2_Basis.hpp"
30 
31 namespace Intrepid2
32 {
38  template<class DeviceType, class OutputScalar, class PointScalar,
39  class OutputFieldType, class InputPointsType>
41  {
42  using ExecutionSpace = typename DeviceType::execution_space;
43  using ScratchSpace = typename ExecutionSpace::scratch_memory_space;
44  using OutputScratchView = Kokkos::View<OutputScalar*,ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
45  using PointScratchView = Kokkos::View<PointScalar*, ScratchSpace,Kokkos::MemoryTraits<Kokkos::Unmanaged>>;
46 
47  using TeamPolicy = Kokkos::TeamPolicy<ExecutionSpace>;
48  using TeamMember = typename TeamPolicy::member_type;
49 
50  OutputFieldType output_; // F,P
51  InputPointsType inputPoints_; // P,D
52 
53  int polyOrder_;
54  int numFields_, numPoints_;
55 
56  EOperator op_;
57 
58  size_t fad_size_output_;
59 
60  Hierarchical_HVOL_LINE_Functor(OutputFieldType output, InputPointsType inputPoints,
61  int polyOrder, EOperator op)
62  : output_(output), inputPoints_(inputPoints), polyOrder_(polyOrder), op_(op),
63  fad_size_output_(getScalarDimensionForView(output))
64  {
65  numFields_ = output.extent_int(0);
66  numPoints_ = output.extent_int(1);
67  INTREPID2_TEST_FOR_EXCEPTION(numPoints_ != inputPoints.extent_int(0), std::invalid_argument, "point counts need to match!");
68  INTREPID2_TEST_FOR_EXCEPTION(numFields_ != polyOrder_+1, std::invalid_argument, "output field size does not match basis cardinality");
69  }
70 
71  KOKKOS_INLINE_FUNCTION
72  void operator()( const TeamMember & teamMember ) const
73  {
74  auto pointOrdinal = teamMember.league_rank();
75  OutputScratchView field_values_at_point;
76  if (fad_size_output_ > 0) {
77  field_values_at_point = OutputScratchView(teamMember.team_shmem(), numFields_, fad_size_output_);
78  }
79  else {
80  field_values_at_point = OutputScratchView(teamMember.team_shmem(), numFields_);
81  }
82 
83  const PointScalar x = inputPoints_(pointOrdinal,0);
84 
85  switch (op_)
86  {
87  case OPERATOR_VALUE:
88  Polynomials::legendreValues(field_values_at_point, polyOrder_, x);
89 
90  // note that because legendreValues determines field values recursively, there is not much
91  // opportunity at that level for further parallelism
92  break;
93  case OPERATOR_GRAD:
94  case OPERATOR_D1:
95  case OPERATOR_D2:
96  case OPERATOR_D3:
97  case OPERATOR_D4:
98  case OPERATOR_D5:
99  case OPERATOR_D6:
100  case OPERATOR_D7:
101  case OPERATOR_D8:
102  case OPERATOR_D9:
103  case OPERATOR_D10:
104  {
105  auto derivativeOrder = getOperatorOrder(op_);
106  Polynomials::legendreDerivativeValues(field_values_at_point, polyOrder_, x, derivativeOrder);
107  break;
108  }
109  default:
110  // unsupported operator type
111  device_assert(false);
112  }
113  // copy the values into the output container
114  for (int fieldOrdinal=0; fieldOrdinal<numFields_; fieldOrdinal++)
115  {
116  output_.access(fieldOrdinal,pointOrdinal,0) = field_values_at_point(fieldOrdinal);
117  }
118  }
119 
120  // Provide the shared memory capacity.
121  // This function takes the team_size as an argument,
122  // which allows team_size-dependent allocations.
123  size_t team_shmem_size (int team_size) const
124  {
125  // we want to use shared memory to create a fast buffer that we can use for basis computations
126  size_t shmem_size = 0;
127  if (fad_size_output_ > 0)
128  shmem_size += OutputScratchView::shmem_size(numFields_, fad_size_output_);
129  else
130  shmem_size += OutputScratchView::shmem_size(numFields_);
131 
132  return shmem_size;
133  }
134  };
135 
147  template<typename DeviceType,
148  typename OutputScalar = double,
149  typename PointScalar = double>
151  : public Basis<DeviceType,OutputScalar,PointScalar>
152  {
153  public:
156 
157  using typename BasisBase::OrdinalTypeArray1DHost;
158  using typename BasisBase::OrdinalTypeArray2DHost;
159 
160  using typename BasisBase::OutputViewType;
161  using typename BasisBase::PointViewType;
162  using typename BasisBase::ScalarViewType;
163 
164  using typename BasisBase::ExecutionSpace;
165 
166  protected:
167  int polyOrder_; // the maximum order of the polynomial
168  EPointType pointType_;
169  public:
178  LegendreBasis_HVOL_LINE(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
179  :
180  polyOrder_(polyOrder),
181  pointType_(pointType)
182  {
183  INTREPID2_TEST_FOR_EXCEPTION(pointType!=POINTTYPE_DEFAULT,std::invalid_argument,"PointType not supported");
184  this->basisCardinality_ = polyOrder+1;
185  this->basisDegree_ = polyOrder;
186  this->basisCellTopologyKey_ = shards::Line<2>::key;
187  this->basisType_ = BASIS_FEM_HIERARCHICAL;
188  this->basisCoordinates_ = COORDINATES_CARTESIAN;
189  this->functionSpace_ = FUNCTION_SPACE_HVOL;
190 
191  const int degreeLength = 1;
192  this->fieldOrdinalPolynomialDegree_ = OrdinalTypeArray2DHost("Integrated Legendre H(grad) line polynomial degree lookup", this->basisCardinality_, degreeLength);
193  this->fieldOrdinalH1PolynomialDegree_ = OrdinalTypeArray2DHost("Integrated Legendre H(grad) line polynomial degree lookup", this->basisCardinality_, degreeLength);
194 
195  for (int i=0; i<this->basisCardinality_; i++)
196  {
197  // for H(vol) line, first basis member is constant, second is first-degree, etc.
198  this->fieldOrdinalPolynomialDegree_ (i,0) = i;
199  this->fieldOrdinalH1PolynomialDegree_(i,0) = i+1; // H^1 degree is one greater
200  }
201 
202  // initialize tags
203  {
204  const auto & cardinality = this->basisCardinality_;
205 
206  // Basis-dependent initializations
207  const ordinal_type tagSize = 4; // size of DoF tag, i.e., number of fields in the tag
208  const ordinal_type posScDim = 0; // position in the tag, counting from 0, of the subcell dim
209  const ordinal_type posScOrd = 1; // position in the tag, counting from 0, of the subcell ordinal
210  const ordinal_type posDfOrd = 2; // position in the tag, counting from 0, of DoF ordinal relative to the subcell
211 
212  OrdinalTypeArray1DHost tagView("tag view", cardinality*tagSize);
213 
214  for (ordinal_type i=0;i<cardinality;++i) {
215  tagView(i*tagSize+0) = 1; // edge dof
216  tagView(i*tagSize+1) = 0; // edge id
217  tagView(i*tagSize+2) = i; // local dof id
218  tagView(i*tagSize+3) = cardinality; // total number of dofs in this edge
219  }
220 
221  // Basis-independent function sets tag and enum data in tagToOrdinal_ and ordinalToTag_ arrays:
222  // tags are constructed on host
223  this->setOrdinalTagData(this->tagToOrdinal_,
224  this->ordinalToTag_,
225  tagView,
226  this->basisCardinality_,
227  tagSize,
228  posScDim,
229  posScOrd,
230  posDfOrd);
231  }
232  }
233 
234  // since the getValues() below only overrides the FEM variant, we specify that
235  // we use the base class's getValues(), which implements the FVD variant by throwing an exception.
236  // (It's an error to use the FVD variant on this basis.)
237  using BasisBase::getValues;
238 
243  virtual
244  const char*
245  getName() const override {
246  return "Intrepid2_LegendreBasis_HVOL_LINE";
247  }
248 
267  virtual void getValues( OutputViewType outputValues, const PointViewType inputPoints,
268  const EOperator operatorType = OPERATOR_VALUE ) const override
269  {
270  auto numPoints = inputPoints.extent_int(0);
271 
273 
274  FunctorType functor(outputValues, inputPoints, polyOrder_, operatorType);
275 
276  const int outputVectorSize = getVectorSizeForHierarchicalParallelism<OutputScalar>();
277  const int pointVectorSize = getVectorSizeForHierarchicalParallelism<PointScalar>();
278  const int vectorSize = std::max(outputVectorSize,pointVectorSize);
279  const int teamSize = 1; // because of the way the basis functions are computed, we don't have a second level of parallelism...
280 
281  auto policy =
282  Kokkos::TeamPolicy<ExecutionSpace>(numPoints, teamSize, vectorSize);
283  Kokkos::parallel_for("Hierarchical_HVOL_LINE_Functor", policy , functor);
284  }
285 
290  virtual BasisPtr<typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar>
291  getHostBasis() const override {
292  using HostDeviceType = typename Kokkos::HostSpace::device_type;
294  return Teuchos::rcp( new HostBasisType(polyOrder_, pointType_) );
295  }
296  };
297 } // end namespace Intrepid2
298 
299 #endif /* Intrepid2_LegendreBasis_HVOL_LINE_h */
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
virtual const char * getName() const override
Returns basis name.
unsigned basisCellTopologyKey_
Identifier of the base topology of the cells for which the basis is defined. See the Shards package f...
Functor for computing values for the LegendreBasis_HVOL_LINE class.
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
Kokkos::DynRankView< scalarType, Kokkos::LayoutStride, DeviceType > ScalarViewType
View type for scalars.
Free functions, callable from device code, that implement various polynomials useful in basis definit...
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
EFunctionSpace functionSpace_
The function space in which the basis is defined.
ordinal_type basisDegree_
Degree of the largest complete polynomial space that can be represented by the basis.
virtual KOKKOS_INLINE_FUNCTION void getValues(OutputViewType, const PointViewType, const EOperator, const typename Kokkos::TeamPolicy< ExecutionSpace >::member_type &teamMember, const typename ExecutionSpace::scratch_memory_space &scratchStorage, const ordinal_type subcellDim=-1, const ordinal_type subcellOrdinal=-1) const
Team-level evaluation of basis functions on a reference cell.
LegendreBasis_HVOL_LINE(int polyOrder, const EPointType pointType=POINTTYPE_DEFAULT)
Constructor.
Implementation of an assert that can safely be called from device code.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
Kokkos::View< ordinal_type **, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
Basis defining Legendre basis on the line, a polynomial subspace of L^2 (a.k.a. H(vol)) on the line...
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const override
Evaluation of a FEM basis on a reference cell.
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
OrdinalTypeArray2DHost ordinalToTag_
&quot;true&quot; if tagToOrdinal_ and ordinalToTag_ have been initialized
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
virtual BasisPtr< typename Kokkos::HostSpace::device_type, OutputScalar, PointScalar > getHostBasis() const override
Creates and returns a Basis object whose DeviceType template argument is Kokkos::HostSpace::device_ty...
OrdinalTypeArray2DHost fieldOrdinalH1PolynomialDegree_
H^1 polynomial degree for each degree of freedom. Only defined for hierarchical bases right now...
OrdinalTypeArray2DHost fieldOrdinalPolynomialDegree_
Polynomial degree for each degree of freedom. Only defined for hierarchical bases right now...
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)
Fills ordinalToTag_ and tagToOrdinal_ by basis-specific tag data.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
Header file for the abstract base class Intrepid2::Basis.
typename DeviceType::execution_space ExecutionSpace
(Kokkos) Execution space for basis.