KOKKOS_INLINE_FUNCTION
void Hydrostatic_Velocity<EvalT, Traits>::
operator() (const Hydrostatic_Velocity_Tag& tag, const int& cell) const{
  for (int node=0; node < numNodes; ++node) 
    for (int level=0; level < numLevels; ++level) 
      for (int dim=0; dim < numDims; ++dim)  
        Velocity(cell,node,level,dim) = Velx(cell,node,level,dim); 
}
void XZHydrostatic_UTracer<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  for (int cell=0; cell < workset.numCells; ++cell) 
    for (int node=0; node < numNodes; ++node) 
      for (int level=0; level < numLevels; ++level) 
        for (int dim=0; dim < numDims; ++dim) {
          UTracer(cell,node,level,dim) = Velx(cell,node,level,dim)*Tracer(cell,node,level);
          //UTracer(cell,node,level,dim) = PiVelx(cell,node,level,dim)*Tracer(cell,node,level);
            //std::cout << "pivelx: " << cell << " " << node << " " << level << " " << dim << " " << PiVelx(cell,node,level,dim) << std::endl;
            //std::cout << "Tracer " << Tracer(cell,node,level) << std::endl;
          }

}
void XZHydrostatic_Omega<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  for (int cell=0; cell < workset.numCells; ++cell) {
    for (int qp=0; qp < numQPs; ++qp) {
      for (int level=0; level < numLevels; ++level) {

        ScalarT sum = Velx(cell,qp,level)*gradp(cell,qp,level) + 0.5*gradpivelx(cell,qp,level)*DeltaEta(cell,qp,level)
;
        for (int j=0; j<level-1; ++j) {
          sum -= gradpivelx(cell,qp,level) * DeltaEta(cell,qp,level);
        }  
        omega(cell,qp,level) = (density(cell,qp,level)/Cp)*sum;
       
      }
    }
  }
}
void Hydrostatic_Velocity<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  time = workset.current_time; 

#ifndef ALBANY_KOKKOS_UNDER_DEVELOPMENT
  //*out << "Aeras::Hydrostatic_Velocity time = " << time << std::endl; 
  switch (adv_type) {
    case UNKNOWN: //velocity is an unknown that we solve for (not prescribed)
    {
      for (int cell=0; cell < workset.numCells; ++cell) 
        for (int node=0; node < numNodes; ++node) 
          for (int level=0; level < numLevels; ++level) 
            for (int dim=0; dim < numDims; ++dim)  
              Velocity(cell,node,level,dim) = Velx(cell,node,level,dim); 
    } 
    break; 

    case PRESCRIBED_1_1: //velocity is prescribed to that of 1-1 test
    {
      for (int cell=0; cell < workset.numCells; ++cell) { 
        for (int node=0; node < numNodes; ++node) {

          const MeshScalarT lambda = sphere_coord(cell, node, 0);
          const MeshScalarT theta = sphere_coord(cell, node, 1);
          ScalarT lambdap = lambda - 2.0*PI*time/tau;

          for (int level=0; level < numLevels; ++level) {

              ScalarT Ua = k*sin(lambdap)*sin(lambdap)*sin(2.0*theta)*cos(PI*time/tau)
                         + (2.0*PI*earthRadius/tau)*cos(theta);
    
              ScalarT Va = k*sin(2.0*lambdap)*cos(theta)*cos(PI*time/tau);

              ScalarT B = E.B(level);
              ScalarT p = pressure(cell,node,level);

              ScalarT taper = - exp( (p    - p0)/(B*ptop) )
                              + exp( (ptop - p )/(B*ptop) );

              ScalarT Ud = (omega0*earthRadius)/(B*ptop)
                           *cos(lambdap)*cos(theta)*cos(theta)*cos(2.0*PI*time/tau)*taper;

              Velocity(cell,node,level,0) = Ua + Ud; 
              Velocity(cell,node,level,1) = Va; 
          }
        }
      }
    }
    break; 

    case PRESCRIBED_1_2: //velocity is prescribed to that of 1-2 test
    {
      //FIXME: Pete, Tom - please fill in
      for (int cell=0; cell < workset.numCells; ++cell) { 
        for (int node=0; node < numNodes; ++node) {
          const MeshScalarT lambda = sphere_coord(cell, node, 0);
          const MeshScalarT theta = sphere_coord(cell, node, 1);
          for (int level=0; level < numLevels; ++level) {
            for (int dim=0; dim < numDims; ++dim) {
              Velocity(cell,node,level,dim) = 0.0; //FIXME  
            }
          }
        }
      }
    }
    break; 
  }

