Main Page   Namespace List   Class Hierarchy   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages   Examples  

inlinePoissonBoltzmann1D.cpp

#include "Sundance.h"


/** \example inlinePoissonBoltzmann1D.cpp
 * Solve the Poisson-Boltzmann equation \f$\nabla^2 u = e^-u$ on the unit
 * line with boundary conditions:
 * Left: Natural, du/dx=0
 * Right: Dirichlet u = 2 log(cosh(1/sqrt(2)))
 *
 * The solution is 2 log(cosh(x/sqrt(2))).
 *
 * The problem is nonlinear, so we use Newton's method to iterate 
 * towards a solution. In this example, Newton's method is 
 * coded inline; we don't use any sort
 * of nonlinear solver object. 
 *
 */

int main(int argc, void** argv)
{
  try
    {
      Sundance::init(&argc, &argv);

      /* create a simple mesh on the unit line */
      double L=1.0;
      int n = 80;
      MeshGenerator mesher = new LineMesher(0.0, L, n);
      Mesh mesh = mesher.getMesh();

      /* define an expression representing the x-coordinate function */
      Expr x = new CoordExpr(0);

      /* create a cell set representing the right boundary */
      CellSet boundary = new BoundaryCellSet();
      CellSet right = boundary.subset( x == L );

      /* create a discrete space on the mesh */
      TSFVectorSpace discreteSpace 
        = new SundanceVectorSpace(mesh, new Lagrange(1));

      /* create an expression for the initial guess. This will be reused as the
       * starting point for each newton step. Assume u(x)=x as an initial 
       * guess, and discretize it.
       */
      Expr u0 = new DiscreteFunction(discreteSpace, x, "u0");

      /* create symbolic objects for test and unknown functions. At each newton
       * step we will solve a linearized equation for a step du, so our
       * unknown is du. */
      Expr v = new TestFunction(new Lagrange(1), "v");
      Expr du = new UnknownFunction(new Lagrange(1), "du");

      /* create a differential operator representing the x-derivative. */
      Expr dx = new Derivative(0);
      
      /* linearized weak equation for the step du */
      Expr newton = (dx*(u0+du))*(dx*v) + v*exp(-u0) - v*exp(-u0)*du;
      Expr eqn = Integral(newton);

      /* Dirichlet boundary condition */
      double uBC = 2.0*log(cosh(L/sqrt(2.0)));          
      EssentialBC bc = EssentialBC(right, (u0+du-uBC)*v) ;
      
      /* linear problem for the step du */
      StaticLinearProblem prob(mesh, eqn, bc, v, du); 

      /* create linear solver */
      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);

          /* solve for the step and compute its norm */
          Expr duSoln = prob.solve(solver);
          resid = duSoln.norm(2);

          TSFOut::printf("resid = %g\n", resid);
          iter++;

          /* add the full step to the previous point. Store the result
          * in the expression u0, so that its value in the linear
          * problem is updated. */
          u0 = new DiscreteFunction(discreteSpace, u0+duSoln);

          /* write the current iterate to disk */
          char fName[100];
          sprintf(fName, "u%d.dat.%d", iter, MPIComm::world().getRank());
          
          FieldWriter writer = new MatlabWriter(fName);
          writer.writeField(u0);

          /* discard the matrix values, preserving the matrix structure. */
          prob.flushMatrixValues();
        }

      
      
      // compare to exact solution
      Expr exactSoln = 2.0*log(cosh(x/sqrt(2.0)));

      // compute the norm of the error
      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();
}

Contact:
Kevin Long (krlong@ca.sandia.gov)


Documentation generated by