ROL
ROL_Constraint_SerialSimOpt.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
45#pragma once
46#ifndef ROL_CONSTRAINT_SERIALSIMOPT_HPP
47#define ROL_CONSTRAINT_SERIALSIMOPT_HPP
48
49namespace ROL {
51/** @ingroup func_group
52 \class ROL::Constraint_SerialSimOpt
53 \brief Unifies the constraint defined on a single time step that are
54 defined through the Constraint_TimeSimOpt interface into a
55 SimOpt constraint for all time. Primarily intended for use
56 in testing the parallel-in-time implementation.
58 In contrast to Constraint_PinTSimOpt, where the argument vectors
59 are PartitionedVectors with Vector_SimOpt, the approach here is
60 to consider the state and control to be of PartitionedVector type
61 directly.
64 NOTE: This class does not address non-autonomous systems as constraints.
65 The formulas involving adjoint Jacobians are almost certainly
66 incorrect in such cases. This will need to be fixed if the
67 Constraint_TimeSimOpt interface can accommodate explicit functions
68 of time. Additionally, opt vectors are assumed to be constant in
69 time on a time step.
78template<typename Real>
81 using V = Vector<Real>;
87private:
89 const Ptr<Con> con_; // Constraint for single time step
90 const Ptr<V> ui_; // Initial condition
91 Ptr<V> u0_; // Zero sim vector on time step
92 Pre<V> z0_; // Zero opt vector on time step
94 VectorWorkspace<Real> workspace_; // Memory management
96protected:
98 PV& partition( V& x ) const { return static_cast<PV&>(x); }
100 const V& partition( const V& x ) const { return static_cast<const PV&>(x); }
103public:
105 Constraint_SerialSimOpt( const Ptr<Con>& con, const V& ui, const V& zi ) :
106 Constraint_SimOpt<Real>(), con_(con),
107 ui_( workspace_.copy( ui ) ),
108 u0_( workspace_.clone( ui ) ),
109 z0_( workspace_.clone( ui ) ) {
110 u0_->zero(); z0_->zero();
113// virtual void update_1( const V& u, const V& z, bool flag = true, int iter = -1 ) override {
114//
115// }
116//
117// virtual void update_2( const V& u, const V& z, bool flag = true, int iter = -1 ) override {
119// }
121 virtual void value( V& c, const V& u, const V& z, Real& tol ) override {
123 auto& cp = partition(c);
124 auto& up = partition(u);
125 auto& zp = partition(z);
127 // First interval value uses initial condition
128 con_->value( *(cp.get(0)), *ui_, *(zp.get(0)), tol );
130 for( size_type k=1, k<cp.numVectors(), ++k ) {
131 con_->value( *(cp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
135 virtual void solve( V& c, V& u, const V& z, Real& tol ) override {
137 auto& cp = partition(c);
138 auto& up = partition(u);
139 auto& zp = partition(z);
141 // First interval value uses initial condition
142 con_->solve( *(cp.get(0)), *ui_, *(zp.get(0)), tol );
144 for( size_type k=1, k<cp.numVectors(), ++k ) {
145 con_->solve( *(cp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
149 virtual void applyJacobian_1( V& jv, const V& v, const V& u, const V& z, Real& tol ) override {
151 auto& jvp = partition(jv); auto& vp = partition(v);
152 auto& up = partition(u); auto& zp = partition(z);
154 auto tmp = workspace_.clone( up.get(0) );
156 con_->applyJacobian_1_new( *(jvp.get(0)), *(vp.get(0)), *u0_, *(up.get(0)), *(zp.get(0)), tol );
158 for( size_type k=1; k<jvp.numVectors(); ++jvp ) {
159 con_->applyJacobian_1_new( *(jvp.get(k)), *(vp.get(k)), *(up.get(k)), *(up.get(k-1)), *(zp.get(k)), tol );
160 con_->applyJacobian_1_old( *tmp, *(vp.get(k)), *(up.get(k)), *(up.get(k-1)), *(zp.get(k)), tol );
161 jvp.plus(tmp);
163 } // applyJacobian_1
165 virtual void applyJacobian_2( V& jv, const V& v, const V& u, const V& z, Real& tol) override {
167 auto& jvp = partition(jv); auto& vp = partition(v);
168 auto& up = partition(u); auto& zp = partition(z);
169
170 for( size_type k=0; k<jvp.numVectors(); ++k ) {
171 con_->applyJacobian_2( *(jvp.get(k)), *(vp.get(k)), *(up.get(k)), *(up.get(k-1)), *(zp.get(k)), tol );
173 } // applyJacobian_2
176 virtual void applyInverseJacobian_1( V& ijv, const V& v, const V& u,
177 const V& z, Real& tol ) override {
179 auto& ijvp = partition(ijv); auto& vp = partition(v);
180 auto& up = partition(u); auto& zp = partition(z);
181
182 // First step
183 con_->applyInverseJacobian_1_new( *(ijvp.get(0)), *(vp.get(0), *u0_, *(up.get(0)), *(zp.get(0)), tol );
185 auto tmp = workspace.clone( vp.get(0) );
187 for( size_type k=1; k<ijvp.numVectors(); ++k ) {
188
189 con_->applyJacobian_1_old( *tmp, *(ijvp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
190 tmp->scale(-1.0);
191 tmp->plus( *(vp.get(k) );
193 con_->applyInverseJacobian_1_new( *(ijvp.get(k)), *tmp, *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
195 } // applyInverseJacobian_1
197
199 virtual void applyAdjointJacobian_1( V& ajv, const V& v, const V& u,
200 const V& z, Real& tol) override {
202 auto& ajvp = partition(ajv); auto& vp = partition(v);
203 auto& up = partition(u); auto& zp = partition(z);
205 auto tmp = workspace.clone( ajvp.get(0) );
207 size_type N = ajvp.numVectors()-1;
209 // First step
210 con_->applyAdjointJacobian_1_new( *(ajvp.get(0)), *(vp.get(0)), *u0_, *(up.get(0)), *(zp.get(0)) );
211 con_->applyAdjointJacobian_1_old( *(ajvp.get(0)), *(vp.get(1)), *u0_, *(up.get(0)), *(zp.get(0)) );
213 for( size_type k=1; k<N; ++k ) {
214 con_->applyAdjointJacobian_1_new( *(ajvp.get(k)), *(vp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
215 con_->applyAdjointJacobian_1_old( *tmp, *(vp.get(k+1)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
216 ajvp.plus(*tmp);
219 // Last step
220 con_->applyAdjointJacobian_1_new( *(ajvp.get(k)), *(vp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
221
222 } // applyAdjointJacobian_1
223
225
226 virtual void applyAdjointJacobian_1( V& ajv, const V& v, const V& u, const V &z,
227 const V& dualv, Real& tol) override {
229 auto& ajvp = partition(ajv); auto& vp = partition(dualv);
230 auto& up = partition(u); auto& zp = partition(z);
231 auto tmp = workspace.clone( ajvp.get(0) );
233 size_type N = ajvp.numVectors()-1;
235 // First step
236 con_->applyAdjointJacobian_1_new( *(ajvp.get(0)), *(vp.get(0)), *u0_, *(up.get(0)), *(zp.get(0)) );
237 con_->applyAdjointJacobian_1_old( *(ajvp.get(0)), *(vp.get(1)), *u0_, *(up.get(0)), *(zp.get(0)) );
239 for( size_type k=1; k<N; ++k ) {
240 con_->applyAdjointJacobian_1_new( *(ajvp.get(k)), *(vp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
241 con_->applyAdjointJacobian_1_old( *tmp, *(vp.get(k+1)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
242 ajvp.plus(*tmp);
245 // Last step
246 con_->applyAdjointJacobian_1_new( *(ajvp.get(k)), *(vp.get(k)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)) );
247
248 } // applyAdjointJacobian_1
250
251
252 virtual void applyAdjointJacobian_2( V& ajv, const V& v, const V& u,
253 const V& z, Real& tol) override {
254 auto& ajvp = partition(ajv); auto& vp = partition(v);
255 auto& up = partition(u); auto& zp = partition(z);
256
257 for( size_type k=0; k<jvp.numVectors(); ++k ) {
258 con_->applyAdjointJacobian_2_time( *(jvp.get(k)), *(vp.get(k)), *(up.get(k)), *(up.get(k-1)), *(zp.get(k)), tol );
260 } // applyAdjointJacobian_2
263 virtual void applyAdjointJacobian_2( V& ajv, const V& v, const V& u, const V& z,
264 const V& dualv, Real& tol) override {
266 auto& ajvp = partition(ajv); auto& vp = partition(v);
267 auto& up = partition(u); auto& zp = partition(z);
268
269 for( size_type k=0; k<jvp.numVectors(); ++k ) {
270 con_->applyAdjointJacobian_2_time( *(jvp.get(k)), *(vp.get(k)), *(up.get(k)), *(up.get(k-1)), *(zp.get(k)), tol );
272 }
273
275 virtual void applyInverseAdjointJacobian_1( V& iajv, const V& v, const V& u,
276 const V& z, Real& tol) override {
278 auto& iajvp = partition(iajv); auto& vp = partition(v);
279 auto& up = partition(u); auto& zp = partition(z);
281 size_type N = iajvp.numVectors()-1;
283 // Last Step
284 con_->applyInverseAdjointJacobian_1_new( *(iajvp.get(N)), *(vp.get(N)), *(up.get(N-1)), *(up.get(N)), *(zp.get(N)), tol );
286 auto tmp = workspace_.clone( vp.get(0) );
288 for( size_type k=N-1; k>0; --k ) {
289 con_->applyAdjointJacobian_1_old( *tmp, *(iajvp.get(k+1)), *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
291 tmp->scale( -1.0 );
292 tmp->plus( *(vp.get(k) );
294 con_->applyAdjointJacobian_1_new( *(iajvp.get(k)), *tmp, *(up.get(k-1)), *(up.get(k)), *(zp.get(k)), tol );
295 }
296
297 // "First step"
298 con_->applyAdjointJacobian_1_old( *tmp, *(iajvp.get(1)), *u0_, *(up.get(0)), *(zp.get(0)), tol );
299
300 tmp->scale( -1.0 );
301 tmp->plus( *(vp.get(0) );
302
303 con_->applyAdjointJacobian_1_new( *(iajvp.get(0)), *tmp, *u0_, *(up.get(0)), *(zp.get(0)), tol );
304 }
305
306
307 virtual void applyAdjointHessian_11( V& ahwv, const V& w, const V& v,
308 const V& u, const V& z, Real& tol) override {
309 // TODO
311
312
313 virtual void applyAdjointHessian_11( V& ahwv, const V& w, const V& v,
314 const V& u, const V& z, Real& tol) override {
315 ahwv.zero();
316 }
317
318 virtual void applyAdjointHessian_11( V& ahwv, const V& w, const V& v,
319 const V& u, const V& z, Real& tol) override {
320 ahwv.zero();
321 }
322
323 virtual void applyAdjointHessian_11( V& ahwv, const V& w, const V& v,
324 const V& u, const V& z, Real& tol) override {
325 ahwv.zero();
326 }
327
328
329
330
331
332
333
335
336
337}; // class Constraint_SerialSimOpt
338
339
341} // namespace ROL
342
343
344#endif // ROL_CONSTRAINT_SERIALSIMOPT_HPP
345
Vector< Real > V
PartitionedVector< Real > PV
const Ptr< V > ui_
VectorWorkspace< Real > workspace_
PV & partition(V &x) const
virtual void solve(Vector< Real > &c, Vector< Real > &u, const Vector< Real > &z) override
virtual Real value(const Vector< Real > &u_old, const Vector< Real > &u_new, const Vector< Real > &z, Real &tol)
Compute contribution to objective value from this time step.
Unifies the constraint defined on a single time step that are defined through the Constraint_TimeSimO...
Defines the time dependent constraint operator interface for simulation-based optimization.
Defines the linear algebra of vector space on a generic partitioned vector.
const Ptr< Constraint< Real > > con_
ROL::Ptr< V > clone() const
Clone to make a new (uninitialized) vector.
virtual void zero()
Set to zero vector.