Anasazi Version of the Day
Loading...
Searching...
No Matches
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
23#include "Teuchos_SerialDenseSolver.hpp"
24
25using Teuchos::RCP;
26
27enum PrecType {NO_PREC, NONSYM, BD_PREC, HSS_PREC};
28
29namespace Anasazi {
30namespace Experimental {
31
32template <class ScalarType, class MV, class OP>
33class SaddleOperator : public TraceMinOp<ScalarType,SaddleContainer<ScalarType,MV>,OP>
34{
36 typedef Teuchos::SerialDenseMatrix<int,ScalarType> SerialDenseMatrix;
37
38public:
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
48private:
49 // A is the 1-1 block, and B the 1-2 block
50 Teuchos::RCP<OP> A_;
51 Teuchos::RCP<const MV> B_;
52 Teuchos::RCP<SerialDenseMatrix> Schur_;
53 PrecType pt_;
54 ScalarType alpha_;
55};
56
57
58
59// Default constructor
60template <class ScalarType, class MV, class OP>
61SaddleOperator<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"
83template <class ScalarType, class MV, class OP>
84void 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 {
110 Teuchos::SerialDenseSolver<int,ScalarType> MySolver;
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
172template<class ScalarType, class MV, class OP>
173class OperatorTraits<ScalarType, Experimental::SaddleContainer<ScalarType,MV>, Experimental::SaddleOperator<ScalarType,MV,OP> >
174{
175public:
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
185namespace Belos {
186
187template<class ScalarType, class MV, class OP>
188class OperatorTraits<ScalarType, Anasazi::Experimental::SaddleContainer<ScalarType,MV>, Anasazi::Experimental::SaddleOperator<ScalarType,MV,OP> >
189{
190public:
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
Anasazi header file which uses auto-configuration information to include necessary C++ headers.
Stores a set of vectors of the form [V; L] where V is a distributed multivector and L is a serialdens...
Traits class which defines basic operations on multivectors.
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...
Namespace Anasazi contains the classes, structs, enums and utilities used by the Anasazi package.