void TabulatorTri<Scalar,ArrayScalar,derivOrder>::tabulate( ArrayScalar &outputValues ,
                                                            const int deg ,
                                                            const ArrayScalar &z ) 
{
  const int np = z.dimension(0);
  const int card = outputValues.dimension(0);
  FieldContainer<Sacado::Fad::DFad<Scalar> > dZ( z.dimension(0) , z.dimension(1) );
  for (int i=0;i<np;i++) {
    for (int j=0;j<2;j++) {
      dZ(i,j) = Sacado::Fad::DFad<Scalar>( z(i,j) );
      dZ(i,j).diff(j,2);
    }
  }
  FieldContainer<Sacado::Fad::DFad<Scalar> > dResult(card,np,derivOrder+1);

  TabulatorTri<Sacado::Fad::DFad<Scalar>,FieldContainer<Sacado::Fad::DFad<Scalar> >,derivOrder-1>::tabulate(dResult ,
                                                                                                            deg ,
                                                                                                            dZ );

  for (int i=0;i<card;i++) {
    for (int j=0;j<np;j++) {
      outputValues(i,j,0) = dResult(i,j,0).dx(0);
      for (unsigned k=0;k<derivOrder;k++) {
        outputValues(i,j,k+1) = dResult(i,j,k).dx(1);
      }
    }
  }

  return;


}
void Basis_HGRAD_QUAD_C2_FEM<Scalar, ArrayScalar>::getDofCoords(ArrayScalar & DofCoords) const {
#ifdef HAVE_INTREPID2_DEBUG
  // Verify rank of output array.
  TEUCHOS_TEST_FOR_EXCEPTION( !(DofCoords.rank() == 2), std::invalid_argument,
                      ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C2_FEM::getDofCoords) rank = 2 required for DofCoords array");
  // Verify 0th dimension of output array.
  TEUCHOS_TEST_FOR_EXCEPTION( !( static_cast<index_type>(DofCoords.dimension(0)) == static_cast<index_type>(this -> basisCardinality_) ), std::invalid_argument,
                      ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C2_FEM::getDofCoords) mismatch in number of DoF and 0th dimension of DofCoords array");
  // Verify 1st dimension of output array.
  TEUCHOS_TEST_FOR_EXCEPTION( !( static_cast<index_type>(DofCoords.dimension(1)) == static_cast<index_type>(this -> basisCellTopology_.getDimension()) ), std::invalid_argument,
                      ">>> ERROR: (Intrepid2::Basis_HGRAD_QUAD_C2_FEM::getDofCoords) incorrect reference cell (1st) dimension in DofCoords array");
#endif

  DofCoords(0,0) = -1.0;   DofCoords(0,1) = -1.0;
  DofCoords(1,0) =  1.0;   DofCoords(1,1) = -1.0;
  DofCoords(2,0) =  1.0;   DofCoords(2,1) =  1.0;
  DofCoords(3,0) = -1.0;   DofCoords(3,1) =  1.0;

  DofCoords(4,0) =  0.0;   DofCoords(4,1) = -1.0;
  DofCoords(5,0) =  1.0;   DofCoords(5,1) =  0.0;
  DofCoords(6,0) =  0.0;   DofCoords(6,1) =  1.0;
  DofCoords(7,0) = -1.0;   DofCoords(7,1) =  0.0;

  DofCoords(8,0) =  0.0;   DofCoords(8,1) =  0.0;

}
  Basis_HGRAD_QUAD_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_QUAD_Cn_FEM( const int orderx , const int ordery,
									const ArrayScalar &pts_x ,
									const ArrayScalar &pts_y ): 
    ptsx_( pts_x.dimension(0) , 1 ) ,
    ptsy_( pts_y.dimension(0) , 1 )
  {
    Array<Array<RCP<Basis<Scalar,ArrayScalar> > > > bases(1);
    bases[0].resize(2);
    bases[0][0] = Teuchos::rcp( new Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>( orderx , pts_x ) );
    bases[0][1] = Teuchos::rcp( new Basis_HGRAD_LINE_Cn_FEM<Scalar,ArrayScalar>( ordery , pts_y ) );
    this->setBases( bases );

    this->basisCardinality_ = (orderx+1)*(ordery+1);
    if (orderx > ordery) {
      this->basisDegree_ = orderx;
    }
    else {
      this->basisDegree_ = ordery;
    }
    this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Quadrilateral<4> >() );
    this -> basisType_         = BASIS_FEM_FIAT;
    this -> basisCoordinates_  = COORDINATES_CARTESIAN;
    this -> basisTagsAreSet_   = false;

    for (int i=0;i<pts_x.dimension(0);i++)
      {
	ptsx_(i,0) = pts_x(i,0);
      }

    for (int i=0;i<pts_y.dimension(0);i++)
      {
	ptsy_(i,0) = pts_y(i,0);
      }

  }
  void TabulatorTet<Scalar,ArrayScalar,1>::tabulate( ArrayScalar &outputValues ,
                                                    const int deg ,
                                                    const ArrayScalar &z ) 
  {
    const int np = z.dimension(0);
    const int card = outputValues.dimension(0);
    FieldContainer<Sacado::Fad::DFad<Scalar> > dZ( z.dimension(0) , z.dimension(1) );
    for (int i=0;i<np;i++) {
      for (int j=0;j<3;j++) {
        dZ(i,j) = Sacado::Fad::DFad<Scalar>( z(i,j) );
        dZ(i,j).diff(j,3);
      }
    }
    FieldContainer<Sacado::Fad::DFad<Scalar> > dResult(card,np);

    TabulatorTet<Sacado::Fad::DFad<Scalar>,FieldContainer<Sacado::Fad::DFad<Scalar> >,0>::tabulate( dResult ,
                                                                                                    deg ,
                                                                                                    dZ );

    for (int i=0;i<card;i++) {
      for (int j=0;j<np;j++) {
        for (int k=0;k<3;k++) {
          outputValues(i,j,k) = dResult(i,j).dx(k);
        }
      }
    }

    return;

  }
  void Basis_HVOL_TRI_C0_FEM<Scalar, ArrayScalar>::getDofCoords(ArrayScalar & DofCoords) const {
#ifdef HAVE_INTREPID_DEBUG
    // Verify rank of output array.
    TEUCHOS_TEST_FOR_EXCEPTION( !(DofCoords.rank() == 2), std::invalid_argument,
                       ">>> ERROR: (Intrepid::Basis_HVOL_TRI_C0_FEM::getDofCoords) rank = 2 required for DofCoords array");
    // Verify 0th dimension of output array.
    TEUCHOS_TEST_FOR_EXCEPTION( !( DofCoords.dimension(0) == this -> basisCardinality_ ), std::invalid_argument,
                       ">>> ERROR: (Intrepid::Basis_HVOL_TRI_C0_FEM::getDofCoords) mismatch in number of DoF and 0th dimension of DofCoords array");
    // Verify 1st dimension of output array.
    TEUCHOS_TEST_FOR_EXCEPTION( !( DofCoords.dimension(1) == (int)(this -> basisCellTopology_.getDimension()) ), std::invalid_argument,
                       ">>> ERROR: (Intrepid::Basis_HVOL_TRI_C0_FEM::getDofCoords) incorrect reference cell (1st) dimension in DofCoords array");
    
    DofCoords(0,0) = 0.0;   DofCoords(0,1) = 0.0;
#endif
  }
Basis_HGRAD_LINE_Hermite_FEM<Scalar,ArrayScalar>::Basis_HGRAD_LINE_Hermite_FEM( const ArrayScalar &pts) : 
    latticePts_( pts.dimension(0), 1 ) {

    int n = pts.dimension(0);

    this->basisCardinality_  = 2*n;                   
    this->basisDegree_       = 2*n-1;    
    this->basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Line<2> >() );
    this->basisType_         = BASIS_FEM_DEFAULT;
    this->basisCoordinates_  = COORDINATES_CARTESIAN;
    this->basisTagsAreSet_   = false;

    for( int i=0; i<n-1; ++i ) {
      TEUCHOS_TEST_FOR_EXCEPTION( pts(i,0) >= pts(i+1,0), std::runtime_error ,
        "Intrepid::Basis_HGRAD_LINE_Hermite_FEM Illegal points given to constructor" );
    }  

    // copy points int latticePts, correcting endpoints if needed
    if (std::abs(pts(0,0)+1.0) < INTREPID_TOL) {
      latticePts_(0,0) = -1.0;
    }
    else {
      latticePts_(0,0) = pts(0,0);
    }
    for (int i=1;i<n-1;i++) {
      latticePts_(i,0) = pts(i,0);
    }
    if (std::abs(pts(n-1,0)-1.0) < INTREPID_TOL) {
      latticePts_(n-1,0) = 1.0;
    }
    else {
      latticePts_(n-1,0) = pts(n-1,0);
    }  

    setupVandermonde();

} // Constructor with points given
void Basis_HGRAD_LINE_Hermite_FEM<Scalar,ArrayScalar>::recurrence( ArrayScalar &P,
                                                                   ArrayScalar &Px,
                                                                   const Scalar x ) const {

  int    n = P.dimension(0);
  Scalar q = x*x-1.0;

  P (0) = 1.0;
  Px(0) = 0.0;
  
  // Loop over basis indices
  for( int j=0; j<n-1; ++j ) {
    P (j+1) =     x*P(j) + q*Px(j)/(j+1); // Compute \f$P_{j+1}(x_i)\f$
    Px(j+1) = (j+1)*P(j) + x*Px(j);       // Compute \f$P'_{j+1}(x_i)\f$
  }

} // recurrence()
void Basis_Constant<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                            const ArrayScalar &  inputPoints,
                                                            const Intrepid2::EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
  Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);  
  
  switch (operatorType) {
    
    case Intrepid2::OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = 1.0;
      }
      break;

    case Intrepid2::OPERATOR_GRAD:
    case Intrepid2::OPERATOR_D1:
    case Intrepid2::OPERATOR_CURL:
    case Intrepid2::OPERATOR_DIV:
    case Intrepid2::OPERATOR_D2:
    case Intrepid2::OPERATOR_D3:
    case Intrepid2::OPERATOR_D4:
    case Intrepid2::OPERATOR_D5:
    case Intrepid2::OPERATOR_D6:
    case Intrepid2::OPERATOR_D7:
    case Intrepid2::OPERATOR_D8:
    case Intrepid2::OPERATOR_D9:
    case Intrepid2::OPERATOR_D10:
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_Constant): Invalid operator type");
  }
}
  Basis_HGRAD_HEX_Cn_FEM<Scalar,ArrayScalar>::Basis_HGRAD_HEX_Cn_FEM( const int orderx , 
								      const int ordery ,
								      const int orderz ,
								      const ArrayScalar &pts_x ,
								      const ArrayScalar &pts_y ,
								      const ArrayScalar &pts_z ):
    ptsx_( pts_x.dimension(0) , 1 ),
    ptsy_( pts_y.dimension(0) , 1 ),
    ptsz_( pts_z.dimension(0) , 1 )
  {
    for (int i=0;i<pts_x.dimension(0);i++)
      {
	ptsx_(i,0) = pts_x(i,0);
      }
    for (int i=0;i<pts_y.dimension(0);i++)
      {
	ptsy_(i,0) = pts_y(i,0);
      }
    for (int i=0;i<pts_z.dimension(0);i++)
      {
	ptsz_(i,0) = pts_z(i,0);
      }

    Array<Array<RCP<Basis<Scalar,ArrayScalar> > > > bases(1);
    bases[0].resize(3);

    bases[0][0] = Teuchos::rcp( new Basis_HGRAD_LINE_Cn_FEM< Scalar , ArrayScalar >( orderx , pts_x ) );
    bases[0][1] = Teuchos::rcp( new Basis_HGRAD_LINE_Cn_FEM< Scalar , ArrayScalar >( ordery , pts_y ) );
    bases[0][2] = Teuchos::rcp( new Basis_HGRAD_LINE_Cn_FEM< Scalar , ArrayScalar >( orderz , pts_z ) );

    this->setBases( bases );

    this->basisCardinality_ = (orderx+1)*(ordery+1)*(orderz+1);
    if (orderx >= ordery && orderx >= orderz ) {
      this->basisDegree_ = orderx;
    }
    else if (ordery >= orderx && ordery >= orderz) {
      this->basisDegree_ = ordery;
    }
    else {
      this->basisDegree_ = orderz;
    }
    this -> basisCellTopology_ = shards::CellTopology(shards::getCellTopologyData<shards::Hexahedron<8> >() );
    this -> basisType_         = BASIS_FEM_FIAT;
    this -> basisCoordinates_  = COORDINATES_CARTESIAN;
    this -> basisTagsAreSet_   = false;

    initializeTags();
    this->basisTagsAreSet_ = true;
  }
