ROL
ROL_ReducedDynamicObjective.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_REDUCEDDYNAMICOBJECTIVE_HPP
45#define ROL_REDUCEDDYNAMICOBJECTIVE_HPP
46
47#include "ROL_Ptr.hpp"
48#include "ROL_Sketch.hpp"
49#include "ROL_Objective.hpp"
52
53#include <fstream>
54
75
76
77namespace ROL {
78
79template<typename Real>
80class ReducedDynamicObjective : public Objective<Real> {
81 using size_type = typename std::vector<Real>::size_type;
82private:
83 // Problem data.
84 const Ptr<DynamicObjective<Real>> obj_;
85 const Ptr<DynamicConstraint<Real>> con_;
86 const Ptr<Vector<Real>> u0_;
87 const std::vector<TimeStamp<Real>> timeStamp_;
89 // General sketch information.
90 const bool useSketch_;
91 // State sketch information.
93 Ptr<Sketch<Real>> stateSketch_;
94 // Adjoint sketch information.
96 Ptr<Sketch<Real>> adjointSketch_;
97 // State sensitivity sketch information.
99 Ptr<Sketch<Real>> stateSensSketch_;
100 // Inexactness information.
101 const bool useInexact_;
104 const bool syncHessRank_;
105 // Vector storage for intermediate computations.
106 std::vector<Ptr<Vector<Real>>> uhist_; // State history.
107 std::vector<Ptr<Vector<Real>>> lhist_; // Adjoint history.
108 std::vector<Ptr<Vector<Real>>> whist_; // State sensitivity history.
109 std::vector<Ptr<Vector<Real>>> phist_; // Adjoint sensitivity history.
110 Ptr<Vector<Real>> cprimal_; // Primal constraint vector.
111 Ptr<Vector<Real>> crhs_; // Primal constraint vector.
112 Ptr<Vector<Real>> udual_; // Dual state vector.
113 Ptr<Vector<Real>> rhs_; // Dual state vector.
114 Ptr<Vector<Real>> zdual_; // Dual control vector.
115 Real val_; // Objective function value.
116 // Flags.
117 bool isValueComputed_; // Whether objective has been evaluated.
118 bool isStateComputed_; // Whether state has been solved.
119 bool isAdjointComputed_; // Whether adjoint has been solved.
120 bool useHessian_; // Whether to use Hessian or FD.
121 bool useSymHess_; // Whether to use symmetric Hessian approximation.
122 // Output information
123 Ptr<std::ostream> stream_;
124 const bool print_;
125 const int freq_;
126
128 return static_cast<PartitionedVector<Real>&>(x);
129 }
130
132 return static_cast<const PartitionedVector<Real>&>(x);
133 }
134
135 void throwError(const int err, const std::string &sfunc,
136 const std::string &func, const int line) const {
137 if (err != 0) {
138 std::stringstream out;
139 out << ">>> ROL::ReducedDynamicObjective::" << func << " (Line " << line << "): ";
140 if (err == 1) {
141 out << "Reconstruction has already been called!";
142 }
143 else if (err == 2) {
144 out << "Input column index exceeds total number of columns!";
145 }
146 else if (err == 3) {
147 out << "Reconstruction failed to compute domain-space basis!";
148 }
149 else if (err == 4) {
150 out << "Reconstruction failed to compute range-space basis!";
151 }
152 else if (err == 5) {
153 out << "Reconstruction failed to generate core matrix!";
154 }
155 throw Exception::NotImplemented(out.str());
156 }
157 }
158
159public:
161 const Ptr<DynamicConstraint<Real>> &con,
162 const Ptr<Vector<Real>> &u0,
163 const Ptr<Vector<Real>> &zvec,
164 const Ptr<Vector<Real>> &cvec,
165 const std::vector<TimeStamp<Real>> &timeStamp,
166 ROL::ParameterList &pl,
167 const Ptr<std::ostream> &stream = nullPtr)
168 : obj_ ( obj ), // Dynamic objective function.
169 con_ ( con ), // Dynamic constraint function.
170 u0_ ( u0 ), // Initial condition.
171 timeStamp_ ( timeStamp ), // Vector of time stamps.
172 Nt_ ( timeStamp.size() ), // Number of time intervals.
173 useSketch_ ( pl.get("Use Sketching", false) ), // Use state sketch if true.
174 rankState_ ( pl.get("State Rank", 10) ), // Rank of state sketch.
175 stateSketch_ ( nullPtr ), // State sketch object.
176 rankAdjoint_ ( pl.get("Adjoint Rank", 10) ), // Rank of adjoint sketch.
177 adjointSketch_ ( nullPtr ), // Adjoint sketch object.
178 rankStateSens_ ( pl.get("State Sensitivity Rank", 10) ), // Rank of state sensitivity sketch.
179 stateSensSketch_ ( nullPtr ), // State sensitivity sketch object.
180 useInexact_ ( pl.get("Adaptive Rank", false) ), // Update rank adaptively.
181 updateFactor_ ( pl.get("Rank Update Factor", 2) ), // Rank update factor.
182 maxRank_ ( pl.get("Maximum Rank", 100) ), // Maximum rank.
183 syncHessRank_ ( pl.get("Sync Hessian Rank", useInexact_) ), // Sync rank for Hessian storage.
184 isValueComputed_ ( false ), // Flag indicating whether value has been computed.
185 isStateComputed_ ( false ), // Flag indicating whether state has been computed.
186 isAdjointComputed_ ( false ), // Flag indicating whether adjoint has been computed.
187 useHessian_ ( pl.get("Use Hessian", true) ), // Flag indicating whether to use the Hessian.
188 useSymHess_ ( pl.get("Use Only Sketched Sensitivity", true) ), // Flag indicating whether to use symmetric sketched Hessian.
189 stream_ ( stream ), // Output stream to print sketch information.
190 print_ ( pl.get("Print Optimization Vector", false) ), // Print control vector to file
191 freq_ ( pl.get("Output Frequency", 5) ) { // Print frequency for control vector
192 uhist_.clear(); lhist_.clear(); whist_.clear(); phist_.clear();
193 if (useSketch_) { // Only maintain a sketch of the state time history
194 Real orthTol = pl.get("Orthogonality Tolerance", 1e2*ROL_EPSILON<Real>());
195 int orthIt = pl.get("Reorthogonalization Iterations", 5);
196 bool trunc = pl.get("Truncate Approximation", false);
197 if (syncHessRank_) {
200 }
201 unsigned dseed = pl.get("State Domain Seed",0);
202 unsigned rseed = pl.get("State Range Seed",0);
203 stateSketch_ = makePtr<Sketch<Real>>(*u0_,static_cast<int>(Nt_)-1,rankState_,
204 orthTol,orthIt,trunc,dseed,rseed);
205 uhist_.push_back(u0_->clone());
206 uhist_.push_back(u0_->clone());
207 lhist_.push_back(cvec->dual().clone());
208 dseed = pl.get("Adjoint Domain Seed",0);
209 rseed = pl.get("Adjoint Range Seed",0);
210 adjointSketch_ = makePtr<Sketch<Real>>(*u0_,static_cast<int>(Nt_)-1,rankAdjoint_,
211 orthTol,orthIt,trunc,dseed,rseed);
212 if (useHessian_) {
213 dseed = pl.get("State Sensitivity Domain Seed",0);
214 rseed = pl.get("State Sensitivity Range Seed",0);
215 stateSensSketch_ = makePtr<Sketch<Real>>(*u0_,static_cast<int>(Nt_)-1,
216 rankStateSens_,orthTol,orthIt,trunc,dseed,rseed);
217 whist_.push_back(u0_->clone());
218 whist_.push_back(u0_->clone());
219 phist_.push_back(cvec->dual().clone());
220 }
221 }
222 else { // Store entire state time history
223 for (size_type i = 0; i < Nt_; ++i) {
224 uhist_.push_back(u0_->clone());
225 lhist_.push_back(cvec->dual().clone());
226 if (useHessian_) {
227 whist_.push_back(u0_->clone());
228 phist_.push_back(cvec->dual().clone());
229 }
230 }
231 }
232 cprimal_ = cvec->clone();
233 crhs_ = cvec->clone();
234 udual_ = u0_->dual().clone();
235 rhs_ = u0_->dual().clone();
236 zdual_ = zvec->dual().clone();
237 }
238
239 Ptr<Vector<Real>> makeDynamicVector(const Vector<Real> &x) const {
241 }
242
243 void update( const Vector<Real> &x, bool flag = true, int iter = -1 ) {
244 if (useSketch_) {
245 stateSketch_->update();
246 if (flag == true) {
247 adjointSketch_->update();
248 if (useHessian_) {
249 stateSensSketch_->update();
250 }
251 }
252 }
253 for (size_type i = 0; i < uhist_.size(); ++i) {
254 uhist_[i]->zero();
255 }
256 val_ = static_cast<Real>(0);
257 isValueComputed_ = false;
258 isStateComputed_ = false;
259 if (flag == true) {
260 isAdjointComputed_ = false;
261 }
262 if (iter >= 0 && iter%freq_==0 && print_) {
263 std::stringstream name;
264 name << "optvector." << iter << ".txt";
265 std::ofstream file;
266 file.open(name.str());
267 x.print(file);
268 file.close();
269 }
270 }
271
272 void update(const Vector<Real> &x, UpdateType type, int iter = -1) {
273 if (useSketch_) {
274 stateSketch_->update(type);
275 adjointSketch_->update(type);
276 if (useHessian_) stateSensSketch_->update(type);
277 }
278 for (size_type i = 0; i < uhist_.size(); ++i) uhist_[i]->zero();
279 val_ = static_cast<Real>(0);
280 isValueComputed_ = false;
281 isStateComputed_ = false;
282 isAdjointComputed_ = false;
283
284 if (iter >= 0 && iter%freq_==0 && print_) {
285 std::stringstream name;
286 name << "optvector." << iter << ".txt";
287 std::ofstream file;
288 file.open(name.str());
289 x.print(file);
290 file.close();
291 }
292 }
293
294 Real value( const Vector<Real> &x, Real &tol ) {
295 if (!isValueComputed_) {
296 int eflag(0);
297 const Real one(1);
298 const PartitionedVector<Real> &xp = partition(x);
299 // Set initial condition
300 uhist_[0]->set(*u0_);
301 if (useSketch_) {
302 stateSketch_->update();
303 uhist_[1]->set(*u0_);
304 }
305 // Run time stepper
306 Real valk(0);
307 size_type index;
308 for (size_type k = 1; k < Nt_; ++k) {
309 index = (useSketch_ ? 1 : k);
310 if (!useSketch_) {
311 uhist_[index]->set(*uhist_[index-1]);
312 }
313 // Update dynamic constraint
314 con_->update_uo(*uhist_[index-1], timeStamp_[k]);
315 con_->update_z(*xp.get(k), timeStamp_[k]);
316 // Solve state on current time interval
317 con_->solve(*cprimal_, *uhist_[index-1], *uhist_[index], *xp.get(k), timeStamp_[k]);
318 // Update dynamic objective
319 obj_->update(*uhist_[index-1], *uhist_[index], *xp.get(k), timeStamp_[k]);
320 // Compute objective function value on current time interval
321 valk = obj_->value(*uhist_[index-1], *uhist_[index], *xp.get(k), timeStamp_[k]);
322 // Update total objective function value
323 val_ += valk;
324 // Sketch state
325 if (useSketch_) {
326 eflag = stateSketch_->advance(one,*uhist_[1],static_cast<int>(k)-1,one);
327 throwError(eflag,"advance","value",273);
328 uhist_[0]->set(*uhist_[1]);
329 }
330 }
331 isValueComputed_ = true;
332 isStateComputed_ = true;
333 }
334 return val_;
335 }
336
337 void gradient( Vector<Real> &g, const Vector<Real> &x, Real &tol ) {
338 int eflag(0);
340 gp.get(0)->zero(); // zero for the nonexistant zeroth control interval
341 const PartitionedVector<Real> &xp = partition(x);
342 const Real one(1);
343 size_type uindex = (useSketch_ ? 1 : Nt_-1);
344 size_type lindex = (useSketch_ ? 0 : Nt_-1);
345 // Must first compute the value
346 solveState(x);
347 if (useSketch_ && useInexact_) {
348 if (stream_ != nullPtr) {
349 *stream_ << std::string(80,'=') << std::endl;
350 *stream_ << " ROL::ReducedDynamicObjective::gradient" << std::endl;
351 }
352 tol = updateSketch(x,tol);
353 if (stream_ != nullPtr) {
354 *stream_ << " State Rank for Gradient Computation: " << rankState_ << std::endl;
355 *stream_ << " Residual Norm: " << tol << std::endl;
356 *stream_ << std::string(80,'=') << std::endl;
357 }
358 }
359 // Recover state from sketch
360 if (useSketch_) {
361 uhist_[1]->set(*uhist_[0]);
362 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(Nt_)-3);
363 throwError(eflag,"reconstruct","gradient",309);
364 if (isAdjointComputed_) {
365 eflag = adjointSketch_->reconstruct(*lhist_[0],static_cast<int>(Nt_)-2);
366 throwError(eflag,"reconstruct","gradient",312);
367 }
368 }
369 // Update dynamic constraint and objective
370 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
371 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
372 // Solve for terminal condition
373 if (!isAdjointComputed_) {
375 *uhist_[uindex-1], *uhist_[uindex],
376 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
377 if (useSketch_) {
378 eflag = adjointSketch_->advance(one,*lhist_[0],static_cast<int>(Nt_)-2,one);
379 throwError(eflag,"advance","gradient",325);
380 }
381 }
382 // Update gradient on terminal interval
383 updateGradient(*gp.get(Nt_-1), *lhist_[lindex],
384 *uhist_[uindex-1], *uhist_[uindex],
385 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
386 // Run reverse time stepper
387 for (size_type k = Nt_-2; k > 0; --k) {
388 if (!isAdjointComputed_) {
389 // Compute k+1 component of rhs
390 computeAdjointRHS(*rhs_, *lhist_[lindex],
391 *uhist_[uindex-1], *uhist_[uindex],
392 *xp.get(k+1), timeStamp_[k+1]);
393 }
394 uindex = (useSketch_ ? 1 : k);
395 lindex = (useSketch_ ? 0 : k);
396 // Recover state from sketch
397 if (useSketch_) {
398 uhist_[1]->set(*uhist_[0]);
399 if (k==1) {
400 uhist_[0]->set(*u0_);
401 }
402 else {
403 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(k)-2);
404 throwError(eflag,"reconstruct","gradient",350);
405 }
406 if (isAdjointComputed_) {
407 eflag = adjointSketch_->reconstruct(*lhist_[0],static_cast<int>(k)-1);
408 throwError(eflag,"reconstruct","gradient",354);
409 }
410 }
411 // Update dynamic constraint and objective
412 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
413 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
414 // Solve for adjoint on interval k
415 if (!isAdjointComputed_) {
416 advanceAdjoint(*lhist_[lindex], *rhs_,
417 *uhist_[uindex-1], *uhist_[uindex],
418 *xp.get(k), timeStamp_[k]);
419 if (useSketch_) {
420 eflag = adjointSketch_->advance(one,*lhist_[0],static_cast<int>(k)-1,one);
421 throwError(eflag,"advance","gradient",367);
422 }
423 }
424 // Update gradient on interval k
425 updateGradient(*gp.get(k), *lhist_[lindex],
426 *uhist_[uindex-1], *uhist_[uindex],
427 *xp.get(k), timeStamp_[k]);
428 }
429 isAdjointComputed_ = true;
430 }
431
432 void hessVec( Vector<Real> &hv, const Vector<Real> &v, const Vector<Real> &x, Real &tol ) {
433 int eflag(0);
434 if (useHessian_) {
435 // Must first solve the state and adjoint equations
436 solveState(x);
437 solveAdjoint(x);
438 // Now compute Hessian
439 const Real one(1);
440 const PartitionedVector<Real> &xp = partition(x);
441 const PartitionedVector<Real> &vp = partition(v);
443 hvp.get(0)->zero(); // zero for the nonexistant zeroth control interval
444 // Compute state sensitivity
445 whist_[0]->zero();
446 if (useSketch_) {
447 stateSensSketch_->update();
448 //stateSensSketch_->advance(one,*whist_[0],0,one);
449 uhist_[0]->set(*u0_);
450 }
451 size_type uindex, lindex;
452 for (size_type k = 1; k < Nt_; ++k) {
453 uindex = (useSketch_ ? 1 : k);
454 lindex = (useSketch_ ? 0 : k);
455 // Reconstruct sketched state
456 if (useSketch_) {
457 eflag = stateSketch_->reconstruct(*uhist_[1],static_cast<int>(k)-1);
458 throwError(eflag,"reconstruct","hessVec",404);
459 eflag = adjointSketch_->reconstruct(*lhist_[0],static_cast<int>(k)-1);
460 throwError(eflag,"reconstruct","hessVec",406);
461 }
462 // Update dynamic constraint and objective
463 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
464 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
465 // Advance state sensitivity on current time interval
466 advanceStateSens(*whist_[uindex],
467 *vp.get(k), *whist_[uindex-1],
468 *uhist_[uindex-1], *uhist_[uindex],
469 *xp.get(k), timeStamp_[k]);
470 // Set control only Hessian
472 *vp.get(k), *lhist_[lindex],
473 *uhist_[uindex-1], *uhist_[uindex],
474 *xp.get(k), timeStamp_[k]);
475 if (!useSymHess_) {
476 // Add mixed derivative Hessian
477 addMixedHessLag(*hvp.get(k), *lhist_[lindex],
478 *whist_[uindex-1], *whist_[uindex],
479 *uhist_[uindex-1], *uhist_[uindex],
480 *xp.get(k), timeStamp_[k]);
481 }
482 // Sketch state sensitivity
483 if (useSketch_) {
484 eflag = stateSensSketch_->advance(one,*whist_[1],static_cast<int>(k)-1,one);
485 throwError(eflag,"advance","hessVec",431);
486 whist_[0]->set(*whist_[1]);
487 uhist_[0]->set(*uhist_[1]);
488 }
489 }
490
491 // Compute adjoint sensitivity
492 uindex = (useSketch_ ? 1 : Nt_-1);
493 lindex = (useSketch_ ? 0 : Nt_-1);
494 if (useSketch_) {
495 // Recover terminal state
496 uhist_[1]->set(*uhist_[0]);
497 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(Nt_)-3);
498 throwError(eflag,"reconstruct","hessVec",444);
499 // Recover terminal adjoint
500 eflag = adjointSketch_->reconstruct(*lhist_[0],static_cast<int>(Nt_)-2);
501 throwError(eflag,"reconstruct","hessVec",447);
502 // Recover terminal state sensitivity
503 whist_[1]->set(*whist_[0]);
504 eflag = stateSensSketch_->reconstruct(*whist_[0],static_cast<int>(Nt_)-3);
505 throwError(eflag,"reconstruct","hessVec",451);
506 }
507 // Update dynamic constraint and objective
508 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
509 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
510 // Solve for terminal condition
512 *vp.get(Nt_-1), *lhist_[lindex],
513 *whist_[uindex-1], *whist_[uindex],
514 *uhist_[uindex-1], *uhist_[uindex],
515 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
516 if (useSymHess_) {
517 // Add mixed derivative Hessian
518 addMixedHessLag(*hvp.get(Nt_-1), *lhist_[lindex],
519 *whist_[uindex-1], *whist_[uindex],
520 *uhist_[uindex-1], *uhist_[uindex],
521 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
522 }
523 // Add adjoint sensitivity to Hessian
524 addAdjointSens(*hvp.get(Nt_-1), *phist_[lindex],
525 *uhist_[uindex-1], *uhist_[uindex],
526 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
527 // Run reverse time stepper
528 for (size_type k = Nt_-2; k > 0; --k) {
529 // Compute new components of rhs
531 *whist_[uindex-1], *whist_[uindex],
532 *uhist_[uindex-1], *uhist_[uindex],
533 *xp.get(k+1), timeStamp_[k+1],
534 false);
536 *vp.get(k+1), *lhist_[lindex],
537 *uhist_[uindex-1], *uhist_[uindex],
538 *xp.get(k+1), timeStamp_[k+1],
539 true);
541 *uhist_[uindex-1], *uhist_[uindex],
542 *xp.get(k+1), timeStamp_[k+1],
543 true);
544 // Recover state, adjoint and state sensitivity from sketch
545 if (useSketch_) {
546 uhist_[1]->set(*uhist_[0]);
547 whist_[1]->set(*whist_[0]);
548 if (k==1) {
549 uhist_[0]->set(*u0_);
550 whist_[0]->zero();
551 }
552 else {
553 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(k)-2);
554 throwError(eflag,"reconstruct","hessVec",500);
555 eflag = stateSensSketch_->reconstruct(*whist_[0],static_cast<int>(k)-2);
556 throwError(eflag,"reconstruct","hessVec",502);
557 }
558 eflag = adjointSketch_->reconstruct(*lhist_[0],static_cast<int>(k)-1);
559 throwError(eflag,"reconstruct","hessVec",505);
560 }
561 uindex = (useSketch_ ? 1 : k);
562 lindex = (useSketch_ ? 0 : k);
563 // Update dynamic constraint and objective
564 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
565 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
566 // Compute old components of rhs
568 *whist_[uindex-1], *whist_[uindex],
569 *uhist_[uindex-1], *uhist_[uindex],
570 *xp.get(k), timeStamp_[k],
571 true);
573 *vp.get(k), *lhist_[lindex],
574 *uhist_[uindex-1], *uhist_[uindex],
575 *xp.get(k), timeStamp_[k],
576 true);
577 // Solve for adjoint on interval k
578 advanceAdjointSens(*phist_[lindex], *rhs_,
579 *uhist_[uindex-1], *uhist_[uindex],
580 *xp.get(k), timeStamp_[k]);
581 if (useSymHess_) {
582 // Add mixed derivative Hessian
583 addMixedHessLag(*hvp.get(k), *lhist_[lindex],
584 *whist_[uindex-1], *whist_[uindex],
585 *uhist_[uindex-1], *uhist_[uindex],
586 *xp.get(k), timeStamp_[k]);
587 }
588 // Add adjoint sensitivity to Hessian
589 addAdjointSens(*hvp.get(k), *phist_[lindex],
590 *uhist_[uindex-1], *uhist_[uindex],
591 *xp.get(k), timeStamp_[k]);
592 }
593 }
594 else {
595 Objective<Real>::hessVec(hv,v,x,tol);
596 }
597 }
598
599private:
600 /***************************************************************************/
601 /************ Method to solve state equation *******************************/
602 /***************************************************************************/
603 Real solveState(const Vector<Real> &x) {
604 Real cnorm(0);
605 if (!isStateComputed_) {
606 int eflag(0);
607 const Real one(1);
608 const PartitionedVector<Real> &xp = partition(x);
609 // Set initial condition
610 uhist_[0]->set(*u0_);
611 if (useSketch_) { // Set initial guess for solve
612 stateSketch_->update();
613 uhist_[1]->set(*u0_);
614 }
615 // Run time stepper
616 size_type index;
617 for (size_type k = 1; k < Nt_; ++k) {
618 index = (useSketch_ ? 1 : k);
619 if (!useSketch_) { // Set initial guess for solve
620 uhist_[index]->set(*uhist_[index-1]);
621 }
622 // Solve state on current time interval
623 con_->update_uo(*uhist_[index-1], timeStamp_[k]);
624 con_->update_z(*xp.get(k), timeStamp_[k]);
625 con_->solve(*cprimal_, *uhist_[index-1], *uhist_[index], *xp.get(k), timeStamp_[k]);
626 cnorm = std::max(cnorm,cprimal_->norm());
627 // Sketch state
628 if (useSketch_) {
629 eflag = stateSketch_->advance(one, *uhist_[1], static_cast<int>(k)-1, one);
630 throwError(eflag,"advance","solveState",574);
631 uhist_[0]->set(*uhist_[1]);
632 }
633 }
634 isStateComputed_ = true;
635 }
636 return cnorm;
637 }
638
639 Real updateSketch(const Vector<Real> &x, const Real tol) {
640 int eflag(0);
641 const PartitionedVector<Real> &xp = partition(x);
642 Real err(0), serr(0), cnorm(0); // cdot(0), dt(0);
643 bool flag = true;
644 while (flag) {
645 err = static_cast<Real>(0);
646 uhist_[0]->set(*u0_);
647 for (size_type k = 1; k < Nt_; ++k) {
648 eflag = stateSketch_->reconstruct(*uhist_[1],static_cast<int>(k)-1);
649 throwError(eflag,"reconstruct","updateSketch",592);
650 con_->update(*uhist_[0], *uhist_[1], *xp.get(k), timeStamp_[k]);
651 con_->value(*cprimal_, *uhist_[0], *uhist_[1], *xp.get(k), timeStamp_[k]);
652 /**** Linf norm for residual error ****/
653 cnorm = cprimal_->norm();
654 err = (cnorm > err ? cnorm : err);
655 if (err > tol) {
656 /**** L2 norm for residual error ****/
657 //cdot = cprimal_->dot(*cprimal_);
658 //dt = timeStamp_[k].t[1]-timeStamp_[k].t[0];
659 //err += cdot / dt;
660 //if (std::sqrt(err) > tol) {
661 break;
662 }
663 uhist_[0]->set(*uhist_[1]);
664 }
665 //err = std::sqrt(err);
666 if (stream_ != nullPtr) {
667 *stream_ << " *** State Rank: " << rankState_ << std::endl;
668 *stream_ << " *** Required Tolerance: " << tol << std::endl;
669 *stream_ << " *** Residual Norm: " << err << std::endl;
670 }
671 if (err > tol) {
672 //Real a(0.1838), b(3.1451); // Navier-Stokes
673 //Real a(2.6125), b(2.4841); // Semilinear
674 //rankState_ = std::max(rankState_+2,static_cast<size_t>(std::ceil((b-std::log(tol))/a)));
675 rankState_ *= updateFactor_; // Perhaps there is a better update strategy
677 stateSketch_->setRank(rankState_);
678 if (syncHessRank_) {
683 }
684 isStateComputed_ = false;
685 isAdjointComputed_ = false;
686 serr = solveState(x);
687 if (stream_ != nullPtr) {
688 *stream_ << " *** Maximum Solver Error: " << serr << std::endl;
689 }
690 }
691 else {
692 flag = false;
693 break;
694 }
695 }
696 return err;
697 }
698
699 /***************************************************************************/
700 /************ Methods to solve adjoint equation ****************************/
701 /***************************************************************************/
703 const Vector<Real> &uold, const Vector<Real> &unew,
704 const Vector<Real> &z, const TimeStamp<Real> &ts) {
705 obj_->gradient_un(*udual_, uold, unew, z, ts);
706 con_->applyInverseAdjointJacobian_un(l, *udual_, uold, unew, z, ts);
707 }
708
710 const Vector<Real> &uold, const Vector<Real> &unew,
711 const Vector<Real> &z, const TimeStamp<Real> &ts) {
712 const Real one(1);
713 obj_->gradient_uo(rhs, uold, unew, z, ts);
714 con_->applyAdjointJacobian_uo(*udual_, l, uold, unew, z, ts);
715 rhs.axpy(-one,*udual_);
716 }
717
719 const Vector<Real> &uold, const Vector<Real> &unew,
720 const Vector<Real> &z, const TimeStamp<Real> &ts) {
721 obj_->gradient_un(*udual_, uold, unew, z, ts);
722 rhs.plus(*udual_);
723 con_->applyInverseAdjointJacobian_un(l, rhs, uold, unew, z, ts);
724 }
725
726 void solveAdjoint(const Vector<Real> &x) {
727 int eflag(0);
728 if (!isAdjointComputed_) {
729 const PartitionedVector<Real> &xp = partition(x);
730 const Real one(1);
731 size_type uindex = (useSketch_ ? 1 : Nt_-1);
732 size_type lindex = (useSketch_ ? 0 : Nt_-1);
733 // Must first compute solve the state equation
734 solveState(x);
735 // Recover state from sketch
736 if (useSketch_) {
737 uhist_[1]->set(*uhist_[0]);
738 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(Nt_)-3);
739 throwError(eflag,"reconstruct","solveAdjoint",672);
740 }
741 // Update dynamic constraint and objective
742 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
743 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(Nt_-1), timeStamp_[Nt_-1]);
744 // Solve for terminal condition
746 *uhist_[uindex-1], *uhist_[uindex],
747 *xp.get(Nt_-1), timeStamp_[Nt_-1]);
748 if (useSketch_) {
749 eflag = adjointSketch_->advance(one,*lhist_[lindex],static_cast<int>(Nt_)-2,one);
750 throwError(eflag,"advance","solveAdjoint",683);
751 }
752 // Run reverse time stepper
753 for (size_type k = Nt_-2; k > 0; --k) {
754 // Compute k+1 component of rhs
755 computeAdjointRHS(*rhs_, *lhist_[lindex],
756 *uhist_[uindex-1], *uhist_[uindex],
757 *xp.get(k+1), timeStamp_[k+1]);
758 // Recover state from sketch
759 if (useSketch_) {
760 uhist_[1]->set(*uhist_[0]);
761 if (k==1) {
762 uhist_[0]->set(*u0_);
763 }
764 else {
765 eflag = stateSketch_->reconstruct(*uhist_[0],static_cast<int>(k)-2);
766 throwError(eflag,"reconstruct","solveAdjoint",699);
767 }
768 }
769 uindex = (useSketch_ ? 1 : k);
770 lindex = (useSketch_ ? 0 : k);
771 // Update dynamic constraint and objective
772 con_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
773 obj_->update(*uhist_[uindex-1], *uhist_[uindex], *xp.get(k), timeStamp_[k]);
774 // Solve for adjoint on interval k
775 advanceAdjoint(*lhist_[lindex], *rhs_,
776 *uhist_[uindex-1], *uhist_[uindex],
777 *xp.get(k), timeStamp_[k]);
778 if (useSketch_) {
779 eflag = adjointSketch_->advance(one,*lhist_[lindex],static_cast<int>(k)-1,one);
780 throwError(eflag,"advance","solveAdjoint",713);
781 }
782 }
783 isAdjointComputed_ = true;
784 }
785 }
786
787 /***************************************************************************/
788 /************ Method for gradient computation ******************************/
789 /***************************************************************************/
791 const Vector<Real> &uold, const Vector<Real> &unew,
792 const Vector<Real> &z, const TimeStamp<Real> &ts) {
793 const Real one(1);
794 obj_->gradient_z(g, uold, unew, z, ts);
795 con_->applyAdjointJacobian_z(*zdual_, l, uold, unew, z, ts);
796 g.axpy(-one,*zdual_);
797 }
798
799 /***************************************************************************/
800 /************ Method to solve state sensitivity equation *******************/
801 /***************************************************************************/
803 const Vector<Real> &wold, const Vector<Real> &uold,
804 const Vector<Real> &unew, const Vector<Real> &z,
805 const TimeStamp<Real> &ts) {
806 const Real one(1);
807 con_->applyJacobian_z(*crhs_, v, uold, unew, z, ts);
808 con_->applyJacobian_uo(*cprimal_, wold, uold, unew, z, ts);
809 crhs_->axpy(-one, *cprimal_);
810 con_->applyInverseJacobian_un(wnew, *crhs_, uold, unew, z, ts);
811 }
812
813 /***************************************************************************/
814 /************ Methods to solve adjoint sensitivity equation ****************/
815 /***************************************************************************/
817 const Vector<Real> &v, const Vector<Real> &l,
818 const Vector<Real> &wold, const Vector<Real> &wnew,
819 const Vector<Real> &uold, const Vector<Real> &unew,
820 const Vector<Real> &z, const TimeStamp<Real> &ts) {
821 const Real one(1);
822 // Mixed derivative rhs term
823 con_->applyAdjointHessian_z_un(*rhs_, l, v, uold, unew, z, ts);
824 obj_->hessVec_un_z(*udual_, v, uold, unew, z, ts);
825 rhs_->axpy(-one, *udual_);
826 // State derivative rhs term
827 con_->applyAdjointHessian_un_un(*udual_, l, wnew, uold, unew, z, ts);
828 rhs_->axpy(-one, *udual_);
829 obj_->hessVec_un_un(*udual_, wnew, uold, unew, z, ts);
830 rhs_->plus(*udual_);
831 con_->applyAdjointHessian_uo_un(*udual_, l, wold, uold, unew, z, ts);
832 rhs_->axpy(-one, *udual_);
833 obj_->hessVec_un_uo(*udual_, wold, uold, unew, z, ts);
834 rhs_->plus(*udual_);
835 // Invert adjoint Jacobian
836 con_->applyInverseAdjointJacobian_un(p, *rhs_, uold, unew, z, ts);
837 }
838
840 const Vector<Real> &wold, const Vector<Real> &wnew,
841 const Vector<Real> &uold, const Vector<Real> &unew,
842 const Vector<Real> &z, const TimeStamp<Real> &ts,
843 const bool sumInto = false) {
844 const Real one(1);
845 // Compute new/old Hessian of Lagrangian
846 if (!sumInto) {
847 obj_->hessVec_un_uo(Hv, wold, uold, unew, z, ts);
848 }
849 else {
850 obj_->hessVec_un_uo(*udual_, wold, uold, unew, z, ts);
851 Hv.plus(*udual_);
852 }
853 con_->applyAdjointHessian_uo_un(*udual_, l, wold, uold, unew, z, ts);
854 Hv.axpy(-one,*udual_);
855 // Compute new/new Hessian of Lagrangian
856 obj_->hessVec_un_un(*udual_, wnew, uold, unew, z, ts);
857 Hv.plus(*udual_);
858 con_->applyAdjointHessian_un_un(*udual_, l, wnew, uold, unew, z, ts);
859 Hv.axpy(-one,*udual_);
860 }
861
863 const Vector<Real> &v, const Vector<Real> &l,
864 const Vector<Real> &uold, const Vector<Real> &unew,
865 const Vector<Real> &z, const TimeStamp<Real> &ts,
866 const bool sumInto = false) {
867 const Real one(1);
868 // Compute new/old Hessian of Lagrangian
869 if (!sumInto) {
870 con_->applyAdjointHessian_z_un(Hv, l, v, uold, unew, z, ts);
871 }
872 else {
873 con_->applyAdjointHessian_z_un(*udual_, l, v, uold, unew, z, ts);
874 Hv.plus(*udual_);
875 }
876 obj_->hessVec_un_z(*udual_, v, uold, unew, z, ts);
877 Hv.axpy(-one, *udual_);
878 }
879
881 const Vector<Real> &uold, const Vector<Real> &unew,
882 const Vector<Real> &z, const TimeStamp<Real> &ts,
883 const bool sumInto = false) {
884 const Real one(1);
885 if (!sumInto) {
886 con_->applyAdjointJacobian_uo(Hv, p, uold, unew, z, ts);
887 Hv.scale(-one);
888 }
889 else {
890 con_->applyAdjointJacobian_uo(*udual_, p, uold, unew, z, ts);
891 Hv.axpy(-one, *udual_);
892 }
893 }
894
896 const Vector<Real> &wold, const Vector<Real> &wnew,
897 const Vector<Real> &uold, const Vector<Real> &unew,
898 const Vector<Real> &z, const TimeStamp<Real> &ts,
899 const bool sumInto = false) {
900 const Real one(1);
901 // Compute old/new Hessian of Lagrangian
902 if (!sumInto) {
903 obj_->hessVec_uo_un(Hv, wnew, uold, unew, z, ts);
904 }
905 else {
906 obj_->hessVec_uo_un(*udual_, wnew, uold, unew, z, ts);
907 Hv.plus(*udual_);
908 }
909 con_->applyAdjointHessian_un_uo(*udual_, l, wnew, uold, unew, z, ts);
910 Hv.axpy(-one,*udual_);
911 // Compute old/old Hessian of Lagrangian
912 obj_->hessVec_uo_uo(*udual_, wold, uold, unew, z, ts);
913 Hv.plus(*udual_);
914 con_->applyAdjointHessian_uo_uo(*udual_, l, wold, uold, unew, z, ts);
915 Hv.axpy(-one,*udual_);
916 }
917
919 const Vector<Real> &v, const Vector<Real> &l,
920 const Vector<Real> &uold, const Vector<Real> &unew,
921 const Vector<Real> &z, const TimeStamp<Real> &ts,
922 const bool sumInto = false) {
923 const Real one(1);
924 // Compute new/old Hessian of Lagrangian
925 if (!sumInto) {
926 con_->applyAdjointHessian_z_uo(Hv, l, v, uold, unew, z, ts);
927 }
928 else {
929 con_->applyAdjointHessian_z_uo(*udual_, l, v, uold, unew, z, ts);
930 Hv.plus(*udual_);
931 }
932 obj_->hessVec_uo_z(*udual_, v, uold, unew, z, ts);
933 Hv.axpy(-one,*udual_);
934 }
935
937 const Vector<Real> &uold, const Vector<Real> &unew,
938 const Vector<Real> &z, const TimeStamp<Real> &ts) {
939 // Solve adjoint sensitivity on current time interval
940 con_->applyInverseAdjointJacobian_un(p, rhs, uold, unew, z, ts);
941 }
942
943 /***************************************************************************/
944 /************ Method for Hessian-times-a-vector computation ****************/
945 /***************************************************************************/
947 const Vector<Real> &v, const Vector<Real> &l,
948 const Vector<Real> &uold, const Vector<Real> &unew,
949 const Vector<Real> &z, const TimeStamp<Real> &ts) {
950 const Real one(1);
951 // Compute Hessian of Lagrangian
952 obj_->hessVec_z_z(Hv, v, uold, unew, z, ts);
953 con_->applyAdjointHessian_z_z(*zdual_, l, v, uold, unew, z, ts);
954 Hv.axpy(-one, *zdual_);
955 }
956
958 const Vector<Real> &wold, const Vector<Real> &wnew,
959 const Vector<Real> &uold, const Vector<Real> &unew,
960 const Vector<Real> &z, const TimeStamp<Real> &ts) {
961 const Real one(1);
962 // Compute Hessian of Lagrangian on previous time interval
963 obj_->hessVec_z_uo(*zdual_, wold, uold, unew, z, ts);
964 Hv.axpy(-one, *zdual_);
965 con_->applyAdjointHessian_uo_z(*zdual_, l, wold, uold, unew, z, ts);
966 Hv.plus(*zdual_);
967 // Compute Hessian of Lagrangian on current time interval
968 obj_->hessVec_z_un(*zdual_, wnew, uold, unew, z, ts);
969 Hv.axpy(-one, *zdual_);
970 con_->applyAdjointHessian_un_z(*zdual_, l, wnew, uold, unew, z, ts);
971 Hv.plus(*zdual_);
972 }
973
975 const Vector<Real> &uold, const Vector<Real> &unew,
976 const Vector<Real> &z, const TimeStamp<Real> &ts) {
977 con_->applyAdjointJacobian_z(*zdual_, p, uold, unew, z, ts);
978 Hv.plus(*zdual_);
979 }
980};
981
982} // namespace ROL
983
984#endif // ROL_REDUCEDDYNAMICOBJECTIVE_HPP
Objective_SerialSimOpt(const Ptr< Obj > &obj, const V &ui) z0 zero)()
Defines the time-dependent constraint operator interface for simulation-based optimization.
Defines the time-dependent objective function interface for simulation-based optimization....
virtual void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Apply Hessian approximation to vector.
Defines the linear algebra of vector space on a generic partitioned vector.
ROL::Ptr< const Vector< Real > > get(size_type i) const
static Ptr< PartitionedVector > create(std::initializer_list< Vp > vs)
void hessVec(Vector< Real > &hv, const Vector< Real > &v, const Vector< Real > &x, Real &tol)
Real updateSketch(const Vector< Real > &x, const Real tol)
const PartitionedVector< Real > & partition(const Vector< Real > &x) const
Ptr< Vector< Real > > makeDynamicVector(const Vector< Real > &x) const
void addMixedHessLag(Vector< Real > &Hv, const Vector< Real > &l, const Vector< Real > &wold, const Vector< Real > &wnew, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void advanceStateSens(Vector< Real > &wnew, const Vector< Real > &v, const Vector< Real > &wold, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void computeNewMixedHessLag(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts, const bool sumInto=false)
void computeNewStateJacobian(Vector< Real > &Hv, const Vector< Real > &p, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts, const bool sumInto=false)
typename std::vector< Real >::size_type size_type
void addAdjointSens(Vector< Real > &Hv, const Vector< Real > &p, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void setTerminalConditionHess(Vector< Real > &p, const Vector< Real > &v, const Vector< Real > &l, const Vector< Real > &wold, const Vector< Real > &wnew, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void computeOldMixedHessLag(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts, const bool sumInto=false)
std::vector< Ptr< Vector< Real > > > uhist_
std::vector< Ptr< Vector< Real > > > phist_
Real solveState(const Vector< Real > &x)
void computeNewStateHessLag(Vector< Real > &Hv, const Vector< Real > &l, const Vector< Real > &wold, const Vector< Real > &wnew, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts, const bool sumInto=false)
void setTerminalCondition(Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void gradient(Vector< Real > &g, const Vector< Real > &x, Real &tol)
std::vector< Ptr< Vector< Real > > > whist_
void update(const Vector< Real > &x, UpdateType type, int iter=-1)
const std::vector< TimeStamp< Real > > timeStamp_
void solveAdjoint(const Vector< Real > &x)
void update(const Vector< Real > &x, bool flag=true, int iter=-1)
void updateGradient(Vector< Real > &g, const Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
Real value(const Vector< Real > &x, Real &tol)
void advanceAdjointSens(Vector< Real > &p, Vector< Real > &rhs, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void computeOldStateHessLag(Vector< Real > &Hv, const Vector< Real > &l, const Vector< Real > &wold, const Vector< Real > &wnew, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts, const bool sumInto=false)
const Ptr< DynamicConstraint< Real > > con_
std::vector< Ptr< Vector< Real > > > lhist_
void advanceAdjoint(Vector< Real > &l, Vector< Real > &rhs, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
PartitionedVector< Real > & partition(Vector< Real > &x) const
const Ptr< DynamicObjective< Real > > obj_
void computeControlHessLag(Vector< Real > &Hv, const Vector< Real > &v, const Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
ReducedDynamicObjective(const Ptr< DynamicObjective< Real > > &obj, const Ptr< DynamicConstraint< Real > > &con, const Ptr< Vector< Real > > &u0, const Ptr< Vector< Real > > &zvec, const Ptr< Vector< Real > > &cvec, const std::vector< TimeStamp< Real > > &timeStamp, ROL::ParameterList &pl, const Ptr< std::ostream > &stream=nullPtr)
void computeAdjointRHS(Vector< Real > &rhs, const Vector< Real > &l, const Vector< Real > &uold, const Vector< Real > &unew, const Vector< Real > &z, const TimeStamp< Real > &ts)
void throwError(const int err, const std::string &sfunc, const std::string &func, const int line) const
Defines the linear algebra or vector space interface.
virtual void scale(const Real alpha)=0
Compute where .
virtual void print(std::ostream &outStream) const
virtual void plus(const Vector &x)=0
Compute , where .
virtual void axpy(const Real alpha, const Vector &x)
Compute where .
Real ROL_EPSILON(void)
Platform-dependent machine epsilon.
Definition ROL_Types.hpp:91
Contains local time step information.