Intrepid2
Intrepid2_Basis.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Intrepid2 Package
5 // Copyright (2007) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Kyungjoo Kim (kyukim@sandia.gov),
38 // Mauro Perego (mperego@sandia.gov), or
39 // Nate Roberts (nvrober@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
50 #ifndef __INTREPID2_BASIS_HPP__
51 #define __INTREPID2_BASIS_HPP__
52 
53 #include "Intrepid2_ConfigDefs.hpp"
54 #include "Intrepid2_Types.hpp"
55 #include "Intrepid2_Utils.hpp"
56 
60 #include "Shards_CellTopology.hpp"
61 #include <Teuchos_RCPDecl.hpp>
62 #include <Kokkos_Core.hpp>
63 
64 #include <vector>
65 
66 namespace Intrepid2 {
67 
68 template<typename DeviceType = void,
69  typename OutputType = double,
70  typename PointType = double>
71 class Basis;
72 
75 template <typename DeviceType = void, typename OutputType = double, typename PointType = double>
76 using BasisPtr = Teuchos::RCP<Basis<DeviceType,OutputType,PointType> >;
77 
80 template <typename OutputType = double, typename PointType = double>
81 using HostBasisPtr = BasisPtr<typename Kokkos::HostSpace::device_type, OutputType, PointType>;
82 
119  template<typename Device,
120  typename outputValueType,
121  typename pointValueType>
122  class Basis {
123  public:
126  using DeviceType = Device;
127 
130  using ExecutionSpace = typename DeviceType::execution_space;
131 
132 
135  using OutputValueType = outputValueType;
136 
139  using PointValueType = pointValueType;
140 
143  using OrdinalViewType = Kokkos::View<ordinal_type,DeviceType>;
144 
147  using EBasisViewType = Kokkos::View<EBasis,DeviceType>;
148 
151  using ECoordinatesViewType = Kokkos::View<ECoordinates,DeviceType>;
152 
153  // ** tag interface
154  // - tag interface is not decorated with Kokkos inline so it should be allocated on hostspace
155 
158  using OrdinalTypeArray1DHost = Kokkos::View<ordinal_type*,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
159 
162  using OrdinalTypeArray2DHost = Kokkos::View<ordinal_type**,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
163 
166  using OrdinalTypeArray3DHost = Kokkos::View<ordinal_type***,typename ExecutionSpace::array_layout,Kokkos::HostSpace>;
167 
170  using OrdinalTypeArrayStride1DHost = Kokkos::View<ordinal_type*, Kokkos::LayoutStride, Kokkos::HostSpace>;
171 
174  using OrdinalTypeArray1D = Kokkos::View<ordinal_type*,DeviceType>;
175 
178  using OrdinalTypeArray2D = Kokkos::View<ordinal_type**,DeviceType>;
179 
182  using OrdinalTypeArray3D = Kokkos::View<ordinal_type***,DeviceType>;
183 
186  using OrdinalTypeArrayStride1D = Kokkos::View<ordinal_type*, Kokkos::LayoutStride, DeviceType>;
187 
190  typedef typename ScalarTraits<pointValueType>::scalar_type scalarType;
191  protected:
192 
195  ordinal_type basisCardinality_;
196 
199  ordinal_type basisDegree_;
200 
208  shards::CellTopology basisCellTopology_;
209 
212  EBasis basisType_;
213 
216  ECoordinates basisCoordinates_;
217 
220  EFunctionSpace functionSpace_ = FUNCTION_SPACE_MAX;
221 
224  //Kokkos::View<bool,DeviceType> basisTagsAreSet_;
225 
238 
251 
263  template<typename OrdinalTypeView3D,
264  typename OrdinalTypeView2D,
265  typename OrdinalTypeView1D>
266  void setOrdinalTagData( OrdinalTypeView3D &tagToOrdinal,
267  OrdinalTypeView2D &ordinalToTag,
268  const OrdinalTypeView1D tags,
269  const ordinal_type basisCard,
270  const ordinal_type tagSize,
271  const ordinal_type posScDim,
272  const ordinal_type posScOrd,
273  const ordinal_type posDfOrd ) {
274  // Create ordinalToTag
275  ordinalToTag = OrdinalTypeView2D("ordinalToTag", basisCard, tagSize);
276 
277  // Initialize with -1
278  Kokkos::deep_copy( ordinalToTag, -1 );
279 
280  // Copy tags
281  for (ordinal_type i=0;i<basisCard;++i)
282  for (ordinal_type j=0;j<tagSize;++j)
283  ordinalToTag(i, j) = tags(i*tagSize + j);
284 
285  // Find out dimension of tagToOrdinal
286  auto maxScDim = 0; // first dimension of tagToOrdinal
287  for (ordinal_type i=0;i<basisCard;++i)
288  if (maxScDim < tags(i*tagSize + posScDim))
289  maxScDim = tags(i*tagSize + posScDim);
290  ++maxScDim;
291 
292  auto maxScOrd = 0; // second dimension of tagToOrdinal
293  for (ordinal_type i=0;i<basisCard;++i)
294  if (maxScOrd < tags(i*tagSize + posScOrd))
295  maxScOrd = tags(i*tagSize + posScOrd);
296  ++maxScOrd;
297 
298  auto maxDfOrd = 0; // third dimension of tagToOrdinal
299  for (ordinal_type i=0;i<basisCard;++i)
300  if (maxDfOrd < tags(i*tagSize + posDfOrd))
301  maxDfOrd = tags(i*tagSize + posDfOrd);
302  ++maxDfOrd;
303 
304  // Create tagToOrdinal
305  tagToOrdinal = OrdinalTypeView3D("tagToOrdinal", maxScDim, maxScOrd, maxDfOrd);
306 
307  // Initialize with -1
308  Kokkos::deep_copy( tagToOrdinal, -1 );
309 
310  // Overwrite elements of the array corresponding to tags with local DoF Id's, leave all other = -1
311  for (ordinal_type i=0;i<basisCard;++i)
312  tagToOrdinal(tags(i*tagSize), tags(i*tagSize+1), tags(i*tagSize+2)) = i;
313  }
314 
315  // dof coords
318  Kokkos::DynRankView<scalarType,DeviceType> dofCoords_;
319 
320  // dof coeffs
328  Kokkos::DynRankView<scalarType,DeviceType> dofCoeffs_;
329 
338 
351  public:
352 
353  Basis() = default;
354  virtual~Basis() = default;
355 
356  // receives input arguments
359  OutputValueType getDummyOutputValue() { return outputValueType(); }
360 
363  PointValueType getDummyPointValue() { return pointValueType(); }
364 
367  using OutputViewType = Kokkos::DynRankView<OutputValueType,Kokkos::LayoutStride,DeviceType>;
368 
371  using PointViewType = Kokkos::DynRankView<PointValueType,Kokkos::LayoutStride,DeviceType>;
372 
375  using ScalarViewType = Kokkos::DynRankView<scalarType,Kokkos::LayoutStride,DeviceType>;
376 
381  Kokkos::DynRankView<OutputValueType,DeviceType> allocateOutputView( const int numPoints, const EOperator operatorType = OPERATOR_VALUE) const;
382 
388  virtual BasisValues<OutputValueType,DeviceType> allocateBasisValues( TensorPoints<PointValueType,DeviceType> points, const EOperator operatorType = OPERATOR_VALUE) const
389  {
390  const bool operatorIsDk = (operatorType >= OPERATOR_D1) && (operatorType <= OPERATOR_D10);
391  const bool operatorSupported = (operatorType == OPERATOR_VALUE) || (operatorType == OPERATOR_GRAD) || (operatorType == OPERATOR_CURL) || (operatorType == OPERATOR_DIV) || operatorIsDk;
392  INTREPID2_TEST_FOR_EXCEPTION(!operatorSupported, std::invalid_argument, "operator is not supported by allocateBasisValues");
393 
394  const int numPoints = points.extent_int(0);
395 
396  using Scalar = OutputValueType;
397 
398  auto dataView = allocateOutputView(numPoints, operatorType);
399  Data<Scalar,DeviceType> data(dataView);
400 
401  bool useVectorData = (rank(dataView) == 3);
402 
403  if (useVectorData)
404  {
405  VectorData<Scalar,DeviceType> vectorData(data);
406  return BasisValues<Scalar,DeviceType>(vectorData);
407  }
408  else
409  {
410  TensorData<Scalar,DeviceType> tensorData(data);
411  return BasisValues<Scalar,DeviceType>(tensorData);
412  }
413  }
414 
434  virtual
435  void
436  getValues( const ExecutionSpace& /* space */,
437  OutputViewType /* outputValues */,
438  const PointViewType /* inputPoints */,
439  const EOperator /* operatorType */ = OPERATOR_VALUE ) const {
440  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
441  ">>> ERROR (Basis::getValues): this method (FEM) is not supported or should be overridden accordingly by derived classes.");
442  }
443 
445  virtual void getValues(
446  OutputViewType outputValues,
447  const PointViewType inputPoints,
448  const EOperator operatorType = OPERATOR_VALUE
449  ) const {
450  this->getValues(ExecutionSpace{}, outputValues, inputPoints, operatorType);
451  }
452 
464  virtual
465  void
467  const TensorPoints<PointValueType,DeviceType> inputPoints,
468  const EOperator operatorType = OPERATOR_VALUE ) const {
469  // note the extra allocation/copy here (this is one reason, among several, to override this method):
470  auto rawExpandedPoints = inputPoints.allocateAndFillExpandedRawPointView();
471 
472  OutputViewType rawOutputView;
474  if (outputValues.numTensorDataFamilies() > 0)
475  {
476  INTREPID2_TEST_FOR_EXCEPTION(outputValues.tensorData(0).numTensorComponents() != 1, std::invalid_argument, "default implementation of getValues() only supports outputValues with trivial tensor-product structure");
477  outputData = outputValues.tensorData().getTensorComponent(0);
478  }
479  else if (outputValues.vectorData().isValid())
480  {
481  INTREPID2_TEST_FOR_EXCEPTION(outputValues.vectorData().numComponents() != 1, std::invalid_argument, "default implementation of getValues() only supports outputValues with trivial tensor-product structure");
482  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");
483  outputData = outputValues.vectorData().getComponent(0).getTensorComponent(0);
484  }
485 
486  this->getValues(outputData.getUnderlyingView(), rawExpandedPoints, operatorType);
487  }
488 
508  virtual
509  void
510  getValues( OutputViewType /* outputValues */,
511  const PointViewType /* inputPoints */,
512  const PointViewType /* cellVertices */,
513  const EOperator /* operatorType */ = OPERATOR_VALUE ) const {
514  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
515  ">>> ERROR (Basis::getValues): this method (FVM) is not supported or should be overridden accordingly by derived classes.");
516  }
517 
518 
522  virtual
523  void
524  getDofCoords( ScalarViewType /* dofCoords */ ) const {
525  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
526  ">>> ERROR (Basis::getDofCoords): this method is not supported or should be overridden accordingly by derived classes.");
527  }
528 
537  virtual
538  void
539  getDofCoeffs( ScalarViewType /* dofCoeffs */ ) const {
540  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
541  ">>> ERROR (Basis::getDofCoeffs): this method is not supported or should be overridden accordingly by derived classes.");
542  }
543 
552  {
553  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
554  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
555  int degreeEntryLength = fieldOrdinalPolynomialDegree_.extent_int(1);
556  int requestedDegreeLength = degrees.extent_int(0);
557  INTREPID2_TEST_FOR_EXCEPTION(degreeEntryLength != requestedDegreeLength, std::invalid_argument, "length of degrees does not match the entries in fieldOrdinalPolynomialDegree_");
558  std::vector<int> fieldOrdinalsVector;
559  for (int basisOrdinal=0; basisOrdinal<fieldOrdinalPolynomialDegree_.extent_int(0); basisOrdinal++)
560  {
561  bool matches = true;
562  for (int d=0; d<degreeEntryLength; d++)
563  {
564  if (fieldOrdinalPolynomialDegree_(basisOrdinal,d) > degrees(d)) matches = false;
565  }
566  if (matches) fieldOrdinalsVector.push_back(basisOrdinal);
567  }
568  OrdinalTypeArray1DHost fieldOrdinals("fieldOrdinalsForDegree",fieldOrdinalsVector.size());
569  for (unsigned i=0; i<fieldOrdinalsVector.size(); i++)
570  {
571  fieldOrdinals(i) = fieldOrdinalsVector[i];
572  }
573  return fieldOrdinals;
574  }
575 
584  {
585  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
586  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
587  int degreeEntryLength = fieldOrdinalH1PolynomialDegree_.extent_int(1);
588  int requestedDegreeLength = degrees.extent_int(0);
589  INTREPID2_TEST_FOR_EXCEPTION(degreeEntryLength != requestedDegreeLength, std::invalid_argument, "length of degrees does not match the entries in fieldOrdinalPolynomialDegree_");
590  std::vector<int> fieldOrdinalsVector;
591  for (int basisOrdinal=0; basisOrdinal<fieldOrdinalH1PolynomialDegree_.extent_int(0); basisOrdinal++)
592  {
593  bool matches = true;
594  for (int d=0; d<degreeEntryLength; d++)
595  {
596  if (fieldOrdinalH1PolynomialDegree_(basisOrdinal,d) > degrees(d)) matches = false;
597  }
598  if (matches) fieldOrdinalsVector.push_back(basisOrdinal);
599  }
600  OrdinalTypeArray1DHost fieldOrdinals("fieldOrdinalsForH1Degree",fieldOrdinalsVector.size());
601  for (unsigned i=0; i<fieldOrdinalsVector.size(); i++)
602  {
603  fieldOrdinals(i) = fieldOrdinalsVector[i];
604  }
605  return fieldOrdinals;
606  }
607 
619  std::vector<int> getFieldOrdinalsForDegree(std::vector<int> &degrees) const
620  {
621  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
622  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
623  OrdinalTypeArray1DHost degreesView("degrees",degrees.size());
624  for (unsigned d=0; d<degrees.size(); d++)
625  {
626  degreesView(d) = degrees[d];
627  }
628  auto fieldOrdinalsView = getFieldOrdinalsForDegree(degreesView);
629  std::vector<int> fieldOrdinalsVector(fieldOrdinalsView.extent_int(0));
630  for (int i=0; i<fieldOrdinalsView.extent_int(0); i++)
631  {
632  fieldOrdinalsVector[i] = fieldOrdinalsView(i);
633  }
634  return fieldOrdinalsVector;
635  }
636 
647  std::vector<int> getFieldOrdinalsForH1Degree(std::vector<int> &degrees) const
648  {
649  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
650  ">>> ERROR (Basis::getFieldOrdinalsForDegree): this method is not supported for non-hierarchical bases.");
651  OrdinalTypeArray1DHost degreesView("degrees",degrees.size());
652  for (unsigned d=0; d<degrees.size(); d++)
653  {
654  degreesView(d) = degrees[d];
655  }
656  auto fieldOrdinalsView = getFieldOrdinalsForH1Degree(degreesView);
657  std::vector<int> fieldOrdinalsVector(fieldOrdinalsView.extent_int(0));
658  for (int i=0; i<fieldOrdinalsView.extent_int(0); i++)
659  {
660  fieldOrdinalsVector[i] = fieldOrdinalsView(i);
661  }
662  return fieldOrdinalsVector;
663  }
664 
672  {
673  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
674  ">>> ERROR (Basis::getPolynomialDegreeOfField): this method is not supported for non-hierarchical bases.");
675  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal < 0, std::invalid_argument, "field ordinal must be non-negative");
676  INTREPID2_TEST_FOR_EXCEPTION(fieldOrdinal >= fieldOrdinalPolynomialDegree_.extent_int(0), std::invalid_argument, "field ordinal out of bounds");
677 
678  int polyDegreeLength = getPolynomialDegreeLength();
679  OrdinalTypeArray1DHost polyDegree("polynomial degree", polyDegreeLength);
680  for (int d=0; d<polyDegreeLength; d++)
681  {
682  polyDegree(d) = fieldOrdinalPolynomialDegree_(fieldOrdinal,d);
683  }
684  return polyDegree;
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 >= fieldOrdinalH1PolynomialDegree_.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) = fieldOrdinalH1PolynomialDegree_(fieldOrdinal,d);
705  }
706  return polyDegree;
707  }
708 
716  std::vector<int> getPolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
717  {
718  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
719  ">>> ERROR (Basis::getPolynomialDegreeOfFieldAsVector): this method is not supported for non-hierarchical bases.");
720  auto polynomialDegreeView = getPolynomialDegreeOfField(fieldOrdinal);
721  std::vector<int> polynomialDegree(polynomialDegreeView.extent_int(0));
722 
723  for (unsigned d=0; d<polynomialDegree.size(); d++)
724  {
725  polynomialDegree[d] = polynomialDegreeView(d);
726  }
727  return polynomialDegree;
728  }
729 
737  std::vector<int> getH1PolynomialDegreeOfFieldAsVector(int fieldOrdinal) const
738  {
739  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
740  ">>> ERROR (Basis::getPolynomialDegreeOfFieldAsVector): this method is not supported for non-hierarchical bases.");
741  auto polynomialDegreeView = getH1PolynomialDegreeOfField(fieldOrdinal);
742  std::vector<int> polynomialDegree(polynomialDegreeView.extent_int(0));
743 
744  for (unsigned d=0; d<polynomialDegree.size(); d++)
745  {
746  polynomialDegree[d] = polynomialDegreeView(d);
747  }
748  return polynomialDegree;
749  }
750 
754  {
755  INTREPID2_TEST_FOR_EXCEPTION( basisType_ != BASIS_FEM_HIERARCHICAL, std::logic_error,
756  ">>> ERROR (Basis::getPolynomialDegreeLength): this method is not supported for non-hierarchical bases.");
757  return fieldOrdinalPolynomialDegree_.extent_int(1);
758  }
759 
764  virtual
765  const char*
766  getName() const {
767  return "Intrepid2_Basis";
768  }
769 
772  virtual
773  bool
775  return false;
776  }
777 
782  ordinal_type
783  getCardinality() const {
784  return basisCardinality_;
785  }
786 
787 
792  ordinal_type
793  getDegree() const {
794  return basisDegree_;
795  }
796 
801  EFunctionSpace
803  return functionSpace_;
804  }
805 
811  shards::CellTopology
813  return basisCellTopology_;
814  }
815 
816 
821  EBasis
822  getBasisType() const {
823  return basisType_;
824  }
825 
826 
831  ECoordinates
833  return basisCoordinates_;
834  }
835 
843  ordinal_type
844  getDofCount( const ordinal_type subcDim,
845  const ordinal_type subcOrd ) const {
846  if ( subcDim >= 0 && subcDim < static_cast<ordinal_type>(tagToOrdinal_.extent(0)) &&
847  subcOrd >= 0 && subcOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(1)) )
848  {
849  int firstDofOrdinal = tagToOrdinal_(subcDim, subcOrd, 0); // will be -1 if no dofs for subcell
850  if (firstDofOrdinal == -1) return static_cast<ordinal_type>(0);
851  // otherwise, lookup its tag and return the dof count stored there
852  return static_cast<ordinal_type>(this->getDofTag(firstDofOrdinal)[3]);
853  }
854  else
855  {
856  // subcDim and/or subcOrd out of bounds -> no dofs associated with subcell
857  return static_cast<ordinal_type>(0);
858  }
859  }
860 
869  ordinal_type
870  getDofOrdinal( const ordinal_type subcDim,
871  const ordinal_type subcOrd,
872  const ordinal_type subcDofOrd ) const {
873  // this should be abort and able to be called as a device function
874 #ifdef HAVE_INTREPID2_DEBUG
875  INTREPID2_TEST_FOR_EXCEPTION( subcDim < 0 || subcDim >= static_cast<ordinal_type>(tagToOrdinal_.extent(0)), std::out_of_range,
876  ">>> ERROR (Basis::getDofOrdinal): subcDim is out of range");
877  INTREPID2_TEST_FOR_EXCEPTION( subcOrd < 0 || subcOrd >= static_cast<ordinal_type>(tagToOrdinal_.extent(1)), std::out_of_range,
878  ">>> ERROR (Basis::getDofOrdinal): subcOrd is out of range");
879  INTREPID2_TEST_FOR_EXCEPTION( subcDofOrd < 0 || subcDofOrd >= static_cast<ordinal_type>(tagToOrdinal_.extent(2)), std::out_of_range,
880  ">>> ERROR (Basis::getDofOrdinal): subcDofOrd is out of range");
881 #endif
882  ordinal_type r_val = -1;
883  if ( subcDim < static_cast<ordinal_type>(tagToOrdinal_.extent(0)) &&
884  subcOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(1)) &&
885  subcDofOrd < static_cast<ordinal_type>(tagToOrdinal_.extent(2)) )
886  r_val = tagToOrdinal_(subcDim, subcOrd, subcDofOrd);
887 #ifdef HAVE_INTREPID2_DEBUG
888  INTREPID2_TEST_FOR_EXCEPTION( r_val == -1, std::runtime_error,
889  ">>> ERROR (Basis::getDofOrdinal): Invalid DoF tag is found.");
890 #endif
891  return r_val;
892  }
893 
896  virtual int getNumTensorialExtrusions() const
897  {
898  return 0;
899  }
900 
904  return tagToOrdinal_;
905  }
906 
907 
919  getDofTag( const ordinal_type dofOrd ) const {
920 #ifdef HAVE_INTREPID2_DEBUG
921  INTREPID2_TEST_FOR_EXCEPTION( dofOrd < 0 || dofOrd >= static_cast<ordinal_type>(ordinalToTag_.extent(0)), std::out_of_range,
922  ">>> ERROR (Basis::getDofTag): dofOrd is out of range");
923 #endif
924  return Kokkos::subview(ordinalToTag_, dofOrd, Kokkos::ALL());
925  }
926 
927 
937  getAllDofTags() const {
938  return ordinalToTag_;
939  }
940 
955  virtual BasisPtr<DeviceType, OutputValueType, PointValueType>
956  getSubCellRefBasis(const ordinal_type subCellDim, const ordinal_type subCellOrd) const {
957  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
958  ">>> ERROR (Basis::getSubCellRefBasis): this method is not supported or should be overridden accordingly by derived classes.");
959  }
960 
965  ordinal_type getDomainDimension() const
966  {
967  return this->getBaseCellTopology().getDimension() + this->getNumTensorialExtrusions();
968  }
969 
974  virtual HostBasisPtr<OutputValueType, PointValueType>
975  getHostBasis() const {
976  INTREPID2_TEST_FOR_EXCEPTION( true, std::logic_error,
977  ">>> ERROR (Basis::getHostBasis): this method is not supported or should be overridden accordingly by derived classes.");
978  }
979 
980  }; // class Basis
981 
982  //--------------------------------------------------------------------------------------------//
983  // //
984  // Helper functions of the Basis class //
985  // //
986  //--------------------------------------------------------------------------------------------//
987 
988  //
989  // functions for orders, cardinality, etc.
990  //
991 
992 
1004  KOKKOS_INLINE_FUNCTION
1005  ordinal_type getFieldRank(const EFunctionSpace spaceType);
1006 
1042  KOKKOS_INLINE_FUNCTION
1043  ordinal_type getOperatorRank(const EFunctionSpace spaceType,
1044  const EOperator operatorType,
1045  const ordinal_type spaceDim);
1046 
1052  KOKKOS_INLINE_FUNCTION
1053  ordinal_type getOperatorOrder(const EOperator operatorType);
1054 
1055  template<EOperator operatorType>
1056  KOKKOS_INLINE_FUNCTION
1057  constexpr ordinal_type getOperatorOrder();
1058 
1082  template<ordinal_type spaceDim>
1083  KOKKOS_INLINE_FUNCTION
1084  ordinal_type getDkEnumeration(const ordinal_type xMult,
1085  const ordinal_type yMult = -1,
1086  const ordinal_type zMult = -1);
1087 
1088 
1099  template<ordinal_type spaceDim>
1100  KOKKOS_INLINE_FUNCTION
1101  ordinal_type getPnEnumeration(const ordinal_type p,
1102  const ordinal_type q = 0,
1103  const ordinal_type r = 0);
1104 
1105 
1106 
1125 template<typename value_type>
1126 KOKKOS_INLINE_FUNCTION
1127 void getJacobyRecurrenceCoeffs (
1128  value_type &an,
1129  value_type &bn,
1130  value_type &cn,
1131  const ordinal_type alpha,
1132  const ordinal_type beta ,
1133  const ordinal_type n);
1134 
1135 
1136 
1137 
1138 
1139  // /** \brief Returns multiplicities of dx, dy, and dz based on the enumeration of the partial
1140  // derivative, its order and the space dimension. Inverse of the getDkEnumeration() method.
1141 
1142  // \param partialMult [out] - array with the multiplicities f dx, dy and dz
1143  // \param derivativeEnum [in] - enumeration of the partial derivative
1144  // \param operatorType [in] - k-th partial derivative Dk
1145  // \param spaceDim [in] - space dimension
1146  // */
1147  // template<typename OrdinalArrayType>
1148  // KOKKOS_INLINE_FUNCTION
1149  // void getDkMultiplicities(OrdinalArrayType partialMult,
1150  // const ordinal_type derivativeEnum,
1151  // const EOperator operatorType,
1152  // const ordinal_type spaceDim);
1153 
1172  KOKKOS_INLINE_FUNCTION
1173  ordinal_type getDkCardinality(const EOperator operatorType,
1174  const ordinal_type spaceDim);
1175 
1176  template<EOperator operatorType, ordinal_type spaceDim>
1177  KOKKOS_INLINE_FUNCTION
1178  constexpr ordinal_type getDkCardinality();
1179 
1180 
1181 
1191  template<ordinal_type spaceDim>
1192  KOKKOS_INLINE_FUNCTION
1193  ordinal_type getPnCardinality (ordinal_type n);
1194 
1195  template<ordinal_type spaceDim, ordinal_type n>
1196  KOKKOS_INLINE_FUNCTION
1197  constexpr ordinal_type getPnCardinality ();
1198 
1199 
1200 
1201  //
1202  // Argument check
1203  //
1204 
1205 
1216  template<typename outputValueViewType,
1217  typename inputPointViewType>
1218  void getValues_HGRAD_Args( const outputValueViewType outputValues,
1219  const inputPointViewType inputPoints,
1220  const EOperator operatorType,
1221  const shards::CellTopology cellTopo,
1222  const ordinal_type basisCard );
1223 
1234  template<typename outputValueViewType,
1235  typename inputPointViewType>
1236  void getValues_HCURL_Args( const outputValueViewType outputValues,
1237  const inputPointViewType inputPoints,
1238  const EOperator operatorType,
1239  const shards::CellTopology cellTopo,
1240  const ordinal_type basisCard );
1241 
1252  template<typename outputValueViewType,
1253  typename inputPointViewType>
1254  void getValues_HDIV_Args( const outputValueViewType outputValues,
1255  const inputPointViewType inputPoints,
1256  const EOperator operatorType,
1257  const shards::CellTopology cellTopo,
1258  const ordinal_type basisCard );
1259 
1270  template<typename outputValueViewType,
1271  typename inputPointViewType>
1272  void getValues_HVOL_Args( const outputValueViewType outputValues,
1273  const inputPointViewType inputPoints,
1274  const EOperator operatorType,
1275  const shards::CellTopology cellTopo,
1276  const ordinal_type basisCard );
1277 
1278 }// namespace Intrepid2
1279 
1280 #include <Intrepid2_BasisDef.hpp>
1281 
1282 //--------------------------------------------------------------------------------------------//
1283 // //
1284 // D O C U M E N T A T I O N P A G E S //
1285 // //
1286 //--------------------------------------------------------------------------------------------//
1388 #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.
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.
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.
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.
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.
const VectorDataType & vectorData() const
VectorData accessor.
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.
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.
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.
TensorDataType & tensorData()
TensorData accessor for single-family scalar data.
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.
shards::CellTopology basisCellTopology_
Base topology of the cells for which the basis is defined. See the Shards package for definition of b...
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.