int main(int argc, char** argv) { try { const double pi = 4.0*atan(1.0); double lambda = 1.25*pi*pi; int nx = 32; int nt = 10; double tFinal = 1.0/lambda; Sundance::setOption("nx", nx, "Number of elements"); Sundance::setOption("nt", nt, "Number of timesteps"); Sundance::setOption("tFinal", tFinal, "Final time"); Sundance::init(&argc, &argv); /* Creation of vector type */ VectorType<double> vecType = new EpetraVectorType(); /* Set up mesh */ MeshType meshType = new BasicSimplicialMeshType(); MeshSource meshSrc = new PartitionedRectangleMesher( 0.0, 1.0, nx, 0.0, 1.0, nx, meshType); Mesh mesh = meshSrc.getMesh(); /* * Specification of cell filters */ CellFilter interior = new MaximalCellFilter(); CellFilter edges = new DimensionalCellFilter(1); CellFilter west = edges.coordSubset(0, 0.0); CellFilter east = edges.coordSubset(0, 1.0); CellFilter south = edges.coordSubset(1, 0.0); CellFilter north = edges.coordSubset(1, 1.0); /* set up test and unknown functions */ BasisFamily basis = new Lagrange(1); Expr u = new UnknownFunction(basis, "u"); Expr v = new TestFunction(basis, "v"); /* set up differential operators */ Expr grad = gradient(2); Expr x = new CoordExpr(0); Expr y = new CoordExpr(1); Expr t = new Sundance::Parameter(0.0); Expr tPrev = new Sundance::Parameter(0.0); DiscreteSpace discSpace(mesh, basis, vecType); Expr uExact = cos(0.5*pi*y)*sin(pi*x)*exp(-lambda*t); L2Projector proj(discSpace, uExact); Expr uPrev = proj.project(); /* * We need a quadrature rule for doing the integrations */ QuadratureFamily quad = new GaussianQuadrature(2); double deltaT = tFinal/nt; Expr gWest = -pi*exp(-lambda*t)*cos(0.5*pi*y); Expr gWestPrev = -pi*exp(-lambda*tPrev)*cos(0.5*pi*y); /* Create the weak form */ Expr eqn = Integral(interior, v*(u-uPrev)/deltaT + 0.5*(grad*v)*(grad*u + grad*uPrev), quad) + Integral(west, -0.5*v*(gWest+gWestPrev), quad); Expr bc = EssentialBC(east + north, v*u, quad); LinearProblem prob(mesh, eqn, bc, v, u, vecType); LinearSolver<double> solver = LinearSolverBuilder::createSolver("amesos.xml"); FieldWriter w0 = new VTKWriter("TransientHeat2D-0"); w0.addMesh(mesh); w0.addField("T", new ExprFieldWrapper(uPrev[0])); w0.write(); for (int i=0; i<nt; i++) { t.setParameterValue((i+1)*deltaT); tPrev.setParameterValue(i*deltaT); Out::root() << "t=" << (i+1)*deltaT << endl; Expr uNext = prob.solve(solver); ostringstream oss; oss << "TransientHeat2D-" << i+1; FieldWriter w = new VTKWriter(oss.str()); w.addMesh(mesh); w.addField("T", new ExprFieldWrapper(uNext[0])); w.write(); updateDiscreteFunction(uNext, uPrev); } double err = L2Norm(mesh, interior, uExact-uPrev, quad); Out::root() << "error norm=" << err << endl; double h = 1.0/(nx-1.0); double tol = 0.1*(pow(h,2.0) + pow(lambda*deltaT, 2.0)); Out::root() << "tol=" << tol << endl; Sundance::passFailTest(err, tol); } catch(std::exception& e) { Sundance::handleException(e); } Sundance::finalize(); return Sundance::testStatus(); }
int main(int argc, char** argv) { try { Sundance::init(&argc, &argv); /* We will do our linear algebra using Epetra */ VectorType<double> vecType = new EpetraVectorType(); /* Create a mesh. It will be of type BasisSimplicialMesh, and will * be built using a PartitionedLineMesher. */ MeshType meshType = new BasicSimplicialMeshType(); int nx = 32; MeshSource mesher = new PartitionedRectangleMesher( 0.0, 1.0, nx, 0.0, 1.0, nx, 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(); /* Make cell filters for the east and west boundaries */ CellFilter edges = new DimensionalCellFilter(1); CellFilter west = edges.coordSubset(0, 0.0); CellFilter east = edges.coordSubset(0, 1.0); /* Create unknown and test functions */ Expr u = new UnknownFunction(new Lagrange(1), "u"); Expr v = new TestFunction(new Lagrange(1), "v"); /* Create differential operator and coordinate function */ Expr x = new CoordExpr(0); Expr grad = gradient(1); /* We need a quadrature rule for doing the integrations */ QuadratureFamily quad = new GaussianQuadrature(4); /* Define the parameter */ Expr xi = new Sundance::Parameter(0.0); /* Construct a forcing term to provide an exact solution for * validation purposes. This will involve the parameter. */ Expr uEx = x*(1.0-x)*(1.0+xi*exp(x)); Expr f = -(-20 - exp(x)*xi*(1 + 32*x + 10*x*x + exp(x)*(-1 + 2*x*(2 + x))*xi))/10.0; /* Define the weak form, using the parameter expression. This weak form * can be used for all parameter values. */ Expr eqn = Integral(interior, (1.0 + 0.1*xi*exp(x))*(grad*v)*(grad*u) - f*v, quad); /* Define the Dirichlet BC */ Expr h = new CellDiameterExpr(); Expr bc = EssentialBC(east + west, v*u/h, quad); /* We can now set up the linear problem. This can be reused * for different parameter values. */ LinearProblem prob(mesh, eqn, bc, v, u, vecType); /* make a projector for the exact solution. Just like the * problem, this can be reused for different parameter values. */ DiscreteSpace ds(mesh, new Lagrange(1), vecType); L2Projector proj(ds, uEx); /* Get the solver and declare variables for the results */ LinearSolver<double> solver = LinearSolverBuilder::createSolver("aztec-ml.xml"); Expr soln; SolverState<double> state; /* Set up the sweep from xi=0 to xi=xiMax in nSteps steps. */ int nSteps = 10; double xiMax = 2.0; /* Make an array in which to keep the observed errors */ Array<double> err(nSteps); /* Do the sweep */ for (int n=0; n<nSteps; n++) { /* Update the parameter value */ double xiVal = xiMax*n/(nSteps - 1.0); xi.setParameterValue(xiVal); Out::root() << "step n=" << n << " of " << nSteps << " xi=" << xiVal; /* Solve the problem. The updated parameter value is automatically used. */ state = prob.solve(solver, soln); TEUCHOS_TEST_FOR_EXCEPTION(state.finalState() != SolveConverged, std::runtime_error, "solve failed!"); /* Project the exact solution onto a discrrete space for viz. The updated * parameter value is automatically used. */ Expr uEx0 = proj.project(); /* Write the approximate and exact solutions for viz */ FieldWriter w = new VTKWriter("ParameterSweep-" + Teuchos::toString(n)); w.addMesh(mesh); w.addField("u", new ExprFieldWrapper(soln[0])); w.addField("uEx", new ExprFieldWrapper(uEx0[0])); w.write(); /* Compute the L2 norm of the error */ err[n] = L2Norm(mesh, interior, soln-uEx, quad); Out::root() << " L2 error = " << err[n] << endl; } /* The errors are O(h^2), so use that to set a tolerance */ double hVal = 1.0/(nx-1.0); double fudge = 2.0; double tol = fudge*hVal*hVal; /* Find the max error over all parameter values */ double maxErr = *std::max_element(err.begin(), err.end()); /* Check the error */ Sundance::passFailTest(maxErr, tol); } catch(std::exception& e) { Sundance::handleException(e); } Sundance::finalize(); return Sundance::testStatus(); }