#include "Sundance.h"
int main(int argc, void** argv)
{
try
{
Sundance::init(&argc, &argv);
double L=1.0;
int n = 80;
MeshGenerator mesher = new LineMesher(0.0, L, n);
Mesh mesh = mesher.getMesh();
Expr x = new CoordExpr(0);
CellSet boundary = new BoundaryCellSet();
CellSet right = boundary.subset( x == L );
TSFVectorSpace discreteSpace
= new SundanceVectorSpace(mesh, new Lagrange(1));
Expr u0 = new DiscreteFunction(discreteSpace, x, "u0");
Expr v = new TestFunction(new Lagrange(1), "v");
Expr du = new UnknownFunction(new Lagrange(1), "du");
Expr dx = new Derivative(0);
Expr newton = (dx*(u0+du))*(dx*v) + v*exp(-u0) - v*exp(-u0)*du;
Expr eqn = Integral(newton);
double uBC = 2.0*log(cosh(L/sqrt(2.0)));
EssentialBC bc = EssentialBC(right, (u0+du-uBC)*v) ;
StaticLinearProblem prob(mesh, eqn, bc, v, du);
TSFPreconditionerFactory prec = new ILUKPreconditionerFactory(1);
TSFLinearSolver solver = new BICGSTABSolver(1.0e-14, 300);
int maxIters = 10;
double tol = 1.0e-12;
double resid = 1;
int iter=0;
while (resid > tol && iter < maxIters)
{
TSFOut::printf("Newton step# %d", iter);
Expr duSoln = prob.solve(solver);
resid = duSoln.norm(2);
TSFOut::printf("resid = %g\n", resid);
iter++;
u0 = new DiscreteFunction(discreteSpace, u0+duSoln);
char fName[100];
sprintf(fName, "u%d.dat.%d", iter, MPIComm::world().getRank());
FieldWriter writer = new MatlabWriter(fName);
writer.writeField(u0);
prob.flushMatrixValues();
}
Expr exactSoln = 2.0*log(cosh(x/sqrt(2.0)));
double errorNorm = (exactSoln - u0).norm(2);
double tolerance = 1.0e-4;
TSFOut::printf("error = %g\n", errorNorm);
Testing::passFailCheck(__FILE__, errorNorm, tolerance);
}
catch(exception& e)
{
Sundance::handleError(e, __FILE__);
}
Sundance::finalize();
}