ROL
poisson-control/example_02.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Rapid Optimization Library (ROL) Package
4//
5// Copyright 2014 NTESS and the ROL contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#include <vector>
11#include <cmath>
12#include <limits>
13
14#include "Teuchos_LAPACK.hpp"
15#include "Teuchos_SerialDenseMatrix.hpp"
16
17#include "ROL_Types.hpp"
18#include "ROL_StdVector.hpp"
21
22
23template<class Real>
24class FEM {
25private:
26 int nx_; // Number of intervals
27 Real kl_; // Left diffusivity
28 Real kr_; // Right diffusivity
29
30 std::vector<Real> pts_;
31 std::vector<Real> wts_;
32public:
33
34 FEM(int nx = 128, Real kl = 0.1, Real kr = 10.0) : nx_(nx), kl_(kl), kr_(kr) {
35 // Set quadrature points
36 pts_.clear();
37 pts_.resize(5,0.0);
38 pts_[0] = -0.9061798459386640;
39 pts_[1] = -0.5384693101056831;
40 pts_[2] = 0.0;
41 pts_[3] = 0.5384693101056831;
42 pts_[4] = 0.9061798459386640;
43 wts_.clear();
44 wts_.resize(5,0.0);
45 wts_[0] = 0.2369268850561891;
46 wts_[1] = 0.4786286704993665;
47 wts_[2] = 0.5688888888888889;
48 wts_[3] = 0.4786286704993665;
49 wts_[4] = 0.2369268850561891;
50 // Scale and normalize points and weights
51 Real sum = 0.0;
52 for (int i = 0; i < 5; i++) {
53 pts_[i] = 0.5*pts_[i] + 0.5;
54 sum += wts_[i];
55 }
56 for (int i = 0; i < 5; i++) {
57 wts_[i] /= sum;
58 }
59 }
60
61 int nu(void) { return nx_-1; }
62 int nz(void) { return nx_+1; }
63
64 void build_mesh(std::vector<Real> &x, const std::vector<Real> &param) {
65 // Partition mesh:
66 // nx1 is the # of intervals on the left of xp -- n1 is the # of interior nodes
67 // nx2 is the # of intervals on the right of xp -- n2 is the # of interior nodes
68 Real xp = 0.1*param[0];
69 int frac = nx_/2;
70 int rem = nx_%2;
71 int nx1 = frac;
72 int nx2 = frac;
73 if ( rem == 1 ) {
74 if (xp > 0.0) {
75 nx2++;
76 }
77 else {
78 nx1++;
79 }
80 }
81 int n1 = nx1-1;
82 int n2 = nx2-1;
83 // Compute mesh spacing
84 Real dx1 = (xp+1.0)/(Real)nx1;
85 Real dx2 = (1.0-xp)/(Real)nx2;
86 // Build uniform meshes on [-1,xp] u [xp,1]
87 x.clear();
88 x.resize(n1+n2+3,0.0);
89 for (int k = 0; k < n1+n2+3; k++) {
90 x[k] = ((k < nx1) ? (Real)k*dx1-1.0 : ((k==nx1) ? xp : (Real)(k-nx1)*dx2+xp));
91 //std::cout << x[k] << "\n";
92 }
93 }
94
95 void build_mesh(std::vector<Real> &x) {
96 int frac = nz()/16;
97 int rem = nz()%16;
98 int nz1 = frac*4;
99 int nz2 = frac;
100 int nz3 = frac*9;
101 int nz4 = frac*2;
102 for ( int i = 0; i < rem; i++ ) {
103 if ( i%4 == 0 ) { nz3++; }
104 else if ( i%4 == 1 ) { nz1++; }
105 else if ( i%4 == 2 ) { nz4++; }
106 else if ( i%4 == 3 ) { nz2++; }
107 }
108 x.clear();
109 x.resize(nz(),0.0);
110 for (int k = 0; k < nz(); k++) {
111 if ( k < nz1 ) {
112 x[k] = 0.25*(Real)k/(Real)(nz1-1) - 1.0;
113 }
114 if ( k >= nz1 && k < nz1+nz2 ) {
115 x[k] = 0.5*(Real)(k-nz1+1)/(Real)nz2 - 0.75;
116 }
117 if ( k >= nz1+nz2 && k < nz1+nz2+nz3 ) {
118 x[k] = 0.5*(Real)(k-nz1-nz2+1)/(Real)nz3 - 0.25;
119 }
120 if ( k >= nz1+nz2+nz3-1 ) {
121 x[k] = 0.75*(Real)(k-nz1-nz2-nz3+1)/(Real)nz4 + 0.25;
122 }
123 //std::cout << x[k] << "\n";
124 }
125 //x.clear();
126 //x.resize(nz(),0.0);
127 //for (int k = 0; k < nz(); k++) {
128 // x[k] = 2.0*(Real)k/(Real)(nz()-1)-1.0;
129 // //std::cout << xz[k] << "\n";
130 //}
131 }
132
133 // Build force.
134 void build_force(std::vector<Real> &F, const std::vector<Real> &param) {
135 // Build mesh
136 std::vector<Real> x(nu()+2,0.0);
137 build_mesh(x,param);
138 // Build force term
139 F.clear();
140 F.resize(x.size()-2,0.0);
141 Real pt = 0.0;
142 int size = static_cast<int>(x.size());
143 for (int i = 0; i < size-2; i++) {
144 for (int j = 0; j < 5; j++) {
145 // Integrate over [xl,x0]
146 pt = (x[i+1]-x[i])*pts_[j] + x[i];
147 F[i] += wts_[j]*(pt-x[i])*std::exp(-std::pow(pt-0.5*param[1],2.0));
148 // Integrate over [x0,xu]
149 pt = (x[i+2]-x[i+1])*pts_[j] + x[i+1];
150 F[i] += wts_[j]*(x[i+2]-pt)*std::exp(-std::pow(pt-0.5*param[1],2.0));
151 }
152 }
153 }
154
155 // Build the PDE residual Jacobian.
156 void build_jacobian_1(std::vector<Real> &dl, std::vector<Real> &d, std::vector<Real> &du,
157 const std::vector<Real> &param) {
158 // Build mesh
159 std::vector<Real> x(nu()+2,0.0);
160 build_mesh(x,param);
161 // Fill diagonal
162 int xsize = static_cast<int>(x.size());
163 d.clear();
164 d.resize(xsize-2,0.0);
165 for ( int i = 0; i < xsize-2; i++ ) {
166 if ( x[i+1] < 0.1*param[0] ) {
167 d[i] = kl_/(x[i+1]-x[i]) + kl_/(x[i+2]-x[i+1]);
168 }
169 else if ( x[i+1] > 0.1*param[0] ) {
170 d[i] = kr_/(x[i+1]-x[i]) + kr_/(x[i+2]-x[i+1]);
171 }
172 else {
173 d[i] = kl_/(x[i+1]-x[i]) + kr_/(x[i+2]-x[i+1]);
174 }
175 //std::cout << d[i] << "\n";
176 }
177 // Fill off-diagonal
178 dl.clear();
179 dl.resize(xsize-3,0.0);
180 for ( int i = 0; i < xsize-3; i++ ) {
181 if ( x[i+2] <= 0.1*param[0] ) {
182 dl[i] = -kl_/(x[i+2]-x[i+1]);
183 }
184 else if ( x[i+2] > 0.1*param[0] ) {
185 dl[i] = -kr_/(x[i+2]-x[i+1]);
186 }
187 //std::cout << dl[i] << "\n";
188 }
189 du.clear();
190 du.assign(dl.begin(),dl.end());
191 }
192
193 // Apply the PDE residual Jacobian.
194 void apply_jacobian_1(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &param) {
195 // Build Jacobian
196 std::vector<Real> dl(nu()-1,0.0);
197 std::vector<Real> d(nu(),0.0);
198 std::vector<Real> du(nu()-1,0.0);
199 build_jacobian_1(dl,d,du,param);
200 // Apply Jacobian
201 jv.clear();
202 jv.resize(d.size(),0.0);
203 int size = static_cast<int>(d.size());
204 for ( int i = 0; i < size; ++i ) {
205 jv[i] = d[i]*v[i];
206 jv[i] += ((i>0) ? dl[i-1]*v[i-1] : 0.0);
207 jv[i] += ((i<size-1) ? du[i]*v[i+1] : 0.0);
208 }
209 }
210
211 void apply_jacobian_2(std::vector<Real> &jv, const std::vector<Real> &v, const std::vector<Real> &param) {
212 // Build u mesh
213 std::vector<Real> xu(nu()+2,0.0);
214 build_mesh(xu,param);
215 // Build z mesh
216 std::vector<Real> xz(nz(),0.0);
217 build_mesh(xz);
218 // Build union of u and z meshes
219 std::vector<Real> x(xu.size()+xz.size(),0.0);
220 typename std::vector<Real>::iterator it;
221 it = std::set_union(xu.begin(),xu.end(),xz.begin(),xz.end(),x.begin());
222 x.resize(it-x.begin());
223 // Interpolate v onto x basis
224 std::vector<Real> vi;
225 int xzsize = static_cast<int>(xz.size());
226 for (it=x.begin(); it!=x.end(); it++) {
227 for (int i = 0; i < xzsize-1; i++) {
228 if ( *it >= xz[i] && *it <= xz[i+1] ) {
229 vi.push_back(v[i+1]*(*it-xz[i])/(xz[i+1]-xz[i]) + v[i]*(xz[i+1]-*it)/(xz[i+1]-xz[i]));
230 break;
231 }
232 }
233 }
234 int xsize = static_cast<int>(x.size());
235 // Apply x basis mass matrix to interpolated v
236 std::vector<Real> Mv(xsize,0.0);
237 for (int i = 0; i < xsize; i++) {
238 Mv[i] += ((i>0) ? (x[i]-x[i-1])/6.0*vi[i-1] + (x[i]-x[i-1])/3.0*vi[i] : 0.0);
239 Mv[i] += ((i<xsize-1) ? (x[i+1]-x[i])/3.0*vi[i] + (x[i+1]-x[i])/6.0*vi[i+1] : 0.0);
240 }
241 // Reduced mass times v to u basis
242 int xusize = static_cast<int>(xu.size());
243 jv.clear();
244 jv.resize(xusize-2,0.0);
245 for (int i = 0; i < xusize-2; i++) {
246 for (int j = 0; j < xsize-1; j++) {
247 jv[i] += (((x[j]>=xu[i ]) && (x[j]< xu[i+1])) ? Mv[j]*(x[j]-xu[i ])/(xu[i+1]-xu[i ]) : 0.0);
248 jv[i] += (((x[j]>=xu[i+1]) && (x[j]<=xu[i+2])) ? Mv[j]*(xu[i+2]-x[j])/(xu[i+2]-xu[i+1]) : 0.0);
249 if ( x[j] > xu[i+2] ) { break; }
250 }
251 }
252 }
253
254 void apply_adjoint_jacobian_2(std::vector<Real> &jv, const std::vector<Real> &v,
255 const std::vector<Real> &param){
256 // Build u mesh
257 std::vector<Real> xu(nu()+2,0.0);
258 build_mesh(xu,param);
259 // Build z mesh
260 std::vector<Real> xz(nz(),0.0);
261 build_mesh(xz);
262 // Build union of u and z meshes
263 std::vector<Real> x(xu.size()+xz.size(),0.0);
264 typename std::vector<Real>::iterator it;
265 it = std::set_union(xu.begin(),xu.end(),xz.begin(),xz.end(),x.begin());
266 x.resize(it-x.begin());
267 // Interpolate v onto x basis
268 std::vector<Real> vi;
269 Real val = 0.0;
270 int xusize = static_cast<int>(xu.size());
271 for (it=x.begin(); it!=x.end(); it++) {
272 for (int i = 0; i < xusize-1; i++) {
273 if ( *it >= xu[i] && *it <= xu[i+1] ) {
274 val = 0.0;
275 val += ((i!=0 ) ? v[i-1]*(xu[i+1]-*it)/(xu[i+1]-xu[i]) : 0.0);
276 val += ((i!=xusize-2) ? v[i ]*(*it-xu[i ])/(xu[i+1]-xu[i]) : 0.0);
277 vi.push_back(val);
278 break;
279 }
280 }
281 }
282 // Apply x basis mass matrix to interpolated v
283 int xsize = static_cast<int>(x.size());
284 std::vector<Real> Mv(xsize,0.0);
285 for (int i = 0; i < xsize; i++) {
286 Mv[i] += ((i>0) ? (x[i]-x[i-1])/6.0*vi[i-1] + (x[i]-x[i-1])/3.0*vi[i] : 0.0);
287 Mv[i] += ((i<xsize-1) ? (x[i+1]-x[i])/3.0*vi[i] + (x[i+1]-x[i])/6.0*vi[i+1] : 0.0);
288 }
289 // Reduced mass times v to u basis
290 jv.clear();
291 jv.resize(nz(),0.0);
292 int xzsize = static_cast<int>(xz.size());
293 for (int i = 0; i < xzsize; i++) {
294 for (int j = 0; j < xsize; j++) {
295 if ( i==0 ) {
296 jv[i] += (((x[j]>=xz[i ]) && (x[j]<=xz[i+1])) ? Mv[j]*(xz[i+1]-x[j])/(xz[i+1]-xz[i ]) : 0.0);
297 if ( x[j] > xz[i+1] ) { break; }
298 }
299 else if ( i == xzsize-1 ) {
300 jv[i] += (((x[j]>=xz[i-1]) && (x[j]<=xz[i ])) ? Mv[j]*(x[j]-xz[i-1])/(xz[i ]-xz[i-1]) : 0.0);
301 }
302 else {
303 jv[i] += (((x[j]>=xz[i-1]) && (x[j]< xz[i ])) ? Mv[j]*(x[j]-xz[i-1])/(xz[i ]-xz[i-1]) : 0.0);
304 jv[i] += (((x[j]>=xz[i ]) && (x[j]<=xz[i+1])) ? Mv[j]*(xz[i+1]-x[j])/(xz[i+1]-xz[i ]) : 0.0);
305 if ( x[j] > xz[i+1] ) { break; }
306 }
307 }
308 }
309 }
310
311 void apply_mass_state(std::vector<Real> &Mv, const std::vector<Real> &v, const std::vector<Real> &param) {
312 // Build u mesh
313 std::vector<Real> x;
314 build_mesh(x,param);
315 // Apply mass matrix
316 int size = static_cast<int>(x.size());
317 Mv.clear();
318 Mv.resize(size-2,0.0);
319 for (int i = 0; i < size-2; i++) {
320 Mv[i] = (x[i+2]-x[i])/3.0*v[i];
321 if ( i > 0 ) {
322 Mv[i] += (x[i+1]-x[i])/6.0*v[i-1];
323 }
324 if ( i < size-3 ) {
325 Mv[i] += (x[i+2]-x[i+1])/6.0*v[i+1];
326 }
327 }
328 }
329
330 void apply_mass_control(std::vector<Real> &Mv, const std::vector<Real> &v) {
331 // Build z mesh
332 std::vector<Real> x(nz(),0.0);
333 build_mesh(x);
334 // Apply mass matrix
335 int xsize = static_cast<Real>(x.size());
336 Mv.clear();
337 Mv.resize(xsize,0.0);
338 for (int i = 0; i < xsize; i++) {
339 if ( i > 0 ) {
340 Mv[i] += (x[i]-x[i-1])/6.0*v[i-1] + (x[i]-x[i-1])/3.0*v[i];
341 }
342 if ( i < xsize-1 ) {
343 Mv[i] += (x[i+1]-x[i])/3.0*v[i] + (x[i+1]-x[i])/6.0*v[i+1];
344 }
345 }
346 }
347
348 void apply_inverse_mass_control(std::vector<Real> &Mv, const std::vector<Real> &v) {
349 // Build z mesh
350 std::vector<Real> x(nz(),0.0);
351 build_mesh(x);
352 // Build mass matrix
353 std::vector<Real> d(nz(),0.0);
354 std::vector<Real> dl(nz()-1,0.0);
355 std::vector<Real> du(nz()-1,0.0);
356 for (int i = 0; i < nz(); i++) {
357 if ( i > 0 ) {
358 dl[i-1] = (x[i]-x[i-1])/6.0;
359 d[i] += (x[i]-x[i-1])/3.0;
360 }
361 if ( i < nz()-1 ) {
362 d[i] += (x[i+1]-x[i])/3.0;
363 du[i] = (x[i+1]-x[i])/6.0;
364 }
365 }
366 // Solve linear system
367 linear_solve(Mv,dl,d,du,v,false);
368 }
369
370 // Solve linear systems in which the matrix is triadiagonal.
371 // This function uses LAPACK routines for:
372 // 1.) Computing the LU factorization of a tridiagonal matrix.
373 // 2.) Use LU factors to solve the linear system.
374 void linear_solve(std::vector<Real> &u, std::vector<Real> &dl, std::vector<Real> &d,
375 std::vector<Real> &du, const std::vector<Real> &r, const bool transpose = false) {
376 u.clear();
377 u.assign(r.begin(),r.end());
378 // Perform LDL factorization
379 Teuchos::LAPACK<int,Real> lp;
380 std::vector<Real> du2(r.size()-2,0.0);
381 std::vector<int> ipiv(r.size(),0);
382 int n = r.size();
383 int info;
384 int ldb = n;
385 int nhrs = 1;
386 lp.GTTRF(n,&dl[0],&d[0],&du[0],&du2[0],&ipiv[0],&info);
387 char trans = 'N';
388 if ( transpose ) {
389 trans = 'T';
390 }
391 lp.GTTRS(trans,n,nhrs,&dl[0],&d[0],&du[0],&du2[0],&ipiv[0],&u[0],ldb,&info);
392 }
393
394 // Evaluates the difference between the solution to the PDE.
395 // and the desired profile
396 Real evaluate_target(int i, const std::vector<Real> &param) {
397 std::vector<Real> x;
398 build_mesh(x,param);
399 Real val = 0.0;
400 int example = 2;
401 switch (example) {
402 case 1: val = ((x[i]<0.5) ? 1.0 : 0.0); break;
403 case 2: val = 1.0; break;
404 case 3: val = std::abs(std::sin(8.0*M_PI*x[i])); break;
405 case 4: val = std::exp(-0.5*(x[i]-0.5)*(x[i]-0.5)); break;
406 }
407 return val;
408 }
409};
410
411template<class Real>
413private:
414 const ROL::Ptr<FEM<Real> > FEM_;
416
417/***************************************************************/
418/********** BEGIN PRIVATE MEMBER FUNCTION DECLARATION **********/
419/***************************************************************/
420 // Returns u <- (u + alpha*s) where u, s are vectors and
421 // alpha is a scalar.
422 void plus(std::vector<Real> &u, const std::vector<Real> &s, const Real alpha=1.0) {
423 int size = static_cast<int>(u.size());
424 for (int i=0; i<size; i++) {
425 u[i] += alpha*s[i];
426 }
427 }
428
429 // Returns u <- alpha*u where u is a vector and alpha is a scalar
430 void scale(std::vector<Real> &u, const Real alpha=0.0) {
431 int size = static_cast<int>(u.size());
432 for (int i=0; i<size; i++) {
433 u[i] *= alpha;
434 }
435 }
436/*************************************************************/
437/********** END PRIVATE MEMBER FUNCTION DECLARATION **********/
438/*************************************************************/
439
440public:
442
443 int getNumSolves(void) const {
444 return num_solves_;
445 }
446
447 void value(ROL::Vector<Real> &c, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
448 ROL::Ptr<std::vector<Real> > cp = dynamic_cast<ROL::StdVector<Real>&>(c).getVector();
449 ROL::Ptr<const std::vector<Real> > up = dynamic_cast<const ROL::StdVector<Real>&>(u).getVector();
450 ROL::Ptr<const std::vector<Real> > zp = dynamic_cast<const ROL::StdVector<Real>&>(z).getVector();
451 // Apply PDE Jacobian
452 FEM_->apply_jacobian_1(*cp, *up, this->getParameter());
453 // Get Right Hand Side
454 std::vector<Real> F(FEM_->nu(),0.0);
455 FEM_->build_force(F,this->getParameter());
456 std::vector<Real> Bz(FEM_->nu(),0.0);
457 FEM_->apply_jacobian_2(Bz,*zp,this->getParameter());
458 plus(F,Bz);
459 // Add Right Hand Side to PDE Term
460 plus(*cp,F,-1.0);
461 }
462
463 void solve(ROL::Vector<Real> &c, ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
464 ROL::Ptr<std::vector<Real> > cp = dynamic_cast<ROL::StdVector<Real>&>(c).getVector();
465 ROL::Ptr<std::vector<Real> > up = dynamic_cast<ROL::StdVector<Real>&>(u).getVector();
466 ROL::Ptr<const std::vector<Real> > zp = dynamic_cast<const ROL::StdVector<Real>&>(z).getVector();
467 // Get PDE Jacobian
468 std::vector<Real> dl(FEM_->nu()-1,0.0);
469 std::vector<Real> d(FEM_->nu(),0.0);
470 std::vector<Real> du(FEM_->nu()-1,0.0);
471 FEM_->build_jacobian_1(dl,d,du,this->getParameter());
472 // Get Right Hand Side
473 std::vector<Real> F(FEM_->nu(),0.0);
474 FEM_->build_force(F,this->getParameter());
475 std::vector<Real> Bz(FEM_->nu(),0.0);
476 FEM_->apply_jacobian_2(Bz,*zp,this->getParameter());
477 plus(F,Bz);
478 // Solve solve state
479 FEM_->linear_solve(*up,dl,d,du,F);
480 num_solves_++;
481 // Compute residual
482 value(c,u,z,tol);
483 }
484
486 const ROL::Vector<Real> &z, Real &tol) {
487 ROL::Ptr<std::vector<Real> > jvp = dynamic_cast<ROL::StdVector<Real>&>(jv).getVector();
488 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
489 FEM_->apply_jacobian_1(*jvp, *vp, this->getParameter());
490 }
491
493 const ROL::Vector<Real> &z, Real &tol) {
494 ROL::Ptr<std::vector<Real> > jvp = dynamic_cast<ROL::StdVector<Real>&>(jv).getVector();
495 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
496 FEM_->apply_jacobian_2(*jvp, *vp, this->getParameter());
497 scale(*jvp,-1.0);
498 }
499
501 const ROL::Vector<Real> &z, Real &tol) {
502 ROL::Ptr<std::vector<Real> > jvp = dynamic_cast<ROL::StdVector<Real>&>(jv).getVector();
503 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
504 // Get PDE Jacobian
505 std::vector<Real> dl(FEM_->nu()-1,0.0);
506 std::vector<Real> d(FEM_->nu(),0.0);
507 std::vector<Real> du(FEM_->nu()-1,0.0);
508 FEM_->build_jacobian_1(dl,d,du,this->getParameter());
509 // Solve solve state
510 FEM_->linear_solve(*jvp,dl,d,du,*vp);
511 num_solves_++;
512 }
513
515 const ROL::Vector<Real> &z, Real &tol) {
516 applyJacobian_1(jv,v,u,z,tol);
517 }
518
520 const ROL::Vector<Real> &z, Real &tol) {
521 ROL::Ptr<std::vector<Real> > jvp = dynamic_cast<ROL::StdVector<Real>&>(jv).getVector();
522 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
523 FEM_->apply_adjoint_jacobian_2(*jvp, *vp, this->getParameter());
524 scale(*jvp,-1.0);
525 }
526
528 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
529 applyInverseJacobian_1(jv,v,u,z,tol);
530 }
531
533 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
534 ahwv.zero();
535 }
536
538 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
539 ahwv.zero();
540 }
541
543 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
544 ahwv.zero();
545 }
546
548 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol) {
549 ahwv.zero();
550 }
551};
552
553// Class BurgersObjective contains the necessary information
554// to compute the value and gradient of the objective function.
555template<class Real>
557private:
558 const ROL::Ptr<FEM<Real> > FEM_;
559 const Real alpha_;
560
561/***************************************************************/
562/********** BEGIN PRIVATE MEMBER FUNCTION DECLARATION **********/
563/***************************************************************/
564 // Evaluates the discretized L2 inner product of two vectors.
565 Real dot(const std::vector<Real> &x, const std::vector<Real> &y) {
566 Real ip = 0.0;
567 int size = static_cast<int>(x.size());
568 for (int i=0; i<size; i++) {
569 ip += x[i]*y[i];
570 }
571 return ip;
572 }
573
574 // Returns u <- alpha*u where u is a vector and alpha is a scalar
575 void scale(std::vector<Real> &u, const Real alpha=0.0) {
576 int size = static_cast<int>(u.size());
577 for (int i=0; i<size; i++) {
578 u[i] *= alpha;
579 }
580 }
581/*************************************************************/
582/********** END PRIVATE MEMBER FUNCTION DECLARATION **********/
583/*************************************************************/
584
585public:
586 DiffusionObjective(const ROL::Ptr<FEM<Real> > fem, const Real alpha = 1.e-4)
587 : FEM_(fem), alpha_(alpha) {}
588
589 Real value( const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
590 ROL::Ptr<const std::vector<Real> > up = dynamic_cast<const ROL::StdVector<Real>&>(u).getVector();
591 ROL::Ptr<const std::vector<Real> > zp = dynamic_cast<const ROL::StdVector<Real>&>(z).getVector();
592 int nz = FEM_->nz(), nu = FEM_->nu();
593 // COMPUTE CONTROL PENALTY
594 std::vector<Real> Mz(nz);
595 FEM_->apply_mass_control(Mz,*zp);
596 Real zval = alpha_*0.5*dot(Mz,*zp);
597 // COMPUTE STATE TRACKING TERM
598 std::vector<Real> diff(nu);
599 for (int i=0; i<nu; i++) {
600 diff[i] = ((*up)[i]-FEM_->evaluate_target(i+1,this->getParameter()));
601 }
602 std::vector<Real> Mu(nu);
603 FEM_->apply_mass_state(Mu,diff,this->getParameter());
604 Real uval = 0.5*dot(Mu,diff);
605 return uval+zval;
606 }
607
608 void gradient_1( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
609 ROL::Ptr<std::vector<Real> > gp = dynamic_cast<ROL::StdVector<Real>&>(g).getVector();
610 ROL::Ptr<const std::vector<Real> > up = dynamic_cast<const ROL::StdVector<Real>&>(u).getVector();
611 int nu = FEM_->nu();
612 // COMPUTE GRADIENT
613 std::vector<Real> diff(nu);
614 for (int i=0; i<nu; i++) {
615 diff[i] = ((*up)[i]-FEM_->evaluate_target(i+1,this->getParameter()));
616 }
617 FEM_->apply_mass_state(*gp,diff,this->getParameter());
618 }
619
620 void gradient_2( ROL::Vector<Real> &g, const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
621 ROL::Ptr<std::vector<Real> > gp = dynamic_cast<ROL::StdVector<Real>&>(g).getVector();
622 ROL::Ptr<const std::vector<Real> > zp = dynamic_cast<const ROL::StdVector<Real>&>(z).getVector();
623 // COMPUTE GRADIENT
624 FEM_->apply_mass_control(*gp,*zp);
625 scale(*gp,alpha_);
626 }
627
629 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
630 ROL::Ptr<std::vector<Real> > hvp = dynamic_cast<ROL::StdVector<Real>&>(hv).getVector();
631 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
632 // COMPUTE HESSVEC
633 FEM_->apply_mass_state(*hvp,*vp,this->getParameter());
634 }
635
637 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
638 hv.zero();
639 }
640
642 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
643 hv.zero();
644 }
645
647 const ROL::Vector<Real> &u, const ROL::Vector<Real> &z, Real &tol ) {
648 ROL::Ptr<std::vector<Real> > hvp = dynamic_cast<ROL::StdVector<Real>&>(hv).getVector();
649 ROL::Ptr<const std::vector<Real> > vp = dynamic_cast<const ROL::StdVector<Real>&>(v).getVector();
650 // COMPUTE HESSVEC
651 FEM_->apply_mass_control(*hvp,*vp);
652 scale(*hvp,alpha_);
653 }
654
655};
Contains definitions of custom data types in ROL.
void applyAdjointHessian_11(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 simulation-space derivative of the adjoint of the constraint simulation-space Jacobian at ...
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 optimization-space derivative of the adjoint of the constraint simulation-space Jacobian at...
const ROL::Ptr< FEM< Real > > FEM_
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 .
DiffusionConstraint(const ROL::Ptr< FEM< Real > > &FEM)
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 .
void scale(std::vector< Real > &u, const Real alpha=0.0)
void applyInverseAdjointJacobian_1(ROL::Vector< Real > &jv, 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 .
void applyInverseJacobian_1(ROL::Vector< Real > &jv, 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 .
void value(ROL::Vector< Real > &c, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Evaluate the constraint operator at .
void applyAdjointJacobian_1(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 the vector . This is the primary inter...
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 simulation-space derivative of the adjoint of the constraint optimization-space Jacobian at...
void plus(std::vector< Real > &u, const std::vector< Real > &s, const Real alpha=1.0)
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 optimization-space derivative of the adjoint of the constraint optimization-space Jacobian ...
void solve(ROL::Vector< Real > &c, ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Given , solve for .
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...
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.
const ROL::Ptr< FEM< Real > > FEM_
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.
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.
void hessVec_21(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
void hessVec_22(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
DiffusionObjective(const ROL::Ptr< FEM< Real > > fem, const Real alpha=1.e-4)
Real value(const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Compute value.
void hessVec_12(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Real dot(const std::vector< Real > &x, const std::vector< Real > &y)
void scale(std::vector< Real > &u, const Real alpha=0.0)
void build_mesh(std::vector< Real > &x, const std::vector< Real > &param)
std::vector< Real > pts_
void build_mesh(std::vector< Real > &x)
void apply_adjoint_jacobian_2(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &param)
void apply_jacobian_2(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &param)
FEM(int nx=128, Real kl=0.1, Real kr=10.0)
void apply_jacobian_1(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &param)
void apply_inverse_mass_control(std::vector< Real > &Mv, const std::vector< Real > &v)
Real evaluate_target(int i, const std::vector< Real > &param)
void apply_mass_state(std::vector< Real > &Mv, const std::vector< Real > &v, const std::vector< Real > &param)
void build_jacobian_1(std::vector< Real > &dl, std::vector< Real > &d, std::vector< Real > &du, const std::vector< Real > &param)
std::vector< Real > wts_
void build_force(std::vector< Real > &F, const std::vector< Real > &param)
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)
void apply_mass_control(std::vector< Real > &Mv, const std::vector< Real > &v)
Defines the constraint operator interface for simulation-based optimization.
const std::vector< Real > getParameter(void) const
Provides the interface to evaluate simulation-based objective functions.
const std::vector< Real > getParameter(void) const
Provides the ROL::Vector interface for scalar values, to be used, for example, with scalar constraint...
Defines the linear algebra or vector space interface.
virtual void zero()
Set to zero vector.