void testNormals()
  {
    if (s->has_elem() &&
        s->get_elem().processor_id() == TestCommWorld->rank())
      {
        ParsedFEMFunction<Number> nx(*sys, "n_x");

        ParsedFEMFunction<Number> ny(*sys, "n_y");

        ParsedFEMFunction<Number> nz(*sys, "n_z");

        const std::vector<Point> & xyz = s->get_side_fe(0)->get_xyz();

        // On side 3 of a hex the normal direction is +y
        for (unsigned int qp=0; qp != xyz.size(); ++qp)
          {
            CPPUNIT_ASSERT_DOUBLES_EQUAL
              (libmesh_real(nx(*s,xyz[qp])), 0.0, TOLERANCE*TOLERANCE);
            CPPUNIT_ASSERT_DOUBLES_EQUAL
              (libmesh_real(ny(*s,xyz[qp])), 1.0, TOLERANCE*TOLERANCE);
            CPPUNIT_ASSERT_DOUBLES_EQUAL
              (libmesh_real(nz(*s,xyz[qp])), 0.0, TOLERANCE*TOLERANCE);
          }
      }
  }
  void testInlineSetter()
  {
    if (c->has_elem() &&
        c->get_elem().processor_id() == TestCommWorld->rank())
      {
        ParsedFEMFunction<Number> ax2(*sys, "a:=4.5;a*x2");
        ax2.set_inline_value("a", 2.5);

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(ax2(*c,Point(0.25,0.25,0.25))), 1.25, TOLERANCE*TOLERANCE);

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(ax2.get_inline_value("a")), 2.5, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> cxy8
          (*sys, "a := 4 ; b := a/2+1; c:=b-a+3.5; c*x2*y4");

        cxy8.set_inline_value("a", 2);

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(cxy8(*c,Point(0.5,0.5,0.5))), 7.0, TOLERANCE*TOLERANCE);

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(cxy8.get_inline_value("b")), 2.0, TOLERANCE*TOLERANCE);

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(cxy8.get_inline_value("c")), 3.5, TOLERANCE*TOLERANCE);

      }
  }
  void testValues()
  {
    if (c->has_elem() &&
        c->get_elem().processor_id() == TestCommWorld->rank())
      {
        ParsedFEMFunction<Number> x2(*sys, "x2");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(x2(*c,Point(0.5,0.5,0.5))), 1.0, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> xy8(*sys, "x2*y4");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(xy8(*c,Point(0.5,0.5,0.5))), 2.0, TOLERANCE*TOLERANCE);
      }
  }
  void testHessians()
  {
    if (c->has_elem() &&
        c->get_elem().processor_id() == TestCommWorld->rank())
      {
        ParsedFEMFunction<Number> c1(*sys, "hess_xy_xy");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(c1(*c,Point(0.35,0.45,0.55))), 1.0, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> x(*sys, "hess_yz_xyz");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(x(*c,Point(0.25,0.35,0.55))), 0.25, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> xz(*sys, "hess_yz_xyz*grad_y_yz");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(xz(*c,Point(0.25,0.4,0.75))), 0.1875, TOLERANCE*TOLERANCE);
      }
  }
  void testGradients()
  {
    if (c->has_elem() &&
        c->get_elem().processor_id() == TestCommWorld->rank())
      {
        ParsedFEMFunction<Number> c2(*sys, "grad_x_x2");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(c2(*c,Point(0.35,0.45,0.55))), 2.0, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> xz(*sys, "grad_y_xyz");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(xz(*c,Point(0.25,0.35,0.75))), 0.1875, TOLERANCE*TOLERANCE);

        ParsedFEMFunction<Number> xyz(*sys, "grad_y_xyz*grad_x_xy");

        CPPUNIT_ASSERT_DOUBLES_EQUAL
          (libmesh_real(xyz(*c,Point(0.25,0.5,0.75))), 0.09375, TOLERANCE*TOLERANCE);
      }
  }