Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziStatusTestSpecTrans.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Anasazi: Block Eigensolvers Package
4 //
5 // Copyright 2004 NTESS and the Anasazi contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef ANASAZI_STATUS_TEST_SPECTRANS_HPP
11 #define ANASAZI_STATUS_TEST_SPECTRANS_HPP
12 
13 #include "AnasaziTypes.hpp"
15 #include "AnasaziTraceMinBase.hpp"
16 
17 using Teuchos::RCP;
18 
19 namespace Anasazi {
20 namespace Experimental {
21 
22  template<class ScalarType, class MV, class OP>
23  class StatusTestSpecTrans : public StatusTest<ScalarType,MV,OP> {
24 
25  typedef typename Teuchos::ScalarTraits<ScalarType>::magnitudeType MagnitudeType;
26  typedef MultiVecTraits<ScalarType,MV> MVT;
27  typedef OperatorTraits<ScalarType,MV,OP> OPT;
28 
29  public:
30 
31  // Constructor
32  StatusTestSpecTrans(MagnitudeType tol, int quorum = -1, ResType whichNorm = RES_2NORM, bool scaled = true, bool throwExceptionOnNan = true, const RCP<const OP> Mop = Teuchos::null);
33 
34  // Destructor
35  virtual ~StatusTestSpecTrans() {};
36 
37  // Check whether the test passed or failed
38  TestStatus checkStatus(Eigensolver<ScalarType,MV,OP> *solver);
39 
40  // Return the result of the most recent checkStatus call
41  TestStatus getStatus() const { return state_; }
42 
43  // Get the indices for the vectors that passed the test
44  std::vector<int> whichVecs() const { return ind_; }
45 
46  // Get the number of vectors that passed the test
47  int howMany() const { return ind_.size(); }
48 
49  void setQuorum (int quorum) {
50  state_ = Undefined;
51  quorum_ = quorum;
52  }
53 
54  int getQuorum() const { return quorum_; }
55 
56  void setTolerance(MagnitudeType tol)
57  {
58  state_ = Undefined;
59  tol_ = tol;
60  }
61 
62  MagnitudeType getTolerance() const { return tol_; }
63 
64  void setWhichNorm(ResType whichNorm)
65  {
66  state_ = Undefined;
67  whichNorm_ = whichNorm;
68  }
69 
70  ResType getWhichNorm() const { return whichNorm_; }
71 
72  void setScale(bool relscale)
73  {
74  state_ = Undefined;
75  scaled_ = relscale;
76  }
77 
78  bool getScale() const { return scaled_; }
79 
80  // Informs the status test that it should reset its internal configuration to the uninitialized state
81  void reset()
82  {
83  ind_.resize(0);
84  state_ = Undefined;
85  }
86 
87  // Clears the results of the last status test
88  void clearStatus() { reset(); };
89 
90  // Output formatted description of stopping test to output stream
91  std::ostream & print(std::ostream &os, int indent=0) const;
92 
93  private:
94  TestStatus state_;
95  MagnitudeType tol_;
96  std::vector<int> ind_;
97  int quorum_;
98  bool scaled_;
99  enum ResType whichNorm_;
100  bool throwExceptionOnNaN_;
101  RCP<const OP> M_;
102 
103  const MagnitudeType ONE;
104  };
105 
106 
107 
108  template <class ScalarType, class MV, class OP>
109  StatusTestSpecTrans<ScalarType,MV,OP>::StatusTestSpecTrans(MagnitudeType tol, int quorum, ResType whichNorm, bool scaled, bool throwExceptionOnNaN, const RCP<const OP> Mop)
110  : state_(Undefined),
111  tol_(tol),
112  quorum_(quorum),
113  scaled_(scaled),
114  whichNorm_(whichNorm),
115  throwExceptionOnNaN_(throwExceptionOnNaN),
116  M_(Mop),
117  ONE(Teuchos::ScalarTraits<MagnitudeType>::one())
118  {}
119 
120 
121 
122  template <class ScalarType, class MV, class OP>
123  TestStatus StatusTestSpecTrans<ScalarType,MV,OP>::checkStatus( Eigensolver<ScalarType,MV,OP>* solver )
124  {
126  typedef TraceMinBase<ScalarType,MV,OP> TS;
127 
128  // Cast the eigensolver to a TraceMin solver
129  // Throw an exception if this fails
130  TS* tm_solver = dynamic_cast<TS*>(solver);
131  TEUCHOS_TEST_FOR_EXCEPTION(tm_solver == 0, std::invalid_argument, "The status test for spectral transformations currently only works for the trace minimization eigensolvers. Sorry!");
132 
133  // Get the residual Ax-\lambda Bx, which is not computed when there's a spectral transformation
134  // TraceMin computes Bx-1/\lambda Ax
135  TraceMinBaseState<ScalarType,MV> state = tm_solver->getState();
136 
137  size_t nvecs = state.ritzShifts->size();
138  std::vector<int> curind(nvecs);
139  for(size_t i=0; i<nvecs; i++)
140  curind[i] = i;
141 
142  RCP<const MV> locKX, locMX, locX;
143  RCP<MV> R;
144  locX = MVT::CloneView(*state.X,curind);
145  if(state.KX != Teuchos::null)
146  locKX = MVT::CloneView(*state.KX,curind);
147  else
148  locKX = locX;
149  if(state.MX != Teuchos::null)
150  locMX = MVT::CloneView(*state.MX,curind);
151  else
152  locMX = locX;
153  R = MVT::CloneCopy(*locKX,curind);
154 
155  std::vector<MagnitudeType> evals(nvecs);
156  for(size_t i=0; i<nvecs; i++)
157  evals[i] = ONE/(*state.T)[i];
158  MVT::MvScale(*R,evals);
159  MVT::MvAddMv(-ONE,*R,ONE,*locMX,*R);
160 
161  // Compute the norms
162  std::vector<MagnitudeType> res(nvecs);
163  switch (whichNorm_) {
164  case RES_2NORM:
165  {
166  MVT::MvNorm(*R,res);
167  break;
168  }
169  case RES_ORTH:
170  {
171  RCP<MV> MR = MVT::Clone(*R,nvecs);
172  OPT::Apply(*M_,*R,*MR);
173  MVT::MvDot(*R,*MR,res);
174  for(size_t i=0; i<nvecs; i++)
175  res[i] = MT::squareroot(res[i]);
176  break;
177  }
178  case RITZRES_2NORM:
179  {
180  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, "The trace minimization solvers do not define a Ritz residual. Please choose a different residual type");
181  break;
182  }
183  }
184 
185  // if appropriate, scale the norms by the magnitude of the eigenvalue estimate
186  if(scaled_)
187  {
188  for(size_t i=0; i<nvecs; i++)
189  res[i] /= std::abs(evals[i]);
190  }
191 
192  // test the norms
193  ind_.resize(0);
194  for(size_t i=0; i<nvecs; i++)
195  {
196  TEUCHOS_TEST_FOR_EXCEPTION( MT::isnaninf(res[i]), ResNormNaNError,
197  "StatusTestSpecTrans::checkStatus(): residual norm is nan or inf" );
198  if(res[i] < tol_)
199  ind_.push_back(i);
200  }
201  int have = ind_.size();
202  int need = (quorum_ == -1) ? nvecs : quorum_;
203  state_ = (have >= need) ? Passed : Failed;
204  return state_;
205  }
206 
207 
208 
209  template <class ScalarType, class MV, class OP>
210  std::ostream& StatusTestSpecTrans<ScalarType,MV,OP>::print(std::ostream& os, int indent) const
211  {
212  std::string ind(indent,' ');
213  os << ind << "- StatusTestSpecTrans: ";
214  switch (state_) {
215  case Passed:
216  os << "Passed\n";
217  break;
218  case Failed:
219  os << "Failed\n";
220  break;
221  case Undefined:
222  os << "Undefined\n";
223  break;
224  }
225  os << ind << " (Tolerance, WhichNorm,Scaled,Quorum): "
226  << "(" << tol_;
227  switch (whichNorm_) {
228  case RES_ORTH:
229  os << ",RES_ORTH";
230  break;
231  case RES_2NORM:
232  os << ",RES_2NORM";
233  break;
234  case RITZRES_2NORM:
235  os << ",RITZRES_2NORM";
236  break;
237  }
238  os << "," << (scaled_ ? "true" : "false")
239  << "," << quorum_
240  << ")\n";
241 
242  if (state_ != Undefined) {
243  os << ind << " Which vectors: ";
244  if (ind_.size() > 0) {
245  for(size_t i=0; i<ind_.size(); i++) os << ind_[i] << " ";
246  os << std::endl;
247  }
248  else
249  os << "[empty]\n";
250  }
251  return os;
252  }
253 
254 }} // end of namespace
255 
256 #endif
Abstract base class for trace minimization eigensolvers.
ResType
Enumerated type used to specify which residual norm used by residual norm status tests.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
TestStatus
Enumerated type used to pass back information from a StatusTest.
A status test for testing the norm of the eigenvectors residuals.
Types and exceptions used within Anasazi solvers and interfaces.