RBGen  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
RBGen_LapackPOD.cpp
1 
2 #include "RBGen_LapackPOD.h"
3 #include "Epetra_BLAS.h"
4 #include "Epetra_Export.h"
5 #include "Epetra_Import.h"
6 #include "Epetra_LAPACK.h"
7 #include "Epetra_Time.h"
8 #include "Epetra_Map.h"
9 
10 #ifdef EPETRA_MPI
11 #include "Epetra_MpiComm.h"
12 #else
13 #include "Epetra_SerialComm.h"
14 #endif
15 
16 namespace RBGen {
17 
19  isInitialized_( false ),
20  basis_size_( 16 ),
21  comp_time_( 0.0 )
22  {
23  }
24 
28  {
29  // Get the "Reduced Basis Method" sublist.
30  Teuchos::ParameterList& rbmethod_params = params->sublist( "Reduced Basis Method" );
31 
32  if ( rbmethod_params.get("Basis Size", 16) < ss->NumVectors() ) {
33  basis_size_ = rbmethod_params.get("Basis Size", 16);
34  }
35  else {
36  basis_size_ = ss->NumVectors();
37  }
38  // Resize the singular value vector
39  sv_.resize( ss->NumVectors() );
40 
41  // Set the snapshot set
42  ss_ = ss;
43  }
44 
46  {
47 #ifdef EPETRA_MPI
48  Epetra_MpiComm comm( MPI_COMM_WORLD );
49 #else
50  Epetra_SerialComm comm;
51 #endif
52  //
53  // Variables for Epetra
54  //
55  Epetra_Time timer( comm );
56  int num_vecs = ss_->NumVectors();
57  int dim = ss_->GlobalLength();
58  //
59  // Check to see if there is more than one processor.
60  // If not, just grab a copy of the multivector, else
61  // export all information to processor 0 and compute basis.
62  //
63  if (comm.NumProc() > 1) {
64  //
65  // Create map putting all elements of vector on Processor 0.
66  //
67  Epetra_Map* Proc0Map;
68  //
69  if ( comm.MyPID() == 0 ) {
70  Proc0Map = new Epetra_Map( dim, dim, 0, comm );
71  } else {
72  Proc0Map = new Epetra_Map( dim, 0, 0, comm );
73  }
74  Epetra_MultiVector Proc0MV( *Proc0Map, num_vecs );
75  //
76  // Create an exporter to get the global Epetra_MultiVector to a local Epetra_MultiVector.
77  //
78  Epetra_Export exporter( ss_->Map(), *Proc0Map );
79  //
80  // Export the Epetra_MultiVector
81  //
82  Proc0MV.Export(*ss_, exporter, Insert);
83  //
84  if ( comm.MyPID() == 0 ) {
85  //
86  // Now we can use the Proc0MV because it's on this processor.
87  //
88  // Create workspace for the SVD.
89  //
90  int info, lwork;
91  double U[ 1 ], Vt[ 1 ];
92  lwork = EPETRA_MAX( 3*num_vecs + dim, 5*num_vecs );
93  std::vector<double> work( lwork );
94  Epetra_LAPACK lapack;
95  //
96  // Compute the SVD.
97  //
98  timer.ResetStartTime();
99  lapack.GESVD( 'O', 'N', dim, num_vecs, Proc0MV.Values(), Proc0MV.Stride(), &sv_[0], U, 1, Vt, 1, &work[0], &lwork, &info );
100  comp_time_ = timer.ElapsedTime();
101  if (info != 0) {
102  // THROW AN EXCEPTION HERE!
103  std::cout<< "The return value of the SVD is not 0!"<< std::endl;
104  }
105  }
106  //
107  // Communicate the singular values and vectors back to all processors.
108  //
109  comm.Broadcast( &sv_[0], basis_size_, 0 );
110  //
111  // Create a MultiVector for the basis and a view of the first basis_size_ vectors of Proc0MV.
112  //
113  basis_ = Teuchos::rcp( new Epetra_MultiVector( ss_->Map(), basis_size_ ) );
114  Epetra_MultiVector Proc0MV_front( Copy, Proc0MV, 0, basis_size_ );
115  //
116  // Each processor needs to import the information back.
117  //
118  Epetra_Import importer( basis_->Map(), Proc0MV_front.Map() );
119  basis_->Import(Proc0MV_front, importer, Insert);
120  //
121  // Clean up
122  //
123  delete Proc0Map;
124  //
125  } else {
126  //
127  // Just use the multivector, it's on this processor.
128  //
129  // Create workspace for the SVD.
130  //
131  int info, lwork;
132  double U[ 1 ], Vt[ 1 ];
133  lwork = EPETRA_MAX( 3*num_vecs + dim, 5*num_vecs );
134  std::vector<double> work( lwork );
135  Epetra_LAPACK lapack;
136  //
137  // Compute the SVD
138  //
139  timer.ResetStartTime();
140  lapack.GESVD( 'O', 'N', dim, num_vecs, ss_->Values(), ss_->Stride(), &sv_[0], U, 1, Vt, 1, &work[0], &lwork, &info );
141  comp_time_ = timer.ElapsedTime();
142  if (info != 0) {
143  // THROW AN EXCEPTION HERE!
144  std::cout<< "The return value of the SVD is not 0!"<< std::endl;
145  }
146  sv_.resize( basis_size_ );
147  basis_ = Teuchos::rcp( new Epetra_MultiVector( Copy, *ss_, 0, basis_size_ ) );
148  //
149  }
150  }
151 
152 } // end of RBGen namespace
153 
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)
double ElapsedTime(void) const
void GESVD(const char JOBU, const char JOBVT, const int M, const int N, float *A, const int LDA, float *S, float *U, const int LDU, float *VT, const int LDVT, float *WORK, const int *LWORK, int *INFO) const
int MyPID() const
LapackPOD()
Default constructor.
void computeBasis()
Compute a basis for the provided snapshots.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
int NumProc() const
ParameterList & sublist(const std::string &name, bool mustAlreadyExist=false, const std::string &docString="")
int Broadcast(double *MyVals, int Count, int Root) const
void ResetStartTime(void)