ROL
ROL_StdLinearOperator.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ************************************************************************
3 //
4 // Rapid Optimization Library (ROL) Package
5 // Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 // Drew Kouri (dpkouri@sandia.gov) and
39 // Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 #ifndef ROL_STDLINEAROPERATOR_H
45 #define ROL_STDLINEAROPERATOR_H
46 
47 #include "ROL_LinearOperator.hpp"
48 #include "ROL_StdVector.hpp"
49 #include "ROL_LAPACK.hpp"
50 
51 
62 namespace ROL {
63 
64 template <class Real>
65 class StdLinearOperator : public LinearOperator<Real> {
66 
68 
69  typedef std::vector<Real> vector;
70 
71 private:
72 
73  ROL::Ptr<std::vector<Real> > A_;
74  int N_;
75  int INFO_;
76 
77  mutable vector PLU_;
78  mutable std::vector<int> ipiv_;
79 
80  ROL::LAPACK<int,Real> lapack_;
81 
82 public:
83 
85 
86  StdLinearOperator( ROL::Ptr<std::vector<Real> > &A ) : A_(A) {
87  int N2 = A_->size();
88  N_ = (std::round(std::sqrt(N2)));
89  bool isSquare = N_*N_ == N2;
90  ROL_TEST_FOR_EXCEPTION( !isSquare, std::invalid_argument,
91  "Error: vector representation of matrix must have a square "
92  "number of elements.");
93  ipiv_.resize(N_);
94  }
95 
96  virtual ~StdLinearOperator() {}
97 
99  void update( const Vector<Real> &x, bool flag = true, int iter = -1 ) {
100  ROL::Ptr<const vector> xp = dynamic_cast<const SV&>(x).getVector();
101  update(*xp,flag,iter);
102  }
103 
104  virtual void update( const std::vector<Real> &x, bool flag = true, int iter = -1 ) {}
105 
106  // Matrix multiplication
108  void apply( Vector<Real> &Hv, const Vector<Real> &v, Real &tol ) const {
109 
110  ROL::Ptr<vector> Hvp = dynamic_cast<SV&>(Hv).getVector();
111  ROL::Ptr<const vector> vp = dynamic_cast<const SV&>(v).getVector();
112  apply(*Hvp,*vp,tol);
113  }
114 
115  virtual void apply( std::vector<Real> &Hv, const std::vector<Real> &v, Real &tol ) const {
116  for( int i=0; i<N_; ++i ) {
117  Hv[i] = Real(0);
118  for( int j=0; j<N_; ++j ) {
119  Hv.at(i) += A_->at(N_*j+i)*v.at(j);
120  }
121  }
122  }
123 
124  // Matrix multiplication with transpose
126  void applyAdjoint( Vector<Real> &Hv, const Vector<Real> &v, Real &tol ) const {
127 
128  ROL::Ptr<vector> Hvp = dynamic_cast<SV&>(Hv).getVector();
129  ROL::Ptr<const vector> vp = dynamic_cast<const SV&>(v).getVector();
130  applyAdjoint(*Hvp,*vp,tol);
131  }
132 
133  virtual void applyAdjoint( std::vector<Real> &Hv, const std::vector<Real> &v, Real &tol ) const {
134  for( int i=0; i<N_; ++i ) {
135  Hv[i] = Real(0);
136  for( int j=0; j<N_; ++j ) {
137  Hv.at(i) += A_->at(N_*i+j)*v.at(j);
138  }
139  }
140  }
141 
142 
143  // Solve the system
144 
146  void applyInverse( Vector<Real> &Hv, const Vector<Real> &v, Real &tol ) const {
147 
148  ROL::Ptr<vector> Hvp = dynamic_cast<SV&>(Hv).getVector();
149  ROL::Ptr<const vector> vp = dynamic_cast<const SV&>(v).getVector();
150  applyInverse(*Hvp,*vp,tol);
151  }
152 
153  virtual void applyInverse( std::vector<Real> &Hv, const std::vector<Real> &v, Real &tol ) const {
154 
155  const int LDA = N_;
156  const int LDB = N_;
157  int INFO;
158  int NRHS = 1;
159 
160  Hv = v;
161  PLU_ = *A_;
162 
163  // Do LU factorization
164  lapack_.GETRF(N_,N_,&PLU_[0],LDA,&ipiv_[0],&INFO);
165 
166  ROL_TEST_FOR_EXCEPTION(INFO>0,std::logic_error,"Error in StdLinearOperator::applyInverse(): "
167  "Zero diagonal element encountered in matrix factor U(" << INFO << "," << INFO << ").");
168 
169  ROL_TEST_FOR_EXCEPTION(INFO<0,std::logic_error,"Error in StdLinearOperator::applyInverse(): "
170  "Illegal value encountered in element " << -INFO << " when performing LU factorization.");
171 
172  // Solve factored system
173  lapack_.GETRS('N',N_,NRHS,&PLU_[0],LDA,&ipiv_[0],&Hv[0],LDB,&INFO);
174 
175  ROL_TEST_FOR_EXCEPTION(INFO<0,std::logic_error,"Error in StdLinearOperator::applyInverse(): "
176  "Illegal value encountered in element " << -INFO << " when solving the factorized system. ");
177 
178  }
179 
180  // Solve the system with transposed matrix
181 
183  void applyAdjointInverse( Vector<Real> &Hv, const Vector<Real> &v, Real &tol ) const {
184 
185  ROL::Ptr<vector> Hvp = dynamic_cast<SV&>(Hv).getVector();
186  ROL::Ptr<const vector> vp = dynamic_cast<const SV&>(v).getVector();
187  applyAdjointInverse(*Hvp,*vp,tol);
188  }
189 
190  virtual void applyAdjointInverse( std::vector<Real> &Hv, const std::vector<Real> &v, Real &tol ) const {
191 
192  const int LDA = N_;
193  const int LDB = N_;
194  int INFO;
195  int NRHS = 1;
196 
197  Hv = v;
198  PLU_ = *A_;
199 
200  // Do LU factorization
201  lapack_.GETRF(N_,N_,&PLU_[0],LDA,&ipiv_[0],&INFO);
202 
203  ROL_TEST_FOR_EXCEPTION(INFO>0,std::logic_error,"Error in StdLinearOperator::applyAdjointInverse(): "
204  "Zero diagonal element encountered in matrix factor U(" << INFO << "," << INFO << ").");
205 
206  ROL_TEST_FOR_EXCEPTION(INFO<0,std::logic_error,"Error in StdLinearOperator::applyAdjointInverse(): "
207  "Illegal value encountered in element " << -INFO << " when performing LU factorization.");
208 
209  // Solve factored system
210  lapack_.GETRS('T',N_,NRHS,&PLU_[0],LDA,&ipiv_[0],&Hv[0],LDB,&INFO);
211 
212  ROL_TEST_FOR_EXCEPTION(INFO<0,std::logic_error,"Error in StdLinearOperator::applyAdjointInverse(): "
213  "Illegal value encountered in element " << -INFO << " when solving the factorized system. ");
214 
215  }
216 
217 }; // class LinearOperator
218 
219 } // namespace ROL
220 
221 #endif
void applyInverse(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply inverse of linear operator.
void apply(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply linear operator.
virtual void apply(std::vector< Real > &Hv, const std::vector< Real > &v, Real &tol) const
Provides the std::vector implementation to apply a linear operator, which is a std::vector representa...
virtual void applyAdjointInverse(std::vector< Real > &Hv, const std::vector< Real > &v, Real &tol) const
virtual void applyAdjoint(std::vector< Real > &Hv, const std::vector< Real > &v, Real &tol) const
ROL::LAPACK< int, Real > lapack_
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
virtual void applyInverse(std::vector< Real > &Hv, const std::vector< Real > &v, Real &tol) const
void update(const Vector< Real > &x, bool flag=true, int iter=-1)
Update linear operator.
Provides the interface to apply a linear operator.
void applyAdjointInverse(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply adjoint of the inverse linear operator.
virtual void update(const std::vector< Real > &x, bool flag=true, int iter=-1)
void applyAdjoint(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const
Apply adjoint of linear operator.
StdLinearOperator(ROL::Ptr< std::vector< Real > > &A)
ROL::Ptr< std::vector< Real > > A_