void Basis_HCURL_TRI_I1_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                            const ArrayScalar &  inputPoints,
                                                            const EOperator      operatorType) const {

// Verify arguments
#ifdef HAVE_INTREPID_DEBUG
  Intrepid::getValues_HCURL_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
 // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);

  // Temporaries: (x,y) coordinates of the evaluation point
  Scalar x = 0.0;                                    
  Scalar y = 0.0;                                    
  
  switch (operatorType) {
    case OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        outputValues(0, i0, 0) =  1.0 - y;
        outputValues(0, i0, 1) =  x;

        outputValues(1, i0, 0) = -y;
        outputValues(1, i0, 1) =  x;

        outputValues(2, i0, 0) = -y;
        outputValues(2, i0, 1) = -1.0 + x;
      }
      break;
      
    case OPERATOR_CURL:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        
        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = 2.0;
        outputValues(1, i0) = 2.0;
        outputValues(2, i0) = 2.0;
      }
      break;
      
    case OPERATOR_DIV:
       TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                          ">>> ERROR (Basis_HCURL_TRI_I1_FEM): DIV is invalid operator for HCURL Basis Functions");
      break;
      
    case OPERATOR_GRAD:
       TEST_FOR_EXCEPTION( (operatorType == OPERATOR_GRAD), std::invalid_argument,
                          ">>> ERROR (Basis_HCURL_TRI_I1_FEM): GRAD is invalid operator for HCURL Basis Functions");
      break;

    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:
      TEST_FOR_EXCEPTION( ( (operatorType == OPERATOR_D1)    ||
                            (operatorType == OPERATOR_D2)    ||
                            (operatorType == OPERATOR_D3)    ||
                            (operatorType == OPERATOR_D4)    ||
                            (operatorType == OPERATOR_D5)    ||
                            (operatorType == OPERATOR_D6)    ||
                            (operatorType == OPERATOR_D7)    ||
                            (operatorType == OPERATOR_D8)    ||
                            (operatorType == OPERATOR_D9)    ||
                            (operatorType == OPERATOR_D10) ),
                          std::invalid_argument,
                          ">>> ERROR (Basis_HCURL_TRI_I1_FEM): Invalid operator type");
      break;

    default:
      TEST_FOR_EXCEPTION( ( (operatorType != OPERATOR_VALUE) &&
                            (operatorType != OPERATOR_GRAD)  &&
                            (operatorType != OPERATOR_CURL)  &&
                            (operatorType != OPERATOR_DIV)   &&
                            (operatorType != OPERATOR_D1)    &&
                            (operatorType != OPERATOR_D2)    &&
                            (operatorType != OPERATOR_D3)    &&
                            (operatorType != OPERATOR_D4)    &&
                            (operatorType != OPERATOR_D5)    &&
                            (operatorType != OPERATOR_D6)    &&
                            (operatorType != OPERATOR_D7)    &&
                            (operatorType != OPERATOR_D8)    &&
                            (operatorType != OPERATOR_D9)    &&
                            (operatorType != OPERATOR_D10) ),
                          std::invalid_argument,
                          ">>> ERROR (Basis_HCURL_TRI_I1_FEM): Invalid operator type");
  }
}
void Basis_HGRAD_WEDGE_C1_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &    outputValues,
                                                             const ArrayScalar &  inputPoints,
                                                             const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
  Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);  
  
  // Temporaries: (x,y,z) coordinates of the evaluation point
  Scalar x = 0.0;                                    
  Scalar y = 0.0;   
  Scalar z = 0.0;
  
  switch (operatorType) {
    
    case OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        z = inputPoints(i0, 2);
        
        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = (1.0 - x - y)*(1.0 - z)/2.0;
        outputValues(1, i0) = x*(1.0 - z)/2.0;
        outputValues(2, i0) = y*(1.0 - z)/2.0;
        outputValues(3, i0) = (1.0 - x - y)*(1.0 + z)/2.0;
        outputValues(4, i0) = x*(1.0 + z)/2.0;
        outputValues(5, i0) = y*(1.0 + z)/2.0;
      }
      break;
      
    case OPERATOR_GRAD:
    case OPERATOR_D1:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);
        z = inputPoints(i0, 2);
        
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        outputValues(0, i0, 0) = -(1.0 - z)/2.0;
        outputValues(0, i0, 1) = -(1.0 - z)/2.0;
        outputValues(0, i0, 2) = -(1.0 - x - y)/2.0;
        
        outputValues(1, i0, 0) =  (1.0 - z)/2.0;
        outputValues(1, i0, 1) =  0.0;
        outputValues(1, i0, 2) = -x/2.0;
        
        outputValues(2, i0, 0) =  0.0;
        outputValues(2, i0, 1) =  (1.0 - z)/2.0;
        outputValues(2, i0, 2) = -y/2.0;
  
        
        outputValues(3, i0, 0) = -(1.0 + z)/2.0;
        outputValues(3, i0, 1) = -(1.0 + z)/2.0;
        outputValues(3, i0, 2) =  (1.0 - x - y)/2.0;
        
        outputValues(4, i0, 0) =  (1.0 + z)/2.0;
        outputValues(4, i0, 1) =  0.0;
        outputValues(4, i0, 2) =  x/2.0;
        
        outputValues(5, i0, 0) =  0.0;
        outputValues(5, i0, 1) =  (1.0 + z)/2.0;
        outputValues(5, i0, 2) =  y/2.0;
      }
      break;
      
    case OPERATOR_CURL:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_CURL), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_WEDGE_C1_FEM): CURL is invalid operator for rank-0 (scalar) functions in 3D");
      break;
      
    case OPERATOR_DIV:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_WEDGE_C1_FEM): DIV is invalid operator for rank-0 (scalar) functions in 3D");
      break;
      
    case OPERATOR_D2:
      for (int i0 = 0; i0 < dim0; i0++) {
        outputValues(0, i0, 0) = 0.0;     outputValues(3, i0, 0) = 0.0; 
        outputValues(0, i0, 1) = 0.0;     outputValues(3, i0, 1) = 0.0;
        outputValues(0, i0, 2) = 0.5;     outputValues(3, i0, 2) =-0.5; 
        outputValues(0, i0, 3) = 0.0;     outputValues(3, i0, 3) = 0.0;
        outputValues(0, i0, 4) = 0.5;     outputValues(3, i0, 4) =-0.5;
        outputValues(0, i0, 5) = 0.0;     outputValues(3, i0, 5) = 0.0;
        
        outputValues(1, i0, 0) = 0.0;     outputValues(4, i0, 0) = 0.0; 
        outputValues(1, i0, 1) = 0.0;     outputValues(4, i0, 1) = 0.0; 
        outputValues(1, i0, 2) =-0.5;     outputValues(4, i0, 2) = 0.5;
        outputValues(1, i0, 3) = 0.0;     outputValues(4, i0, 3) = 0.0;
        outputValues(1, i0, 4) = 0.0;     outputValues(4, i0, 4) = 0.0;
        outputValues(1, i0, 5) = 0.0;     outputValues(4, i0, 5) = 0.0;
        
        outputValues(2, i0, 0) = 0.0;     outputValues(5, i0, 0) = 0.0;
        outputValues(2, i0, 1) = 0.0;     outputValues(5, i0, 1) = 0.0;
        outputValues(2, i0, 2) = 0.0;     outputValues(5, i0, 2) = 0.0;
        outputValues(2, i0, 3) = 0.0;     outputValues(5, i0, 3) = 0.0;
        outputValues(2, i0, 4) =-0.5;     outputValues(5, i0, 4) = 0.5;
        outputValues(2, i0, 5) = 0.0;     outputValues(5, i0, 5) = 0.0;
      }
      break;
      
    case OPERATOR_D3:
    case OPERATOR_D4:
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        int DkCardinality = Intrepid2::getDkCardinality(operatorType, 
                                                       this -> basisCellTopology_.getDimension() );
        for(int dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
          for (int i0 = 0; i0 < dim0; i0++) {
            for(int dkOrd = 0; dkOrd < DkCardinality; dkOrd++){
              outputValues(dofOrd, i0, dkOrd) = 0.0;
            }
          }
        }
      }
      break;
      
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_WEDGE_C1_FEM): Invalid operator type");
  }
}
  void Basis_HCURL_QUAD_In_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
							      const ArrayScalar &  inputPoints,
							      const EOperator      operatorType) const {
    
    // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
    Intrepid2::getValues_HCURL_Args<Scalar, ArrayScalar>(outputValues,
						       inputPoints,
						       operatorType,
						       this -> getBaseCellTopology(),
						       this -> getCardinality() );
#endif
    
    // Number of evaluation points = dim 0 of inputPoints
    int dim0 = inputPoints.dimension(0);
    
    // separate out points
    FieldContainer<Scalar> xPoints(dim0,1);
    FieldContainer<Scalar> yPoints(dim0,1);
    
    for (int i=0;i<dim0;i++) {
      xPoints(i,0) = inputPoints(i,0);
      yPoints(i,0) = inputPoints(i,1);
    }
    
    switch (operatorType) {
    case OPERATOR_VALUE:
      {
	FieldContainer<Scalar> closedBasisValsXPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisValsYPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsXPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsYPts( openBasis_.getCardinality() , dim0 );
	
	closedBasis_.getValues( closedBasisValsXPts , xPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisValsYPts , yPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsXPts , xPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsYPts , yPoints , OPERATOR_VALUE );
	
	int bfcur = 0;
	// x component bfs are (open(x) closed(y),0)
	for (int j=0;j<closedBasis_.getCardinality();j++) 
	  {
	    for (int i=0;i<openBasis_.getCardinality();i++) 
	      {
		for (int l=0;l<dim0;l++) 
		  {
		    outputValues(bfcur,l,0) = closedBasisValsYPts(j,l) * openBasisValsXPts(i,l);
		    outputValues(bfcur,l,1) = 0.0;
		  }
		bfcur++;
	      }
	  }
	
	// y component bfs are (0,closed(x) open(y))
	for (int j=0;j<openBasis_.getCardinality();j++) 
	  {
	    for (int i=0;i<closedBasis_.getCardinality();i++) 
	      {
		for (int l=0;l<dim0;l++) 
		  {
		    outputValues(bfcur,l,0) = 0.0;
		    outputValues(bfcur,l,1) = openBasisValsYPts(j,l) * closedBasisValsXPts(i,l);
		  }
		bfcur++;
	      }
	  }
      }
      break;
    case OPERATOR_CURL:
      {
	FieldContainer<Scalar> closedBasisDerivsXPts( closedBasis_.getCardinality() , dim0 , 1 );
	FieldContainer<Scalar> closedBasisDerivsYPts( closedBasis_.getCardinality() , dim0 , 1 );
	FieldContainer<Scalar> openBasisValsXPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsYPts( openBasis_.getCardinality() , dim0 );
	
	closedBasis_.getValues( closedBasisDerivsXPts , xPoints , OPERATOR_D1 );
	closedBasis_.getValues( closedBasisDerivsYPts , yPoints , OPERATOR_D1 );
	openBasis_.getValues( openBasisValsXPts , xPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsYPts , yPoints , OPERATOR_VALUE );
	
	int bfcur = 0;
	
	// x component basis functions first
	for (int j=0;j<closedBasis_.getCardinality();j++) 
	  {
	    for (int i=0;i<openBasis_.getCardinality();i++) 
	      {
		for (int l=0;l<dim0;l++) {
		  outputValues(bfcur,l) = -closedBasisDerivsYPts(j,l,0) * openBasisValsXPts(i,l);
		}
		bfcur++;
	      }
	  }
	
	// now y component basis functions
	for (int j=0;j<openBasis_.getCardinality();j++) 
	  {
	    for (int i=0;i<closedBasis_.getCardinality();i++) 
	      {
		for (int l=0;l<dim0;l++) 
		  {
		    outputValues(bfcur,l) = closedBasisDerivsXPts(i,l,0) * openBasisValsYPts(j,l);
		  }
		bfcur++;
	      }
	  }
      }
      break;
    case OPERATOR_DIV:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_QUAD_In_FEM): DIV is invalid operator for HCURL Basis Functions");
      break;
      
    case OPERATOR_GRAD:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_GRAD), std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_QUAD_In_FEM): GRAD is invalid operator for HCURL Basis Functions");
      break;
      
    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:
      TEUCHOS_TEST_FOR_EXCEPTION( ( (operatorType == OPERATOR_D1)    ||
			    (operatorType == OPERATOR_D2)    ||
			    (operatorType == OPERATOR_D3)    ||
			    (operatorType == OPERATOR_D4)    ||
			    (operatorType == OPERATOR_D5)    ||
			    (operatorType == OPERATOR_D6)    ||
			    (operatorType == OPERATOR_D7)    ||
			    (operatorType == OPERATOR_D8)    ||
			    (operatorType == OPERATOR_D9)    ||
			    (operatorType == OPERATOR_D10) ),
			  std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_QUAD_In_FEM): Invalid operator type");
      break;
      
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( ( (operatorType != OPERATOR_VALUE) &&
			    (operatorType != OPERATOR_GRAD)  &&
			    (operatorType != OPERATOR_CURL)  &&
			    (operatorType != OPERATOR_CURL)   &&
			    (operatorType != OPERATOR_D1)    &&
			    (operatorType != OPERATOR_D2)    &&
			    (operatorType != OPERATOR_D3)    &&
			    (operatorType != OPERATOR_D4)    &&
			    (operatorType != OPERATOR_D5)    &&
			    (operatorType != OPERATOR_D6)    &&
			    (operatorType != OPERATOR_D7)    &&
			    (operatorType != OPERATOR_D8)    &&
			    (operatorType != OPERATOR_D9)    &&
			    (operatorType != OPERATOR_D10) ),
			  std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_QUAD_In_FEM): Invalid operator type");
    }
  }
  void Basis_HGRAD_LINE_Cn_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                              const ArrayScalar &  inputPoints,
                                                              const EOperator      operatorType) const {
  
    // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
    Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                        inputPoints,
                                                        operatorType,
                                                        this -> getBaseCellTopology(),
                                                        this -> getCardinality() );
