Laplace3D.cpp
Go to the documentation of this file.
00001 /* @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                             Sundance
00005 //                 Copyright 2011 Sandia Corporation
00006 // 
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu)
00038 // 
00039 
00040 /* @HEADER@ */
00041 
00042 
00043 
00044 #include "Sundance.hpp"
00045 
00046 // This test depends on Exodus, so skip it if Expdus hasn't been enabled. 
00047 #if defined(HAVE_SUNDANCE_EXODUS) 
00048 
00049 using namespace Sundance;
00050 
00051 /** 
00052  * This example program sets up and solves the Laplace 
00053  * equation \f$-\nabla^2 u=0\f$. See the
00054  * document GettingStarted.pdf for more information.
00055  */
00056 int main(int argc, char** argv)
00057 {
00058   try
00059   {
00060     /* command-line options */
00061     std::string meshFile="plateWithHole3D-1";
00062     std::string solverFile = "aztec-ml.xml";
00063     Sundance::setOption("meshFile", meshFile, "mesh file");
00064     Sundance::setOption("solver", solverFile, 
00065       "name of XML file for solver");
00066 
00067     /* Initialize */
00068     Sundance::init(&argc, &argv);
00069 
00070     /* --- Specify vector representation to be used --- */
00071     VectorType<double> vecType = new EpetraVectorType();
00072 
00073     /* --- Read mesh --- */
00074     MeshType meshType = new BasicSimplicialMeshType();
00075     MeshSource meshSrc
00076       =  new ExodusMeshReader(meshFile, meshType);
00077     Mesh mesh = meshSrc.getMesh();
00078 
00079     /* --- Specification of geometric regions --- */
00080 
00081     /* Region "interior" consists of all maximal-dimension cells */
00082     CellFilter interior = new MaximalCellFilter();
00083 
00084     /* Identify boundary regions via labels in mesh */
00085     CellFilter edges = new DimensionalCellFilter(2);
00086 
00087     CellFilter south = edges.labeledSubset(1);
00088     CellFilter east = edges.labeledSubset(2);
00089     CellFilter north = edges.labeledSubset(3);
00090     CellFilter west = edges.labeledSubset(4);
00091     CellFilter hole = edges.labeledSubset(5);
00092     CellFilter down = edges.labeledSubset(6);
00093     CellFilter up = edges.labeledSubset(7);
00094 
00095     /* --- Symbolic equation definition --- */
00096 
00097     /* Test and unknown function */
00098     BasisFamily basis = new Lagrange(1);
00099     Expr u = new UnknownFunction(basis, "u");
00100     Expr v = new TestFunction(basis, "v");
00101 
00102     /* Gradient operator */
00103     Expr dx = new Derivative(0);
00104     Expr dy = new Derivative(1);
00105     Expr dz = new Derivative(2);
00106     Expr grad = List(dx, dy, dz);
00107 
00108     /* We need a quadrature rule for doing the integrations */
00109     QuadratureFamily quad1 = new GaussianQuadrature(1);
00110     QuadratureFamily quad2 = new GaussianQuadrature(2);
00111 
00112 
00113     /** Write the weak form */
00114     Expr eqn 
00115       = Integral(interior, (grad*u)*(grad*v), quad1)
00116       + Integral(east, v, quad1);
00117 
00118     /* Write the essential boundary conditions */
00119     Expr h = new CellDiameterExpr();
00120     Expr bc = EssentialBC(west, v*u/h, quad2);
00121 
00122     /* Set up linear problem */
00123     LinearProblem prob(mesh, eqn, bc, v, u, vecType);
00124 
00125     /* --- solve the problem --- */
00126 
00127     /* Create the solver as specified by parameters in 
00128      * an XML file */
00129 
00130     LinearSolver<double> solver 
00131       = LinearSolverBuilder::createSolver(solverFile);
00132 
00133     /* Solve! The solution is returned as an Expr containing a 
00134     * DiscreteFunction */
00135     Expr soln = prob.solve(solver);
00136 
00137     /* --- Postprocessing --- */
00138 
00139     /* Project the derivative onto the P1 basis */
00140     DiscreteSpace discSpace(mesh, List(basis, basis, basis), vecType);
00141     L2Projector proj(discSpace, grad*soln);
00142     Expr gradU = proj.project();
00143 
00144     /* Write the solution and its projected gradient to a VTK file */
00145     FieldWriter w = new VTKWriter("LaplaceDemo3D");
00146     w.addMesh(mesh);
00147     w.addField("soln", new ExprFieldWrapper(soln[0]));
00148     w.addField("du_dx", new ExprFieldWrapper(gradU[0]));
00149     w.addField("du_dy", new ExprFieldWrapper(gradU[1]));
00150     w.addField("du_dz", new ExprFieldWrapper(gradU[2]));
00151     w.write();
00152 
00153     /* Check flux balance */
00154     Expr n = CellNormalExpr(3, "n");
00155     CellFilter wholeBdry = east+west+north+south+up+down+hole;
00156     Expr fluxExpr 
00157       = Integral(wholeBdry, (n*grad)*soln, quad1); 
00158     double flux = evaluateIntegral(mesh, fluxExpr);
00159     Out::root() << "numerical flux = " << flux << std::endl;
00160 
00161     /* --- Let's compute a few other quantities, such as the centroid of
00162      * the mesh:*/
00163 
00164     /* Coordinate functions let us build up functions of position */
00165     Expr x = new CoordExpr(0);
00166     Expr y = new CoordExpr(1);
00167     Expr z = new CoordExpr(2);
00168 
00169     Expr xCMExpr = Integral(interior, x, quad1);
00170     Expr yCMExpr = Integral(interior, y, quad1);
00171     Expr zCMExpr = Integral(interior, z, quad1);
00172     Expr volExpr = Integral(interior, 1.0, quad1);
00173     
00174     double vol = evaluateIntegral(mesh, volExpr);
00175     double xCM = evaluateIntegral(mesh, xCMExpr)/vol;
00176     double yCM = evaluateIntegral(mesh, yCMExpr)/vol;
00177     double zCM = evaluateIntegral(mesh, zCMExpr)/vol;
00178     Out::root() << "centroid = (" << xCM << ", " << yCM 
00179               << ", " << zCM << ")" << std::endl;
00180 
00181     /* Next, compute the first Fourier sine coefficient of the solution on the
00182      * surface of the hole.*/
00183     Expr r = sqrt(x*x + y*y);
00184     Expr sinPhi = y/r;
00185 
00186     /* Use a higher-order quadrature rule for these integrals */
00187     QuadratureFamily quad4 = new GaussianQuadrature(4);
00188 
00189     Expr fourierSin1Expr = Integral(hole, sinPhi*soln, quad4);
00190     Expr fourierDenomExpr = Integral(hole, sinPhi*sinPhi, quad2);
00191     double fourierSin1 = evaluateIntegral(mesh, fourierSin1Expr);
00192     double fourierDenom = evaluateIntegral(mesh, fourierDenomExpr);
00193     Out::root() << "fourier sin m=1 = " << fourierSin1/fourierDenom << std::endl;
00194 
00195     /* Compute the L2 norm of the solution */
00196     Expr L2NormExpr = Integral(interior, soln*soln, quad2);     
00197     double l2Norm_method1 = sqrt(evaluateIntegral(mesh, L2NormExpr));     
00198     Out::os() << "method #1: ||soln|| = " << l2Norm_method1 << endl;
00199 
00200     /* Use the L2Norm() function to do the same calculation */
00201     double l2Norm_method2 = L2Norm(mesh, interior, soln, quad2);     
00202     Out::os() << "method #2: ||soln|| = " << l2Norm_method2 << endl;
00203 
00204     /*
00205      * Check that the flux is acceptably close to zero. The flux calculation
00206      * is only O(h) so keep the tolerance loose. This
00207      * is just a sanity check to ensure the code doesn't get completely 
00208      * broken after a change to the library. 
00209      */
00210     Sundance::passFailTest(fabs(flux), 1.0e-2);
00211   }
00212   catch(std::exception& e) 
00213   {
00214     Sundance::handleException(e);
00215   }
00216   Sundance::finalize(); 
00217 
00218   return Sundance::testStatus();
00219 }
00220 
00221 /*
00222  * All done!
00223  */
00224 
00225 #else
00226 
00227 
00228 int main(int argc, char** argv)
00229 {
00230   Sundance::init(&argc, &argv);
00231   std::cout << "dummy Laplace3D PASSED. Enable exodus to run the actual test" << std::endl;
00232   Sundance::finalize();
00233   return 0;
00234 }
00235 
00236 
00237 #endif
00238 

Site Contact