void XZHydrostaticResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  std::vector<ScalarT> vel(numLevels);
  for (int level=0; level < numLevels; ++level) {
    vel[level] = (level+1)*Re;
  }

  for (int i=0; i < Residual.size(); ++i) Residual(i)=0.0;

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

      for (int node=0; node < numNodes; ++node) {
        for (int level=0; level < numLevels; ++level) {
          // Transient Term
          Residual(cell,node,level) += rhoDot(cell,qp,level)*wBF(cell,node,qp);
          // Advection Term
          for (int j=0; j < numDims; ++j) {
              Residual(cell,node,level) += vel[level]*rhoGrad(cell,qp,level,j)*wBF(cell,node,qp);
          }
        }
      }
    }
  }
}
void XZScalarAdvectionResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  // Constants 
  L = 2.5e6 // Latent Heat J/kg
  cp = 1004.64 // Specfic Heat J/kg/K
  
  std::vector<ScalarT> vel(2);
  for (std::size_t i=0; i < Residual.size(); ++i) Residual(i)=0.0;

  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
  
      if (coordVec(cell,qp,1) > 5.0) vel[0] = Re;
      else                           vel[0] = 0.0;
      vel[1] = 0.0;

      for (std::size_t node=0; node < numNodes; ++node) {
          // Transient Term
          // Residual(cell,node) += rhoDot(cell,qp)*wBF(cell,node,qp);
          Residual(cell,node,0) += rhoDot(cell,qp)*wBF(cell,node,qp);
          Residual(cell,node,1) += tempDot(cell,qp)*wBF(cell,node,qp);
          Residual(cell,node,2) += qvDot(cell,qp)*wBF(cell,node,qp);
          Residual(cell,node,3) += qcDot(cell,qp)*wBF(cell,node,qp);

          // Compute saturation mixing ratio for condensation rate with Teton's formula
          // Saturation vapor pressure, temp in Celcius, equation valid over [-35,35] with a 3% error
          qvs = 3.8 / rhoDot(cell,qp) * exp(17.27 * (tempGrad(cell,qp) - 273.)/(tempGrad(cell,qp) - 36.));

          C = max( (qvDot(cell,qp) - qvs)/( 1. + qvs*((4093.*L)/(cp*tempDot(cell,qp)-36.)^2.) ) , -qcDot(cell,qp) );

 
          Tv = T * (1 + 0.6*qv);

          // Advection Term
          for (std::size_t j=0; j < numDims; ++j) {
            Residual(cell,node,0) += vel[j]*rhoGrad(cell,qp,j)*wBF(cell,node,qp);
            Residual(cell,node,1) += vel[j]*tempGrad(cell,qp,j)*wBF(cell,node,qp)+L/cp*C;
            Residual(cell,node,2) += vel[j]*qvGrad(cell,qp,j)*wBF(cell,node,qp)-C;
            Residual(cell,node,3) += vel[j]*qcGrad(cell,qp,j)*wBF(cell,node,qp)+C;
          }
      }
    }
  }
}
void XZScalarAdvectionResid<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  std::vector<ScalarT> vel(2);
  for (std::size_t i=0; i < Residual.size(); ++i) Residual(i)=0.0;

  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
  
      if (coordVec(cell,qp,1) > 0.5) vel[0] = Re;
      else                           vel[0] = 0.0;
      vel[1] = 0.0;

      for (std::size_t node=0; node < numNodes; ++node) {
          // Transient Term
          Residual(cell,node) += rhoDot(cell,qp)*wBF(cell,node,qp);
          // Advection Term
          for (std::size_t j=0; j < numDims; ++j) {
            Residual(cell,node) += vel[j]*rhoGrad(cell,qp,j)*wBF(cell,node,qp);
          }
      }
    }
  }
}