#endif
    const int numPts = inputPoints.dimension(0);
    const int numBf = this->getCardinality();

    try {
      switch (operatorType) {
      case OPERATOR_VALUE:
        {
          ArrayScalar phisCur( numBf , numPts );
          Phis_.getValues( phisCur , inputPoints , operatorType );
          for (int i=0;i<outputValues.dimension(0);i++) {
            for (int j=0;j<outputValues.dimension(1);j++) {
              outputValues(i,j) = 0.0;
              for (int k=0;k<this->getCardinality();k++) {
                outputValues(i,j) += this->Vinv_(k,i) * phisCur(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:
        {
          const int dkcard = 
            (operatorType == OPERATOR_GRAD)? getDkCardinality(OPERATOR_D1,1): getDkCardinality(operatorType,1);
          
          ArrayScalar phisCur( numBf , numPts , dkcard );
          Phis_.getValues( phisCur , inputPoints , operatorType );

          for (int i=0;i<outputValues.dimension(0);i++) {
            for (int j=0;j<outputValues.dimension(1);j++) {
              for (int k=0;k<outputValues.dimension(2);k++) {
                outputValues(i,j,k) = 0.0;
                for (int l=0;l<this->getCardinality();l++) {
                  outputValues(i,j,k) += this->Vinv_(l,i) * phisCur(l,j,k);
                }
              }
            }
          }
        }
        break;
      default:
        TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                            ">>> ERROR (Basis_HGRAD_LINE_Cn_FEM): Operator type not implemented" );
        break;
      }
    }
    catch (std::invalid_argument &exception){
      TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_LINE_Cn_FEM): Operator failed");    
    }

  }
void TabulatorTri<Scalar,ArrayScalar,0>::tabulate(ArrayScalar &outputValues ,
                                                  const int deg ,
                                                  const ArrayScalar &z )
{
  const int np = z.dimension( 0 );
  
  // each point needs to be transformed from Pavel's element
  // z(i,0) --> (2.0 * z(i,0) - 1.0)
  // z(i,1) --> (2.0 * z(i,1) - 1.0)
  
  // set up constant term
  int idx_cur = TabulatorTri<Scalar,ArrayScalar,0>::idx(0,0);
  int idx_curp1,idx_curm1;
  
  // set D^{0,0} = 1.0
  for (int i=0;i<np;i++) {
    outputValues(idx_cur,i) = Scalar( 1.0 ) + z(i,0) - z(i,0) + z(i,1) - z(i,1);
  }
  

  if (deg > 0) {
    Teuchos::Array<Scalar> f1(np),f2(np),f3(np);
    
    for (int i=0;i<np;i++) {
      f1[i] = 0.5 * (1.0+2.0*(2.0*z(i,0)-1.0)+(2.0*z(i,1)-1.0));
      f2[i] = 0.5 * (1.0-(2.0*z(i,1)-1.0));
      f3[i] = f2[i] * f2[i];
    }
    
    // set D^{1,0} = f1
    idx_cur = TabulatorTri<Scalar,ArrayScalar,0>::idx(1,0);
    for (int i=0;i<np;i++) {
      outputValues(idx_cur,i) = f1[i];
    }
    
    // recurrence in p
    for (int p=1;p<deg;p++) {
      idx_cur = TabulatorTri<Scalar,ArrayScalar,0>::idx(p,0);
      idx_curp1 = TabulatorTri<Scalar,ArrayScalar,0>::idx(p+1,0);
      idx_curm1 = TabulatorTri<Scalar,ArrayScalar,0>::idx(p-1,0);
      Scalar a = (2.0*p+1.0)/(1.0+p);
      Scalar b = p / (p+1.0);
      
      for (int i=0;i<np;i++) {
        outputValues(idx_curp1,i) = a * f1[i] * outputValues(idx_cur,i)
          - b * f3[i] * outputValues(idx_curm1,i);
      }
    }
    
    // D^{p,1}
    for (int p=0;p<deg;p++) {
      int idxp0 = TabulatorTri<Scalar,ArrayScalar,0>::idx(p,0);
      int idxp1 = TabulatorTri<Scalar,ArrayScalar,0>::idx(p,1);
      for (int i=0;i<np;i++) {
        outputValues(idxp1,i) = outputValues(idxp0,i)
          *0.5*(1.0+2.0*p+(3.0+2.0*p)*(2.0*z(i,1)-1.0));
      }
    }
    
    
    // recurrence in q
    for (int p=0;p<deg-1;p++) {
      for (int q=1;q<deg-p;q++) {
        int idxpqp1=TabulatorTri<Scalar,ArrayScalar,0>::idx(p,q+1);
        int idxpq=TabulatorTri<Scalar,ArrayScalar,0>::idx(p,q);
        int idxpqm1=TabulatorTri<Scalar,ArrayScalar,0>::idx(p,q-1);
        Scalar a,b,c;
        TabulatorTri<Scalar,ArrayScalar,0>::jrc((Scalar)(2*p+1),(Scalar)0,q,a,b,c);
        for (int i=0;i<np;i++) {
          outputValues(idxpqp1,i)
            = (a*(2.0*z(i,1)-1.0)+b)*outputValues(idxpq,i)
            - c*outputValues(idxpqm1,i);
        }
      }
    }
  }    
  
  // orthogonalize
  for (int p=0;p<=deg;p++) {
    for (int q=0;q<=deg-p;q++) {
      for (int i=0;i<np;i++) {
        outputValues(TabulatorTri<Scalar,ArrayScalar,0>::idx(p,q),i) *= sqrt( (p+0.5)*(p+q+1.0));
      }
    }
  }
  
  return;
}
void Basis_HGRAD_LINE_Hermite_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                                  const ArrayScalar &  inputPoints,
                                                                  const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
  Intrepid::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  // Number of evaluation points = dim 0 of inputPoints
  int nPts = inputPoints.dimension(0);  
  int nBf  = this->getCardinality();  

  int n = nBf/2;

  // Legendre polynomials and their derivatives evaluated on inputPoints
  SerialDenseMatrix legendre(nBf,nPts); 

  // Hermite interpolants evaluated on inputPoints
  SerialDenseMatrix hermite(nBf,nPts);
    
  ArrayScalar P (nBf);
  ArrayScalar Px(nBf);
         
  int derivative_order;
  int derivative_case = static_cast<int>(operatorType);

  if( derivative_case == 0 ) {
    derivative_order = 0;
  }
  else if( derivative_case > 0 && derivative_case < 5 ) {
    derivative_order = 1;
  }
  else {
    derivative_order = derivative_case - 3;
  }
  
  try {
    // GRAD,CURL,DIV, and D1 are all the first derivative
    switch (operatorType) {
      case OPERATOR_VALUE: 
      { 
        for( int i=0; i<nPts; ++i ) { 
          recurrence( P, Px, inputPoints(i,0) );
          for( int j=0; j<nBf; ++j ) {
             legendre(j,i) = P(j);
          }
        }
        break; 
      }
      case OPERATOR_GRAD:
      case OPERATOR_DIV:
      case OPERATOR_CURL:
      case OPERATOR_D1:
      {
        for( int i=0; i<nPts; ++i ) { 
          recurrence( P, Px, inputPoints(i,0) );
          for( int j=0; j<nBf; ++j ) {
             legendre(j,i) = Px(j);
          }
        }
        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:
      {
        for( int i=0; i<nPts; ++i ) {
          legendre_d( P, Px, derivative_order, inputPoints(i,0));
          for( int j=0; j<nBf; ++j ) {
            legendre(j,i) = Px(j); 
          }
        }
        break;
      }
      default:
        TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid::isValidOperator(operatorType) ), std::invalid_argument,
                            ">>> ERROR (Basis_HGRAD_LINE_Hermite_FEM): Invalid operator type");

    } // switch(operatorType)
  }
  catch (std::invalid_argument &exception){
    TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                        ">>> ERROR (Basis_HGRAD_LINE_Hermite_FEM): Operator failed");    
  }

  if( !isFactored_ ) {
    solver_.factorWithEquilibration(true);
    solver_.factor();
  }

  solver_.setVectors(Teuchos::rcpFromRef(hermite),Teuchos::rcpFromRef(legendre));
  solver_.solve();

  if(derivative_order > 0)
  {
    for( int i=0; i<n; ++i ) {
      for( int j=0; j<nPts; ++j ) {
        outputValues(2*i,  j,0)  = hermite(i,  j);
        outputValues(2*i+1,j,0)  = hermite(i+n,j);
      } 
    }
  }
  else {
    for( int i=0; i<n; ++i ) {
      for( int j=0; j<nPts; ++j ) {
        outputValues(2*i  ,j)   = hermite(i,  j);
        outputValues(2*i+1,j)   = hermite(i+n,j);
      } 
    }
  }
     
} // getValues()
void Basis_HGRAD_QUAD_C2_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                             const ArrayScalar &  inputPoints,
                                                             const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
  Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);  
  
  // Temporaries: (x,y) coordinates of the evaluation point
  Scalar x = 0.0;                                    
  Scalar y = 0.0;                                    
  
  switch (operatorType) {
    
    case OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        
        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = x*(x - 1.0)*y*(y - 1.0)/4.0;
        outputValues(1, i0) = x*(x + 1.0)*y*(y - 1.0)/4.0;
        outputValues(2, i0) = x*(x + 1.0)*y*(y + 1.0)/4.0;
        outputValues(3, i0) = x*(x - 1.0)*y*(y + 1.0)/4.0;
        // edge midpoints basis functions
        outputValues(4, i0) = (1.0 - x)*(1.0 + x)*y*(y - 1.0)/2.0;
        outputValues(5, i0) = x*(x + 1.0)*(1.0 - y)*(1.0 + y)/2.0;
        outputValues(6, i0) = (1.0 - x)*(1.0 + x)*y*(y + 1.0)/2.0;
        outputValues(7, i0) = x*(x - 1.0)*(1.0 - y)*(1.0 + y)/2.0;
        // quad bubble basis function
        outputValues(8, i0) = (1.0 - x)*(1.0 + x)*(1.0 - y)*(1.0 + y); 
      }
      break;
      
    case OPERATOR_GRAD:
    case OPERATOR_D1:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);
        
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        outputValues(0, i0, 0) = (-0.25 + 0.5*x)*(-1. + y)*y;
        outputValues(0, i0, 1) = (-1.0 + x)*x*(-0.25 + 0.5*y);
        
        outputValues(1, i0, 0) = (0.25 + 0.5*x)*(-1. + y)*y;
        outputValues(1, i0, 1) = x*(1. + x)*(-0.25 + 0.5*y);
        
        outputValues(2, i0, 0) = (0.25 + 0.5*x)*y*(1. + y);
        outputValues(2, i0, 1) = x*(1. + x)*(0.25 + 0.5*y);
 
        outputValues(3, i0, 0) = (-0.25 + 0.5*x)*y*(1. + y);
        outputValues(3, i0, 1) = (-1. + x)*x*(0.25 + 0.5*y);

        outputValues(4, i0, 0) = x*(1.0 - y)*y;
        outputValues(4, i0, 1) = 0.5*(1.0 - x)*(1.0 + x)*(-1.0 + 2.0*y);
          
        outputValues(5, i0, 0) = 0.5*(1.0 - y)*(1.0 + y)*(1.0 + 2.0*x);
        outputValues(5, i0, 1) =-x*(1.0 + x)*y;
          
        outputValues(6, i0, 0) =-y*(1.0 + y)*x;
        outputValues(6, i0, 1) = 0.5*(1.0 - x)*(1.0 + x)*(1.0 + 2.0*y);
          
        outputValues(7, i0, 0) = 0.5*(1.0 - y)*(1.0+ y)*(-1.0 + 2.0*x);
        outputValues(7, i0, 1) = (1.0 - x)*x*y;
 
        outputValues(8, i0, 0) =-2.0*(1.0 - y)*(1.0 + y)*x;
        outputValues(8, i0, 1) =-2.0*(1.0 - x)*(1.0 + x)*y;          
      }
      break;
      
    case OPERATOR_CURL:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);
        
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        // CURL(u) = (u_y, -u_x), is rotated GRAD
        outputValues(0, i0, 1) =-(-0.25 + 0.5*x)*(-1. + y)*y;
        outputValues(0, i0, 0) = (-1.0 + x)*x*(-0.25 + 0.5*y);
        
        outputValues(1, i0, 1) =-(0.25 + 0.5*x)*(-1. + y)*y;
        outputValues(1, i0, 0) = x*(1. + x)*(-0.25 + 0.5*y);
        
        outputValues(2, i0, 1) =-(0.25 + 0.5*x)*y*(1. + y);
        outputValues(2, i0, 0) = x*(1. + x)*(0.25 + 0.5*y);
        
        outputValues(3, i0, 1) =-(-0.25 + 0.5*x)*y*(1. + y);
        outputValues(3, i0, 0) = (-1. + x)*x*(0.25 + 0.5*y);
        
        outputValues(4, i0, 1) =-x*(1.0 - y)*y;
        outputValues(4, i0, 0) = 0.5*(1.0 - x)*(1.0 + x)*(-1.0 + 2.0*y);
        
        outputValues(5, i0, 1) =-0.5*(1.0 - y)*(1.0 + y)*(1.0 + 2.0*x);
        outputValues(5, i0, 0) =-x*(1.0 + x)*y;
        
        outputValues(6, i0, 1) = y*(1.0 + y)*x;
        outputValues(6, i0, 0) = 0.5*(1.0 - x)*(1.0 + x)*(1.0 + 2.0*y);
        
        outputValues(7, i0, 1) =-0.5*(1.0 - y)*(1.0 + y)*(-1.0 + 2.0*x);
        outputValues(7, i0, 0) = (1.0 - x)*x*y;
        
        outputValues(8, i0, 1) = 2.0*(1.0 - y)*(1.0 + y)*x;
        outputValues(8, i0, 0) =-2.0*(1.0 - x)*(1.0 + x)*y;          
      }
      break;
      
    case OPERATOR_DIV:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_QUAD_C2_FEM): DIV is invalid operator for rank-0 (scalar) functions in 2D");
      break;
      
    case OPERATOR_D2:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);
       
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, D2Cardinality=3) 
        outputValues(0, i0, 0) = 0.5*(-1.0 + y)*y;
        outputValues(0, i0, 1) = 0.25 - 0.5*y + x*(-0.5 + 1.*y);
        outputValues(0, i0, 2) = 0.5*(-1.0 + x)*x;

        outputValues(1, i0, 0) = 0.5*(-1.0 + y)*y;
        outputValues(1, i0, 1) =-0.25 + 0.5*y + x*(-0.5 + 1.*y);
        outputValues(1, i0, 2) = 0.5*x*(1.0 + x);
        
        outputValues(2, i0, 0) = 0.5*y*(1.0 + y);
        outputValues(2, i0, 1) = 0.25 + 0.5*y + x*(0.5 + 1.*y);
        outputValues(2, i0, 2) = 0.5*x*(1.0 + x);
        
        outputValues(3, i0, 0) = 0.5*y*(1.0 + y);
        outputValues(3, i0, 1) =-0.25 - 0.5*y + x*(0.5 + 1.*y);
        outputValues(3, i0, 2) = 0.5*(-1.0 + x)*x;
        
        outputValues(4, i0, 0) = (1.0 - y)*y;
        outputValues(4, i0, 1) = x*(1. - 2.*y);
        outputValues(4, i0, 2) = (1.0 - x)*(1.0 + x);

        outputValues(5, i0, 0) = (1.0 - y)*(1.0 + y);
        outputValues(5, i0, 1) = x*(0. - 2.*y) - 1.*y;
        outputValues(5, i0, 2) =-x*(1.0 + x);

        outputValues(6, i0, 0) =-y*(1.0 + y);
        outputValues(6, i0, 1) = x*(-1. - 2.*y);
        outputValues(6, i0, 2) = (1.0 - x)*(1.0 + x);

        outputValues(7, i0, 0) = (1.0 - y)*(1.0 + y);
        outputValues(7, i0, 1) = x*(0. - 2.*y) + 1.*y;
        outputValues(7, i0, 2) = (1.0 - x)*x;

        outputValues(8, i0, 0) =-2.0 + 2.0*y*y;
        outputValues(8, i0, 1) = 4*x*y;
        outputValues(8, i0, 2) =-2.0 + 2.0*x*x;
        
      }
      break;
      
    case OPERATOR_D3:
      // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, D3Cardinality=4) 
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);

        outputValues(0, i0, 0) = 0.0;
        outputValues(0, i0, 1) =-0.5 + y;
        outputValues(0, i0, 2) =-0.5 + x;
        outputValues(0, i0, 3) = 0.0;

        outputValues(1, i0, 0) = 0.0;
        outputValues(1, i0, 1) =-0.5 + y;
        outputValues(1, i0, 2) = 0.5 + x;
        outputValues(1, i0, 3) = 0.0;

        outputValues(2, i0, 0) = 0.0;
        outputValues(2, i0, 1) = 0.5 + y;
        outputValues(2, i0, 2) = 0.5 + x;
        outputValues(2, i0, 3) = 0.0;

        outputValues(3, i0, 0) = 0.0;
        outputValues(3, i0, 1) = 0.5 + y;
        outputValues(3, i0, 2) =-0.5 + x;
        outputValues(3, i0, 3) = 0.0;

        outputValues(4, i0, 0) = 0.0;
        outputValues(4, i0, 1) = 1.0 - 2.0*y;
        outputValues(4, i0, 2) =-2.0*x;
        outputValues(4, i0, 3) = 0.0;

        outputValues(5, i0, 0) = 0.0;
        outputValues(5, i0, 1) =-2.0*y;
        outputValues(5, i0, 2) =-1.0 - 2.0*x;
        outputValues(5, i0, 3) = 0.0;

        outputValues(6, i0, 0) = 0.0;
        outputValues(6, i0, 1) =-1.0 - 2.0*y;
        outputValues(6, i0, 2) =-2.0*x;
        outputValues(6, i0, 3) = 0.0;

        outputValues(7, i0, 0) = 0.0;
        outputValues(7, i0, 1) =-2.0*y;
        outputValues(7, i0, 2) = 1.0 - 2.0*x;
        outputValues(7, i0, 3) = 0.0;        
        
        outputValues(8, i0, 0) = 0.0;
        outputValues(8, i0, 1) = 4.0*y;
        outputValues(8, i0, 2) = 4.0*x;
        outputValues(8, i0, 3) = 0.0;                
      }
      break;
    
    case OPERATOR_D4:
      // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, D4Cardinality=5) 
      for (int i0 = 0; i0 < dim0; i0++) {
        
        outputValues(0, i0, 0) = 0.0;
        outputValues(0, i0, 1) = 0.0;
        outputValues(0, i0, 2) = 1.0;
        outputValues(0, i0, 3) = 0.0;                
        outputValues(0, i0, 4) = 0.0;                

        outputValues(1, i0, 0) = 0.0;
        outputValues(1, i0, 1) = 0.0;
        outputValues(1, i0, 2) = 1.0;
        outputValues(1, i0, 3) = 0.0;                
        outputValues(1, i0, 4) = 0.0;                
        
        outputValues(2, i0, 0) = 0.0;
        outputValues(2, i0, 1) = 0.0;
        outputValues(2, i0, 2) = 1.0;
        outputValues(2, i0, 3) = 0.0;                
        outputValues(2, i0, 4) = 0.0;                
        
        outputValues(3, i0, 0) = 0.0;
        outputValues(3, i0, 1) = 0.0;
        outputValues(3, i0, 2) = 1.0;
        outputValues(3, i0, 3) = 0.0;                
        outputValues(3, i0, 4) = 0.0;                
        
        outputValues(4, i0, 0) = 0.0;
        outputValues(4, i0, 1) = 0.0;
        outputValues(4, i0, 2) =-2.0;
        outputValues(4, i0, 3) = 0.0;                
        outputValues(4, i0, 4) = 0.0;                

        outputValues(5, i0, 0) = 0.0;
        outputValues(5, i0, 1) = 0.0;
        outputValues(5, i0, 2) =-2.0;
        outputValues(5, i0, 3) = 0.0;                
        outputValues(5, i0, 4) = 0.0;                
        
        outputValues(6, i0, 0) = 0.0;
        outputValues(6, i0, 1) = 0.0;
        outputValues(6, i0, 2) =-2.0;
        outputValues(6, i0, 3) = 0.0;                
        outputValues(6, i0, 4) = 0.0;                
        
        outputValues(7, i0, 0) = 0.0;
        outputValues(7, i0, 1) = 0.0;
        outputValues(7, i0, 2) =-2.0;
        outputValues(7, i0, 3) = 0.0;                
        outputValues(7, i0, 4) = 0.0;                
        
        outputValues(8, i0, 0) = 0.0;
        outputValues(8, i0, 1) = 0.0;
        outputValues(8, i0, 2) = 4.0;
        outputValues(8, i0, 3) = 0.0;                
        outputValues(8, i0, 4) = 0.0;                
      }
      break;
      
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        int DkCardinality = Intrepid2::getDkCardinality(operatorType, 
                                                       this -> basisCellTopology_.getDimension() );
        for(int dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
          for (int i0 = 0; i0 < dim0; i0++) {
            for(int dkOrd = 0; dkOrd < DkCardinality; dkOrd++){
              outputValues(dofOrd, i0, dkOrd) = 0.0;
            }
          }
        }
      }
      break;
      
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_QUAD_C2_FEM): Invalid operator type");
  }
}
void Basis_HGRAD_TRI_C2_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                            const ArrayScalar &  inputPoints,
                                                            const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
  Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);  
  
  // Temporaries: (x,y) coordinates of the evaluation point
  Scalar x = 0.0;                                    
  Scalar y = 0.0;   
  
  switch (operatorType) {
    
    case OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
          
        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = (x + y - 1.0)*(2.0*x + 2.0*y - 1.0);
        outputValues(1, i0) = x*(2.0*x - 1.0);
        outputValues(2, i0) = y*(2.0*y - 1.0);
        outputValues(3, i0) = -4.0*x*(x + y - 1.0);
        outputValues(4, i0) =  4.0*x*y;
        outputValues(5, i0) = -4.0*y*(x + y - 1.0);
        
      }
      break;

    case OPERATOR_GRAD:
    case OPERATOR_D1:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);

        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        outputValues(0, i0, 0) =  4.0*x + 4.0*y - 3.0;
        outputValues(0, i0, 1) =  4.0*x + 4.0*y - 3.0;

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

        outputValues(2, i0, 0) =  0.0;
        outputValues(2, i0, 1) =  4.0*y - 1.0;
        
        outputValues(3, i0, 0) = -4.0*(2.0*x + y - 1.0);
        outputValues(3, i0, 1) = -4.0*x;

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

        outputValues(5, i0, 0) = -4.0*y;
        outputValues(5, i0, 1) = -4.0*(x + 2.0*y - 1.0);
      }
      break;

    case OPERATOR_CURL:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        
        // CURL(u) = (u_y, -u_x), is rotated GRAD
        outputValues(0, i0, 1) =-(4.0*x + 4.0*y - 3.0);
        outputValues(0, i0, 0) =  4.0*x + 4.0*y - 3.0;
        
        outputValues(1, i0, 1) =-(4.0*x - 1.0);
        outputValues(1, i0, 0) =  0.0;
        
        outputValues(2, i0, 1) =  0.0;
        outputValues(2, i0, 0) =  4.0*y - 1.0;
        
        outputValues(3, i0, 1) =  4.0*(2.0*x + y - 1.0);
        outputValues(3, i0, 0) = -4.0*x;
        
        outputValues(4, i0, 1) = -4.0*y;
        outputValues(4, i0, 0) =  4.0*x;
        
        outputValues(5, i0, 1) =  4.0*y;
        outputValues(5, i0, 0) = -4.0*(x + 2.0*y - 1.0);
      }
      break;

    case OPERATOR_DIV:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_TRI_C2_FEM): DIV is invalid operator for rank-0 (scalar) fields in 2D.");
      break;

    case OPERATOR_D2:
      for (int i0 = 0; i0 < dim0; i0++) {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        // D2 -> (2,0) -> dx^2. 
        outputValues(0, i0, 0) = 4.0;
        outputValues(1, i0, 0) = 4.0;
        outputValues(2, i0, 0) = 0.0;
        outputValues(3, i0, 0) =-8.0;
        outputValues(4, i0, 0) = 0.0;
        outputValues(5, i0, 0) = 0.0;
        
        // D2 -> (1,1) -> dx dy
        outputValues(0, i0, 1) = 4.0;
        outputValues(1, i0, 1) = 0.0;
        outputValues(2, i0, 1) = 0.0;
        outputValues(3, i0, 1) =-4.0;
        outputValues(4, i0, 1) = 4.0;
        outputValues(5, i0, 1) =-4.0;
        
        // D2 -> (0,2) -> dy^2
        outputValues(0, i0, 2) = 4.0;
        outputValues(1, i0, 2) = 0.0;
        outputValues(2, i0, 2) = 4.0;
        outputValues(3, i0, 2) = 0.0;
        outputValues(4, i0, 2) = 0.0;
        outputValues(5, i0, 2) =-8.0;
      }// for i0
      break;
      
    case OPERATOR_D3:
    case OPERATOR_D4:
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        int DkCardinality = Intrepid2::getDkCardinality(operatorType, 
                                                       this -> basisCellTopology_.getDimension() );
        for(int dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
          for (int i0 = 0; i0 < dim0; i0++) {
            for(int dkOrd = 0; dkOrd < DkCardinality; dkOrd++){
              outputValues(dofOrd, i0, dkOrd) = 0.0;
            }
          }
        }
      }
      break;

    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_TRI_C2_FEM): Invalid operator type");
  }
}
  void Basis_HGRAD_QUAD_Cn_FEM<Scalar,ArrayScalar>::getValues( ArrayScalar &outputValues ,
							       const ArrayScalar &inputPoints ,
							       const EOperator operatorType ) const 
  {
#ifdef HAVE_INTREPID2_DEBUG
    getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
					      inputPoints,
					      operatorType,
					      this -> getBaseCellTopology(),
					      this -> getCardinality() );
