Intrepid2
Intrepid2_Basis.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_BASIS_HPP__
17 #define __INTREPID2_BASIS_HPP__
18 
19 #include "Intrepid2_ConfigDefs.hpp"
20 #include "Intrepid2_Types.hpp"
21 #include "Intrepid2_Utils.hpp"
22 
26 #include "Shards_CellTopology.hpp"
27 #include "Intrepid2_CellData.hpp"
28 #include <Teuchos_RCPDecl.hpp>
29 #include <Kokkos_Core.hpp>
30 
31 #include <vector>
32 
33 namespace Intrepid2 {
34 
35 template<typename DeviceType = void,
36  typename OutputType = double,
37  typename PointType = double>
38 class Basis;
39 
42 template <typename DeviceType = void, typename OutputType = double, typename PointType = double>
43 using BasisPtr = Teuchos::RCP<Basis<DeviceType,OutputType,PointType> >;
44 
47 template <typename OutputType = double, typename PointType = double>
48 using HostBasisPtr = BasisPtr<typename Kokkos::HostSpace::device_type, OutputType, PointType>;
49 
86  template<typename Device,
87  typename outputValueType,
88  typename pointValueType>
89  class Basis {
90  public:
93  using DeviceType = Device;
94 
97  using ExecutionSpace = typename DeviceType::execution_space;
98 
99 
102  using OutputValueType = outputValueType;
103 
106  using PointValueType = pointValueType;
107 
110  using OrdinalViewType = Kokkos::View<ordinal_type,DeviceType>;
111 
114  using EBasisViewType = Kokkos::View<EBasis,DeviceType>;
115 
118  using ECoordinatesViewType = Kokkos::View<ECoordinates,DeviceType>;
119 
120  // ** tag interface
121  // - tag interface is not decorated with Kokkos inline so it should be allocated on hostspace
122 
125  using OrdinalTypeArray1DHost = Kokkos::View<ordinal_type*,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
126 
129  using OrdinalTypeArray2DHost = Kokkos::View<ordinal_type**,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
130 
133  using OrdinalTypeArray3DHost = Kokkos::View<ordinal_type***,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
134 
137  using OrdinalTypeArrayStride1DHost = Kokkos::View<ordinal_type*, Kokkos::LayoutStride, Kokkos::HostSpace>;
138 
141  using OrdinalTypeArray1D = Kokkos::View<ordinal_type*,DeviceType>;
142 
145  using OrdinalTypeArray2D = Kokkos::View<ordinal_type**,DeviceType>;
146 
149  using OrdinalTypeArray3D = Kokkos::View<ordinal_type***,DeviceType>;
150 
153  using OrdinalTypeArrayStride1D = Kokkos::View<ordinal_type*, Kokkos::LayoutStride, DeviceType>;
154 
157  typedef typename ScalarTraits<pointValueType>::scalar_type scalarType;
158  protected:
159 
162  ordinal_type basisCardinality_;
163 
166  ordinal_type basisDegree_;
167 
176 
179  EBasis basisType_;
180 
183  ECoordinates basisCoordinates_;
184 
187  EFunctionSpace functionSpace_ = FUNCTION_SPACE_MAX;
188 
191  //Kokkos::View<bool,DeviceType> basisTagsAreSet_;
192 
205 
218 
230  template<typename OrdinalTypeView3D,
231  typename OrdinalTypeView2D,
232  typename OrdinalTypeView1D>
233  void setOrdinalTagData( OrdinalTypeView3D &tagToOrdinal,
234  OrdinalTypeView2D &ordinalToTag,
235  const OrdinalTypeView1D tags,
236  const ordinal_type basisCard,
237  const ordinal_type tagSize,
238  const ordinal_type posScDim,
239  const ordinal_type posScOrd,
240  const ordinal_type posDfOrd ) {
241  // Create ordinalToTag
242  ordinalToTag = OrdinalTypeView2D("ordinalToTag", basisCard, tagSize);
243 
244  // Initialize with -1
245  Kokkos::deep_copy( ordinalToTag, -1 );
246 
247  // Copy tags
248  for (ordinal_type i=0;i<basisCard;++i)
249  for (ordinal_type j=0;j<tagSize;++j)
250  ordinalToTag(i, j) = tags(i*tagSize + j);
251 
252  // Find out dimension of tagToOrdinal
253  auto maxScDim = 0; // first dimension of tagToOrdinal
254  for (ordinal_type i=0;i<basisCard;++i)
255  if (maxScDim < tags(i*tagSize + posScDim))
256  maxScDim = tags(i*tagSize + posScDim);
257  ++maxScDim;
258 
259  auto maxScOrd = 0; // second dimension of tagToOrdinal
260  for (ordinal_type i=0;i<basisCard;++i)
261  if (maxScOrd < tags(i*tagSize + posScOrd))
262  maxScOrd = tags(i*tagSize + posScOrd);
263  ++maxScOrd;
264 
265  auto maxDfOrd = 0; // third dimension of tagToOrdinal
266  for (ordinal_type i=0;i<basisCard;++i)
267  if (maxDfOrd < tags(i*tagSize + posDfOrd))
268  maxDfOrd = tags(i*tagSize + posDfOrd);
269  ++maxDfOrd;
270 
271  // Create tagToOrdinal
272  tagToOrdinal = OrdinalTypeView3D("tagToOrdinal", maxScDim, maxScOrd, maxDfOrd);
273 
274  // Initialize with -1
275  Kokkos::deep_copy( tagToOrdinal, -1 );
276 
277  // Overwrite elements of the array corresponding to tags with local DoF Id's, leave all other = -1
278  for (ordinal_type i=0;i<basisCard;++i)
279  tagToOrdinal(tags(i*tagSize), tags(i*tagSize+1), tags(i*tagSize+2)) = i;
280  }
281 
282  // dof coords
285  Kokkos::DynRankView<scalarType,DeviceType> dofCoords_;
286 
287  // dof coeffs
295  Kokkos::DynRankView<scalarType,DeviceType> dofCoeffs_;
296 
305 
318  public:
319 
320  Basis() = default;
321  virtual~Basis() = default;
322 
323  // receives input arguments
326  OutputValueType getDummyOutputValue() { return outputValueType(); }
327 
330  PointValueType getDummyPointValue() { return pointValueType(); }
331 
334  using OutputViewType = Kokkos::DynRankView<OutputValueType,Kokkos::LayoutStride,DeviceType>;
335 
338  using PointViewType = Kokkos::DynRankView<PointValueType,Kokkos::LayoutStride,DeviceType>;
339 
342  using ScalarViewType = Kokkos::DynRankView<scalarType,Kokkos::LayoutStride,DeviceType>;
343 
348  Kokkos::DynRankView<OutputValueType,DeviceType> allocateOutputView( const int numPoints, const EOperator operatorType = OPERATOR_VALUE) const;
349 
355  virtual BasisValues<OutputValueType,DeviceType> allocateBasisValues( TensorPoints<PointValueType,DeviceType> points, const EOperator operatorType = OPERATOR_VALUE) const
356  {
357  const bool operatorIsDk = (operatorType >= OPERATOR_D1) && (operatorType <= OPERATOR_D10);
358  const bool operatorSupported = (operatorType == OPERATOR_VALUE) || (operatorType == OPERATOR_GRAD) || (operatorType == OPERATOR_CURL) || (operatorType == OPERATOR_DIV) || operatorIsDk;
359  INTREPID2_TEST_FOR_EXCEPTION(!operatorSupported, std::invalid_argument, "operator is not supported by allocateBasisValues");
360 
361  const int numPoints = points.extent_int(0);
362 
363  using Scalar = OutputValueType;
364 
365  auto dataView = allocateOutputView(numPoints, operatorType);
366  Data<Scalar,DeviceType> data(dataView);
367 
368  bool useVectorData = (rank(dataView) == 3);
369 
370  if (useVectorData)
371  {
372  VectorData<Scalar,DeviceType> vectorData(data);
373  return BasisValues<Scalar,DeviceType>(vectorData);
374  }
375  else
376  {
377  TensorData<Scalar,DeviceType> tensorData(data);
378  return BasisValues<Scalar,DeviceType>(tensorData);
379  }
380  }
381 
382 
394  virtual
395  void getScratchSpaceSize( ordinal_type& perTeamSpaceSize,
396  ordinal_type& perThreadSpaceSize,
397  const PointViewType inputPoints,
398  const EOperator operatorType = OPERATOR_VALUE) const {
399  INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( true, std::logic_error,
400  ">>> ERROR (Basis::getValuesScratchSpace): this method is not supported or should be overridden accordingly by derived classes.");
401  }
402 
403 
424  KOKKOS_INLINE_FUNCTION
425  virtual
426  void getValues( OutputViewType /* outputValues */,
427  const PointViewType /* inputPoints */,
428  const EOperator /* operatorType */,
429  const typename Kokkos::TeamPolicy<ExecutionSpace>::member_type& teamMember,
430  const typename ExecutionSpace::scratch_memory_space &scratchStorage,
431  const ordinal_type subcellDim=-1,
432  const ordinal_type subcellOrdinal=-1) const {
433  INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE( true, std::logic_error,
434  ">>> ERROR (Basis::getValues): this method is not supported or should be overridden accordingly by derived classes.");
435  }
436 
456  virtual
457  void
458  getValues( const ExecutionSpace& /* space */,
459  OutputViewType /* outputValues */,
460  const PointViewType /* inputPoints */,
461  const EOperator /* operatorType */ = OPERATOR_VALUE ) const {
462  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
463  ">>> ERROR (Basis::getValues): this method (FEM) is not supported or should be overridden accordingly by derived classes.");
464  }
465 
467  virtual void getValues(
468  OutputViewType outputValues,
469  const PointViewType inputPoints,
470  const EOperator operatorType = OPERATOR_VALUE
471  ) const {
472  this->getValues(ExecutionSpace{}, outputValues, inputPoints, operatorType);
473  }
474 
486  virtual
487  void
489  const TensorPoints<PointValueType,DeviceType> inputPoints,
490  const EOperator operatorType = OPERATOR_VALUE ) const {
491  // note the extra allocation/copy here (this is one reason, among several, to override this method):
492  auto rawExpandedPoints = inputPoints.allocateAndFillExpandedRawPointView();
493 
494  OutputViewType rawOutputView;
496  if (outputValues.numTensorDataFamilies() > 0)
497  {
498  INTREPID2_TEST_FOR_EXCEPTION(outputValues.tensorData(0).numTensorComponents() != 1, std::invalid_argument, "default implementation of getValues() only supports outputValues with trivial tensor-product structure");
499  outputData = outputValues.tensorData().getTensorComponent(0);
500  }
501  else if (outputValues.vectorData().isValid())
502  {
503  INTREPID2_TEST_FOR_EXCEPTION(outputValues.vectorData().numComponents() != 1, std::invalid_argument, "default implementation of getValues() only supports outputValues with trivial tensor-product structure");
504  INTREPID2_TEST_FOR_EXCEPTION(outputValues.vectorData().getComponent(0).numTensorComponents() != 1, std::invalid_argument, "default implementation of getValues() only supports outputValues with trivial tensor-product structure");
505  outputData = outputValues.vectorData().getComponent(0).getTensorComponent(0);
506  }
507 
508  this->getValues(outputData.getUnderlyingView(), rawExpandedPoints, operatorType);
509  }
510 
530  virtual
531  void
532  getValues( OutputViewType /* outputValues */,
533  const PointViewType /* inputPoints */,
534  const PointViewType /* cellVertices */,
535  const EOperator /* operatorType */ = OPERATOR_VALUE ) const {
536  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
537  ">>> ERROR (Basis::getValues): this method (FVM) is not supported or should be overridden accordingly by derived classes.");
538  }
539 
540 
544  virtual
545  void
546  getDofCoords( ScalarViewType /* dofCoords */ ) const {
547  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
548  ">>> ERROR (Basis::getDofCoords): this method is not supported or should be overridden accordingly by derived classes.");
549  }
550 
559  virtual
560  void
561  getDofCoeffs( ScalarViewType /* dofCoeffs */ ) const {
562  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
563  ">>> ERROR (Basis::getDofCoeffs): this method is not supported or should be overridden accordingly by derived classes.");
564  }
565 
574  {
575  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
576  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
577  int degreeEntryLength = fieldOrdinalPolynomialDegree_.extent_int(1);
578  int requestedDegreeLength = degrees.extent_int(0);
579  INTREPID2_TEST_FOR_EXCEPTION(degreeEntryLength != requestedDegreeLength, std::invalid_argument, "length of degrees does not match the entries in fieldOrdinalPolynomialDegree_");
580  std::vector<int> fieldOrdinalsVector;
581  for (int basisOrdinal=0; basisOrdinal<fieldOrdinalPolynomialDegree_.extent_int(0); basisOrdinal++)
582  {
583  bool matches = true;
584  for (int d=0; d<degreeEntryLength; d++)
585  {
586  if (fieldOrdinalPolynomialDegree_(basisOrdinal,d) > degrees(d)) matches = false;
587  }
588  if (matches) fieldOrdinalsVector.push_back(basisOrdinal);
589  }
590  OrdinalTypeArray1DHost fieldOrdinals("fieldOrdinalsForDegree",fieldOrdinalsVector.size());
591  for (unsigned i=0; i<fieldOrdinalsVector.size(); i++)
592  {
593  fieldOrdinals(i) = fieldOrdinalsVector[i];
594  }
595  return fieldOrdinals;
596  }
597 
606  {
607  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
608  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
609  int degreeEntryLength = fieldOrdinalH1PolynomialDegree_.extent_int(1);
610  int requestedDegreeLength = degrees.extent_int(0);
611  INTREPID2_TEST_FOR_EXCEPTION(degreeEntryLength != requestedDegreeLength, std::invalid_argument, "length of degrees does not match the entries in fieldOrdinalPolynomialDegree_");
612  std::vector<int> fieldOrdinalsVector;
613  for (int basisOrdinal=0; basisOrdinal<fieldOrdinalH1PolynomialDegree_.extent_int(0); basisOrdinal++)
614  {
615  bool matches = true;
616  for (int d=0; d<degreeEntryLength; d++)
617  {
618  if (fieldOrdinalH1PolynomialDegree_(basisOrdinal,d) > degrees(d)) matches = false;
619  }
620  if (matches) fieldOrdinalsVector.push_back(basisOrdinal);
621  }
622  OrdinalTypeArray1DHost fieldOrdinals("fieldOrdinalsForH1Degree",fieldOrdinalsVector.size());
623  for (unsigned i=0; i<fieldOrdinalsVector.size(); i++)
624  {
625  fieldOrdinals(i) = fieldOrdinalsVector[i];
626  }
627  return fieldOrdinals;
628  }
629 
641  std::vector<int> getFieldOrdinalsForDegree(std::vector<int> &degrees) const
642  {
643  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
644  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
645  OrdinalTypeArray1DHost degreesView("degrees",degrees.size());
646  for (unsigned d=0; d<degrees.size(); d++)
647  {
648  degreesView(d) = degrees[d];
649  }
650  auto fieldOrdinalsView = getFieldOrdinalsForDegree(degreesView);
651  std::vector<int> fieldOrdinalsVector(fieldOrdinalsView.extent_int(0));
652  for (int i=0; i<fieldOrdinalsView.extent_int(0); i++)
653  {
654  fieldOrdinalsVector[i] = fieldOrdinalsView(i);
655  }
656  return fieldOrdinalsVector;
657  }
658 
669  std::vector<int> getFieldOrdinalsForH1Degree(std::vector<int> &degrees) const
670  {
671  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
672  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
673  OrdinalTypeArray1DHost degreesView("degrees",degrees.size());
674  for (unsigned d=0; d<degrees.size(); d++)
675  {
676  degreesView(d) = degrees[d];
677  }
678  auto fieldOrdinalsView = getFieldOrdinalsForH1Degree(degreesView);
679  std::vector<int> fieldOrdinalsVector(fieldOrdinalsView.extent_int(0));
680  for (int i=0; i<fieldOrdinalsView.extent_int(0); i++)
681  {
682  fieldOrdinalsVector[i] = fieldOrdinalsView(i);
683  }
684  return fieldOrdinalsVector;
685  }
686 
694  {
695  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
696  ">>> ERROR (Basis::getPolynomialDegreeOfField): this method is not supported for non-hierarchical bases.");
697  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal < 0, std::invalid_argument, "field ordinal must be non-negative");
698  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal >= fieldOrdinalPolynomialDegree_.extent_int(0), std::invalid_argument, "field ordinal out of bounds");
699 
700  int polyDegreeLength = getPolynomialDegreeLength();
701  OrdinalTypeArray1DHost polyDegree("polynomial degree", polyDegreeLength);
702  for (int d=0; d<polyDegreeLength; d++)
703  {
704  polyDegree(d) = fieldOrdinalPolynomialDegree_(fieldOrdinal,d);
705  }
706  return polyDegree;
707  }
708 
716  {
717  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
718  ">>> ERROR (Basis::getPolynomialDegreeOfField): this method is not supported for non-hierarchical bases.");
719  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal < 0, std::invalid_argument, "field ordinal must be non-negative");
720  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal >= fieldOrdinalH1PolynomialDegree_.extent_int(0), std::invalid_argument, "field ordinal out of bounds");
721 
722  int polyDegreeLength = getPolynomialDegreeLength();
723  OrdinalTypeArray1DHost polyDegree("polynomial degree", polyDegreeLength);
724  for (int d=0; d<polyDegreeLength; d++)
725  {
726  polyDegree(d) = fieldOrdinalH1PolynomialDegree_(fieldOrdinal,d);
727  }
728  return polyDegree;
729  }
730 
738  std::vector<int> getPolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
739  {
740  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
741  ">>> ERROR (Basis::getPolynomialDegreeOfFieldAsVector): this method is not supported for non-hierarchical bases.");
742  auto polynomialDegreeView = getPolynomialDegreeOfField(fieldOrdinal);
743  std::vector<int> polynomialDegree(polynomialDegreeView.extent_int(0));
744 
745  for (unsigned d=0; d<polynomialDegree.size(); d++)
746  {
747  polynomialDegree[d] = polynomialDegreeView(d);
748  }
749  return polynomialDegree;
750  }
751 
759  std::vector<int> getH1PolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
760  {
761  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
762  ">>> ERROR (Basis::getPolynomialDegreeOfFieldAsVector): this method is not supported for non-hierarchical bases.");
763  auto polynomialDegreeView = getH1PolynomialDegreeOfField(fieldOrdinal);
764  std::vector<int> polynomialDegree(polynomialDegreeView.extent_int(0));
765 
766  for (unsigned d=0; d<polynomialDegree.size(); d++)
767  {
768  polynomialDegree[d] = polynomialDegreeView(d);
769  }
770  return polynomialDegree;
771  }
772 
776  {
777  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
778  ">>> ERROR (Basis::getPolynomialDegreeLength): this method is not supported for non-hierarchical bases.");
779  return fieldOrdinalPolynomialDegree_.extent_int(1);
780  }
781 
786  virtual
787  const char*
788  getName() const {
789  return "Intrepid2_Basis";
790  }
791 
794  virtual
795  bool
797  return false;
798  }
799 
804  ordinal_type
805  getCardinality() const {
806  return basisCardinality_;
807  }
808 
809 
814  ordinal_type
815  getDegree() const {
816  return basisDegree_;
817  }
818 
823  EFunctionSpace
825  return functionSpace_;
826  }
827 
833  shards::CellTopology
835  return getCellTopologyData(basisCellTopologyKey_);
836  }
837 
838 
843  EBasis
844  getBasisType() const {
845  return basisType_;
846  }
847 
848 
853  ECoordinates
855  return basisCoordinates_;
856  }
857 
865  ordinal_type
866  getDofCount( const ordinal_type subcDim,
867  const ordinal_type subcOrd ) const {
868  if ( subcDim >= 0 && subcDim < static_cast<ordinal_type>(tagToOrdinal_.extent(0)) &&
869  subcOrd >= 0 && subcOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(1)) )
870  {
871  int firstDofOrdinal = tagToOrdinal_(subcDim, subcOrd, 0); // will be -1 if no dofs for subcell
872  if (firstDofOrdinal == -1) return static_cast<ordinal_type>(0);
873  // otherwise, lookup its tag and return the dof count stored there
874  return static_cast<ordinal_type>(this->getDofTag(firstDofOrdinal)[3]);
875  }
876  else
877  {
878  // subcDim and/or subcOrd out of bounds -> no dofs associated with subcell
879  return static_cast<ordinal_type>(0);
880  }
881  }
882 
891  ordinal_type
892  getDofOrdinal( const ordinal_type subcDim,
893  const ordinal_type subcOrd,
894  const ordinal_type subcDofOrd ) const {
895  // this should be abort and able to be called as a device function
896 #ifdef HAVE_INTREPID2_DEBUG
897  INTREPID2_TEST_FOR_EXCEPTION( subcDim < 0 || subcDim >= static_cast<ordinal_type>(tagToOrdinal_.extent(0)), std::out_of_range,
898  ">>> ERROR (Basis::getDofOrdinal): subcDim is out of range");
899  INTREPID2_TEST_FOR_EXCEPTION( subcOrd < 0 || subcOrd >= static_cast<ordinal_type>(tagToOrdinal_.extent(1)), std::out_of_range,
900  ">>> ERROR (Basis::getDofOrdinal): subcOrd is out of range");
901  INTREPID2_TEST_FOR_EXCEPTION( subcDofOrd < 0 || subcDofOrd >= static_cast<ordinal_type>(tagToOrdinal_.extent(2)), std::out_of_range,
902  ">>> ERROR (Basis::getDofOrdinal): subcDofOrd is out of range");
903 #endif
904  ordinal_type r_val = -1;
905  if ( subcDim < static_cast<ordinal_type>(tagToOrdinal_.extent(0)) &&
906  subcOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(1)) &&
907  subcDofOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(2)) )
908  r_val = tagToOrdinal_(subcDim, subcOrd, subcDofOrd);
909 #ifdef HAVE_INTREPID2_DEBUG
910  INTREPID2_TEST_FOR_EXCEPTION( r_val == -1, std::runtime_error,
911  ">>> ERROR (Basis::getDofOrdinal): Invalid DoF tag is found.");
912 #endif
913  return r_val;
914  }
915 
918  virtual int getNumTensorialExtrusions() const
919  {
920  return 0;
921  }
922 
926  return tagToOrdinal_;
927  }
928 
929 
941  getDofTag( const ordinal_type dofOrd ) const {
942 #ifdef HAVE_INTREPID2_DEBUG
943  INTREPID2_TEST_FOR_EXCEPTION( dofOrd < 0 || dofOrd >= static_cast<ordinal_type>(ordinalToTag_.extent(0)), std::out_of_range,
944  ">>> ERROR (Basis::getDofTag): dofOrd is out of range");
945 #endif
946  return Kokkos::subview(ordinalToTag_, dofOrd, Kokkos::ALL());
947  }
948 
949 
959  getAllDofTags() const {
960  return ordinalToTag_;
961  }
962 
977  virtual BasisPtr<DeviceType, OutputValueType, PointValueType>
978  getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const {
979  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
980  ">>> ERROR (Basis::getSubCellRefBasis): this method is not supported or should be overridden accordingly by derived classes.");
981  }
982 
987  ordinal_type getDomainDimension() const
988  {
989  return this->getBaseCellTopology().getDimension() + this->getNumTensorialExtrusions();
990  }
991 
996  virtual HostBasisPtr<OutputValueType, PointValueType>
997  getHostBasis() const {
998  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
999  ">>> ERROR (Basis::getHostBasis): this method is not supported or should be overridden accordingly by derived classes.");
1000  }
1001 
1002  }; // class Basis
1003 
1004  //--------------------------------------------------------------------------------------------//
1005  // //
1006  // Helper functions of the Basis class //
1007  // //
1008  //--------------------------------------------------------------------------------------------//
1009 
1010  //
1011  // functions for orders, cardinality, etc.
1012  //
1013 
1014 
1026  KOKKOS_INLINE_FUNCTION
1027  ordinal_type getFieldRank(const EFunctionSpace spaceType);
1028 
1064  KOKKOS_INLINE_FUNCTION
1065  ordinal_type getOperatorRank(const EFunctionSpace spaceType,
1066  const EOperator operatorType,
1067  const ordinal_type spaceDim);
1068 
1074  KOKKOS_INLINE_FUNCTION
1075  ordinal_type getOperatorOrder(const EOperator operatorType);
1076 
1077  template<EOperator operatorType>
1078  KOKKOS_INLINE_FUNCTION
1079  constexpr ordinal_type getOperatorOrder();
1080 
1104  template<ordinal_type spaceDim>
1105  KOKKOS_INLINE_FUNCTION
1106  ordinal_type getDkEnumeration(const ordinal_type xMult,
1107  const ordinal_type yMult = -1,
1108  const ordinal_type zMult = -1);
1109 
1110 
1121  template<ordinal_type spaceDim>
1122  KOKKOS_INLINE_FUNCTION
1123  ordinal_type getPnEnumeration(const ordinal_type p,
1124  const ordinal_type q = 0,
1125  const ordinal_type r = 0);
1126 
1127 
1128 
1147 template<typename value_type>
1148 KOKKOS_INLINE_FUNCTION
1149 void getJacobyRecurrenceCoeffs (
1150  value_type &an,
1151  value_type &bn,
1152  value_type &cn,
1153  const ordinal_type alpha,
1154  const ordinal_type beta ,
1155  const ordinal_type n);
1156 
1157 
1158 
1159 
1160 
1161  // /** \brief Returns multiplicities of dx, dy, and dz based on the enumeration of the partial
1162  // derivative, its order and the space dimension. Inverse of the getDkEnumeration() method.
1163 
1164  // \param partialMult [out] - array with the multiplicities f dx, dy and dz
1165  // \param derivativeEnum [in] - enumeration of the partial derivative
1166  // \param operatorType [in] - k-th partial derivative Dk
1167  // \param spaceDim [in] - space dimension
1168  // */
1169  // template<typename OrdinalArrayType>
1170  // KOKKOS_INLINE_FUNCTION
1171  // void getDkMultiplicities(OrdinalArrayType partialMult,
1172  // const ordinal_type derivativeEnum,
1173  // const EOperator operatorType,
1174  // const ordinal_type spaceDim);
1175 
1194  KOKKOS_INLINE_FUNCTION
1195  ordinal_type getDkCardinality(const EOperator operatorType,
1196  const ordinal_type spaceDim);
1197 
1198  template<EOperator operatorType, ordinal_type spaceDim>
1199  KOKKOS_INLINE_FUNCTION
1200  constexpr ordinal_type getDkCardinality();
1201 
1202 
1203 
1213  template<ordinal_type spaceDim>
1214  KOKKOS_INLINE_FUNCTION
1215  ordinal_type getPnCardinality (ordinal_type n);
1216 
1217  template<ordinal_type spaceDim, ordinal_type n>
1218  KOKKOS_INLINE_FUNCTION
1219  constexpr ordinal_type getPnCardinality ();
1220 
1221 
1222 
1223  //
1224  // Argument check
1225  //
1226 
1227 
1238  template<typename outputValueViewType,
1239  typename inputPointViewType>
1240  void getValues_HGRAD_Args( const outputValueViewType outputValues,
1241  const inputPointViewType inputPoints,
1242  const EOperator operatorType,
1243  const shards::CellTopology cellTopo,
1244  const ordinal_type basisCard );
1245 
1256  template<typename outputValueViewType,
1257  typename inputPointViewType>
1258  void getValues_HCURL_Args( const outputValueViewType outputValues,
1259  const inputPointViewType inputPoints,
1260  const EOperator operatorType,
1261  const shards::CellTopology cellTopo,
1262  const ordinal_type basisCard );
1263 
1274  template<typename outputValueViewType,
1275  typename inputPointViewType>
1276  void getValues_HDIV_Args( const outputValueViewType outputValues,
1277  const inputPointViewType inputPoints,
1278  const EOperator operatorType,
1279  const shards::CellTopology cellTopo,
1280  const ordinal_type basisCard );
1281 
1292  template<typename outputValueViewType,
1293  typename inputPointViewType>
1294  void getValues_HVOL_Args( const outputValueViewType outputValues,
1295  const inputPointViewType inputPoints,
1296  const EOperator operatorType,
1297  const shards::CellTopology cellTopo,
1298  const ordinal_type basisCard );
1299 
1300 }// namespace Intrepid2
1301 
1302 #include <Intrepid2_BasisDef.hpp>
1303 
1304 //--------------------------------------------------------------------------------------------//
1305 // //
1306 // D O C U M E N T A T I O N P A G E S //
1307 // //
1308 //--------------------------------------------------------------------------------------------//
1410 #endif
ordinal_type getDomainDimension() const
Returns the spatial dimension of the domain of the basis; this is equal to getBaseCellTopology().getDimension() + getNumTensorialExtrusions().
Kokkos::View< ordinal_type *, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray1DHost
View type for 1d host array.
std::vector< int > getFieldOrdinalsForH1Degree(std::vector< int > &degrees) const
For hierarchical bases, returns the field ordinals that have at most the specified H^1 degree in each...
const OrdinalTypeArrayStride1DHost getDofTag(const ordinal_type dofOrd) const
DoF ordinal to DoF tag lookup.
std::vector< int > getFieldOrdinalsForDegree(std::vector< int > &degrees) const
For hierarchical bases, returns the field ordinals that have at most the specified degree in each dim...
ordinal_type getCardinality() const
Returns cardinality of the basis.
virtual void getValues(const ExecutionSpace &, OutputViewType, const PointViewType, const EOperator=OPERATOR_VALUE) const
Evaluation of a FEM basis on a reference cell.
unsigned basisCellTopologyKey_
Identifier of the base topology of the cells for which the basis is defined. See the Shards package f...
ScalarTraits< pointValueType >::scalar_type scalarType
Scalar type for point values.
EBasis basisType_
Type of the basis.
View-like interface to tensor points; point components are stored separately; the appropriate coordin...
std::vector< int > getH1PolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
For hierarchical bases, returns the polynomial degree (which may have multiple values in higher spati...
OrdinalTypeArray1DHost getFieldOrdinalsForH1Degree(OrdinalTypeArray1DHost &degrees) const
For hierarchical bases, returns the field ordinals that have at most the specified H^1 degree in each...
ECoordinates getCoordinateSystem() const
Returns the type of coordinate system for which the basis is defined.
#define INTREPID2_TEST_FOR_EXCEPTION_DEVICE_SAFE(test, x, msg)
OrdinalTypeArray1DHost getFieldOrdinalsForDegree(OrdinalTypeArray1DHost &degrees) const
For hierarchical bases, returns the field ordinals that have at most the specified degree in each dim...
Kokkos::View< ordinal_type *, DeviceType > OrdinalTypeArray1D
View type for 1d device array.
outputValueType OutputValueType
Output value type for basis; default is double.
Kokkos::DynRankView< OutputValueType, DeviceType > allocateOutputView(const int numPoints, const EOperator operatorType=OPERATOR_VALUE) const
Allocate a View container suitable for passing to the getValues() variant that accepts Kokkos DynRank...
virtual void getValues(BasisValues< OutputValueType, DeviceType > outputValues, const TensorPoints< PointValueType, DeviceType > inputPoints, const EOperator operatorType=OPERATOR_VALUE) const
Evaluation of a FEM basis on a reference cell, using point and output value containers that allow pre...
An abstract base class that defines interface for concrete basis implementations for Finite Element (...
View-like interface to tensor points; point components are stored separately; the appropriate coordin...
shards::CellTopology getBaseCellTopology() const
Returns the base cell topology for which the basis is defined. See Shards documentation https://trili...
ordinal_type getDofOrdinal(const ordinal_type subcDim, const ordinal_type subcOrd, const ordinal_type subcDofOrd) const
DoF tag to ordinal lookup.
Device DeviceType
(Kokkos) Device type on which Basis is templated. Does not necessarily return true for Kokkos::is_dev...
Kokkos::DynRankView< scalarType, Kokkos::LayoutStride, DeviceType > ScalarViewType
View type for scalars.
const VectorDataType & vectorData() const
VectorData accessor.
KOKKOS_INLINE_FUNCTION enable_if_t< rank==1, const Kokkos::View< typename RankExpander< DataScalar, rank >::value_type, DeviceType > & > getUnderlyingView() const
Returns the underlying view. Throws an exception if the underlying view is not rank 1...
virtual BasisPtr< DeviceType, OutputValueType, PointValueType > getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const
returns the basis associated to a subCell.
EFunctionSpace functionSpace_
The function space in which the basis is defined.
const OrdinalTypeArray2DHost getAllDofTags() const
Retrieves all DoF tags.
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.
Header function for Intrepid2::Util class and other utility functions.
ScalarView< PointScalar, DeviceType > allocateAndFillExpandedRawPointView() const
This method is for compatibility with existing methods that take raw point views. Note that in genera...
Kokkos::View< ordinal_type *, Kokkos::LayoutStride, DeviceType > OrdinalTypeArrayStride1D
View type for 1d device array.
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
const OrdinalTypeArray3DHost getAllDofOrdinal() const
DoF tag to ordinal data structure.
virtual bool requireOrientation() const
True if orientation is required.
Kokkos::View< ordinal_type **, DeviceType > OrdinalTypeArray2D
View type for 2d device array.
Header file for the classes: Intrepid2::RefSubcellParametrization, Intrepid2::RefCellNodes, Intrepid2::RefCellCenter.
virtual HostBasisPtr< OutputValueType, PointValueType > getHostBasis() const
Creates and returns a Basis object whose DeviceType template argument is Kokkos::HostSpace::device_ty...
std::vector< int > getPolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
For hierarchical bases, returns the polynomial degree (which may have multiple values in higher spati...
Kokkos::View< ordinal_type **, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray2DHost
View type for 2d host array.
virtual void getScratchSpaceSize(ordinal_type &perTeamSpaceSize, ordinal_type &perThreadSpaceSize, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const
Return the size of the scratch space, in bytes, needed for using the team-level implementation of get...
The data containers in Intrepid2 that support sum factorization and other reduced-data optimizations ...
Kokkos::DynRankView< OutputValueType, Kokkos::LayoutStride, DeviceType > OutputViewType
View type for basis value output.
Definition of cell topology information.
Kokkos::View< ECoordinates, DeviceType > ECoordinatesViewType
View for coordinate system type.
virtual void getValues(OutputViewType outputValues, const PointViewType inputPoints, const EOperator operatorType=OPERATOR_VALUE) const
EBasis getBasisType() const
Returns the basis type.
Contains definitions of custom data types in Intrepid2.
ordinal_type basisCardinality_
Cardinality of the basis, i.e., the number of basis functions/degrees-of-freedom. ...
virtual void getDofCoords(ScalarViewType) const
Returns spatial locations (coordinates) of degrees of freedom on the reference cell.
Kokkos::View< ordinal_type *, Kokkos::LayoutStride, Kokkos::HostSpace > OrdinalTypeArrayStride1DHost
View type for 1d host array.
EFunctionSpace getFunctionSpace() const
Returns the function space for the basis.
virtual int getNumTensorialExtrusions() const
returns the number of tensorial extrusions relative to the cell topology returned by getBaseCellTopol...
virtual void getValues(OutputViewType, const PointViewType, const PointViewType, const EOperator=OPERATOR_VALUE) const
Evaluation of an FVD basis evaluation on a physical cell.
OrdinalTypeArray3DHost tagToOrdinal_
DoF tag to ordinal lookup table.
Kokkos::View< ordinal_type ***, typename ExecutionSpace::array_layout, Kokkos::HostSpace > OrdinalTypeArray3DHost
View type for 3d host array.
Kokkos::View< ordinal_type ***, DeviceType > OrdinalTypeArray3D
View type for 3d device array.
OutputValueType getDummyOutputValue()
Dummy array to receive input arguments.
OrdinalTypeArray2DHost ordinalToTag_
&quot;true&quot; if tagToOrdinal_ and ordinalToTag_ have been initialized
ordinal_type getDegree() const
Returns the degree of the basis.
pointValueType PointValueType
Point value type for basis; default is double.
ECoordinates basisCoordinates_
The coordinate system for which the basis is defined.
Kokkos::DynRankView< scalarType, DeviceType > dofCoeffs_
Coefficients for computing degrees of freedom for Lagrangian basis If P is an element of the space sp...
PointValueType getDummyPointValue()
Dummy array to receive input arguments.
View-like interface to tensor data; tensor components are stored separately and multiplied together a...
virtual BasisValues< OutputValueType, DeviceType > allocateBasisValues(TensorPoints< PointValueType, DeviceType > points, const EOperator operatorType=OPERATOR_VALUE) const
Allocate BasisValues container suitable for passing to the getValues() variant that takes a TensorPoi...
Implementation file for the abstract base class Intrepid2::Basis.
Kokkos::View< EBasis, DeviceType > EBasisViewType
View for basis type.
ordinal_type getDofCount(const ordinal_type subcDim, const ordinal_type subcOrd) const
DoF count for specified subcell.
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< scalarType, DeviceType > dofCoords_
Coordinates of degrees-of-freedom for basis functions defined in physical space.
Kokkos::DynRankView< PointValueType, Kokkos::LayoutStride, DeviceType > PointViewType
View type for input points.
OrdinalTypeArray1DHost getPolynomialDegreeOfField(int fieldOrdinal) const
For hierarchical bases, returns the polynomial degree (which may have multiple values in higher spati...
virtual void getDofCoeffs(ScalarViewType) const
Coefficients for computing degrees of freedom for Lagrangian basis If P is an element of the space sp...
Header file for the data-wrapper class Intrepid2::BasisValues.
int getPolynomialDegreeLength() const
For hierarchical bases, returns the number of entries required to specify the polynomial degree of a ...
OrdinalTypeArray1DHost getH1PolynomialDegreeOfField(int fieldOrdinal) const
For hierarchical bases, returns the polynomial degree (which may have multiple values in higher spati...
Reference-space field values for a basis, designed to support typical vector-valued bases...
virtual const char * getName() const
Returns basis name.
Kokkos::View< ordinal_type, DeviceType > OrdinalViewType
View type for ordinal.
KOKKOS_INLINE_FUNCTION std::enable_if< std::is_integral< iType >::value, int >::type extent_int(const iType &r) const
Returns the logical extent in the requested dimension.
typename DeviceType::execution_space ExecutionSpace
(Kokkos) Execution space for basis.