KOKKOS_INLINE_FUNCTION
    void OrthPolynomial<1>::generate( /**/  outputViewType output,
                                      const inputViewType input,
                                      const ordinal_type p ) {
      typedef outputViewType::value_type value_type;
      typedef Sacado::Fad::SFad<value_type,2> fad_type;

      constexpr ordinal_type maxCard = (maxOrder+1)*(maxOrder+2)/2;

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

      // use stack buffer
      fad_type inBuf[maxNumPts][2], outBuf[maxCard][maxNumPts];

      Kokkos::View<fad_type**, Kokkos::Impl::ActiveExecutionMemorySpace> in(&inBuf[0][0],            npts, 2);
      Kokkos::View<fad_type***,Kokkos::Impl::ActiveExecutionMemorySpace> out(&outBuf[0][0][0], card, npts);

      for (ordinal_type i=0;i<npts;++i)
        for (ordinal_type j=0;j<2;++j) {
          in(i,j) = Sacado::Fad::SFad<value_type,2>( input(i,j) );
          in(i,j).diff(j,2);
        }

      OrthPolynomial<0>::generate<maxOrder,maxNumPts>(out, in, p);

      for (ordinal_type i=0;i<card;++i)
        for (ordinal_type j=0;j<npts;++j)
          for (ordinal_type k=0;k<2;++k)
            output(i,j,k) = out(i,j).dx(k);
    }
    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
      void operator()(const size_type iter) const {
        size_type cl = 0, bf = 0, pt = 0;
        size_type outputRank(_output.rank()), rightRank(_rightInput.rank());

        if (_hasField) 
          Util::unrollIndex( cl, bf, pt, 
                             _output.dimension(0),
                             _output.dimension(1),
                             _output.dimension(2),
                             iter );
        else          
          Util::unrollIndex( cl, pt,
                             _output.dimension(0),
                             _output.dimension(1),
                             iter );

        auto result = ( _hasField ? Kokkos::subview(_output, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
                        /**/        Kokkos::subview(_output, cl,     pt, Kokkos::ALL(), Kokkos::ALL()));
        
        const auto right = ( outputRank == rightRank ? ( _hasField ? Kokkos::subview(_rightInput, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
                                                         /**/        Kokkos::subview(_rightInput, cl,     pt, Kokkos::ALL(), Kokkos::ALL()) ) : 
                             /**/                      ( _hasField ? Kokkos::subview(_rightInput,     bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
                                                         /**/        Kokkos::subview(_rightInput,         pt, Kokkos::ALL(), Kokkos::ALL()) ) );
                                                                
        const auto left = (_leftInput.dimension(1) == 1) ? Kokkos::subview(_leftInput, cl, 0) :
                            /**/                           Kokkos::subview(_leftInput, cl, pt);

        const size_type iend  = result.dimension(0);
        const size_type jend  = result.dimension(1);

        const auto val = left();
        if (_reciprocal)
          for(size_type i = 0; i < iend; ++i)
            for(size_type j = 0; j < jend; ++j)
              result(i, j) = right(i, j)/val;
        else
          for(size_type i = 0; i < iend; ++i)
            for(size_type j = 0; j < jend; ++j)
              result(i, j) = right(i, j)*val;
      }
      KOKKOS_INLINE_FUNCTION
      void operator()(const size_type iter) const {
        size_type cl, bf, pt;
        size_type leftRank(_leftInput.rank()), rightRank(_rightInput.rank());

        if (_hasField) 
          unrollIndex( cl, bf, pt, 
                             _output.dimension(0),
                             _output.dimension(1), 
                             _output.dimension(2), 
                             iter );
        else          
          unrollIndex( cl, pt,
                             _output.dimension(0),
                             _output.dimension(1),
                             iter);
        
        auto result = ( _hasField ? Kokkos::subview(_output, cl, bf, pt) :
                        /**/        Kokkos::subview(_output, cl,     pt));
        
        const auto left = (_leftInput.dimension(1) == 1) ? Kokkos::subview(_leftInput, cl, 0, Kokkos::ALL(), Kokkos::ALL()) :
                            /**/                           Kokkos::subview(_leftInput, cl, pt, Kokkos::ALL(), Kokkos::ALL());

        
        const auto right = (rightRank == leftRank + int(_hasField)) ?
                             ( _hasField ? Kokkos::subview(_rightInput, cl, bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
                             /**/          Kokkos::subview(_rightInput, cl,     pt, Kokkos::ALL(), Kokkos::ALL())) :
                             ( _hasField ? Kokkos::subview(_rightInput,     bf, pt, Kokkos::ALL(), Kokkos::ALL()) :
                             /**/          Kokkos::subview(_rightInput,         pt, Kokkos::ALL(), Kokkos::ALL()));
        
        const size_type iend  = left.dimension(0);
        const size_type jend  = left.dimension(1);

        value_type tmp(0);
        for(size_type i = 0; i < iend; ++i)
          for(size_type j = 0; j < jend; ++j)
            tmp += left(i, j)*right(i, j);
        result() = tmp;
      }
    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");

      }
      }
    }
    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.extent(0);
      const ordinal_type npts = input.extent(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.access(i,j) = 0.0;
            for (ordinal_type k=0;k<card;++k)
              output.access(i,j) += vinv(k,i)*phis.access(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.access(i,j,k) = 0.0;
              for (ordinal_type l=0;l<card;++l)
                output.access(i,j,k) += vinv(l,i)*phis.access(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_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::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");
      }
      }
    }