#else
  switch (adv_type) {
    case UNKNOWN: //velocity is an unknown that we solve for (not prescribed)
    {
      Kokkos::parallel_for(Hydrostatic_Velocity_Policy(0,workset.numCells),*this);
      cudaCheckError();
      break; 
    } 

    case PRESCRIBED_1_1: //velocity is prescribed to that of 1-1 test
    {
      Kokkos::parallel_for(Hydrostatic_Velocity_PRESCRIBED_1_1_Policy(0,workset.numCells),*this);
      cudaCheckError();
      break; 
    }

    case PRESCRIBED_1_2: //velocity is prescribed to that of 1-2 test
    {
      Kokkos::parallel_for(Hydrostatic_Velocity_PRESCRIBED_1_2_Policy(0,workset.numCells),*this);
      cudaCheckError();
      break; 
    }
  }

#endif
}
void XZHydrostatic_EtaDotPi<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
	const Eta<EvalT> &E = Eta<EvalT>::self();

	//etadotpi(level) shifted by 1/2
	std::vector<ScalarT> etadotpi(numLevels+1);

	if(!pureAdvection){
		for (int cell=0; cell < workset.numCells; ++cell) {
			for (int qp=0; qp < numQPs; ++qp) {
				ScalarT pdotp0 = 0;
				for (int level=0; level < numLevels; ++level) pdotp0 -= divpivelx(cell,qp,level) * E.delta(level);
				for (int level=0; level < numLevels; ++level) {
					ScalarT integral = 0;
					for (int j=0; j<=level; ++j) integral += divpivelx(cell,qp,j) * E.delta(j);
					etadotpi[level] = -E.B(level+.5)*pdotp0 - integral;
				}
				etadotpi[0] = etadotpi[numLevels] = 0;

				//Vertical Finite Differencing
				for (int level=0; level < numLevels; ++level) {
					const ScalarT factor     = 1.0/(2.0*Pi(cell,qp,level)*E.delta(level));
					const int level_m = level             ? level-1 : 0;
					const int level_p = level+1<numLevels ? level+1 : level;
					const ScalarT etadotpi_m = etadotpi[level  ];
					const ScalarT etadotpi_p = etadotpi[level+1];

					const ScalarT dT_m       = Temperature(cell,qp,level)   - Temperature(cell,qp,level_m);
					const ScalarT dT_p       = Temperature(cell,qp,level_p) - Temperature(cell,qp,level);
					etadotdT(cell,qp,level) = factor * ( etadotpi_p*dT_p + etadotpi_m*dT_m );

					for (int dim=0; dim<numDims; ++dim) {
						const ScalarT dVx_m      = Velx(cell,qp,level,dim)   - Velx(cell,qp,level_m,dim);
						const ScalarT dVx_p      = Velx(cell,qp,level_p,dim) - Velx(cell,qp,level,dim);
						etadotdVelx(cell,qp,level,dim) = factor * ( etadotpi_p*dVx_p + etadotpi_m*dVx_m );
					}

					for (int i = 0; i < tracerNames.size(); ++i) {
						const ScalarT q_m = 0.5*( Tracer[tracerNames[i]](cell,qp,level)   / Pi(cell,qp,level)
								+ Tracer[tracerNames[i]](cell,qp,level_m) / Pi(cell,qp,level_m) );
						const ScalarT q_p = 0.5*( Tracer[tracerNames[i]](cell,qp,level_p) / Pi(cell,qp,level_p)
								+ Tracer[tracerNames[i]](cell,qp,level)   / Pi(cell,qp,level)   );
						//etadotdTracer[tracerNames[i]](cell,qp,level) = ( etadotpi_p*q_p - etadotpi_m*q_m ) / E.delta(level);
						dedotpiTracerde[tracerNames[i]](cell,qp,level) = ( etadotpi_p*q_p - etadotpi_m*q_m ) / E.delta(level);
					}

					Pidot(cell,qp,level) = - divpivelx(cell,qp,level) - (etadotpi_p - etadotpi_m)/E.delta(level);

				}
			}
		}
	}//end of (not pure Advection)
	//pure advection: there are amny auxiliary variables.
	else{
		for (int cell=0; cell < workset.numCells; ++cell) {
			for (int qp=0; qp < numQPs; ++qp) {
				//Vertical Finite Differencing
				for (int level=0; level < numLevels; ++level) {
					etadotdT(cell,qp,level) = 0.0;
					for (int dim=0; dim<numDims; ++dim)
						etadotdVelx(cell,qp,level,dim) = 0.0;
					for (int i = 0; i < tracerNames.size(); ++i)
						dedotpiTracerde[tracerNames[i]](cell,qp,level) = 0.0;
					Pidot(cell,qp,level) = - divpivelx(cell,qp,level);
				}
			}
		}
	}
}