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;