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);
    }
Exemplo n.º 3
0
void
LSQRSolMgr<ScalarType,MV,OP,false>::
setParameters (const Teuchos::RCP<Teuchos::ParameterList> &params)
{
    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", &paramListFile,
                       "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 );
}