ParameterSweep.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 #include "Sundance.hpp"
00043 
00044 using Sundance::List;
00045 
00046 using namespace Sundance;
00047 using namespace Playa;
00048 
00049 
00050 /**
00051  *
00052  * This example shows how to sweep over a changing parameter without creating a new
00053  * expression and problem for each parameter value. 
00054  *
00055  * Similar logic can be used for continuation methods or parameter space sampling.
00056  *
00057  */
00058 
00059 
00060 int main(int argc, char** argv)
00061 {
00062   
00063   try
00064     {
00065       Sundance::init(&argc, &argv);
00066             
00067       /* We will do our linear algebra using Epetra */
00068       VectorType<double> vecType = new EpetraVectorType();
00069 
00070       /* Create a mesh. It will be of type BasisSimplicialMesh, and will
00071        * be built using a PartitionedLineMesher. */
00072       MeshType meshType = new BasicSimplicialMeshType();
00073       int nx = 32;
00074 
00075       MeshSource mesher = new PartitionedRectangleMesher(
00076                0.0, 1.0, nx,
00077                0.0, 1.0, nx,
00078                meshType);
00079       Mesh mesh = mesher.getMesh();
00080 
00081       /* Create a cell filter that will identify the maximal cells
00082        * in the interior of the domain */
00083       CellFilter interior = new MaximalCellFilter();
00084 
00085       /* Make cell filters for the east and west boundaries */
00086       CellFilter edges = new DimensionalCellFilter(1);
00087       CellFilter west = edges.coordSubset(0, 0.0);
00088       CellFilter east = edges.coordSubset(0, 1.0);
00089 
00090       /* Create unknown and test functions */
00091       Expr u = new UnknownFunction(new Lagrange(1), "u");
00092       Expr v = new TestFunction(new Lagrange(1), "v");
00093 
00094       /* Create differential operator and coordinate function */
00095       Expr x = new CoordExpr(0);
00096       Expr grad = gradient(1);
00097 
00098       /* We need a quadrature rule for doing the integrations */
00099       QuadratureFamily quad = new GaussianQuadrature(4);
00100 
00101       /* Define the parameter */
00102       Expr xi = new Sundance::Parameter(0.0);
00103 
00104       /* Construct a forcing term to provide an exact solution for
00105        * validation purposes. This will involve the parameter. */
00106       Expr uEx = x*(1.0-x)*(1.0+xi*exp(x));
00107       Expr f = -(-20 - exp(x)*xi*(1 + 32*x + 10*x*x + 
00108           exp(x)*(-1 + 2*x*(2 + x))*xi))/10.0;
00109 
00110       /* Define the weak form, using the parameter expression. This weak form
00111        * can be used for all parameter values. */
00112       Expr eqn = Integral(interior, 
00113         (1.0 + 0.1*xi*exp(x))*(grad*v)*(grad*u) - f*v, quad);
00114 
00115       /* Define the Dirichlet BC */
00116       Expr h = new CellDiameterExpr();
00117       Expr bc = EssentialBC(east + west, v*u/h, quad);
00118 
00119       /* We can now set up the linear problem. This can be reused
00120        * for different parameter values. */
00121       LinearProblem prob(mesh, eqn, bc, v, u, vecType);
00122 
00123       /* make a projector for the exact solution. Just like the
00124        * problem, this can be reused for different parameter values. */
00125       DiscreteSpace ds(mesh, new Lagrange(1), vecType);
00126       L2Projector proj(ds, uEx);
00127 
00128       /* Get the solver and declare variables for the results */
00129       LinearSolver<double> solver = LinearSolverBuilder::createSolver("aztec-ml.xml");
00130       Expr soln;
00131       SolverState<double> state;
00132 
00133       /* Set up the sweep from xi=0 to xi=xiMax in nSteps steps. */
00134       int nSteps = 10;
00135       double xiMax = 2.0;
00136       
00137       /* Make an array in which to keep the observed errors */
00138       Array<double> err(nSteps);
00139 
00140       /* Do the sweep */
00141       for (int n=0; n<nSteps; n++)
00142   {
00143     /* Update the parameter value */
00144     double xiVal = xiMax*n/(nSteps - 1.0);
00145     xi.setParameterValue(xiVal);
00146     Out::root() << "step n=" << n << " of " << nSteps << " xi=" << xiVal;
00147 
00148     /* Solve the problem. The updated parameter value is automatically used. */
00149     state = prob.solve(solver, soln);
00150 
00151     TEUCHOS_TEST_FOR_EXCEPTION(state.finalState() != SolveConverged,
00152              std::runtime_error,
00153              "solve failed!");
00154 
00155     /* Project the exact solution onto a discrrete space for viz. The updated
00156      * parameter value is automatically used. */
00157     Expr uEx0 = proj.project();
00158 
00159     /* Write the approximate and exact solutions for viz */
00160     FieldWriter w = new VTKWriter("ParameterSweep-" + Teuchos::toString(n));
00161     w.addMesh(mesh);
00162     w.addField("u", new ExprFieldWrapper(soln[0]));
00163     w.addField("uEx", new ExprFieldWrapper(uEx0[0]));
00164     w.write();
00165 
00166     /* Compute the L2 norm of the error */
00167     err[n] = L2Norm(mesh, interior, soln-uEx, quad);
00168     Out::root() << " L2 error = " << err[n] << endl;
00169   } 
00170 
00171       /* The errors are O(h^2), so use that to set a tolerance */
00172       double hVal = 1.0/(nx-1.0);
00173       double fudge = 2.0;
00174       double tol = fudge*hVal*hVal;
00175 
00176       /* Find the max error over all parameter values */
00177       double maxErr = *std::max_element(err.begin(), err.end());
00178 
00179       /* Check the error */
00180       Sundance::passFailTest(maxErr, tol);
00181     }
00182   catch(std::exception& e)
00183     {
00184       Sundance::handleException(e);
00185     }
00186   Sundance::finalize(); 
00187   return Sundance::testStatus(); 
00188 }

Site Contact