184  const RCP<
const LinearOpBase<double> > &fwdOp
 
  185  ,
const RCP<
const LinearOpSourceBase<double> > &fwdOpSrc
 
  186  ,
const RCP<
const PreconditionerBase<double> > &prec
 
  187  ,
const bool isExternalPrec_in
 
  188  ,
const RCP<
const LinearOpSourceBase<double> > &approxFwdOpSrc
 
  189  ,
const RCP<AztecOO> &aztecFwdSolver
 
  190  ,
const bool allowInexactFwdSolve
 
  191  ,
const RCP<AztecOO> &aztecAdjSolver
 
  192  ,
const bool allowInexactAdjSolve
 
  193  ,
const double aztecSolverScalar
 
  197  TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL);
 
  198  TEUCHOS_TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL);
 
  199  TEUCHOS_TEST_FOR_EXCEPT(aztecFwdSolver.get()==NULL);
 
  202  fwdOpSrc_ = fwdOpSrc;
 
  203  isExternalPrec_ = isExternalPrec_in;
 
  205  approxFwdOpSrc_ = approxFwdOpSrc;
 
  206  aztecFwdSolver_ = aztecFwdSolver;
 
  207  allowInexactFwdSolve_ = allowInexactFwdSolve;
 
  208  aztecAdjSolver_ = aztecAdjSolver;
 
  209  allowInexactAdjSolve_ = allowInexactAdjSolve;
 
  210  aztecSolverScalar_ = aztecSolverScalar;
 
  211  const std::string fwdOpLabel = fwdOp_->getObjectLabel();
 
  212  if (fwdOpLabel.length())
 
  213    this->setObjectLabel( 
"lows("+fwdOpLabel+
")" );
 
 
  254  RCP<
const LinearOpBase<double> > *fwdOp,
 
  255  RCP<
const LinearOpSourceBase<double> > *fwdOpSrc,
 
  256  RCP<
const PreconditionerBase<double> > *prec,
 
  257  bool *isExternalPrec_inout,
 
  258  RCP<
const LinearOpSourceBase<double> > *approxFwdOpSrc,
 
  259  RCP<AztecOO> *aztecFwdSolver,
 
  260  bool *allowInexactFwdSolve,
 
  261  RCP<AztecOO> *aztecAdjSolver,
 
  262  bool *allowInexactAdjSolve,
 
  263  double *aztecSolverScalar
 
  266  if (fwdOp) *fwdOp = fwdOp_;
 
  267  if (fwdOpSrc) *fwdOpSrc = fwdOpSrc_;
 
  268  if (prec) *prec = prec_;
 
  269  if (isExternalPrec_inout) *isExternalPrec_inout = isExternalPrec_;
 
  270  if (approxFwdOpSrc) *approxFwdOpSrc = approxFwdOpSrc_;
 
  271  if (aztecFwdSolver) *aztecFwdSolver = aztecFwdSolver_;
 
  272  if (allowInexactFwdSolve) *allowInexactFwdSolve = allowInexactFwdSolve_;
 
  273  if (aztecAdjSolver) *aztecAdjSolver = aztecAdjSolver_;
 
  274  if (allowInexactAdjSolve) *allowInexactAdjSolve = allowInexactAdjSolve_;
 
  275  if (aztecSolverScalar) *aztecSolverScalar = aztecSolverScalar_;
 
  277  fwdOp_ = Teuchos::null;
 
  278  fwdOpSrc_ = Teuchos::null;
 
  279  prec_ = Teuchos::null;
 
  280  isExternalPrec_ = 
false; 
 
  281  approxFwdOpSrc_ = Teuchos::null;
 
  282  aztecFwdSolver_ = Teuchos::null;
 
  283  allowInexactFwdSolve_ = 
false;
 
  284  aztecAdjSolver_ = Teuchos::null;
 
  285  allowInexactAdjSolve_ = 
