RBGen  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
RBGen_AnasaziPOD.cpp
1 
2 #include "RBGen_AnasaziPOD.h"
3 #include "Epetra_BLAS.h"
4 #include "Epetra_Export.h"
5 #include "Epetra_Import.h"
6 #include "Epetra_Time.h"
7 
8 #include "AnasaziEpetraAdapter.hpp"
9 #include "AnasaziSpecializedEpetraAdapter.hpp"
10 #include "AnasaziBasicEigenproblem.hpp"
11 #include "AnasaziBlockKrylovSchurSolMgr.hpp"
12 
13 #ifdef EPETRA_MPI
14 #include "Epetra_MpiComm.h"
15 #else
16 #include "Epetra_SerialComm.h"
17 #endif
18 
19 namespace RBGen {
20 
22  isInitialized_( false ),
23  isInner_( true ),
24  basis_size_( 16 ),
25  comp_time_( 0.0 )
26  {
27  }
28 
32  {
33 
34  // Get the "Reduced Basis Method" sublist.
35  Teuchos::ParameterList& rbmethod_params = params->sublist( "Reduced Basis Method" );
36 
37  if ( rbmethod_params.get("Basis Size", 16) < ss->NumVectors() ) {
38  basis_size_ = rbmethod_params.get("Basis Size", 16);
39  }
40  else {
41  basis_size_ = ss->NumVectors();
42  }
43  // Get the inner / outer product form of the operator
44  isInner_ = ( rbmethod_params.get("Anasazi POD Operator Form","Inner")=="Inner"? true : false );
45 
46  // See if there is a matrix to be used for an inner-product form
47  if (rbmethod_params.isParameter( "POD Operator Weighting Matrix" )) {
48  std::string matFile = Teuchos::getParameter<std::string>( rbmethod_params, "POD Operator Weighting Matrix" );
49  std::vector<std::string> filename(1,matFile);
50  op_ = fileio->Read( filename );
51  }
52 
53  // See if there is a matrix to be used in the orthogonal basis construction
54  if (rbmethod_params.isParameter( "Inner Product Matrix" )) {
55  std::string matFile = Teuchos::getParameter<std::string>( rbmethod_params, "Inner Product Matrix" );
56  std::vector<std::string> filename(1,matFile);
57  inner_prod_op_ = fileio->Read( filename );
58  }
59 
60  // Resize the singular value vector
61  sv_.resize( basis_size_ );
62 
63  // Set the snapshot set
64  ss_ = ss;
65  }
66 
68  {
69 #ifdef EPETRA_MPI
70  Epetra_MpiComm comm( MPI_COMM_WORLD );
71 #else
72  Epetra_SerialComm comm;
73 #endif
74 
75  int MyPID = comm.MyPID();
76  //
77  // Variables used for the Block Krylov Method
78  //
79  int step = 5;
80  int num_vecs = ss_->NumVectors();
81  int vec_length = ss_->GlobalLength();
82  //
83  // If the user is requesting more basis vectors than there are snapshots,
84  // compute the basis vectors using an outer product formulation.
85  //
86  if (basis_size_ > num_vecs) {
87  step = 1;
88  basis_size_ = num_vecs;
89  isInner_ = false;
90  }
91  Epetra_Time timer( comm );
92  int i, blockSize = 1;
93  int nev = basis_size_;
94  int maxBlocks = 3*basis_size_;
95  int maxRestarts = 300;
96  int verbosity = Anasazi::Warnings + Anasazi::Errors;
97  double tol = 1e-14;
98  std::string which="LM";
99  //
100  // If the user is requesting a large portion of basis vectors, reduce the
101  // maximum number of blocks for BKS.
102  //
103  if (isInner_) {
104  if ( maxBlocks > num_vecs )
105  maxBlocks = num_vecs-1;
106  }
107  else {
108  if ( maxBlocks > vec_length )
109  maxBlocks = vec_length-1;
110  }
111  //
112  // Create parameter list to pass into solver
113  //
115  MyPL.set( "Verbosity", verbosity );
116  MyPL.set( "Block Size", blockSize );
117  MyPL.set( "Num Blocks", maxBlocks );
118  MyPL.set( "Maximum Restarts", maxRestarts );
119  MyPL.set( "Which", which );
120  MyPL.set( "Step Size", step );
121  MyPL.set( "Convergence Tolerance", tol );
122  //
123  // Typedefs for Anasazi solvers
124  //
125  typedef Anasazi::MultiVec<double> MV;
126  typedef Anasazi::Operator<double> OP;
127  //
128  // Create the operator.
129  //
130  Teuchos::RCP<OP> Amat;
131  if (op_ != Teuchos::null) {
132  // Call the constructor for the A^T*W*A operator
133  Amat = Teuchos::rcp( new Anasazi::EpetraWSymMVOp( ss_, op_ ) );
134  isInner_ = true; // Only inner products are supported at this time.
135  }
136  else {
137  // Call the constructor for the (A^T*A) operator
138  Amat = Teuchos::rcp( new Anasazi::EpetraSymMVOp( ss_, !isInner_ ) );
139  }
140  //
141  // Create a map for the columns of the snapshot set.
142  //
143  Epetra_LocalMap localMap(num_vecs, 0, comm);
144  //
145  // Create the initial vector and randomize it.
146  //
147  Teuchos::RCP<MV> ivec;
148  if (isInner_) {
149  if (inner_prod_op_ != Teuchos::null)
150  ivec=Teuchos::rcp( new Anasazi::EpetraOpMultiVec( inner_prod_op_, localMap, blockSize ) );
151  else
152  ivec = Teuchos::rcp( new Anasazi::EpetraMultiVec( localMap, blockSize ) );
153  }
154  else {
155  if (inner_prod_op_ != Teuchos::null)
156  ivec = Teuchos::rcp( new Anasazi::EpetraOpMultiVec( inner_prod_op_, ss_->Map(), blockSize ) );
157  else
158  ivec = Teuchos::rcp( new Anasazi::EpetraMultiVec( ss_->Map(), blockSize ) );
159  }
160  ivec->MvRandom();
161  //
162 
163  // Create the eigenproblem
165  Teuchos::rcp( new Anasazi::BasicEigenproblem<double,MV,OP>(Amat, ivec) );
166 
167  // Inform the eigenproblem that the operator A is symmetric
168  MyProblem->setHermitian( true );
169 
170  // Set the number of eigenvalues requested
171  MyProblem->setNEV( nev );
172 
173  // Inform the eigenproblem that you are finishing passing it information
174  bool boolret = MyProblem->setProblem();
175  if (boolret != true) {
176  if (MyPID == 0) {
177  std::cout << "Anasazi::BasicEigenproblem::setProblem() returned with error." << std::endl;
178  }
179  }
180 
181  // Initialize the Block Arnoldi solver
182  Anasazi::BlockKrylovSchurSolMgr<double,MV,OP> MySolverMgr(MyProblem, MyPL);
183 
184  timer.ResetStartTime();
185 
186  // Solve the problem to the specified tolerances or length
187  Anasazi::ReturnType returnCode = MySolverMgr.solve();
188  if (returnCode != Anasazi::Converged && MyPID==0) {
189  std::cout << "Anasazi::EigensolverMgr::solve() returned unconverged." << std::endl;
190  }
191 
192  comp_time_ = timer.ElapsedTime();
193 
194  // Get the eigenvalues and eigenvectors from the eigenproblem
195  Anasazi::Eigensolution<double,MV> sol = MyProblem->getSolution();
196  std::vector<Anasazi::Value<double> > evals = sol.Evals;
197  int numev = sol.numVecs;
198 
199  if (numev < nev && MyPID==0) {
200  std::cout << "RBGen::AnasaziPOD will return " << numev << " singular vectors." << std::endl;
201  }
202 
203  // Resize the singular value vector to the number of computed singular pairs.
204  sv_.resize( numev );
205 
206  if (numev > 0) {
207  // Retrieve eigenvectors
208  std::vector<int> index(numev);
209  for (i=0; i<numev; i++) { index[i] = i; }
210  Teuchos::RCP<const Anasazi::EpetraMultiVec> evecs = Teuchos::rcp_dynamic_cast<const Anasazi::EpetraMultiVec>(
211  Anasazi::MultiVecTraits<double,MV>::CloneView(*sol.Evecs, index) );
212  // const Anasazi::EpetraMultiVec* evecs = dynamic_cast<const Anasazi::EpetraMultiVec *>(sol.Evecs->CloneView( index ));
213  //
214  // Compute singular values which are the square root of the eigenvalues
215  //
216  for (i=0; i<numev; i++) {
218  }
219  //
220  // If we are using inner product formulation,
221  // then we must compute left singular vectors:
222  // u = Av/sigma
223  //
224  int info = 0;
225  std::vector<double> tempnrm( numev );
226  if (isInner_) {
227  basis_ = Teuchos::rcp( new Epetra_MultiVector(ss_->Map(), numev) );
228  Epetra_MultiVector AV( ss_->Map(), numev );
229 
230  /* A*V */
231  info = AV.Multiply( 'N', 'N', 1.0, *ss_, *evecs, 0.0 );
232  AV.Norm2( &tempnrm[0] );
233 
234  /* U = A*V(i)/S(i) */
235  Epetra_LocalMap localMap2( numev, 0, ss_->Map().Comm() );
236  Epetra_MultiVector S( localMap2, numev );
237  for( i=0; i<numev; i++ ) { S[i][i] = 1.0/tempnrm[i]; }
238  info = basis_->Multiply( 'N', 'N', 1.0, AV, S, 0.0 );
239 
240  /* Compute direct residuals : || Av - sigma*u ||
241  for (i=0; i<nev; i++) { S[i][i] = sv_[i]; }
242  info = AV.Multiply( 'N', 'N', -1.0, *basis_, S, 1.0 );
243  AV.Norm2( &tempnrm[0] );
244  if (MyPID == 0) {
245  std::cout<<"Singular Value"<<"\t\t"<<"Direct Residual"<<std::endl;
246  std::cout<<"------------------------------------------------------"<<std::endl;
247  for (i=0; i<nev; i++) {
248  std::cout<< sv_[i] << "\t\t\t" << tempnrm[i] << std::endl;
249  }
250  std::cout<<"------------------------------------------------------"<<std::endl;
251  }
252  */
253  } else {
254  basis_ = Teuchos::rcp( new Epetra_MultiVector( Copy, *evecs, 0, numev ) );
255  Epetra_MultiVector ATU( localMap, numev );
256  Epetra_MultiVector V( localMap, numev );
257 
258  /* A^T*U */
259  info = ATU.Multiply( 'T', 'N', 1.0, *ss_, *evecs, 0.0 );
260  ATU.Norm2( &tempnrm[0] );
261 
262  /* V = A^T*U(i)/S(i) */
263  Epetra_LocalMap localMap2( numev, 0, ss_->Map().Comm() );
264  Epetra_MultiVector S( localMap2, numev );
265  for( i=0; i<numev; i++ ) { S[i][i] = 1.0/tempnrm[i]; }
266  info = V.Multiply( 'N', 'N', 1.0, ATU, S, 0.0 );
267 
268  /* Compute direct residuals : || (A^T)u - sigma*v ||
269  for (i=0; i<nev; i++) { S[i][i] = sv_[i]; }
270  info = ATU.Multiply( 'N', 'N', -1.0, V, S, 1.0 );
271  ATU.Norm2( tempnrm );
272  if (comm.MyPID() == 0) {
273  std::cout<<"Singular Value"<<"\t\t"<<"Direct Residual"<<std::endl;
274  std::cout<<"------------------------------------------------------"<<std::endl;
275  for (i=0; i<nev; i++) {
276  std::cout<< sv_[i] << "\t\t\t" << tempnrm[i] << std::endl;
277  }
278  std::cout<<"------------------------------------------------------"<<std::endl;
279  }
280  */
281  }
282  }
283  }
284 } // end of RBGen namespace
285 
286 
287 
288 
void Initialize(const Teuchos::RCP< Teuchos::ParameterList > &params, const Teuchos::RCP< const Epetra_MultiVector > &ss, const Teuchos::RCP< RBGen::FileIOHandler< Epetra_Operator > > &fileio=Teuchos::null)
Initialize the method with the given parameter list and snapshot set.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
double ElapsedTime(void) const
static T squareroot(T x)
AnasaziPOD()
Default constructor.
int MyPID() const
Provides POD method using Anasazi eigensolvers.
bool isParameter(const std::string &name) const
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
void ResetStartTime(void)
void computeBasis()
Compute a basis for the provided snapshots.