#endif

    ArrayScalar xInputPoints(inputPoints.dimension(0),1);
    ArrayScalar yInputPoints(inputPoints.dimension(0),1);

    const Basis<Scalar,ArrayScalar> &xBasis_ = *this->bases_[0][0];
    const Basis<Scalar,ArrayScalar> &yBasis_ = *this->bases_[0][1];

    for (int i=0;i<inputPoints.dimension(0);i++) {
      xInputPoints(i,0) = inputPoints(i,0);
      yInputPoints(i,0) = inputPoints(i,1);
    }

    switch (operatorType) {
    case OPERATOR_VALUE:
      {
	ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
	ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));

	xBasis_.getValues(xBasisValues,xInputPoints,OPERATOR_VALUE);
	yBasis_.getValues(yBasisValues,yInputPoints,OPERATOR_VALUE);

	int bfcur = 0;
	for (int j=0;j<yBasis_.getCardinality();j++) {
	  for (int i=0;i<xBasis_.getCardinality();i++) {
	    for (int k=0;k<inputPoints.dimension(0);k++) {
	      outputValues(bfcur,k) = xBasisValues(i,k) * yBasisValues(j,k);
	    }
	    bfcur++;
	  }
	}
      }
      break;
    case OPERATOR_GRAD:
    case OPERATOR_D1:
      {
	ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
	ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));
	ArrayScalar xBasisDerivs(xBasis_.getCardinality(),xInputPoints.dimension(0),1);
	ArrayScalar yBasisDerivs(yBasis_.getCardinality(),yInputPoints.dimension(0),1);

	xBasis_.getValues(xBasisValues,xInputPoints,OPERATOR_VALUE);
	yBasis_.getValues(yBasisValues,yInputPoints,OPERATOR_VALUE);
	xBasis_.getValues(xBasisDerivs,xInputPoints,OPERATOR_D1);
	yBasis_.getValues(yBasisDerivs,yInputPoints,OPERATOR_D1);	

	// there are two multiindices: I need the (1,0) and (0,1) derivatives
	int bfcur = 0;

	for (int j=0;j<yBasis_.getCardinality();j++) {
	  for (int i=0;i<xBasis_.getCardinality();i++) {
	    for (int k=0;k<inputPoints.dimension(0);k++) {
	      outputValues(bfcur,k,0) = xBasisDerivs(i,k,0) * yBasisValues(j,k);
	      outputValues(bfcur,k,1) = xBasisValues(i,k) * yBasisDerivs(j,k,0);
	    }
	    bfcur++;
	  }
	}
      }
      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:
      {
	ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
	ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));

	Teuchos::Array<int> partialMult;

	for (int d=0;d<getDkCardinality(operatorType,2);d++) {
	  getDkMultiplicities( partialMult , d , operatorType , 2 );
	  if (partialMult[0] == 0) {
	    xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0));
	    xBasis_.getValues( xBasisValues , xInputPoints, OPERATOR_VALUE );
	  }
	  else {
	    xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0),1);
	    EOperator xop = (EOperator) ( (int) OPERATOR_D1 + partialMult[0] - 1 );
	    xBasis_.getValues( xBasisValues , xInputPoints, xop );
	    xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0));
	  }
	  if (partialMult[1] == 0) {
	    yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0));
	    yBasis_.getValues( yBasisValues , yInputPoints, OPERATOR_VALUE );
	  }
	  else {
	    yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0),1);
	    EOperator yop = (EOperator) ( (int) OPERATOR_D1 + partialMult[1] - 1 );
	    yBasis_.getValues( yBasisValues , yInputPoints, yop );
	    yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0));
	  }


	  int bfcur = 0;
	  for (int j=0;j<yBasis_.getCardinality();j++) {
	    for (int i=0;i<xBasis_.getCardinality();i++) {
	      for (int k=0;k<inputPoints.dimension(0);k++) {
		outputValues(bfcur,k,d) = xBasisValues(i,k) * yBasisValues(j,k);
	      }
	      bfcur++;
	    }
	  }
	}
      }
      break;
    case OPERATOR_CURL:
      {
	ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
	ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));
	ArrayScalar xBasisDerivs(xBasis_.getCardinality(),xInputPoints.dimension(0),1);
	ArrayScalar yBasisDerivs(yBasis_.getCardinality(),yInputPoints.dimension(0),1);

	xBasis_.getValues(xBasisValues,xInputPoints,OPERATOR_VALUE);
	yBasis_.getValues(yBasisValues,yInputPoints,OPERATOR_VALUE);
	xBasis_.getValues(xBasisDerivs,xInputPoints,OPERATOR_D1);
	yBasis_.getValues(yBasisDerivs,yInputPoints,OPERATOR_D1);	

	// there are two multiindices: I need the (1,0) and (0,1) derivatives
	int bfcur = 0;

	for (int j=0;j<yBasis_.getCardinality();j++) {
	  for (int i=0;i<xBasis_.getCardinality();i++) {
	    for (int k=0;k<inputPoints.dimension(0);k++) {
	      outputValues(bfcur,k,0) = xBasisValues(i,k) * yBasisDerivs(j,k,0);
	      outputValues(bfcur,k,1) = -xBasisDerivs(i,k,0) * yBasisValues(j,k);
	    }
	    bfcur++;
	  }
	}
      }
      break;      
    default:
        TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                            ">>> ERROR (Basis_HGRAD_QUAD_Cn_FEM): Operator type not implemented");
        break;
    }
  }
  void Basis_HDIV_TRI_In_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                              const ArrayScalar &  inputPoints,
                                                              const EOperator      operatorType) const {
  
    // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
    Intrepid2::getValues_HDIV_Args<Scalar, ArrayScalar>(outputValues,
                                                        inputPoints,
                                                        operatorType,
                                                        this -> getBaseCellTopology(),
                                                        this -> getCardinality() );
#endif
    const int numPts = inputPoints.dimension(0);
    const int deg = this -> getDegree();
    const int scalarBigN = (deg+1)*(deg+2)/2;

    try {
      switch (operatorType) {
      case OPERATOR_VALUE:
        {
          ArrayScalar phisCur( scalarBigN , numPts );
          Phis.getValues( phisCur , inputPoints , OPERATOR_VALUE );

          for (int i=0;i<outputValues.dimension(0);i++) { // RT bf
            for (int j=0;j<outputValues.dimension(1);j++) {  // point
              outputValues(i,j,0) = 0.0;
              outputValues(i,j,1) = 0.0;
              for (int k=0;k<scalarBigN;k++) { // Dubiner bf
                outputValues(i,j,0) += coeffs(k,i) * phisCur(k,j);
                outputValues(i,j,1) += coeffs(k+scalarBigN,i) * phisCur(k,j);
              }
            }
          }
        }
        break;
      case OPERATOR_DIV:
        {
          ArrayScalar phisCur( scalarBigN , numPts , 2 );
          Phis.getValues( phisCur , inputPoints , OPERATOR_GRAD );
          for (int i=0;i<outputValues.dimension(0);i++) { // bf loop
            for (int j=0;j<outputValues.dimension(1);j++) { // point loop
              // dx of x component
              outputValues(i,j) = 0.0;
              for (int k=0;k<scalarBigN;k++) {
                outputValues(i,j) += coeffs(k,i) * phisCur(k,j,0);
              }
              // dy of y component
              for (int k=0;k<scalarBigN;k++) {
                outputValues(i,j) += coeffs(k+scalarBigN,i) * phisCur(k,j,1);
              }
            }
          }
        }
        break;
      default:
        TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                            ">>> ERROR (Basis_HDIV_TRI_In_FEM): Operator type not implemented");
        break;
      }
    }
    catch (std::invalid_argument &exception){
      TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                          ">>> ERROR (Basis_HDIV_TRI_In_FEM): Operator type not implemented");    
    }

  }
  void TabulatorTet<Scalar,ArrayScalar,0>::tabulate( ArrayScalar &outputValues ,
                                                    const int deg ,
                                                    const ArrayScalar &z )
  {
    const int np = z.dimension( 0 );
    int idxcur;
  
    // each point needs to be transformed from Pavel's element
    // z(i,0) --> (2.0 * z(i,0) - 1.0)
    // z(i,1) --> (2.0 * z(i,1) - 1.0)
    // z(i,2) --> (2.0 * z(i,2) - 1.0)
  
    Teuchos::Array<Scalar> f1(np),f2(np),f3(np),f4(np),f5(np);
  
    for (int i=0;i<np;i++) {
      f1[i] = 0.5 * ( 2.0 + 2.0*(2.0*z(i,0)-1.0) + (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
      Scalar foo =  0.5 * ( (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
      f2[i] = foo * foo;
      f3[i] = 0.5 * ( 1.0 + 2.0 * (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) );
      f4[i] = 0.5 * ( 1.0 - (2.0*z(i,2)-1.0) );
      f5[i] = f4[i] * f4[i];
    }

    // constant term
    idxcur = TabulatorTet<Scalar,ArrayScalar,0>::idx(0,0,0);
    for (int i=0;i<np;i++) {
      outputValues(idxcur,i) = 1.0 + z(i,0) - z(i,0) + z(i,1) - z(i,1) + z(i,2) - z(i,2);
    }
  
    if (deg > 0) {

      // D^{1,0,0}
      idxcur = TabulatorTet<Scalar,ArrayScalar,0>::idx(1,0,0);
      for (int i=0;i<np;i++) {
        outputValues(idxcur,i) = f1[i];
      }
  
      // p recurrence
      for (int p=1;p<deg;p++) {
        Scalar a1 = (2.0 * p + 1.0) / ( p + 1.0);
        Scalar a2 = p / ( p + 1.0 );
        int idxp = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,0,0);
        int idxpp1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p+1,0,0);
        int idxpm1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p-1,0,0);
        for (int i=0;i<np;i++) {
          outputValues(idxpp1,i) = a1 * f1[i] * outputValues(idxp,i) - a2 * f2[i] * outputValues(idxpm1,i);
        }
      }
      // q = 1
      for (int p=0;p<deg;p++) {
        int idx0 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,0,0);
        int idx1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,1,0);
        for (int i=0;i<np;i++) {
          outputValues(idx1,i) = outputValues(idx0,i) * ( p * ( 1.0 + (2.0*z(i,1)-1.0) ) +
                                                          0.5 * ( 2.0 + 3.0 * (2.0*z(i,1)-1.0) + (2.0*z(i,2)-1.0) ) );
        }
      }
  
      // q recurrence
      for (int p=0;p<deg-1;p++) {
        for (int q=1;q<deg-p;q++) {
          Scalar aq,bq,cq;

	  TabulatorTet<Scalar,ArrayScalar,0>::jrc(2.0*p+1.0 ,0 ,q, aq, bq, cq);
          int idxpqp1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q+1,0);
          int idxpq = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,0);
          int idxpqm1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q-1,0);
          for (int i=0;i<np;i++) {
            outputValues(idxpqp1,i) = ( aq * f3[i] + bq * f4[i] ) * outputValues(idxpq,i) 
              - ( cq * f5[i] ) * outputValues(idxpqm1,i);
          }
        }
      }
  
      // r = 1
      for (int p=0;p<deg;p++) {
        for (int q=0;q<deg-p;q++) {
          int idxpq1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,1);
          int idxpq0 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,0);
          for (int i=0;i<np;i++) {
            outputValues(idxpq1,i) = outputValues(idxpq0,i) * ( 1.0 + p + q + ( 2.0 + q + 
                                                                                p ) * (2.0*z(i,2)-1.0) );
          }
        }
      }
      // general r recurrence
      for (int p=0;p<deg-1;p++) {
        for (int q=0;q<deg-p-1;q++) {
          for (int r=1;r<deg-p-q;r++) {
            Scalar ar,br,cr;
            int idxpqrp1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,r+1);
            int idxpqr = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,r);
            int idxpqrm1 = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,r-1);
            jrc(2.0*p+2.0*q+2.0, 0.0, r, ar, br, cr);
            for (int i=0;i<np;i++) {
              outputValues(idxpqrp1,i) = (ar * (2.0*z(i,2)-1.0) + br) * outputValues( idxpqr , i ) - cr * outputValues(idxpqrm1,i);
            }
          }
        }
      }

    }  
    // normalize
    for (int p=0;p<=deg;p++) {
      for (int q=0;q<=deg-p;q++) {
        for (int r=0;r<=deg-p-q;r++) {
          int idxcur = TabulatorTet<Scalar,ArrayScalar,0>::idx(p,q,r);
          Scalar scal = sqrt( (p+0.5)*(p+q+1.0)*(p+q+r+1.5) );
          for (int i=0;i<np;i++) {
            outputValues(idxcur,i) *= scal;
          }
        }
      }
    }
  
    return;
  
  }
