Belos  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosStatusTestGenResNorm.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
42 #ifndef BELOS_STATUS_TEST_GEN_RESNORM_H
43 #define BELOS_STATUS_TEST_GEN_RESNORM_H
44 
51 #include "BelosLinearProblem.hpp"
52 #include "BelosMultiVecTraits.hpp"
53 
76 namespace Belos {
77 
78 template <class ScalarType, class MV, class OP>
79 class StatusTestGenResNorm: public StatusTestResNorm<ScalarType,MV,OP> {
80 
81  public:
82 
83  // Convenience typedefs
87 
89 
90 
94  enum ResType {Implicit,
97  };
98 
100 
102 
103 
117  StatusTestGenResNorm( MagnitudeType Tolerance, int quorum = -1, bool showMaxResNormOnly = false );
118 
120  virtual ~StatusTestGenResNorm();
122 
124 
125 
127 
134  int defineResForm( ResType TypeOfResidual, NormType TypeOfNorm);
135 
137 
157  int defineScaleForm( ScaleType TypeOfScaling, NormType TypeOfNorm, MagnitudeType ScaleValue = Teuchos::ScalarTraits<MagnitudeType>::one());
158 
159  NormType getResNormType() {return resnormtype_;}
160 
162 
165  int setTolerance(MagnitudeType tolerance) {tolerance_ = tolerance; return(0);}
166 
169  int setQuorum(int quorum) {quorum_ = quorum; return(0);}
170 
172  int setShowMaxResNormOnly(bool showMaxResNormOnly) {showMaxResNormOnly_ = showMaxResNormOnly; return(0);}
173 
175 
177 
178 
186 
188  StatusType getStatus() const {return(status_);};
190 
192 
193 
195  void reset();
196 
198 
200 
201 
203  void print(std::ostream& os, int indent = 0) const;
204 
206  void printStatus(std::ostream& os, StatusType type) const;
208 
210 
211 
215  Teuchos::RCP<MV> getSolution() { if (restype_==Implicit) { return Teuchos::null; } else { return curSoln_; } }
216 
219  int getQuorum() const { return quorum_; }
220 
222  bool getShowMaxResNormOnly() { return showMaxResNormOnly_; }
223 
225  std::vector<int> convIndices() { return ind_; }
226 
228  MagnitudeType getTolerance() const {return(tolerance_);};
229 
231  const std::vector<MagnitudeType>* getTestValue() const {return(&testvector_);};
232 
234  const std::vector<MagnitudeType>* getResNormValue() const {return(&resvector_);};
235 
237  const std::vector<MagnitudeType>* getScaledNormValue() const {return(&scalevector_);};
238 
241  bool getLOADetected() const { return false; }
242 
244 
245 
248 
256 
259 
261  std::string description() const
262  {
263  std::ostringstream oss;
264  oss << "Belos::StatusTestGenResNorm<>: " << resFormStr();
265  oss << ", tol = " << tolerance_;
266  return oss.str();
267  }
269 
270  protected:
271 
272  private:
273 
275 
276 
277  std::string resFormStr() const
278  {
279  std::ostringstream oss;
280  oss << "(";
281  oss << ((resnormtype_==OneNorm) ? "1-Norm" : (resnormtype_==TwoNorm) ? "2-Norm" : "Inf-Norm");
282  oss << ((restype_==Explicit) ? " Exp" : " Imp");
283  oss << " Res Vec) ";
284 
285  // If there is no residual scaling, return current string.
286  if (scaletype_!=None)
287  {
288  // Insert division sign.
289  oss << "/ ";
290 
291  // Determine output string for scaling, if there is any.
292  if (scaletype_==UserProvided)
293  oss << " (User Scale)";
294  else {
295  oss << "(";
296  oss << ((scalenormtype_==OneNorm) ? "1-Norm" : (resnormtype_==TwoNorm) ? "2-Norm" : "Inf-Norm");
297  if (scaletype_==NormOfInitRes || scaletype_==NormOfFullInitRes || scaletype_==NormOfFullScaledInitRes)
298  oss << " Res0";
299  else if (scaletype_==NormOfPrecInitRes || scaletype_==NormOfFullPrecInitRes || scaletype_==NormOfFullScaledPrecInitRes)
300  oss << " Prec Res0";
301  else
302  oss << " RHS ";
303  oss << ")";
304  }
305  }
306 
307  return oss.str();
308  }
309 
311 
313 
314 
316  MagnitudeType tolerance_;
317 
319  int quorum_;
320 
322  bool showMaxResNormOnly_;
323 
325  ResType restype_;
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  std::vector<int> ind_;
350 
352  Teuchos::RCP<MV> curSoln_;
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 
383 };
384 
385 template <class ScalarType, class MV, class OP>
387 StatusTestGenResNorm (MagnitudeType Tolerance, int quorum, bool showMaxResNormOnly)
388  : tolerance_(Tolerance),
389  quorum_(quorum),
390  showMaxResNormOnly_(showMaxResNormOnly),
391  restype_(Implicit),
392  resnormtype_(TwoNorm),
393  scaletype_(NormOfInitRes),
394  scalenormtype_(TwoNorm),
395  scalevalue_(Teuchos::ScalarTraits<MagnitudeType>::one ()),
396  status_(Undefined),
397  curBlksz_(0),
398  curNumRHS_(0),
399  curLSNum_(0),
400  numrhs_(0),
401  firstcallCheckStatus_(true),
402  firstcallDefineResForm_(true),
403  firstcallDefineScaleForm_(true)
404 {
405  // This constructor will compute the residual ||r_i||/||r0_i|| <= tolerance using the 2-norm of
406  // the implicit residual std::vector.
407 }
408 
409 template <class ScalarType, class MV, class OP>
411 {}
412 
413 template <class ScalarType, class MV, class OP>
415 {
416  status_ = Undefined;
417  curBlksz_ = 0;
418  curLSNum_ = 0;
419  curLSIdx_.resize(0);
420  numrhs_ = 0;
421  ind_.resize(0);
422  firstcallCheckStatus_ = true;
423  curSoln_ = Teuchos::null;
424 }
425 
426 template <class ScalarType, class MV, class OP>
428 {
429  TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineResForm_==false,StatusTestError,
430  "StatusTestGenResNorm::defineResForm(): The residual form has already been defined.");
431  firstcallDefineResForm_ = false;
432 
433  restype_ = TypeOfResidual;
434  resnormtype_ = TypeOfNorm;
435 
436  return(0);
437 }
438 
439 template <class ScalarType, class MV, class OP>
441  MagnitudeType ScaleValue )
442 {
443  TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineScaleForm_==false,StatusTestError,
444  "StatusTestGenResNorm::defineScaleForm(): The scaling type has already been defined.");
445  firstcallDefineScaleForm_ = false;
446 
447  scaletype_ = TypeOfScaling;
448  scalenormtype_ = TypeOfNorm;
449  scalevalue_ = ScaleValue;
450 
451  return(0);
452 }
453 
454 template <class ScalarType, class MV, class OP>
456 {
458  const LinearProblem<ScalarType,MV,OP>& lp = iSolver->getProblem();
459  // Compute scaling term (done once for each block that's being solved)
460  if (firstcallCheckStatus_) {
461  StatusType status = firstCallCheckStatusSetup(iSolver);
462  if(status==Failed) {
463  status_ = Failed;
464  return(status_);
465  }
466  }
467  //
468  // This section computes the norm of the residual std::vector
469  //
470  if ( curLSNum_ != lp.getLSNumber() ) {
471  //
472  // We have moved on to the next rhs block
473  //
474  curLSNum_ = lp.getLSNumber();
475  curLSIdx_ = lp.getLSIndex();
476  curBlksz_ = (int)curLSIdx_.size();
477  int validLS = 0;
478  for (int i=0; i<curBlksz_; ++i) {
479  if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
480  validLS++;
481  }
482  curNumRHS_ = validLS;
483  curSoln_ = Teuchos::null;
484  //
485  } else {
486  //
487  // We are in the same rhs block, return if we are converged
488  //
489  if (status_==Passed) { return status_; }
490  }
491  if (restype_==Implicit) {
492  //
493  // get the native residual norms from the solver for this block of right-hand sides.
494  // If the residual is returned in multivector form, use the resnormtype to compute the residual norms.
495  // Otherwise the native residual is assumed to be stored in the resvector_.
496  //
497  std::vector<MagnitudeType> tmp_resvector( curBlksz_ );
498  Teuchos::RCP<const MV> residMV = iSolver->getNativeResiduals( &tmp_resvector );
499  if ( residMV != Teuchos::null ) {
500  tmp_resvector.resize( MVT::GetNumberVecs( *residMV ) );
501  MVT::MvNorm( *residMV, tmp_resvector, resnormtype_ );
502  typename std::vector<int>::iterator p = curLSIdx_.begin();
503  for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
504  // Check if this index is valid
505  if (*p != -1)
506  resvector_[*p] = tmp_resvector[i];
507  }
508  } else {
509  typename std::vector<int>::iterator p = curLSIdx_.begin();
510  for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
511  // Check if this index is valid
512  if (*p != -1)
513  resvector_[*p] = tmp_resvector[i];
514  }
515  }
516  }
517  else if (restype_==Explicit) {
518  //
519  // Request the true residual for this block of right-hand sides.
520  //
521  Teuchos::RCP<MV> cur_update = iSolver->getCurrentUpdate();
522  curSoln_ = lp.updateSolution( cur_update );
523  Teuchos::RCP<MV> cur_res = MVT::Clone( *curSoln_, MVT::GetNumberVecs( *curSoln_ ) );
524  lp.computeCurrResVec( &*cur_res, &*curSoln_ );
525  std::vector<MagnitudeType> tmp_resvector( MVT::GetNumberVecs( *cur_res ) );
526  MVT::MvNorm( *cur_res, tmp_resvector, resnormtype_ );
527  typename std::vector<int>::iterator p = curLSIdx_.begin();
528  for (int i=0; p<curLSIdx_.end(); ++p, ++i) {
529  // Check if this index is valid
530  if (*p != -1)
531  resvector_[*p] = tmp_resvector[i];
532  }
533  }
534  //
535  // Compute the new linear system residuals for testing.
536  // (if any of them don't meet the tolerance or are NaN, then we exit with that status)
537  //
538  if ( scalevector_.size() > 0 ) {
539  typename std::vector<int>::iterator p = curLSIdx_.begin();
540  for (; p<curLSIdx_.end(); ++p) {
541  // Check if this index is valid
542  if (*p != -1) {
543  // Scale the std::vector accordingly
544  testvector_[ *p ] =
545  scalevector_[ *p ] != zero? resvector_[ *p ] / (scalevector_[ *p ] * scalevalue_) : resvector_[ *p ] / scalevalue_;
546  }
547  }
548  }
549  else {
550  typename std::vector<int>::iterator p = curLSIdx_.begin();
551  for (; p<curLSIdx_.end(); ++p) {
552  // Check if this index is valid
553  if (*p != -1)
554  testvector_[ *p ] = resvector_[ *p ] / scalevalue_;
555  }
556  }
557 
558  // Check status of new linear system residuals and see if we have the quorum.
559  int have = 0;
560  ind_.resize( curLSIdx_.size() );
561  typename std::vector<int>::iterator p = curLSIdx_.begin();
562  for (; p<curLSIdx_.end(); ++p) {
563  // Check if this index is valid
564  if (*p != -1) {
565  // Check if any of the residuals are larger than the tolerance.
566  if (testvector_[ *p ] > tolerance_) {
567  // do nothing.
568  } else if (testvector_[ *p ] <= tolerance_) {
569  ind_[have] = *p;
570  have++;
571  } else {
572  // Throw an std::exception if a NaN is found.
573  status_ = Failed;
574  TEUCHOS_TEST_FOR_EXCEPTION(true,StatusTestError,"StatusTestGenResNorm::checkStatus(): NaN has been detected.");
575  }
576  }
577  }
578  ind_.resize(have);
579  int need = (quorum_ == -1) ? curNumRHS_: quorum_;
580  status_ = (have >= need) ? Passed : Failed;
581 
582  // Return the current status
583  return status_;
584 }
585 
586 template <class ScalarType, class MV, class OP>
587 void StatusTestGenResNorm<ScalarType,MV,OP>::print(std::ostream& os, int indent) const
588 {
589  for (int j = 0; j < indent; j ++)
590  os << ' ';
591  printStatus(os, status_);
592  os << resFormStr();
593  if (status_==Undefined)
594  os << ", tol = " << tolerance_ << std::endl;
595  else {
596  os << std::endl;
597  if(showMaxResNormOnly_ && curBlksz_ > 1) {
598  const MagnitudeType maxRelRes = *std::max_element(
599  testvector_.begin()+curLSIdx_[0],testvector_.begin()+curLSIdx_[curBlksz_-1]
600  );
601  for (int j = 0; j < indent + 13; j ++)
602  os << ' ';
603  os << "max{residual["<<curLSIdx_[0]<<"..."<<curLSIdx_[curBlksz_-1]<<"]} = " << maxRelRes
604  << ( maxRelRes <= tolerance_ ? " <= " : " > " ) << tolerance_ << std::endl;
605  }
606  else {
607  for ( int i=0; i<numrhs_; i++ ) {
608  for (int j = 0; j < indent + 13; j ++)
609  os << ' ';
610  os << "residual [ " << i << " ] = " << testvector_[ i ];
611  os << ((testvector_[i]<tolerance_) ? " < " : (testvector_[i]==tolerance_) ? " == " : (testvector_[i]>tolerance_) ? " > " : " " ) << tolerance_ << std::endl;
612  }
613  }
614  }
615  os << std::endl;
616 }
617 
618 template <class ScalarType, class MV, class OP>
620 {
621  os << std::left << std::setw(13) << std::setfill('.');
622  switch (type) {
623  case Passed:
624  os << "Converged";
625  break;
626  case Failed:
627  os << "Unconverged";
628  break;
629  case Undefined:
630  default:
631  os << "**";
632  break;
633  }
634  os << std::left << std::setfill(' ');
635  return;
636 }
637 
638 template <class ScalarType, class MV, class OP>
640 {
641  int i;
644  const LinearProblem<ScalarType,MV,OP>& lp = iSolver->getProblem();
645  // Compute scaling term (done once for each block that's being solved)
646  if (firstcallCheckStatus_) {
647  //
648  // Get some current solver information.
649  //
650  firstcallCheckStatus_ = false;
651 
652  if (scaletype_== NormOfRHS) {
653  Teuchos::RCP<const MV> rhs = lp.getRHS();
654  numrhs_ = MVT::GetNumberVecs( *rhs );
655  scalevector_.resize( numrhs_ );
656  MVT::MvNorm( *rhs, scalevector_, scalenormtype_ );
657  }
658  else if (scaletype_==NormOfInitRes || scaletype_==NormOfFullInitRes || scaletype_==NormOfFullScaledInitRes) {
659  Teuchos::RCP<const MV> init_res = lp.getInitResVec();
660  numrhs_ = MVT::GetNumberVecs( *init_res );
661  scalevector_.resize( numrhs_ );
662  MVT::MvNorm( *init_res, scalevector_, scalenormtype_ );
663  }
664  else if (scaletype_==NormOfPrecInitRes || scaletype_==NormOfFullPrecInitRes || scaletype_==NormOfFullScaledPrecInitRes) {
666  numrhs_ = MVT::GetNumberVecs( *init_res );
667  scalevector_.resize( numrhs_ );
668  MVT::MvNorm( *init_res, scalevector_, scalenormtype_ );
669  }
670  else {
671  numrhs_ = MVT::GetNumberVecs( *(lp.getRHS()) );
672  }
673 
674  resvector_.resize( numrhs_ );
675  testvector_.resize( numrhs_ );
676 
677  curLSNum_ = lp.getLSNumber();
678  curLSIdx_ = lp.getLSIndex();
679  curBlksz_ = (int)curLSIdx_.size();
680  int validLS = 0;
681  for (i=0; i<curBlksz_; ++i) {
682  if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
683  validLS++;
684  }
685  curNumRHS_ = validLS;
686  //
687  // Initialize the testvector.
688  for (i=0; i<numrhs_; i++) { testvector_[i] = one; }
689 
690  // Return an error if the scaling is zero.
691  if (scalevalue_ == zero) {
692  return Failed;
693  }
694  }
695  return Undefined;
696 }
697 
698 } // end namespace Belos
699 
700 #endif /* BELOS_STATUS_TEST_RESNORM_H */
virtual Teuchos::RCP< const MV > getNativeResiduals(std::vector< typename Teuchos::ScalarTraits< ScalarType >::magnitudeType > *norms) const =0
Get the residuals native to the solver.
int defineScaleForm(ScaleType TypeOfScaling, NormType TypeOfNorm, MagnitudeType ScaleValue=Teuchos::ScalarTraits< MagnitudeType >::one())
Define form of the scaling, its norm, its optional weighting std::vector, or, alternatively, define an explicit value.
MagnitudeType getTolerance() const
Returns the value of the tolerance, , set in the constructor.
const std::vector< MagnitudeType > * getTestValue() const
Returns the test value, , computed in most recent call to CheckStatus.
ScaleType
The type of scaling to use on the residual norm value.
Definition: BelosTypes.hpp:120
Exception thrown to signal error in a status test during Belos::StatusTest::checkStatus().
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 std::vector.
virtual Teuchos::RCP< MV > updateSolution(const Teuchos::RCP< MV > &update=Teuchos::null, bool updateLP=false, ScalarType scale=Teuchos::ScalarTraits< ScalarType >::one())
Compute the new solution to the linear system using the given update vector.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
virtual Teuchos::RCP< MV > getCurrentUpdate() const =0
Get the current update to the linear system.
Declaration of basic traits for the multivector type.
std::string description() const
Method to return description of the maximum iteration status test.
Teuchos::RCP< const MV > getInitPrecResVec() const
A pointer to the preconditioned initial residual vector.
An abstract class of StatusTest for stopping criteria using residual norms.
void printStatus(std::ostream &os, StatusType type) const
Print message for each status specific to this stopping test.
An implementation of StatusTestResNorm using a family of residual norms.
Teuchos::RCP< const MV > getRHS() const
A pointer to the right-hand side B.
StatusType
Whether the StatusTest wants iteration to stop.
Definition: BelosTypes.hpp:189
const std::vector< MagnitudeType > * getResNormValue() const
Returns the residual norm value, , computed in most recent call to CheckStatus.
Traits class which defines basic operations on multivectors.
const std::vector< int > & getLSIndex() const
(Zero-based) indices of the linear system(s) currently being solved.
MultiVecTraits< ScalarType, MV > MVT
bool getShowMaxResNormOnly()
Returns whether the only maximum residual norm is displayed when the print() method is called...
int defineResForm(ResType TypeOfResidual, NormType TypeOfNorm)
Define form of the residual, its norm and optional weighting std::vector.
Teuchos::ScalarTraits< ScalarType > SCT
A linear system to solve, and its associated information.
Class which describes the linear problem to be solved by the iterative solver.
int getLSNumber() const
The number of linear systems that have been set.
int setQuorum(int quorum)
Sets the number of residuals that must pass the convergence test before Passed is returned...
std::vector< int > convIndices()
Returns the std::vector containing the indices of the residuals that passed the test.
virtual const LinearProblem< ScalarType, MV, OP > & getProblem() const =0
Get a constant reference to the linear problem.
Teuchos::RCP< const MV > getInitResVec() const
A pointer to the initial unpreconditioned residual vector.
Belos::StatusTest abstract class for specifying a residual norm stopping criteria.
StatusType getStatus() const
Return the result of the most recent CheckStatus call.
int setTolerance(MagnitudeType tolerance)
Set the value of the tolerance.
NormType
The type of vector norm to compute.
Definition: BelosTypes.hpp:97
StatusType checkStatus(Iteration< ScalarType, MV, OP > *iSolver)
Check convergence status: Passed, Failed, or Undefined.
virtual void computeCurrResVec(MV *R, const MV *X=0, const MV *B=0) const
Compute a residual R for this operator given a solution X, and right-hand side B. ...
void print(std::ostream &os, int indent=0) const
Output formatted description of stopping test to output stream.
ResType
Select how the residual std::vector is produced.
void reset()
Resets the internal configuration to the initial state.
int getQuorum() const
Returns the number of residuals that must pass the convergence test before Passed is returned...
StatusTestGenResNorm(MagnitudeType Tolerance, int quorum=-1, bool showMaxResNormOnly=false)
Constructor.
const std::vector< MagnitudeType > * getScaledNormValue() const
Returns the scaled norm value, .
Teuchos::RCP< MV > getSolution()
Returns the current solution estimate that was computed for the most recent residual test...
bool getLOADetected() const
Returns a boolean indicating a loss of accuracy has been detected in computing the residual...

Generated on Mon Nov 4 2024 09:26:14 for Belos by doxygen 1.8.5