Ejemplo n.º 1
0
int main(int argc, char** argv)
{
  try
  {
    /*
     * Initialization code
     */
    std::string meshFile="plateWithHole2D-1";
    std::string solverFile = "nox-aztec.xml";
    Sundance::setOption("meshFile", meshFile, "mesh file");
    Sundance::setOption("solver", solverFile, 
      "name of XML file for solver");

    Sundance::init(&argc, &argv);

    // This next line is just a hack to deal with some 
    // transitional code in the
    // element integration logic. 
    Sundance::ElementIntegral::alwaysUseCofacets() = false;

    /* 
     * Creation of vector type
     */
    VectorType<double> vecType = new EpetraVectorType();

    /* 
     * Creation of mesh
     */
    MeshType meshType = new BasicSimplicialMeshType();
      
    MeshSource meshSrc
      =  new ExodusMeshReader(meshFile, meshType);
    Mesh mesh = meshSrc.getMesh();

    /* 
     * Specification of cell filters
     */
    CellFilter interior = new MaximalCellFilter();
    CellFilter edges = new DimensionalCellFilter(1);

    CellFilter south = edges.labeledSubset(1);
    CellFilter east = edges.labeledSubset(2);
    CellFilter north = edges.labeledSubset(3);
    CellFilter west = edges.labeledSubset(4);

    /* 
     * <Header level="subsubsection" name="symb_setup">
     * Setup of symbolic problem description
     * </Header>
     * 
     * Create unknown and test functions discretized on the space
     * first-order Lagrange polynomials. 
     */
    BasisFamily basis = new Lagrange(2);
    Expr u = new UnknownFunction(basis, "u");
    Expr v = new TestFunction(basis, "v");

    /* 
     * Create differential operators and coordinate functions. Directions
     * are indexed starting from zero. The \verb+List()+ function can 
     * collect expressions into a vector. 
     */
    Expr dx = new Derivative(0);
    Expr dy = new Derivative(1);
    Expr grad = List(dx, dy);

    Expr x = new CoordExpr(0);
    Expr y = new CoordExpr(1);

    /* 
     * We need a quadrature rule for doing the integrations 
     */
    QuadratureFamily quad2 = new GaussianQuadrature(2);
    QuadratureFamily quad4 = new GaussianQuadrature(4);

    /* 
     * Create the weak form and the BCs
     */
    Expr source=exp(u);
    Expr eqn 
      = Integral(interior, (grad*u)*(grad*v)+v*source, quad4);

    Expr h = new CellDiameterExpr();
    Expr bc = EssentialBC(west+east, v*(u-1.0)/h, quad2);

    /* 
     * <Header level="subsubsection" name="lin_prob">
     * Creation of initial guess
     * </Header>
     *
     * So far the setup has been almost identical to that for the linear
     * problem, the only difference being the nonlinear term in the
     * equation set. 
     */
    DiscreteSpace discSpace(mesh, basis, vecType);
    L2Projector proj(discSpace, 1.0);
    Expr u0 = proj.project();

    /* 
     * <Header level="subsubsection" name="lin_prob">
     * Creation of nonlinear problem
     * </Header>
     *
     * Similar to the setup of a \verb+LinearProblem+, the equation, BCs,
     * and mesh are put into a \verb+NonlinearProblem+ object which
     * controls the construction of the \verb+Assembler+ and its use
     * in building Jacobians and residuals during a nonlinear solve.
     */
    NonlinearProblem prob(mesh, eqn, bc, v, u, u0, vecType);

    /*
     *
     */
    
    ParameterXMLFileReader reader(solverFile);
    ParameterList solverParams = reader.getParameters();
    NOXSolver solver(solverParams); 
    
    prob.solve(solver);
    
    /* 
     * Visualization output
     */
    FieldWriter w = new VTKWriter("PoissonBoltzmannDemo2D");
    w.addMesh(mesh);
    w.addField("soln", new ExprFieldWrapper(u0));
    w.write();


    /* 
     * <Header level="subsubsection" name="postproc">
     * Postprocessing
     * </Header>
     *
     * Postprocessing can be done using the same symbolic language
     * as was used for the problem specification. Here, we define
     * an integral giving the flux, then evaluate it on the mesh. 
     */
    Expr n = CellNormalExpr(2, "n");
    Expr fluxExpr 
      = Integral(east + west, (n*grad)*u0, quad2); 
    double flux = evaluateIntegral(mesh, fluxExpr);
    Out::os() << "numerical flux = " << flux << std::endl;
    Expr sourceExpr 
      = Integral(interior, exp(u0), quad4); 
    double src = evaluateIntegral(mesh, sourceExpr);
    Out::os() << "numerical integrated source = " << src << std::endl;


    /*
     * Check that the flux is acceptably close to zero. This
     * is just a sanity check to ensure the code doesn't get completely 
     * broken after a change to the library. 
     */
    Sundance::passFailTest(fabs(flux-src), 1.0e-3);

    /*
     * <Header level="subsubsection" name="finalize">
     * Finalization boilerplate
     * </Header>
     * Finally, we have boilerplate code for exception handling
     * and finalization. 
     */

  }
	catch(std::exception& e) 
  {
    Sundance::handleException(e);
  }
  Sundance::finalize(); return Sundance::testStatus(); 

  return Sundance::testStatus();
}
Ejemplo n.º 2
0
/** 
 * This example program sets up and solves the Laplace 
 * equation \f$-\nabla^2 u=0\f$. See the
 * document GettingStarted.pdf for more information.
 */
