#include "Sundance.h"



using namespace Sundance;

using namespace TSF;

int main(int argc, void** argv)
{
  try
    {
      MPIComm::init(&argc, &argv);
      int n = 150;
      Mesh mesh = lineMesh(0.0, 1.0, n);
      CellSet left(0, "left");
      CellSet right(0, "right");

      Expr x = new CoordExpr(0, "x");
			
      // create an expr
      Expr delU = new TestFunction(Lagrange(1), "delU");
      Expr U = new UnknownFunction(Lagrange(1), "U");
      Expr dx = new Derivative(0,1);
      Expr dy = new Derivative(1,1);

      Expr grad = dx;
			
      Expr e = (grad*delU)*(grad*U)  + exp(x)*delU;

			
      Expr eqn = Integral(e, GaussLegendre(8));

      EssentialBC bc = EssentialBC(left, delU*(U-exp(0.0))) 
        && EssentialBC(right, delU*(U-exp(1.0)));


      TSFLinearSolver solver = new BICGSTABSolver(1.e-13, 5000);

      StaticLinearProblem prob(mesh, eqn, bc, delU, U, new PetraMatrix());

      Expr soln = prob.solve(solver);
			
 
      ofstream of("u1.dat");
      soln.matlabDump(of);

      Expr exactSoln = exp(x);
      Expr errorExpr = soln-exactSoln;
			
      // compute the norm of the error
      double errorNorm = sqrt(fabs(definiteIntegral(mesh, errorExpr*errorExpr, 
                                                    GaussLegendre(8))));
      double tolerance = 1.0e-5;
				
      Testing::passFailCheck(__FILE__, errorNorm, tolerance);
      Testing::timeStamp(__FILE__, __DATE__, __TIME__);
    }
  catch(exception& e)
    {
      TSFOut::println(e.what());
      Testing::crash(__FILE__);
      Testing::timeStamp(__FILE__, __DATE__, __TIME__);
    }

}

