|
Stratimikos Package Browser (Single Doxygen Collection)
Version of the Day
|
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", ¶mListFile, 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 }
1.7.6.1