00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
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 
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 
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 
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 
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 }