void SurfaceScalarGradientOperator<EvalT, Traits>::
  evaluateFields(typename Traits::EvalData workset)
  {
    Intrepid2::Vector<MeshScalarT> Parent_Grad_plus(3);
    Intrepid2::Vector<MeshScalarT> Parent_Grad_minor(3);

    for (int cell=0; cell < workset.numCells; ++cell) {
      for (int pt=0; pt < numQPs; ++pt) {

        Intrepid2::Tensor<MeshScalarT> gBasis(3, refDualBasis,cell, pt,0,0);

        Intrepid2::Vector<MeshScalarT> N(3, refNormal,cell, pt,0);

        gBasis = Intrepid2::transpose(gBasis);

        // in-plane (parallel) contribution
        for (int node(0); node < numPlaneNodes; ++node) {
          int topNode = node + numPlaneNodes;

          // the parallel-to-the-plane term
          for (int i(0); i < numPlaneDims; ++i ){
            Parent_Grad_plus(i) = 0.5*refGrads(node, pt, i);
            Parent_Grad_minor(i) = 0.5*refGrads(node, pt, i);
          }

          // the orthogonal-to-the-plane term
          MeshScalarT invh = 1./ thickness;
          Parent_Grad_plus(numPlaneDims) = invh * refValues(node,pt);
          Parent_Grad_minor(numPlaneDims) = -invh * refValues(node,pt);

          // Mapping from parent to the physical domain
          Intrepid2::Vector<MeshScalarT> Transformed_Grad_plus(Intrepid2::dot(gBasis, Parent_Grad_plus));
          Intrepid2::Vector<MeshScalarT> Transformed_Grad_minor(Intrepid2::dot(gBasis,Parent_Grad_minor));

          // assign components to MDfield ScalarGrad
          for (int j(0); j < numDims; ++j ){
            surface_Grad_BF(cell, topNode, pt, j) = Transformed_Grad_plus(j);
            surface_Grad_BF(cell, node, pt, j) = Transformed_Grad_minor(j);
          }
        }
      }
    }

    for (int cell=0; cell < workset.numCells; ++cell) {
      for (int pt=0; pt < numQPs; ++pt) {
        for (int k(0); k< numDims; ++k){
          grad_val_qp(cell, pt, k) = 0;
          for (int node(0); node < numNodes; ++node) {
            grad_val_qp(cell, pt, k) += surface_Grad_BF(cell, node, pt, k)*
              val_node(cell,node);
          }
        }
      }
    }

  }
  void SurfaceTLPoroMassResidual<EvalT, Traits>::
  evaluateFields(typename Traits::EvalData workset)
  {
    typedef Intrepid::FunctionSpaceTools FST;
    typedef Intrepid::RealSpaceTools<ScalarT> RST;

    Albany::MDArray porePressureold = (*workset.stateArrayPtr)[porePressureName];
    Albany::MDArray Jold;
    if (haveMech) {
      Jold = (*workset.stateArrayPtr)[JName];
    }

    ScalarT dt = deltaTime(0);

    // THE INTREPID REALSPACE TOOLS AND FUNCTION SPACE TOOLS NEED TO BE REMOVED!!!
    // Compute pore fluid flux
    if (haveMech) {
      // Put back the permeability tensor to the reference configuration
      RST::inverse(F_inv, defGrad);
      RST::transpose(F_invT, F_inv);
       FST::scalarMultiplyDataData<ScalarT>(JF_invT, J, F_invT);
       FST::scalarMultiplyDataData<ScalarT>(KJF_invT, kcPermeability, JF_invT);
      FST::tensorMultiplyDataData<ScalarT>(Kref, F_inv, KJF_invT);
      FST::tensorMultiplyDataData<ScalarT> (flux, Kref, scalarGrad); // flux_i = k I_ij p_j
    } else {
       FST::scalarMultiplyDataData<ScalarT> (flux, kcPermeability, scalarGrad); // flux_i = kc p_i
    }

    for (int cell(0); cell < workset.numCells; ++cell) {
      for (int node(0); node < numPlaneNodes; ++node) {
        // initialize the residual
        int topNode = node + numPlaneNodes;
        poroMassResidual(cell, topNode)  = 0.0;
        poroMassResidual(cell, node)  = 0.0;
      }
    }
 
    for (int cell(0); cell < workset.numCells; ++cell) {
      for (int node(0); node < numPlaneNodes; ++node) {
        int topNode = node + numPlaneNodes;

        for (int pt=0; pt < numQPs; ++pt) {

          // If there is no diffusion, then the residual defines only on the mid-plane value

          // Local Rate of Change volumetric constraint term
          poroMassResidual(cell, node) -= refValues(node,pt)*
            (std::log(J(cell,pt)/Jold(cell, pt))*
                     biotCoefficient(cell,pt) +
                     (porePressure(cell, pt) - porePressureold(cell, pt))/
                     biotModulus(cell,pt))*refArea(cell,pt);

          poroMassResidual(cell, topNode) -= refValues(node,pt)*
            (std::log(J(cell,pt)/Jold(cell, pt))*
                     biotCoefficient(cell,pt) +
                     (porePressure(cell, pt) - porePressureold(cell, pt))/
                     biotModulus(cell,pt))*refArea(cell,pt);

        } // end integrartion point loop
      } //  end plane node loop
    } // end cell loop


    for (int cell(0); cell < workset.numCells; ++cell) {
      for (int node(0); node < numPlaneNodes; ++node) {

        int topNode = node + numPlaneNodes;

        for (int pt=0; pt < numQPs; ++pt) {
          for (int dim=0; dim <numDims; ++dim){

            poroMassResidual(cell,node) -=  flux(cell, pt, dim)*dt*
              surface_Grad_BF(cell, node, pt, dim)*
              refArea(cell,pt);

            poroMassResidual(cell, topNode) -= flux(cell, pt, dim)*dt*
              surface_Grad_BF(cell, topNode, pt, dim)*
              refArea(cell,pt);
          }
        }
      }
    }

  }