void Basis_HGRAD_LINE_Cn_FEM_JACOBI<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                                    const ArrayScalar &  inputPoints,
                                                                    const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
  Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dimension 0 of inputPoints
  int numPoints = inputPoints.dimension(0);  
  
  Teuchos::Array<Scalar> tmpPoints(numPoints);
  Teuchos::Array<Scalar> jacobiPolyAtPoints(numPoints);

  // Copy inputPoints into tmpPoints, to prepare for call to jacobfd
  for (int i=0; i<numPoints; i++) {
    tmpPoints[i] = inputPoints(i, 0);
  }

  try {
    switch (operatorType) {
    case OPERATOR_VALUE: {
      for (int ord = 0; ord < this -> basisCardinality_; ord++) {
        IntrepidPolylib::jacobfd(numPoints, &tmpPoints[0], &jacobiPolyAtPoints[0], (Scalar*)0, ord, jacobiAlpha_, jacobiBeta_);
        for (int pt = 0; pt < numPoints; pt++) {
          // outputValues is a rank-2 array with dimensions (basisCardinality_, numPoints)
          outputValues(ord, pt) = jacobiPolyAtPoints[pt];
        }
      }
    }
    break;
      
    case OPERATOR_GRAD:
    case OPERATOR_D1: {
      for (int ord = 0; ord < this -> basisCardinality_; ord++) {
        IntrepidPolylib::jacobd(numPoints, &tmpPoints[0], &jacobiPolyAtPoints[0], ord, jacobiAlpha_, jacobiBeta_);
        for (int pt = 0; pt < numPoints; pt++) {
          // outputValues is a rank-2 array with dimensions (basisCardinality_, numPoints)
          outputValues(ord, pt, 0) = jacobiPolyAtPoints[pt];
        }
      }
    }
    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: {
      int d_order = getOperatorOrder( operatorType );
      // fill in derivatives of polynomials of degree 0 through d_order - 1  with 0
      // e.g. D2 annhialates linears.
      int stop_order;
      if (d_order > this->getDegree()) {
	stop_order = this->getDegree();
      }
      else {
	stop_order = d_order;
      }
      for (int p_order=0;p_order<stop_order;p_order++) {
	for (int pt=0;pt<numPoints;pt++) {
	  outputValues(p_order,pt,0) = 0.0;
	}
      }
      // fill in rest of derivatives with the differentiation rule for Jacobi polynomials
      for (int p_order=d_order;p_order<=this->getDegree();p_order++) {
	// calculate the scaling factor with a little loop.
	Scalar scalefactor = 1.0;
	for (int d=1;d<=d_order;d++) {
	  scalefactor *= 0.5 * ( p_order + jacobiAlpha_ + jacobiBeta_ + d );
	}

	// put in the right call to IntrepidPolyLib
        IntrepidPolylib::jacobfd(numPoints, &tmpPoints[0], 
				 &jacobiPolyAtPoints[0], 
				 (Scalar*)0, p_order-d_order, 
				 jacobiAlpha_ + d_order, 
				 jacobiBeta_ + d_order);
        for (int pt = 0; pt < numPoints; pt++) {
          // outputValues is a rank-3 array with dimensions (basisCardinality_, numPoints)
          outputValues(p_order, pt,0) = scalefactor *jacobiPolyAtPoints[pt];
        }
	
      }
      
    }
    break;
    case OPERATOR_DIV:
    case OPERATOR_CURL:
	TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
			    ">>> ERROR (Basis_HGRAD_LINE_Cn_FEM_JACOBI): Invalid operator type.");
      break;
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_LINE_Cn_FEM_JACOBI): Invalid operator type.");
      break;
    }
  }
  catch (std::invalid_argument &exception){
    TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
			">>> ERROR (Basis_HGRAD_LINE_Cn_FEM_JACOBI): Operator failed");    
  }
}
void Basis_HGRAD_PYR_C1_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
                                                             const ArrayScalar &  inputPoints,
                                                             const EOperator      operatorType) const {
  
  // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
  Intrepid::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
                                                      inputPoints,
                                                      operatorType,
                                                      this -> getBaseCellTopology(),
                                                      this -> getCardinality() );
#endif
  
  // Number of evaluation points = dim 0 of inputPoints
  int dim0 = inputPoints.dimension(0);  
  
  // Temporaries: (x,y,z) coordinates of the evaluation point
  Scalar x = 0.0;                                    
  Scalar y = 0.0;   
  Scalar z = 0.0;
  const Scalar eps = std::numeric_limits<Scalar>::epsilon( );
  
  switch (operatorType) {
    
    case OPERATOR_VALUE:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0, 0);
        y = inputPoints(i0, 1);
        z = inputPoints(i0, 2);
        
        //be sure that the basis functions are defined when z is very close to 1.
        if(fabs(z-1.0) < eps) {
          if(z <= 1.0) z = 1.0-eps;
          else  z = 1.0+eps;
        }


        Scalar zTerm = 0.25/(1.0 - z);

        // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
        outputValues(0, i0) = (1.0 - x - z) * (1.0 - y - z) * zTerm;
        outputValues(1, i0) = (1.0 + x - z) * (1.0 - y - z) * zTerm;
        outputValues(2, i0) = (1.0 + x - z) * (1.0 + y - z) * zTerm;
        outputValues(3, i0) = (1.0 - x - z) * (1.0 + y - z)  * zTerm;
        outputValues(4, i0) = z;
      }
      break;
      
    case OPERATOR_GRAD:
    case OPERATOR_D1:
      for (int i0 = 0; i0 < dim0; i0++) {

    	x = inputPoints(i0, 0);
    	y = inputPoints(i0, 1);
    	z = inputPoints(i0, 2);


    	//be sure that the basis functions are defined when z is very close to 1.
    	//warning, the derivatives are discontinuous in (0, 0, 1)
    	if(fabs(z-1.0) < eps) {
        if(z <= 1.0) z = 1.0-eps;
        else  z = 1.0+eps;
      }


    	Scalar zTerm = 0.25/(1.0 - z);
    	Scalar zTerm2 = 4.0 * zTerm * zTerm;
        
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, spaceDim)
        outputValues(0, i0, 0) = (y + z - 1.0) * zTerm;
        outputValues(0, i0, 1) = (x + z - 1.0) * zTerm;
        outputValues(0, i0, 2) = x * y * zTerm2 - 0.25;
        
        outputValues(1, i0, 0) =  (1.0 - y - z) * zTerm;
        outputValues(1, i0, 1) =  (z - x - 1.0) * zTerm;
        outputValues(1, i0, 2) =  - x*y * zTerm2 - 0.25;
        
        outputValues(2, i0, 0) =  (1.0 + y - z) * zTerm;
        outputValues(2, i0, 1) =  (1.0 + x - z) * zTerm;
        outputValues(2, i0, 2) =  x * y * zTerm2 - 0.25;

        outputValues(3, i0, 0) =  (z - y - 1.0) * zTerm;
        outputValues(3, i0, 1) =  (1.0 - x - z) * zTerm;
        outputValues(3, i0, 2) =  - x*y * zTerm2 - 0.25;
  
        outputValues(4, i0, 0) =  0.0;
        outputValues(4, i0, 1) =  0.0;
        outputValues(4, i0, 2) =  1;
      }
      break;
      
    case OPERATOR_CURL:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_CURL), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_PYR_C1_FEM): CURL is invalid operator for rank-0 (scalar) functions in 3D");
      break;
      
    case OPERATOR_DIV:
      TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_PYR_C1_FEM): DIV is invalid operator for rank-0 (scalar) functions in 3D");
      break;
      
    case OPERATOR_D2:
      for (int i0 = 0; i0 < dim0; i0++) {
        x = inputPoints(i0,0);
        y = inputPoints(i0,1);
        z = inputPoints(i0,2);

        //be sure that the basis functions are defined when z is very close to 1.
        //warning, the derivatives are discontinuous in (0, 0, 1)
        if(fabs(z-1.0) < eps) {
          if(z <= 1.0) z = 1.0-eps;
          else  z = 1.0+eps;
        }


        Scalar zTerm = 0.25/(1.0 - z);
        Scalar zTerm2 = 4.0 * zTerm * zTerm;
        Scalar zTerm3 = 8.0 * zTerm * zTerm2;

        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, D2Cardinality = 6)
        outputValues(0, i0, 0) =  0.0;                    // {2, 0, 0}
        outputValues(0, i0, 1) =  zTerm;          		  // {1, 1, 0}
        outputValues(0, i0, 2) =  y*zTerm2;          	  // {1, 0, 1}
        outputValues(0, i0, 3) =  0.0;                    // {0, 2, 0}
        outputValues(0, i0, 4) =  x*zTerm2;        		  // {0, 1, 1}
        outputValues(0, i0, 5) =  x*y*zTerm3;             // {0, 0, 2}

        outputValues(1, i0, 0) =  0.0;                    // {2, 0, 0}
        outputValues(1, i0, 1) =  -zTerm;			      // {1, 1, 0}
        outputValues(1, i0, 2) =  -y*zTerm2; 			  // {1, 0, 1}
        outputValues(1, i0, 3) =  0.0;                    // {0, 2, 0}
        outputValues(1, i0, 4) =  -x*zTerm2;              // {0, 1, 1}
        outputValues(1, i0, 5) =  -x*y*zTerm3;            // {0, 0, 2}

        outputValues(2, i0, 0) =  0.0;                    // {2, 0, 0}
        outputValues(2, i0, 1) =  zTerm;          		  // {1, 1, 0}
        outputValues(2, i0, 2) =  y*zTerm2;          	  // {1, 0, 1}
        outputValues(2, i0, 3) =  0.0;                    // {0, 2, 0}
        outputValues(2, i0, 4) =  x*zTerm2;       		  // {0, 1, 1}
        outputValues(2, i0, 5) =  x*y*zTerm3;             // {0, 0, 2}

        outputValues(3, i0, 0) =  0.0;                    // {2, 0, 0}
        outputValues(3, i0, 1) =  -zTerm;			      // {1, 1, 0}
        outputValues(3, i0, 2) =  -y*zTerm2;        	  // {1, 0, 1}
        outputValues(3, i0, 3) =  0.0;                    // {0, 2, 0}
        outputValues(3, i0, 4) =  -x*zTerm2;			  // {0, 1, 1}
        outputValues(3, i0, 5) =  -x*y*zTerm3;            // {0, 0, 2}

        outputValues(4, i0, 0) =  0.0;                    // {2, 0, 0}
        outputValues(4, i0, 1) =  0.0;          		  // {1, 1, 0}
        outputValues(4, i0, 2) =  0.0;          		  // {1, 0, 1}
        outputValues(4, i0, 3) =  0.0;                    // {0, 2, 0}
        outputValues(4, i0, 4) =  0.0;         			  // {0, 1, 1}
        outputValues(4, i0, 5) =  0.0;                    // {0, 0, 2}
      }
      break;

    case OPERATOR_D3:
    case OPERATOR_D4:
    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
      {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        int DkCardinality = Intrepid::getDkCardinality(operatorType, 
                                                       this -> basisCellTopology_.getDimension() );
        for(int dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
          for (int i0 = 0; i0 < dim0; i0++) {
            for(int dkOrd = 0; dkOrd < DkCardinality; dkOrd++){
              outputValues(dofOrd, i0, dkOrd) = 0.0;
            }
          }
        }
      }
      break;
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid::isValidOperator(operatorType) ), std::invalid_argument,
                          ">>> ERROR (Basis_HGRAD_PYR_C1_FEM): Invalid operator type");
  }
}
  void Basis_HGRAD_HEX_Cn_FEM<Scalar,ArrayScalar>::getValues( ArrayScalar &outputValues ,
							       const ArrayScalar &inputPoints ,
							       const EOperator operatorType ) const 
  {
#ifdef HAVE_INTREPID2_DEBUG
    Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
							inputPoints,
							operatorType,
							this -> getBaseCellTopology(),
							this -> getCardinality() );
