KOKKOS_INLINE_FUNCTION
  ordinal_type getDkCardinality(const EOperator    operatorType,
                                const ordinal_type spaceDim) {

    // This should only be called for Dk operators
    ordinal_type derivativeOrder;
    switch(operatorType) {

    case OPERATOR_D1:
    case OPERATOR_D2:
    case OPERATOR_D3:
    case OPERATOR_D4:
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      derivativeOrder = Intrepid2::getOperatorOrder(operatorType);
      break;

    default:
      INTREPID2_TEST_FOR_ABORT(true,
                               ">>> ERROR (Intrepid2::getDkCardinality): operator type Dk required for this method");
    }// switch

    ordinal_type cardinality = -999;
    switch(spaceDim) {

    case 1:
      cardinality = 1;
      break;

    case 2:
      cardinality = derivativeOrder + 1;
      break;

    case 3:
      cardinality = (derivativeOrder + 1)*(derivativeOrder + 2)/2;
      break;

    default:
      INTREPID2_TEST_FOR_ABORT( !( (0 < spaceDim ) && (spaceDim < 4) ),
                                ">>> ERROR (Intrepid2::getDkcardinality): Invalid space dimension");
    }

    return cardinality;
  }
  KOKKOS_INLINE_FUNCTION
  ordinal_type getOperatorOrder(const EOperator operatorType) {
    ordinal_type opOrder = -1;

    switch (operatorType) {

    case OPERATOR_VALUE:
      opOrder = 0;
      break;

    case OPERATOR_GRAD:
    case OPERATOR_CURL:
    case OPERATOR_DIV:
    case OPERATOR_D1:
      opOrder = 1;
      break;

    case OPERATOR_D2:
    case OPERATOR_D3:
    case OPERATOR_D4:
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      opOrder = (ordinal_type)operatorType - (ordinal_type)OPERATOR_D1 + 1;
      break;

    default:
      INTREPID2_TEST_FOR_ABORT( !( Intrepid2::isValidOperator(operatorType) ),
                                ">>> ERROR (Intrepid2::getOperatorOrder): Invalid operator type");
    }
    return opOrder;
  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HDIV_TRI_I1_FEM::Serial<opType>::
    getValues(       outputViewType output,
               const inputViewType input ) {
      switch (opType) {
      case OPERATOR_VALUE: {
        const auto x = input(0);
        const auto y = input(1);

        // output is a rank-2 array with dimensions (basisCardinality_)
        output(0, 0) = x;
        output(0, 1) = y - 1.0;

        output(1, 0) =  x;
        output(1, 1) =  y;

        output(2, 0) =  x - 1.0;
        output(2, 1) =  y;
        break;
      }
      case OPERATOR_DIV: {
        // output is a rank-3 array with dimensions (basisCardinality_, spaceDim)
        output(0) = 2;
        output(1) = 2;
        output(2) = 2;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_DIV,
                                  ">>> ERROR: (Intrepid2::Basis_HDIV_TRI_I1_FEM::Serial::getValues) operator is not supported");
      }
      }
    }
  KOKKOS_INLINE_FUNCTION
  ordinal_type getFieldRank(const EFunctionSpace spaceType) {
    ordinal_type fieldRank = -1;

    switch (spaceType) {

    case FUNCTION_SPACE_HGRAD:
    case FUNCTION_SPACE_HVOL:
      fieldRank = 0;
      break;

    case FUNCTION_SPACE_HCURL:
    case FUNCTION_SPACE_HDIV:
    case FUNCTION_SPACE_VECTOR_HGRAD:
      fieldRank = 1;
      break;

    case FUNCTION_SPACE_TENSOR_HGRAD:
      fieldRank = 2;
      break;

    default:
      INTREPID2_TEST_FOR_ABORT( !isValidFunctionSpace(spaceType),
                                ">>> ERROR (Intrepid2::getFieldRank): Invalid function space type");
    }
    return fieldRank;
  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_Constant_FEM::Serial<opType>::
    getValues( /**/  outputViewType output,
               const inputViewType input ) {
      switch (opType) {
      case OPERATOR_VALUE : {
        output(0) = 1.0;
        break;
      }
      case OPERATOR_MAX : {
        const ordinal_type jend = output.dimension(1);
        const ordinal_type iend = output.dimension(0);

        for (ordinal_type j=0;j<jend;++j)
          for (ordinal_type i=0;i<iend;++i)
            output(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_MAX,
                                  ">>> ERROR: (Intrepid2::Basis_Constant_FEM::Serial::getValues) operator is not supported");
      }
      }
    }
  KOKKOS_INLINE_FUNCTION
  ordinal_type getDkEnumeration(const ordinal_type xMult,
                                const ordinal_type yMult,
                                const ordinal_type zMult) {

    if (yMult < 0 && zMult < 0) {

#ifdef HAVE_INTREPID2_DEBUG
      // We are in 1D: verify input - xMult is non-negative  and total order <= 10:
      INTREPID2_TEST_FOR_ABORT( !( (0 <= xMult) && (xMult <= Parameters::MaxDerivative) ),
                                ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
#endif

      // there's only one derivative of order xMult
      return 0;
    } else {
      if (zMult < 0) {

#ifdef HAVE_INTREPID2_DEBUG
        // We are in 2D: verify input - xMult and yMult are non-negative and total order <= 10:
        INTREPID2_TEST_FOR_ABORT( !(0 <= xMult && 0 <= yMult && (xMult + yMult) <= Parameters::MaxDerivative),
                                  ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
#endif

        // enumeration is the value of yMult
        return yMult;
      }

      // We are in 3D: verify input - xMult, yMult and zMult are non-negative and total order <= 10:
      else {
        const auto order = xMult + yMult + zMult;
#ifdef HAVE_INTREPID2_DEBUG
        // Verify input:  total order cannot exceed 10:
        INTREPID2_TEST_FOR_ABORT(  !( (0 <= xMult) && (0 <= yMult) && (0 <= zMult) &&
                                      (order <= Parameters::MaxDerivative) ),
                                   ">>> ERROR (Intrepid2::getDkEnumeration): Derivative order out of range");
#endif
        ordinal_type enumeration = zMult;
        const ordinal_type iend = order-xMult+1;
        for(ordinal_type i=0;i<iend;++i) {
          enumeration += i;
        }
        return enumeration;
      }
    }
  }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HGRAD_TRI_C1_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {
    switch (opType) {
    case OPERATOR_VALUE: {
      const auto x = input(0);
      const auto y = input(1);
      
      // output is a rank-2 array with dimensions (basisCardinality_)
      output(0) = 1.0 - x - y;
      output(1) = x;
      output(2) = y;
      break;
    }
    case OPERATOR_GRAD: {
      // output is a rank-3 array with dimensions (basisCardinality_, spaceDim)
      output(0, 0) = -1.0;
      output(0, 1) = -1.0;
      
      output(1, 0) =  1.0;
      output(1, 1) =  0.0;
      
      output(2, 0) =  0.0;
      output(2, 1) =  1.0;
      break;
    }
    case OPERATOR_CURL: {
      output(0, 0) = -1.0;
      output(0, 1) =  1.0;
      
      output(1, 0) =  0.0;
      output(1, 1) = -1.0;
      
      output(2, 0) =  1.0;
      output(2, 1) =  0.0;
      break;
    }
    case OPERATOR_MAX: {
      const auto jend = output.dimension(1);
      const auto iend = output.dimension(0);

      for (size_type j=0;j<jend;++j)
        for (size_type i=0;i<iend;++i)
          output(i, j) = 0.0;
      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_GRAD &&
                                opType != OPERATOR_CURL &&
                                opType != OPERATOR_MAX,
                                ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C1_FEM::Serial::getValues) operator is not supported");
    }
    }
  }
  KOKKOS_INLINE_FUNCTION
  bool OrientationTools<SpT>::
  isLeftHandedCell(const ptViewType pts) {
#ifdef HAVE_INTREPID2_DEBUG
    INTREPID2_TEST_FOR_ABORT( pts.rank() != 2,  // npts x ndim
                              ">>> ERROR (Intrepid::OrientationTools::isLeftHandedCell): " \
                              "Point array is supposed to have rank 2.");
#endif
    typedef typename ptViewType::value_type value_type;
    
    const auto dim = pts.dimension(1);
    value_type det = 0.0;
    switch (dim) {
    case 2: {
      // need 3 points (origin, x end point, y end point)
      const value_type v[2][2] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1) },
                                   { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1) } };
      
      det = (v[0][0]*v[1][1] - v[1][0]*v[0][1]);
      break;
    }
    case 3: {
      // need 4 points (origin, x end point, y end point, z end point)
      const value_type v[3][3] = { { pts(1,0) - pts(0,0), pts(1,1) - pts(0,1), pts(1,2) - pts(0,2) },
                                   { pts(2,0) - pts(0,0), pts(2,1) - pts(0,1), pts(2,2) - pts(0,2) },
                                   { pts(3,0) - pts(0,0), pts(3,1) - pts(0,1), pts(3,2) - pts(0,2) } };
      
      det = (v[0][0] * v[1][1] * v[2][2] +
             v[0][1] * v[1][2] * v[2][0] +
             v[0][2] * v[1][0] * v[2][1] -
             v[0][2] * v[1][1] * v[2][0] -
             v[0][0] * v[1][2] * v[2][1] -
             v[0][1] * v[1][0] * v[2][2]);
      break;
    }
    default:{
      INTREPID2_TEST_FOR_ABORT( true, 
                                ">>> ERROR (Intrepid::Orientation::isLeftHandedCell): " \
                                "Dimension of points must be 2 or 3");
    }
    }
    return (det < 0.0);
  }
    KOKKOS_INLINE_FUNCTION
    void
    OrientationTools::
    getModifiedLinePoint(VT &ot,
                         const VT pt,
                         const ordinal_type ort) {
#ifdef HAVE_INTREPID2_DEBUG
      INTREPID2_TEST_FOR_ABORT( !( -1.0 <= pt && pt <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedLinePoint): "
                                "Input point is out of range [-1, 1].");
#endif
      
      switch (ort) {
      case 0: ot =  pt; break;
      case 1: ot = -pt; break;
      default:
        INTREPID2_TEST_FOR_ABORT( true, 
                                  ">>> ERROR (Intrepid2::OrientationTools::getModifiedLinePoint): "
                                  "Orientation is invalid (0--1)." );
      }
    }
    KOKKOS_INLINE_FUNCTION
    void
    OrientationTools::
    getModifiedTrianglePoint(VT &ot0,
                             VT &ot1,
                             const VT pt0,
                             const VT pt1,
                             const int ort) {
      const VT lambda[3] = { 1.0 - pt0 - pt1,
                             pt0,
                             pt1 };
      
#ifdef HAVE_INTREPID2_DEBUG
      INTREPID2_TEST_FOR_ABORT( !( 0.0 <= lambda[0] && lambda[0] <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedTrianglePoint): " \
                                "Computed bicentric coordinate (lamba[0]) is out of range [0, 1].");
      
      INTREPID2_TEST_FOR_ABORT( !( 0.0 <= lambda[1] && lambda[1] <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedTrianglePoint): " \
                                "Computed bicentric coordinate (lamba[1]) is out of range [0, 1].");
      
      INTREPID2_TEST_FOR_ABORT( !( 0.0 <= lambda[2] && lambda[2] <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedTrianglePoint): "
                                "Computed bicentric coordinate (lamba[2]) is out of range [0, 1].");
#endif
      
      switch (ort) {
      case 0: ot0 = lambda[1]; ot1 = lambda[2]; break;
      case 1: ot0 = lambda[0]; ot1 = lambda[1]; break;
      case 2: ot0 = lambda[2]; ot1 = lambda[0]; break;
        
      case 3: ot0 = lambda[2]; ot1 = lambda[1]; break;
      case 4: ot0 = lambda[0]; ot1 = lambda[2]; break;
      case 5: ot0 = lambda[1]; ot1 = lambda[0]; break;
      default:
        INTREPID2_TEST_FOR_ABORT( true, 
                                  ">>> ERROR (Intrepid2::OrientationTools::getModifiedTrianglePoint): " \
                                  "Orientation is invalid (0--5)." );
      }
    }
    KOKKOS_INLINE_FUNCTION
    void
    OrientationTools::
    getModifiedQuadrilateralPoint(VT &ot0,
                                  VT &ot1,
                                  const VT pt0,
                                  const VT pt1,
                                  const ordinal_type ort) {
#ifdef HAVE_INTREPID2_DEBUG
      INTREPID2_TEST_FOR_ABORT( !( -1.0 <= pt0 && pt0 <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedQuadrilateralPoint): " \
                                "Input point(0) is out of range [-1, 1].");
      
      INTREPID2_TEST_FOR_ABORT( !( -1.0 <= pt1 && pt1 <= 1.0 ), 
                                ">>> ERROR (Intrepid::OrientationTools::getModifiedQuadrilateralPoint): " \
                                "Input point(1) is out of range [-1, 1].");
#endif
      
      const VT lambda[2][2] = { { pt0, -pt0 },
                                { pt1, -pt1 } };
      
      switch (ort) {
      case 0: ot0 = lambda[0][0]; ot1 = lambda[1][0]; break;
      case 1: ot0 = lambda[1][1]; ot1 = lambda[0][0]; break;
      case 2: ot0 = lambda[0][1]; ot1 = lambda[1][1]; break;
      case 3: ot0 = lambda[1][0]; ot1 = lambda[0][1]; break;
        // flip
      case 4: ot0 = lambda[1][0]; ot1 = lambda[0][0]; break;
      case 5: ot0 = lambda[0][1]; ot1 = lambda[1][0]; break;
      case 6: ot0 = lambda[1][1]; ot1 = lambda[0][1]; break;
      case 7: ot0 = lambda[0][0]; ot1 = lambda[1][1]; break;
      default:
        INTREPID2_TEST_FOR_ABORT( true, 
                                  ">>> ERROR (Intrepid2::OrientationTools::getModifiedQuadrilateralPoint): " \
                                  "Orientation is invalid (0--7)." );
      }
    }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HDIV_TET_I1_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {
    switch (opType) {
    case OPERATOR_VALUE: {
      const auto x = input(0);
      const auto y = input(1);
      const auto z = input(2);

      // output is a rank-2 array with dimensions (basisCardinality_)
      output(0, 0) = 2.0*x;
      output(0, 1) = 2.0*(y - 1.0);
      output(0, 2) = 2.0*z;

      output(1, 0) = 2.0*x;
      output(1, 1) = 2.0*y;
      output(1, 2) = 2.0*z;

      output(2, 0) = 2.0*(x - 1.0);
      output(2, 1) = 2.0*y;
      output(2, 2) = 2.0*z;

      output(3, 0) = 2.0*x;
      output(3, 1) = 2.0*y;
      output(3, 2) = 2.0*(z - 1.0);
      break;
    }
    case OPERATOR_DIV: {
      // output is a rank-3 array with dimensions (basisCardinality_, spaceDim)
      output(0) = 6;
      output(1) = 6;
      output(2) = 6;
      output(3) = 6;
      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_DIV,
                                ">>> ERROR: (Intrepid2::Basis_HDIV_TET_I1_FEM::Serial::getValues) operator is not supported");
    }
    }
  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_TRI_Cn_FEM_ORTH::Serial<opType>::
    getValues( /**/  outputViewType output,
               const inputViewType  input,
               const ordinal_type   order,
               const ordinal_type   operatorDn ) {
      ordinal_type opDn = operatorDn;

      switch (opType) {
      case OPERATOR_VALUE: {
        OrthPolynomial<0>( output, order, input );
        break;
      }
      case OPERATOR_GRAD:
      case OPERATOR_D1: {
        OrthPolynomial<1>( output, order, input );
        break;
      }
      case OPERATOR_D2:
      case OPERATOR_D3:
      case OPERATOR_D4:
      case OPERATOR_D5:
      case OPERATOR_D6:
      case OPERATOR_D7:
      case OPERATOR_D8:
      case OPERATOR_D9:
      case OPERATOR_D10:
        opDn = getOperatorOrder(opType);
      case OPERATOR_Dn: {
        OrthPolynomial( output, order, input, opDn );
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( true,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_Cn_FEM_ORTH::Serial::getValues) operator is not supported");
      }
      }
    }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HGRAD_LINE_C1_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {
    switch (opType) {
    case OPERATOR_VALUE : {
      const auto x = input();

      output(0) = (1.0 - x)/2.0;
      output(1) = (1.0 + x)/2.0;
      break;
    }
    case OPERATOR_GRAD : {
      output(0, 0) = -0.5;
      output(1, 0) =  0.5;
      break;
    }
    case OPERATOR_MAX : {
      const auto jend = output.dimension(1);
      const auto iend = output.dimension(0);

      for (size_type j=0;j<jend;++j)
        for (size_type i=0;i<iend;++i)
          output(i, j) = 0.0;
      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_GRAD &&
                                opType != OPERATOR_MAX,
                                ">>> ERROR: (Intrepid2::Basis_HGRAD_LINE_C1_FEM::Serial::getValues) operator is not supported");

    }
    }
  }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HCURL_TRI_I1_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {
    switch (opType) {
    case OPERATOR_VALUE: {
      const auto x = input(0);
      const auto y = input(1);
      
      // output is a subdynrankview of a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim), dim0 iteration of range
      output(0, 0) = 1.0 - y;
      output(0, 1) = x;
      
      output(1, 0) = -y;
      output(1, 1) =  x;
      
      output(2, 0) = -y;
      output(2, 1) = -1.0 + x;
      break;
    }
    case OPERATOR_CURL: {
      // outputValues is a subdynrankview of a rank-2 array with dimensions (basisCardinality_, dim0), dim0 iteration of range
      output(0) = 2.0;
      output(1) = 2.0;
      output(2) = 2.0;

      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_CURL,
                                ">>> ERROR: (Intrepid2::Basis_HCURL_TRI_I1_FEM::Serial::getValues) operator is not supported");
    }
    }
  }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HCURL_HEX_I1_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {

    switch (opType) {
    case OPERATOR_VALUE: {
      const auto x = input(0);
      const auto y = input(1);
      const auto z = input(2);

      // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
      output(0, 0) = (1.0 - y)*(1.0 - z)/8.0;
      output(0, 1) = 0.0;
      output(0, 2) = 0.0;
          
      output(1, 0) = 0.0;
      output(1, 1) = (1.0 + x)*(1.0 - z)/8.0;
      output(1, 2) = 0.0;
          
      output(2, 0) = -(1.0 + y)*(1.0 - z)/8.0;
      output(2, 1) = 0.0;
      output(2, 2) = 0.0;
          
      output(3, 0) = 0.0;
      output(3, 1) = -(1.0 - x)*(1.0 - z)/8.0;
      output(3, 2) = 0.0;
          
      output(4, 0) = (1.0 - y)*(1.0 + z)/8.0;
      output(4, 1) = 0.0;
      output(4, 2) = 0.0;
          
      output(5, 0) = 0.0;
      output(5, 1) = (1.0 + x)*(1.0 + z)/8.0;
      output(5, 2) = 0.0;
          
      output(6, 0) = -(1.0 + y)*(1.0 + z)/8.0;
      output(6, 1) = 0.0;
      output(6, 2) = 0.0;
          
      output(7, 0) = 0.0;
      output(7, 1) = -(1.0 - x)*(1.0 + z)/8.0;
      output(7, 2) = 0.0;
          
      output(8, 0) = 0.0;
      output(8, 1) = 0.0;
      output(8, 2) = (1.0 - x)*(1.0 - y)/8.0;
          
      output(9, 0) = 0.0;
      output(9, 1) = 0.0;
      output(9, 2) = (1.0 + x)*(1.0 - y)/8.0;
          
      output(10, 0) = 0.0;
      output(10, 1) = 0.0;
      output(10, 2) = (1.0 + x)*(1.0 + y)/8.0;
          
      output(11, 0) = 0.0;
      output(11, 1) = 0.0;
      output(11, 2) = (1.0 - x)*(1.0 + y)/8.0;
      break;
    }
    case OPERATOR_CURL: {
      const auto x = input(0);
      const auto y = input(1);
      const auto z = input(2);

      // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
      output(0, 0) = 0.0;
      output(0, 1) = -(1.0 - y)/8.0;
      output(0, 2) = (1.0 - z)/8.0;

      output(1, 0) = (1.0 + x)/8.0;
      output(1, 1) = 0.0;
      output(1, 2) = (1.0 - z)/8.0;

      output(2, 0) = 0.0;
      output(2, 1) = (1.0 + y)/8.0;
      output(2, 2) = (1.0 - z)/8.0;

      output(3, 0) = -(1.0 - x)/8.0;
      output(3, 1) = 0.0;
      output(3, 2) = (1.0 - z)/8.0;

      output(4, 0) = 0.0;
      output(4, 1) = (1.0 - y)/8.0;
      output(4, 2) = (1.0 + z)/8.0;

      output(5, 0) = -(1.0 + x)/8.0;
      output(5, 1) = 0.0;
      output(5, 2) = (1.0 + z)/8.0;

      output(6, 0) = 0.0;
      output(6, 1) = -(1.0 + y)/8.0;
      output(6, 2) = (1.0 + z)/8.0;

      output(7, 0) = (1.0 - x)/8.0;
      output(7, 1) = 0.0;
      output(7, 2) = (1.0 + z)/8.0;

      output(8, 0) = -(1.0 - x)/8.0;
      output(8, 1) = (1.0 - y)/8.0;
      output(8, 2) = 0.0;

      output(9, 0) = -(1.0 + x)/8.0;
      output(9, 1) = -(1.0 - y)/8.0;
      output(9, 2) = 0.0;

      output(10, 0) = (1.0 + x)/8.0;
      output(10, 1) = -(1.0 + y)/8.0;
      output(10, 2) = 0.0;

      output(11, 0) = (1.0 - x)/8.0;
      output(11, 1) = (1.0 + y)/8.0;
      output(11, 2) = 0.0;
      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_CURL, 
                                ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_C1_FEM::Serial::getValues) operator is not supported");
    }
    } //end switch

  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_TET_COMP12_FEM::Serial<opType>::
    getValues(       outputValueViewType output,
               const inputPointViewType  input ) {
      switch (opType) {
      case OPERATOR_VALUE: {
        const typename inputPointViewType::value_type r = input(0);
        const typename inputPointViewType::value_type s = input(1);
        const typename inputPointViewType::value_type t = input(2);

        // initialize output 
        for (auto i=0;i<10;++i) 
          output(i) = 0.0;
        
        const auto subtet = getLocalSubTet( r, s, t );
        
        // idependent verification shows that a given point will produce
        // the same shape functions for each tet that contains it, so
        // we only need to use the first one returned.
        if (subtet != -1) {
          typename inputPointViewType::value_type aux = 0.0;
          switch (subtet) {
          case 0:
            output(0) = 1. - 2. * (r + s + t);
            output(4) = 2. * r;
            output(6) = 2. * s;
            output(7) = 2. * t;
            break;
          case 1:
            output(1) = 2. * r - 1.;
            output(4) = 2. - 2. * (r + s + t);
            output(5) = 2. * s;
            output(8) = 2. * t;
            break;
          case 2:
            output(2) = 2. * s - 1.;
            output(5) = 2. * r;
            output(6) = 2. - 2. * (r + s + t);
            output(9) = 2. * t;
            break;
          case 3:
            output(3) = 2. * t - 1.;
            output(7) = 2. - 2. * (r + s + t);
            output(8) = 2. * r;
            output(9) = 2. * s;
            break;
          case 4:
            output(4) = 1. - 2. * (s + t);
            output(5) = 2. * (r + s) - 1.;
            output(8) = 2. * (r + t) - 1.;
            aux = 2. - 4. * r;
            break;
          case 5:
            output(5) = 2. * (r + s) - 1.;
            output(8) = 2. * (r + t) - 1.;
            output(9) = 2. * (s + t) - 1.;
            aux = 4. - 4. * (r + s + t);
            break;
          case 6:
            output(7) = 1. - 2. * (r + s);
            output(8) = 2. * (r + t) - 1.;
            output(9) = 2. * (s + t) - 1.;
            aux = 2. - 4. * t;
            break;
          case 7:
            output(4) = 1. - 2. * (s + t);
            output(7) = 1. - 2. * (r + s);
            output(8) = 2. * (r + t) - 1.;
            aux = 4. * s;
            break;
          case 8:
            output(4) = 1. - 2. * (s + t);
            output(5) = 2. * (r + s) - 1.;
            output(6) = 1. - 2. * (r + t);
            aux = 4. * t;
            break;
          case 9:
            output(5) = 2. * (r + s) - 1.;
            output(6) = 1. - 2. * (r + t);
            output(9) = 2. * (s + t) - 1.;
            aux = 2. - 4. * s;
            break;
          case 10:
            output(6) = 1. - 2. * (r + t);
            output(7) = 1. - 2. * (r + s);
            output(9) = 2. * (s + t) - 1.;
            aux = 4. * r;
            break;
          case 11:
            output(4) = 1. - 2. * (s + t);
            output(6) = 1. - 2. * (r + t);
            output(7) = 1. - 2. * (r + s);
            aux = 4. * (r + s + t) - 2.;
            break;
          }
          for (auto i=4;i<10;++i)
            output(i) += aux/6.0;
        }
        break;
      }
      case OPERATOR_GRAD: {
        const typename inputPointViewType::value_type r = input(0);
        const typename inputPointViewType::value_type s = input(1);
        const typename inputPointViewType::value_type t = input(2);
        
        output(0,0) = (-17 + 20*r + 20*s + 20*t)/8.;
        output(0,1) = (-17 + 20*r + 20*s + 20*t)/8.;
        output(0,2) = (-17 + 20*r + 20*s + 20*t)/8.;
        output(1,0) = -0.375 + (5*r)/2.;
        output(1,1) = 0.;
        output(1,2) = 0.;
        output(2,0) = 0.;
        output(2,1) = -0.375 + (5*s)/2.;
        output(2,2) = 0.;
        output(3,0) = 0.;
        output(3,1) = 0.;
        output(3,2) = -0.375 + (5*t)/2.;
        output(4,0) = (-35*(-1 + 2*r + s + t))/12.;
        output(4,1) = (-4 - 35*r + 5*s + 10*t)/12.;
        output(4,2) = (-4 - 35*r + 10*s + 5*t)/12.;
        output(5,0) = (-1 + 5*r + 40*s - 5*t)/12.;
        output(5,1) = (-1 + 40*r + 5*s - 5*t)/12.;
        output(5,2) = (-5*(-1 + r + s + 2*t))/12.;
        output(6,0) = (-4 + 5*r - 35*s + 10*t)/12.;
        output(6,1) = (-35*(-1 + r + 2*s + t))/12.;
        output(6,2) = (-4 + 10*r - 35*s + 5*t)/12.;
        output(7,0) = (-4 + 5*r + 10*s - 35*t)/12.;
        output(7,1) = (-4 + 10*r + 5*s - 35*t)/12.;
        output(7,2) = (-35*(-1 + r + s + 2*t))/12.;
        output(8,0) = (-1 + 5*r - 5*s + 40*t)/12.;
        output(8,1) = (-5*(-1 + r + 2*s + t))/12.;
        output(8,2) = (-1 + 40*r - 5*s + 5*t)/12.;
        output(9,0) = (-5*(-1 + 2*r + s + t))/12.;
        output(9,1) = (-1 - 5*r + 5*s + 40*t)/12.;
        output(9,2) = (-1 - 5*r + 40*s + 5*t)/12.;
        break;
      }
      case OPERATOR_MAX: {
        const ordinal_type jend = output.dimension(1);
        const ordinal_type iend = output.dimension(0);

        for (ordinal_type j=0;j<jend;++j)
          for (auto i=0;i<iend;++i)
            output(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( true , 
                                  ">>> ERROR (Basis_HGRAD_TET_COMP12_FEM): Operator type not implemented" );
      }
      }
    }
    KOKKOS_INLINE_FUNCTION                                                                                                                                               
    void                                                                                                                                                                 
    Basis_HGRAD_TET_C2_FEM::Serial<opType>::                                                                                                                             
    getValues(       outputViewType output,                                                                                                                              
               const inputViewType input ) {   
      switch (opType) {
      case OPERATOR_VALUE: {
        const auto x = input(0);
        const auto y = input(1);
        const auto z = input(2);
        
        // output is a rank-2 array with dimensions (basisCardinality_, dim0)
        output.access(0) = (-1. + x + y + z)*(-1. + 2.*x + 2.*y + 2.*z);
        output.access(1) = x*(-1. + 2.*x);
        output.access(2) = y*(-1. + 2.*y);
        output.access(3) = z*(-1. + 2.*z);

        output.access(4) = -4.*x*(-1. + x + y + z);
        output.access(5) =  4.*x*y;
        output.access(6) = -4.*y*(-1. + x + y + z);
        output.access(7) = -4.*z*(-1. + x + y + z);
        output.access(8) =  4.*x*z;
        output.access(9) =  4.*y*z;
        break;
      }
      case OPERATOR_D1:
      case OPERATOR_GRAD: {
        const auto x = input(0);
        const auto y = input(1);
        const auto z = input(2);
        
        // output.access is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        output.access(0, 0) = -3.+ 4.*x + 4.*y + 4.*z;
        output.access(0, 1) = -3.+ 4.*x + 4.*y + 4.*z;
        output.access(0, 2) = -3.+ 4.*x + 4.*y + 4.*z; 
      
        output.access(1, 0) = -1.+ 4.*x; 
        output.access(1, 1) =  0.;
        output.access(1, 2) =  0.;
      
        output.access(2, 0) =  0.;        
        output.access(2, 1) = -1.+ 4.*y;
        output.access(2, 2) =  0.;

        output.access(3, 0) =  0.;         
        output.access(3, 1) =  0.;
        output.access(3, 2) = -1.+ 4.*z;
 
      
        output.access(4, 0) = -4.*(-1.+ 2*x + y + z);         
        output.access(4, 1) = -4.*x;
        output.access(4, 2) = -4.*x;
      
        output.access(5, 0) =  4.*y;       
        output.access(5, 1) =  4.*x; 
        output.access(5, 2) =  0.;

        output.access(6, 0) = -4.*y;          
        output.access(6, 1) = -4.*(-1.+ x + 2*y + z);
        output.access(6, 2) = -4.*y; 

        output.access(7, 0) = -4.*z;          
        output.access(7, 1) = -4.*z;
        output.access(7, 2) = -4.*(-1.+ x + y + 2*z);

        output.access(8, 0) =  4.*z;     
        output.access(8, 1) =  0.;
        output.access(8, 2) =  4.*x;

        output.access(9, 0) =  0.;         
        output.access(9, 1) =  4.*z;
        output.access(9, 2) =  4.*y;
        break;
      }
      case OPERATOR_D2: {
        output.access(0, 0) =  4.;
        output.access(0, 1) =  4.;
        output.access(0, 2) =  4.;
        output.access(0, 3) =  4.;
        output.access(0, 4) =  4.;
        output.access(0, 5) =  4.;
      
        output.access(1, 0) =  4.;
        output.access(1, 1) =  0.;
        output.access(1, 2) =  0.;
        output.access(1, 3) =  0.;
        output.access(1, 4) =  0.;
        output.access(1, 5) =  0.;

        output.access(2, 0) =  0.;
        output.access(2, 1) =  0.;
        output.access(2, 2) =  0.;
        output.access(2, 3) =  4.;
        output.access(2, 4) =  0.;
        output.access(2, 5) =  0.;

        output.access(3, 0) =  0.;
        output.access(3, 1) =  0.;
        output.access(3, 2) =  0.;
        output.access(3, 3) =  0.;
        output.access(3, 4) =  0.;
        output.access(3, 5) =  4.;

        output.access(4, 0) = -8.;
        output.access(4, 1) = -4.;
        output.access(4, 2) = -4.;
        output.access(4, 3) =  0.;
        output.access(4, 4) =  0.;
        output.access(4, 5) =  0.;

        output.access(5, 0) =  0.;
        output.access(5, 1) =  4.;
        output.access(5, 2) =  0.;
        output.access(5, 3) =  0.;
        output.access(5, 4) =  0.;
        output.access(5, 5) =  0.;

        output.access(6, 0) =  0.;
        output.access(6, 1) = -4.;
        output.access(6, 2) =  0.;
        output.access(6, 3) = -8.;
        output.access(6, 4) = -4.;
        output.access(6, 5) =  0;

        output.access(7, 0) =  0.;
        output.access(7, 1) =  0.;
        output.access(7, 2) = -4.;
        output.access(7, 3) =  0.;
        output.access(7, 4) = -4.;
        output.access(7, 5) = -8.;

        output.access(8, 0) =  0.;
        output.access(8, 1) =  0.;
        output.access(8, 2) =  4.;
        output.access(8, 3) =  0.;
        output.access(8, 4) =  0.;
        output.access(8, 5) =  0.;

        output.access(9, 0) =  0.;
        output.access(9, 1) =  0.;
        output.access(9, 2) =  0.;
        output.access(9, 3) =  0.;
        output.access(9, 4) =  4.;
        output.access(9, 5) =  0.;
        break;
      }
      case OPERATOR_MAX: {
        const ordinal_type jend = output.extent(1);
        const ordinal_type iend = output.extent(0);

        for (ordinal_type j=0;j<jend;++j)
          for (ordinal_type i=0;i<iend;++i)
            output.access(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_GRAD &&
                                  opType != OPERATOR_D1 &&
                                  opType != OPERATOR_D2 &&
                                  opType != OPERATOR_MAX,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_C2_FEM::Serial::getValues) operator is not supported");
      }
      }
    }
  KOKKOS_INLINE_FUNCTION
  ordinal_type getOperatorRank(const EFunctionSpace spaceType,
                               const EOperator      operatorType,
                               const ordinal_type   spaceDim) {

    const auto fieldRank = Intrepid2::getFieldRank(spaceType);
#ifdef HAVE_INTREPID2_DEBUG
    // Verify arguments: field rank can be 0,1, or 2, spaceDim can be 1,2, or 3.
    INTREPID2_TEST_FOR_ABORT( !(0 <= fieldRank && fieldRank <= 2),
                              ">>> ERROR (Intrepid2::getOperatorRank): Invalid field rank");
    INTREPID2_TEST_FOR_ABORT( !(1 <= spaceDim && spaceDim  <= 3),
                              ">>> ERROR (Intrepid2::getOperatorRank): Invalid space dimension");
#endif
    ordinal_type operatorRank = -999;
    
    // In 1D GRAD, CURL, and DIV default to d/dx; Dk defaults to d^k/dx^k, no casing needed.
    if (spaceDim == 1) {
      if (fieldRank == 0) {
        // By default, in 1D any operator other than VALUE has rank 1
        if (operatorType == OPERATOR_VALUE) {
          operatorRank = 0;
        } else {
          operatorRank = 1;
        }
      }
      
      // Only scalar fields are allowed in 1D
      else {
        INTREPID2_TEST_FOR_ABORT( fieldRank > 0,
                                  ">>> ERROR (getOperatorRank): Only scalar fields are allowed in 1D");
      } // fieldRank == 0
    } // spaceDim == 1
    
    // We are either in 2D or 3D
    else {
      switch (operatorType) {
      case OPERATOR_VALUE:
        operatorRank = 0;
        break;
        
      case OPERATOR_GRAD:
      case OPERATOR_D1:
      case OPERATOR_D2:
      case OPERATOR_D3:
      case OPERATOR_D4:
      case OPERATOR_D5:
      case OPERATOR_D6:
      case OPERATOR_D7:
      case OPERATOR_D8:
      case OPERATOR_D9:
      case OPERATOR_D10:
        operatorRank = 1;
        break;

      case OPERATOR_CURL:

        // operator rank for vector and tensor fields equals spaceDim - 3 (-1 in 2D and 0 in 3D)
        if (fieldRank > 0) {
          operatorRank = spaceDim - 3;
        } else {
          
          // CURL can be applied to scalar functions (rank = 0) in 2D and gives a vector (rank = 1)
          if (spaceDim == 2) {
            operatorRank = 3 - spaceDim;
          }
          
          // If we are here, fieldRank=0, spaceDim=3: CURL is undefined for 3D scalar functions
          else {
            INTREPID2_TEST_FOR_ABORT( ( (spaceDim == 3) && (fieldRank == 0) ),
                                      ">>> ERROR (Intrepid2::getOperatorRank): CURL cannot be applied to scalar fields in 3D");
          }
        }
        break;
        
      case OPERATOR_DIV:

        // DIV can be applied to vectors and tensors and has rank -1 in 2D and 3D
        if (fieldRank > 0) {
          operatorRank = -1;
        }

        // DIV cannot be applied to scalar fields except in 1D where it defaults to d/dx
        else {
          INTREPID2_TEST_FOR_ABORT( ( (spaceDim > 1) && (fieldRank == 0) ),
                                    ">>> ERROR (Intrepid2::getOperatorRank): DIV cannot be applied to scalar fields in 2D and 3D");
        }
        break;

      default:
        INTREPID2_TEST_FOR_ABORT( !( isValidOperator(operatorType) ),
                                  ">>> ERROR (Intrepid2::getOperatorRank): Invalid operator type");
      } // switch
    }// 2D and 3D

    return operatorRank;
  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_QUAD_C1_FEM::Serial<opType>::
    getValues(       outputViewType output,
               const inputViewType input ) {
      switch (opType) {
      case OPERATOR_VALUE : {
        const auto x = input(0);
        const auto y = input(1);

        // output with dimensions (basisCardinality_)
        output(0) = (1.0 - x)*(1.0 - y)/4.0;
        output(1) = (1.0 + x)*(1.0 - y)/4.0;
        output(2) = (1.0 + x)*(1.0 + y)/4.0;
        output(3) = (1.0 - x)*(1.0 + y)/4.0;
        break;
      }
      case OPERATOR_GRAD : {
        const auto x = input(0);
        const auto y = input(1);

        // output with dimensions (basisCardinality_, spaceDim)
        output(0, 0) = -(1.0 - y)/4.0;
        output(0, 1) = -(1.0 - x)/4.0;

        output(1, 0) =  (1.0 - y)/4.0;
        output(1, 1) = -(1.0 + x)/4.0;

        output(2, 0) =  (1.0 + y)/4.0;
        output(2, 1) =  (1.0 + x)/4.0;

        output(3, 0) = -(1.0 + y)/4.0;
        output(3, 1) =  (1.0 - x)/4.0;
        break;
      }
      case OPERATOR_CURL : {
        const auto x = input(0);
        const auto y = input(1);

        // output with dimensions (basisCardinality_, spaceDim)
        output(0, 0) = -(1.0 - x)/4.0;
        output(0, 1) =  (1.0 - y)/4.0;

        output(1, 0) = -(1.0 + x)/4.0;
        output(1, 1) = -(1.0 - y)/4.0;

        output(2, 0) =  (1.0 + x)/4.0;
        output(2, 1) = -(1.0 + y)/4.0;

        output(3, 0) =  (1.0 - x)/4.0;
        output(3, 1) =  (1.0 + y)/4.0;
        break;
      }
      case OPERATOR_D2 : {
        // output with dimensions (basisCardinality_, D2Cardinality=3)
        output(0, 0) =  0.0;
        output(0, 1) =  0.25;
        output(0, 2) =  0.0;

        output(1, 0) =  0.0;
        output(1, 1) = -0.25;
        output(1, 2) =  0.0;

        output(2, 0) =  0.0;
        output(2, 1) =  0.25;
        output(2, 2) =  0.0;

        output(3, 0) =  0.0;
        output(3, 1) = -0.25;
        output(3, 2) =  0.0;
        break;
      }
      case OPERATOR_MAX : {
        const ordinal_type jend = output.dimension(1);
        const ordinal_type iend = output.dimension(0);

        for (ordinal_type j=0;j<jend;++j)
          for (ordinal_type i=0;i<iend;++i)
            output(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_GRAD &&
                                  opType != OPERATOR_CURL &&
                                  opType != OPERATOR_D2 &&
                                  opType != OPERATOR_MAX,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C1_FEM::Serial::getValues) operator is not supported");

      }
      }
    }
  KOKKOS_INLINE_FUNCTION
  void
  Basis_HGRAD_TET_C2_FEM<SpT,OT,PT>::Serial<opType>::
  getValues( /**/  Kokkos::DynRankView<outputValueValueType,outputValueProperties...> output,
             const Kokkos::DynRankView<inputPointValueType, inputPointProperties...>  input ) {
    switch (opType) {
    case OPERATOR_VALUE: {
      const auto x = input(0);
      const auto y = input(1);
      const auto z = input(2);
        
      // output is a rank-2 array with dimensions (basisCardinality_, dim0)
      output(0) = (-1. + x + y + z)*(-1. + 2.*x + 2.*y + 2.*z);
      output(1) = x*(-1. + 2.*x);
      output(2) = y*(-1. + 2.*y);
      output(3) = z*(-1. + 2.*z);

      output(4) = -4.*x*(-1. + x + y + z);
      output(5) =  4.*x*y;
      output(6) = -4.*y*(-1. + x + y + z);
      output(7) = -4.*z*(-1. + x + y + z);
      output(8) =  4.*x*z;
      output(9) =  4.*y*z;
      break;
    }
    case OPERATOR_D1:
    case OPERATOR_GRAD: {
      const auto x = input(0);
      const auto y = input(1);
      const auto z = input(2);
        
      // output is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
      output(0, 0) = -3.+ 4.*x + 4.*y + 4.*z;
      output(0, 1) = -3.+ 4.*x + 4.*y + 4.*z;
      output(0, 2) = -3.+ 4.*x + 4.*y + 4.*z; 
      
      output(1, 0) = -1.+ 4.*x; 
      output(1, 1) =  0.;
      output(1, 2) =  0.;
      
      output(2, 0) =  0.;        
      output(2, 1) = -1.+ 4.*y;
      output(2, 2) =  0.;

      output(3, 0) =  0.;         
      output(3, 1) =  0.;
      output(3, 2) = -1.+ 4.*z;
 
      
      output(4, 0) = -4.*(-1.+ 2*x + y + z);         
      output(4, 1) = -4.*x;
      output(4, 2) = -4.*x;
      
      output(5, 0) =  4.*y;       
      output(5, 1) =  4.*x; 
      output(5, 2) =  0.;

      output(6, 0) = -4.*y;          
      output(6, 1) = -4.*(-1.+ x + 2*y + z);
      output(6, 2) = -4.*y; 

      output(7, 0) = -4.*z;          
      output(7, 1) = -4.*z;
      output(7, 2) = -4.*(-1.+ x + y + 2*z);

      output(8, 0) =  4.*z;     
      output(8, 1) =  0.;
      output(8, 2) =  4.*x;

      output(9, 0) =  0.;         
      output(9, 1) =  4.*z;
      output(9, 2) =  4.*y;
      break;
    }
    case OPERATOR_D2: {
      output(0, 0) =  4.;
      output(0, 1) =  4.;
      output(0, 2) =  4.;
      output(0, 3) =  4.;
      output(0, 4) =  4.;
      output(0, 5) =  4.;
      
      output(1, 0) =  4.;
      output(1, 1) =  0.;
      output(1, 2) =  0.;
      output(1, 3) =  0.;
      output(1, 4) =  0.;
      output(1, 5) =  0.;

      output(2, 0) =  0.;
      output(2, 1) =  0.;
      output(2, 2) =  0.;
      output(2, 3) =  4.;
      output(2, 4) =  0.;
      output(2, 5) =  0.;

      output(3, 0) =  0.;
      output(3, 1) =  0.;
      output(3, 2) =  0.;
      output(3, 3) =  0.;
      output(3, 4) =  0.;
      output(3, 5) =  4.;

      output(4, 0) = -8.;
      output(4, 1) = -4.;
      output(4, 2) = -4.;
      output(4, 3) =  0.;
      output(4, 4) =  0.;
      output(4, 5) =  0.;

      output(5, 0) =  0.;
      output(5, 1) =  4.;
      output(5, 2) =  0.;
      output(5, 3) =  0.;
      output(5, 4) =  0.;
      output(5, 5) =  0.;

      output(6, 0) =  0.;
      output(6, 1) = -4.;
      output(6, 2) =  0.;
      output(6, 3) = -8.;
      output(6, 4) = -4.;
      output(6, 5) =  0;

      output(7, 0) =  0.;
      output(7, 1) =  0.;
      output(7, 2) = -4.;
      output(7, 3) =  0.;
      output(7, 4) = -4.;
      output(7, 5) = -8.;

      output(8, 0) =  0.;
      output(8, 1) =  0.;
      output(8, 2) =  4.;
      output(8, 3) =  0.;
      output(8, 4) =  0.;
      output(8, 5) =  0.;

      output(9, 0) =  0.;
      output(9, 1) =  0.;
      output(9, 2) =  0.;
      output(9, 3) =  0.;
      output(9, 4) =  4.;
      output(9, 5) =  0.;
      break;
    }
    case OPERATOR_MAX: {
      const auto jend = output.dimension(1);
      const auto iend = output.dimension(0);

      for (auto j=0;j<jend;++j)
        for (auto i=0;i<iend;++i)
          output(i, j) = 0.0;
      break;
    }
    default: {
      INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                opType != OPERATOR_GRAD &&
                                opType != OPERATOR_D1 &&
                                opType != OPERATOR_D2 &&
                                opType != OPERATOR_MAX,
                                ">>> ERROR: (Intrepid2::Basis_HGRAD_TET_C2_FEM::Serial::getValues) operator is not supported");
    }
    }
  }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_LINE_Cn_FEM::Serial<opType>::
    getValues(       outputViewType output,
               const inputViewType  input,
                     workViewType   work,
               const vinvViewType   vinv,
               const ordinal_type   operatorDn ) {    
      ordinal_type opDn = operatorDn;

      const ordinal_type card = vinv.dimension(0);
      const ordinal_type npts = input.dimension(0);

      const ordinal_type order = card - 1;
      const double alpha = 0.0, beta = 0.0;

      typedef typename Kokkos::DynRankView<typename workViewType::value_type, typename workViewType::memory_space> viewType;
      auto vcprop = Kokkos::common_view_alloc_prop(work);
      
      switch (opType) {
      case OPERATOR_VALUE: {
        viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts);     

        Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI::
          Serial<opType>::getValues(phis, input, order, alpha, beta);

        for (ordinal_type i=0;i<card;++i) 
          for (ordinal_type j=0;j<npts;++j) {
            output(i,j) = 0.0;
            for (ordinal_type k=0;k<card;++k)
              output(i,j) += vinv(k,i)*phis(k,j);
          }
        break;
      }
      case OPERATOR_GRAD:
      case OPERATOR_D1:
      case OPERATOR_D2:
      case OPERATOR_D3:
      case OPERATOR_D4:
      case OPERATOR_D5:
      case OPERATOR_D6:
      case OPERATOR_D7:
      case OPERATOR_D8:
      case OPERATOR_D9:
      case OPERATOR_D10: 
        opDn = getOperatorOrder(opType);
      case OPERATOR_Dn: {
        // dkcard is always 1 for 1D element
        const ordinal_type dkcard = 1;
        viewType phis(Kokkos::view_wrap(work.data(), vcprop), card, npts, dkcard);     
        Impl::Basis_HGRAD_LINE_Cn_FEM_JACOBI::
          Serial<opType>::getValues(phis, input, order, alpha, beta, opDn);

        for (ordinal_type i=0;i<card;++i) 
          for (ordinal_type j=0;j<npts;++j) 
            for (ordinal_type k=0;k<dkcard;++k) {
              output(i,j,k) = 0.0;
              for (ordinal_type l=0;l<card;++l)
                output(i,j,k) += vinv(l,i)*phis(l,j,k);
            }
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( true,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_LINE_Cn_FEM::Serial::getValues) operator is not supported." );
      }
      }
    }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_TRI_C2_FEM::Serial<opType>::
    getValues( /**/  outputViewType output,
               const inputViewType input ) {
      switch (opType) {
      case OPERATOR_VALUE: {
        const auto x = input(0);
        const auto y = input(1);

        // output is a rank-2 array with dimensions (basisCardinality_, dim0)
        output(0) = (x + y - 1.0)*(2.0*x + 2.0*y - 1.0);
        output(1) = x*(2.0*x - 1.0);
        output(2) = y*(2.0*y - 1.0);
        output(3) = -4.0*x*(x + y - 1.0);
        output(4) =  4.0*x*y;
        output(5) = -4.0*y*(x + y - 1.0);
        break;
      }
      case OPERATOR_D1:
      case OPERATOR_GRAD: {
        const auto x = input(0);
        const auto y = input(1);
        // output is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        output(0, 0) =  4.0*x + 4.0*y - 3.0;
        output(0, 1) =  4.0*x + 4.0*y - 3.0;

        output(1, 0) =  4.0*x - 1.0;
        output(1, 1) =  0.0;

        output(2, 0) =  0.0;
        output(2, 1) =  4.0*y - 1.0;

        output(3, 0) = -4.0*(2.0*x + y - 1.0);
        output(3, 1) = -4.0*x;

        output(4, 0) =  4.0*y;
        output(4, 1) =  4.0*x;

        output(5, 0) = -4.0*y;
        output(5, 1) = -4.0*(x + 2.0*y - 1.0);
        break;
      }
      case OPERATOR_CURL: {
        const auto x = input(0);
        const auto y = input(1);
        // CURL(u) = (u_y, -u_x), is rotated GRAD
        output(0, 1) =-(4.0*x + 4.0*y - 3.0);
        output(0, 0) =  4.0*x + 4.0*y - 3.0;

        output(1, 1) =-(4.0*x - 1.0);
        output(1, 0) =  0.0;

        output(2, 1) =  0.0;
        output(2, 0) =  4.0*y - 1.0;

        output(3, 1) =  4.0*(2.0*x + y - 1.0);
        output(3, 0) = -4.0*x;

        output(4, 1) = -4.0*y;
        output(4, 0) =  4.0*x;

        output(5, 1) =  4.0*y;
        output(5, 0) = -4.0*(x + 2.0*y - 1.0);
        break;
      }
      case OPERATOR_D2: {
        // output is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        // D2 -> (2,0) -> dx^2.
        output(0, 0) = 4.0;
        output(1, 0) = 4.0;
        output(2, 0) = 0.0;
        output(3, 0) =-8.0;
        output(4, 0) = 0.0;
        output(5, 0) = 0.0;

        // D2 -> (1,1) -> dx dy
        output(0, 1) = 4.0;
        output(1, 1) = 0.0;
        output(2, 1) = 0.0;
        output(3, 1) =-4.0;
        output(4, 1) = 4.0;
        output(5, 1) =-4.0;

        // D2 -> (0,2) -> dy^2
        output(0, 2) = 4.0;
        output(1, 2) = 0.0;
        output(2, 2) = 4.0;
        output(3, 2) = 0.0;
        output(4, 2) = 0.0;
        output(5, 2) =-8.0;
        break;
      }
      case OPERATOR_MAX: {
        const ordinal_type jend = output.dimension(1);
        const ordinal_type iend = output.dimension(0);

        for (ordinal_type j=0;j<jend;++j)
          for (ordinal_type i=0;i<iend;++i)
            output(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_GRAD &&
                                  opType != OPERATOR_CURL &&
                                  opType != OPERATOR_D1 &&
                                  opType != OPERATOR_D2 &&
                                  opType != OPERATOR_MAX,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_TRI_C2_FEM::Serial::getValues) operator is not supported");
      }
      }
    }
    KOKKOS_INLINE_FUNCTION
    void
    Basis_HGRAD_HEX_C1_FEM::Serial<opType>::
    getValues( /**/  outputViewType output,
               const inputViewType input ) {
      switch (opType) {
      case OPERATOR_VALUE : {
        const auto x = input(0);
        const auto y = input(1);
        const auto z = input(2);

        // output is a rank-2 array with dimensions (basisCardinality_, dim0)
        output(0) = (1.0 - x)*(1.0 - y)*(1.0 - z)/8.0;
        output(1) = (1.0 + x)*(1.0 - y)*(1.0 - z)/8.0;
        output(2) = (1.0 + x)*(1.0 + y)*(1.0 - z)/8.0;
        output(3) = (1.0 - x)*(1.0 + y)*(1.0 - z)/8.0;

        output(4) = (1.0 - x)*(1.0 - y)*(1.0 + z)/8.0;
        output(5) = (1.0 + x)*(1.0 - y)*(1.0 + z)/8.0;
        output(6) = (1.0 + x)*(1.0 + y)*(1.0 + z)/8.0;
        output(7) = (1.0 - x)*(1.0 + y)*(1.0 + z)/8.0;
        break;
      }
      case OPERATOR_GRAD : {
        const auto x = input(0);
        const auto y = input(1);
        const auto z = input(2);

        // output is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        output(0, 0) = -(1.0 - y)*(1.0 - z)/8.0;
        output(0, 1) = -(1.0 - x)*(1.0 - z)/8.0;
        output(0, 2) = -(1.0 - x)*(1.0 - y)/8.0;

        output(1, 0) =  (1.0 - y)*(1.0 - z)/8.0;
        output(1, 1) = -(1.0 + x)*(1.0 - z)/8.0;
        output(1, 2) = -(1.0 + x)*(1.0 - y)/8.0;

        output(2, 0) =  (1.0 + y)*(1.0 - z)/8.0;
        output(2, 1) =  (1.0 + x)*(1.0 - z)/8.0;
        output(2, 2) = -(1.0 + x)*(1.0 + y)/8.0;

        output(3, 0) = -(1.0 + y)*(1.0 - z)/8.0;
        output(3, 1) =  (1.0 - x)*(1.0 - z)/8.0;
        output(3, 2) = -(1.0 - x)*(1.0 + y)/8.0;

        output(4, 0) = -(1.0 - y)*(1.0 + z)/8.0;
        output(4, 1) = -(1.0 - x)*(1.0 + z)/8.0;
        output(4, 2) =  (1.0 - x)*(1.0 - y)/8.0;

        output(5, 0) =  (1.0 - y)*(1.0 + z)/8.0;
        output(5, 1) = -(1.0 + x)*(1.0 + z)/8.0;
        output(5, 2) =  (1.0 + x)*(1.0 - y)/8.0;

        output(6, 0) =  (1.0 + y)*(1.0 + z)/8.0;
        output(6, 1) =  (1.0 + x)*(1.0 + z)/8.0;
        output(6, 2) =  (1.0 + x)*(1.0 + y)/8.0;

        output(7, 0) = -(1.0 + y)*(1.0 + z)/8.0;
        output(7, 1) =  (1.0 - x)*(1.0 + z)/8.0;
        output(7, 2) =  (1.0 - x)*(1.0 + y)/8.0;
        break;
      }
      case OPERATOR_D2 : {
        const auto x = input(0);
        const auto y = input(1);
        const auto z = input(2);

        // output is a rank-3 array with dimensions (basisCardinality_, dim0, D2Cardinality = 6)
        output(0, 0) =  0.0;                    // {2, 0, 0}
        output(0, 1) =  (1.0 - z)/8.0;          // {1, 1, 0}
        output(0, 2) =  (1.0 - y)/8.0;          // {1, 0, 1}
        output(0, 3) =  0.0;                    // {0, 2, 0}
        output(0, 4) =  (1.0 - x)/8.0;          // {0, 1, 1}
        output(0, 5) =  0.0;                    // {0, 0, 2}

        output(1, 0) =  0.0;                    // {2, 0, 0}
        output(1, 1) = -(1.0 - z)/8.0;          // {1, 1, 0}
        output(1, 2) = -(1.0 - y)/8.0;          // {1, 0, 1}
        output(1, 3) =  0.0;                    // {0, 2, 0}
        output(1, 4) =  (1.0 + x)/8.0;          // {0, 1, 1}
        output(1, 5) =  0.0;                    // {0, 0, 2}

        output(2, 0) =  0.0;                    // {2, 0, 0}
        output(2, 1) =  (1.0 - z)/8.0;          // {1, 1, 0}
        output(2, 2) = -(1.0 + y)/8.0;          // {1, 0, 1}
        output(2, 3) =  0.0;                    // {0, 2, 0}
        output(2, 4) = -(1.0 + x)/8.0;          // {0, 1, 1}
        output(2, 5) =  0.0;                    // {0, 0, 2}

        output(3, 0) =  0.0;                    // {2, 0, 0}
        output(3, 1) = -(1.0 - z)/8.0;          // {1, 1, 0}
        output(3, 2) =  (1.0 + y)/8.0;          // {1, 0, 1}
        output(3, 3) =  0.0;                    // {0, 2, 0}
        output(3, 4) = -(1.0 - x)/8.0;          // {0, 1, 1}
        output(3, 5) =  0.0;                    // {0, 0, 2}


        output(4, 0) =  0.0;                    // {2, 0, 0}
        output(4, 1) =  (1.0 + z)/8.0;          // {1, 1, 0}
        output(4, 2) = -(1.0 - y)/8.0;          // {1, 0, 1}
        output(4, 3) =  0.0;                    // {0, 2, 0}
        output(4, 4) = -(1.0 - x)/8.0;          // {0, 1, 1}
        output(4, 5) =  0.0;                    // {0, 0, 2}

        output(5, 0) =  0.0;                    // {2, 0, 0}
        output(5, 1) = -(1.0 + z)/8.0;          // {1, 1, 0}
        output(5, 2) =  (1.0 - y)/8.0;          // {1, 0, 1}
        output(5, 3) =  0.0;                    // {0, 2, 0}
        output(5, 4) = -(1.0 + x)/8.0;          // {0, 1, 1}
        output(5, 5) =  0.0;                    // {0, 0, 2}

        output(6, 0) =  0.0;                    // {2, 0, 0}
        output(6, 1) =  (1.0 + z)/8.0;          // {1, 1, 0}
        output(6, 2) =  (1.0 + y)/8.0;          // {1, 0, 1}
        output(6, 3) =  0.0;                    // {0, 2, 0}
        output(6, 4) =  (1.0 + x)/8.0;          // {0, 1, 1}
        output(6, 5) =  0.0;                    // {0, 0, 2}

        output(7, 0) =  0.0;                    // {2, 0, 0}
        output(7, 1) = -(1.0 + z)/8.0;          // {1, 1, 0}
        output(7, 2) = -(1.0 + y)/8.0;          // {1, 0, 1}
        output(7, 3) =  0.0;                    // {0, 2, 0}
        output(7, 4) =  (1.0 - x)/8.0;          // {0, 1, 1}
        output(7, 5) =  0.0;                    // {0, 0, 2}
        break;
      }
      case OPERATOR_MAX : {
        const ordinal_type jend = output.dimension(1);
        const ordinal_type iend = output.dimension(0);

        for (ordinal_type j=0;j<jend;++j)
          for (ordinal_type i=0;i<iend;++i)
            output(i, j) = 0.0;
        break;
      }
      default: {
        INTREPID2_TEST_FOR_ABORT( opType != OPERATOR_VALUE &&
                                  opType != OPERATOR_GRAD &&
                                  opType != OPERATOR_CURL &&
                                  opType != OPERATOR_D2 &&
                                  opType != OPERATOR_MAX,
                                  ">>> ERROR: (Intrepid2::Basis_HGRAD_HEX_C1_FEM::Serial::getValues) operator is not supported");

      }
      }
    }