ROL
ROL_MINRES.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 #pragma once
45 #ifndef ROL_MINRES_HPP
46 #define ROL_MINRES_HPP
47 
48 #include <array>
49 
50 #include "ROL_Krylov.hpp"
51 #include "ROL_VectorClone.hpp"
52 
53 namespace ROL {
54 
61 namespace details {
62 
63 using namespace std;
64 
65 template<typename Real>
66 class MINRES : public Krylov<Real> {
67 
68  using V = Vector<Real>;
70 
71 private:
72 
73  // Givens rotation matrix elements
74  Real resnorm_;
75  int maxiter_;
77  array<Real,4> H_;
78  array<Real,2> rhs_;
79 
81 
82  void givens( Real& c, Real& s, Real& r, Real a, Real b ) const {
83 
84  Real zero(0), one(1);
85 
86  if( b == zero ) {
87  c = ( a >= zero ? one : -one );
88  s = zero;
89  r = abs(a);
90  }
91  else if( a == zero ) {
92  c = zero;
93  s = ( b >= zero ? one : -one );
94  r = abs(b);
95  }
96  else if( abs(a) > abs(b) ) {
97  auto t = b/a;
98  auto u = copysign(sqrt(one+t*t),a);
99  c = one/u;
100  s = c*t;
101  r = a*u;
102  }
103  else {
104  auto t = a/b;
105  auto u = copysign(sqrt(one+t*t),b);
106  s = 1/u;
107  c = s*t;
108  r = b*u;
109  }
110  } // givens()
111 
112 public:
113 
114  MINRES( Real absTol = 1.e-4, Real relTol = 1.e-2, unsigned maxit = 100, bool useInexact = false) :
115  Krylov<Real>(absTol,relTol,maxit), useInexact_(useInexact),
116  clones_("v_prev","v_curr","v_next","w_prev","w_curr","w_next") { }
117 
118  // Note: Preconditioner is not implemented
119  virtual Real run( V &x, OP &A, const V &b, OP &M, int &iter, int &flag ) override {
120 
121  auto v_prev = clones_( x, "v_prev" ); v_prev->zero();
122  auto v_curr = clones_( x, "v_curr" ); v_curr->set(b);
123  auto v_next = clones_( x, "v_next" ); v_next->zero();
124  auto w_prev = clones_( x, "w_prev" ); w_prev->zero();
125  auto w_curr = clones_( x, "w_curr" ); w_curr->zero();
126  auto w_next = clones_( x, "w_next" ); w_next->zero();
127 
128  Real c_prev{0}, s_prev{0}, c_curr{0}, s_curr{0}, c_next{0}, s_next{0};
129 
130  resnorm_ = v_curr->norm();
132  Real itol = sqrt(ROL_EPSILON<Real>());
133 
134  for( auto &e: H_ ) e = 0;
135 
136  rhs_[0] = resnorm_; rhs_[1] = 0;
137 
138  v_curr->scale(1.0/resnorm_);
139 
140  for( iter=0; iter < (int)Krylov<Real>::getMaximumIteration(); iter++) {
141  if ( useInexact_ ) {
142  itol = rtol/((Real)Krylov<Real>::getMaximumIteration() * resnorm_);
143  }
144 
145  if( resnorm_ < rtol ) break;
146 
147  A.apply( *v_next, *v_curr, itol );
148 
149  if( iter>0 ) v_next->axpy(-H_[1],*v_prev);
150 
151  H_[2] = v_next->dot(*v_curr);
152 
153  v_next->axpy(-H_[2],*v_curr);
154 
155  H_[3] = v_next->norm();
156 
157  v_next->scale(1.0/H_[3]);
158 
159  // Rotation on H_[0] and H_[1].
160  if( iter>1 ) {
161  H_[0] = s_prev*H_[1];
162  H_[1] *= c_prev;
163  }
164 
165  // Rotation on H_[1] and H_[2]
166  if( iter>0 ) {
167  auto tmp = c_curr*H_[2]-s_curr*H_[1];
168  H_[1] = c_curr*H_[1] + s_curr*H_[2];
169  H_[2] = tmp;
170  }
171 
172  // Form rotation coefficients
173  givens( c_next, s_next, H_[2], H_[2], H_[3] );
174  rhs_[1] = -s_next*rhs_[0];
175  rhs_[0] *= c_next;
176 
177  w_next->set( *v_curr );
178 
179  if( iter>0 ) w_next->axpy( -H_[1], *w_curr );
180  if( iter>1 ) w_next->axpy( -H_[0], *w_prev );
181 
182  w_next->scale(1.0/H_[2]);
183 
184  x.axpy( rhs_[0], *w_next );
185 
186  v_prev->set( *v_curr );
187  v_curr->set( *v_next );
188  w_prev->set( *w_curr );
189  w_curr->set( *w_next );
190 
191  c_prev = c_curr;
192  c_curr = c_next;
193  s_prev = s_curr;
194  s_curr = s_next;
195 
196  rhs_[0] = rhs_[1];
197 
198  H_[1] = H_[3];
199 
200  resnorm_ = abs( rhs_[1] );
201 
202  } // for (iter)
203 
204  if ( iter == (int)Krylov<Real>::getMaximumIteration() ) flag = 1;
205  else iter++;
206 
207  return resnorm_;
208  } // run()
209 
210 }; // class MINRES
211 
212 } // namespace details
213 
214 
215 using details::MINRES;
216 
217 
218 } // namespace ROL
219 
220 
221 #endif // ROL_MINRES_HPP
222 
virtual Real run(V &x, OP &A, const V &b, OP &M, int &iter, int &flag) override
Definition: ROL_MINRES.hpp:119
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Definition: ROL_Vector.hpp:153
virtual void apply(Vector< Real > &Hv, const Vector< Real > &v, Real &tol) const =0
Apply linear operator.
array< Real, 4 > H_
Definition: ROL_MINRES.hpp:77
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0_ zero()
array< Real, 2 > rhs_
Definition: ROL_MINRES.hpp:78
Provides definitions for Krylov solvers.
Definition: ROL_Krylov.hpp:58
Provides the interface to apply a linear operator.
void givens(Real &c, Real &s, Real &r, Real a, Real b) const
Definition: ROL_MINRES.hpp:82
VectorCloneMap< Real > clones_
Definition: ROL_MINRES.hpp:80
Implements the MINRES algorithm for solving symmetric indefinite systems.
MINRES(Real absTol=1.e-4, Real relTol=1.e-2, unsigned maxit=100, bool useInexact=false)
Definition: ROL_MINRES.hpp:114