Anasazi  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AnasaziSaddleOperator.hpp
Go to the documentation of this file.
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 
16 #ifndef ANASAZI_SADDLE_OPERATOR_HPP
17 #define ANASAZI_SADDLE_OPERATOR_HPP
18 
19 #include "AnasaziConfigDefs.hpp"
22 
24 
25 using Teuchos::RCP;
26 
27 enum PrecType {NO_PREC, NONSYM, BD_PREC, HSS_PREC};
28 
29 namespace Anasazi {
30 namespace Experimental {
31 
32 template <class ScalarType, class MV, class OP>
33 class SaddleOperator : public TraceMinOp<ScalarType,SaddleContainer<ScalarType,MV>,OP>
34 {
36  typedef Teuchos::SerialDenseMatrix<int,ScalarType> SerialDenseMatrix;
37 
38 public:
39  // Default constructor
40  SaddleOperator( ) { };
41  SaddleOperator( const Teuchos::RCP<OP> A, const Teuchos::RCP<const MV> B, PrecType pt=NO_PREC, const ScalarType alpha=1. );
42 
43  // Applies the saddle point operator to a "multivector"
44  void Apply(const SaddleContainer<ScalarType,MV>& X, SaddleContainer<ScalarType,MV>& Y) const;
45 
46  void removeIndices(const std::vector<int>& indicesToRemove) { A_->removeIndices(indicesToRemove); };
47 
48 private:
49  // A is the 1-1 block, and B the 1-2 block
53  PrecType pt_;
54  ScalarType alpha_;
55 };
56 
57 
58 
59 // Default constructor
60 template <class ScalarType, class MV, class OP>
61 SaddleOperator<ScalarType, MV, OP>::SaddleOperator( const Teuchos::RCP<OP> A, const Teuchos::RCP<const MV> B, PrecType pt, const ScalarType alpha )
62 {
63  // Get a pointer to A and B
64  A_ = A;
65  B_ = B;
66  pt_ = pt;
67  alpha_ = alpha;
68 
69  if(pt == BD_PREC)
70  {
71  // Form the Schur complement
72  int nvecs = MVT::GetNumberVecs(*B);
73  Teuchos::RCP<MV> AinvB = MVT::Clone(*B,nvecs);
74  Schur_ = rcp(new SerialDenseMatrix(nvecs,nvecs));
75 
76  A_->Apply(*B_,*AinvB);
77 
78  MVT::MvTransMv(1., *B_, *AinvB, *Schur_);
79  }
80 }
81 
82 // Applies the saddle point operator to a "multivector"
83 template <class ScalarType, class MV, class OP>
84 void SaddleOperator<ScalarType, MV, OP>::Apply(const SaddleContainer<ScalarType,MV>& X, SaddleContainer<ScalarType,MV>& Y) const
85 {
86  RCP<SerialDenseMatrix> Xlower = X.getLower();
87  RCP<SerialDenseMatrix> Ylower = Y.getLower();
88 
89  if(pt_ == NO_PREC)
90  {
91  // trans does literally nothing, because the operator is symmetric
92  // Y.bottom = B'X.top
93  MVT::MvTransMv(1., *B_, *(X.upper_), *Ylower);
94 
95  // Y.top = A*X.top+B*X.bottom
96  A_->Apply(*(X.upper_), *(Y.upper_));
97  MVT::MvTimesMatAddMv(1., *B_, *Xlower, 1., *(Y.upper_));
98  }
99  else if(pt_ == NONSYM)
100  {
101  // Y.bottom = -B'X.top
102  MVT::MvTransMv(-1., *B_, *(X.upper_), *Ylower);
103 
104  // Y.top = A*X.top+B*X.bottom
105  A_->Apply(*(X.upper_), *(Y.upper_));
106  MVT::MvTimesMatAddMv(1., *B_, *Xlower, 1., *(Y.upper_));
107  }
108  else if(pt_ == BD_PREC)
109  {
111 
112  // Solve A Y.X = X.X
113  A_->Apply(*(X.upper_),*(Y.upper_));
114 
115  // So, let me tell you a funny story about how the SerialDenseSolver destroys the original matrix...
116  Teuchos::RCP<SerialDenseMatrix> localSchur = Teuchos::rcp(new SerialDenseMatrix(*Schur_));
117 
118  // Solve the small system
119  MySolver.setMatrix(localSchur);
120  MySolver.setVectors(Ylower, Xlower);
121  MySolver.solve();
122  }
123  // Hermitian-Skew Hermitian splitting has some extra requirements
124  // We need B'B = I, which is true for standard eigenvalue problems, but not generalized
125  // We also need to use gmres, because our operator is no longer symmetric
126  else if(pt_ == HSS_PREC)
127  {
128 // std::cout << "applying preconditioner to";
129 // X.MvPrint(std::cout);
130 
131  // Solve (H + alpha I) Y1 = X
132  // 1. Apply preconditioner
133  A_->Apply(*(X.upper_),*(Y.upper_));
134  // 2. Scale by 1/alpha
135  *Ylower = *Xlower;
136  Ylower->scale(1./alpha_);
137 
138 // std::cout << "H preconditioning produced";
139 // Y.setLower(Ylower);
140 // Y.MvPrint(std::cout);
141 
142  // Solve (S + alpha I) Y = Y1
143  // 1. Y_lower = (B' Y1_upper + alpha Y1_lower) / (1 + alpha^2)
144  Teuchos::RCP<SerialDenseMatrix> Y1_lower = Teuchos::rcp(new SerialDenseMatrix(*Ylower));
145  MVT::MvTransMv(1,*B_,*(Y.upper_),*Ylower);
146 // std::cout << "Y'b1 " << *Ylower;
147  Y1_lower->scale(alpha_);
148 // std::cout << "alpha b2 " << *Y1_lower;
149  *Ylower += *Y1_lower;
150 // std::cout << "alpha b2 + Y'b1 " << *Ylower;
151  Ylower->scale(1/(1+alpha_*alpha_));
152  // 2. Y_upper = (Y1_upper - B Y_lower) / alpha
153  MVT::MvTimesMatAddMv(-1/alpha_,*B_,*Ylower,1/alpha_,*(Y.upper_));
154 
155 // std::cout << "preconditioning produced";
156 // Y.setLower(Ylower);
157 // Y.MvPrint(std::cout);
158  }
159  else
160  {
161  std::cout << "Not a valid preconditioner type\n";
162  }
163 
164  Y.setLower(Ylower);
165 
166 // std::cout << "result of applying operator";
167 // Y.MvPrint(std::cout);
168 }
169 
170 } // End namespace Experimental
171 
172 template<class ScalarType, class MV, class OP>
173 class OperatorTraits<ScalarType, Experimental::SaddleContainer<ScalarType,MV>, Experimental::SaddleOperator<ScalarType,MV,OP> >
174 {
175 public:
176  static void Apply( const Experimental::SaddleOperator<ScalarType,MV,OP>& Op,
177  const Experimental::SaddleContainer<ScalarType,MV>& x,
178  Experimental::SaddleContainer<ScalarType,MV>& y)
179  { Op.Apply( x, y); };
180 };
181 
182 } // end namespace Anasazi
183 
184 #ifdef HAVE_ANASAZI_BELOS
185 namespace Belos {
186 
187 template<class ScalarType, class MV, class OP>
188 class OperatorTraits<ScalarType, Anasazi::Experimental::SaddleContainer<ScalarType,MV>, Anasazi::Experimental::SaddleOperator<ScalarType,MV,OP> >
189 {
190 public:
191  static void Apply( const Anasazi::Experimental::SaddleOperator<ScalarType,MV,OP>& Op,
192  const Anasazi::Experimental::SaddleContainer<ScalarType,MV>& x,
193  Anasazi::Experimental::SaddleContainer<ScalarType,MV>& y)
194  { Op.Apply( x, y); };
195 };
196 
197 } // end namespace Belos
198 #endif
199 
200 #endif
static void Apply(const OP &Op, const MV &x, MV &y)
Application method which performs operation y = Op*x. An OperatorError exception is thrown if there i...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Traits class which defines basic operations on multivectors.
Anasazi header file which uses auto-configuration information to include necessary C++ headers...
int setVectors(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &X, const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &B)
Stores a set of vectors of the form [V; L] where V is a distributed multivector and L is a serialdens...
int setMatrix(const RCP< SerialDenseMatrix< OrdinalType, ScalarType > > &A)