void DOFInterpolation<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  //Intrepid version:
  // for (int i=0; i < val_qp.size() ; i++) val_qp[i] = 0.0;
  // Intrepid::FunctionSpaceTools:: evaluate<ScalarT>(val_qp, val_node, BF);
  for (int cell=0; cell < workset.numCells; ++cell) {
    for (int qp=0; qp < numQPs; ++qp) {
      if (2==numRank) {
        typename PHAL::Ref<ScalarT>::type vqp = val_qp(cell,qp) = 0;
        for (int node=0; node < numNodes; ++node) {
          vqp += val_node(cell, node) * BF(cell, node, qp);
        }
      } else {
        for (int level=0; level < numLevels; ++level) {
          typename PHAL::Ref<ScalarT>::type vqp = val_qp(cell,qp,level);
          vqp = 0;
          for (int node=0; node < numNodes; ++node) {
            vqp += val_node(cell, node, level) * BF(cell, node, qp);
          }
        }
      } 
    }
  }

}
KOKKOS_INLINE_FUNCTION
void FEInterpolation<EvalT, Traits>::operator () (const int i) const
{  
  for (PHX::index_size_type qp = 0; qp < num_qp; ++qp) {
    val_qp(i,qp) = 0.0;

    for (PHX::index_size_type dim = 0; dim < num_dim; ++dim)
      val_grad_qp(i,qp,dim) = 0.0;

    // Sum nodal contributions to qp
    for (PHX::index_size_type node = 0; node < num_nodes; ++node) {
      val_qp(i,qp) += phi(qp, node) * val_node(i,node);
      for (PHX::index_size_type dim = 0; dim < num_dim; ++dim)
	val_grad_qp(i,qp,dim) += grad_phi(qp, node, dim) * val_node(i,node);
    }
  }
}
//**********************************************************************
PHX_EVALUATE_FIELDS(FEInterpolation,cell_data)
{ 

  std::vector<Element_Linear2D>::iterator cell_it = cell_data.begin;

  // Loop over number of cells
  for (std::size_t cell = 0; cell < cell_data.num_cells; ++cell) {
    
    const shards::Array<double,shards::NaturalOrder,QuadPoint,Node>& phi = 
      cell_it->basisFunctions();

    const shards::Array<double,shards::NaturalOrder,QuadPoint,Node,Dim>& 
      grad_phi = cell_it->basisFunctionGradientsRealSpace();

    // Loop over quad points of cell
    for (int qp = 0; qp < num_qp; ++qp) {
      
      val_qp(cell,qp) = 0.0;

      for (int dim = 0; dim < num_dim; ++dim)
	val_grad_qp(cell,qp,dim) = 0.0;

      // Sum nodal contributions to qp
      for (int node = 0; node < num_nodes; ++node) {

	val_qp(cell,qp) += phi(qp,node) * val_node(cell,node);
	
	for (int dim = 0; dim < num_dim; ++dim)
	  val_grad_qp(cell,qp,dim) += 
	    grad_phi(qp,node,dim) * val_node(cell,node);
	
      }
    }
    
    ++cell_it;
 
  }
    
//   std::cout << "FEINterpolation: val_node" << std::endl;
//   val_node.print(std::cout,true);
//   std::cout << "FEINterpolation: val_qp" << std::endl;
//   val_qp.print(std::cout,true);
//   std::cout << "FEINterpolation: val_grad_qp" << std::endl;
//   val_grad_qp.print(std::cout,true);

}
void DOFInterpolation<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  //Intrepid version:
  // for (int i=0; i < val_qp.size() ; i++) val_qp[i] = 0.0;
  // Intrepid::FunctionSpaceTools:: evaluate<ScalarT>(val_qp, val_node, BF);

  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
      //ScalarT& vqp = val_qp(cell,qp);
      val_qp(cell,qp) = val_node(cell, 0) * BF(cell, 0, qp);
      for (std::size_t node=1; node < numNodes; ++node) {
        val_qp(cell,qp) += val_node(cell, node) * BF(cell, node, qp);
      }
    }
  }
}
void DOFVecInterpolationLevels<EvalT, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  PHAL::set(val_qp, 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) 
          for (int dim=0; dim < numDims; ++dim) 
            val_qp(cell,qp,level,dim) += val_node(cell,node,level,dim) * BF(cell,node,qp);
}
void DOFInterpolation<PHAL::AlbanyTraits::MPJacobian, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  //Intrepid version:
  // for (int i=0; i < val_qp.size() ; i++) val_qp[i] = 0.0;
  // Intrepid::FunctionSpaceTools:: evaluate<ScalarT>(val_qp, val_node, BF);

  const int num_dof = val_node(0,0).size();
  const int neq = workset.wsElNodeEqID[0][0].size();

  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
      //ScalarT& vqp = val_qp(cell,qp);
      val_qp(cell,qp) = ScalarT(num_dof, val_node(cell, 0).val() * BF(cell, 0, qp));
      if (num_dof) (val_qp(cell,qp)).fastAccessDx(offset) = val_node(cell, 0).fastAccessDx(offset) * BF(cell, 0, qp);
      for (std::size_t node=1; node < numNodes; ++node) {
        (val_qp(cell,qp)).val() += val_node(cell, node).val() * BF(cell, node, qp);
        if (num_dof) (val_qp(cell,qp)).fastAccessDx(neq*node+offset) += val_node(cell, node).fastAccessDx(neq*node+offset) * BF(cell, node, qp);
      }
    }
  }
}
void DOFTensorInterpolationBase<EvalT, Traits, ScalarT>::
evaluateFields(typename Traits::EvalData workset)
{
  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < numQPs; ++qp) {
      for (std::size_t i=0; i<vecDim; i++) {
        for (std::size_t j=0; j<vecDim; j++) {
          // Zero out for node==0; then += for node = 1 to numNodes
          typename PHAL::Ref<ScalarT>::type vqp = val_qp(cell,qp,i,j);
          vqp = val_node(cell, 0, i, j) * BF(cell, 0, qp);
          for (std::size_t node=1; node < numNodes; ++node) {
            vqp += val_node(cell, node, i, j) * BF(cell, node, qp);
          }
        }
      }
    }
  }
}
void ATO::ModalObjective<PHAL::AlbanyTraits::Residual, Traits>::
evaluateFields(typename Traits::EvalData workset)
{

  Albany::MDArray F    = (*workset.stateArrayPtr)[FName];
  Albany::MDArray dEdp = (*workset.stateArrayPtr)[dFdpName];
  Albany::MDArray topo = (*workset.stateArrayPtr)[topology->getName()];
  std::vector<int> dims;
  gradX.dimensions(dims);
  int size = dims.size();

  int numCells = dims[0];
  int numQPs = dims[1];
  int numDims = dims[2];
  int numNodes = topo.dimension(1);

  if( size == 4 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double dmass_term = 0.;
      double dstiffness_term = 0.;
      for(int qp=0; qp<numQPs; qp++){
        double topoVal = 0.0;
        for(int node=0; node<numNodes; node++)
          topoVal += topo(cell,node)*BF(cell,node,qp);
        double P = topology->Penalize(functionIndex,topoVal);
        double dP = topology->dPenalize(functionIndex,topoVal);
        double dE = 0.0;
        double dmass_term = 0.;
        double dstiffness_term = 0.;
        for(int i=0; i<numDims; i++) {
          dmass_term += val_qp(cell,qp,i)*val_qp(cell,qp,i) * qp_weights(cell,qp);
          for(int j=0; j<numDims; j++)
            dstiffness_term += dP*gradX(cell,qp,i,j)*workConj(cell,qp,i,j)*qp_weights(cell,qp);
        }
        for(int node=0; node<numNodes; node++)
        dEdp(cell,node) = -(dstiffness_term - dmass_term*eigval(0))*BF(cell,node,qp);
      }
//tevhack        std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in StiffnessObjective:" << size << std::endl);
  }

/*
  if( size == 3 ){
    for(int cell=0; cell<numCells; cell++){
      double dE = 0.0;
      double P = topology->Penalize(topo(cell));
      for(int qp=0; qp<numQPs; qp++) {
        for(int i=0; i<numDims; i++) {
          dE += val_qp(cell,qp,i) * val_qp(cell,qp,i);
        }
        for(int node=0; node<numNodes; node++)
          dEdp(cell,node) = dE/P*BF(cell,node,qp);
      }
      std::cout << "dEdp(" << cell << ") = " << dEdp(cell) << std::endl;
    }
  } else {
    TEUCHOS_TEST_FOR_EXCEPTION(
      true, 
      Teuchos::Exceptions::InvalidParameter,
      "Unexpected array dimensions in ModalObjective:" << size << std::endl
    );
  }
*/

  F(0) = -eigval(0);

}