void BrentsLineSearch<Scalar>::setParameterList( RCP<ParameterList> const& paramList ) { typedef ScalarTraits<Scalar> ST; namespace BLSU = BrentsLineSearchUtils; using Teuchos::sublist; paramList->validateParametersAndSetDefaults(*this->getValidParameters()); bracket_.setParameterList(sublist(paramList, BLSU::bracket_name, true)); brentsMin_.setParameterList(sublist(paramList, BLSU::minimize_name, true)); setMyParamList(paramList); }
void setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist) { using Teuchos::ParameterList; using Teuchos::parameterList; using Teuchos::RCP; using Teuchos::sublist; RCP<ParameterList> params = plist.is_null() ? parameterList (*getValidParameters ()) : plist; nodeTsqr_->setParameterList (sublist (params, "NodeTsqr")); distTsqr_->setParameterList (sublist (params, "DistTsqr")); this->setMyParamList (params); }
void LSQRSolMgr<ScalarType,MV,OP,false>:: setParameters (const Teuchos::RCP<Teuchos::ParameterList> ¶ms) { using Teuchos::isParameterType; using Teuchos::getParameter; using Teuchos::null; using Teuchos::ParameterList; using Teuchos::parameterList; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcpFromRef; using Teuchos::Time; using Teuchos::TimeMonitor; using Teuchos::Exceptions::InvalidParameter; using Teuchos::Exceptions::InvalidParameterName; using Teuchos::Exceptions::InvalidParameterType; TEUCHOS_TEST_FOR_EXCEPTION(params.is_null(), std::invalid_argument, "Belos::LSQRSolMgr::setParameters: " "the input ParameterList is null."); RCP<const ParameterList> defaultParams = getValidParameters (); params->validateParametersAndSetDefaults (*defaultParams); // At this point, params is a valid parameter list with defaults // filled in. Now we can "commit" it to our instance's parameter // list. params_ = params; // Get the damping (a.k.a. regularization) parameter lambda. lambda_ = params->get<MagnitudeType> ("Lambda"); // Get the maximum number of iterations. maxIters_ = params->get<int>("Maximum Iterations"); // (Re)set the timer label. { const std::string newLabel = params->get<std::string>("Timer Label"); // Update parameter in our list and solver timer if (newLabel != label_) { label_ = newLabel; } #ifdef BELOS_TEUCHOS_TIME_MONITOR std::string newSolveLabel = label_ + ": LSQRSolMgr total solve time"; if (timerSolve_.is_null()) { // Ask TimeMonitor for a new timer. timerSolve_ = TimeMonitor::getNewCounter (newSolveLabel); } else { // We've already created a timer, but we may have changed its // label. If we did change its name, then we have to forget // about the old timer and create a new one with a different // name. This is because Teuchos::Time doesn't give you a way // to change a timer's name, once you've created it. We assume // that if the user changed the timer's label, then the user // wants to reset the timer's results. const std::string oldSolveLabel = timerSolve_->name (); if (oldSolveLabel != newSolveLabel) { // Tell TimeMonitor to forget about the old timer. // TimeMonitor lets you clear timers by name. TimeMonitor::clearCounter (oldSolveLabel); timerSolve_ = TimeMonitor::getNewCounter (newSolveLabel); } } #endif // BELOS_TEUCHOS_TIME_MONITOR } // Check for a change in verbosity level { int newVerbosity = 0; // ParameterList gets confused sometimes about enums. This // ensures that no matter how "Verbosity" was stored -- either an // an int, or as a Belos::MsgType enum, we will be able to extract // it. If it was stored as some other type, we let the exception // through. try { newVerbosity = params->get<Belos::MsgType> ("Verbosity"); } catch (Teuchos::Exceptions::InvalidParameterType&) { newVerbosity = params->get<int> ("Verbosity"); } if (newVerbosity != verbosity_) { verbosity_ = newVerbosity; } } // (Re)set the output style. outputStyle_ = params->get<int> ("Output Style"); // Get the output stream for the output manager. // // In case the output stream can't be read back in, we default to // stdout (std::cout), just to ensure reasonable behavior. { outputStream_ = params->get<RCP<std::ostream> > ("Output Stream"); // We assume that a null output stream indicates that the user // doesn't want to print anything, so we replace it with a "black // hole" stream that prints nothing sent to it. (We can't use a // null output stream, since the output manager always sends // things it wants to print to the output stream.) if (outputStream_.is_null()) outputStream_ = rcp (new Teuchos::oblackholestream); } // Get the frequency of solver output. (For example, -1 means // "never," 1 means "every iteration.") outputFreq_ = params->get<int> ("Output Frequency"); // Create output manager if we need to, using the verbosity level // and output stream that we fetched above. We do this here because // instantiating an OrthoManager using OrthoManagerFactory requires // a valid OutputManager. if (printer_.is_null()) { printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_)); } else { printer_->setVerbosity (verbosity_); printer_->setOStream (outputStream_); } // Check if the orthogonalization changed, or if we need to // initialize it. typedef OrthoManagerFactory<ScalarType, MV, OP> factory_type; factory_type factory; bool mustMakeOrtho = false; { std::string tempOrthoType; try { tempOrthoType = params_->get<std::string> ("Orthogonalization"); } catch (InvalidParameterName&) { tempOrthoType = orthoType_; } if (ortho_.is_null() || tempOrthoType != orthoType_) { mustMakeOrtho = true; // Ensure that the specified orthogonalization type is valid. if (! factory.isValidName (tempOrthoType)) { std::ostringstream os; os << "Belos::LSQRSolMgr: Invalid orthogonalization name \"" << tempOrthoType << "\". The following are valid options " << "for the \"Orthogonalization\" name parameter: "; factory.printValidNames (os); TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, os.str()); } orthoType_ = tempOrthoType; // The name is valid, so accept it. params_->set ("Orthogonalization", orthoType_); } } // Get any parameters for the orthogonalization ("Orthogonalization // Parameters"). If not supplied, the orthogonalization manager // factory will supply default values. // // NOTE (mfh 21 Oct 2011) For the sake of backwards compatibility, // if params has an "Orthogonalization Constant" parameter and the // DGKS orthogonalization manager is to be used, the value of this // parameter will override DGKS's "depTol" parameter. // // Users must supply the orthogonalization manager parameters as a // sublist (supplying it as an RCP<ParameterList> would make the // resulting parameter list not serializable). RCP<ParameterList> orthoParams; { // The nonmember function returns an RCP<ParameterList>, // which is what we want here. using Teuchos::sublist; // Abbreviation to avoid typos. const std::string paramName ("Orthogonalization Parameters"); try { orthoParams = sublist (params_, paramName, true); } catch (InvalidParameter&) { // We didn't get the parameter list from params, so get a // default parameter list from the OrthoManagerFactory. // Modify params_ so that it has the default parameter list, // and set orthoParams to ensure it's a sublist of params_ // (and not just a copy of one). params_->set (paramName, factory.getDefaultParameters (orthoType_)); orthoParams = sublist (params_, paramName, true); } } TEUCHOS_TEST_FOR_EXCEPTION(orthoParams.is_null(), std::logic_error, "Failed to get orthogonalization parameters. " "Please report this bug to the Belos developers."); // If we need to, instantiate a new MatOrthoManager subclass // instance corresponding to the desired orthogonalization method. // We've already fetched the orthogonalization method name // (orthoType_) and its parameters (orthoParams) above. // // NOTE (mfh 21 Oct 2011) We only instantiate a new MatOrthoManager // subclass if the orthogonalization method name is different than // before. Thus, for some orthogonalization managers, changes to // their parameters may not get propagated, if the manager type // itself didn't change. The one exception is the "depTol" // (a.k.a. orthoKappa or "Orthogonalization Constant") parameter of // DGKS; changes to that _do_ get propagated down to the DGKS // instance. // // The most general way to fix this issue would be to supply each // orthogonalization manager class with a setParameterList() method // that takes a parameter list input, and changes the parameters as // appropriate. A less efficient but correct way would be simply to // reinstantiate the OrthoManager every time, whether or not the // orthogonalization method name or parameters have changed. if (mustMakeOrtho) { // Create orthogonalization manager. This requires that the // OutputManager (printer_) already be initialized. LSQR // currently only orthogonalizes with respect to the Euclidean // inner product, so we set the inner product matrix M to null. RCP<const OP> M = null; ortho_ = factory.makeMatOrthoManager (orthoType_, M, printer_, label_, orthoParams); } TEUCHOS_TEST_FOR_EXCEPTION(ortho_.is_null(), std::logic_error, "The MatOrthoManager is not yet initialized, but " "should be by this point. " "Please report this bug to the Belos developers."); // Check which orthogonalization constant to use. We only need this // if orthoType_ == "DGKS" (and we already fetched the orthoType_ // parameter above). if (orthoType_ == "DGKS") { if (params->isParameter ("Orthogonalization Constant")) { orthoKappa_ = params_->get<MagnitudeType> ("Orthogonalization Constant"); if (orthoKappa_ > 0 && ! ortho_.is_null()) { typedef DGKSOrthoManager<ScalarType,MV,OP> ortho_impl_type; rcp_dynamic_cast<ortho_impl_type> (ortho_)->setDepTol (orthoKappa_); } } } // Check for condition number limit, number of consecutive passed // iterations, relative RHS error, and relative matrix error. // Create the LSQR convergence test if necessary. { condMax_ = params->get<MagnitudeType> ("Condition Limit"); termIterMax_ = params->get<int>("Term Iter Max"); relRhsErr_ = params->get<MagnitudeType> ("Rel RHS Err"); relMatErr_ = params->get<MagnitudeType> ("Rel Mat Err"); // Create the LSQR convergence test if it doesn't exist yet. // Otherwise, update its parameters. if (convTest_.is_null()) { convTest_ = rcp (new LSQRStatusTest<ScalarType,MV,OP> (condMax_, termIterMax_, relRhsErr_, relMatErr_)); } else { convTest_->setCondLim (condMax_); convTest_->setTermIterMax (termIterMax_); convTest_->setRelRhsErr (relRhsErr_); convTest_->setRelMatErr (relMatErr_); } } // Create the status test for maximum number of iterations if // necessary. Otherwise, update it with the new maximum iteration // count. if (maxIterTest_.is_null()) { maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP> (maxIters_)); } else { maxIterTest_->setMaxIters (maxIters_); } // The stopping criterion is an OR combination of the test for // maximum number of iterations, and the LSQR convergence test. // ("OR combination" means that both tests will always be evaluated, // as opposed to a SEQ combination.) typedef StatusTestCombo<ScalarType,MV,OP> StatusTestCombo_t; // If sTest_ is not null, then maxIterTest_ and convTest_ were // already constructed on entry to this routine, and sTest_ has // their pointers. Thus, maxIterTest_ and convTest_ have gotten any // parameter changes, so we don't need to do anything to sTest_. if (sTest_.is_null()) { sTest_ = rcp (new StatusTestCombo_t (StatusTestCombo_t::OR, maxIterTest_, convTest_)); } if (outputTest_.is_null()) { // Create the status test output class. // This class manages and formats the output from the status test. StatusTestOutputFactory<ScalarType,MV,OP> stoFactory (outputStyle_); outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_, Passed + Failed + Undefined); // Set the solver string for the output test. const std::string solverDesc = " LSQR "; outputTest_->setSolverDesc (solverDesc); } else { // FIXME (mfh 18 Sep 2011) How do we change the output style of // outputTest_, without destroying and recreating it? outputTest_->setOutputManager (printer_); outputTest_->setChild (sTest_); outputTest_->setOutputFrequency (outputFreq_); // Since outputTest_ can only be created here, I'm assuming that // the fourth constructor argument ("printStates") was set // correctly on constrution; I don't need to reset it (and I can't // set it anyway, given StatusTestOutput's interface). } // Inform the solver manager that the current parameters were set. isSet_ = true; }
int main(int argc, char* argv[]) { using Teuchos::describe; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcp_const_cast; using Teuchos::RCP; using Teuchos::CommandLineProcessor; using Teuchos::ParameterList; using Teuchos::sublist; using Teuchos::getParametersFromXmlFile; typedef ParameterList::PrintOptions PLPrintOptions; using Thyra::inverse; using Thyra::initializePreconditionedOp; using Thyra::initializeOp; using Thyra::unspecifiedPrec; using Thyra::solve; typedef RCP<const Thyra::LinearOpBase<double> > LinearOpPtr; typedef RCP<Thyra::VectorBase<double> > VectorPtr; bool success = true; bool verbose = true; Teuchos::GlobalMPISession mpiSession(&argc,&argv); Teuchos::RCP<Teuchos::FancyOStream> out = Teuchos::VerboseObjectBase::getDefaultOStream(); try { // // Read in options from the command line // CommandLineProcessor clp(false); // Don't throw exceptions const int numVerbLevels = 6; Teuchos::EVerbosityLevel verbLevelValues[] = { Teuchos::VERB_DEFAULT, Teuchos::VERB_NONE, Teuchos::VERB_LOW, Teuchos::VERB_MEDIUM, Teuchos::VERB_HIGH, Teuchos::VERB_EXTREME }; const char* verbLevelNames[] = { "default", "none", "low", "medium", "high", "extreme" }; Teuchos::EVerbosityLevel verbLevel = Teuchos::VERB_MEDIUM; clp.setOption( "verb-level", &verbLevel, numVerbLevels, verbLevelValues, verbLevelNames, "Verbosity level used for all objects." ); std::string matrixFile = "."; clp.setOption( "matrix-file", &matrixFile, "Matrix file." ); std::string paramListFile = ""; clp.setOption( "param-list-file", ¶mListFile, "Parameter list for preconditioner and solver blocks." ); bool showParams = false; clp.setOption( "show-params", "no-show-params", &showParams, "Show the parameter list or not." ); bool testPrecIsLinearOp = true; clp.setOption( "test-prec-is-linear-op", "test-prec-is-linear-op", &testPrecIsLinearOp, "Test if the preconditioner is a linear operator or not." ); double solveTol = 1e-8; clp.setOption( "solve-tol", &solveTol, "Tolerance for the solution to determine success or failure!" ); clp.setDocString( "This example program shows how to use one linear solver (e.g. AztecOO)\n" "as a preconditioner for another iterative solver (e.g. Belos).\n" ); // Note: Use --help on the command line to see the above documentation CommandLineProcessor::EParseCommandLineReturn parse_return = clp.parse(argc,argv); if( parse_return != CommandLineProcessor::PARSE_SUCCESSFUL ) return parse_return; // *out << "\nA) Reading in the matrix ...\n"; // #ifdef HAVE_MPI Epetra_MpiComm comm(MPI_COMM_WORLD); #else Epetra_SerialComm comm; #endif const LinearOpPtr A = readEpetraCrsMatrixFromMatrixMarketAsLinearOp( matrixFile, comm, "A"); *out << "\nA = " << describe(*A,verbLevel) << "\n"; const RCP<ParameterList> paramList = getParametersFromXmlFile(paramListFile); if (showParams) { *out << "\nRead in parameter list:\n\n"; paramList->print(*out, PLPrintOptions().indent(2).showTypes(true)); } // *out << "\nB) Get the preconditioner as a forward solver\n"; // const RCP<ParameterList> precParamList = sublist(paramList, "Preconditioner Solver"); Stratimikos::DefaultLinearSolverBuilder precSolverBuilder; precSolverBuilder.setParameterList(precParamList); const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > precSolverStrategy = createLinearSolveStrategy(precSolverBuilder); //precSolverStrategy->setVerbLevel(verbLevel); const LinearOpPtr A_inv_prec = inverse<double>(*precSolverStrategy, A, Thyra::SUPPORT_SOLVE_FORWARD_ONLY, Teuchos::null, // Use internal solve criteria Thyra::IGNORE_SOLVE_FAILURE // Ignore solve failures since this is just a prec ); *out << "\nA_inv_prec = " << describe(*A_inv_prec, verbLevel) << "\n"; if (testPrecIsLinearOp) { *out << "\nTest that the preconditioner A_inv_prec is indeed a linear operator.\n"; Thyra::LinearOpTester<double> linearOpTester; linearOpTester.check_adjoint(false); const bool linearOpCheck = linearOpTester.check(*A_inv_prec, out.ptr()); if (!linearOpCheck) { success = false; } } // *out << "\nC) Create the forward solver using the created preconditioner ...\n"; // const RCP<ParameterList> fwdSolverParamList = sublist(paramList, "Forward Solver"); Stratimikos::DefaultLinearSolverBuilder fwdSolverSolverBuilder; fwdSolverSolverBuilder.setParameterList(fwdSolverParamList); const RCP<const Thyra::LinearOpWithSolveFactoryBase<double> > fwdSolverSolverStrategy = createLinearSolveStrategy(fwdSolverSolverBuilder); const RCP<Thyra::LinearOpWithSolveBase<double> > A_lows = fwdSolverSolverStrategy->createOp(); initializePreconditionedOp<double>( *fwdSolverSolverStrategy, A, unspecifiedPrec(A_inv_prec), A_lows.ptr()); //A_lows->setVerbLevel(verbLevel); *out << "\nA_lows = " << describe(*A_lows, verbLevel) << "\n"; // *out << "\nD) Solve the linear system for a random RHS ...\n"; // VectorPtr x = createMember(A->domain()); VectorPtr b = createMember(A->range()); Thyra::randomize(-1.0, +1.0, b.ptr()); Thyra::assign(x.ptr(), 0.0); // Must give an initial guess! Thyra::SolveStatus<double> solveStatus = solve<double>( *A_lows, Thyra::NOTRANS, *b, x.ptr() ); *out << "\nSolve status:\n" << solveStatus; *out << "\nSolution ||x|| = " << Thyra::norm(*x) << "\n"; if(showParams) { *out << "\nParameter list after use:\n\n"; paramList->print(*out, PLPrintOptions().indent(2).showTypes(true)); } // *out << "\nF) Checking the error in the solution of r=b-A*x ...\n"; // VectorPtr Ax = Thyra::createMember(b->space()); Thyra::apply( *A, Thyra::NOTRANS, *x, Ax.ptr() ); VectorPtr r = Thyra::createMember(b->space()); Thyra::V_VmV<double>(r.ptr(), *b, *Ax); double Ax_nrm = Thyra::norm(*Ax), r_nrm = Thyra::norm(*r), b_nrm = Thyra::norm(*b), r_nrm_over_b_nrm = r_nrm / b_nrm; bool resid_tol_check = ( r_nrm_over_b_nrm <= solveTol ); if(!resid_tol_check) success = false; *out << "\n||A*x|| = " << Ax_nrm << "\n"; *out << "\n||A*x-b||/||b|| = " << r_nrm << "/" << b_nrm << " = " << r_nrm_over_b_nrm << " <= " << solveTol << " : " << Thyra::passfail(resid_tol_check) << "\n"; Teuchos::TimeMonitor::summarize(*out<<"\n"); } TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success) if (verbose) { if(success) *out << "\nCongratulations! All of the tests checked out!\n"; else *out << "\nOh no! At least one of the tests failed!\n"; } return ( success ? EXIT_SUCCESS : EXIT_FAILURE ); }