#endif
    
    Basis<Scalar,ArrayScalar> &xBasis_ = *this->bases_[0][0];
    Basis<Scalar,ArrayScalar> &yBasis_ = *this->bases_[0][1];
    Basis<Scalar,ArrayScalar> &zBasis_ = *this->bases_[0][2];


    ArrayScalar xInputPoints(inputPoints.dimension(0),1);
    ArrayScalar yInputPoints(inputPoints.dimension(0),1);
    ArrayScalar zInputPoints(inputPoints.dimension(0),1);

    for (int i=0;i<inputPoints.dimension(0);i++) {
      xInputPoints(i,0) = inputPoints(i,0);
      yInputPoints(i,0) = inputPoints(i,1);
      zInputPoints(i,0) = inputPoints(i,2);
    }

    switch (operatorType) {
    case OPERATOR_VALUE:
      {
	ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
	ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));
	ArrayScalar zBasisValues(zBasis_.getCardinality(),zInputPoints.dimension(0));

	xBasis_.getValues(xBasisValues,xInputPoints,OPERATOR_VALUE);
	yBasis_.getValues(yBasisValues,yInputPoints,OPERATOR_VALUE);
	zBasis_.getValues(zBasisValues,zInputPoints,OPERATOR_VALUE);

	int bfcur = 0;
	for (int k=0;k<zBasis_.getCardinality();k++) {
	  for (int j=0;j<yBasis_.getCardinality();j++) {
	    for (int i=0;i<xBasis_.getCardinality();i++) {
	      for (int l=0;l<inputPoints.dimension(0);l++) {
		outputValues(bfcur,l) = xBasisValues(i,l) * yBasisValues(j,l) * zBasisValues(k,l);
	      }
	      bfcur++;
	    }
	  }
	}
      }
      break;
    case OPERATOR_D1:
    case OPERATOR_GRAD:
      {
        ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
        ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));
        ArrayScalar zBasisValues(zBasis_.getCardinality(),zInputPoints.dimension(0));
        ArrayScalar xBasisDerivs(xBasis_.getCardinality(),xInputPoints.dimension(0),1);
        ArrayScalar yBasisDerivs(yBasis_.getCardinality(),yInputPoints.dimension(0),1);
        ArrayScalar zBasisDerivs(zBasis_.getCardinality(),zInputPoints.dimension(0),1);

        xBasis_.getValues(xBasisValues,xInputPoints,OPERATOR_VALUE);
        yBasis_.getValues(yBasisValues,yInputPoints,OPERATOR_VALUE);
        zBasis_.getValues(zBasisValues,zInputPoints,OPERATOR_VALUE);
        xBasis_.getValues(xBasisDerivs,xInputPoints,OPERATOR_D1);
        yBasis_.getValues(yBasisDerivs,yInputPoints,OPERATOR_D1);    	
        zBasis_.getValues(zBasisDerivs,zInputPoints,OPERATOR_D1);    	

	int bfcur = 0;
	for (int k=0;k<zBasis_.getCardinality();k++) {
	  for (int j=0;j<yBasis_.getCardinality();j++) {
	    for (int i=0;i<xBasis_.getCardinality();i++) {
	      for (int l=0;l<inputPoints.dimension(0);l++) {
		outputValues(bfcur,l,0) = xBasisDerivs(i,l,0) * yBasisValues(j,l) * zBasisValues(k,l);
		outputValues(bfcur,l,1) = xBasisValues(i,l) * yBasisDerivs(j,l,0) * zBasisValues(k,l);
		outputValues(bfcur,l,2) = xBasisValues(i,l) * yBasisValues(j,l) * zBasisDerivs(k,l,0);
	      }
	      bfcur++;
	    }
	  }
	}
      }
      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:
      {
        ArrayScalar xBasisValues(xBasis_.getCardinality(),xInputPoints.dimension(0));
        ArrayScalar yBasisValues(yBasis_.getCardinality(),yInputPoints.dimension(0));
        ArrayScalar zBasisValues(yBasis_.getCardinality(),zInputPoints.dimension(0));

        Teuchos::Array<int> partialMult;
	
        for (int d=0;d<getDkCardinality(operatorType,3);d++) {
          getDkMultiplicities( partialMult , d , operatorType , 3 );
          if (partialMult[0] == 0) {
            xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0));
            xBasis_.getValues( xBasisValues , xInputPoints, OPERATOR_VALUE );
          }
          else {
            xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0),1);
            EOperator xop = (EOperator) ( (int) OPERATOR_D1 + partialMult[0] - 1 );
            xBasis_.getValues( xBasisValues , xInputPoints, xop );
            xBasisValues.resize(xBasis_.getCardinality(),xInputPoints.dimension(0));
          }
          if (partialMult[1] == 0) {
            yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0));
            yBasis_.getValues( yBasisValues , yInputPoints, OPERATOR_VALUE );
          }
          else {
            yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0),1);
            EOperator yop = (EOperator) ( (int) OPERATOR_D1 + partialMult[1] - 1 );
            yBasis_.getValues( yBasisValues , yInputPoints, yop );
            yBasisValues.resize(yBasis_.getCardinality(),yInputPoints.dimension(0));
          }
          if (partialMult[2] == 0) {
            zBasisValues.resize(zBasis_.getCardinality(),zInputPoints.dimension(0));
            zBasis_.getValues( zBasisValues , zInputPoints, OPERATOR_VALUE );
          }
          else {
            zBasisValues.resize(zBasis_.getCardinality(),zInputPoints.dimension(0),1);
            EOperator zop = (EOperator) ( (int) OPERATOR_D1 + partialMult[2] - 1 );
            zBasis_.getValues( zBasisValues , zInputPoints, zop );
            zBasisValues.resize(zBasis_.getCardinality(),zInputPoints.dimension(0));
          }


          int bfcur = 0;
	  for (int k=0;k<zBasis_.getCardinality();k++) {
	    for (int j=0;j<yBasis_.getCardinality();j++) {
	      for (int i=0;i<xBasis_.getCardinality();i++) {
		for (int l=0;l<inputPoints.dimension(0);l++) {
		  outputValues(bfcur,l,d) = xBasisValues(i,l) * yBasisValues(j,l) * zBasisValues(k,l);
		}
		bfcur++;
	      }
	    }
	  }
	}
      }
      break;
    default:
        TEUCHOS_TEST_FOR_EXCEPTION( true , std::invalid_argument,
                            ">>> ERROR (Basis_HGRAD_HEX_Cn_FEM): Operator type not implemented");
        break;
    }
  }
  void Basis_HGRAD_POLY_C1_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar& outputValues,
							       const ArrayScalar& inputPoints,
							       const ArrayScalar& cellVertices,
							       const EOperator operatorType) const{
    
    
    // implement wachspress basis functions
    switch (operatorType) {
    case OPERATOR_VALUE:
      {
	shapeFunctions<Scalar,ArrayScalar>(outputValues,inputPoints,cellVertices);
      }
      break;
    case OPERATOR_GRAD:
      {
	FieldContainer<Sacado::Fad::DFad<Scalar> > dInput(inputPoints.dimension(0),inputPoints.dimension(1));
	for (int i=0;i<inputPoints.dimension(0);i++){
	  for (int j=0;j<2;j++){
	    dInput(i,j) = Sacado::Fad::DFad<Scalar>( inputPoints(i,j));
	    dInput(i,j).diff(j,2);
	  }
	}
	FieldContainer<Sacado::Fad::DFad<Scalar> > cellVerticesFad(cellVertices.dimension(0),cellVertices.dimension(1));
	for (int i=0;i<cellVertices.dimension(0);i++){
	  for (int j=0;j<cellVertices.dimension(1);j++){
	    cellVerticesFad(i,j) = Sacado::Fad::DFad<Scalar>( cellVertices(i,j) );
	  }
	}
	
	FieldContainer<Sacado::Fad::DFad<Scalar> > dOutput(outputValues.dimension(0),outputValues.dimension(1));
	
	shapeFunctions<Sacado::Fad::DFad<Scalar>, FieldContainer<Sacado::Fad::DFad<Scalar> > >(dOutput,dInput,cellVerticesFad);
	
	for (int i=0;i<outputValues.dimension(0);i++){
	  for (int j=0;j<outputValues.dimension(1);j++){
	    for (int k=0;k<outputValues.dimension(2);k++){
	      outputValues(i,j,k) = dOutput(i,j).dx(k);
	    }
	  }
	}
      }
      break;
    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:
      {
	TEUCHOS_TEST_FOR_EXCEPTION ( true, std::invalid_argument, 
			     ">>> ERROR (Basis_HGRAD_POLY_C1_FEM): operator not implemented yet");
      }
      break;
    default:
      TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid::isValidOperator(operatorType)), std::invalid_argument,
			  ">>> ERROR (Basis_HGRAD_POLY_C1_FEM): Invalid operator type");
      break;
    }

  }
  void Basis_HCURL_HEX_In_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
							      const ArrayScalar &  inputPoints,
							      const EOperator      operatorType) const {
    
    // Verify arguments
#ifdef HAVE_INTREPID_DEBUG
    Intrepid::getValues_HCURL_Args<Scalar, ArrayScalar>(outputValues,
						       inputPoints,
						       operatorType,
						       this -> getBaseCellTopology(),
						       this -> getCardinality() );
#endif
    
    // Number of evaluation points = dim 0 of inputPoints
    int dim0 = inputPoints.dimension(0);
    
    // separate out points
    FieldContainer<Scalar> xPoints(dim0,1);
    FieldContainer<Scalar> yPoints(dim0,1);
    FieldContainer<Scalar> zPoints(dim0,1);
    
    for (int i=0;i<dim0;i++) {
      xPoints(i,0) = inputPoints(i,0);
      yPoints(i,0) = inputPoints(i,1);
      zPoints(i,0) = inputPoints(i,2);
    }
    
    switch (operatorType) {
    case OPERATOR_VALUE:
      {
	FieldContainer<Scalar> closedBasisValsXPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisValsYPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisValsZPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsXPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsYPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsZPts( openBasis_.getCardinality() , dim0 );
	
	closedBasis_.getValues( closedBasisValsXPts , xPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisValsYPts , yPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisValsZPts , zPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsXPts , xPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsYPts , yPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsZPts , zPoints , OPERATOR_VALUE );

	// first we get the "horizontal basis functions that are tangent to the x-varying edges
	int bfcur = 0;
	for (int k=0;k<closedBasis_.getCardinality();k++) {
	  for (int j=0;j<closedBasis_.getCardinality();j++) {
	    for (int i=0;i<openBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = openBasisValsXPts(i,l) * closedBasisValsYPts(j,l) * closedBasisValsZPts(k,l);
		outputValues(bfcur,l,1) = 0.0;
		outputValues(bfcur,l,2) = 0.0;
	      }
	      bfcur++;
	    }
	  }
	}
	
	// second we get the basis functions in the direction of the y-varying edges
	for (int k=0;k<closedBasis_.getCardinality();k++) {
	  for (int j=0;j<openBasis_.getCardinality();j++) {
	    for (int i=0;i<closedBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = 0.0;
		outputValues(bfcur,l,1) = closedBasisValsXPts(i,l) * openBasisValsYPts(j,l) * closedBasisValsZPts(k,l);
		outputValues(bfcur,l,2) = 0.0;
	      }
	      bfcur++;
	    }
	  }
	}	

	// third we get the basis functions in the direction of the y-varying edges
	for (int k=0;k<openBasis_.getCardinality();k++) {
	  for (int j=0;j<closedBasis_.getCardinality();j++) {
	    for (int i=0;i<closedBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = 0.0;
		outputValues(bfcur,l,1) = 0.0;
		outputValues(bfcur,l,2) = closedBasisValsXPts(i,l) * closedBasisValsYPts(j,l) * openBasisValsZPts(k,l);
	      }
	      bfcur++;
	    }
	  }
	}
      }
      break;
    case OPERATOR_CURL:
      {
	FieldContainer<Scalar> closedBasisValsXPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisValsYPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisValsZPts( closedBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> closedBasisDerivsXPts( closedBasis_.getCardinality() , dim0 , 1 );
	FieldContainer<Scalar> closedBasisDerivsYPts( closedBasis_.getCardinality() , dim0 , 1 );
	FieldContainer<Scalar> closedBasisDerivsZPts( closedBasis_.getCardinality() , dim0 , 1 );
	FieldContainer<Scalar> openBasisValsXPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsYPts( openBasis_.getCardinality() , dim0 );
	FieldContainer<Scalar> openBasisValsZPts( openBasis_.getCardinality() , dim0 );
	
	closedBasis_.getValues( closedBasisValsXPts , xPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisValsYPts , yPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisValsZPts , zPoints , OPERATOR_VALUE );
	closedBasis_.getValues( closedBasisDerivsXPts , xPoints , OPERATOR_D1 );
	closedBasis_.getValues( closedBasisDerivsYPts , yPoints , OPERATOR_D1 );
	closedBasis_.getValues( closedBasisDerivsZPts , zPoints , OPERATOR_D1 );
	openBasis_.getValues( openBasisValsXPts , xPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsYPts , yPoints , OPERATOR_VALUE );
	openBasis_.getValues( openBasisValsZPts , zPoints , OPERATOR_VALUE );
	
	int bfcur = 0;

	// first we get the basis functions that are tangent to the x-varying edges
	for (int k=0;k<closedBasis_.getCardinality();k++) {
	  for (int j=0;j<closedBasis_.getCardinality();j++) {
	    for (int i=0;i<openBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = 0.0;
		outputValues(bfcur,l,1) = -openBasisValsXPts(i,l) * closedBasisValsYPts(j,l) * closedBasisDerivsZPts(k,l,0);
		outputValues(bfcur,l,2) = openBasisValsXPts(i,l) * closedBasisDerivsYPts(j,l,0) * closedBasisValsZPts(k,l);
	      }
	      bfcur++;
	    }
	  }
	}
	
	// second we get the basis functions in the direction of the y-varying edges
	for (int k=0;k<closedBasis_.getCardinality();k++) {
	  for (int j=0;j<openBasis_.getCardinality();j++) {
	    for (int i=0;i<closedBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = -closedBasisValsXPts(i,l) * openBasisValsYPts(j,l) * closedBasisDerivsZPts(k,l,0);
		outputValues(bfcur,l,1) = 0.0;
		outputValues(bfcur,l,2) = closedBasisDerivsXPts(i,l,0) * openBasisValsYPts(j,l) * closedBasisValsZPts(k,l);
	      }
	      bfcur++;
	    }
	  }
	}	

	// third we get the basis functions in the direction of the y-varying edges
	for (int k=0;k<openBasis_.getCardinality();k++) {
	  for (int j=0;j<closedBasis_.getCardinality();j++) {
	    for (int i=0;i<closedBasis_.getCardinality();i++) {
	      for (int l=0;l<dim0;l++) {
		outputValues(bfcur,l,0) = closedBasisValsXPts(i,l) * closedBasisDerivsYPts(j,l,0) * openBasisValsZPts(k,l);
		outputValues(bfcur,l,1) = -closedBasisDerivsXPts(i,l,0) * closedBasisValsYPts(j,l) * openBasisValsZPts(k,l);
		outputValues(bfcur,l,2) = 0.0;
	      }
	      bfcur++;
	    }
	  }
	}		
      }
      break;
    case OPERATOR_DIV:
      TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_HEX_In_FEM): DIV is invalid operator for HCURL Basis Functions");
      break;
      
    case OPERATOR_GRAD:
      TEST_FOR_EXCEPTION( (operatorType == OPERATOR_GRAD), std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_HEX_In_FEM): GRAD is invalid operator for HCURL Basis Functions");
      break;
      
    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:
      TEST_FOR_EXCEPTION( ( (operatorType == OPERATOR_D1)    ||
			    (operatorType == OPERATOR_D2)    ||
			    (operatorType == OPERATOR_D3)    ||
			    (operatorType == OPERATOR_D4)    ||
			    (operatorType == OPERATOR_D5)    ||
			    (operatorType == OPERATOR_D6)    ||
			    (operatorType == OPERATOR_D7)    ||
			    (operatorType == OPERATOR_D8)    ||
			    (operatorType == OPERATOR_D9)    ||
			    (operatorType == OPERATOR_D10) ),
			  std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_HEX_In_FEM): Invalid operator type");
      break;
      
    default:
      TEST_FOR_EXCEPTION( ( (operatorType != OPERATOR_VALUE) &&
			    (operatorType != OPERATOR_GRAD)  &&
			    (operatorType != OPERATOR_CURL)  &&
			    (operatorType != OPERATOR_CURL)   &&
			    (operatorType != OPERATOR_D1)    &&
			    (operatorType != OPERATOR_D2)    &&
			    (operatorType != OPERATOR_D3)    &&
			    (operatorType != OPERATOR_D4)    &&
			    (operatorType != OPERATOR_D5)    &&
			    (operatorType != OPERATOR_D6)    &&
			    (operatorType != OPERATOR_D7)    &&
			    (operatorType != OPERATOR_D8)    &&
			    (operatorType != OPERATOR_D9)    &&
			    (operatorType != OPERATOR_D10) ),
			  std::invalid_argument,
			  ">>> ERROR (Basis_HCURL_HEX_In_FEM): Invalid operator type");
    }
  }
