00001 #include "Sundance.hpp"
00002
00003
00004
00005
00006
00007 int main(int argc, char** argv)
00008 {
00009 try
00010 {
00011 int nx = 32;
00012 double convTol = 1.0e-8;
00013 double lambda = 0.5;
00014 Sundance::setOption("nx", nx, "Number of elements");
00015 Sundance::setOption("tol", convTol, "Convergence tolerance");
00016 Sundance::setOption("lambda", lambda, "Lambda (parameter in Bratu's equation)");
00017
00018 Sundance::init(&argc, &argv);
00019
00020 Out::root() << "Bratu problem (lambda=" << lambda << ")" << endl;
00021 Out::root() << "Newton's method with automated linearization"
00022 << endl << endl;
00023
00024 VectorType<double> vecType = new EpetraVectorType();
00025
00026 MeshType meshType = new BasicSimplicialMeshType();
00027 MeshSource mesher = new PartitionedLineMesher(0.0, 1.0, nx, meshType);
00028 Mesh mesh = mesher.getMesh();
00029
00030 CellFilter interior = new MaximalCellFilter();
00031 CellFilter sides = new DimensionalCellFilter(mesh.spatialDim()-1);
00032 CellFilter left = sides.subset(new CoordinateValueCellPredicate(0, 0.0));
00033 CellFilter right = sides.subset(new CoordinateValueCellPredicate(0, 1.0));
00034
00035 BasisFamily basis = new Lagrange(1);
00036 Expr u = new UnknownFunction(basis, "w");
00037 Expr v = new TestFunction(basis, "v");
00038
00039 Expr grad = gradient(1);
00040
00041 Expr x = new CoordExpr(0);
00042
00043 const double pi = 4.0*atan(1.0);
00044 Expr uExact = sin(pi*x);
00045 Expr R = pi*pi*uExact - lambda*exp(uExact);
00046
00047 QuadratureFamily quad4 = new GaussianQuadrature(4);
00048 QuadratureFamily quad2 = new GaussianQuadrature(2);
00049
00050 DiscreteSpace discSpace(mesh, basis, vecType);
00051 Expr uPrev = new DiscreteFunction(discSpace, 0.5);
00052
00053 Expr eqn
00054 = Integral(interior, (grad*v)*(grad*u) - v*lambda*exp(u) - v*R, quad4);
00055
00056 Expr h = new CellDiameterExpr();
00057 Expr bc = EssentialBC(left+right, v*u/h, quad2);
00058
00059 NonlinearProblem prob(mesh, eqn, bc, v, u, uPrev, vecType);
00060
00061 LinearSolver<double> linSolver
00062 = LinearSolverBuilder::createSolver("amesos.xml");
00063
00064 Out::root() << "Newton iteration" << endl;
00065 int maxIters = 20;
00066 Expr soln ;
00067 bool converged = false;
00068
00069 LinearOperator<double> J = prob.allocateJacobian();
00070 Vector<double> residVec = J.range().createMember();
00071 Vector<double> stepVec;
00072
00073 for (int i=0; i<maxIters; i++)
00074 {
00075 prob.setInitialGuess(uPrev);
00076 prob.computeJacobianAndFunction(J, residVec);
00077
00078 linSolver.solve(J, -1.0*residVec, stepVec);
00079
00080 double deltaU = stepVec.norm2();
00081 Out::root() << "Iter=" << setw(3) << i << " ||Delta u||=" << setw(20)
00082 << deltaU << endl;
00083 addVecToDiscreteFunction(uPrev, stepVec);
00084 if (deltaU < convTol)
00085 {
00086 soln = uPrev;
00087 converged = true;
00088 break;
00089 }
00090 }
00091 TEUCHOS_TEST_FOR_EXCEPTION(!converged, std::runtime_error,
00092 "Newton iteration did not converge after "
00093 << maxIters << " iterations");
00094
00095 FieldWriter writer = new DSVWriter("AutoLinearizedBratu.dat");
00096 writer.addMesh(mesh);
00097 writer.addField("soln", new ExprFieldWrapper(soln[0]));
00098 writer.write();
00099
00100 Out::root() << "Converged!" << endl << endl;
00101
00102 double L2Err = L2Norm(mesh, interior, soln-uExact, quad4);
00103 Out::root() << "L2 Norm of error: " << L2Err << endl;
00104
00105 Sundance::passFailTest(L2Err, 1.5/((double) nx*nx));
00106 }
00107 catch(exception& e)
00108 {
00109 Sundance::handleException(e);
00110 }
00111 Sundance::finalize();
00112 }
00113