Laplace3D.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (2009) Kevin Long
00003  * Department of Mathematics and Statistics
00004  * Texas Tech University
00005  *
00006  * This library is free software; you can redistribute it and/or modify
00007  * it under the terms of the GNU Lesser General Public License as
00008  * published by the Free Software Foundation; either version 2.1 of the
00009  * License, or (at your option) any later version.
00010  *  
00011  * This library is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *                                                                           
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00019  * USA                                                                       
00020  * 
00021  */
00022 
00023 #include "Sundance.hpp"
00024 
00025 // This test depends on Exodus, so skip it if Expdus hasn't been enabled. 
00026 #if defined(HAVE_SUNDANCE_EXODUS) && defined(Trilinos_DATA_DIR)
00027 
00028 using namespace Sundance;
00029 
00030 /** 
00031  * This example program sets up and solves the Laplace 
00032  * equation \f$-\nabla^2 u=0\f$. See the
00033  * document GettingStarted.pdf for more information.
00034  */
00035 int main(int argc, char** argv)
00036 {
00037   try
00038   {
00039     /* command-line options */
00040     std::string meshFile="plateWithHole3D-1";
00041     std::string solverFile = "aztec-ml.xml";
00042     Sundance::setOption("meshFile", meshFile, "mesh file");
00043     Sundance::setOption("solver", solverFile, 
00044       "name of XML file for solver");
00045 
00046     /* Initialize */
00047     Sundance::init(&argc, &argv);
00048 
00049     /* --- Specify vector representation to be used --- */
00050     VectorType<double> vecType = new EpetraVectorType();
00051 
00052     /* --- Read mesh --- */
00053     MeshType meshType = new BasicSimplicialMeshType();
00054     MeshSource meshSrc
00055       =  new ExodusMeshReader(meshFile, meshType);
00056     Mesh mesh = meshSrc.getMesh();
00057 
00058     /* --- Specification of geometric regions --- */
00059 
00060     /* Region "interior" consists of all maximal-dimension cells */
00061     CellFilter interior = new MaximalCellFilter();
00062 
00063     /* Identify boundary regions via labels in mesh */
00064     CellFilter edges = new DimensionalCellFilter(2);
00065 
00066     CellFilter south = edges.labeledSubset(1);
00067     CellFilter east = edges.labeledSubset(2);
00068     CellFilter north = edges.labeledSubset(3);
00069     CellFilter west = edges.labeledSubset(4);
00070     CellFilter hole = edges.labeledSubset(5);
00071     CellFilter down = edges.labeledSubset(6);
00072     CellFilter up = edges.labeledSubset(7);
00073 
00074     /* --- Symbolic equation definition --- */
00075 
00076     /* Test and unknown function */
00077     BasisFamily basis = new Lagrange(1);
00078     Expr u = new UnknownFunction(basis, "u");
00079     Expr v = new TestFunction(basis, "v");
00080 
00081     /* Gradient operator */
00082     Expr dx = new Derivative(0);
00083     Expr dy = new Derivative(1);
00084     Expr dz = new Derivative(2);
00085     Expr grad = List(dx, dy, dz);
00086 
00087     /* We need a quadrature rule for doing the integrations */
00088     QuadratureFamily quad1 = new GaussianQuadrature(1);
00089     QuadratureFamily quad2 = new GaussianQuadrature(2);
00090 
00091 
00092     /** Write the weak form */
00093     Expr eqn 
00094       = Integral(interior, (grad*u)*(grad*v), quad1)
00095       + Integral(east, v, quad1);
00096 
00097     /* Write the essential boundary conditions */
00098     Expr h = new CellDiameterExpr();
00099     Expr bc = EssentialBC(west, v*u/h, quad2);
00100 
00101     /* Set up linear problem */
00102     LinearProblem prob(mesh, eqn, bc, v, u, vecType);
00103 
00104     /* --- solve the problem --- */
00105 
00106     /* Create the solver as specified by parameters in 
00107      * an XML file */
00108     LinearSolver<double> solver 
00109       = LinearSolverBuilder::createSolver(solverFile);
00110 
00111     /* Solve! The solution is returned as an Expr containing a 
00112     * DiscreteFunction */
00113     Expr soln = prob.solve(solver);
00114 
00115     /* --- Postprocessing --- */
00116 
00117     /* Project the derivative onto the P1 basis */
00118     DiscreteSpace discSpace(mesh, List(basis, basis, basis), vecType);
00119     L2Projector proj(discSpace, grad*soln);
00120     Expr gradU = proj.project();
00121 
00122     /* Write the solution and its projected gradient to a VTK file */
00123     FieldWriter w = new VTKWriter("LaplaceDemo3D");
00124     w.addMesh(mesh);
00125     w.addField("soln", new ExprFieldWrapper(soln[0]));
00126     w.addField("du_dx", new ExprFieldWrapper(gradU[0]));
00127     w.addField("du_dy", new ExprFieldWrapper(gradU[1]));
00128     w.addField("du_dz", new ExprFieldWrapper(gradU[2]));
00129     w.write();
00130 
00131     /* Check flux balance */
00132     Expr n = CellNormalExpr(3, "n");
00133     CellFilter wholeBdry = east+west+north+south+up+down+hole;
00134     Expr fluxExpr 
00135       = Integral(wholeBdry, (n*grad)*soln, quad1); 
00136     double flux = evaluateIntegral(mesh, fluxExpr);
00137     Out::root() << "numerical flux = " << flux << std::endl;
00138 
00139     /* --- Let's compute a few other quantities, such as the centroid of
00140      * the mesh:*/
00141 
00142     /* Coordinate functions let us build up functions of position */
00143     Expr x = new CoordExpr(0);
00144     Expr y = new CoordExpr(1);
00145     Expr z = new CoordExpr(2);
00146 
00147     Expr xCMExpr = Integral(interior, x, quad1);
00148     Expr yCMExpr = Integral(interior, y, quad1);
00149     Expr zCMExpr = Integral(interior, z, quad1);
00150     Expr volExpr = Integral(interior, 1.0, quad1);
00151     
00152     double vol = evaluateIntegral(mesh, volExpr);
00153     double xCM = evaluateIntegral(mesh, xCMExpr)/vol;
00154     double yCM = evaluateIntegral(mesh, yCMExpr)/vol;
00155     double zCM = evaluateIntegral(mesh, zCMExpr)/vol;
00156     Out::root() << "centroid = (" << xCM << ", " << yCM 
00157               << ", " << zCM << ")" << std::endl;
00158 
00159     /* Next, compute the first Fourier sine coefficient of the solution on the
00160      * surface of the hole.*/
00161     Expr r = sqrt(x*x + y*y);
00162     Expr sinPhi = y/r;
00163 
00164     /* Use a higher-order quadrature rule for these integrals */
00165     QuadratureFamily quad4 = new GaussianQuadrature(4);
00166 
00167     Expr fourierSin1Expr = Integral(hole, sinPhi*soln, quad4);
00168     Expr fourierDenomExpr = Integral(hole, sinPhi*sinPhi, quad2);
00169     double fourierSin1 = evaluateIntegral(mesh, fourierSin1Expr);
00170     double fourierDenom = evaluateIntegral(mesh, fourierDenomExpr);
00171     Out::root() << "fourier sin m=1 = " << fourierSin1/fourierDenom << std::endl;
00172 
00173     /* Compute the L2 norm of the solution */
00174     Expr L2NormExpr = Integral(interior, soln*soln, quad2);     
00175     double l2Norm_method1 = sqrt(evaluateIntegral(mesh, L2NormExpr));     
00176     Out::os() << "method #1: ||soln|| = " << l2Norm_method1 << endl;
00177 
00178     /* Use the L2Norm() function to do the same calculation */
00179     double l2Norm_method2 = L2Norm(mesh, interior, soln, quad2);     
00180     Out::os() << "method #2: ||soln|| = " << l2Norm_method2 << endl;
00181 
00182     /*
00183      * Check that the flux is acceptably close to zero. The flux calculation
00184      * is only O(h) so keep the tolerance loose. This
00185      * is just a sanity check to ensure the code doesn't get completely 
00186      * broken after a change to the library. 
00187      */
00188     Sundance::passFailTest(fabs(flux), 1.0e-2);
00189   }
00190   catch(std::exception& e) 
00191   {
00192     Sundance::handleException(e);
00193   }
00194   Sundance::finalize(); 
00195 
00196   return Sundance::testStatus();
00197 }
00198 
00199 /*
00200  * All done!
00201  */
00202 
00203 #else
00204 
00205 
00206 int main(int argc, char** argv)
00207 {
00208   Sundance::init(&argc, &argv);
00209   std::cout << "dummy Laplace3D PASSED. Enable exodus to run the actual test" << std::endl;
00210   Sundance::finalize();
00211   return 0;
00212 }
00213 
00214 
00215 #endif
00216 

Site Contact