void Basis_HGRAD_HEX_I2_FEM<Scalar, ArrayScalar>::getValues(ArrayScalar &        outputValues,
        const ArrayScalar &  inputPoints,
        const EOperator      operatorType) const {

    // Verify arguments
#ifdef HAVE_INTREPID2_DEBUG
    Intrepid2::getValues_HGRAD_Args<Scalar, ArrayScalar>(outputValues,
            inputPoints,
            operatorType,
            this -> getBaseCellTopology(),
            this -> getCardinality() );
#endif

    // Number of evaluation points = dim 0 of inputPoints
    ordinal_type dim0 = inputPoints.dimension(0);

    // Temporaries: (x,y,z) coordinates of the evaluation point
    Scalar x = 0.0;
    Scalar y = 0.0;
    Scalar z = 0.0;

    switch (operatorType) {

    case OPERATOR_VALUE:
        for (ordinal_type i0 = 0; i0 < dim0; i0++) {
            x = inputPoints(i0, 0);
            y = inputPoints(i0, 1);
            z = inputPoints(i0, 2);

            // outputValues is a rank-2 array with dimensions (basisCardinality_, dim0)
            outputValues( 0, i0) = 0.125*(1.0 - x)*(1.0 - y)*(1.0 - z)*(-x - y - z - 2.0);
            outputValues( 1, i0) = 0.125*(1.0 + x)*(1.0 - y)*(1.0 - z)*( x - y - z - 2.0);
            outputValues( 2, i0) = 0.125*(1.0 + x)*(1.0 + y)*(1.0 - z)*( x + y - z - 2.0);
            outputValues( 3, i0) = 0.125*(1.0 - x)*(1.0 + y)*(1.0 - z)*(-x + y - z - 2.0);
            outputValues( 4, i0) = 0.125*(1.0 - x)*(1.0 - y)*(1.0 + z)*(-x - y + z - 2.0);
            outputValues( 5, i0) = 0.125*(1.0 + x)*(1.0 - y)*(1.0 + z)*( x - y + z - 2.0);
            outputValues( 6, i0) = 0.125*(1.0 + x)*(1.0 + y)*(1.0 + z)*( x + y + z - 2.0);
            outputValues( 7, i0) = 0.125*(1.0 - x)*(1.0 + y)*(1.0 + z)*(-x + y + z - 2.0);

            outputValues( 8, i0) = 0.25*(1.0 - x*x)*(1.0 - y)*(1.0 - z);
            outputValues( 9, i0) = 0.25*(1.0 + x)*(1.0 - y*y)*(1.0 - z);
            outputValues(10, i0) = 0.25*(1.0 - x*x)*(1.0 + y)*(1.0 - z);
            outputValues(11, i0) = 0.25*(1.0 - x)*(1.0 - y*y)*(1.0 - z);

            outputValues(12, i0) = 0.25*(1.0 - x)*(1.0 - y)*(1.0 - z*z);
            outputValues(13, i0) = 0.25*(1.0 + x)*(1.0 - y)*(1.0 - z*z);
            outputValues(14, i0) = 0.25*(1.0 + x)*(1.0 + y)*(1.0 - z*z);
            outputValues(15, i0) = 0.25*(1.0 - x)*(1.0 + y)*(1.0 - z*z);

            outputValues(16, i0) = 0.25*(1.0 - x*x)*(1.0 - y)*(1.0 + z);
            outputValues(17, i0) = 0.25*(1.0 + x)*(1.0 - y*y)*(1.0 + z);
            outputValues(18, i0) = 0.25*(1.0 - x*x)*(1.0 + y)*(1.0 + z);
            outputValues(19, i0) = 0.25*(1.0 - x)*(1.0 - y*y)*(1.0 + z);
        }
        break;

    case OPERATOR_GRAD:
    case OPERATOR_D1:
        for (ordinal_type i0 = 0; i0 < dim0; i0++) {
            x = inputPoints(i0,0);
            y = inputPoints(i0,1);
            z = inputPoints(i0,2);

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

            outputValues(1, i0, 0) =  0.125*(1.0-y)*(1.0-z)*( x-y-z-2.0) + 0.125*(1.0+x)*(1.0-y)*(1.0-z);
            outputValues(1, i0, 1) = -0.125*(1.0+x)*(1.0-z)*( x-y-z-2.0) - 0.125*(1.0+x)*(1.0-y)*(1.0-z);
            outputValues(1, i0, 2) = -0.125*(1.0+x)*(1.0-y)*( x-y-z-2.0) - 0.125*(1.0+x)*(1.0-y)*(1.0-z);

            outputValues(2, i0, 0) =  0.125*(1.0+y)*(1.0-z)*( x+y-z-2.0) + 0.125*(1.0+x)*(1.0+y)*(1.0-z);
            outputValues(2, i0, 1) =  0.125*(1.0+x)*(1.0-z)*( x+y-z-2.0) + 0.125*(1.0+x)*(1.0+y)*(1.0-z);
            outputValues(2, i0, 2) = -0.125*(1.0+x)*(1.0+y)*( x+y-z-2.0) - 0.125*(1.0+x)*(1.0+y)*(1.0-z);

            outputValues(3, i0, 0) = -0.125*(1.0+y)*(1.0-z)*(-x+y-z-2.0) - 0.125*(1.0-x)*(1.0+y)*(1.0-z);
            outputValues(3, i0, 1) =  0.125*(1.0-x)*(1.0-z)*(-x+y-z-2.0) + 0.125*(1.0-x)*(1.0+y)*(1.0-z);
            outputValues(3, i0, 2) = -0.125*(1.0-x)*(1.0+y)*(-x+y-z-2.0) - 0.125*(1.0-x)*(1.0+y)*(1.0-z);

            outputValues(4, i0, 0) = -0.125*(1.0-y)*(1.0+z)*(-x-y+z-2.0) - 0.125*(1.0-x)*(1.0-y)*(1.0+z);
            outputValues(4, i0, 1) = -0.125*(1.0-x)*(1.0+z)*(-x-y+z-2.0) - 0.125*(1.0-x)*(1.0-y)*(1.0+z);
            outputValues(4, i0, 2) =  0.125*(1.0-x)*(1.0-y)*(-x-y+z-2.0) + 0.125*(1.0-x)*(1.0-y)*(1.0+z);

            outputValues(5, i0, 0) =  0.125*(1.0-y)*(1.0+z)*( x-y+z-2.0) + 0.125*(1.0+x)*(1.0-y)*(1.0+z);
            outputValues(5, i0, 1) = -0.125*(1.0+x)*(1.0+z)*( x-y+z-2.0) - 0.125*(1.0+x)*(1.0-y)*(1.0+z);
            outputValues(5, i0, 2) =  0.125*(1.0+x)*(1.0-y)*( x-y+z-2.0) + 0.125*(1.0+x)*(1.0-y)*(1.0+z);

            outputValues(6, i0, 0) =  0.125*(1.0+y)*(1.0+z)*( x+y+z-2.0) + 0.125*(1.0+x)*(1.0+y)*(1.0+z);
            outputValues(6, i0, 1) =  0.125*(1.0+x)*(1.0+z)*( x+y+z-2.0) + 0.125*(1.0+x)*(1.0+y)*(1.0+z);
            outputValues(6, i0, 2) =  0.125*(1.0+x)*(1.0+y)*( x+y+z-2.0) + 0.125*(1.0+x)*(1.0+y)*(1.0+z);

            outputValues(7, i0, 0) = -0.125*(1.0+y)*(1.0+z)*(-x+y+z-2.0) - 0.125*(1.0-x)*(1.0+y)*(1.0+z);
            outputValues(7, i0, 1) =  0.125*(1.0-x)*(1.0+z)*(-x+y+z-2.0) + 0.125*(1.0-x)*(1.0+y)*(1.0+z);
            outputValues(7, i0, 2) =  0.125*(1.0-x)*(1.0+y)*(-x+y+z-2.0) + 0.125*(1.0-x)*(1.0+y)*(1.0+z);

            outputValues(8, i0, 0) = -0.5*x*(1.0-y)*(1.0-z);
            outputValues(8, i0, 1) = -0.25*(1.0-x*x)*(1.0-z);
            outputValues(8, i0, 2) = -0.25*(1.0-x*x)*(1.0-y);

            outputValues(9, i0, 0) =  0.25*(1.0-y*y)*(1.0-z);
            outputValues(9, i0, 1) = -0.5*y*(1.0+x)*(1.0-z);
            outputValues(9, i0, 2) = -0.25*(1.0+x)*(1.0-y*y);

            outputValues(10, i0, 0) = -0.5*x*(1.0+y)*(1.0-z);
            outputValues(10, i0, 1) =  0.25*(1.0-x*x)*(1.0-z);
            outputValues(10, i0, 2) = -0.25*(1.0-x*x)*(1.0+y);

            outputValues(11, i0, 0) = -0.25*(1.0-y*y)*(1.0-z);
            outputValues(11, i0, 1) = -0.5*y*(1.0-x)*(1.0-z);
            outputValues(11, i0, 2) = -0.25*(1.0-x)*(1.0-y*y);

            outputValues(12, i0, 0) = -0.25*(1.0-y)*(1.0-z*z);
            outputValues(12, i0, 1) = -0.25*(1.0-x)*(1.0-z*z);
            outputValues(12, i0, 2) = -0.5*z*(1.0-x)*(1.0-y);

            outputValues(13, i0, 0) =  0.25*(1.0-y)*(1.0-z*z);
            outputValues(13, i0, 1) = -0.25*(1.0+x)*(1.0-z*z);
            outputValues(13, i0, 2) = -0.5*z*(1.0+x)*(1.0-y);

            outputValues(14, i0, 0) =  0.25*(1.0+y)*(1.0-z*z);
            outputValues(14, i0, 1) =  0.25*(1.0+x)*(1.0-z*z);
            outputValues(14, i0, 2) = -0.5*z*(1.0+x)*(1.0+y);

            outputValues(15, i0, 0) = -0.25*(1.0+y)*(1.0-z*z);
            outputValues(15, i0, 1) =  0.25*(1.0-x)*(1.0-z*z);
            outputValues(15, i0, 2) = -0.5*z*(1.0-x)*(1.0+y);

            outputValues(16, i0, 0) = -0.5*x*(1.0-y)*(1.0+z);
            outputValues(16, i0, 1) = -0.25*(1.0-x*x)*(1.0+z);
            outputValues(16, i0, 2) =  0.25*(1.0-x*x)*(1.0-y);

            outputValues(17, i0, 0) =  0.25*(1.0-y*y)*(1.0+z);
            outputValues(17, i0, 1) = -0.5*y*(1.0+x)*(1.0+z);
            outputValues(17, i0, 2) =  0.25*(1.0+x)*(1.0-y*y);

            outputValues(18, i0, 0) = -0.5*x*(1.0+y)*(1.0+z);
            outputValues(18, i0, 1) =  0.25*(1.0-x*x)*(1.0+z);
            outputValues(18, i0, 2) =  0.25*(1.0-x*x)*(1.0+y);

            outputValues(19, i0, 0) = -0.25*(1.0-y*y)*(1.0+z);
            outputValues(19, i0, 1) = -0.5*y*(1.0-x)*(1.0+z);
            outputValues(19, i0, 2) =  0.25*(1.0-x)*(1.0-y*y);

        }
        break;

    case OPERATOR_CURL:
        TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_CURL), std::invalid_argument,
                                    ">>> ERROR (Basis_HGRAD_HEX_I2_FEM): CURL is invalid operator for rank-0 (scalar) functions in 3D");
        break;

    case OPERATOR_DIV:
        TEUCHOS_TEST_FOR_EXCEPTION( (operatorType == OPERATOR_DIV), std::invalid_argument,
                                    ">>> ERROR (Basis_HGRAD_HEX_I2_FEM): DIV is invalid operator for rank-0 (scalar) functions in 3D");
        break;

    case OPERATOR_D2:
        for (ordinal_type i0 = 0; i0 < dim0; i0++) {
            x = inputPoints(i0,0);
            y = inputPoints(i0,1);
            z = inputPoints(i0,2);

            // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, D2Cardinality = 6)
            outputValues(0, i0, 0) =  0.25*(1.0 - y)*(1.0 - z);
            outputValues(0, i0, 1) =  0.125*(1.0 - z)*(-2.0*x - 2.0*y - z);
            outputValues(0, i0, 2) =  0.125*(1.0 - y)*(-2.0*x - y - 2.0*z);
            outputValues(0, i0, 3) =  0.25*(1.0 - x)*(1.0 - z);
            outputValues(0, i0, 4) =  0.125*(1.0 - x)*(-x - 2.0*y - 2.0*z);
            outputValues(0, i0, 5) =  0.25*(1.0 - x)*(1.0 - y);

            outputValues(1, i0, 0) =  0.25*(1.0 - y)*(1.0 - z);
            outputValues(1, i0, 1) = -0.125*(1.0 - z)*(2.0*x - 2.0*y - z);
            outputValues(1, i0, 2) = -0.125*(1.0 - y)*(2.0*x - y - 2.0*z);
            outputValues(1, i0, 3) =  0.25*(1.0 + x)*(1.0 - z);
            outputValues(1, i0, 4) =  0.125*(1.0 + x)*(x - 2.0*y - 2.0*z);
            outputValues(1, i0, 5) =  0.25*(1.0 + x)*(1.0 - y);

            outputValues(2, i0, 0) =  0.25*(1.0 + y)*(1.0 - z);
            outputValues(2, i0, 1) =  0.125*(1.0 - z)*(2.0*x + 2.0*y - z);
            outputValues(2, i0, 2) = -0.125*(1.0 + y)*(2.0*x + y - 2.0*z);
            outputValues(2, i0, 3) =  0.25*(1.0 + x)*(1.0 - z);
            outputValues(2, i0, 4) = -0.125*(1.0 + x)*(x + 2.0*y - 2.0*z);
            outputValues(2, i0, 5) =  0.25*(1.0 + x)*(1.0 + y);

            outputValues(3, i0, 0) =  0.25*(1.0 + y)*(1.0 - z);
            outputValues(3, i0, 1) = -0.125*(1.0 - z)*(-2.0*x + 2.0*y - z);
            outputValues(3, i0, 2) =  0.125*(1.0 + y)*(-2.0*x + y - 2.0*z);
            outputValues(3, i0, 3) =  0.25*(1.0 - x)*(1.0 - z);
            outputValues(3, i0, 4) = -0.125*(1.0 - x)*(-x + 2.0*y - 2.0*z);
            outputValues(3, i0, 5) =  0.25*(1.0 - x)*(1.0 + y);

            outputValues(4, i0, 0) =  0.25*(1.0 - y)*(1.0 + z);
            outputValues(4, i0, 1) =  0.125*(1.0 + z)*(-2.0*x - 2.0*y + z);
            outputValues(4, i0, 2) = -0.125*(1.0 - y)*(-2.0*x - y + 2.0*z);
            outputValues(4, i0, 3) =  0.25*(1.0 - x)*(1.0 + z);
            outputValues(4, i0, 4) = -0.125*(1.0 - x)*(-x - 2.0*y + 2.0*z);
            outputValues(4, i0, 5) =  0.25*(1.0 - x)*(1.0 - y);

            outputValues(5, i0, 0) =  0.25*(1.0 - y)*(1.0 + z);
            outputValues(5, i0, 1) = -0.125*(1.0 + z)*(2.0*x - 2.0*y + z);
            outputValues(5, i0, 2) =  0.125*(1.0 - y)*(2.0*x - y + 2.0*z);
            outputValues(5, i0, 3) =  0.25*(1.0 + x)*(1.0 + z);
            outputValues(5, i0, 4) = -0.125*(1.0 + x)*(x - 2.0*y + 2.0*z);
            outputValues(5, i0, 5) =  0.25*(1.0 + x)*(1.0 - y);

            outputValues(6, i0, 0) =  0.25*(1.0 + y)*(1.0 + z);
            outputValues(6, i0, 1) =  0.125*(1.0 + z)*(2.0*x + 2.0*y + z);
            outputValues(6, i0, 2) =  0.125*(1.0 + y)*(2.0*x + y + 2.0*z);
            outputValues(6, i0, 3) =  0.25*(1.0 + x)*(1.0 + z);
            outputValues(6, i0, 4) =  0.125*(1.0 + x)*(x + 2.0*y + 2.0*z);
            outputValues(6, i0, 5) =  0.25*(1.0 + x)*(1.0 + y);

            outputValues(7, i0, 0) =  0.25*(1.0 + y)*(1.0 + z);
            outputValues(7, i0, 1) = -0.125*(1.0 + z)*(-2.0*x + 2.0*y + z);
            outputValues(7, i0, 2) = -0.125*(1.0 + y)*(-2.0*x + y + 2.0*z);
            outputValues(7, i0, 3) =  0.25*(1.0 - x)*(1.0 + z);
            outputValues(7, i0, 4) =  0.125*(1.0 - x)*(-x + 2.0*y + 2.0*z);
            outputValues(7, i0, 5) =  0.25*(1.0 - x)*(1.0 + y);

            outputValues(8, i0, 0) = -0.5*(1.0 - y)*(1.0 - z);
            outputValues(8, i0, 1) =  0.5*x*(1.0 - z);
            outputValues(8, i0, 2) =  0.5*x*(1.0 - y);
            outputValues(8, i0, 3) =  0.0;
            outputValues(8, i0, 4) =  0.25*(1.0 - x*x);
            outputValues(8, i0, 5) =  0.0;

            outputValues(9, i0, 0) =  0.0;
            outputValues(9, i0, 1) = -0.5*y*(1.0 - z);
            outputValues(9, i0, 2) = -0.25*(1.0 - y*y);
            outputValues(9, i0, 3) = -0.5*(1.0 + x)*(1.0 - z);
            outputValues(9, i0, 4) =  0.5*y*(1.0 + x);
            outputValues(9, i0, 5) =  0.0;

            outputValues(10, i0, 0) = -0.5*(1.0 + y)*(1.0 - z);
            outputValues(10, i0, 1) = -0.5*x*(1.0 - z);
            outputValues(10, i0, 2) =  0.5*x*(1.0 + y);
            outputValues(10, i0, 3) =  0.0;
            outputValues(10, i0, 4) = -0.25*(1.0 - x*x);
            outputValues(10, i0, 5) =  0.0;

            outputValues(11, i0, 0) =  0.0;
            outputValues(11, i0, 1) =  0.5*y*(1.0 - z);
            outputValues(11, i0, 2) =  0.25*(1.0 - y*y);
            outputValues(11, i0, 3) = -0.5*(1.0 - x)*(1.0 - z);
            outputValues(11, i0, 4) =  0.5*y*(1.0 - x);
            outputValues(11, i0, 5) =  0.0;

            outputValues(12, i0, 0) =  0.0;
            outputValues(12, i0, 1) =  0.25*(1.0 - z*z);
            outputValues(12, i0, 2) =  0.5*z*(1.0 - y);
            outputValues(12, i0, 3) =  0.0;
            outputValues(12, i0, 4) =  0.5*z*(1.0 - x);
            outputValues(12, i0, 5) = -0.5*(1.0 - x)*(1.0 - y);

            outputValues(13, i0, 0) =  0.0;
            outputValues(13, i0, 1) = -0.25*(1.0 - z*z);
            outputValues(13, i0, 2) = -0.5*z*(1.0 - y);
            outputValues(13, i0, 3) =  0.0;
            outputValues(13, i0, 4) =  0.5*z*(1.0 + x);
            outputValues(13, i0, 5) = -0.5*(1.0 + x)*(1.0 - y);

            outputValues(14, i0, 0) =  0.0;
            outputValues(14, i0, 1) =  0.25*(1.0 - z*z);
            outputValues(14, i0, 2) = -0.5*z*(1.0 + y);
            outputValues(14, i0, 3) =  0.0;
            outputValues(14, i0, 4) = -0.5*z*(1.0 + x);
            outputValues(14, i0, 5) = -0.5*(1.0 + x)*(1.0 + y);

            outputValues(15, i0, 0) =  0.0;
            outputValues(15, i0, 1) = -0.25*(1.0 - z*z);
            outputValues(15, i0, 2) =  0.5*z*(1.0 + y);
            outputValues(15, i0, 3) =  0.0;
            outputValues(15, i0, 4) = -0.5*z*(1.0 - x);
            outputValues(14, i0, 5) = -0.5*(1.0 - x)*(1.0 + y);

            outputValues(16, i0, 0) = -0.5*(1.0 - y)*(1.0 + z);
            outputValues(16, i0, 1) =  0.5*x*(1.0 + z);
            outputValues(16, i0, 2) = -0.5*x*(1.0 - y);
            outputValues(16, i0, 3) =  0.0;
            outputValues(16, i0, 4) = -0.25*(1.0 - x*x);
            outputValues(16, i0, 5) =  0.0;

            outputValues(17, i0, 0) =  0.0;
            outputValues(17, i0, 1) = -0.5*y*(1.0 + z);
            outputValues(17, i0, 2) =  0.25*(1.0 - y*y);
            outputValues(17, i0, 3) = -0.5*(1.0 + x)*(1.0 + z);
            outputValues(17, i0, 4) = -0.5*y*(1.0 + x);
            outputValues(17, i0, 5) =  0.0;

            outputValues(18, i0, 0) = -0.5*(1.0 + y)*(1.0 + z);
            outputValues(18, i0, 1) = -0.5*x*(1.0 + z);
            outputValues(18, i0, 2) = -0.5*x*(1.0 + y);
            outputValues(18, i0, 3) =  0.0;
            outputValues(18, i0, 4) =  0.25*(1.0 - x*x);
            outputValues(18, i0, 5) =  0.0;

            outputValues(19, i0, 0) =  0.0;
            outputValues(19, i0, 1) =  0.5*y*(1.0 + z);
            outputValues(19, i0, 2) = -0.25*(1.0 - y*y);
            outputValues(19, i0, 3) = -0.5*(1.0 - x)*(1.0 + z);
            outputValues(19, i0, 4) = -0.5*y*(1.0 - x);
            outputValues(19, i0, 5) =  0.0;

        }
        break;

    case OPERATOR_D3:
        for (ordinal_type i0 = 0; i0 < dim0; i0++) {
            x = inputPoints(i0,0);
            y = inputPoints(i0,1);
            z = inputPoints(i0,2);

            outputValues(0,i0, 0) =  0.0;
            outputValues(0,i0, 1) = -0.25*(1.0 - z);
            outputValues(0,i0, 2) = -0.25*(1.0 - y);
            outputValues(0,i0, 3) = -0.25*(1.0 - z);
            outputValues(0,i0, 4) = -0.125*(-2.0*x - 2.0*y - 2.0*z + 1.0);
            outputValues(0,i0, 5) = -0.25*(1.0 - y);
            outputValues(0,i0, 6) =  0.0;
            outputValues(0,i0, 7) = -0.25*(1.0 - x);
            outputValues(0,i0, 8) = -0.25*(1.0 - x);
            outputValues(0,i0, 9) =  0.0;

            outputValues(1,i0, 0) =  0.0;
            outputValues(1,i0, 1) = -0.25*(1.0 - z);
            outputValues(1,i0, 2) = -0.25*(1.0 - y);
            outputValues(1,i0, 3) =  0.25*(1.0 - z);
            outputValues(1,i0, 4) =  0.125*(2.0*x - 2.0*y - 2.0*z + 1.0);
            outputValues(1,i0, 5) =  0.25*(1.0 - y);
            outputValues(1,i0, 6) =  0.0;
            outputValues(1,i0, 7) = -0.25*(1.0 + x);
            outputValues(1,i0, 8) = -0.25*(1.0 + x);
            outputValues(1,i0, 9) =  0.0;

            outputValues(2,i0, 0) =  0.0;
            outputValues(2,i0, 1) =  0.25*(1.0 - z);
            outputValues(2,i0, 2) = -0.25*(1.0 + y);
            outputValues(2,i0, 3) =  0.25*(1.0 - z);
            outputValues(2,i0, 4) = -0.125*(2.0*x + 2.0*y - 2.0*z + 1.0);
            outputValues(2,i0, 5) =  0.25*(1.0 + y);
            outputValues(2,i0, 6) =  0.0;
            outputValues(2,i0, 7) = -0.25*(1.0 + x);
            outputValues(2,i0, 8) =  0.25*(1.0 + x);
            outputValues(2,i0, 9) =  0.0;

            outputValues(3,i0, 0) =  0.0;
            outputValues(3,i0, 1) =  0.25*(1.0 - z);
            outputValues(3,i0, 2) = -0.25*(1.0 + y);
            outputValues(3,i0, 3) = -0.25*(1.0 - z);
            outputValues(3,i0, 4) =  0.125*(-2.0*x + 2.0*y - 2.0*z + 1.0);
            outputValues(3,i0, 5) = -0.25*(1.0 + y);
            outputValues(3,i0, 6) =  0.0;
            outputValues(3,i0, 7) = -0.25*(1.0 - x);
            outputValues(3,i0, 8) =  0.25*(1.0 - x);
            outputValues(3,i0, 9) =  0.0;

            outputValues(4,i0, 0) =  0.0;
            outputValues(4,i0, 1) = -0.25*(1.0 + z);
            outputValues(4,i0, 2) =  0.25*(1.0 - y);
            outputValues(4,i0, 3) = -0.25*(1.0 + z);
            outputValues(4,i0, 4) =  0.125*(-2.0*x - 2.0*y + 2.0*z + 1.0);
            outputValues(4,i0, 5) = -0.25*(1.0 - y);
            outputValues(4,i0, 6) =  0.0;
            outputValues(4,i0, 7) =  0.25*(1.0 - x);
            outputValues(4,i0, 8) = -0.25*(1.0 - x);
            outputValues(4,i0, 9) =  0.0;

            outputValues(5,i0, 0) =  0.0;
            outputValues(5,i0, 1) = -0.25*(1.0 + z);
            outputValues(5,i0, 2) =  0.25*(1.0 - y);
            outputValues(5,i0, 3) =  0.25*(1.0 + z);
            outputValues(5,i0, 4) = -0.125*(2.0*x - 2.0*y + 2.0*z + 1.0);
            outputValues(5,i0, 5) =  0.25*(1.0 - y);
            outputValues(5,i0, 6) =  0.0;
            outputValues(5,i0, 7) =  0.25*(1.0 + x);
            outputValues(5,i0, 8) = -0.25*(1.0 + x);
            outputValues(5,i0, 9) =  0.0;

            outputValues(6,i0, 0) =  0.0;
            outputValues(6,i0, 1) =  0.25*(1.0 + z);
            outputValues(6,i0, 2) =  0.25*(1.0 + y);
            outputValues(6,i0, 3) =  0.25*(1.0 + z);
            outputValues(6,i0, 4) =  0.125*(2.0*x + 2.0*y + 2.0*z + 1.0);
            outputValues(6,i0, 5) =  0.25*(1.0 + y);
            outputValues(6,i0, 6) =  0.0;
            outputValues(6,i0, 7) =  0.25*(1.0 + x);
            outputValues(6,i0, 8) =  0.25*(1.0 + x);
            outputValues(6,i0, 9) =  0.0;

            outputValues(7,i0, 0) =  0.0;
            outputValues(7,i0, 1) =  0.25*(1.0 + z);
            outputValues(7,i0, 2) =  0.25*(1.0 + y);
            outputValues(7,i0, 3) = -0.25*(1.0 + z);
            outputValues(7,i0, 4) = -0.125*(-2.0*x + 2.0*y + 2.0*z + 1.0);
            outputValues(7,i0, 5) = -0.25*(1.0 + y);
            outputValues(7,i0, 6) =  0.0;
            outputValues(7,i0, 7) =  0.25*(1.0 - x);
            outputValues(7,i0, 8) =  0.25*(1.0 - x);
            outputValues(7,i0, 9) =  0.0;

            outputValues(8,i0, 0) =  0.0;
            outputValues(8,i0, 1) =  0.5*(1.0 - z);
            outputValues(8,i0, 2) =  0.5*(1.0 - y);
            outputValues(8,i0, 3) =  0.0;
            outputValues(8,i0, 4) = -0.5*x;
            outputValues(8,i0, 5) =  0.0;
            outputValues(8,i0, 6) =  0.0;
            outputValues(8,i0, 7) =  0.0;
            outputValues(8,i0, 8) =  0.0;
            outputValues(8,i0, 9) =  0.0;

            outputValues(9,i0, 0) =  0.0;
            outputValues(9,i0, 1) =  0.0;
            outputValues(9,i0, 2) =  0.0;
            outputValues(9,i0, 3) = -0.5*(1.0 - z);
            outputValues(9,i0, 4) =  0.5*y;
            outputValues(9,i0, 5) =  0.0;
            outputValues(9,i0, 6) =  0.0;
            outputValues(9,i0, 7) =  0.5*(1.0 + x);
            outputValues(9,i0, 8) =  0.0;
            outputValues(9,i0, 9) =  0.0;

            outputValues(10,i0, 0) =  0.0;
            outputValues(10,i0, 1) = -0.5*(1.0 - z);
            outputValues(10,i0, 2) =  0.5*(1.0 + y);
            outputValues(10,i0, 3) =  0.0;
            outputValues(10,i0, 4) =  0.5*x;
            outputValues(10,i0, 5) =  0.0;
            outputValues(10,i0, 6) =  0.0;
            outputValues(10,i0, 7) =  0.0;
            outputValues(10,i0, 8) =  0.0;
            outputValues(10,i0, 9) =  0.0;

            outputValues(11,i0, 0) =  0.0;
            outputValues(11,i0, 1) =  0.0;
            outputValues(11,i0, 2) =  0.0;
            outputValues(11,i0, 3) =  0.5*(1.0 - z);
            outputValues(11,i0, 4) = -0.5*y;
            outputValues(11,i0, 5) =  0.0;
            outputValues(11,i0, 6) =  0.0;
            outputValues(11,i0, 7) =  0.5*(1.0 - x);
            outputValues(11,i0, 8) =  0.0;
            outputValues(11,i0, 9) =  0.0;

            outputValues(12,i0, 0) =  0.0;
            outputValues(12,i0, 1) =  0.0;
            outputValues(12,i0, 2) =  0.0;
            outputValues(12,i0, 3) =  0.0;
            outputValues(12,i0, 4) = -0.5*z;
            outputValues(12,i0, 5) =  0.5*(1.0 - y);
            outputValues(12,i0, 6) =  0.0;
            outputValues(12,i0, 7) =  0.0;
            outputValues(12,i0, 8) =  0.5*(1.0 - x);
            outputValues(12,i0, 9) =  0.0;

            outputValues(13,i0, 0) =  0.0;
            outputValues(13,i0, 1) =  0.0;
            outputValues(13,i0, 2) =  0.0;
            outputValues(13,i0, 3) =  0.0;
            outputValues(13,i0, 4) =  0.5*z;
            outputValues(13,i0, 5) = -0.5*(1.0 - y);
            outputValues(13,i0, 6) =  0.0;
            outputValues(13,i0, 7) =  0.0;
            outputValues(13,i0, 8) =  0.5*(1.0 + x);
            outputValues(13,i0, 9) =  0.0;

            outputValues(14,i0, 0) =  0.0;
            outputValues(14,i0, 1) =  0.0;
            outputValues(14,i0, 2) =  0.0;
            outputValues(14,i0, 3) =  0.0;
            outputValues(14,i0, 4) = -0.5*z;
            outputValues(14,i0, 5) = -0.5*(1.0 + y);
            outputValues(14,i0, 6) =  0.0;
            outputValues(14,i0, 7) =  0.0;
            outputValues(14,i0, 8) = -0.5*(1.0 + x);
            outputValues(14,i0, 9) =  0.0;

            outputValues(15,i0, 0) =  0.0;
            outputValues(15,i0, 1) =  0.0;
            outputValues(15,i0, 2) =  0.0;
            outputValues(15,i0, 3) =  0.0;
            outputValues(15,i0, 4) =  0.5*z;
            outputValues(15,i0, 5) =  0.5*(1.0 + y);
            outputValues(15,i0, 6) =  0.0;
            outputValues(15,i0, 7) =  0.0;
            outputValues(15,i0, 8) = -0.5*(1.0 - x);
            outputValues(15,i0, 9) =  0.0;

            outputValues(16,i0, 0) =  0.0;
            outputValues(16,i0, 1) =  0.5*(1.0 + z);
            outputValues(16,i0, 2) = -0.5*(1.0 - y);
            outputValues(16,i0, 3) =  0.0;
            outputValues(16,i0, 4) =  0.5*x;
            outputValues(16,i0, 5) =  0.0;
            outputValues(16,i0, 6) =  0.0;
            outputValues(16,i0, 7) =  0.0;
            outputValues(16,i0, 8) =  0.0;
            outputValues(16,i0, 9) =  0.0;

            outputValues(17,i0, 0) =  0.0;
            outputValues(17,i0, 1) =  0.0;
            outputValues(17,i0, 2) =  0.0;
            outputValues(17,i0, 3) = -0.5*(1.0 + z);
            outputValues(17,i0, 4) = -0.5*y;
            outputValues(17,i0, 5) =  0.0;
            outputValues(17,i0, 6) =  0.0;
            outputValues(17,i0, 7) = -0.5*(1.0 + x);
            outputValues(17,i0, 8) =  0.0;
            outputValues(17,i0, 9) =  0.0;

            outputValues(18,i0, 0) =  0.0;
            outputValues(18,i0, 1) = -0.5*(1.0 + z);
            outputValues(18,i0, 2) = -0.5*(1.0 + y);
            outputValues(18,i0, 3) =  0.0;
            outputValues(18,i0, 4) = -0.5*x;
            outputValues(18,i0, 5) =  0.0;
            outputValues(18,i0, 6) =  0.0;
            outputValues(18,i0, 7) =  0.0;
            outputValues(18,i0, 8) =  0.0;
            outputValues(18,i0, 9) =  0.0;

            outputValues(19,i0, 0) =  0.0;
            outputValues(19,i0, 1) =  0.0;
            outputValues(19,i0, 2) =  0.0;
            outputValues(19,i0, 3) =  0.5*(1.0 + z);
            outputValues(19,i0, 4) =  0.5*y;
            outputValues(19,i0, 5) =  0.0;
            outputValues(19,i0, 6) =  0.0;
            outputValues(19,i0, 7) = -0.5*(1.0 - x);
            outputValues(19,i0, 8) =  0.0;
            outputValues(19,i0, 9) =  0.0;

        }
        break;

    case OPERATOR_D4:
    {
        // Intitialize array by zero and then fill only non-zero entries.
        ordinal_type DkCardinality = Intrepid2::getDkCardinality(operatorType, this -> basisCellTopology_.getDimension() );
        for(ordinal_type dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
            for (ordinal_type i0 = 0; i0 < dim0; i0++) {
                for(ordinal_type dkOrd = 0; dkOrd < DkCardinality; dkOrd++) {
                    outputValues(dofOrd, i0, dkOrd) = 0.0;
                }
            }
        }

        for (ordinal_type i0 = 0; i0 < dim0; i0++) {
            x = inputPoints(i0,0);
            y = inputPoints(i0,1);
            z = inputPoints(i0,2);

            outputValues( 0, i0, 4) =  0.25;
            outputValues( 0, i0, 7) =  0.25;
            outputValues( 0, i0, 8) =  0.25;

            outputValues( 1, i0, 4) =  0.25;
            outputValues( 1, i0, 7) = -0.25;
            outputValues( 1, i0, 8) = -0.25;

            outputValues( 2, i0, 4) = -0.25;
            outputValues( 2, i0, 7) = -0.25;
            outputValues( 2, i0, 8) =  0.25;

            outputValues( 3, i0, 4) = -0.25;
            outputValues( 3, i0, 7) =  0.25;
            outputValues( 3, i0, 8) = -0.25;

            outputValues( 4, i0, 4) = -0.25;
            outputValues( 4, i0, 7) = -0.25;
            outputValues( 4, i0, 8) =  0.25;

            outputValues( 5, i0, 4) = -0.25;
            outputValues( 5, i0, 7) =  0.25;
            outputValues( 5, i0, 8) = -0.25;

            outputValues( 6, i0, 4) =  0.25;
            outputValues( 6, i0, 7) =  0.25;
            outputValues( 6, i0, 8) =  0.25;

            outputValues( 7, i0, 4) =  0.25;
            outputValues( 7, i0, 7) = -0.25;
            outputValues( 7, i0, 8) = -0.25;

            outputValues( 8, i0, 4) = -0.5;
            outputValues( 9, i0, 7) =  0.5;
            outputValues(10, i0, 4) =  0.5;
            outputValues(11, i0, 7) = -0.5;
            outputValues(12, i0, 8) = -0.5;
            outputValues(13, i0, 8) =  0.5;
            outputValues(14, i0, 8) = -0.5;
            outputValues(15, i0, 8) =  0.5;
            outputValues(16, i0, 4) =  0.5;
            outputValues(17, i0, 7) = -0.5;
            outputValues(18, i0, 4) = -0.5;
            outputValues(19, i0, 7) =  0.5;
        }
    }
    break;

    case OPERATOR_D5:
    case OPERATOR_D6:
    case OPERATOR_D7:
    case OPERATOR_D8:
    case OPERATOR_D9:
    case OPERATOR_D10:
    {
        // outputValues is a rank-3 array with dimensions (basisCardinality_, dim0, DkCardinality)
        ordinal_type DkCardinality = Intrepid2::getDkCardinality(operatorType,
                                     this -> basisCellTopology_.getDimension() );
        for(ordinal_type dofOrd = 0; dofOrd < this -> basisCardinality_; dofOrd++) {
            for (ordinal_type i0 = 0; i0 < dim0; i0++) {
                for(ordinal_type dkOrd = 0; dkOrd < DkCardinality; dkOrd++) {
                    outputValues(dofOrd, i0, dkOrd) = 0.0;
                }
            }
        }
    }
    break;

    default:
        TEUCHOS_TEST_FOR_EXCEPTION( !( Intrepid2::isValidOperator(operatorType) ), std::invalid_argument,
                                    ">>> ERROR (Basis_HGRAD_HEX_I2_FEM): Invalid operator type");
    }
}