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; }
void MinresSolMgr<ScalarType, MV, OP>:: setParameters (const Teuchos::RCP<Teuchos::ParameterList>& params) { using Teuchos::ParameterList; using Teuchos::parameterList; using Teuchos::RCP; using Teuchos::rcp; using Teuchos::rcpFromRef; using Teuchos::null; using Teuchos::is_null; using std::string; using std::ostream; using std::endl; if (params_.is_null()) { params_ = parameterList (*getValidParameters()); } RCP<ParameterList> pl = params; pl->validateParametersAndSetDefaults (*params_); // // Read parameters from the parameter list. We have already // populated it with defaults. // blockSize_ = pl->get<int> ("Block Size"); verbosity_ = pl->get<int> ("Verbosity"); outputStyle_ = pl->get<int> ("Output Style"); outputFreq_ = pl->get<int>("Output Frequency"); outputStream_ = pl->get<RCP<std::ostream> > ("Output Stream"); convtol_ = pl->get<MagnitudeType> ("Convergence Tolerance"); maxIters_ = pl->get<int> ("Maximum Iterations"); // // All done reading parameters from the parameter list. // Now we know it's valid and we can store it. // params_ = pl; // Change the timer label, and create the timer if necessary. const string newLabel = pl->get<string> ("Timer Label"); { if (newLabel != label_ || timerSolve_.is_null()) { label_ = newLabel; #ifdef BELOS_TEUCHOS_TIME_MONITOR const string solveLabel = label_ + ": MinresSolMgr total solve time"; // Unregister the old timer before creating a new one. if (! timerSolve_.is_null()) { Teuchos::TimeMonitor::clearCounter (label_); timerSolve_ = Teuchos::null; } timerSolve_ = Teuchos::TimeMonitor::getNewCounter (solveLabel); #endif // BELOS_TEUCHOS_TIME_MONITOR } } // Create output manager, if necessary; otherwise, set its parameters. bool recreatedPrinter = false; if (printer_.is_null()) { printer_ = rcp (new OutputManager<ScalarType> (verbosity_, outputStream_)); recreatedPrinter = true; } else { // Set the output stream's verbosity level. printer_->setVerbosity (verbosity_); // Tell the output manager about the new output stream. printer_->setOStream (outputStream_); } // // Set up the convergence tests // typedef StatusTestGenResNorm<ScalarType, MV, OP> res_norm_type; typedef StatusTestCombo<ScalarType, MV, OP> combo_type; // Do we need to allocate at least one of the implicit or explicit // residual norm convergence tests? const bool allocatedConvergenceTests = impConvTest_.is_null() || expConvTest_.is_null(); // Allocate or set the tolerance of the implicit residual norm // convergence test. if (impConvTest_.is_null()) { impConvTest_ = rcp (new res_norm_type (convtol_)); impConvTest_->defineResForm (res_norm_type::Implicit, TwoNorm); // TODO (mfh 03 Nov 2011) Allow users to define the type of // scaling (or a custom scaling factor). impConvTest_->defineScaleForm (NormOfInitRes, TwoNorm); } else { impConvTest_->setTolerance (convtol_); } // Allocate or set the tolerance of the explicit residual norm // convergence test. if (expConvTest_.is_null()) { expConvTest_ = rcp (new res_norm_type (convtol_)); expConvTest_->defineResForm (res_norm_type::Explicit, TwoNorm); // TODO (mfh 03 Nov 2011) Allow users to define the type of // scaling (or a custom scaling factor). expConvTest_->defineScaleForm (NormOfInitRes, TwoNorm); } else { expConvTest_->setTolerance (convtol_); } // Whether we need to recreate the full status test. We only need // to do that if at least one of convTest_ or maxIterTest_ had to // be reallocated. bool needToRecreateFullStatusTest = sTest_.is_null(); // Residual status test is a combo of the implicit and explicit // convergence tests. if (convTest_.is_null() || allocatedConvergenceTests) { convTest_ = rcp (new combo_type (combo_type::SEQ, impConvTest_, expConvTest_)); needToRecreateFullStatusTest = true; } // Maximum number of iterations status test. It tells the solver to // stop iteration, if the maximum number of iterations has been // exceeded. Initialize it if we haven't yet done so, otherwise // tell it the new maximum number of iterations. if (maxIterTest_.is_null()) { maxIterTest_ = rcp (new StatusTestMaxIters<ScalarType,MV,OP> (maxIters_)); needToRecreateFullStatusTest = true; } else { maxIterTest_->setMaxIters (maxIters_); } // Create the full status test if we need to. // // The full status test: the maximum number of iterations have // been reached, OR the residual has converged. // // "If we need to" means either that the status test was never // created before, or that its two component tests had to be // reallocated. if (needToRecreateFullStatusTest) { sTest_ = rcp (new combo_type (combo_type::OR, maxIterTest_, convTest_)); } // If necessary, create the status test output class. This class // manages and formats the output from the status test. We have // to recreate the output test if we had to (re)allocate either // printer_ or sTest_. if (outputTest_.is_null() || needToRecreateFullStatusTest || recreatedPrinter) { StatusTestOutputFactory<ScalarType,MV,OP> stoFactory (outputStyle_); outputTest_ = stoFactory.create (printer_, sTest_, outputFreq_, Passed+Failed+Undefined); } else { outputTest_->setOutputFrequency (outputFreq_); } // Set the solver string for the output test. // StatusTestOutputFactory has no constructor argument for this. outputTest_->setSolverDesc (std::string (" MINRES ")); // Inform the solver manager that the current parameters were set. parametersSet_ = true; if (verbosity_ & Debug) { using std::endl; std::ostream& dbg = printer_->stream (Debug); dbg << "MINRES parameters:" << endl << params_ << endl; } }