int main(int argc, char** argv)
{
  try
  {
    /* command-line options */
    std::string meshFile="plateWithHole3D-1";
    std::string solverFile = "aztec-ml.xml";
    Sundance::setOption("meshFile", meshFile, "mesh file");
    Sundance::setOption("solver", solverFile, 
      "name of XML file for solver");

    /* Initialize */
    Sundance::init(&argc, &argv);

    /* --- Specify vector representation to be used --- */
    VectorType<double> vecType = new EpetraVectorType();

    /* --- Read mesh --- */
    MeshType meshType = new BasicSimplicialMeshType();
    MeshSource meshSrc
      =  new ExodusMeshReader(meshFile, meshType);
    Mesh mesh = meshSrc.getMesh();

    /* --- Specification of geometric regions --- */

    /* Region "interior" consists of all maximal-dimension cells */
    CellFilter interior = new MaximalCellFilter();

    /* Identify boundary regions via labels in mesh */
    CellFilter edges = new DimensionalCellFilter(2);

    CellFilter south = edges.labeledSubset(1);
    CellFilter east = edges.labeledSubset(2);
    CellFilter north = edges.labeledSubset(3);
    CellFilter west = edges.labeledSubset(4);
    CellFilter hole = edges.labeledSubset(5);
    CellFilter down = edges.labeledSubset(6);
    CellFilter up = edges.labeledSubset(7);

    /* --- Symbolic equation definition --- */

    /* Test and unknown function */
    BasisFamily basis = new Lagrange(1);
    Expr u = new UnknownFunction(basis, "u");
    Expr v = new TestFunction(basis, "v");

    /* Gradient operator */
    Expr dx = new Derivative(0);
    Expr dy = new Derivative(1);
    Expr dz = new Derivative(2);
    Expr grad = List(dx, dy, dz);

    /* We need a quadrature rule for doing the integrations */
    QuadratureFamily quad1 = new GaussianQuadrature(1);
    QuadratureFamily quad2 = new GaussianQuadrature(2);


    /** Write the weak form */
    Expr eqn 
      = Integral(interior, (grad*u)*(grad*v), quad1)
      + Integral(east, v, quad1);

    /* Write the essential boundary conditions */
    Expr h = new CellDiameterExpr();
    Expr bc = EssentialBC(west, v*u/h, quad2);

    /* Set up linear problem */
    LinearProblem prob(mesh, eqn, bc, v, u, vecType);

    /* --- solve the problem --- */

    /* Create the solver as specified by parameters in 
     * an XML file */

    LinearSolver<double> solver 
      = LinearSolverBuilder::createSolver(solverFile);

    /* Solve! The solution is returned as an Expr containing a 
    * DiscreteFunction */
    Expr soln = prob.solve(solver);

    /* --- Postprocessing --- */

    /* Project the derivative onto the P1 basis */
    DiscreteSpace discSpace(mesh, List(basis, basis, basis), vecType);
    L2Projector proj(discSpace, grad*soln);
    Expr gradU = proj.project();

    /* Write the solution and its projected gradient to a VTK file */
    FieldWriter w = new VTKWriter("LaplaceDemo3D");
    w.addMesh(mesh);
    w.addField("soln", new ExprFieldWrapper(soln[0]));
    w.addField("du_dx", new ExprFieldWrapper(gradU[0]));
    w.addField("du_dy", new ExprFieldWrapper(gradU[1]));
    w.addField("du_dz", new ExprFieldWrapper(gradU[2]));
    w.write();

    /* Check flux balance */
    Expr n = CellNormalExpr(3, "n");
    CellFilter wholeBdry = east+west+north+south+up+down+hole;
    Expr fluxExpr 
      = Integral(wholeBdry, (n*grad)*soln, quad1); 
    double flux = evaluateIntegral(mesh, fluxExpr);
    Out::root() << "numerical flux = " << flux << std::endl;

    /* --- Let's compute a few other quantities, such as the centroid of
     * the mesh:*/

    /* Coordinate functions let us build up functions of position */
    Expr x = new CoordExpr(0);
    Expr y = new CoordExpr(1);
    Expr z = new CoordExpr(2);

    Expr xCMExpr = Integral(interior, x, quad1);
    Expr yCMExpr = Integral(interior, y, quad1);
    Expr zCMExpr = Integral(interior, z, quad1);
    Expr volExpr = Integral(interior, 1.0, quad1);
    
    double vol = evaluateIntegral(mesh, volExpr);
    double xCM = evaluateIntegral(mesh, xCMExpr)/vol;
    double yCM = evaluateIntegral(mesh, yCMExpr)/vol;
    double zCM = evaluateIntegral(mesh, zCMExpr)/vol;
    Out::root() << "centroid = (" << xCM << ", " << yCM 
              << ", " << zCM << ")" << std::endl;

    /* Next, compute the first Fourier sine coefficient of the solution on the
     * surface of the hole.*/
    Expr r = sqrt(x*x + y*y);
    Expr sinPhi = y/r;

    /* Use a higher-order quadrature rule for these integrals */
    QuadratureFamily quad4 = new GaussianQuadrature(4);

    Expr fourierSin1Expr = Integral(hole, sinPhi*soln, quad4);
    Expr fourierDenomExpr = Integral(hole, sinPhi*sinPhi, quad2);
    double fourierSin1 = evaluateIntegral(mesh, fourierSin1Expr);
    double fourierDenom = evaluateIntegral(mesh, fourierDenomExpr);
    Out::root() << "fourier sin m=1 = " << fourierSin1/fourierDenom << std::endl;

    /* Compute the L2 norm of the solution */
    Expr L2NormExpr = Integral(interior, soln*soln, quad2);     
    double l2Norm_method1 = sqrt(evaluateIntegral(mesh, L2NormExpr));     
    Out::os() << "method #1: ||soln|| = " << l2Norm_method1 << endl;

    /* Use the L2Norm() function to do the same calculation */
    double l2Norm_method2 = L2Norm(mesh, interior, soln, quad2);     
    Out::os() << "method #2: ||soln|| = " << l2Norm_method2 << endl;

    /*
     * Check that the flux is acceptably close to zero. The flux calculation
     * is only O(h) so keep the tolerance loose. This
     * is just a sanity check to ensure the code doesn't get completely 
     * broken after a change to the library. 
     */
    Sundance::passFailTest(fabs(flux), 1.0e-2);
  }
	catch(std::exception& e) 
  {
    Sundance::handleException(e);
  }
  Sundance::finalize(); 

  return Sundance::testStatus();
}
Ejemplo n.º 3
0
int main(int argc, char** argv)
{
  try
		{
      int depth = 0;
      bool useCCode = false;
      Sundance::ElementIntegral::alwaysUseCofacets() = true;
      Sundance::clp().setOption("depth", &depth, "expression depth");
      Sundance::clp().setOption("C", "symb", &useCCode, "Code type (C or symbolic)");
      Sundance::init(&argc, &argv);

      /* We will do our linear algebra using Epetra */
      VectorType<double> vecType = new EpetraVectorType();

      /* Read the mesh */
      MeshType meshType = new BasicSimplicialMeshType();

      MeshSource mesher 
        = new ExodusMeshReader("cube-0.1", meshType);
      Mesh mesh = mesher.getMesh();

      /* Create a cell filter that will identify the maximal cells
       * in the interior of the domain */
      CellFilter interior = new MaximalCellFilter();
      CellFilter faces = new DimensionalCellFilter(2);
      CellFilter side1 = faces.labeledSubset(1);
      CellFilter side2 = faces.labeledSubset(2);
      CellFilter side3 = faces.labeledSubset(3);
      CellFilter side4 = faces.labeledSubset(4);
      CellFilter side5 = faces.labeledSubset(5);
      CellFilter side6 = faces.labeledSubset(6);

      
      /* Create unknown and test functions, discretized using second-order
       * Lagrange interpolants */
      Expr u = new UnknownFunction(new Lagrange(1), "u");
      Expr v = new TestFunction(new Lagrange(1), "v");

      /* Create differential operator and coordinate functions */
      Expr dx = new Derivative(0);
      Expr dy = new Derivative(1);
      Expr dz = new Derivative(2);
      Expr grad = List(dx, dy, dz);
      Expr x = new CoordExpr(0);
      Expr y = new CoordExpr(1);
      Expr z = new CoordExpr(2);

      /* We need a quadrature rule for doing the integrations */
      QuadratureFamily quad2 = new GaussianQuadrature(2);
      QuadratureFamily quad4 = new GaussianQuadrature(4);

      /* Define the weak form */
      //Expr eqn = Integral(interior, (grad*v)*(grad*u) + v, quad);
      
      Expr coeff = 1.0;
#ifdef FOR_TIMING
      if (useCCode)
      {
        coeff = Poly(depth, x);
      }
      else
      {
        for (int i=0; i<depth; i++)
        {
          Expr t = 1.0;
          for (int j=0; j<depth; j++) t = t*x;
          coeff = coeff + 2.0*t - t - t;
        }
      }
#endif
      Expr eqn = Integral(interior, coeff*(grad*v)*(grad*u) /*+ 2.0*v*/, quad2);

      /* Define the Dirichlet BC */
      Expr exactSoln = x;//(x + 1.0)*x - 1.0/4.0;
      Expr h = new CellDiameterExpr();

      WatchFlag watchBC("watch BCs");
      watchBC.setParam("integration setup", 6);
      watchBC.setParam("integration", 6);
      watchBC.setParam("fill", 6);
      watchBC.setParam("evaluation", 6);
      watchBC.deactivate();

      Expr bc = EssentialBC(side4, v*(u-exactSoln), quad4)
        + EssentialBC(side6, v*(u-exactSoln), quad4, watchBC);

      /* We can now set up the linear problem! */
      LinearProblem prob(mesh, eqn, bc, v, u, vecType);

#ifdef HAVE_CONFIG_H
      ParameterXMLFileReader reader(searchForFile("SolverParameters/aztec-ml.xml"));
#else
      ParameterXMLFileReader reader("aztec-ml.xml");
#endif
      ParameterList solverParams = reader.getParameters();
      std::cerr << "params = " << solverParams << std::endl;


      LinearSolver<double> solver 
        = LinearSolverBuilder::createSolver(solverParams);

      Expr soln = prob.solve(solver);

#ifndef FOR_TIMING

      DiscreteSpace discSpace(mesh, new Lagrange(1), vecType);
      L2Projector proj1(discSpace, exactSoln);
      L2Projector proj2(discSpace, soln-exactSoln);
      L2Projector proj3(discSpace, pow(soln-exactSoln, 2.0));
      Expr exactDisc = proj1.project();
      Expr errorDisc = proj2.project();
//      Expr errorSqDisc = proj3.project();

      std::cerr << "writing fields" << std::endl;
      /* Write the field in VTK format */
      FieldWriter w = new VTKWriter("Poisson3d");
      w.addMesh(mesh);
      w.addField("soln", new ExprFieldWrapper(soln[0]));
      w.addField("exact soln", new ExprFieldWrapper(exactDisc));
      w.addField("error", new ExprFieldWrapper(errorDisc));
//      w.addField("errorSq", new ExprFieldWrapper(errorSqDisc));
      w.write();

      std::cerr << "computing error" << std::endl;

      Expr errExpr = Integral(interior, 
                              pow(soln-exactSoln, 2.0),
                              new GaussianQuadrature(4));

      double errorSq = evaluateIntegral(mesh, errExpr);
      std::cerr << "error norm = " << sqrt(errorSq) << std::endl << std::endl;
#else
      double errorSq = 1.0;
#endif
      double tol = 1.0e-10;
      Sundance::passFailTest(sqrt(errorSq), tol);
    }
	catch(std::exception& e)
		{
      Sundance::handleException(e);
		}
  Sundance::finalize(); return Sundance::testStatus(); 
}