Stratimikos Package Browser (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
ForwardSolverAsPreconditioner.cpp
Go to the documentation of this file.
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //         Stratimikos: Thyra-based strategies for linear solvers
00005 //                Copyright (2006) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
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 Roscoe A. Bartlett (rabartl@sandia.gov)
00038 //
00039 // ***********************************************************************
00040 // @HEADER
00041 
00042 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
00043 #include "Thyra_LinearOpWithSolveFactoryHelpers.hpp"
00044 #include "Thyra_PreconditionerFactoryHelpers.hpp"
00045 #include "Thyra_DefaultInverseLinearOp.hpp"
00046 #include "Thyra_DefaultMultipliedLinearOp.hpp"
00047 #include "Thyra_EpetraThyraWrappers.hpp"
00048 #include "Thyra_EpetraLinearOp.hpp"
00049 #include "Thyra_get_Epetra_Operator.hpp"
00050 #include "Thyra_TestingTools.hpp"
00051 #include "Thyra_LinearOpTester.hpp"
00052 #include "EpetraExt_CrsMatrixIn.h"
00053 #include "Epetra_CrsMatrix.h"
00054 #include "Teuchos_GlobalMPISession.hpp"
00055 #include "Teuchos_VerboseObject.hpp"
00056 #include "Teuchos_XMLParameterListHelpers.hpp"
00057 #include "Teuchos_CommandLineProcessor.hpp"
00058 #include "Teuchos_StandardCatchMacros.hpp"
00059 #include "Teuchos_TimeMonitor.hpp"
00060 #ifdef HAVE_MPI
00061 #  include "Epetra_MpiComm.h"
00062 #else
00063 #  include "Epetra_SerialComm.h"
00064 #endif
00065 
00066 
00075 namespace {
00076 
00077 
00078 // Read a Epetra_CrsMatrix from a Matrix market file
00079 Teuchos::RCP<Epetra_CrsMatrix>
00080 readEpetraCrsMatrixFromMatrixMarket(
00081   const std::string fileName, const Epetra_Comm &comm
00082   )
00083 {
00084   Epetra_CrsMatrix *A = 0;
00085   TEUCHOS_TEST_FOR_EXCEPTION(
00086     0!=EpetraExt::MatrixMarketFileToCrsMatrix( fileName.c_str(), comm, A ),
00087     std::runtime_error,
00088     "Error, could not read matrix file \""<<fileName<<"\"!"
00089     );
00090   return Teuchos::rcp(A);
00091 }
00092 
00093 
00094 // Read an Epetra_CrsMatrix in as a wrapped Thyra::EpetraLinearOp object
00095 Teuchos::RCP<const Thyra::LinearOpBase<double> >
00096 readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
00097   const std::string fileName, const Epetra_Comm &comm,
00098   const std::string &label
00099   )
00100 {
00101   return Thyra::epetraLinearOp(
00102     readEpetraCrsMatrixFromMatrixMarket(fileName,comm),label
00103     );
00104 }
00105 
00106 
00107 } // namespace
00108 
00109 
00110 int main(int argc, char* argv[])
00111 {
00112 
00113   using Teuchos::describe;
00114   using Teuchos::rcp;
00115   using Teuchos::rcp_dynamic_cast;
00116   using Teuchos::rcp_const_cast;
00117   using Teuchos::RCP;
00118   using Teuchos::CommandLineProcessor;
00119   using Teuchos::ParameterList;
00120   using Teuchos::sublist;
00121   using Teuchos::getParametersFromXmlFile;
00122   typedef ParameterList::PrintOptions PLPrintOptions;
00123   using Thyra::inverse;
00124   using Thyra::initializePreconditionedOp;
00125   using Thyra::initializeOp;
00126   using Thyra::unspecifiedPrec;
00127   using Thyra::solve;
00128   typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr;
00129   typedef RCP<Thyra::VectorBase<double> > VectorPtr;
00130 
00131   bool success = true;
00132   bool verbose = true;
00133 
00134   Teuchos::GlobalMPISession mpiSession(&argc,&argv);
00135 
00136   Teuchos::RCP<Teuchos::FancyOStream>
00137     out = Teuchos::VerboseObjectBase::getDefaultOStream();
00138 
00139   try {
00140 
00141     //
00142     // Read in options from the command line
00143     //
00144 
00145     CommandLineProcessor clp(false); // Don't throw exceptions
00146 
00147     const int numVerbLevels = 6;
00148     Teuchos::EVerbosityLevel
00149       verbLevelValues[] =
00150       {
00151         Teuchos::VERB_DEFAULT, Teuchos::VERB_NONE,
00152         Teuchos::VERB_LOW, Teuchos::VERB_MEDIUM,
00153         Teuchos::VERB_HIGH, Teuchos::VERB_EXTREME
00154       };
00155     const char*
00156       verbLevelNames[] =
00157       { "default", "none", "low", "medium", "high", "extreme" };
00158 
00159     Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM;
00160     clp.setOption( "verb-level", &verbLevel,
00161       numVerbLevels, verbLevelValues, verbLevelNames,
00162       "Verbosity level used for all objects."
00163       );
00164 
00165     std::string matrixFile = ".";
00166     clp.setOption( "matrix-file", &matrixFile,
00167       "Matrix file."
00168       );
00169 
00170     std::string paramListFile = "";
00171     clp.setOption( "param-list-file", &paramListFile,
00172       "Parameter list for preconditioner and solver blocks."
00173       );
00174 
00175     bool showParams = false;
00176     clp.setOption( "show-params", "no-show-params", &showParams,
00177       "Show the parameter list or not."
00178       );
00179 
00180     bool testPrecIsLinearOp = true;
00181     clp.setOption( "test-prec-is-linear-op", "test-prec-is-linear-op", &testPrecIsLinearOp,
00182       "Test if the preconditioner is a linear operator or not."
00183       );
00184 
00185     double solveTol = 1e-8;
00186     clp.setOption( "solve-tol", &solveTol,
00187       "Tolerance for the solution to determine success or failure!"
00188       );
00189 
00190     clp.setDocString(
00191       "This example program shows how to use one linear solver (e.g. AztecOO)\n"
00192       "as a preconditioner for another iterative solver (e.g. Belos).\n"
00193       );
00194 
00195     // Note: Use --help on the command line to see the above documentation
00196 
00197     CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv);
00198     if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return;
00199 
00200 
00201     //
00202     *out << "\nA) Reading in the matrix ...\n";
00203     //
00204 
00205 #ifdef HAVE_MPI
00206     Epetra_MpiComm comm(MPI_COMM_WORLD);
00207 #else
00208     Epetra_SerialComm comm;
00209 #endif
00210 
00211     const LinearOpPtr A = readEpetraCrsMatrixFromMatrixMarketAsLinearOp(
00212       matrixFile, comm, "A");
00213     *out << "\nA = " << describe(*A,verbLevel) << "\n";
00214 
00215     const RCP<ParameterList> paramList = getParametersFromXmlFile(paramListFile);
00216     if (showParams) {
00217       *out << "\nRead in parameter list:\n\n";
00218       paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
00219     }
00220 
00221     //
00222     *out << "\nB) Get the preconditioner as a forward solver\n";
00223     //
00224 
00225     const RCP<ParameterList> precParamList = sublist(paramList, "Preconditioner Solver");
00226     Stratimikos::DefaultLinearSolverBuilder precSolverBuilder;
00227     precSolverBuilder.setParameterList(precParamList);
00228     const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > precSolverStrategy
00229       = createLinearSolveStrategy(precSolverBuilder);
00230     //precSolverStrategy->setVerbLevel(verbLevel);
00231 
00232     const LinearOpPtr A_inv_prec = inverse<double>(*precSolverStrategy, A,
00233       Thyra::SUPPORT_SOLVE_FORWARD_ONLY,
00234       Teuchos::null, // Use internal solve criteria
00235       Thyra::IGNORE_SOLVE_FAILURE // Ignore solve failures since this is just a prec
00236       );
00237     *out << "\nA_inv_prec = " << describe(*A_inv_prec, verbLevel) << "\n";
00238 
00239     if (testPrecIsLinearOp) {
00240       *out << "\nTest that the preconditioner A_inv_prec is indeed a linear operator.\n";
00241       Thyra::LinearOpTester<double> linearOpTester;
00242       linearOpTester.check_adjoint(false);
00243       const bool linearOpCheck = linearOpTester.check(*A_inv_prec, out.ptr());
00244       if (!linearOpCheck) { success = false; }
00245     }
00246 
00247     //
00248     *out << "\nC) Create the forward solver using the created preconditioner ...\n";
00249     //
00250 
00251     const RCP<ParameterList> fwdSolverParamList = sublist(paramList, "Forward Solver");
00252     Stratimikos::DefaultLinearSolverBuilder fwdSolverSolverBuilder;
00253     fwdSolverSolverBuilder.setParameterList(fwdSolverParamList);
00254     const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > fwdSolverSolverStrategy
00255       = createLinearSolveStrategy(fwdSolverSolverBuilder);
00256 
00257     const RCP<Thyra::LinearOpWithSolveBase<double> >
00258       A_lows = fwdSolverSolverStrategy->createOp();
00259 
00260     initializePreconditionedOp<double>( *fwdSolverSolverStrategy, A,
00261         unspecifiedPrec(A_inv_prec), A_lows.ptr());
00262     //A_lows->setVerbLevel(verbLevel);
00263     *out << "\nA_lows = " << describe(*A_lows, verbLevel) << "\n";
00264 
00265     //
00266     *out << "\nD) Solve the linear system for a random RHS ...\n";
00267     //
00268 
00269     VectorPtr x = createMember(A->domain());
00270     VectorPtr b = createMember(A->range());
00271     Thyra::randomize(-1.0, +1.0, b.ptr());
00272     Thyra::assign(x.ptr(), 0.0); // Must give an initial guess!
00273 
00274     Thyra::SolveStatus<double>
00275       solveStatus = solve<double>( *A_lows, Thyra::NOTRANS, *b, x.ptr() );
00276 
00277     *out << "\nSolve status:\n" << solveStatus;
00278 
00279     *out << "\nSolution ||x|| = " << Thyra::norm(*x) << "\n";
00280 
00281     if(showParams) {
00282       *out << "\nParameter list after use:\n\n";
00283       paramList->print(*out, PLPrintOptions().indent(2).showTypes(true));
00284     }
00285 
00286     //
00287     *out << "\nF) Checking the error in the solution of r=b-A*x ...\n";
00288     //
00289 
00290     VectorPtr Ax = Thyra::createMember(b->space());
00291     Thyra::apply( *A, Thyra::NOTRANS, *x, Ax.ptr() );
00292     VectorPtr r = Thyra::createMember(b->space());
00293     Thyra::V_VmV<double>(r.ptr(), *b, *Ax);
00294 
00295     double
00296       Ax_nrm = Thyra::norm(*Ax),
00297       r_nrm = Thyra::norm(*r),
00298       b_nrm = Thyra::norm(*b),
00299       r_nrm_over_b_nrm = r_nrm / b_nrm;
00300 
00301     bool resid_tol_check = ( r_nrm_over_b_nrm <= solveTol );
00302     if(!resid_tol_check) success = false;
00303 
00304     *out
00305       << "\n||A*x|| = " << Ax_nrm << "\n";
00306 
00307     *out
00308       << "\n||A*x-b||/||b|| = " << r_nrm << "/" << b_nrm
00309       << " = " << r_nrm_over_b_nrm << " <= " << solveTol
00310       << " : " << Thyra::passfail(resid_tol_check) << "\n";
00311 
00312     Teuchos::TimeMonitor::summarize(*out<<"\n");
00313   }
00314   TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success)
00315 
00316   if (verbose) {
00317     if(success)  *out << "\nCongratulations! All of the tests checked out!\n";
00318     else         *out << "\nOh no! At least one of the tests failed!\n";
00319   }
00320 
00321   return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
00322 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines