ROL
example_04.cpp
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 
49 #include "ROL_Algorithm.hpp"
50 #include "ROL_CompositeStepSQP.hpp"
51 #include "ROL_TrustRegionStep.hpp"
52 #include "ROL_StatusTest.hpp"
53 #include "ROL_Types.hpp"
54 
55 #include "ROL_StdVector.hpp"
56 #include "ROL_Vector_SimOpt.hpp"
58 #include "ROL_Objective_SimOpt.hpp"
60 
61 #include "Teuchos_oblackholestream.hpp"
62 #include "Teuchos_GlobalMPISession.hpp"
63 #include "Teuchos_XMLParameterListHelpers.hpp"
64 #include "Teuchos_LAPACK.hpp"
65 
66 #include <iostream>
67 #include <algorithm>
68 #include <ctime>
69 
70 template<class Real>
72 private:
73  unsigned nx_;
74  unsigned nt_;
75 
76  Real dx_;
77  Real T_;
78  Real dt_;
79 
80  Real nu_;
81  Real u0_;
82  Real u1_;
83  Real f_;
84  std::vector<Real> u_init_;
85 
86 private:
87  Real compute_norm(const std::vector<Real> &r) {
88  return std::sqrt(dot(r,r));
89  }
90 
91  Real dot(const std::vector<Real> &x, const std::vector<Real> &y) {
92  Real ip = 0.0;
93  Real c = ((x.size()==nx_) ? 4.0 : 2.0);
94  for (unsigned i = 0; i < x.size(); i++) {
95  if ( i == 0 ) {
96  ip += dx_/6.0*(c*x[i] + x[i+1])*y[i];
97  }
98  else if ( i == x.size()-1 ) {
99  ip += dx_/6.0*(x[i-1] + c*x[i])*y[i];
100  }
101  else {
102  ip += dx_/6.0*(x[i-1] + 4.0*x[i] + x[i+1])*y[i];
103  }
104  }
105  return ip;
106  }
107 
108  void update(std::vector<Real> &u, const std::vector<Real> &s, const Real alpha=1.0) {
109  for (unsigned i = 0; i < u.size(); i++) {
110  u[i] += alpha*s[i];
111  }
112  }
113 
114  void scale(std::vector<Real> &u, const Real alpha=0.0) {
115  for (unsigned i = 0; i < u.size(); i++) {
116  u[i] *= alpha;
117  }
118  }
119 
120  void compute_residual(std::vector<Real> &r, const std::vector<Real> &uold, const std::vector<Real> &zold,
121  const std::vector<Real> &unew, const std::vector<Real> &znew) {
122  r.clear();
123  r.resize(nx_,0.0);
124  for (unsigned n = 0; n < nx_; n++) {
125  // Contribution from mass & stiffness term at time step t and t-1
126  r[n] += (4.0*dx_/6.0 + 0.5*dt_*2.0*nu_/dx_)*unew[n];
127  r[n] += (-4.0*dx_/6.0 + 0.5*dt_*2.0*nu_/dx_)*uold[n];
128  if ( n > 0 ) {
129  r[n] += (dx_/6.0 - 0.5*dt_*nu_/dx_)*unew[n-1];
130  r[n] -= (dx_/6.0 + 0.5*dt_*nu_/dx_)*uold[n-1];
131  }
132  if ( n < nx_-1 ) {
133  r[n] += (dx_/6.0 - 0.5*dt_*nu_/dx_)*unew[n+1];
134  r[n] -= (dx_/6.0 + 0.5*dt_*nu_/dx_)*uold[n+1];
135  }
136  // Contribution from nonlinear term
137  if ( n > 0 ) {
138  r[n] -= 0.5*dt_*unew[n-1]*(unew[n-1]+unew[n])/6.0;
139  r[n] -= 0.5*dt_*uold[n-1]*(uold[n-1]+uold[n])/6.0;
140  }
141  if ( n < nx_-1 ){
142  r[n] += 0.5*dt_*unew[n+1]*(unew[n]+unew[n+1])/6.0;
143  r[n] += 0.5*dt_*uold[n+1]*(uold[n]+uold[n+1])/6.0;
144  }
145  // Contribution from control
146  r[n] -= 0.5*dt_*dx_/6.0*(znew[n]+4.0*znew[n+1]+znew[n+2]);
147  r[n] -= 0.5*dt_*dx_/6.0*(zold[n]+4.0*zold[n+1]+zold[n+2]);
148  // Contribution from right-hand side
149  r[n] -= dt_*dx_*f_;
150  }
151  // Contribution from Dirichlet boundary terms
152  r[0] -= dt_*(0.5*u0_*(unew[ 0] + uold[ 0])/6.0 + u0_*u0_/6.0 + nu_*u0_/dx_);
153  r[nx_-1] += dt_*(0.5*u1_*(unew[nx_-1] + uold[nx_-1])/6.0 + u1_*u1_/6.0 - nu_*u1_/dx_);
154  }
155 
156  void compute_pde_jacobian(std::vector<Real> &dl, std::vector<Real> &d, std::vector<Real> &du,
157  const std::vector<Real> &u) {
158  // Get Diagonal and Off-Diagonal Entries of linear PDE Jacobian
159  d.clear();
160  d.resize(nx_,4.0*dx_/6.0 + 0.5*dt_*nu_*2.0/dx_);
161  dl.clear();
162  dl.resize(nx_-1,dx_/6.0 - 0.5*dt_*nu_/dx_);
163  du.clear();
164  du.resize(nx_-1,dx_/6.0 - 0.5*dt_*nu_/dx_);
165  // Contribution from nonlinearity
166  for (unsigned n = 0; n < nx_; n++) {
167  if ( n < nx_-1 ) {
168  dl[n] += 0.5*dt_*(-2.0*u[n]-u[n+1])/6.0;
169  d[n] += 0.5*dt_*u[n+1]/6.0;
170  }
171  if ( n > 0 ) {
172  d[n] -= 0.5*dt_*u[n-1]/6.0;
173  du[n-1] += 0.5*dt_*(u[n-1]+2.0*u[n])/6.0;
174  }
175  }
176  // Contribution from Dirichlet boundary conditions
177  d[0] -= 0.5*dt_*u0_/6.0;
178  d[nx_-1] += 0.5*dt_*u1_/6.0;
179  }
180 
181  void apply_pde_jacobian_new(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &u,
182  bool adjoint = false) {
183  jv.clear();
184  jv.resize(nx_,0.0);
185  // Fill Jacobian times a vector
186  for (unsigned n = 0; n < nx_; n++) {
187  jv[n] = (4.0*dx_/6.0 + 0.5*dt_*nu_/dx_*2.0)*v[n]; // Mass & Stiffness
188  if ( n > 0 ) {
189  jv[n] += dx_/6.0*v[n-1]-0.5*dt_*nu_/dx_*v[n-1]; // Mass & Stiffness
190  if ( adjoint ) {
191  jv[n] -= 0.5*dt_*(u[n-1]/6.0*v[n]-(u[n-1]+2.0*u[n])/6.0*v[n-1]); // Nonlinearity
192  }
193  else {
194  jv[n] -= 0.5*dt_*(u[n-1]/6.0*v[n]+(u[n]+2.0*u[n-1])/6.0*v[n-1]); // Nonlinearity
195  }
196  }
197  if ( n < nx_-1 ) {
198  jv[n] += dx_/6.0*v[n+1]-0.5*dt_*nu_/dx_*v[n+1]; // Mass & Stiffness
199  if ( adjoint ) {
200  jv[n] += 0.5*dt_*(u[n+1]/6.0*v[n]-(u[n+1]+2.0*u[n])/6.0*v[n+1]); // Nonlinearity
201  }
202  else {
203  jv[n] += 0.5*dt_*(u[n+1]/6.0*v[n]+(u[n]+2.0*u[n+1])/6.0*v[n+1]); // Nonlinearity
204  }
205  }
206  }
207  jv[0] -= 0.5*dt_*u0_/6.0*v[0]; // Nonlinearity
208  jv[nx_-1] += 0.5*dt_*u1_/6.0*v[nx_-1]; // Nonlinearity
209  }
210 
211  void apply_pde_jacobian_old(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &u,
212  bool adjoint = false) {
213  jv.clear();
214  jv.resize(nx_,0.0);
215  // Fill Jacobian times a vector
216  for (unsigned n = 0; n < nx_; n++) {
217  jv[n] = (-4.0*dx_/6.0 + 0.5*dt_*nu_/dx_*2.0)*v[n]; // Mass & Stiffness
218  if ( n > 0 ) {
219  jv[n] += -dx_/6.0*v[n-1]-0.5*dt_*nu_/dx_*v[n-1]; // Mass & Stiffness
220  if ( adjoint ) {
221  jv[n] -= 0.5*dt_*(u[n-1]/6.0*v[n]-(u[n-1]+2.0*u[n])/6.0*v[n-1]); // Nonlinearity
222  }
223  else {
224  jv[n] -= 0.5*dt_*(u[n-1]/6.0*v[n]+(u[n]+2.0*u[n-1])/6.0*v[n-1]); // Nonlinearity
225  }
226  }
227  if ( n < nx_-1 ) {
228  jv[n] += -dx_/6.0*v[n+1]-0.5*dt_*nu_/dx_*v[n+1]; // Mass & Stiffness
229  if ( adjoint ) {
230  jv[n] += 0.5*dt_*(u[n+1]/6.0*v[n]-(u[n+1]+2.0*u[n])/6.0*v[n+1]); // Nonlinearity
231  }
232  else {
233  jv[n] += 0.5*dt_*(u[n+1]/6.0*v[n]+(u[n]+2.0*u[n+1])/6.0*v[n+1]); // Nonlinearity
234  }
235  }
236  }
237  jv[0] -= 0.5*dt_*u0_/6.0*v[0]; // Nonlinearity
238  jv[nx_-1] += 0.5*dt_*u1_/6.0*v[nx_-1]; // Nonlinearity
239  }
240 
241  void apply_pde_jacobian(std::vector<Real> &jv, const std::vector<Real> &vold, const std::vector<Real> &uold,
242  const std::vector<Real> &vnew, const std::vector<Real> unew, bool adjoint = false) {
243  jv.clear();
244  jv.resize(nx_,0.0);
245  // Fill Jacobian times a vector
246  for (unsigned n = 0; n < nx_; n++) {
247  jv[n] += (4.0*dx_/6.0+0.5*dt_*nu_/dx_*2.0)*vnew[n]; // Mass & Stiffness
248  jv[n] -= (4.0*dx_/6.0-0.5*dt_*nu_/dx_*2.0)*vold[n]; // Mass & Stiffness
249  if ( n > 0 ) {
250  jv[n] += dx_/6.0*vnew[n-1]-0.5*dt_*nu_/dx_*vnew[n-1]; // Mass & Stiffness
251  jv[n] -= dx_/6.0*vold[n-1]+0.5*dt_*nu_/dx_*vold[n-1]; // Mass & Stiffness
252  if ( adjoint ) {
253  jv[n] -= 0.5*dt_*(unew[n-1]/6.0*vnew[n]-(unew[n-1]+2.0*unew[n])/6.0*vnew[n-1]); // Nonlinearity
254  jv[n] -= 0.5*dt_*(uold[n-1]/6.0*vold[n]-(uold[n-1]+2.0*uold[n])/6.0*vold[n-1]); // Nonlinearity
255  }
256  else {
257  jv[n] -= 0.5*dt_*(unew[n-1]/6.0*vnew[n]+(unew[n]+2.0*unew[n-1])/6.0*vnew[n-1]); // Nonlinearity
258  jv[n] -= 0.5*dt_*(uold[n-1]/6.0*vold[n]+(uold[n]+2.0*uold[n-1])/6.0*vold[n-1]); // Nonlinearity
259  }
260  }
261  if ( n < nx_-1 ) {
262  jv[n] += dx_/6.0*vnew[n+1]-0.5*dt_*nu_/dx_*vnew[n+1]; // Mass & Stiffness
263  jv[n] -= dx_/6.0*vold[n+1]+0.5*dt_*nu_/dx_*vold[n+1]; // Mass & Stiffness
264  if ( adjoint ) {
265  jv[n] += 0.5*dt_*(unew[n+1]/6.0*vnew[n]-(unew[n+1]+2.0*unew[n])/6.0*vnew[n+1]); // Nonlinearity
266  jv[n] += 0.5*dt_*(uold[n+1]/6.0*vold[n]-(uold[n+1]+2.0*uold[n])/6.0*vold[n+1]); // Nonlinearity
267  }
268  else {
269  jv[n] += 0.5*dt_*(unew[n+1]/6.0*vnew[n]+(unew[n]+2.0*unew[n+1])/6.0*vnew[n+1]); // Nonlinearity
270  jv[n] += 0.5*dt_*(uold[n+1]/6.0*vold[n]+(uold[n]+2.0*uold[n+1])/6.0*vold[n+1]); // Nonlinearity
271  }
272  }
273  }
274  jv[0] -= 0.5*dt_*u0_/6.0*vnew[0]; // Nonlinearity
275  jv[0] -= 0.5*dt_*u0_/6.0*vold[0]; // Nonlinearity
276  jv[nx_-1] += 0.5*dt_*u1_/6.0*vnew[nx_-1]; // Nonlinearity
277  jv[nx_-1] += 0.5*dt_*u1_/6.0*vold[nx_-1]; // Nonlinearity
278  }
279 
280  void apply_pde_hessian(std::vector<Real> &hv, const std::vector<Real> &wold, const std::vector<Real> &vold,
281  const std::vector<Real> &wnew, const std::vector<Real> &vnew) {
282  hv.clear();
283  hv.resize(nx_,0.0);
284  for (unsigned n = 0; n < nx_; n++) {
285  if ( n > 0 ) {
286  hv[n] += 0.5*dt_*((wnew[n-1]*(vnew[n-1]+2.0*vnew[n]) - wnew[n]*vnew[n-1])/6.0);
287  hv[n] += 0.5*dt_*((wold[n-1]*(vold[n-1]+2.0*vold[n]) - wold[n]*vold[n-1])/6.0);
288  }
289  if ( n < nx_-1 ){
290  hv[n] += 0.5*dt_*((wnew[n]*vnew[n+1] - wnew[n+1]*(2.0*vnew[n]+vnew[n+1]))/6.0);
291  hv[n] += 0.5*dt_*((wold[n]*vold[n+1] - wold[n+1]*(2.0*vold[n]+vold[n+1]))/6.0);
292  }
293  }
294  }
295 
296  void apply_control_jacobian(std::vector<Real> &jv, const std::vector<Real> &v, bool adjoint = false) {
297  jv.clear();
298  unsigned dim = ((adjoint == true) ? nx_+2 : nx_);
299  jv.resize(dim,0.0);
300  for (unsigned n = 0; n < dim; n++) {
301  if ( adjoint ) {
302  if ( n == 0 ) {
303  jv[n] = -0.5*dt_*dx_/6.0*v[n];
304  }
305  else if ( n == 1 ) {
306  jv[n] = -0.5*dt_*dx_/6.0*(4.0*v[n-1]+v[n]);
307  }
308  else if ( n == nx_ ) {
309  jv[n] = -0.5*dt_*dx_/6.0*(4.0*v[n-1]+v[n-2]);
310  }
311  else if ( n == nx_+1 ) {
312  jv[n] = -0.5*dt_*dx_/6.0*v[n-2];
313  }
314  else {
315  jv[n] = -0.5*dt_*dx_/6.0*(v[n-2]+4.0*v[n-1]+v[n]);
316  }
317  }
318  else {
319  jv[n] -= 0.5*dt_*dx_/6.0*(v[n]+4.0*v[n+1]+v[n+2]);
320  }
321  }
322  }
323 
324  void run_newton(std::vector<Real> &u, const std::vector<Real> &znew,
325  const std::vector<Real> &uold, const std::vector<Real> &zold) {
326  u.clear();
327  u.resize(nx_,0.0);
328  // Compute residual and residual norm
329  std::vector<Real> r(nx_,0.0);
330  compute_residual(r,uold,zold,u,znew);
331  Real rnorm = compute_norm(r);
332  // Define tolerances
333  Real rtol = 1.e2*ROL::ROL_EPSILON;
334  unsigned maxit = 500;
335  // Initialize Jacobian storage
336  std::vector<Real> d(nx_,0.0);
337  std::vector<Real> dl(nx_-1,0.0);
338  std::vector<Real> du(nx_-1,0.0);
339  // Iterate Newton's method
340  Real alpha = 1.0, tmp = 0.0;
341  std::vector<Real> s(nx_,0.0);
342  std::vector<Real> utmp(nx_,0.0);
343  for (unsigned i = 0; i < maxit; i++) {
344  //std::cout << i << " " << rnorm << "\n";
345  // Get Jacobian
346  compute_pde_jacobian(dl,d,du,u);
347  // Solve Newton system
348  linear_solve(s,dl,d,du,r);
349  // Perform line search
350  tmp = rnorm;
351  alpha = 1.0;
352  utmp.assign(u.begin(),u.end());
353  update(utmp,s,-alpha);
354  compute_residual(r,uold,zold,utmp,znew);
355  rnorm = compute_norm(r);
356  while ( rnorm > (1.0-1.e-4*alpha)*tmp && alpha > std::sqrt(ROL::ROL_EPSILON) ) {
357  alpha *= 0.5;
358  utmp.assign(u.begin(),u.end());
359  update(utmp,s,-alpha);
360  compute_residual(r,uold,zold,utmp,znew);
361  rnorm = compute_norm(r);
362  }
363  // Update iterate
364  u.assign(utmp.begin(),utmp.end());
365  if ( rnorm < rtol ) {
366  break;
367  }
368  }
369  }
370 
371  void linear_solve(std::vector<Real> &u,
372  const std::vector<Real> &dl, const std::vector<Real> &d, const std::vector<Real> &du,
373  const std::vector<Real> &r, const bool transpose = false) {
374  bool useLAPACK = false;
375  if ( useLAPACK ) { // DIRECT SOLVE: USE LAPACK
376  u.assign(r.begin(),r.end());
377  // Store matrix diagonal & off-diagonals.
378  std::vector<Real> Dl(dl);
379  std::vector<Real> Du(du);
380  std::vector<Real> D(d);
381  // Perform LDL factorization
382  Teuchos::LAPACK<int,Real> lp;
383  std::vector<Real> Du2(nx_-2,0.0);
384  std::vector<int> ipiv(nx_,0);
385  int info;
386  int ldb = nx_;
387  int nhrs = 1;
388  lp.GTTRF(nx_,&Dl[0],&D[0],&Du[0],&Du2[0],&ipiv[0],&info);
389  char trans = ((transpose == true) ? 'T' : 'N');
390  lp.GTTRS(trans,nx_,nhrs,&Dl[0],&D[0],&Du[0],&Du2[0],&ipiv[0],&u[0],ldb,&info);
391  }
392  else { // ITERATIVE SOLVE: USE GAUSS-SEIDEL
393  u.clear();
394  u.resize(nx_,0.0);
395  unsigned maxit = 100;
396  Real rtol = std::min(1.e-12,1.e-4*std::sqrt(dot(r,r)));
397  Real resid = 0.0;
398  Real rnorm = 10.0*rtol;
399  for (unsigned i = 0; i < maxit; i++) {
400  for (unsigned n = 0; n < nx_; n++) {
401  u[n] = r[n]/d[n];
402  if ( n < nx_-1 ) {
403  u[n] -= ((transpose == false) ? du[n] : dl[n])*u[n+1]/d[n];
404  }
405  if ( n > 0 ) {
406  u[n] -= ((transpose == false) ? dl[n-1] : du[n-1])*u[n-1]/d[n];
407  }
408  }
409  // Compute Residual
410  rnorm = 0.0;
411  for (unsigned n = 0; n < nx_; n++) {
412  resid = r[n] - d[n]*u[n];
413  if ( n < nx_-1 ) {
414  resid -= ((transpose == false) ? du[n] : dl[n])*u[n+1];
415  }
416  if ( n > 0 ) {
417  resid -= ((transpose == false) ? dl[n-1] : du[n-1])*u[n-1];
418  }
419  rnorm += resid*resid;
420  }
421  rnorm = std::sqrt(rnorm);
422  if ( rnorm < rtol ) {
423  //std::cout << "\ni = " << i+1 << " rnorm = " << rnorm << "\n";
424  break;
425  }
426  }
427  }
428  }
429 
430 public:
431 
432  EqualityConstraint_BurgersControl(int nx = 128, int nt = 100, Real T = 1,
433  Real nu = 1.e-2, Real u0 = 0.0, Real u1 = 0.0, Real f = 0.0)
434  : nx_((unsigned)nx), nt_((unsigned)nt), T_(T), nu_(nu), u0_(u0), u1_(u1), f_(f) {
435  dx_ = 1.0/((Real)nx+1.0);
436  dt_ = T/((Real)nt);
437  u_init_.clear();
438  u_init_.resize(nx_,0.0);
439  Real x = 0.0;
440  for (unsigned n = 0; n < nx_; n++) {
441  x = (Real)(n+1)*dx_;
442  u_init_[n] = ((x <= 0.5) ? 1.0 : 0.0);
443  }
444  }
445 
446  void value(ROL::Vector<Real> &c, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
447  Teuchos::RCP<std::vector<Real> > cp =
448  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(c)).getVector());
449  Teuchos::RCP<const std::vector<Real> > up =
450  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
451  Teuchos::RCP<const std::vector<Real> > zp =
452  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
453  // Initialize storage
454  std::vector<Real> C(nx_,0.0);
455  std::vector<Real> uold(u_init_);
456  std::vector<Real> unew(u_init_);
457  std::vector<Real> zold(nx_+2,0.0);
458  std::vector<Real> znew(nx_+2,0.0);
459  // Copy initial control
460  for (unsigned n = 0; n < nx_+2; n++) {
461  zold[n] = (*zp)[n];
462  }
463  // Evaluate residual
464  for (unsigned t = 0; t < nt_; t++) {
465  // Copy current state at time step t
466  for (unsigned n = 0; n < nx_; n++) {
467  unew[n] = (*up)[t*nx_+n];
468  }
469  // Copy current control at time step t
470  for (unsigned n = 0; n < nx_+2; n++) {
471  znew[n] = (*zp)[(t+1)*(nx_+2)+n];
472  }
473  // Compute residual at time step t
474  compute_residual(C,uold,zold,unew,znew);
475  // Store residual at time step t
476  for (unsigned n = 0; n < nx_; n++) {
477  (*cp)[t*nx_+n] = C[n];
478  }
479  // Copy previous state and control at time step t+1
480  uold.assign(unew.begin(),unew.end());
481  zold.assign(znew.begin(),znew.end());
482  }
483  }
484 
485  void solve(ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
486  Teuchos::RCP<std::vector<Real> > up =
487  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(u)).getVector());
488  up->assign(up->size(),z.norm()/up->size());
489  Teuchos::RCP<const std::vector<Real> > zp =
490  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
491  // Initialize storage
492  std::vector<Real> uold(u_init_);
493  std::vector<Real> unew(u_init_);
494  std::vector<Real> zold(nx_+2,0.0);
495  std::vector<Real> znew(nx_+2,0.0);
496  // Copy initial control
497  for (unsigned n = 0; n < nx_+2; n++) {
498  zold[n] = (*zp)[n];
499  }
500  // Time step using the trapezoidal rule
501  for (unsigned t = 0; t < nt_; t++) {
502  // Copy current control at time step t
503  for (unsigned n = 0; n < nx_+2; n++) {
504  znew[n] = (*zp)[(t+1)*(nx_+2)+n];
505  }
506  // Solve nonlinear system at time step t
507  run_newton(unew,znew,uold,zold);
508  // store state at time step t
509  for (unsigned n = 0; n < nx_; n++) {
510  (*up)[t*nx_+n] = unew[n];
511  }
512  // Copy previous state and control at time step t+1
513  uold.assign(unew.begin(),unew.end());
514  zold.assign(znew.begin(),znew.end());
515  }
516  }
517 
519  const ROL::Vector<Real> &z, Real &tol) {
520  Teuchos::RCP<std::vector<Real> > jvp =
521  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(jv)).getVector());
522  Teuchos::RCP<const std::vector<Real> > vp =
523  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
524  Teuchos::RCP<const std::vector<Real> > up =
525  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
526  std::vector<Real> J(nx_,0.0);
527  std::vector<Real> vold(nx_,0.0);
528  std::vector<Real> vnew(nx_,0.0);
529  std::vector<Real> uold(nx_,0.0);
530  std::vector<Real> unew(nx_,0.0);
531  for (unsigned t = 0; t < nt_; t++) {
532  for (unsigned n = 0; n < nx_; n++) {
533  unew[n] = (*up)[t*nx_+n];
534  vnew[n] = (*vp)[t*nx_+n];
535  }
536  apply_pde_jacobian(J,vold,uold,vnew,unew);
537  for (unsigned n = 0; n < nx_; n++) {
538  (*jvp)[t*nx_+n] = J[n];
539  }
540  vold.assign(vnew.begin(),vnew.end());
541  uold.assign(unew.begin(),unew.end());
542  }
543  }
544 
546  const ROL::Vector<Real> &z, Real &tol) {
547  Teuchos::RCP<std::vector<Real> > jvp =
548  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(jv)).getVector());
549  Teuchos::RCP<const std::vector<Real> > vp =
550  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
551  Teuchos::RCP<const std::vector<Real> > zp =
552  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
553  std::vector<Real> vnew(nx_+2,0.0);
554  std::vector<Real> vold(nx_+2,0.0);
555  std::vector<Real> jnew(nx_,0.0);
556  std::vector<Real> jold(nx_,0.0);
557  for (unsigned n = 0; n < nx_+2; n++) {
558  vold[n] = (*vp)[n];
559  }
560  apply_control_jacobian(jold,vold);
561  for (unsigned t = 0; t < nt_; t++) {
562  for (unsigned n = 0; n < nx_+2; n++) {
563  vnew[n] = (*vp)[(t+1)*(nx_+2)+n];
564  }
565  apply_control_jacobian(jnew,vnew);
566  for (unsigned n = 0; n < nx_; n++) {
567  // Contribution from control
568  (*jvp)[t*nx_+n] = jnew[n] + jold[n];
569  }
570  jold.assign(jnew.begin(),jnew.end());
571  }
572  }
573 
575  const ROL::Vector<Real> &z, Real &tol) {
576  Teuchos::RCP<std::vector<Real> > ijvp =
577  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(ijv)).getVector());
578  Teuchos::RCP<const std::vector<Real> > vp =
579  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
580  Teuchos::RCP<const std::vector<Real> > up =
581  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
582  std::vector<Real> J(nx_,0.0);
583  std::vector<Real> r(nx_,0.0);
584  std::vector<Real> s(nx_,0.0);
585  std::vector<Real> uold(nx_,0.0);
586  std::vector<Real> unew(nx_,0.0);
587  std::vector<Real> d(nx_,0.0);
588  std::vector<Real> dl(nx_-1,0.0);
589  std::vector<Real> du(nx_-1,0.0);
590  for (unsigned t = 0; t < nt_; t++) {
591  // Build rhs.
592  for (unsigned n = 0; n < nx_; n++) {
593  r[n] = (*vp)[t*nx_+n];
594  unew[n] = (*up)[t*nx_+n];
595  }
596  apply_pde_jacobian_old(J,s,uold);
597  update(r,J,-1.0);
598  // Build Jacobian.
599  compute_pde_jacobian(dl,d,du,unew);
600  // Solve linear system.
601  linear_solve(s,dl,d,du,r);
602  // Copy solution.
603  for (unsigned n = 0; n < nx_; n++) {
604  (*ijvp)[t*nx_+n] = s[n];
605  }
606  uold.assign(unew.begin(),unew.end());
607  }
608  }
609 
611  const ROL::Vector<Real> &z, Real &tol) {
612  Teuchos::RCP<std::vector<Real> > jvp =
613  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(ajv)).getVector());
614  Teuchos::RCP<const std::vector<Real> > vp =
615  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
616  Teuchos::RCP<const std::vector<Real> > up =
617  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
618  std::vector<Real> J(nx_,0.0);
619  std::vector<Real> vold(nx_,0.0);
620  std::vector<Real> vnew(nx_,0.0);
621  std::vector<Real> unew(nx_,0.0);
622  for (unsigned t = nt_; t > 0; t--) {
623  for (unsigned n = 0; n < nx_; n++) {
624  unew[n] = (*up)[(t-1)*nx_+n];
625  vnew[n] = (*vp)[(t-1)*nx_+n];
626  }
627  apply_pde_jacobian(J,vold,unew,vnew,unew,true);
628  for (unsigned n = 0; n < nx_; n++) {
629  (*jvp)[(t-1)*nx_+n] = J[n];
630  }
631  vold.assign(vnew.begin(),vnew.end());
632  }
633  }
634 
636  const ROL::Vector<Real> &z, Real &tol) {
637  Teuchos::RCP<std::vector<Real> > jvp =
638  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(jv)).getVector());
639  Teuchos::RCP<const std::vector<Real> > vp =
640  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
641  Teuchos::RCP<const std::vector<Real> > zp =
642  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
643  std::vector<Real> vnew(nx_,0.0);
644  std::vector<Real> vold(nx_,0.0);
645  std::vector<Real> jnew(nx_+2,0.0);
646  std::vector<Real> jold(nx_+2,0.0);
647  for (unsigned t = nt_+1; t > 0; t--) {
648  for (unsigned n = 0; n < nx_; n++) {
649  if ( t > 1 ) {
650  vnew[n] = (*vp)[(t-2)*nx_+n];
651  }
652  else {
653  vnew[n] = 0.0;
654  }
655  }
656  apply_control_jacobian(jnew,vnew,true);
657  for (unsigned n = 0; n < nx_+2; n++) {
658  // Contribution from control
659  (*jvp)[(t-1)*(nx_+2)+n] = jnew[n] + jold[n];
660  }
661  jold.assign(jnew.begin(),jnew.end());
662  }
663  }
664 
666  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
667  Teuchos::RCP<std::vector<Real> > ijvp =
668  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(ijv)).getVector());
669  Teuchos::RCP<const std::vector<Real> > vp =
670  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
671  Teuchos::RCP<const std::vector<Real> > up =
672  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
673  std::vector<Real> J(nx_,0.0);
674  std::vector<Real> r(nx_,0.0);
675  std::vector<Real> s(nx_,0.0);
676  std::vector<Real> unew(nx_,0.0);
677  std::vector<Real> d(nx_,0.0);
678  std::vector<Real> dl(nx_-1,0.0);
679  std::vector<Real> du(nx_-1,0.0);
680  for (unsigned t = nt_; t > 0; t--) {
681  // Build rhs.
682  for (unsigned n = 0; n < nx_; n++) {
683  r[n] = (*vp)[(t-1)*nx_+n];
684  unew[n] = (*up)[(t-1)*nx_+n];
685  }
686  apply_pde_jacobian_old(J,s,unew,true);
687  update(r,J,-1.0);
688  // Build Jacobian.
689  compute_pde_jacobian(dl,d,du,unew);
690  // Solve linear system.
691  linear_solve(s,dl,d,du,r,true);
692  // Copy solution.
693  for (unsigned n = 0; n < nx_; n++) {
694  (*ijvp)[(t-1)*nx_+n] = s[n];
695  }
696  }
697  }
698 
700  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
701  Teuchos::RCP<std::vector<Real> > hwvp =
702  Teuchos::rcp_const_cast<std::vector<Real> >((Teuchos::dyn_cast<ROL::StdVector<Real> >(hwv)).getVector());
703  Teuchos::RCP<const std::vector<Real> > wp =
704  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(w))).getVector();
705  Teuchos::RCP<const std::vector<Real> > vp =
706  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
707  std::vector<Real> snew(nx_,0.0);
708  std::vector<Real> wnew(nx_,0.0);
709  std::vector<Real> wold(nx_,0.0);
710  std::vector<Real> vnew(nx_,0.0);
711  for (unsigned t = nt_; t > 0; t--) {
712  for (unsigned n = 0; n < nx_; n++) {
713  vnew[n] = (*vp)[(t-1)*nx_+n];
714  wnew[n] = (*wp)[(t-1)*nx_+n];
715  }
716  apply_pde_hessian(snew,wold,vnew,wnew,vnew);
717  for (unsigned n = 0; n < nx_; n++) {
718  (*hwvp)[(t-1)*nx_+n] = snew[n];
719  }
720  wold.assign(wnew.begin(),wnew.end());
721  }
722  }
723 
725  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
726  ahwv.zero();
727  }
729  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
730  ahwv.zero();
731  }
733  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
734  ahwv.zero();
735  }
736 };
737 
738 template<class Real>
739 class Objective_BurgersControl : public ROL::Objective_SimOpt<Real> {
740 private:
741  Real alpha_; // Penalty Parameter
742 
743  unsigned nx_; // Number of interior nodes
744  Real dx_; // Mesh spacing (i.e. 1/(nx+1))
745  unsigned nt_; // Number of time steps
746  Real dt_; // Time step size
747  Real T_; // Final time
748 
749 /***************************************************************/
750 /********** BEGIN PRIVATE MEMBER FUNCTION DECLARATION **********/
751 /***************************************************************/
752  Real evaluate_target(Real x) {
753  Real val = 0.0;
754  int example = 1;
755  switch (example) {
756  case 1: val = ((x<=0.5) ? 1.0 : 0.0); break;
757  case 2: val = 1.0; break;
758  case 3: val = std::abs(std::sin(8.0*M_PI*x)); break;
759  case 4: val = std::exp(-0.5*(x-0.5)*(x-0.5)); break;
760  }
761  return val;
762  }
763 
764  Real dot(const std::vector<Real> &x, const std::vector<Real> &y) {
765  Real ip = 0.0;
766  Real c = ((x.size()==nx_) ? 4.0 : 2.0);
767  for (unsigned i=0; i<x.size(); i++) {
768  if ( i == 0 ) {
769  ip += dx_/6.0*(c*x[i] + x[i+1])*y[i];
770  }
771  else if ( i == x.size()-1 ) {
772  ip += dx_/6.0*(x[i-1] + c*x[i])*y[i];
773  }
774  else {
775  ip += dx_/6.0*(x[i-1] + 4.0*x[i] + x[i+1])*y[i];
776  }
777  }
778  return ip;
779  }
780 
781  void apply_mass(std::vector<Real> &Mu, const std::vector<Real> &u ) {
782  Mu.resize(u.size(),0.0);
783  Real c = ((u.size()==nx_) ? 4.0 : 2.0);
784  for (unsigned i=0; i<u.size(); i++) {
785  if ( i == 0 ) {
786  Mu[i] = dx_/6.0*(c*u[i] + u[i+1]);
787  }
788  else if ( i == u.size()-1 ) {
789  Mu[i] = dx_/6.0*(u[i-1] + c*u[i]);
790  }
791  else {
792  Mu[i] = dx_/6.0*(u[i-1] + 4.0*u[i] + u[i+1]);
793  }
794  }
795  }
796 /*************************************************************/
797 /********** END PRIVATE MEMBER FUNCTION DECLARATION **********/
798 /*************************************************************/
799 
800 public:
801 
802  Objective_BurgersControl(Real alpha = 1.e-4, int nx = 128, int nt = 100, Real T = 1.0)
803  : alpha_(alpha), nx_((unsigned)nx), nt_((unsigned)nt), T_(T) {
804  dx_ = 1.0/((Real)nx+1.0);
805  dt_ = T/((Real)nt);
806  }
807 
808  Real value( const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
809  Teuchos::RCP<const std::vector<Real> > up =
810  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
811  Teuchos::RCP<const std::vector<Real> > zp =
812  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
813  // COMPUTE RESIDUAL
814  std::vector<Real> U(nx_,0.0);
815  std::vector<Real> Z(nx_+2,0.0);
816  for (unsigned n = 0; n < nx_+2; n++) {
817  Z[n] = (*zp)[n];
818  }
819  Real ss = 0.5*dt_;
820  Real val = 0.5*ss*alpha_*dot(Z,Z);
821  for (unsigned t = 0; t < nt_; t++) {
822  ss = ((t < nt_-1) ? dt_ : 0.5*dt_);
823  for (unsigned n = 0; n < nx_; n++) {
824  U[n] = (*up)[t*nx_+n]-evaluate_target((Real)(n+1)*dx_);
825  }
826  val += 0.5*ss*dot(U,U);
827  for (unsigned n = 0; n < nx_+2; n++) {
828  Z[n] = (*zp)[(t+1)*(nx_+2)+n];
829  }
830  val += 0.5*ss*alpha_*dot(Z,Z);
831  }
832  return val;
833  }
834 
835  void gradient_1( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
836  Teuchos::RCP<std::vector<Real> > gp = Teuchos::rcp_const_cast<std::vector<Real> >(
837  (Teuchos::dyn_cast<const ROL::StdVector<Real> >(g)).getVector());
838  Teuchos::RCP<const std::vector<Real> > up =
839  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(u))).getVector();
840  // COMPUTE GRADIENT WRT U
841  std::vector<Real> U(nx_,0.0);
842  std::vector<Real> M(nx_,0.0);
843  Real ss = dt_;
844  for (unsigned t = 0; t < nt_; t++) {
845  ss = ((t < nt_-1) ? dt_ : 0.5*dt_);
846  for (unsigned n = 0; n < nx_; n++) {
847  U[n] = (*up)[t*nx_+n]-evaluate_target((Real)(n+1)*dx_);
848  }
849  apply_mass(M,U);
850  for (unsigned n = 0; n < nx_; n++) {
851  (*gp)[t*nx_+n] = ss*M[n];
852  }
853  }
854  }
855 
856  void gradient_2( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
857  Teuchos::RCP<std::vector<Real> > gp = Teuchos::rcp_const_cast<std::vector<Real> >(
858  (Teuchos::dyn_cast<const ROL::StdVector<Real> >(g)).getVector());
859  Teuchos::RCP<const std::vector<Real> > zp =
860  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(z))).getVector();
861  // COMPUTE GRADIENT WRT Z
862  std::vector<Real> Z(nx_+2,0.0);
863  std::vector<Real> M(nx_+2,0.0);
864  Real ss = dt_;
865  for (unsigned t = 0; t < nt_+1; t++) {
866  ss = ((t < nt_ && t > 0) ? dt_ : 0.5*dt_);
867  for (unsigned n = 0; n < nx_+2; n++) {
868  Z[n] = (*zp)[t*(nx_+2)+n];
869  }
870  apply_mass(M,Z);
871  for (unsigned n = 0; n < nx_+2; n++) {
872  (*gp)[t*(nx_+2)+n] = ss*alpha_*M[n];
873  }
874  }
875  }
876 
878  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
879  Teuchos::RCP<std::vector<Real> > hvp = Teuchos::rcp_const_cast<std::vector<Real> >(
880  (Teuchos::dyn_cast<const ROL::StdVector<Real> >(hv)).getVector());
881  Teuchos::RCP<const std::vector<Real> > vp =
882  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
883  // COMPUTE GRADIENT WRT U
884  std::vector<Real> V(nx_,0.0);
885  std::vector<Real> M(nx_,0.0);
886  Real ss = 0.5*dt_;
887  for (unsigned t = 0; t < nt_; t++) {
888  ss = ((t < nt_-1) ? dt_ : 0.5*dt_);
889  for (unsigned n = 0; n < nx_; n++) {
890  V[n] = (*vp)[t*nx_+n];
891  }
892  apply_mass(M,V);
893  for (unsigned n = 0; n < nx_; n++) {
894  (*hvp)[t*nx_+n] = ss*M[n];
895  }
896  }
897  }
898 
900  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
901  hv.zero();
902  }
903 
905  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
906  hv.zero();
907  }
908 
910  const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
911  Teuchos::RCP<std::vector<Real> > hvp = Teuchos::rcp_const_cast<std::vector<Real> >(
912  (Teuchos::dyn_cast<const ROL::StdVector<Real> >(hv)).getVector());
913  Teuchos::RCP<const std::vector<Real> > vp =
914  (Teuchos::dyn_cast<ROL::StdVector<Real> >(const_cast<ROL::Vector<Real> &>(v))).getVector();
915  // COMPUTE GRADIENT WRT Z
916  std::vector<Real> V(nx_+2,0.0);
917  std::vector<Real> M(nx_+2,0.0);
918  Real ss = 0.0;
919  for (unsigned t = 0; t < nt_+1; t++) {
920  ss = ((t < nt_ && t > 0) ? dt_ : 0.5*dt_);
921  for (unsigned n = 0; n < nx_+2; n++) {
922  V[n] = (*vp)[t*(nx_+2)+n];
923  }
924  apply_mass(M,V);
925  for (unsigned n = 0; n < nx_+2; n++) {
926  (*hvp)[t*(nx_+2)+n] = ss*alpha_*M[n];
927  }
928  }
929  }
930 };
931 
932 typedef double RealT;
933 
934 int main(int argc, char *argv[]) {
935 
936  Teuchos::GlobalMPISession mpiSession(&argc, &argv);
937 
938  // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided.
939  int iprint = argc - 1;
940  Teuchos::RCP<std::ostream> outStream;
941  Teuchos::oblackholestream bhs; // outputs nothing
942  if (iprint > 0)
943  outStream = Teuchos::rcp(&std::cout, false);
944  else
945  outStream = Teuchos::rcp(&bhs, false);
946 
947  int errorFlag = 0;
948 
949  // *** Example body.
950 
951  try {
952  // Initialize full objective function.
953  int nx = 20; // Set spatial discretization.
954  int nt = 20; // Set temporal discretization.
955  RealT T = 1.0; // Set end time.
956  RealT alpha = 0.05; // Set penalty parameter.
957  RealT nu = 1.e-2; // Set viscosity parameter.
958  Objective_BurgersControl<RealT> obj(alpha,nx,nt,T);
959  // Initialize equality constraints
960  EqualityConstraint_BurgersControl<RealT> con(nx, nt, T, nu);
961  // Initialize iteration vectors.
962  Teuchos::RCP<std::vector<RealT> > z_rcp = Teuchos::rcp( new std::vector<RealT> ((nx+2)*(nt+1), 1.0) );
963  Teuchos::RCP<std::vector<RealT> > gz_rcp = Teuchos::rcp( new std::vector<RealT> ((nx+2)*(nt+1), 1.0) );
964  Teuchos::RCP<std::vector<RealT> > yz_rcp = Teuchos::rcp( new std::vector<RealT> ((nx+2)*(nt+1), 1.0) );
965  for (int i=0; i<(nx+2)*(nt+1); i++) {
966  (*z_rcp)[i] = (RealT)rand()/(RealT)RAND_MAX;
967  (*yz_rcp)[i] = (RealT)rand()/(RealT)RAND_MAX;
968  }
969  ROL::StdVector<RealT> z(z_rcp);
970  ROL::StdVector<RealT> gz(gz_rcp);
971  ROL::StdVector<RealT> yz(yz_rcp);
972  Teuchos::RCP<ROL::Vector<RealT> > zp = Teuchos::rcp(&z,false);
973  Teuchos::RCP<ROL::Vector<RealT> > gzp = Teuchos::rcp(&gz,false);
974  Teuchos::RCP<ROL::Vector<RealT> > yzp = Teuchos::rcp(&yz,false);
975 
976  Teuchos::RCP<std::vector<RealT> > u_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
977  Teuchos::RCP<std::vector<RealT> > gu_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
978  Teuchos::RCP<std::vector<RealT> > yu_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
979  for (int i=0; i<nx*nt; i++) {
980  (*u_rcp)[i] = (RealT)rand()/(RealT)RAND_MAX;
981  (*yu_rcp)[i] = (RealT)rand()/(RealT)RAND_MAX;
982  }
983  ROL::StdVector<RealT> u(u_rcp);
984  ROL::StdVector<RealT> gu(gu_rcp);
985  ROL::StdVector<RealT> yu(yu_rcp);
986  Teuchos::RCP<ROL::Vector<RealT> > up = Teuchos::rcp(&u,false);
987  Teuchos::RCP<ROL::Vector<RealT> > gup = Teuchos::rcp(&gu,false);
988  Teuchos::RCP<ROL::Vector<RealT> > yup = Teuchos::rcp(&yu,false);
989 
990  Teuchos::RCP<std::vector<RealT> > c_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
991  Teuchos::RCP<std::vector<RealT> > l_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
992  ROL::StdVector<RealT> c(c_rcp);
993  ROL::StdVector<RealT> l(l_rcp);
994 
995  ROL::Vector_SimOpt<RealT> x(up,zp);
996  ROL::Vector_SimOpt<RealT> g(gup,gzp);
997  ROL::Vector_SimOpt<RealT> y(yup,yzp);
998  // Check derivatives.
999  obj.checkGradient(x,x,y,true,*outStream);
1000  obj.checkHessVec(x,x,y,true,*outStream);
1001  con.checkApplyJacobian(x,y,c,true,*outStream);
1002  con.checkApplyAdjointJacobian(x,yu,c,x,true,*outStream);
1003  con.checkApplyAdjointHessian(x,yu,y,x,true,*outStream);
1004  // Check consistency of Jacobians and adjoint Jacobians.
1005  con.checkAdjointConsistencyJacobian_1(c,yu,u,z,true,*outStream);
1006  con.checkAdjointConsistencyJacobian_2(c,yz,u,z,true,*outStream);
1007  // Check consistency of solves.
1008  con.checkSolve(u,z,c,true,*outStream);
1009  con.checkInverseJacobian_1(c,yu,u,z,true,*outStream);
1010  con.checkInverseAdjointJacobian_1(yu,c,u,z,true,*outStream);
1011 
1012  // Initialize reduced objective function.
1013  Teuchos::RCP<std::vector<RealT> > p_rcp = Teuchos::rcp( new std::vector<RealT> (nx*nt, 1.0) );
1014  ROL::StdVector<RealT> p(p_rcp);
1015  Teuchos::RCP<ROL::Vector<RealT> > pp = Teuchos::rcp(&p,false);
1016  Teuchos::RCP<ROL::Objective_SimOpt<RealT> > pobj = Teuchos::rcp(&obj,false);
1017  Teuchos::RCP<ROL::EqualityConstraint_SimOpt<RealT> > pcon = Teuchos::rcp(&con,false);
1018  ROL::Reduced_Objective_SimOpt<RealT> robj(pobj,pcon,up,pp);
1019  // Check derivatives.
1020  robj.checkGradient(z,z,yz,true,*outStream);
1021  robj.checkHessVec(z,z,yz,true,*outStream);
1022  // Optimization
1023  std::string filename = "input.xml";
1024  Teuchos::RCP<Teuchos::ParameterList> parlist_tr = Teuchos::rcp( new Teuchos::ParameterList() );
1025  Teuchos::updateParametersFromXmlFile( filename, Teuchos::Ptr<Teuchos::ParameterList>(&*parlist_tr) );
1026 
1027  // Trust Region Newton.
1028  RealT gtol = 1e-14; // norm of gradient tolerance
1029  RealT stol = 1e-16; // norm of step tolerance
1030  int maxit = 100; // maximum number of iterations
1031  ROL::StatusTest<RealT> status_tr(gtol, stol, maxit);
1032  ROL::TrustRegionStep<RealT> step_tr(*parlist_tr);
1033  ROL::DefaultAlgorithm<RealT> algo_tr(step_tr,status_tr,false);
1034  z.zero();
1035  std::clock_t timer_tr = std::clock();
1036  algo_tr.run(z,robj,true,*outStream);
1037  *outStream << "Trust-Region Newton required " << (std::clock()-timer_tr)/(RealT)CLOCKS_PER_SEC
1038  << " seconds.\n";
1039 
1040  // SQP.
1041  RealT ctol = 1.e-14;
1042  ROL::StatusTestSQP<RealT> status_sqp(gtol,ctol,stol,maxit);
1043  ROL::CompositeStepSQP<RealT> step_sqp(*parlist_tr);
1044  ROL::DefaultAlgorithm<RealT> algo_sqp(step_sqp,status_sqp,false);
1045  x.zero();
1046  std::clock_t timer_sqp = std::clock();
1047  algo_sqp.run(x,g,l,c,obj,con,true,*outStream);
1048  *outStream << "Composite-Step SQP required " << (std::clock()-timer_sqp)/(RealT)CLOCKS_PER_SEC
1049  << " seconds.\n";
1050 
1051  std::ofstream control;
1052  control.open("control.txt");
1053  for (int t = 0; t < nt+1; t++) {
1054  for (int n = 0; n < nx+2; n++) {
1055  control << (RealT)t/(RealT)nt << " "
1056  << (RealT)n/((RealT)(nx+1)) << " "
1057  << (*z_rcp)[t*(nx+2)+n] << "\n";
1058  }
1059  }
1060  control.close();
1061 
1062  std::ofstream state;
1063  state.open("state.txt");
1064  for (int t = 0; t < nt; t++) {
1065  for (int n = 0; n < nx; n++) {
1066  state << (RealT)(t+1)/(RealT)nt << " "
1067  << (RealT)(n+1)/((RealT)(nx+1)) << " "
1068  << (*u_rcp)[t*nx+n] << "\n";
1069  }
1070  }
1071  state.close();
1072  }
1073  catch (std::logic_error err) {
1074  *outStream << err.what() << "\n";
1075  errorFlag = -1000;
1076  }; // end try
1077 
1078  if (errorFlag != 0)
1079  std::cout << "End Result: TEST FAILED\n";
1080  else
1081  std::cout << "End Result: TEST PASSED\n";
1082 
1083  return 0;
1084 
1085 }
1086 
virtual Real checkInverseJacobian_1(const Vector< Real > &jv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, const bool printToStream=true, std::ostream &outStream=std::cout)
Provides the interface to evaluate simulation-based objective functions.
void run_newton(std::vector< Real > &u, const std::vector< Real > &znew, const std::vector< Real > &uold, const std::vector< Real > &zold)
Definition: example_04.cpp:324
void compute_pde_jacobian(std::vector< Real > &dl, std::vector< Real > &d, std::vector< Real > &du, const std::vector< Real > &u)
Definition: example_04.cpp:156
void applyAdjointHessian_21(ROL::Vector< Real > &ahwv, const ROL::Vector< Real > &w, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Hessian at , , to vector in direction ...
Definition: example_04.cpp:728
void linear_solve(std::vector< Real > &u, std::vector< Real > &dl, std::vector< Real > &d, std::vector< Real > &du, const std::vector< Real > &r, const bool transpose=false)
Real evaluate_target(Real x)
Definition: example_04.cpp:752
Defines the linear algebra or vector space interface for simulation-based optimization.
void applyAdjointHessian_22(ROL::Vector< Real > &ahwv, const ROL::Vector< Real > &w, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Hessian at , , to vector in direction ...
Definition: example_04.cpp:732
void applyInverseJacobian_1(ROL::Vector< Real > &ijv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the inverse partial constraint Jacobian at , , to the vector .
Definition: example_04.cpp:574
Real dot(const std::vector< Real > &x, const std::vector< Real > &y)
Contains definitions of custom data types in ROL.
virtual std::vector< std::vector< Real > > checkApplyAdjointJacobian(const Vector< Real > &x, const Vector< Real > &v, const Vector< Real > &c, const Vector< Real > &ajv, const bool printToStream=true, std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS)
Finite-difference check for the application of the adjoint of constraint Jacobian.
void compute_residual(std::vector< Real > &r, const std::vector< Real > &uold, const std::vector< Real > &zold, const std::vector< Real > &unew, const std::vector< Real > &znew)
Definition: example_04.cpp:120
Real compute_norm(const std::vector< Real > &r)
Definition: example_04.cpp:87
EqualityConstraint_BurgersControl(int nx=128, int nt=100, Real T=1, Real nu=1.e-2, Real u0=0.0, Real u1=0.0, Real f=0.0)
Definition: example_04.cpp:432
virtual void zero()
Set to zero vector.
Definition: ROL_Vector.hpp:155
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:72
void apply_control_jacobian(std::vector< Real > &jv, const std::vector< Real > &v, bool adjoint=false)
Definition: example_04.cpp:296
int main(int argc, char *argv[])
Definition: example_04.cpp:934
void compute_residual(std::vector< Real > &r, const std::vector< Real > &u, const std::vector< Real > &z)
void apply_pde_hessian(std::vector< Real > &hv, const std::vector< Real > &wold, const std::vector< Real > &vold, const std::vector< Real > &wnew, const std::vector< Real > &vnew)
Definition: example_04.cpp:280
Defines the equality constraint operator interface for simulation-based optimization.
virtual std::vector< std::vector< Real > > checkGradient(const Vector< Real > &x, const Vector< Real > &d, const bool printToStream=true, std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS, const int order=1)
Finite-difference gradient check.
void hessVec_22(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Definition: example_04.cpp:909
Real value(const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Compute value.
Definition: example_04.cpp:808
virtual std::vector< std::vector< Real > > checkApplyJacobian(const Vector< Real > &x, const Vector< Real > &v, const Vector< Real > &jv, const std::vector< Real > &steps, const bool printToStream=true, std::ostream &outStream=std::cout, const int order=1)
Finite-difference check for the constraint Jacobian application.
void gradient_1(ROL::Vector< Real > &g, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Compute gradient with respect to first component.
Definition: example_04.cpp:835
Provides the interface to evaluate simulation-based reduced objective functions.
void applyAdjointJacobian_1(ROL::Vector< Real > &ajv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Jacobian at , , to the vector . This is the primary inter...
Definition: example_04.cpp:610
void apply_pde_jacobian_new(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &u, bool adjoint=false)
Definition: example_04.cpp:181
void applyAdjointJacobian_2(ROL::Vector< Real > &jv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Jacobian at , , to vector . This is the primary interface...
Definition: example_04.cpp:635
Provides the std::vector implementation of the ROL::Vector interface.
void applyJacobian_1(ROL::Vector< Real > &jv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the partial constraint Jacobian at , , to the vector .
Definition: example_04.cpp:518
virtual Real checkSolve(const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, const ROL::Vector< Real > &c, const bool printToStream=true, std::ostream &outStream=std::cout)
virtual std::vector< std::string > run(Vector< Real > &x, Objective< Real > &obj, bool print=false, std::ostream &outStream=std::cout)
Run algorithm on unconstrained problems (Type-U). This is the primary Type-U interface.
Real dot(const std::vector< Real > &x, const std::vector< Real > &y)
Definition: example_04.cpp:764
Implements the computation of optimization steps with composite-step trust-region SQP methods...
void hessVec_21(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Definition: example_04.cpp:904
void hessVec_12(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Definition: example_04.cpp:899
Provides an interface to check status of optimization algorithms.
void gradient_2(ROL::Vector< Real > &g, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Compute gradient with respect to second component.
Definition: example_04.cpp:856
void solve(ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Given , solve for .
Definition: example_04.cpp:485
void scale(std::vector< Real > &u, const Real alpha=0.0)
Definition: example_04.cpp:114
Objective_BurgersControl(Real alpha=1.e-4, int nx=128, int nt=100, Real T=1.0)
Definition: example_04.cpp:802
void applyJacobian_2(ROL::Vector< Real > &jv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the partial constraint Jacobian at , , to the vector .
Definition: example_04.cpp:545
void hessVec_11(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply Hessian approximation to vector.
Definition: example_04.cpp:877
void value(ROL::Vector< Real > &c, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Evaluate the constraint operator at .
Definition: example_04.cpp:446
void applyInverseAdjointJacobian_1(ROL::Vector< Real > &ijv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the inverse of the adjoint of the partial constraint Jacobian at , , to the vector ...
Definition: example_04.cpp:665
void apply_mass(std::vector< Real > &Mu, const std::vector< Real > &u)
Definition: example_04.cpp:781
void linear_solve(std::vector< Real > &u, const std::vector< Real > &dl, const std::vector< Real > &d, const std::vector< Real > &du, const std::vector< Real > &r, const bool transpose=false)
Definition: example_04.cpp:371
virtual std::vector< std::vector< Real > > checkHessVec(const Vector< Real > &x, const Vector< Real > &v, const bool printToStream=true, std::ostream &outStream=std::cout, const int numSteps=ROL_NUM_CHECKDERIV_STEPS, const int order=1)
Finite-difference Hessian-applied-to-vector check.
void apply_pde_jacobian(std::vector< Real > &jv, const std::vector< Real > &vold, const std::vector< Real > &uold, const std::vector< Real > &vnew, const std::vector< Real > unew, bool adjoint=false)
Definition: example_04.cpp:241
virtual Real checkAdjointConsistencyJacobian_1(const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, const bool printToStream=true, std::ostream &outStream=std::cout)
Check the consistency of the Jacobian and its adjoint. This is the primary interface.
double RealT
virtual Real checkInverseAdjointJacobian_1(const Vector< Real > &jv, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, const bool printToStream=true, std::ostream &outStream=std::cout)
virtual Real norm() const =0
Returns where .
virtual std::vector< std::vector< Real > > checkApplyAdjointHessian(const Vector< Real > &x, const Vector< Real > &u, const Vector< Real > &v, const Vector< Real > &hv, const std::vector< Real > &step, const bool printToScreen=true, std::ostream &outStream=std::cout, const int order=1)
Finite-difference check for the application of the adjoint of constraint Hessian. ...
double RealT
Definition: example_04.cpp:932
void update(std::vector< Real > &u, const std::vector< Real > &s, const Real alpha=1.0)
Definition: example_04.cpp:108
void applyAdjointHessian_12(ROL::Vector< Real > &ahwv, const ROL::Vector< Real > &w, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Hessian at , , to vector in direction ...
Definition: example_04.cpp:724
virtual Real checkAdjointConsistencyJacobian_2(const Vector< Real > &w, const Vector< Real > &v, const Vector< Real > &u, const Vector< Real > &z, const bool printToStream=true, std::ostream &outStream=std::cout)
Check the consistency of the Jacobian and its adjoint. This is the primary interface.
void apply_pde_jacobian_old(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &u, bool adjoint=false)
Definition: example_04.cpp:211
Provides the interface to compute optimization steps with trust regions.
static const double ROL_EPSILON
Platform-dependent machine epsilon.
Definition: ROL_Types.hpp:115
void applyAdjointHessian_11(ROL::Vector< Real > &hwv, const ROL::Vector< Real > &w, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Apply the adjoint of the partial constraint Hessian at , , to vector in direction ...
Definition: example_04.cpp:699