SundanceProblemTesting.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 "SundanceProblemTesting.hpp"
00032 
00033 #include "SundanceMaximalCellFilter.hpp"
00034 #include "SundanceDimensionalCellFilter.hpp"
00035 #include "SundancePositionalCellPredicate.hpp"
00036 #include "SundanceMesh.hpp"
00037 #include "SundanceMeshSource.hpp"
00038 #include "SundanceMeshType.hpp"
00039 #include "SundanceBasicSimplicialMeshType.hpp"
00040 #include "SundancePartitionedLineMesher.hpp"
00041 #include "SundancePartitionedRectangleMesher.hpp"
00042 #include "PlayaEpetraVectorType.hpp"
00043 #include "PlayaLinearSolverBuilder.hpp"
00044 #include "SundanceGaussianQuadrature.hpp"
00045 #include "SundanceCoordExpr.hpp"
00046 #include "SundanceCellDiameterExpr.hpp"
00047 #include "SundanceLinearProblem.hpp"
00048 #include "SundanceIntegral.hpp"
00049 
00050 namespace Sundance
00051 {
00052 
00053 bool checkErrorNorms(
00054   const Mesh& mesh,
00055   const CellFilter& filter,
00056   const Expr& numSoln,
00057   const Expr& exactSoln,
00058   const QuadratureFamily& quad,
00059   double L2Tol,
00060   double H1SemiTol,
00061   double H1Tol)
00062 {
00063   Tabs tab;
00064   Tabs tab1;
00065   Expr df = numSoln - exactSoln;
00066 
00067   double L2Err = L2Norm(mesh, filter, df, quad);
00068   Out::root() << tab << "L2 norm check:" << std::endl
00069               << tab1 << setw(16) << setprecision(6) << L2Err 
00070               << " tol=" << setw(12) << L2Tol ;
00071   if (fabs(L2Err) > L2Tol) Out::root() << "   <==== FAIL!" << std::endl;
00072   else Out::root() << std::endl;
00073 
00074   double H1SemiErr = H1Seminorm(mesh, filter, df, quad);
00075   Out::root() << tab << "H1 seminorm check:" << std::endl
00076               << tab1 << setw(16) << setprecision(6) << H1SemiErr 
00077               << " tol=" << setw(12) << H1SemiTol ;
00078   if (fabs(H1SemiErr) > H1SemiTol) Out::root() << "   <==== FAIL!" << std::endl;
00079   else Out::root() << std::endl;
00080 
00081 
00082   double H1Err = H1Norm(mesh, filter, df, quad);
00083   Out::root() << tab << "H1 norm check:" << std::endl
00084               << tab1 << setw(16) << setprecision(6) << H1Err 
00085               << " tol=" << setw(12) << H1Tol;
00086   if (fabs(H1Err) > H1Tol) Out::root() << "   <==== FAIL!" << std::endl;
00087   else Out::root() << std::endl;
00088 
00089   return (fabs(L2Err) <= L2Tol) 
00090     && (fabs(H1SemiErr) <= H1SemiTol) 
00091     && (fabs(H1Err) <= H1Tol) ;
00092 }
00093 
00094 double fitPower(const Array<double>& h, const Array<double>& err)
00095 {
00096   Array<double> x(h.size());
00097   Array<double> y(h.size());
00098   double xBar = 0.0;
00099   double yBar = 0.0;
00100   for (int i=0; i<h.size(); i++)
00101   {
00102     x[i] = log(h[i]);
00103     y[i] = log(err[i]);
00104     xBar += x[i];
00105     yBar += y[i];
00106   }
00107 
00108   xBar /= h.size();
00109   yBar /= h.size();
00110   
00111   double u = 0.0;
00112   double v = 0.0;
00113   for (int i=0; i<h.size(); i++)
00114   {
00115     u += (x[i]-xBar)*(y[i]-yBar);
00116     v += pow(x[i]-xBar,2.0);
00117   }
00118 
00119   return u/v;
00120 }
00121 
00122 /* -------- LineDomain ----------------- */
00123 
00124 LineDomain::LineDomain(const Array<int>& nx)
00125   : a_(0.0), b_(1.0), nx_(nx), interior_(new MaximalCellFilter()),
00126     left_(), right_(), mesh_()
00127 {init();}
00128 
00129 
00130 LineDomain::LineDomain(double a, double b, const Array<int>& nx)
00131   : a_(a), b_(b), nx_(nx), interior_(new MaximalCellFilter()),
00132     left_(), right_(), mesh_()
00133 {init();}
00134 
00135 void LineDomain::init()
00136 {
00137   int np = MPIComm::world().getNProc();
00138   MeshType meshType = new BasicSimplicialMeshType();
00139   mesh_.resize(nx_.size());
00140   for (int i=0; i<nx_.size(); i++)
00141   {
00142     MeshSource mesher = new PartitionedLineMesher(a_, b_, np*nx_[i], meshType);
00143     mesh_[i] = mesher.getMesh();
00144   }
00145   
00146   CellFilter points = new DimensionalCellFilter(0);
00147   left_ = points.subset(new CoordinateValueCellPredicate(0,a_));
00148   right_ = points.subset(new CoordinateValueCellPredicate(0,b_));
00149 }
00150 
00151 /* -------- RectangleDomain ----------------- */
00152 
00153 RectangleDomain::RectangleDomain(const Array<int>& n)
00154   : ax_(0.0), bx_(1.0), nx_(n), 
00155     ay_(0.0), by_(1.0), ny_(n), 
00156     interior_(new MaximalCellFilter()),
00157     north_(), south_(), east_(), west_(),
00158     mesh_()
00159 {init();}
00160 
00161 RectangleDomain::RectangleDomain(
00162   double ax, double bx, const Array<int>& nx,
00163   double ay, double by, const Array<int>& ny
00164   )
00165   : ax_(ax), bx_(bx), nx_(nx), 
00166     ay_(ay), by_(by), ny_(ny), 
00167     interior_(new MaximalCellFilter()),
00168     north_(), south_(), east_(), west_(),
00169     mesh_()
00170 {init();}
00171 
00172 
00173 void RectangleDomain::init()
00174 {
00175   TEUCHOS_TEST_FOR_EXCEPT(nx_.size() != ny_.size());
00176   int np = MPIComm::world().getNProc();
00177   int npx = -1;
00178   int npy = -1;
00179 
00180   PartitionedRectangleMesher::balanceXY(np, &npx, &npy);
00181   TEUCHOS_TEST_FOR_EXCEPT(npx < 1);
00182   TEUCHOS_TEST_FOR_EXCEPT(npy < 1);
00183   TEUCHOS_TEST_FOR_EXCEPT(npx * npy != np);
00184 
00185   MeshType meshType = new BasicSimplicialMeshType();
00186   mesh_.resize(nx_.size());
00187 
00188   for (int i=0; i<nx_.size(); i++)
00189   {
00190     MeshSource mesher 
00191       = new PartitionedRectangleMesher(
00192         ax_, bx_, nx_[i], npx,
00193         ay_, by_, ny_[i], npy,
00194         meshType);
00195     mesh_[i] = mesher.getMesh();
00196   }
00197   
00198   CellFilter edges = new DimensionalCellFilter(1);
00199   north_ = edges.subset(new CoordinateValueCellPredicate(1,by_));
00200   south_ = edges.subset(new CoordinateValueCellPredicate(1,ay_));
00201   west_ = edges.subset(new CoordinateValueCellPredicate(0,ax_));
00202   east_ = edges.subset(new CoordinateValueCellPredicate(0,bx_));
00203 }
00204 
00205 
00206 
00207 
00208 
00209 /* -------- norm calculators ----------------- */
00210 
00211 Array<double> L2NormCalculator::computeNorms(
00212   const ForwardProblemTestBase* prob,
00213   int meshIndex,
00214   const Expr& numSoln, const Expr& exactSoln) const
00215 {
00216   Expr errFunc = (numSoln - exactSoln).flatten();
00217 
00218   Mesh mesh = prob->getMesh(meshIndex);
00219   CellFilter interior = prob->interior();
00220 
00221   Array<int> p = prob->pExpected();
00222   TEUCHOS_TEST_FOR_EXCEPTION(p.size() != errFunc.size(),
00223     std::runtime_error,
00224     "size mismatch between array of expected orders (p=" << p << ") and "
00225     "array of solutions: " << errFunc.size());
00226  
00227   Array<double> rtn(p.size());
00228   for (int i=0; i<errFunc.size(); i++)
00229   {
00230     QuadratureFamily quad = new GaussianQuadrature(2*p[i]);
00231     double L2Err = L2Norm(mesh, interior, errFunc[i], quad);
00232     rtn[i] = L2Err;
00233   }  
00234 
00235   return rtn;
00236 }
00237   
00238 
00239 Array<LPTestSpec> LPTestBase::specs() const
00240 {
00241   return tuple(
00242     LPTestSpec("amesos.xml", 1.0e-10, makeSet<int>(1)),
00243     LPTestSpec("aztec-ifpack.xml", 1.0e-10),
00244     LPTestSpec("aztec-ml.xml", 1.0e-10),
00245     LPTestSpec("belos-ifpack.xml", 1.0e-8),
00246     LPTestSpec("belos-ml.xml", 1.0e-10)
00247     );
00248 }
00249 
00250 /** \relates LPTestSpec */
00251 std::ostream& operator<<(std::ostream& os, const LPTestSpec& spec)
00252 {
00253   os << "LPTestSpec(tol=" << spec.tol() << ", solver=" << spec.solverFile()
00254      << std::endl;
00255   return os;
00256 }
00257 
00258 
00259 
00260 
00261 bool LPTestSuite::run() const 
00262 {
00263   int np = MPIComm::world().getNProc();
00264 
00265   bool allOK = true;
00266 
00267   for (int i=0; i<tests_.size(); i++)
00268   {
00269     Tabs tab(0);
00270     Array<LPTestSpec> specs = tests_[i]->specs();
00271     for (int j=0; j<specs.size(); j++)
00272     {
00273       if (specs[j].nProcIsAllowed(np))
00274       {
00275         Out::root() << std::endl;
00276         Out::root() << std::endl;
00277         Out::root() << std::endl;
00278         Out::root() << tab 
00279                     << "-------------------------------------" 
00280           "-------------------------------------" 
00281                     << std::endl;
00282         Out::root() << tab << "running test " << tests_[i]->name()
00283                     << " with spec " << specs[j] << std::endl;
00284         Out::root() << tab 
00285                     << "-------------------------------------" 
00286           "-------------------------------------" 
00287                     << std::endl;
00288 
00289         std::string solverFile = specs[j].solverFile();
00290         double tol = specs[j].tol();
00291         bool pass = tests_[i]->run(solverFile, tol);
00292         allOK = pass && allOK;
00293       }
00294       else
00295       {
00296         Out::root() << tab << "skipping test " << tests_[i]->name()
00297                     << " with spec=" << specs[j] << std::endl;
00298       }
00299     }
00300     Out::root() << std::endl;
00301     Out::root() << std::endl;
00302   }
00303   return allOK;
00304 }
00305 
00306 
00307 LPTestSuite::LPTestSuite()
00308   : tests_(), testSpecs_() {}
00309 
00310 
00311 void LPTestSuite::registerTest(const RCP<LPTestBase>& test) 
00312 {
00313   tests_.append(test);
00314 }
00315 
00316 VectorType<double> ForwardProblemTestBase::vecType() const
00317 {
00318   return new EpetraVectorType();
00319 }
00320 
00321 Expr ForwardProblemTestBase::coord(int d) const 
00322 {
00323   TEUCHOS_TEST_FOR_EXCEPT(d<0 || d>2);
00324   return new CoordExpr(d);
00325 }
00326 
00327 double ForwardProblemTestBase::cellSize(int i) const 
00328 {
00329   Expr h = new CellDiameterExpr();
00330   Expr hExpr = Integral(interior(), h, new GaussianQuadrature(1));
00331   Expr AExpr = Integral(interior(), 1.0, new GaussianQuadrature(1));
00332   
00333   double area = evaluateIntegral(getMesh(i), AExpr);
00334   double hMean = evaluateIntegral(getMesh(i), hExpr)/area;
00335 
00336   return hMean;
00337 }
00338 
00339 RCP<ErrNormCalculatorBase> ForwardProblemTestBase::normCalculator() const
00340 {
00341   return rcp(new L2NormCalculator());
00342 
00343 }
00344 bool ForwardProblemTestBase::run(const std::string& solverFile, 
00345   double tol) const
00346 {
00347   if (numMeshes()==1) return runSingleTest(solverFile, tol);
00348   else return runTestSequence(solverFile, tol);
00349 }
00350 
00351 
00352 bool ForwardProblemTestBase::runTestSequence(const std::string& solverFile, 
00353   const double& pTol) const
00354 {
00355   Tabs tab(0);
00356   Out::root() << tab << "Running test sequence " << name() << std::endl;
00357 
00358   LinearSolver<double> solver 
00359     = LinearSolverBuilder::createSolver(solverFile);
00360 
00361   Expr exact = exactSoln();
00362 
00363   Array<double> hList(numMeshes());
00364   Array<Array<double> > errList(numMeshes());
00365 
00366   for (int i=0; i<numMeshes(); i++)
00367   {
00368     Tabs tab1;
00369     Out::root() << tab1 << "running on mesh #" << i << std::endl;
00370     Expr soln;
00371     bool solveOK = solve(getMesh(i), solver, soln);
00372     if (!solveOK) return false;
00373 
00374     postRunCallback(i, getMesh(i), solverFile, soln);
00375 
00376     double h = cellSize(i);
00377     Array<double> err = normCalculator()->computeNorms(
00378       this, i, soln, exact);
00379     hList[i] = h;
00380     errList[i] = err;
00381   }
00382 
00383   bool allPass = true;
00384   Out::root() << tab << "Error results: " << std::endl;
00385   for (int f=0; f < pExpected().size(); f++)
00386   {
00387     Tabs tab1;
00388     Out::root() << tab1 << "Variable #" << f << std::endl; 
00389     Out::root() << std::endl << tab1 << "Error norm versus h" << std::endl;
00390     Array<double> err;
00391     for (int i=0; i<numMeshes(); i++)
00392     {
00393       Tabs tab2;
00394       Out::root() << tab2 << setw(20) << setprecision(5) << hList[i] 
00395                   << " " << setw(20) << setprecision(5) << errList[i][f] 
00396                   << std::endl;
00397       err.append(errList[i][f]); 
00398     }
00399     
00400     double p = fitPower(hList, err);
00401     Out::root() << tab << "Measured exponent: " << p << std::endl;
00402     Out::root() << tab << "Expected exponent: " << pExpected()[f] << std::endl;
00403     double pErr = fabs(p - pExpected()[f]) ;
00404     Out::root() << tab << "Difference: " << setw(12) << pErr
00405                 << " Tolerance: " << setw(12) << pTol;
00406     bool pass = pErr <= pTol;
00407     if (!pass) Out::root() << "  <==== FAIL!";
00408     Out::root() << std::endl;
00409     allPass = allPass && pass;
00410   }
00411 
00412   return allPass;
00413 }
00414 
00415 
00416 
00417 bool ForwardProblemTestBase::runSingleTest(const std::string& solverFile, 
00418   const double& tol) const
00419 {
00420   Tabs tab(0);
00421 
00422   LinearSolver<double> solver 
00423     = LinearSolverBuilder::createSolver(solverFile);
00424 
00425   Expr exact = exactSoln();
00426 
00427   Expr soln;
00428   bool solveOK = solve(getMesh(0), solver, soln);
00429   if (!solveOK) return false;
00430   
00431   Array<double> err = normCalculator()->computeNorms(this, 0, 
00432     soln, exact);
00433   
00434   for (int i=0; i<err.size(); i++)
00435   {
00436     Out::root() << tab << setw(20) << setprecision(5) << err[i] 
00437                 << " " << setw(20) << setprecision(5) << tol 
00438               << std::endl;
00439   }
00440   return err[0] <= tol;
00441 }
00442 
00443 bool LPTestBase::solve(const Mesh& mesh,
00444   const LinearSolver<double>& solver,
00445   Expr& soln) const
00446 {
00447   Tabs tab(0);
00448   LinearProblem::solveFailureIsFatal() = false;
00449   SolverState<double> state = prob(mesh).solve(solver, soln);
00450 
00451   bool converged = (state.finalState() == SolveConverged) ;
00452   if (!converged)
00453   {
00454     Out::root() << tab << "solve failed to converge!" << std::endl;
00455     Tabs tab1;
00456     Out::root() << tab1 << "state = " << state << std::endl;
00457   }
00458   return converged;
00459 }
00460 
00461 LP1DTestBase::LP1DTestBase(const Array<int>& nx)
00462   : domain_(nx) {}
00463 
00464 LP1DTestBase::LP1DTestBase(double a, double b, const Array<int>& nx)
00465   : domain_(a, b, nx) {}
00466 
00467 LPRectTestBase::LPRectTestBase(const Array<int>& n)
00468   : domain_(n) {}
00469 }

Site Contact