false;
 
  286  aztecSolverScalar_ = 0.0;
 
 
  331  Teuchos::FancyOStream &out,
 
  332  const Teuchos::EVerbosityLevel verbLevel
 
  335  using Teuchos::OSTab;
 
  336  using Teuchos::typeName;
 
  337  using Teuchos::describe;
 
  339    case Teuchos::VERB_DEFAULT:
 
  340    case Teuchos::VERB_LOW:
 
  343    case Teuchos::VERB_MEDIUM:
 
  344    case Teuchos::VERB_HIGH:
 
  345    case Teuchos::VERB_EXTREME:
 
  348        << Teuchos::Describable::description() << 
"{" 
  349        << 
"rangeDim=" << this->
range()->dim()
 
  350        << 
",domainDim="<< this->
domain()->dim() << 
"}\n";
 
  352      if (!is_null(fwdOp_)) {
 
  353        out << 
"fwdOp = " << 
describe(*fwdOp_,verbLevel);
 
  355      if (!is_null(prec_)) {
 
  356        out << 
"prec = " << 
describe(*prec_,verbLevel);
 
  358      if (!is_null(aztecFwdSolver_)) {
 
  359        if (aztecFwdSolver_->GetUserOperator())
 
  362            << typeName(*aztecFwdSolver_->GetUserOperator()) << 
"\n";
 
  363        if (aztecFwdSolver_->GetUserMatrix())
 
  365            << 
"Aztec Fwd Mat = " 
  366            << typeName(*aztecFwdSolver_->GetUserMatrix()) << 
"\n";
 
  367        if (aztecFwdSolver_->GetPrecOperator())
 
  369            << 
"Aztec Fwd Prec Op = " 
  370            << typeName(*aztecFwdSolver_->GetPrecOperator()) << 
"\n";
 
  371        if (aztecFwdSolver_->GetPrecMatrix())
 
  373            << 
"Aztec Fwd Prec Mat = " 
  374            << typeName(*aztecFwdSolver_->GetPrecMatrix()) << 
"\n";
 
  376      if (!is_null(aztecAdjSolver_)) {
 
  377        if (aztecAdjSolver_->GetUserOperator())
 
  380            << typeName(*aztecAdjSolver_->GetUserOperator()) << 
"\n";
 
  381        if (aztecAdjSolver_->GetUserMatrix())
 
  383            << 
"Aztec Adj Mat = " 
  384            << typeName(*aztecAdjSolver_->GetUserMatrix()) << 
"\n";
 
  385        if (aztecAdjSolver_->GetPrecOperator())
 
  387            << 
"Aztec Adj Prec Op = " 
  388            << typeName(*aztecAdjSolver_->GetPrecOperator()) << 
"\n";
 
  389        if (aztecAdjSolver_->GetPrecMatrix())
 
  391            << 
"Aztec Adj Prec Mat = " 
  392            << typeName(*aztecAdjSolver_->GetPrecMatrix()) << 
"\n";
 
  397      TEUCHOS_TEST_FOR_EXCEPT(
true); 
 
 
  513  const EOpTransp M_trans,
 
  514  const MultiVectorBase<double> &B,
 
  515  const Ptr<MultiVectorBase<double> > &X,
 
  516  const Ptr<
const SolveCriteria<double> > solveCriteria
 
  521  using Teuchos::rcpFromRef;
 
  522  using Teuchos::rcpFromPtr;
 
  523  using Teuchos::OSTab;
 
  524  typedef SolveCriteria<double> SC;
 
  525  typedef SolveStatus<double> SS;
 
  527  THYRA_FUNC_TIME_MONITOR(
"Stratimikos: AztecOOLOWS");
 
  528  Teuchos::Time totalTimer(
""), timer(
"");
 
  529  totalTimer.start(
true);
 
  531  RCP<Teuchos::FancyOStream> out = this->getOStream();
 
  532  Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel();
 
  533  OSTab tab = this->getOSTab();
 
  534  if (out.get() && 
static_cast<int>(verbLevel) > 
static_cast<int>(Teuchos::VERB_NONE))
 
  535    *out << 
"\nSolving block system using AztecOO ...\n\n";
 
  541  SolveMeasureType solveMeasureType;
 
  542  if (nonnull(solveCriteria)) {
 
  543    solveMeasureType = solveCriteria->solveMeasureType;
 
  544    assertSupportsSolveMeasureType(*
this, M_trans, solveMeasureType);
 
  550  const EOpTransp aztecOpTransp = real_trans(M_trans);
 
  556    aztecSolver = ( aztecOpTransp == 
NOTRANS ? aztecFwdSolver_  : aztecAdjSolver_ );
 
  558    *aztecOp = aztecSolver->GetUserOperator();
 
  570  double tol = ( aztecOpTransp==
NOTRANS ? fwdDefaultTol() : adjDefaultTol() );
 
  571  int maxIterations = ( aztecOpTransp==
NOTRANS 
  572    ? fwdDefaultMaxIterations() : adjDefaultMaxIterations() );
 
  573  bool isDefaultSolveCriteria = 
true;
 
  574  if (nonnull(solveCriteria)) {
 
  575    if ( solveCriteria->requestedTol != SC::unspecifiedTolerance() ) {
 
  576      tol = solveCriteria->requestedTol;
 
  577      isDefaultSolveCriteria = 
false;
 
  579    if (nonnull(solveCriteria->extraParameters)) {
 
  580      maxIterations = solveCriteria->extraParameters->get(
"Maximum Iterations",maxIterations);
 
  588  RCP<const Epetra_MultiVector> epetra_B;
 
  589  RCP<Epetra_MultiVector> epetra_X;
 
  591  const EpetraOperatorWrapper* opWrapper =
 
  592    dynamic_cast<const EpetraOperatorWrapper*
>(aztecOp);
 
  594  if (opWrapper == 0) {
 
  595    epetra_B = get_Epetra_MultiVector(opRangeMap, rcpFromRef(B));
 
  596    epetra_X = get_Epetra_MultiVector(opDomainMap, rcpFromPtr(X));
 
  603  int totalIterations = 0;
 
  604  SolveStatus<double> solveStatus;
 
  605  solveStatus.solveStatus = SOLVE_STATUS_CONVERGED;
 
  606  solveStatus.achievedTol = -1.0;
 
  612  const int m = B.domain()->dim();
 
  614  for( 
int j = 0; j < m; ++j ) {
 
  616    THYRA_FUNC_TIME_MONITOR_DIFF(
"Stratimikos: AztecOOLOWS:SingleSolve", SingleSolve);
 
  626    RCP<Epetra_Vector> epetra_b_j;
 
  627    RCP<Epetra_Vector> epetra_x_j;
 
  629    if (opWrapper == 0) {
 
  630      epetra_b_j = rcpFromRef(*
const_cast<Epetra_Vector*
>((*epetra_B)(j)));
 
  631      epetra_x_j = rcpFromRef(*(*epetra_X)(j));
 
  634      if (is_null(epetra_b_j)) {
 
  638      opWrapper->copyThyraIntoEpetra(*B.col(j), *epetra_b_j);
 
  639      opWrapper->copyThyraIntoEpetra(*X->col(j), *epetra_x_j);
 
  646    aztecSolver->SetRHS(&*epetra_b_j);
 
  647    aztecSolver->SetLHS(&*epetra_x_j);
 
  655        setAztecSolveState(aztecSolver,out,verbLevel,solveMeasureType);
 
  656      aztecSolver->Iterate( maxIterations, tol );
 
  667    if (aztecSolverScalar_ != 1.0)
 
  668      epetra_x_j->Scale(1.0/aztecSolverScalar_);
 
  673    if (opWrapper != 0) {
 
  674      opWrapper->copyEpetraIntoThyra(*epetra_x_j, X->col(j).ptr());
 
  681    const int iterations = aztecSolver->NumIters();
 
  682    const double achievedTol = aztecSolver->ScaledResidual();
 
  683    const double *AZ_status = aztecSolver->GetAztecStatus();
 
  684    std::ostringstream oss;
 
  685    bool converged = 
false;
 
  686    if (AZ_status[AZ_why]==AZ_normal) { oss << 
"Aztec returned AZ_normal."; converged = 
true; }
 
  687    else if (AZ_status[AZ_why]==AZ_param) oss << 
"Aztec returned AZ_param.";
 
  688    else if (AZ_status[AZ_why]==AZ_breakdown) oss << 
"Aztec returned AZ_breakdown.";
 
  689    else if (AZ_status[AZ_why]==AZ_loss) oss << 
"Aztec returned AZ_loss.";
 
  690    else if (AZ_status[AZ_why]==AZ_ill_cond) oss << 
"Aztec returned AZ_ill_cond.";
 
  691    else if (AZ_status[AZ_why]==AZ_maxits) oss << 
"Aztec returned AZ_maxits.";
 
  692    else oss << 
"Aztec returned an unknown status?";
 
  693    oss << 
"  Iterations = " << iterations << 
".";
 
  694    oss << 
"  Achieved Tolerance = " << achievedTol << 
".";
 
  695    oss << 
"  Total time = " << timer.totalElapsedTime() << 
" sec.";
 
  696    if (out.get() && 
static_cast<int>(verbLevel) > 
static_cast<int>(Teuchos::VERB_NONE) && outputEveryRhs())
 
  697      Teuchos::OSTab(out).o() << 
"j="<<j<<
": " << oss.str() << 
"\n";
 
  699    solveStatus.achievedTol = TEUCHOS_MAX(solveStatus.achievedTol, achievedTol);
 
  702    totalIterations += iterations;
 
  704    solveStatus.message = oss.str();
 
  705    if ( isDefaultSolveCriteria ) {
 
  706      switch(solveStatus.solveStatus) {
 
  707        case SOLVE_STATUS_UNKNOWN:
 
  710        case SOLVE_STATUS_CONVERGED:
 
  711          solveStatus.solveStatus = ( converged ? SOLVE_STATUS_CONVERGED : SOLVE_STATUS_UNCONVERGED );
 
  713        case SOLVE_STATUS_UNCONVERGED:
 
  717          TEUCHOS_TEST_FOR_EXCEPT(
true); 
 
  722  aztecSolver->UnsetLHSRHS();
 
  727  epetra_X = Teuchos::null;
 
  728  epetra_B = Teuchos::null;
 
  734  SolveStatus<double> overallSolveStatus;
 
  735  if (isDefaultSolveCriteria) {
 
  736    overallSolveStatus.solveStatus = SOLVE_STATUS_UNKNOWN;
 
  737    overallSolveStatus.achievedTol = SS::unknownTolerance();
 
  740    overallSolveStatus.solveStatus = solveStatus.solveStatus;
 
  741    overallSolveStatus.achievedTol = solveStatus.achievedTol;
 
  743  std::ostringstream oss;
 
  746    << ( overallSolveStatus.solveStatus==SOLVE_STATUS_CONVERGED ? 
"converged" : 
"unconverged" )
 
  747    << 
" on m = "<<m<<
" RHSs using " << totalIterations << 
" cumulative iterations" 
  748    << 
" for an average of " << (totalIterations/m) << 
" iterations/RHS and" 
  749    << 
" total CPU time of "<<totalTimer.totalElapsedTime()<<
" sec.";
 
  750  overallSolveStatus.message = oss.str();
 
  753  if (overallSolveStatus.extraParameters.is_null()) {
 
  754    overallSolveStatus.extraParameters = Teuchos::parameterList ();
 
  756  overallSolveStatus.extraParameters->set (
"AztecOO/Iteration Count",
 
  759  overallSolveStatus.extraParameters->set (
"Iteration Count",
 
  761  overallSolveStatus.extraParameters->set (
"AztecOO/Achieved Tolerance",
 
  762                                            overallSolveStatus.achievedTol);
 
  767  if (out.get() && 
static_cast<int>(verbLevel) >= 
static_cast<int>(Teuchos::VERB_LOW))
 
  769      << 
"\nTotal solve time = "<<totalTimer.totalElapsedTime()<<
" sec\n";
 
  771  return overallSolveStatus;