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 /*! \file example_04.hpp 45 \brief Provides definitions of equality constraint and objective for 46 example_04. 47 */ 48 49 #include "ROL_Algorithm.hpp" 50 #include "ROL_Types.hpp" 51 52 #include "ROL_StdVector.hpp" 53 #include "ROL_Vector_SimOpt.hpp" 54 #include "ROL_Constraint_SimOpt.hpp" 55 #include "ROL_Objective_SimOpt.hpp" 56 #include "ROL_Reduced_Objective_SimOpt.hpp" 57 #include "ROL_ParameterList.hpp" 58 59 #include "ROL_Stream.hpp" 60 #include "Teuchos_GlobalMPISession.hpp" 61 #include "Teuchos_LAPACK.hpp" 62 63 #include <iostream> 64 #include <algorithm> 65 #include <ctime> 66 67 template<class Real> 68 class Constraint_BurgersControl : public ROL::Constraint_SimOpt<Real> { 69 private: 70 unsigned nx_; 71 unsigned nt_; 72 73 Real dx_; 74 Real T_; 75 Real dt_; 76 77 Real nu_; 78 Real u0_; 79 Real u1_; 80 Real f_; 81 std::vector<Real> u_init_; 82 83 private: compute_norm(const std::vector<Real> & r)84 Real compute_norm(const std::vector<Real> &r) { 85 return std::sqrt(dot(r,r)); 86 } 87 dot(const std::vector<Real> & x,const std::vector<Real> & y)88 Real dot(const std::vector<Real> &x, const std::vector<Real> &y) { 89 Real ip = 0.0; 90 Real c = ((x.size()==nx_) ? 4.0 : 2.0); 91 for (unsigned i = 0; i < x.size(); i++) { 92 if ( i == 0 ) { 93 ip += dx_/6.0*(c*x[i] + x[i+1])*y[i]; 94 } 95 else if ( i == x.size()-1 ) { 96 ip += dx_/6.0*(x[i-1] + c*x[i])*y[i]; 97 } 98 else { 99 ip += dx_/6.0*(x[i-1] + 4.0*x[i] + x[i+1])*y[i]; 100 } 101 } 102 return ip; 103 } 104 105 using ROL::Constraint_SimOpt<Real>::update; 106 update(std::vector<Real> & u,const std::vector<Real> & s,const Real alpha=1.0)107 void update(std::vector<Real> &u, const std::vector<Real> &s, const Real alpha=1.0) { 108 for (unsigned i = 0; i < u.size(); i++) { 109 u[i] += alpha*s[i]; 110 } 111 } 112 scale(std::vector<Real> & u,const Real alpha=0.0)113 void scale(std::vector<Real> &u, const Real alpha=0.0) { 114 for (unsigned i = 0; i < u.size(); i++) { 115 u[i] *= alpha; 116 } 117 } 118 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)119 void compute_residual(std::vector<Real> &r, const std::vector<Real> &uold, const std::vector<Real> &zold, 120 const std::vector<Real> &unew, const std::vector<Real> &znew) { 121 r.clear(); 122 r.resize(nx_,0.0); 123 for (unsigned n = 0; n < nx_; n++) { 124 // Contribution from mass & stiffness term at time step t and t-1 125 r[n] += (4.0*dx_/6.0 + 0.5*dt_*2.0*nu_/dx_)*unew[n]; 126 r[n] += (-4.0*dx_/6.0 + 0.5*dt_*2.0*nu_/dx_)*uold[n]; 127 if ( n > 0 ) { 128 r[n] += (dx_/6.0 - 0.5*dt_*nu_/dx_)*unew[n-1]; 129 r[n] -= (dx_/6.0 + 0.5*dt_*nu_/dx_)*uold[n-1]; 130 } 131 if ( n < nx_-1 ) { 132 r[n] += (dx_/6.0 - 0.5*dt_*nu_/dx_)*unew[n+1]; 133 r[n] -= (dx_/6.0 + 0.5*dt_*nu_/dx_)*uold[n+1]; 134 } 135 // Contribution from nonlinear term 136 if ( n > 0 ) { 137 r[n] -= 0.5*dt_*unew[n-1]*(unew[n-1]+unew[n])/6.0; 138 r[n] -= 0.5*dt_*uold[n-1]*(uold[n-1]+uold[n])/6.0; 139 } 140 if ( n < nx_-1 ){ 141 r[n] += 0.5*dt_*unew[n+1]*(unew[n]+unew[n+1])/6.0; 142 r[n] += 0.5*dt_*uold[n+1]*(uold[n]+uold[n+1])/6.0; 143 } 144 // Contribution from control 145 r[n] -= 0.5*dt_*dx_/6.0*(znew[n]+4.0*znew[n+1]+znew[n+2]); 146 r[n] -= 0.5*dt_*dx_/6.0*(zold[n]+4.0*zold[n+1]+zold[n+2]); 147 // Contribution from right-hand side 148 r[n] -= dt_*dx_*f_; 149 } 150 // Contribution from Dirichlet boundary terms 151 r[0] -= dt_*(0.5*u0_*(unew[ 0] + uold[ 0])/6.0 + u0_*u0_/6.0 + nu_*u0_/dx_); 152 r[nx_-1] += dt_*(0.5*u1_*(unew[nx_-1] + uold[nx_-1])/6.0 + u1_*u1_/6.0 - nu_*u1_/dx_); 153 } 154 compute_pde_jacobian(std::vector<Real> & dl,std::vector<Real> & d,std::vector<Real> & du,const std::vector<Real> & u)155 void compute_pde_jacobian(std::vector<Real> &dl, std::vector<Real> &d, std::vector<Real> &du, 156 const std::vector<Real> &u) { 157 // Get Diagonal and Off-Diagonal Entries of linear PDE Jacobian 158 d.clear(); 159 d.resize(nx_,4.0*dx_/6.0 + 0.5*dt_*nu_*2.0/dx_); 160 dl.clear(); 161 dl.resize(nx_-1,dx_/6.0 - 0.5*dt_*nu_/dx_); 162 du.clear(); 163 du.resize(nx_-1,dx_/6.0 - 0.5*dt_*nu_/dx_); 164 // Contribution from nonlinearity 165 for (unsigned n = 0; n < nx_; n++) { 166 if ( n < nx_-1 ) { 167 dl[n] += 0.5*dt_*(-2.0*u[n]-u[n+1])/6.0; 168 d[n] += 0.5*dt_*u[n+1]/6.0; 169 } 170 if ( n > 0 ) { 171 d[n] -= 0.5*dt_*u[n-1]/6.0; 172 du[n-1] += 0.5*dt_*(u[n-1]+2.0*u[n])/6.0; 173 } 174 } 175 // Contribution from Dirichlet boundary conditions 176 d[0] -= 0.5*dt_*u0_/6.0; 177 d[nx_-1] += 0.5*dt_*u1_/6.0; 178 } 179 apply_pde_jacobian_new(std::vector<Real> & jv,const std::vector<Real> & v,const std::vector<Real> & u,bool adjoint=false)180 void apply_pde_jacobian_new(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &u, 181 bool adjoint = false) { 182 jv.clear(); 183 jv.resize(nx_,0.0); 184 // Fill Jacobian times a vector 185 for (unsigned n = 0; n < nx_; n++) { 186 jv[n] = (4.0*dx_/6.0 + 0.5*dt_*nu_/dx_*2.0)*v[n]; // Mass & Stiffness 187 if ( n > 0 ) { 188 jv[n] += dx_/6.0*v[n-1]-0.5*dt_*nu_/dx_*v[n-1]; // Mass & Stiffness 189 if ( adjoint ) { 190 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 191 } 192 else { 193 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 194 } 195 } 196 if ( n < nx_-1 ) { 197 jv[n] += dx_/6.0*v[n+1]-0.5*dt_*nu_/dx_*v[n+1]; // Mass & Stiffness 198 if ( adjoint ) { 199 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 200 } 201 else { 202 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 203 } 204 } 205 } 206 jv[0] -= 0.5*dt_*u0_/6.0*v[0]; // Nonlinearity 207 jv[nx_-1] += 0.5*dt_*u1_/6.0*v[nx_-1]; // Nonlinearity 208 } 209 apply_pde_jacobian_old(std::vector<Real> & jv,const std::vector<Real> & v,const std::vector<Real> & u,bool adjoint=false)210 void apply_pde_jacobian_old(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &u, 211 bool adjoint = false) { 212 jv.clear(); 213 jv.resize(nx_,0.0); 214 // Fill Jacobian times a vector 215 for (unsigned n = 0; n < nx_; n++) { 216 jv[n] = (-4.0*dx_/6.0 + 0.5*dt_*nu_/dx_*2.0)*v[n]; // Mass & Stiffness 217 if ( n > 0 ) { 218 jv[n] += -dx_/6.0*v[n-1]-0.5*dt_*nu_/dx_*v[n-1]; // Mass & Stiffness 219 if ( adjoint ) { 220 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 221 } 222 else { 223 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 224 } 225 } 226 if ( n < nx_-1 ) { 227 jv[n] += -dx_/6.0*v[n+1]-0.5*dt_*nu_/dx_*v[n+1]; // Mass & Stiffness 228 if ( adjoint ) { 229 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 230 } 231 else { 232 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 233 } 234 } 235 } 236 jv[0] -= 0.5*dt_*u0_/6.0*v[0]; // Nonlinearity 237 jv[nx_-1] += 0.5*dt_*u1_/6.0*v[nx_-1]; // Nonlinearity 238 } 239 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)240 void apply_pde_jacobian(std::vector<Real> &jv, const std::vector<Real> &vold, const std::vector<Real> &uold, 241 const std::vector<Real> &vnew, const std::vector<Real> unew, bool adjoint = false) { 242 jv.clear(); 243 jv.resize(nx_,0.0); 244 // Fill Jacobian times a vector 245 for (unsigned n = 0; n < nx_; n++) { 246 jv[n] += (4.0*dx_/6.0+0.5*dt_*nu_/dx_*2.0)*vnew[n]; // Mass & Stiffness 247 jv[n] -= (4.0*dx_/6.0-0.5*dt_*nu_/dx_*2.0)*vold[n]; // Mass & Stiffness 248 if ( n > 0 ) { 249 jv[n] += dx_/6.0*vnew[n-1]-0.5*dt_*nu_/dx_*vnew[n-1]; // Mass & Stiffness 250 jv[n] -= dx_/6.0*vold[n-1]+0.5*dt_*nu_/dx_*vold[n-1]; // Mass & Stiffness 251 if ( adjoint ) { 252 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 253 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 254 } 255 else { 256 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 257 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 258 } 259 } 260 if ( n < nx_-1 ) { 261 jv[n] += dx_/6.0*vnew[n+1]-0.5*dt_*nu_/dx_*vnew[n+1]; // Mass & Stiffness 262 jv[n] -= dx_/6.0*vold[n+1]+0.5*dt_*nu_/dx_*vold[n+1]; // Mass & Stiffness 263 if ( adjoint ) { 264 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 265 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 266 } 267 else { 268 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 269 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 270 } 271 } 272 } 273 jv[0] -= 0.5*dt_*u0_/6.0*vnew[0]; // Nonlinearity 274 jv[0] -= 0.5*dt_*u0_/6.0*vold[0]; // Nonlinearity 275 jv[nx_-1] += 0.5*dt_*u1_/6.0*vnew[nx_-1]; // Nonlinearity 276 jv[nx_-1] += 0.5*dt_*u1_/6.0*vold[nx_-1]; // Nonlinearity 277 } 278 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)279 void apply_pde_hessian(std::vector<Real> &hv, const std::vector<Real> &wold, const std::vector<Real> &vold, 280 const std::vector<Real> &wnew, const std::vector<Real> &vnew) { 281 hv.clear(); 282 hv.resize(nx_,0.0); 283 for (unsigned n = 0; n < nx_; n++) { 284 if ( n > 0 ) { 285 hv[n] += 0.5*dt_*((wnew[n-1]*(vnew[n-1]+2.0*vnew[n]) - wnew[n]*vnew[n-1])/6.0); 286 hv[n] += 0.5*dt_*((wold[n-1]*(vold[n-1]+2.0*vold[n]) - wold[n]*vold[n-1])/6.0); 287 } 288 if ( n < nx_-1 ){ 289 hv[n] += 0.5*dt_*((wnew[n]*vnew[n+1] - wnew[n+1]*(2.0*vnew[n]+vnew[n+1]))/6.0); 290 hv[n] += 0.5*dt_*((wold[n]*vold[n+1] - wold[n+1]*(2.0*vold[n]+vold[n+1]))/6.0); 291 } 292 } 293 } 294 apply_control_jacobian(std::vector<Real> & jv,const std::vector<Real> & v,bool adjoint=false)295 void apply_control_jacobian(std::vector<Real> &jv, const std::vector<Real> &v, bool adjoint = false) { 296 jv.clear(); 297 unsigned dim = ((adjoint == true) ? nx_+2 : nx_); 298 jv.resize(dim,0.0); 299 for (unsigned n = 0; n < dim; n++) { 300 if ( adjoint ) { 301 if ( n == 0 ) { 302 jv[n] = -0.5*dt_*dx_/6.0*v[n]; 303 } 304 else if ( n == 1 ) { 305 jv[n] = -0.5*dt_*dx_/6.0*(4.0*v[n-1]+v[n]); 306 } 307 else if ( n == nx_ ) { 308 jv[n] = -0.5*dt_*dx_/6.0*(4.0*v[n-1]+v[n-2]); 309 } 310 else if ( n == nx_+1 ) { 311 jv[n] = -0.5*dt_*dx_/6.0*v[n-2]; 312 } 313 else { 314 jv[n] = -0.5*dt_*dx_/6.0*(v[n-2]+4.0*v[n-1]+v[n]); 315 } 316 } 317 else { 318 jv[n] -= 0.5*dt_*dx_/6.0*(v[n]+4.0*v[n+1]+v[n+2]); 319 } 320 } 321 } 322 run_newton(std::vector<Real> & u,const std::vector<Real> & znew,const std::vector<Real> & uold,const std::vector<Real> & zold)323 void run_newton(std::vector<Real> &u, const std::vector<Real> &znew, 324 const std::vector<Real> &uold, const std::vector<Real> &zold) { 325 u.clear(); 326 u.resize(nx_,0.0); 327 // Compute residual and residual norm 328 std::vector<Real> r(nx_,0.0); 329 compute_residual(r,uold,zold,u,znew); 330 Real rnorm = compute_norm(r); 331 // Define tolerances 332 Real rtol = 1.e2*ROL::ROL_EPSILON<Real>(); 333 unsigned maxit = 500; 334 // Initialize Jacobian storage 335 std::vector<Real> d(nx_,0.0); 336 std::vector<Real> dl(nx_-1,0.0); 337 std::vector<Real> du(nx_-1,0.0); 338 // Iterate Newton's method 339 Real alpha = 1.0, tmp = 0.0; 340 std::vector<Real> s(nx_,0.0); 341 std::vector<Real> utmp(nx_,0.0); 342 for (unsigned i = 0; i < maxit; i++) { 343 //std::cout << i << " " << rnorm << "\n"; 344 // Get Jacobian 345 compute_pde_jacobian(dl,d,du,u); 346 // Solve Newton system 347 linear_solve(s,dl,d,du,r); 348 // Perform line search 349 tmp = rnorm; 350 alpha = 1.0; 351 utmp.assign(u.begin(),u.end()); 352 update(utmp,s,-alpha); 353 compute_residual(r,uold,zold,utmp,znew); 354 rnorm = compute_norm(r); 355 while ( rnorm > (1.0-1.e-4*alpha)*tmp && alpha > std::sqrt(ROL::ROL_EPSILON<Real>()) ) { 356 alpha *= 0.5; 357 utmp.assign(u.begin(),u.end()); 358 update(utmp,s,-alpha); 359 compute_residual(r,uold,zold,utmp,znew); 360 rnorm = compute_norm(r); 361 } 362 // Update iterate 363 u.assign(utmp.begin(),utmp.end()); 364 if ( rnorm < rtol ) { 365 break; 366 } 367 } 368 } 369 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)370 void linear_solve(std::vector<Real> &u, 371 const std::vector<Real> &dl, const std::vector<Real> &d, const std::vector<Real> &du, 372 const std::vector<Real> &r, const bool transpose = false) { 373 bool useLAPACK = true; 374 if ( useLAPACK ) { // DIRECT SOLVE: USE LAPACK 375 u.assign(r.begin(),r.end()); 376 // Store matrix diagonal & off-diagonals. 377 std::vector<Real> Dl(dl); 378 std::vector<Real> Du(du); 379 std::vector<Real> D(d); 380 // Perform LDL factorization 381 Teuchos::LAPACK<int,Real> lp; 382 std::vector<Real> Du2(nx_-2,0.0); 383 std::vector<int> ipiv(nx_,0); 384 int info; 385 int ldb = nx_; 386 int nhrs = 1; 387 lp.GTTRF(nx_,&Dl[0],&D[0],&Du[0],&Du2[0],&ipiv[0],&info); 388 char trans = ((transpose == true) ? 'T' : 'N'); 389 lp.GTTRS(trans,nx_,nhrs,&Dl[0],&D[0],&Du[0],&Du2[0],&ipiv[0],&u[0],ldb,&info); 390 } 391 else { // ITERATIVE SOLVE: USE GAUSS-SEIDEL 392 u.clear(); 393 u.resize(nx_,0.0); 394 unsigned maxit = 100; 395 Real rtol = std::min(1.e-12,1.e-4*std::sqrt(dot(r,r))); 396 //Real rtol = 1e-6; 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 Constraint_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)432 Constraint_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 value(ROL::Vector<Real> & c,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)446 void value(ROL::Vector<Real> &c, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 447 ROL::Ptr<std::vector<Real> > cp = 448 dynamic_cast<ROL::StdVector<Real>&>(c).getVector(); 449 ROL::Ptr<const std::vector<Real> > up = 450 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 451 ROL::Ptr<const std::vector<Real> > zp = 452 dynamic_cast<const ROL::StdVector<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 solve(ROL::Vector<Real> & c,ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)485 void solve(ROL::Vector<Real> &c, ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 486 ROL::Ptr<std::vector<Real> > up = 487 dynamic_cast<ROL::StdVector<Real>&>(u).getVector(); 488 up->assign(up->size(),z.norm()/up->size()); 489 ROL::Ptr<const std::vector<Real> > zp = 490 dynamic_cast<const ROL::StdVector<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 value(c,u,z,tol); 517 } 518 applyJacobian_1(ROL::Vector<Real> & jv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)519 void applyJacobian_1(ROL::Vector<Real> &jv, const ROL::Vector<Real> &v, const ROL::Vector<Real> &u, 520 const ROL::Vector<Real> &z, Real &tol) { 521 ROL::Ptr<std::vector<Real> > jvp = 522 dynamic_cast<ROL::StdVector<Real>&>(jv).getVector(); 523 ROL::Ptr<const std::vector<Real> > vp = 524 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 525 ROL::Ptr<const std::vector<Real> > up = 526 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 527 std::vector<Real> J(nx_,0.0); 528 std::vector<Real> vold(nx_,0.0); 529 std::vector<Real> vnew(nx_,0.0); 530 std::vector<Real> uold(nx_,0.0); 531 std::vector<Real> unew(nx_,0.0); 532 for (unsigned t = 0; t < nt_; t++) { 533 for (unsigned n = 0; n < nx_; n++) { 534 unew[n] = (*up)[t*nx_+n]; 535 vnew[n] = (*vp)[t*nx_+n]; 536 } 537 apply_pde_jacobian(J,vold,uold,vnew,unew); 538 for (unsigned n = 0; n < nx_; n++) { 539 (*jvp)[t*nx_+n] = J[n]; 540 } 541 vold.assign(vnew.begin(),vnew.end()); 542 uold.assign(unew.begin(),unew.end()); 543 } 544 } 545 applyJacobian_2(ROL::Vector<Real> & jv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)546 void applyJacobian_2(ROL::Vector<Real> &jv, const ROL::Vector<Real> &v, const ROL::Vector<Real> &u, 547 const ROL::Vector<Real> &z, Real &tol) { 548 ROL::Ptr<std::vector<Real> > jvp = 549 dynamic_cast<ROL::StdVector<Real>&>(jv).getVector(); 550 ROL::Ptr<const std::vector<Real> > vp = 551 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 552 ROL::Ptr<const std::vector<Real> > zp = 553 dynamic_cast<const ROL::StdVector<Real>&>(z).getVector(); 554 std::vector<Real> vnew(nx_+2,0.0); 555 std::vector<Real> vold(nx_+2,0.0); 556 std::vector<Real> jnew(nx_,0.0); 557 std::vector<Real> jold(nx_,0.0); 558 for (unsigned n = 0; n < nx_+2; n++) { 559 vold[n] = (*vp)[n]; 560 } 561 apply_control_jacobian(jold,vold); 562 for (unsigned t = 0; t < nt_; t++) { 563 for (unsigned n = 0; n < nx_+2; n++) { 564 vnew[n] = (*vp)[(t+1)*(nx_+2)+n]; 565 } 566 apply_control_jacobian(jnew,vnew); 567 for (unsigned n = 0; n < nx_; n++) { 568 // Contribution from control 569 (*jvp)[t*nx_+n] = jnew[n] + jold[n]; 570 } 571 jold.assign(jnew.begin(),jnew.end()); 572 } 573 } 574 applyInverseJacobian_1(ROL::Vector<Real> & ijv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)575 void applyInverseJacobian_1(ROL::Vector<Real> &ijv, const ROL::Vector<Real> &v, const ROL::Vector<Real> &u, 576 const ROL::Vector<Real> &z, Real &tol) { 577 ROL::Ptr<std::vector<Real> > ijvp = 578 dynamic_cast<ROL::StdVector<Real>&>(ijv).getVector(); 579 ROL::Ptr<const std::vector<Real> > vp = 580 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 581 ROL::Ptr<const std::vector<Real> > up = 582 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 583 std::vector<Real> J(nx_,0.0); 584 std::vector<Real> r(nx_,0.0); 585 std::vector<Real> s(nx_,0.0); 586 std::vector<Real> uold(nx_,0.0); 587 std::vector<Real> unew(nx_,0.0); 588 std::vector<Real> d(nx_,0.0); 589 std::vector<Real> dl(nx_-1,0.0); 590 std::vector<Real> du(nx_-1,0.0); 591 for (unsigned t = 0; t < nt_; t++) { 592 // Build rhs. 593 for (unsigned n = 0; n < nx_; n++) { 594 r[n] = (*vp)[t*nx_+n]; 595 unew[n] = (*up)[t*nx_+n]; 596 } 597 apply_pde_jacobian_old(J,s,uold); 598 update(r,J,-1.0); 599 // Build Jacobian. 600 compute_pde_jacobian(dl,d,du,unew); 601 // Solve linear system. 602 linear_solve(s,dl,d,du,r); 603 // Copy solution. 604 for (unsigned n = 0; n < nx_; n++) { 605 (*ijvp)[t*nx_+n] = s[n]; 606 } 607 uold.assign(unew.begin(),unew.end()); 608 } 609 } 610 applyAdjointJacobian_1(ROL::Vector<Real> & ajv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)611 void applyAdjointJacobian_1(ROL::Vector<Real> &ajv, const ROL::Vector<Real> &v, const ROL::Vector<Real> &u, 612 const ROL::Vector<Real> &z, Real &tol) { 613 ROL::Ptr<std::vector<Real> > jvp = 614 dynamic_cast<ROL::StdVector<Real>&>(ajv).getVector(); 615 ROL::Ptr<const std::vector<Real> > vp = 616 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 617 ROL::Ptr<const std::vector<Real> > up = 618 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 619 std::vector<Real> J(nx_,0.0); 620 std::vector<Real> vold(nx_,0.0); 621 std::vector<Real> vnew(nx_,0.0); 622 std::vector<Real> unew(nx_,0.0); 623 for (unsigned t = nt_; t > 0; t--) { 624 for (unsigned n = 0; n < nx_; n++) { 625 unew[n] = (*up)[(t-1)*nx_+n]; 626 vnew[n] = (*vp)[(t-1)*nx_+n]; 627 } 628 apply_pde_jacobian(J,vold,unew,vnew,unew,true); 629 for (unsigned n = 0; n < nx_; n++) { 630 (*jvp)[(t-1)*nx_+n] = J[n]; 631 } 632 vold.assign(vnew.begin(),vnew.end()); 633 } 634 } 635 applyAdjointJacobian_2(ROL::Vector<Real> & jv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)636 void applyAdjointJacobian_2(ROL::Vector<Real> &jv, const ROL::Vector<Real> &v, const ROL::Vector<Real> &u, 637 const ROL::Vector<Real> &z, Real &tol) { 638 ROL::Ptr<std::vector<Real> > jvp = 639 dynamic_cast<ROL::StdVector<Real>&>(jv).getVector(); 640 ROL::Ptr<const std::vector<Real> > vp = 641 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 642 ROL::Ptr<const std::vector<Real> > zp = 643 dynamic_cast<const ROL::StdVector<Real>&>(z).getVector(); 644 std::vector<Real> vnew(nx_,0.0); 645 std::vector<Real> vold(nx_,0.0); 646 std::vector<Real> jnew(nx_+2,0.0); 647 std::vector<Real> jold(nx_+2,0.0); 648 for (unsigned t = nt_+1; t > 0; t--) { 649 for (unsigned n = 0; n < nx_; n++) { 650 if ( t > 1 ) { 651 vnew[n] = (*vp)[(t-2)*nx_+n]; 652 } 653 else { 654 vnew[n] = 0.0; 655 } 656 } 657 apply_control_jacobian(jnew,vnew,true); 658 for (unsigned n = 0; n < nx_+2; n++) { 659 // Contribution from control 660 (*jvp)[(t-1)*(nx_+2)+n] = jnew[n] + jold[n]; 661 } 662 jold.assign(jnew.begin(),jnew.end()); 663 } 664 } 665 applyInverseAdjointJacobian_1(ROL::Vector<Real> & ijv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)666 void applyInverseAdjointJacobian_1(ROL::Vector<Real> &ijv, const ROL::Vector<Real> &v, 667 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 668 ROL::Ptr<std::vector<Real> > ijvp = 669 dynamic_cast<ROL::StdVector<Real>&>(ijv).getVector(); 670 ROL::Ptr<const std::vector<Real> > vp = 671 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 672 ROL::Ptr<const std::vector<Real> > up = 673 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 674 std::vector<Real> J(nx_,0.0); 675 std::vector<Real> r(nx_,0.0); 676 std::vector<Real> s(nx_,0.0); 677 std::vector<Real> unew(nx_,0.0); 678 std::vector<Real> d(nx_,0.0); 679 std::vector<Real> dl(nx_-1,0.0); 680 std::vector<Real> du(nx_-1,0.0); 681 for (unsigned t = nt_; t > 0; t--) { 682 // Build rhs. 683 for (unsigned n = 0; n < nx_; n++) { 684 r[n] = (*vp)[(t-1)*nx_+n]; 685 unew[n] = (*up)[(t-1)*nx_+n]; 686 } 687 apply_pde_jacobian_old(J,s,unew,true); 688 update(r,J,-1.0); 689 // Build Jacobian. 690 compute_pde_jacobian(dl,d,du,unew); 691 // Solve linear system. 692 linear_solve(s,dl,d,du,r,true); 693 // Copy solution. 694 for (unsigned n = 0; n < nx_; n++) { 695 (*ijvp)[(t-1)*nx_+n] = s[n]; 696 } 697 } 698 } 699 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)700 void applyAdjointHessian_11(ROL::Vector<Real> &hwv, const ROL::Vector<Real> &w, const ROL::Vector<Real> &v, 701 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 702 ROL::Ptr<std::vector<Real> > hwvp = 703 dynamic_cast<ROL::StdVector<Real>&>(hwv).getVector(); 704 ROL::Ptr<const std::vector<Real> > wp = 705 dynamic_cast<const ROL::StdVector<Real>&>(w).getVector(); 706 ROL::Ptr<const std::vector<Real> > vp = 707 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 708 std::vector<Real> snew(nx_,0.0); 709 std::vector<Real> wnew(nx_,0.0); 710 std::vector<Real> wold(nx_,0.0); 711 std::vector<Real> vnew(nx_,0.0); 712 for (unsigned t = nt_; t > 0; t--) { 713 for (unsigned n = 0; n < nx_; n++) { 714 vnew[n] = (*vp)[(t-1)*nx_+n]; 715 wnew[n] = (*wp)[(t-1)*nx_+n]; 716 } 717 apply_pde_hessian(snew,wold,vnew,wnew,vnew); 718 for (unsigned n = 0; n < nx_; n++) { 719 (*hwvp)[(t-1)*nx_+n] = snew[n]; 720 } 721 wold.assign(wnew.begin(),wnew.end()); 722 } 723 } 724 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)725 void applyAdjointHessian_12(ROL::Vector<Real> &ahwv, const ROL::Vector<Real> &w, const ROL::Vector<Real> &v, 726 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 727 ahwv.zero(); 728 } 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)729 void applyAdjointHessian_21(ROL::Vector<Real> &ahwv, const ROL::Vector<Real> &w, const ROL::Vector<Real> &v, 730 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 731 ahwv.zero(); 732 } 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)733 void applyAdjointHessian_22(ROL::Vector<Real> &ahwv, const ROL::Vector<Real> &w, const ROL::Vector<Real> &v, 734 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) { 735 ahwv.zero(); 736 } 737 }; 738 739 template<class Real> 740 class Objective_BurgersControl : public ROL::Objective_SimOpt<Real> { 741 private: 742 Real alpha_; // Penalty Parameter 743 744 unsigned nx_; // Number of interior nodes 745 Real dx_; // Mesh spacing (i.e. 1/(nx+1)) 746 unsigned nt_; // Number of time steps 747 Real dt_; // Time step size 748 Real T_; // Final time 749 750 /***************************************************************/ 751 /********** BEGIN PRIVATE MEMBER FUNCTION DECLARATION **********/ 752 /***************************************************************/ evaluate_target(Real x)753 Real evaluate_target(Real x) { 754 Real val = 0.0; 755 int example = 1; 756 switch (example) { 757 case 1: val = ((x<=0.5) ? 1.0 : 0.0); break; 758 case 2: val = 1.0; break; 759 case 3: val = std::abs(std::sin(8.0*M_PI*x)); break; 760 case 4: val = std::exp(-0.5*(x-0.5)*(x-0.5)); break; 761 } 762 return val; 763 } 764 dot(const std::vector<Real> & x,const std::vector<Real> & y)765 Real dot(const std::vector<Real> &x, const std::vector<Real> &y) { 766 Real ip = 0.0; 767 Real c = ((x.size()==nx_) ? 4.0 : 2.0); 768 for (unsigned i=0; i<x.size(); i++) { 769 if ( i == 0 ) { 770 ip += dx_/6.0*(c*x[i] + x[i+1])*y[i]; 771 } 772 else if ( i == x.size()-1 ) { 773 ip += dx_/6.0*(x[i-1] + c*x[i])*y[i]; 774 } 775 else { 776 ip += dx_/6.0*(x[i-1] + 4.0*x[i] + x[i+1])*y[i]; 777 } 778 } 779 return ip; 780 } 781 apply_mass(std::vector<Real> & Mu,const std::vector<Real> & u)782 void apply_mass(std::vector<Real> &Mu, const std::vector<Real> &u ) { 783 Mu.resize(u.size(),0.0); 784 Real c = ((u.size()==nx_) ? 4.0 : 2.0); 785 for (unsigned i=0; i<u.size(); i++) { 786 if ( i == 0 ) { 787 Mu[i] = dx_/6.0*(c*u[i] + u[i+1]); 788 } 789 else if ( i == u.size()-1 ) { 790 Mu[i] = dx_/6.0*(u[i-1] + c*u[i]); 791 } 792 else { 793 Mu[i] = dx_/6.0*(u[i-1] + 4.0*u[i] + u[i+1]); 794 } 795 } 796 } 797 /*************************************************************/ 798 /********** END PRIVATE MEMBER FUNCTION DECLARATION **********/ 799 /*************************************************************/ 800 801 public: 802 Objective_BurgersControl(Real alpha=1.e-4,int nx=128,int nt=100,Real T=1.0)803 Objective_BurgersControl(Real alpha = 1.e-4, int nx = 128, int nt = 100, Real T = 1.0) 804 : alpha_(alpha), nx_((unsigned)nx), nt_((unsigned)nt), T_(T) { 805 dx_ = 1.0/((Real)nx+1.0); 806 dt_ = T/((Real)nt); 807 } 808 value(const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)809 Real value( const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 810 ROL::Ptr<const std::vector<Real> > up = 811 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 812 ROL::Ptr<const std::vector<Real> > zp = 813 dynamic_cast<const ROL::StdVector<Real>&>(z).getVector(); 814 // COMPUTE RESIDUAL 815 std::vector<Real> U(nx_,0.0); 816 std::vector<Real> G(nx_,0.0); 817 std::vector<Real> Z(nx_+2,0.0); 818 for (unsigned n = 0; n < nx_+2; n++) { 819 Z[n] = (*zp)[n]; 820 } 821 Real ss = 0.5*dt_; 822 Real val = 0.5*ss*alpha_*dot(Z,Z); 823 for (unsigned t = 0; t < nt_; t++) { 824 ss = ((t < nt_-1) ? dt_ : 0.5*dt_); 825 for (unsigned n = 0; n < nx_; n++) { 826 U[n] = (*up)[t*nx_+n]-evaluate_target((Real)(n+1)*dx_); 827 G[n] = evaluate_target((Real)(n+1)*dx_); 828 } 829 val += 0.5*ss*dot(U,U); 830 val -= 0.5*ss*dot(G,G); // subtract constant term 831 for (unsigned n = 0; n < nx_+2; n++) { 832 Z[n] = (*zp)[(t+1)*(nx_+2)+n]; 833 } 834 val += 0.5*ss*alpha_*dot(Z,Z); 835 } 836 return val; 837 } 838 gradient_1(ROL::Vector<Real> & g,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)839 void gradient_1( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 840 ROL::Ptr<std::vector<Real> > gp = 841 dynamic_cast<ROL::StdVector<Real>&>(g).getVector(); 842 ROL::Ptr<const std::vector<Real> > up = 843 dynamic_cast<const ROL::StdVector<Real>&>(u).getVector(); 844 // COMPUTE GRADIENT WRT U 845 std::vector<Real> U(nx_,0.0); 846 std::vector<Real> M(nx_,0.0); 847 Real ss = dt_; 848 for (unsigned t = 0; t < nt_; t++) { 849 ss = ((t < nt_-1) ? dt_ : 0.5*dt_); 850 for (unsigned n = 0; n < nx_; n++) { 851 U[n] = (*up)[t*nx_+n]-evaluate_target((Real)(n+1)*dx_); 852 } 853 apply_mass(M,U); 854 for (unsigned n = 0; n < nx_; n++) { 855 (*gp)[t*nx_+n] = ss*M[n]; 856 } 857 } 858 } 859 gradient_2(ROL::Vector<Real> & g,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)860 void gradient_2( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 861 ROL::Ptr<std::vector<Real> > gp = 862 dynamic_cast<ROL::StdVector<Real>&>(g).getVector(); 863 ROL::Ptr<const std::vector<Real> > zp = 864 dynamic_cast<const ROL::StdVector<Real>&>(z).getVector(); 865 // COMPUTE GRADIENT WRT Z 866 std::vector<Real> Z(nx_+2,0.0); 867 std::vector<Real> M(nx_+2,0.0); 868 Real ss = dt_; 869 for (unsigned t = 0; t < nt_+1; t++) { 870 ss = ((t < nt_ && t > 0) ? dt_ : 0.5*dt_); 871 for (unsigned n = 0; n < nx_+2; n++) { 872 Z[n] = (*zp)[t*(nx_+2)+n]; 873 } 874 apply_mass(M,Z); 875 for (unsigned n = 0; n < nx_+2; n++) { 876 (*gp)[t*(nx_+2)+n] = ss*alpha_*M[n]; 877 } 878 } 879 } 880 hessVec_11(ROL::Vector<Real> & hv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)881 void hessVec_11( ROL::Vector<Real> &hv, const ROL::Vector<Real> &v, 882 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 883 ROL::Ptr<std::vector<Real> > hvp = 884 dynamic_cast<ROL::StdVector<Real>&>(hv).getVector(); 885 ROL::Ptr<const std::vector<Real> > vp = 886 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 887 // COMPUTE GRADIENT WRT U 888 std::vector<Real> V(nx_,0.0); 889 std::vector<Real> M(nx_,0.0); 890 Real ss = 0.5*dt_; 891 for (unsigned t = 0; t < nt_; t++) { 892 ss = ((t < nt_-1) ? dt_ : 0.5*dt_); 893 for (unsigned n = 0; n < nx_; n++) { 894 V[n] = (*vp)[t*nx_+n]; 895 } 896 apply_mass(M,V); 897 for (unsigned n = 0; n < nx_; n++) { 898 (*hvp)[t*nx_+n] = ss*M[n]; 899 } 900 } 901 } 902 hessVec_12(ROL::Vector<Real> & hv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)903 void hessVec_12( ROL::Vector<Real> &hv, const ROL::Vector<Real> &v, 904 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 905 hv.zero(); 906 } 907 hessVec_21(ROL::Vector<Real> & hv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)908 void hessVec_21( ROL::Vector<Real> &hv, const ROL::Vector<Real> &v, 909 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 910 hv.zero(); 911 } 912 hessVec_22(ROL::Vector<Real> & hv,const ROL::Vector<Real> & v,const ROL::Vector<Real> & u,const ROL::Vector<Real> & z,Real & tol)913 void hessVec_22( ROL::Vector<Real> &hv, const ROL::Vector<Real> &v, 914 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) { 915 ROL::Ptr<std::vector<Real> > hvp = ROL::constPtrCast<std::vector<Real> >( 916 (dynamic_cast<const ROL::StdVector<Real>&>(hv)).getVector()); 917 ROL::Ptr<const std::vector<Real> > vp = 918 dynamic_cast<const ROL::StdVector<Real>&>(v).getVector(); 919 // COMPUTE GRADIENT WRT Z 920 std::vector<Real> V(nx_+2,0.0); 921 std::vector<Real> M(nx_+2,0.0); 922 Real ss = 0.0; 923 for (unsigned t = 0; t < nt_+1; t++) { 924 ss = ((t < nt_ && t > 0) ? dt_ : 0.5*dt_); 925 for (unsigned n = 0; n < nx_+2; n++) { 926 V[n] = (*vp)[t*(nx_+2)+n]; 927 } 928 apply_mass(M,V); 929 for (unsigned n = 0; n < nx_+2; n++) { 930 (*hvp)[t*(nx_+2)+n] = ss*alpha_*M[n]; 931 } 932 } 933 } 934 }; 935