void updateDiscreteFunction(const Expr& newVals, Expr old)
{
    const DiscreteFunction* in = DiscreteFunction::discFunc(newVals);
    TEST_FOR_EXCEPT(in==0);
    DiscreteFunction* out = DiscreteFunction::discFunc(old);
    TEST_FOR_EXCEPT(out==0);
    Vector<double> vec = in->getVector();
    out->setVector(vec);
}
double FunctionalEvaluator::fdGradientCheck(double h) const
{
  bool showAll = false;
  Tabs tabs;
  double f0, fPlus, fMinus;
  Expr gradF0 = evalGradient(f0);

  FancyOStream& os = Out::os();


  DiscreteFunction* df = DiscreteFunction::discFunc(varValues_);
  DiscreteFunction* dg = DiscreteFunction::discFunc(gradF0);
  Vector<double> x = df->getVector();
  Vector<double> x0 = x.copy();
  Vector<double> gf = dg->getVector();

  RCP<GhostView<double> > xView = df->ghostView();
  RCP<GhostView<double> > gradF0View = dg->ghostView();


  TEUCHOS_TEST_FOR_EXCEPTION(xView.get() == 0, std::runtime_error, 
    "bad pointer in FunctionalEvaluator::fdGradientCheck");
  TEUCHOS_TEST_FOR_EXCEPTION(gradF0View.get() == 0, std::runtime_error, 
    "bad pointer in FunctionalEvaluator::fdGradientCheck");

  int nTot = x.space().dim();
  int n = x.space().numLocalElements();
  int lowestIndex = x.space().baseGlobalNaturalIndex();

  os << tabs << "doing fd check:  h=" << h << std::endl;
  Array<double> df_dx(n);

  int localIndex = 0;
  for (int globalIndex=0; globalIndex<nTot; globalIndex++)
  {
    double tmp=0.0;
    bool isLocal = globalIndex >= lowestIndex 
      && globalIndex < (lowestIndex+n);
    if (isLocal)
    {
      tmp = xView->getElement(globalIndex);
      loadable(x)->setElement(globalIndex, tmp + h);
    }

    df->setVector(x);
    fPlus = evaluate();
    if (isLocal)
    {
      loadable(x)->setElement(globalIndex, tmp - h);
    }

    df->setVector(x);
    fMinus = evaluate();
      
    if (isLocal)
    {
      df_dx[localIndex] = (fPlus - fMinus)/2.0/h;
      os << "g=" << setw(5) << globalIndex << ", l=" << setw(5) << localIndex << " f0="
         << setw(12) << f0 
         << " fPlus=" << setw(12) << fPlus << " fMinus=" << setw(12) << fMinus << " df_dx="
         << setw(12) << df_dx[localIndex] << std::endl;
      if (showAll)
      {
        os << "i " << globalIndex << " x_i=" << tmp 
           << " f(x)=" << f0 
           << " f(x+h)=" << fPlus 
           << " f(x-h)=" << fMinus << std::endl;
      }
      loadable(x)->setElement(globalIndex, tmp);
      localIndex++;
    }
    df->setVector(x);
  }
  
  double localMaxErr = 0.0;

  showAll = true;
  VectorSpace<double> space = x.space();
  for (int i=0; i<space.numLocalElements(); i++)
  {
    double num =  fabs(df_dx[i]-gf[i]);
    double den = fabs(df_dx[i]) + fabs(gf[i]) + 1.0e-14;
    double r = 0.0;
    if (fabs(den) > 1.0e-16) r = num/den;
    else r = 1.0;
    if (showAll)
    {
      os << "i " << i;
      os << " FD=" << df_dx[i] 
         << " grad=" << gf[i]
         << " r=" << r << std::endl;
    }
    if (localMaxErr < r) localMaxErr = r;
  }
  os << "local max error = " << localMaxErr << std::endl;
  
  double maxErr = localMaxErr;
  df->mesh().comm().allReduce((void*) &localMaxErr, (void*) &maxErr, 1, 
    MPIDataType::doubleType(), MPIOp::maxOp());
  os << tabs << "fd check: max error = " << maxErr << std::endl;

  return maxErr;
}