MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosXpetraStatusTestGenResSubNorm.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 // Tobias Wiesner (tawiesn@sandia.gov)
43 //
44 // ***********************************************************************
45 //
46 // @HEADER
47 #ifndef BELOS_XPETRA_STATUS_TEST_GEN_RES_SUB_NORM_HPP
48 #define BELOS_XPETRA_STATUS_TEST_GEN_RES_SUB_NORM_HPP
49 
50 #include "Xpetra_ConfigDefs.hpp"
51 
53 
54 #include "MueLu_Exceptions.hpp"
55 
56 #include <BelosConfigDefs.hpp>
57 #include <BelosTypes.hpp>
58 #include <BelosOperatorT.hpp>
59 #include <BelosXpetraAdapterOperator.hpp>
60 #include <BelosStatusTestGenResSubNorm.hpp>
61 
62 namespace Belos {
63 
67 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68 class StatusTestGenResSubNorm<Scalar, Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>, Belos::OperatorT<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > >
69  : public StatusTestResNorm<Scalar, Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>, Belos::OperatorT<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> > > {
70  public:
71  // Convenience typedefs
75  typedef Belos::OperatorT<MV> OP;
76 
79  typedef MultiVecTraits<Scalar, MV> MVT;
80  typedef OperatorTraits<Scalar, MV, OP> OT;
81 
83 
84 
97  StatusTestGenResSubNorm(MagnitudeType Tolerance, size_t subIdx, int quorum = -1, bool showMaxResNormOnly = false)
98  : tolerance_(Tolerance)
99  , subIdx_(subIdx)
100  , quorum_(quorum)
101  , showMaxResNormOnly_(showMaxResNormOnly)
102  , resnormtype_(TwoNorm)
103  , scaletype_(NormOfInitRes)
104  , scalenormtype_(TwoNorm)
105  , scalevalue_(Teuchos::ScalarTraits<MagnitudeType>::one())
106  , status_(Undefined)
107  , curBlksz_(0)
108  , curNumRHS_(0)
109  , curLSNum_(0)
110  , numrhs_(0)
111  , firstcallCheckStatus_(true)
112  , firstcallDefineResForm_(true)
113  , firstcallDefineScaleForm_(true)
114  , mapExtractor_(Teuchos::null) {}
115 
117  virtual ~StatusTestGenResSubNorm(){};
119 
121 
122 
124 
130  int defineResForm(NormType TypeOfNorm) {
131  TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineResForm_ == false, StatusTestError,
132  "StatusTestGenResSubNorm::defineResForm(): The residual form has already been defined.");
133  firstcallDefineResForm_ = false;
134 
135  resnormtype_ = TypeOfNorm;
136 
137  return (0);
138  }
139 
141 
161  int defineScaleForm(ScaleType TypeOfScaling, NormType TypeOfNorm, MagnitudeType ScaleValue = Teuchos::ScalarTraits<MagnitudeType>::one()) {
162  TEUCHOS_TEST_FOR_EXCEPTION(firstcallDefineScaleForm_ == false, StatusTestError,
163  "StatusTestGenResSubNorm::defineScaleForm(): The scaling type has already been defined.");
164  firstcallDefineScaleForm_ = false;
165 
166  scaletype_ = TypeOfScaling;
167  scalenormtype_ = TypeOfNorm;
168  scalevalue_ = ScaleValue;
169 
170  return (0);
171  }
172 
174 
177  int setTolerance(MagnitudeType tolerance) {
178  tolerance_ = tolerance;
179  return (0);
180  }
181 
183 
185  int setSubIdx(size_t subIdx) {
186  subIdx_ = subIdx;
187  return (0);
188  }
189 
192  int setQuorum(int quorum) {
193  quorum_ = quorum;
194  return (0);
195  }
196 
198  int setShowMaxResNormOnly(bool showMaxResNormOnly) {
199  showMaxResNormOnly_ = showMaxResNormOnly;
200  return (0);
201  }
202 
204 
206 
207 
214  StatusType checkStatus(Iteration<Scalar, MV, OP>* iSolver) {
215  MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
216  const LinearProblem<Scalar, MV, OP>& lp = iSolver->getProblem();
217  // Compute scaling term (done once for each block that's being solved)
218  if (firstcallCheckStatus_) {
219  StatusType status = firstCallCheckStatusSetup(iSolver);
220  if (status == Failed) {
221  status_ = Failed;
222  return (status_);
223  }
224  }
225 
226  //
227  // This section computes the norm of the residual std::vector
228  //
229  if (curLSNum_ != lp.getLSNumber()) {
230  //
231  // We have moved on to the next rhs block
232  //
233  curLSNum_ = lp.getLSNumber();
234  curLSIdx_ = lp.getLSIndex();
235  curBlksz_ = (int)curLSIdx_.size();
236  int validLS = 0;
237  for (int i = 0; i < curBlksz_; ++i) {
238  if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
239  validLS++;
240  }
241  curNumRHS_ = validLS;
242  curSoln_ = Teuchos::null;
243  //
244  } else {
245  //
246  // We are in the same rhs block, return if we are converged
247  //
248  if (status_ == Passed) {
249  return status_;
250  }
251  }
252 
253  //
254  // Request the true residual for this block of right-hand sides.
255  //
256  Teuchos::RCP<MV> cur_update = iSolver->getCurrentUpdate();
257  curSoln_ = lp.updateSolution(cur_update);
258  Teuchos::RCP<MV> cur_res = MVT::Clone(*curSoln_, MVT::GetNumberVecs(*curSoln_));
259  lp.computeCurrResVec(&*cur_res, &*curSoln_);
260  std::vector<MagnitudeType> tmp_resvector(MVT::GetNumberVecs(*cur_res));
261  MvSubNorm(*cur_res, subIdx_, tmp_resvector, resnormtype_);
262 
263  typename std::vector<int>::iterator p = curLSIdx_.begin();
264  for (int i = 0; p < curLSIdx_.end(); ++p, ++i) {
265  // Check if this index is valid
266  if (*p != -1)
267  resvector_[*p] = tmp_resvector[i];
268  }
269 
270  //
271  // Compute the new linear system residuals for testing.
272  // (if any of them don't meet the tolerance or are NaN, then we exit with that status)
273  //
274  if (scalevector_.size() > 0) {
275  typename std::vector<int>::iterator pp = curLSIdx_.begin();
276  for (; pp < curLSIdx_.end(); ++pp) {
277  // Check if this index is valid
278  if (*pp != -1) {
279  // Scale the std::vector accordingly
280  if (scalevector_[*pp] != zero) {
281  // Don't intentionally divide by zero.
282  testvector_[*pp] = resvector_[*pp] / scalevector_[*pp] / scalevalue_;
283  } else {
284  testvector_[*pp] = resvector_[*pp] / scalevalue_;
285  }
286  }
287  }
288  } else {
289  typename std::vector<int>::iterator pp = curLSIdx_.begin();
290  for (; pp < curLSIdx_.end(); ++pp) {
291  // Check if this index is valid
292  if (*pp != -1)
293  testvector_[*pp] = resvector_[*pp] / scalevalue_;
294  }
295  }
296  // Check status of new linear system residuals and see if we have the quorum.
297  int have = 0;
298  ind_.resize(curLSIdx_.size());
299  typename std::vector<int>::iterator p2 = curLSIdx_.begin();
300  for (; p2 < curLSIdx_.end(); ++p2) {
301  // Check if this index is valid
302  if (*p2 != -1) {
303  // Check if any of the residuals are larger than the tolerance.
304  if (testvector_[*p2] > tolerance_) {
305  // do nothing.
307  reset();
308  } else if (testvector_[*p2] <= tolerance_) {
309  ind_[have] = *p2;
310  have++;
311  } else {
312  // Throw an std::exception if a NaN is found.
313  status_ = Failed;
314  TEUCHOS_TEST_FOR_EXCEPTION(true, StatusTestError, "StatusTestGenResSubNorm::checkStatus(): NaN has been detected.");
315  }
316  }
317  }
318  ind_.resize(have);
319  int need = (quorum_ == -1) ? curNumRHS_ : quorum_;
320  status_ = (have >= need) ? Passed : Failed;
321  // Return the current status
322  return status_;
323  }
324 
326  StatusType getStatus() const { return (status_); };
328 
330 
331 
333  void reset() {
334  status_ = Undefined;
335  curBlksz_ = 0;
336  curLSNum_ = 0;
337  curLSIdx_.resize(0);
338  numrhs_ = 0;
339  ind_.resize(0);
340  firstcallCheckStatus_ = true;
341  curSoln_ = Teuchos::null;
342  }
343 
345 
347 
348 
350  void print(std::ostream& os, int indent = 0) const {
351  os.setf(std::ios_base::scientific);
352  for (int j = 0; j < indent; j++)
353  os << ' ';
354  printStatus(os, status_);
355  os << resFormStr();
356  if (status_ == Undefined)
357  os << ", tol = " << tolerance_ << std::endl;
358  else {
359  os << std::endl;
360  if (showMaxResNormOnly_ && curBlksz_ > 1) {
361  const MagnitudeType maxRelRes = *std::max_element(
362  testvector_.begin() + curLSIdx_[0], testvector_.begin() + curLSIdx_[curBlksz_ - 1]);
363  for (int j = 0; j < indent + 13; j++)
364  os << ' ';
365  os << "max{residual[" << curLSIdx_[0] << "..." << curLSIdx_[curBlksz_ - 1] << "]} = " << maxRelRes
366  << (maxRelRes <= tolerance_ ? " <= " : " > ") << tolerance_ << std::endl;
367  } else {
368  for (int i = 0; i < numrhs_; i++) {
369  for (int j = 0; j < indent + 13; j++)
370  os << ' ';
371  os << "residual [ " << i << " ] = " << testvector_[i];
372  os << ((testvector_[i] < tolerance_) ? " < " : (testvector_[i] == tolerance_) ? " == "
373  : (testvector_[i] > tolerance_) ? " > "
374  : " ")
375  << tolerance_ << std::endl;
376  }
377  }
378  }
379  os << std::endl;
380  }
381 
383  void printStatus(std::ostream& os, StatusType type) const {
384  os << std::left << std::setw(13) << std::setfill('.');
385  switch (type) {
386  case Passed:
387  os << "Converged";
388  break;
389  case Failed:
390  os << "Unconverged";
391  break;
392  case Undefined:
393  default:
394  os << "**";
395  break;
396  }
397  os << std::left << std::setfill(' ');
398  return;
399  }
401 
403 
404 
406  Teuchos::RCP<MV> getSolution() { return curSoln_; }
407 
410  int getQuorum() const { return quorum_; }
411 
413  size_t getSubIdx() const { return subIdx_; }
414 
416  bool getShowMaxResNormOnly() { return showMaxResNormOnly_; }
417 
419  std::vector<int> convIndices() { return ind_; }
420 
422  MagnitudeType getTolerance() const { return (tolerance_); };
423 
425  const std::vector<MagnitudeType>* getTestValue() const { return (&testvector_); };
426 
428  const std::vector<MagnitudeType>* getResNormValue() const { return (&resvector_); };
429 
431  const std::vector<MagnitudeType>* getScaledNormValue() const { return (&scalevector_); };
432 
435  bool getLOADetected() const { return false; }
436 
438 
441 
447  StatusType firstCallCheckStatusSetup(Iteration<Scalar, MV, OP>* iSolver) {
448  int i;
449  MagnitudeType zero = Teuchos::ScalarTraits<MagnitudeType>::zero();
450  MagnitudeType one = Teuchos::ScalarTraits<MagnitudeType>::one();
451  const LinearProblem<Scalar, MV, OP>& lp = iSolver->getProblem();
452  // Compute scaling term (done once for each block that's being solved)
453  if (firstcallCheckStatus_) {
454  //
455  // Get some current solver information.
456  //
457  firstcallCheckStatus_ = false;
458 
459  // try to access the underlying blocked operator
460  Teuchos::RCP<const OP> Op = lp.getOperator();
462  Teuchos::rcp_dynamic_cast<const Belos::XpetraOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(Op);
463  TEUCHOS_TEST_FOR_EXCEPTION(xOp.is_null(), MueLu::Exceptions::BadCast, "Bad cast from \'const Belos::OperatorT\' to \'const Belos::XpetraOp\'. The origin type is " << typeid(const OP).name() << ".");
465  xOp->getOperator();
466  TEUCHOS_TEST_FOR_EXCEPTION(xIntOp.is_null(), MueLu::Exceptions::BadCast, "Cannot access Xpetra::Operator stored in Belos::XpetraOperator.");
468  Teuchos::rcp_dynamic_cast<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >(xIntOp);
469  TEUCHOS_TEST_FOR_EXCEPTION(xMat.is_null(), MueLu::Exceptions::RuntimeError, "Cannot access Xpetra::Matrix stored in Belos::XpetraOp. Error.");
471  TEUCHOS_TEST_FOR_EXCEPTION(bMat.is_null(), MueLu::Exceptions::BadCast, "Bad cast from \'const Xpetra::Matrix\' to \'const Xpetra::BlockedCrsMatrix\'. The origin type is " << typeid(const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>).name() << ". Note: you need a BlockedCrsMatrix object for the StatusTestGenResSubNorm to work!");
472  mapExtractor_ = bMat->getRangeMapExtractor();
473  TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor_.is_null(), MueLu::Exceptions::RuntimeError, "Could not extract map extractor from BlockedCrsMatrix. Error.");
474  TEUCHOS_TEST_FOR_EXCEPTION(mapExtractor_->NumMaps() <= subIdx_, MueLu::Exceptions::RuntimeError, "The multivector is only split into " << mapExtractor_->NumMaps() << " sub parts. Cannot access sub-block " << subIdx_ << ".");
475 
476  // calculate initial norms
477  if (scaletype_ == NormOfRHS) {
478  Teuchos::RCP<const MV> rhs = lp.getRHS();
479  numrhs_ = MVT::GetNumberVecs(*rhs);
480  scalevector_.resize(numrhs_);
481  MvSubNorm(*rhs, subIdx_, scalevector_, scalenormtype_);
482  } else if (scaletype_ == NormOfInitRes) {
483  Teuchos::RCP<const MV> init_res = lp.getInitResVec();
484  numrhs_ = MVT::GetNumberVecs(*init_res);
485  scalevector_.resize(numrhs_);
486  MvSubNorm(*init_res, subIdx_, scalevector_, scalenormtype_);
487  } else if (scaletype_ == NormOfPrecInitRes) {
488  Teuchos::RCP<const MV> init_res = lp.getInitPrecResVec();
489  numrhs_ = MVT::GetNumberVecs(*init_res);
490  scalevector_.resize(numrhs_);
491  MvSubNorm(*init_res, subIdx_, scalevector_, scalenormtype_);
492  } else if (scaletype_ == NormOfFullInitRes) {
493  Teuchos::RCP<const MV> init_res = lp.getInitResVec();
494  numrhs_ = MVT::GetNumberVecs(*init_res);
495  scalevector_.resize(numrhs_);
496  MVT::MvNorm(*init_res, scalevector_, scalenormtype_);
497  scalevalue_ = one;
498  } else if (scaletype_ == NormOfFullPrecInitRes) {
499  Teuchos::RCP<const MV> init_res = lp.getInitPrecResVec();
500  numrhs_ = MVT::GetNumberVecs(*init_res);
501  scalevector_.resize(numrhs_);
502  MVT::MvNorm(*init_res, scalevector_, scalenormtype_);
503  scalevalue_ = one;
504  } else if (scaletype_ == NormOfFullScaledInitRes) {
505  Teuchos::RCP<const MV> init_res = lp.getInitResVec();
506  numrhs_ = MVT::GetNumberVecs(*init_res);
507  scalevector_.resize(numrhs_);
508  MVT::MvNorm(*init_res, scalevector_, scalenormtype_);
509  MvScalingRatio(*init_res, subIdx_, scalevalue_);
510  } else if (scaletype_ == NormOfFullScaledPrecInitRes) {
511  Teuchos::RCP<const MV> init_res = lp.getInitPrecResVec();
512  numrhs_ = MVT::GetNumberVecs(*init_res);
513  scalevector_.resize(numrhs_);
514  MVT::MvNorm(*init_res, scalevector_, scalenormtype_);
515  MvScalingRatio(*init_res, subIdx_, scalevalue_);
516  } else {
517  numrhs_ = MVT::GetNumberVecs(*(lp.getRHS()));
518  }
519 
520  resvector_.resize(numrhs_);
521  testvector_.resize(numrhs_);
522 
523  curLSNum_ = lp.getLSNumber();
524  curLSIdx_ = lp.getLSIndex();
525  curBlksz_ = (int)curLSIdx_.size();
526  int validLS = 0;
527  for (i = 0; i < curBlksz_; ++i) {
528  if (curLSIdx_[i] > -1 && curLSIdx_[i] < numrhs_)
529  validLS++;
530  }
531  curNumRHS_ = validLS;
532  //
533  // Initialize the testvector.
534  for (i = 0; i < numrhs_; i++) {
535  testvector_[i] = one;
536  }
537 
538  // Return an error if the scaling is zero.
539  if (scalevalue_ == zero) {
540  return Failed;
541  }
542  }
543  return Undefined;
544  }
546 
549 
551  std::string description() const {
552  std::ostringstream oss;
553  oss << "Belos::StatusTestGenResSubNorm<>: " << resFormStr();
554  oss << ", tol = " << tolerance_;
555  return oss.str();
556  }
558 
559  protected:
560  private:
562 
563 
564  std::string resFormStr() const {
565  std::ostringstream oss;
566  oss << "(";
567  oss << ((resnormtype_ == OneNorm) ? "1-Norm" : (resnormtype_ == TwoNorm) ? "2-Norm"
568  : "Inf-Norm");
569  oss << " Exp";
570  oss << " Res Vec [" << subIdx_ << "]) ";
571 
572  // If there is no residual scaling, return current string.
573  if (scaletype_ != None) {
574  // Insert division sign.
575  oss << "/ ";
576 
577  // Determine output string for scaling, if there is any.
578  if (scaletype_ == UserProvided)
579  oss << " (User Scale)";
580  else {
581  oss << "(";
582  oss << ((scalenormtype_ == OneNorm) ? "1-Norm" : (resnormtype_ == TwoNorm) ? "2-Norm"
583  : "Inf-Norm");
584  if (scaletype_ == NormOfInitRes)
585  oss << " Res0 [" << subIdx_ << "]";
586  else if (scaletype_ == NormOfPrecInitRes)
587  oss << " Prec Res0 [" << subIdx_ << "]";
588  else if (scaletype_ == NormOfFullInitRes)
589  oss << " Full Res0 [" << subIdx_ << "]";
590  else if (scaletype_ == NormOfFullPrecInitRes)
591  oss << " Full Prec Res0 [" << subIdx_ << "]";
592  else if (scaletype_ == NormOfFullScaledInitRes)
593  oss << " scaled Full Res0 [" << subIdx_ << "]";
594  else if (scaletype_ == NormOfFullScaledPrecInitRes)
595  oss << " scaled Full Prec Res0 [" << subIdx_ << "]";
596  else
597  oss << " RHS [" << subIdx_ << "]";
598  oss << ")";
599  }
600  }
601 
602  // TODO add a tagging name
603 
604  return oss.str();
605  }
606 
608 
610 
611 
612  // calculate norm of partial multivector
613  void MvSubNorm(const MV& mv, size_t block, std::vector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>& normVec, NormType type = TwoNorm) {
614  Teuchos::RCP<const MV> input = Teuchos::rcpFromRef(mv);
615 
616  Teuchos::RCP<const MV> SubVec = mapExtractor_->ExtractVector(input, block);
617  MVT::MvNorm(*SubVec, normVec, type);
618  }
619 
620  // calculate ration of sub-vector length to full vector length (for scalevalue_)
621  void MvScalingRatio(const MV& mv, size_t block, MagnitudeType& lengthRatio) {
622  Teuchos::RCP<const MV> input = Teuchos::rcpFromRef(mv);
623 
624  Teuchos::RCP<const MV> SubVec = mapExtractor_->ExtractVector(input, block);
625 
626  lengthRatio = Teuchos::as<MagnitudeType>(SubVec->getGlobalLength()) / Teuchos::as<MagnitudeType>(input->getGlobalLength());
627  }
629 
631 
632 
634  MagnitudeType tolerance_;
635 
637  size_t subIdx_;
638 
640  int quorum_;
641 
643  bool showMaxResNormOnly_;
644 
646  NormType resnormtype_;
647 
649  ScaleType scaletype_;
650 
652  NormType scalenormtype_;
653 
655  MagnitudeType scalevalue_;
656 
658  std::vector<MagnitudeType> scalevector_;
659 
661  std::vector<MagnitudeType> resvector_;
662 
664  std::vector<MagnitudeType> testvector_;
665 
667  std::vector<int> ind_;
668 
670  Teuchos::RCP<MV> curSoln_;
671 
673  StatusType status_;
674 
676  int curBlksz_;
677 
679  int curNumRHS_;
680 
682  std::vector<int> curLSIdx_;
683 
685  int curLSNum_;
686 
688  int numrhs_;
689 
691  bool firstcallCheckStatus_;
692 
694  bool firstcallDefineResForm_;
695 
697  bool firstcallDefineScaleForm_;
698 
700  Teuchos::RCP<const ME> mapExtractor_;
702 };
703 
704 } // namespace Belos
705 
706 #endif /* BELOS_XPETRA_STATUS_TEST_GEN_RES_SUB_NORM_HPP */
Exception indicating invalid cast attempted.
void reset()
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
MueLu::DefaultScalar Scalar
Exception throws to report errors in the internal logical of the program.
bool is_null() const