ParameterSweep.cpp
Go to the documentation of this file.
00001 /** @HEADER@ */
00002 // ************************************************************************
00003 // 
00004 //                              Sundance
00005 //                 Copyright (2005) Sandia Corporation
00006 // 
00007 // Copyright (year first published) Sandia Corporation.  Under the terms 
00008 // of Contract DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 
00009 // retains certain rights in this software.
00010 // 
00011 // This library is free software; you can redistribute it and/or modify
00012 // it under the terms of the GNU Lesser General Public License as
00013 // published by the Free Software Foundation; either version 2.1 of the
00014 // License, or (at your option) any later version.
00015 //  
00016 // This library is distributed in the hope that it will be useful, but
00017 // WITHOUT ANY WARRANTY; without even the implied warranty of
00018 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00019 // Lesser General Public License for more details.
00020 //                                                                                 
00021 // You should have received a copy of the GNU Lesser General Public
00022 // License along with this library; if not, write to the Free Software
00023 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00024 // USA                                                                                
00025 // Questions? Contact Kevin Long (krlong@sandia.gov), 
00026 // Sandia National Laboratories, Livermore, California, USA
00027 // 
00028 // ************************************************************************
00029 /* @HEADER@ */
00030 
00031 #include "Sundance.hpp"
00032 
00033 using Sundance::List;
00034 
00035 using namespace Sundance;
00036 using namespace Playa;
00037 
00038 
00039 /**
00040  *
00041  * This example shows how to sweep over a changing parameter without creating a new
00042  * expression and problem for each parameter value. 
00043  *
00044  * Similar logic can be used for continuation methods or parameter space sampling.
00045  *
00046  */
00047 
00048 
00049 int main(int argc, char** argv)
00050 {
00051   
00052   try
00053     {
00054       Sundance::init(&argc, &argv);
00055             
00056       /* We will do our linear algebra using Epetra */
00057       VectorType<double> vecType = new EpetraVectorType();
00058 
00059       /* Create a mesh. It will be of type BasisSimplicialMesh, and will
00060        * be built using a PartitionedLineMesher. */
00061       MeshType meshType = new BasicSimplicialMeshType();
00062       int nx = 32;
00063 
00064       MeshSource mesher = new PartitionedRectangleMesher(
00065         0.0, 1.0, nx,
00066         0.0, 1.0, nx,
00067         meshType);
00068       Mesh mesh = mesher.getMesh();
00069 
00070       /* Create a cell filter that will identify the maximal cells
00071        * in the interior of the domain */
00072       CellFilter interior = new MaximalCellFilter();
00073 
00074       /* Make cell filters for the east and west boundaries */
00075       CellFilter edges = new DimensionalCellFilter(1);
00076       CellFilter west = edges.coordSubset(0, 0.0);
00077       CellFilter east = edges.coordSubset(0, 1.0);
00078 
00079       /* Create unknown and test functions */
00080       Expr u = new UnknownFunction(new Lagrange(1), "u");
00081       Expr v = new TestFunction(new Lagrange(1), "v");
00082 
00083       /* Create differential operator and coordinate function */
00084       Expr x = new CoordExpr(0);
00085       Expr grad = gradient(1);
00086 
00087       /* We need a quadrature rule for doing the integrations */
00088       QuadratureFamily quad = new GaussianQuadrature(4);
00089 
00090       /* Define the parameter */
00091       Expr xi = new Sundance::Parameter(0.0);
00092 
00093       /* Construct a forcing term to provide an exact solution for
00094        * validation purposes. This will involve the parameter. */
00095       Expr uEx = x*(1.0-x)*(1.0+xi*exp(x));
00096       Expr f = -(-20 - exp(x)*xi*(1 + 32*x + 10*x*x + 
00097           exp(x)*(-1 + 2*x*(2 + x))*xi))/10.0;
00098 
00099       /* Define the weak form, using the parameter expression. This weak form
00100        * can be used for all parameter values. */
00101       Expr eqn = Integral(interior, 
00102         (1.0 + 0.1*xi*exp(x))*(grad*v)*(grad*u) - f*v, quad);
00103 
00104       /* Define the Dirichlet BC */
00105       Expr h = new CellDiameterExpr();
00106       Expr bc = EssentialBC(east + west, v*u/h, quad);
00107 
00108       /* We can now set up the linear problem. This can be reused
00109        * for different parameter values. */
00110       LinearProblem prob(mesh, eqn, bc, v, u, vecType);
00111 
00112       /* make a projector for the exact solution. Just like the
00113        * problem, this can be reused for different parameter values. */
00114       DiscreteSpace ds(mesh, new Lagrange(1), vecType);
00115       L2Projector proj(ds, uEx);
00116 
00117       /* Get the solver and declare variables for the results */
00118       LinearSolver<double> solver = LinearSolverBuilder::createSolver("aztec-ml.xml");
00119       Expr soln;
00120       SolverState<double> state;
00121 
00122       /* Set up the sweep from xi=0 to xi=xiMax in nSteps steps. */
00123       int nSteps = 10;
00124       double xiMax = 2.0;
00125       
00126       /* Make an array in which to keep the observed errors */
00127       Array<double> err(nSteps);
00128 
00129       /* Do the sweep */
00130       for (int n=0; n<nSteps; n++)
00131       {
00132         /* Update the parameter value */
00133         double xiVal = xiMax*n/(nSteps - 1.0);
00134         xi.setParameterValue(xiVal);
00135         Out::root() << "step n=" << n << " of " << nSteps << " xi=" << xiVal;
00136 
00137         /* Solve the problem. The updated parameter value is automatically used. */
00138         state = prob.solve(solver, soln);
00139 
00140         TEUCHOS_TEST_FOR_EXCEPTION(state.finalState() != SolveConverged,
00141           std::runtime_error,
00142           "solve failed!");
00143 
00144         /* Project the exact solution onto a discrrete space for viz. The updated
00145          * parameter value is automatically used. */
00146         Expr uEx0 = proj.project();
00147 
00148         /* Write the approximate and exact solutions for viz */
00149         FieldWriter w = new VTKWriter("ParameterSweep-" + Teuchos::toString(n));
00150         w.addMesh(mesh);
00151         w.addField("u", new ExprFieldWrapper(soln[0]));
00152         w.addField("uEx", new ExprFieldWrapper(uEx0[0]));
00153         w.write();
00154 
00155         /* Compute the L2 norm of the error */
00156         err[n] = L2Norm(mesh, interior, soln-uEx, quad);
00157         Out::root() << " L2 error = " << err[n] << endl;
00158       } 
00159 
00160       /* The errors are O(h^2), so use that to set a tolerance */
00161       double hVal = 1.0/(nx-1.0);
00162       double fudge = 2.0;
00163       double tol = fudge*hVal*hVal;
00164 
00165       /* Find the max error over all parameter values */
00166       double maxErr = *std::max_element(err.begin(), err.end());
00167 
00168       /* Check the error */
00169       Sundance::passFailTest(maxErr, tol);
00170     }
00171   catch(std::exception& e)
00172     {
00173       Sundance::handleException(e);
00174     }
00175   Sundance::finalize(); 
00176   return Sundance::testStatus(); 
00177 }

Site Contact