ROL
ROL_SerialConstraint.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_SERIALCONSTRAINT_HPP
46 #define ROL_SERIALCONSTRAINT_HPP
47 
48 #include <type_traits>
49 
52 #include "ROL_SerialFunction.hpp"
53 
61 namespace ROL {
62 
63 template<typename Real>
64 class SerialConstraint : public Constraint_SimOpt<Real>,
65  public SerialFunction<Real> {
66 private:
67 
71 
72  Ptr<DynamicConstraint<Real>> con_; // Constraint over a single time step
73 
74 public:
75 
81 
83  const Vector<Real>& u_initial,
84  const TimeStampsPtr<Real>& timeStampsPtr ) :
85  SerialFunction<Real>::SerialFunction( u_initial, timeStampsPtr ),
86  con_(con) {}
87 
88  virtual void solve( Vector<Real>& c,
89  Vector<Real>& u,
90  const Vector<Real>& z,
91  Real& tol ) override {
92 
93  auto& cp = partition(c);
94  auto& up = partition(u);
95  auto& zp = partition(z);
96 
98  con_->solve( cp[0], getInitialCondition(), up[0], zp[0], ts(0) );
99 
100  for( size_type k=1; k<numTimeSteps(); ++k )
101  con_->solve( cp[k], up[k-1], up[k], zp[k], ts(k) );
102 
103  } // solve
104 
105 
106  virtual void value( Vector<Real>& c,
107  const Vector<Real>& u,
108  const Vector<Real>& z,
109  Real& tol ) override {
110 
111  auto& cp = partition(c);
112  auto& up = partition(u);
113  auto& zp = partition(z);
114 
115  if( !getSkipInitialCondition() )
116  con_->value( cp[0], getInitialCondition(), up[0], zp[0], ts(0) );
117 
118  for( size_type k=1; k<numTimeSteps(); ++k )
119  con_->value( cp[k], up[k-1], up[k], zp[k], ts(k) );
120 
121  } // value
122 
123 
124  virtual void applyJacobian_1( Vector<Real>& jv,
125  const Vector<Real>& v,
126  const Vector<Real>& u,
127  const Vector<Real>& z,
128  Real& tol ) override {
129 
130  auto& jvp = partition(jv); auto& vp = partition(v);
131  auto& up = partition(u); auto& zp = partition(z);
132 
133  auto tmp = clone(jvp[0]);
134  auto& x = *tmp;
135 
136  if( !getSkipInitialCondition() )
137  con_->applyJacobian_un( jvp[0], vp[0], getZeroState(), up[0], zp[0], ts(0) );
138 
139  for( size_type k=1; k<numTimeSteps(); ++k ) {
140 
141  con_->applyJacobian_uo( x, vp[k-1], up[k-1], up[k], zp[k], ts(k) );
142  con_->applyJacobian_un( jvp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
143  jvp.get(k)->plus(x);
144 
145  } // end for
146 
147  } // applyJacobian_1
148 
149 
151  const Vector<Real>& v,
152  const Vector<Real>& u,
153  const Vector<Real>& z,
154  Real& tol) override {
155 
156  auto& ijvp = partition(ijv); auto& vp = partition(v);
157  auto& up = partition(u); auto& zp = partition(z);
158 
159  auto tmp = clone(ijvp[0]);
160  auto& x = *tmp;
161 
162  if( !getSkipInitialCondition() )
163  con_->applyInverseJacobian_un( ijvp[0], vp[0], getZeroState(),
164  up[0], zp[0], ts(0) );
165 
166  for( size_type k=1; k<numTimeSteps(); ++k ) {
167 
168  con_->applyJacobian_uo( x, ijvp[k-1], up[k-1], up[k], zp[k], ts(k) );
169  x.scale(-1.0);
170  x.plus( vp[k] );
171  con_->applyInverseJacobian_un( ijvp[k], x, up[k-1], up[k], zp[k], ts(k) );
172 
173  } // end for
174 
175  } // applyInverseJacobian_1
176 
177 
179  const Vector<Real>& v,
180  const Vector<Real>& u,
181  const Vector<Real>& z,
182  const Vector<Real>& dualv,
183  Real& tol) override {
184 
185  auto& ajvp = partition(ajv); auto& vp = partition(v);
186  auto& up = partition(u); auto& zp = partition(z);
187 
188  auto tmp = clone(ajvp[0]);
189  auto& x = *tmp;
190 
191  if( !getSkipInitialCondition() )
192  con_->applyAdjointJacobian_un( ajvp[0], vp[0], getZeroState(), up[0], zp[0], ts(0) );
193 
194  for( size_type k=1; k<numTimeSteps(); ++k ) {
195 
196  con_->applyAdjointJacobian_un( ajvp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
197  con_->applyAdjointJacobian_uo( x, vp[k], up[k-1], up[k], zp[k], ts(k) );
198  ajvp[k-1].plus(x);
199 
200  } // end for
201 
202  } // applyAdjointJacobian_1
203 
205  const Vector<Real>& v,
206  const Vector<Real>& u,
207  const Vector<Real>& z,
208  Real& tol) override {
209 
210  auto& iajvp = partition(iajv); auto& vp = partition(v);
211  auto& up = partition(u); auto& zp = partition(z);
212 
213  auto tmp = clone(iajvp[0]);
214  auto& x = *tmp;
215 
216  size_type k = numTimeSteps()-1;
217 
218  con_->applyInverseAdjointJacobian_un( iajvp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
219 
220  for( size_type k=numTimeSteps()-2; k>0; --k ) {
221 
222  con_->applyAdjointJacobian_uo( x, iajvp[k+1], up[k], up[k+1], zp[k+1], ts(k+1) );
223  x.scale(-1.0);
224  x.plus( vp[k] );
225  con_->applyInverseAdjointJacobian_un( iajvp[k], x, up[k-1], up[k], zp[k], ts(k) );
226 
227  } // end for
228 
229  con_->applyAdjointJacobian_uo( x, iajvp[1], up[0], up[1], zp[1], ts(1) );
230  x.scale(-1.0);
231  x.plus( vp[0] );
232 
233  if( !getSkipInitialCondition() )
234  con_->applyInverseAdjointJacobian_un( iajvp[0], x, getZeroState(), up[0], zp[0], ts(0) );
235 
236  // this weird condition places iajvp in the final vector slot
237  else iajvp[0].set(x);
238 
239  } // applyInverseAdjointJacobian_1
240 
241 
242  virtual void applyJacobian_2( Vector<Real>& jv,
243  const Vector<Real>& v,
244  const Vector<Real>& u,
245  const Vector<Real>& z,
246  Real &tol ) override {
247 
248  auto& jvp = partition(jv); auto& vp = partition(v);
249  auto& up = partition(u); auto& zp = partition(z);
250 
251  if( !getSkipInitialCondition() )
252  con_->applyJacobian_z( jvp[0], vp[0], getInitialCondition(), up[0], zp[0], ts(0) );
253 
254  for( size_type k=1; k<numTimeSteps(); ++k )
255  con_->applyJacobian_z( jvp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
256 
257  } // applyJacobian_2
258 
259 
261  const Vector<Real>& v,
262  const Vector<Real>& u,
263  const Vector<Real>& z,
264  Real& tol ) override {
265 
266  auto& ajvp = partition(ajv); auto& vp = partition(v);
267  auto& up = partition(u); auto& zp = partition(z);
268 
269  if( !getSkipInitialCondition() )
270  con_->applyAdjointJacobian_z( ajvp[0], vp[0], getInitialCondition(), up[0], zp[0], ts(0) );
271 
272  for( size_type k=1; k<numTimeSteps(); ++k )
273  con_->applyAdjointJacobian_z( ajvp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
274 
275  } // applyAdjointJacobian_2
276 
277 
278 
279  virtual void applyAdjointHessian_11( Vector<Real>& ahwv,
280  const Vector<Real>& w,
281  const Vector<Real>& v,
282  const Vector<Real>& u,
283  const Vector<Real>& z,
284  Real& tol) override {
285 
286  auto& ahwvp = partition(ahwv); auto& wp = partition(w);
287  auto& vp = partition(v); auto& up = partition(u);
288  auto& zp = partition(z);
289 
290  auto tmp = clone(ahwvp[0]);
291  auto& x = *tmp;
292 
293  if( !getSkipInitialCondition() ) {
294 
295  con_->applyAdjointHessian_un_un( ahwvp[0], wp[0], vp[0], getZeroState(), up[0], zp[0], ts(0) );
296  con_->applyAdjointHessian_un_uo( x, wp[1], vp[1], up[0], up[1], zp[1], ts(1) );
297  ahwvp[0].plus(x);
298  con_->applyAdjointHessian_uo_uo( x, wp[1], vp[0], up[0], up[1], zp[1], ts(1) );
299  ahwvp[0].plus(x);
300 
301  }
302 
303  for( size_type k=1; k<numTimeSteps(); ++k ) {
304 
305  con_->applyAdjointHessian_un_un( ahwvp[k], wp[k], vp[k], up[k-1], up[k], zp[k], ts(k) );
306  con_->applyAdjointHessian_uo_un( x, wp[k], vp[k-1], up[k-1], up[k], zp[k], ts(k) );
307  ahwvp[k].plus(x);
308 
309  if( k < numTimeSteps()-1 ) {
310  con_->applyAdjointHessian_un_uo( x, wp[k+1], vp[k+1], up[k], up[k+1], zp[k+1], ts(k+1) );
311  ahwvp[k].plus(x);
312  con_->applyAdjointHessian_uo_uo( x, wp[k+1], vp[k], up[k], up[k+1], zp[k+1], ts(k+1) );
313  ahwvp[k].plus(x);
314  } // endif
315  } // endfor
316 
317  } // applyAdjointHessian_11
318 
319 
320  // TODO: Implement off-diagonal blocks
322  const Vector<Real>& w,
323  const Vector<Real>& v,
324  const Vector<Real>& u,
325  const Vector<Real>& z,
326  Real& tol) override {
327  }
328 
329 
331  const Vector<Real>& w,
332  const Vector<Real>& v,
333  const Vector<Real>& u,
334  const Vector<Real>& z,
335  Real& tol) override {
336  }
337 
338  virtual void applyAdjointHessian_22( Vector<Real>& ahwv,
339  const Vector<Real>& w,
340  const Vector<Real>& v,
341  const Vector<Real>& u,
342  const Vector<Real>& z,
343  Real& tol) override {
344 
345  auto& ahwvp = partition(ahwv); auto& vp = partition(v); auto& wp = partition(w);
346  auto& up = partition(u); auto& zp = partition(z);
347 
348  con_->applyAdjointHessian_z_z( ahwvp[0], wp[0], vp[0], getInitialCondition(),
349  up[0], zp[0], ts(0) );
350 
351  for( size_type k=1; k<numTimeSteps(); ++k ) {
352  con_->applyAdjointHessian_z_z( ahwvp[k], wp[k], vp[k], up[k-1],
353  up[k], zp[k], ts(k) );
354  }
355 
356  } // applyAdjointHessian_22
357 
358 
359 }; // SerialConstraint
360 
361 // Helper function to create a new SerialConstraint
362 
363 template<typename DynCon, typename Real, typename P = Ptr<SerialConstraint<Real>>>
364 inline typename std::enable_if<std::is_base_of<DynamicConstraint<Real>,DynCon>::value,P>::type
365 make_SerialConstraint( const Ptr<DynCon>& con,
366  const Vector<Real>& u_initial,
367  const TimeStampsPtr<Real> timeStampsPtr ) {
368  return makePtr<SerialConstraint<Real>>(con,u_initial,timeStampsPtr);
369 }
370 
371 
372 
373 
374 
375 
376 } // namespace ROL
377 
378 
379 #endif // ROL_SERIALCONSTRAINT_HPP
PartitionedVector< Real > & partition(Vector< Real > &x)
const Vector< Real > & getInitialCondition() const
typename PV< Real >::size_type size_type
virtual void applyAdjointHessian_12(Vector< Real > &ahwv, const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the optimization-space derivative of the adjoint of the constraint simulation-space Jacobian at...
const Vector< Real > & getZeroState() const
Defines the time-dependent constraint operator interface for simulation-based optimization.
Defines the linear algebra of vector space on a generic partitioned vector.
virtual void applyAdjointHessian_21(Vector< Real > &ahwv, const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the simulation-space derivative of the adjoint of the constraint optimization-space Jacobian at...
virtual void applyAdjointHessian_22(Vector< Real > &ahwv, const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the optimization-space derivative of the adjoint of the constraint optimization-space Jacobian ...
ROL::Objective_SimOpt value
size_type numTimeSteps() const
virtual void value(Vector< Real > &c, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Evaluate the constraint operator at .
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:80
virtual void applyAdjointJacobian_1(Vector< Real > &ajv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, const Vector< Real > &dualv, Real &tol) override
Apply the adjoint of the partial constraint Jacobian at , , to the vector . This is the secondary int...
virtual void applyJacobian_1(Vector< Real > &jv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the partial constraint Jacobian at , , to the vector .
virtual void applyJacobian_2(Vector< Real > &jv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the partial constraint Jacobian at , , to the vector .
std::enable_if< std::is_base_of< DynamicConstraint< Real >, DynCon >::value, P >::type make_SerialConstraint(const Ptr< DynCon > &con, const Vector< Real > &u_initial, const TimeStampsPtr< Real > timeStampsPtr)
Ptr< Vector< Real > > clone(const Vector< Real > &x)
typename std::vector< Real >::size_type size_type
virtual void applyAdjointJacobian_2(Vector< Real > &ajv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the adjoint of the partial constraint Jacobian at , , to vector . This is the primary interface...
SerialConstraint(const Ptr< DynamicConstraint< Real >> &con, const Vector< Real > &u_initial, const TimeStampsPtr< Real > &timeStampsPtr)
void applyInverseAdjointJacobian_1(Vector< Real > &iajv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the inverse of the adjoint of the partial constraint Jacobian at , , to the vector ...
bool getSkipInitialCondition() const
Provides behavior common to SerialObjective as SerialConstaint.
virtual void applyAdjointHessian_11(Vector< Real > &ahwv, const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the simulation-space derivative of the adjoint of the constraint simulation-space Jacobian at ...
Ptr< DynamicConstraint< Real > > con_
Ptr< std::vector< TimeStamp< Real >>> TimeStampsPtr
virtual void solve(Vector< Real > &c, Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Given , solve for .
Evaluates ROL::DynamicConstraint over a sequential set of time intervals.
Defines the constraint operator interface for simulation-based optimization.
const TimeStamp< Real > & ts(size_type i) const
virtual void applyInverseJacobian_1(Vector< Real > &ijv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, Real &tol) override
Apply the inverse partial constraint Jacobian at , , to the vector .