Belos Version of the Day
Loading...
Searching...
No Matches
BelosStatusTestImpResNorm.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Belos: Block Linear Solvers Package
4//
5// Copyright 2004-2016 NTESS and the Belos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef BELOS_STATUS_TEST_IMPRESNORM_H
11#define BELOS_STATUS_TEST_IMPRESNORM_H
12
21#include "Teuchos_as.hpp"
22
69namespace Belos {
70
71template <class ScalarType, class MV, class OP>
72class StatusTestImpResNorm: public StatusTestResNorm<ScalarType,MV,OP> {
73public:
75 typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
76
77private:
79
80 typedef Teuchos::ScalarTraits<ScalarType> STS;
81 typedef Teuchos::ScalarTraits<MagnitudeType> STM;
84
85public:
87
88
101 int quorum = -1,
102 bool showMaxResNormOnly = false);
103
105 virtual ~StatusTestImpResNorm();
106
108
110
112
119
121
141 int defineScaleForm( ScaleType TypeOfScaling, NormType TypeOfNorm, MagnitudeType ScaleValue = Teuchos::ScalarTraits<MagnitudeType>::one());
142
144
148 tolerance_ = tolerance;
149 return 0;
150 }
151
154 int setQuorum (int quorum) {
155 quorum_ = quorum;
156 return 0;
157 }
158
161 showMaxResNormOnly_ = showMaxResNormOnly;
162 return 0;
163 }
164
166
168
169
177
179 StatusType getStatus() const {return(status_);};
181
183
184
186 void reset();
187
189
191
192
194 void print(std::ostream& os, int indent = 0) const;
195
197 void printStatus(std::ostream& os, StatusType type) const;
199
201
202
204 Teuchos::RCP<MV> getSolution() { return curSoln_; }
205
208 int getQuorum() const { return quorum_; }
209
211 bool getShowMaxResNormOnly() { return showMaxResNormOnly_; }
212
214 std::vector<int> convIndices() { return ind_; }
215
224 return tolerance_;
225 }
226
235 return currTolerance_;
236 }
237
239 const std::vector<MagnitudeType>* getTestValue() const {return(&testvector_);};
240
242 const std::vector<MagnitudeType>* getResNormValue() const {return(&resvector_);};
243
245 const std::vector<MagnitudeType>* getScaledNormValue() const {return(&scalevector_);};
246
248 bool getLOADetected() const { return lossDetected_; }
250
251
254
262
265
267 std::string description() const
268 {
269 std::ostringstream oss;
270 oss << "Belos::StatusTestImpResNorm<>: " << resFormStr();
271 oss << ", tol = " << tolerance_;
272 return oss.str();
273 }
275
276 protected:
277
278 private:
279
281
282
283 std::string resFormStr() const
284 {
285 std::ostringstream oss;
286 oss << "(";
287 oss << ((resnormtype_==OneNorm) ? "1-Norm" : (resnormtype_==TwoNorm) ? "2-Norm" : "Inf-Norm");
288 oss << " Res Vec) ";
289
290 // If there is no residual scaling, return current string.
291 if (scaletype_!=None)
292 {
293 // Insert division sign.
294 oss << "/ ";
295
296 // Determine output string for scaling, if there is any.
297 if (scaletype_==UserProvided)
298 oss << " (User Scale)";
299 else {
300 oss << "(";
301 oss << ((scalenormtype_==OneNorm) ? "1-Norm" : (resnormtype_==TwoNorm) ? "2-Norm" : "Inf-Norm");
302 if (scaletype_==NormOfInitRes)
303 oss << " Res0";
304 else if (scaletype_==NormOfPrecInitRes)
305 oss << " Prec Res0";
306 else
307 oss << " RHS ";
308 oss << ")";
309 }
310 }
311
312 return oss.str();
313 }
314
316
317
319 MagnitudeType tolerance_, currTolerance_;
320
322 int quorum_;
323
325 bool showMaxResNormOnly_;
326
328 NormType resnormtype_;
329
331 ScaleType scaletype_;
332
334 NormType scalenormtype_;
335
337 MagnitudeType scalevalue_;
338
340 std::vector<MagnitudeType> scalevector_;
341
343 std::vector<MagnitudeType> resvector_;
344
346 std::vector<MagnitudeType> testvector_;
347
349 Teuchos::RCP<MV> curSoln_;
350
352 std::vector<int> ind_;
353
355 StatusType status_;
356
358 int curBlksz_;
359
361 int curNumRHS_;
362
364 std::vector<int> curLSIdx_;
365
367 int curLSNum_;
368
370 int numrhs_;
371
373 bool firstcallCheckStatus_;
374
376 bool firstcallDefineResForm_;
377
379 bool firstcallDefineScaleForm_;
380
382 bool lossDetected_;
384
385};
386
387template <class ScalarType, class MV, class OP>
390 : tolerance_(Tolerance),
391 currTolerance_(Tolerance),
392 quorum_(quorum),
393 showMaxResNormOnly_(showMaxResNormOnly),
394 resnormtype_(TwoNorm),
395 scaletype_(NormOfInitRes),
396 scalenormtype_(TwoNorm),
397 scalevalue_(Teuchos::ScalarTraits<MagnitudeType>::one ()),
398 status_(Undefined),
399 curBlksz_(0),
400 curNumRHS_(0),
401 curLSNum_(0),
402 numrhs_(0),
403 firstcallCheckStatus_(true),
404 firstcallDefineResForm_(true),
405 firstcallDefineScaleForm_(true),
406 lossDetected_(false)
407{
408 // This constructor will compute the residual ||r_i||/||r0_i|| <= tolerance using the 2-norm of
409 // the implicit residual vector.
410}
411
412template <class ScalarType, class MV, class OP>
415
416template <class ScalarType, class MV, class OP>
418{
419 status_ = Undefined;
420 curBlksz_ = 0;
421 curLSNum_ = 0;
422 curLSIdx_.resize(0);
423 numrhs_ = 0;
424 ind_.resize(0);
425 currTolerance_ = tolerance_;
426 firstcallCheckStatus_ = true;
427 lossDetected_ = false;
428 curSoln_ = Teuchos::null;
429}
430
431template <class ScalarType, class MV, class OP>
433{
434 TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineResForm_==false,StatusTestError,
435 "StatusTestResNorm::defineResForm(): The residual form has already been defined.");
436 firstcallDefineResForm_ = false;
437
438 resnormtype_ = TypeOfNorm;
439
440 return(0);
441}
442
443template <class ScalarType, class MV, class OP>
446{
447 TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineScaleForm_==false,StatusTestError,
448 "StatusTestResNorm::defineScaleForm(): The scaling type has already been defined.");
449 firstcallDefineScaleForm_ = false;
450
451 scaletype_ = TypeOfScaling;
452 scalenormtype_ = TypeOfNorm;
453 scalevalue_ = ScaleValue;
454
455 return(0);
456}
457
458template <class ScalarType, class MV, class OP>
461{
462 using Teuchos::as;
463 using Teuchos::RCP;
464
465 const MagnitudeType zero = STM::zero ();
466 const LinearProblem<ScalarType,MV,OP>& lp = iSolver->getProblem ();
467
468 // Compute scaling term (done once for each block that's being solved)
469 if (firstcallCheckStatus_) {
470 StatusType status = firstCallCheckStatusSetup (iSolver);
471 if (status == Failed) {
472 status_ = Failed;
473 return status_;
474 }
475 }
476
477 // mfh 23 Apr 2012: I don't know exactly what this code does. It
478 // has something to do with picking the block of right-hand sides
479 // which we're currently checking.
480 if (curLSNum_ != lp.getLSNumber ()) {
481 //
482 // We have moved on to the next rhs block
483 //
484 curLSNum_ = lp.getLSNumber();
485 curLSIdx_ = lp.getLSIndex();
486 curBlksz_ = (int)curLSIdx_.size();
487 int validLS = 0;
488 for (int i=0; i<curBlksz_; ++i) {
489 if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
490 validLS++;
491 }
492 curNumRHS_ = validLS;
493 curSoln_ = Teuchos::null;
494 } else {
495 //
496 // We are in the same rhs block, return if we are converged
497 //
498 if (status_ == Passed) {
499 return status_;
500 }
501 }
502
503 //
504 // Get the "native" residual norms from the solver for this block of
505 // right-hand sides. If the solver's getNativeResiduals() method
506 // actually returns a multivector, compute the norms of the columns
507 // of the multivector explicitly. Otherwise, we assume that
508 // resvector_ contains the norms.
509 //
510 // Note that "compute the norms explicitly" doesn't necessarily mean
511 // the "explicit" residual norms (in the sense discussed in this
512 // class' documentation). These are just some vectors returned by
513 // the solver. Some Krylov methods, like CG, compute a residual
514 // vector "recursively." This is an "implicit residual" in the
515 // sense of this class' documentation. It equals the explicit
516 // residual in exact arithmetic, but due to rounding error, it is
517 // usually different than the explicit residual.
518 //
519 // FIXME (mfh 23 Apr 2012) This method does _not_ respect the
520 // OrthoManager used by the solver.
521 //
522 std::vector<MagnitudeType> tmp_resvector( curBlksz_ );
523 RCP<const MV> residMV = iSolver->getNativeResiduals (&tmp_resvector);
524 if (! residMV.is_null ()) {
525 // We got a multivector back. Compute the norms explicitly.
526 tmp_resvector.resize (MVT::GetNumberVecs (*residMV));
527 MVT::MvNorm (*residMV, tmp_resvector, resnormtype_);
528 typename std::vector<int>::iterator p = curLSIdx_.begin();
529 for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
530 // Check if this index is valid
531 if (*p != -1) {
532 resvector_[*p] = tmp_resvector[i];
533 }
534 }
535 } else {
536 typename std::vector<int>::iterator p = curLSIdx_.begin();
537 for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
538 // Check if this index is valid
539 if (*p != -1) {
540 resvector_[*p] = tmp_resvector[i];
541 }
542 }
543 }
544 //
545 // Scale the unscaled residual norms we computed or obtained above.
546 //
547 if (scalevector_.size () > 0) {
548 // There are per-vector scaling factors to apply.
549 typename std::vector<int>::iterator p = curLSIdx_.begin();
550 for (; p<curLSIdx_.end(); ++p) {
551 // Check if this index is valid
552 if (*p != -1) {
553 // Scale the vector accordingly
554 if ( scalevector_[ *p ] != zero ) {
555 // Don't intentionally divide by zero.
556 testvector_[ *p ] = resvector_[ *p ] / scalevector_[ *p ] / scalevalue_;
557 } else {
558 testvector_[ *p ] = resvector_[ *p ] / scalevalue_;
559 }
560 }
561 }
562 }
563 else { // There are no per-vector scaling factors.
564 typename std::vector<int>::iterator p = curLSIdx_.begin();
565 for (; p<curLSIdx_.end(); ++p) {
566 // Check if this index is valid
567 if (*p != -1) {
568 testvector_[ *p ] = resvector_[ *p ] / scalevalue_;
569 }
570 }
571 }
572
573 // Count how many scaled residual norms (in testvector_) pass, using
574 // the current tolerance (currTolerance_) rather than the original
575 // tolerance (tolerance_). If at least quorum_ of them pass, we
576 // have a quorum for the whole test to pass.
577 //
578 // We also check here whether any of the scaled residual norms is
579 // NaN, and throw an exception in that case.
580 int have = 0;
581 ind_.resize( curLSIdx_.size() );
582 std::vector<int> lclInd( curLSIdx_.size() );
583 typename std::vector<int>::iterator p = curLSIdx_.begin();
584 for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
585 // Check if this index is valid
586 if (*p != -1) {
587 if (testvector_[ *p ] > currTolerance_) {
588 // The current residual norm doesn't pass. Do nothing.
589 } else if (testvector_[ *p ] <= currTolerance_) {
590 ind_[have] = *p;
591 lclInd[have] = i;
592 have++; // Yay, the current residual norm passes!
593 } else {
594 // Throw an std::exception if the current residual norm is
595 // NaN. We know that it's NaN because it is not less than,
596 // equal to, or greater than the current tolerance. This is
597 // only possible if either the residual norm or the current
598 // tolerance is NaN; we assume the former. We also mark the
599 // test as failed, in case you want to catch the exception.
600 status_ = Failed;
602 "StatusTestImpResNorm::checkStatus(): One or more of the current "
603 "implicit residual norms is NaN.");
604 }
605 }
606 }
607 // "have" is the number of residual norms that passed.
608 ind_.resize(have);
609 lclInd.resize(have);
610
611 // Now check the exact residuals
612 if (have) { // At least one residual norm has converged.
613 //
614 // Compute the explicit residual norm(s) from the current solution update.
615 //
616 RCP<MV> cur_update = iSolver->getCurrentUpdate ();
617 curSoln_ = lp.updateSolution (cur_update);
618 RCP<MV> cur_res = MVT::Clone (*curSoln_, MVT::GetNumberVecs (*curSoln_));
619 lp.computeCurrResVec (&*cur_res, &*curSoln_);
620 tmp_resvector.resize (MVT::GetNumberVecs (*cur_res));
621 std::vector<MagnitudeType> tmp_testvector (have);
622 MVT::MvNorm (*cur_res, tmp_resvector, resnormtype_);
623
624 // Scale the explicit residual norm(s), just like the implicit norm(s).
625 if ( scalevector_.size() > 0 ) {
626 for (int i=0; i<have; ++i) {
627 // Scale the vector accordingly
628 if ( scalevector_[ ind_[i] ] != zero ) {
629 // Don't intentionally divide by zero.
630 tmp_testvector[ i ] = tmp_resvector[ lclInd[i] ] / scalevector_[ ind_[i] ] / scalevalue_;
631 } else {
632 tmp_testvector[ i ] = tmp_resvector[ lclInd[i] ] / scalevalue_;
633 }
634 }
635 }
636 else {
637 for (int i=0; i<have; ++i) {
638 tmp_testvector[ i ] = tmp_resvector[ lclInd[i] ] / scalevalue_;
639 }
640 }
641
642 //
643 // Check whether the explicit residual norms also pass the
644 // convergence test. If not, check whether we want to try
645 // iterating a little more to force both implicit and explicit
646 // residual norms to pass.
647 //
648 int have2 = 0;
649 for (int i = 0; i < have; ++i) {
650 // testvector_ contains the implicit (i.e., recursive, computed
651 // by the algorithm) (possibly scaled) residuals. All of these
652 // pass the convergence test.
653 //
654 // tmp_testvector contains the explicit (i.e., ||B-AX||)
655 // (possibly scaled) residuals. We're checking whether these
656 // pass as well. The explicit residual norms only have to meet
657 // the _original_ tolerance (tolerance_), not the current
658 // tolerance (currTolerance_).
659 if (tmp_testvector[i] <= tolerance_) {
660 ind_[have2] = ind_[i];
661 have2++; // This right-hand side has converged.
662 }
663 else {
664 // Absolute difference between the current explicit and
665 // implicit residual norm.
666 const MagnitudeType diff = STM::magnitude (testvector_[ind_[i]] - tmp_testvector[i]);
667 if (diff > currTolerance_) {
668 // If the above difference is bigger than the current
669 // convergence tolerance, report a loss of accuracy, but
670 // mark this right-hand side converged. (The latter tells
671 // users not to iterate further on this right-hand side,
672 // since it probably won't do much good.) Note that the
673 // current tolerance may have been changed by the branch
674 // below in a previous call to this method.
675 lossDetected_ = true;
676 ind_[have2] = ind_[i];
677 have2++; // Count this right-hand side as converged.
678 }
679 else {
680 // Otherwise, the explicit and implicit residuals are pretty
681 // close together, and the implicit residual has converged,
682 // but the explicit residual hasn't converged. Reduce the
683 // convergence tolerance by some formula related to the
684 // difference, and keep iterating.
685 //
686 // mfh 23 Apr 2012: I have no idea why the currTolerance_
687 // update formula is done the way it's done below. It
688 // doesn't make sense to me. It definitely makes the
689 // current tolerance smaller, though, which is what we want.
690
691 // We define these constants in this way, rather than simply
692 // writing 1.5 resp. 0.1, to ensure no rounding error from
693 // translating from float to MagnitudeType. Remember that
694 // 0.1 doesn't have an exact representation in binary finite
695 // floating-point arithmetic.
697 const MagnitudeType oneTenth = STM::one () / as<MagnitudeType> (10);
698
699 currTolerance_ = currTolerance_ - onePointFive * diff;
700 while (currTolerance_ < STM::zero ()) {
701 currTolerance_ += oneTenth * diff;
702 }
703 }
704 }
705 }
706 have = have2;
707 ind_.resize(have);
708 }
709
710 // Check whether we've met the quorum of vectors necessary for the
711 // whole test to pass.
712 int need = (quorum_ == -1) ? curNumRHS_: quorum_;
713 status_ = (have >= need) ? Passed : Failed;
714
715 // Return the current status
716 return status_;
717}
718
719template <class ScalarType, class MV, class OP>
721{
722 for (int j = 0; j < indent; j ++)
723 os << ' ';
724 printStatus(os, status_);
725 os << resFormStr();
726 if (status_==Undefined)
727 os << ", tol = " << tolerance_ << std::endl;
728 else {
729 os << std::endl;
730 if(showMaxResNormOnly_ && curBlksz_ > 1) {
731 const MagnitudeType maxRelRes = *std::max_element(
732 testvector_.begin()+curLSIdx_[0],testvector_.begin()+curLSIdx_[curBlksz_-1]
733 );
734 for (int j = 0; j < indent + 13; j ++)
735 os << ' ';
736 os << "max{residual["<<curLSIdx_[0]<<"..."<<curLSIdx_[curBlksz_-1]<<"]} = " << maxRelRes
737 << ( maxRelRes <= tolerance_ ? " <= " : " > " ) << tolerance_ << std::endl;
738 }
739 else {
740 for ( int i=0; i<numrhs_; i++ ) {
741 for (int j = 0; j < indent + 13; j ++)
742 os << ' ';
743 os << "residual [ " << i << " ] = " << testvector_[ i ];
744 os << ((testvector_[i]<tolerance_) ? " < " : (testvector_[i]==tolerance_) ? " == " : (testvector_[i]>tolerance_) ? " > " : " " ) << tolerance_ << std::endl;
745 }
746 }
747 }
748 os << std::endl;
749}
750
751template <class ScalarType, class MV, class OP>
753{
754 os << std::left << std::setw(13) << std::setfill('.');
755 switch (type) {
756 case Passed:
757 os << "Converged";
758 break;
759 case Failed:
760 if (lossDetected_)
761 os << "Unconverged (LoA)";
762 else
763 os << "Unconverged";
764 break;
765 case Undefined:
766 default:
767 os << "**";
768 break;
769 }
770 os << std::left << std::setfill(' ');
771 return;
772}
773
774template <class ScalarType, class MV, class OP>
777{
778 int i;
779 const MagnitudeType zero = STM::zero ();
780 const MagnitudeType one = STM::one ();
781 const LinearProblem<ScalarType,MV,OP>& lp = iSolver->getProblem();
782 // Compute scaling term (done once for each block that's being solved)
783 if (firstcallCheckStatus_) {
784 //
785 // Get some current solver information.
786 //
787 firstcallCheckStatus_ = false;
788
789 if (scaletype_== NormOfRHS) {
790 Teuchos::RCP<const MV> rhs = lp.getRHS();
791 numrhs_ = MVT::GetNumberVecs( *rhs );
792 scalevector_.resize( numrhs_ );
793 MVT::MvNorm( *rhs, scalevector_, scalenormtype_ );
794 }
795 else if (scaletype_==NormOfInitRes) {
796 Teuchos::RCP<const MV> init_res = lp.getInitResVec();
797 numrhs_ = MVT::GetNumberVecs( *init_res );
798 scalevector_.resize( numrhs_ );
799 MVT::MvNorm( *init_res, scalevector_, scalenormtype_ );
800 }
801 else if (scaletype_==NormOfPrecInitRes) {
802 Teuchos::RCP<const MV> init_res = lp.getInitPrecResVec();
803 numrhs_ = MVT::GetNumberVecs( *init_res );
804 scalevector_.resize( numrhs_ );
805 MVT::MvNorm( *init_res, scalevector_, scalenormtype_ );
806 }
807 else {
808 numrhs_ = MVT::GetNumberVecs( *(lp.getRHS()) );
809 }
810
811 resvector_.resize( numrhs_ );
812 testvector_.resize( numrhs_ );
813
814 curLSNum_ = lp.getLSNumber();
815 curLSIdx_ = lp.getLSIndex();
816 curBlksz_ = (int)curLSIdx_.size();
817 int validLS = 0;
818 for (i=0; i<curBlksz_; ++i) {
819 if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
820 validLS++;
821 }
822 curNumRHS_ = validLS;
823 //
824 // Initialize the testvector.
825 for (i=0; i<numrhs_; i++) { testvector_[i] = one; }
826
827 // Return an error if the scaling is zero.
828 if (scalevalue_ == zero) {
829 return Failed;
830 }
831 }
832 return Undefined;
833}
834
835} // end namespace Belos
836
837#endif /* BELOS_STATUS_TEST_IMPRESNORM_H */
Class which describes the linear problem to be solved by the iterative solver.
Declaration of basic traits for the multivector type.
Belos::StatusTest abstract class for specifying a residual norm stopping criteria.
Alternative run-time polymorphic interface for operators.
Operator()
Default constructor (does nothing).
Exception thrown to signal error in a status test during Belos::StatusTest::checkStatus().
Convergence test using the implicit residual norm(s), with an explicit residual norm(s) check for los...
StatusTestImpResNorm(MagnitudeType Tolerance, int quorum=-1, bool showMaxResNormOnly=false)
Constructor.
const std::vector< MagnitudeType > * getScaledNormValue() const
Returns the scaled norm value, .
virtual ~StatusTestImpResNorm()
Destructor (virtual for memory safety).
Teuchos::ScalarTraits< ScalarType >::magnitudeType MagnitudeType
The type of the magnitude (absolute value) of a ScalarType.
MagnitudeType getTolerance() const
"Original" convergence tolerance as set by user.
MagnitudeType getCurrTolerance() const
Current convergence tolerance; may be changed to prevent loss of accuracy.
std::string description() const
Method to return description of the maximum iteration status test
std::vector< int > convIndices()
Returns the vector containing the indices of the residuals that passed the test.
void printStatus(std::ostream &os, StatusType type) const
Print message for each status specific to this stopping test.
int defineScaleForm(ScaleType TypeOfScaling, NormType TypeOfNorm, MagnitudeType ScaleValue=Teuchos::ScalarTraits< MagnitudeType >::one())
Define form of the scaling, its norm, its optional weighting vector, or, alternatively,...
const std::vector< MagnitudeType > * getResNormValue() const
Returns the residual norm value, , computed in most recent call to CheckStatus.
Teuchos::RCP< MV > getSolution()
Returns the current solution estimate that was computed for the most recent residual test.
void print(std::ostream &os, int indent=0) const
Output formatted description of stopping test to output stream.
void reset()
Resets the internal configuration to the initial state.
bool getShowMaxResNormOnly()
Returns whether the only maximum residual norm is displayed when the print() method is called.
bool getLOADetected() const
Returns a boolean indicating a loss of accuracy has been detected in computing the residual.
int getQuorum() const
Returns the number of residuals that must pass the convergence test before Passed is returned.
StatusType getStatus() const
Return the result of the most recent CheckStatus call.
StatusType checkStatus(Iteration< ScalarType, MV, OP > *iSolver)
Check convergence status: Passed, Failed, or Undefined.
int setTolerance(MagnitudeType tolerance)
Set the value of the tolerance.
const std::vector< MagnitudeType > * getTestValue() const
Returns the test value, , computed in most recent call to CheckStatus.
int defineResForm(NormType TypeOfNorm)
Define form of the residual, its norm and optional weighting vector.
int setShowMaxResNormOnly(bool showMaxResNormOnly)
Set whether the only maximum residual norm is displayed when the print() method is called.
StatusType firstCallCheckStatusSetup(Iteration< ScalarType, MV, OP > *iSolver)
Call to setup initial scaling vector.
int setQuorum(int quorum)
Sets the number of residuals that must pass the convergence test before Passed is returned.
An abstract class of StatusTest for stopping criteria using residual norms.
NormType
The type of vector norm to compute.
StatusType
Whether the StatusTest wants iteration to stop.
ScaleType
The type of scaling to use on the residual norm value.
@ UserProvided
@ NormOfPrecInitRes
@ NormOfInitRes
@ NormOfRHS

Generated for Belos by doxygen 1.9.8