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"
19 #include "ROL_Objective_SimOpt.hpp"
21 
22 
23 template<class Real>
24 class FEM {
25 private:
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_;
32 public:
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 
411 template<class Real>
413 private:
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 
440 public:
441  DiffusionConstraint(const ROL::Ptr<FEM<Real> > &FEM) : FEM_(FEM), num_solves_(0) {}
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.
555 template<class Real>
557 private:
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 
585 public:
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 };
std::vector< Real > pts_
Provides the interface to evaluate simulation-based objective functions.
void scale(std::vector< Real > &u, const Real alpha=0.0)
void plus(std::vector< Real > &u, const std::vector< Real > &s, const Real alpha=1.0)
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.
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)
Contains definitions of custom data types in ROL.
DiffusionConstraint(const ROL::Ptr< FEM< Real > > &FEM)
const std::vector< Real > getParameter(void) const
void value(ROL::Vector< Real > &c, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Evaluate the constraint operator at .
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 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 apply_jacobian_2(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &param)
Real dot(const std::vector< Real > &x, const std::vector< Real > &y)
virtual void zero()
Set to zero vector.
Definition: ROL_Vector.hpp:133
Defines the linear algebra or vector space interface.
Definition: ROL_Vector.hpp:46
std::vector< Real > wts_
void hessVec_22(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
void build_mesh(std::vector< Real > &x, const std::vector< Real > &param)
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 hessVec_12(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Real value(const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Compute value.
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...
FEM(int nx=128, Real kl=0.1, Real kr=10.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 ...
DiffusionObjective(const ROL::Ptr< FEM< Real > > fem, const Real alpha=1.e-4)
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 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 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 .
void apply_mass_control(std::vector< Real > &Mv, const std::vector< Real > &v)
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 scale(std::vector< Real > &u, const Real alpha=0.0)
void apply_jacobian_1(std::vector< Real > &jv, const std::vector< Real > &v, const std::vector< Real > &param)
void hessVec_21(ROL::Vector< Real > &hv, const ROL::Vector< Real > &v, const ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
const std::vector< Real > getParameter(void) const
void solve(ROL::Vector< Real > &c, ROL::Vector< Real > &u, const ROL::Vector< Real > &z, Real &tol)
Given , solve for .
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.
Defines the constraint operator interface for simulation-based optimization.
const ROL::Ptr< FEM< Real > > FEM_
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 build_jacobian_1(std::vector< Real > &dl, std::vector< Real > &d, std::vector< Real > &du, 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_state(std::vector< Real > &Mv, const std::vector< Real > &v, const std::vector< Real > &param)
void apply_inverse_mass_control(std::vector< Real > &Mv, const std::vector< Real > &v)
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...
const ROL::Ptr< FEM< Real > > FEM_
void build_force(std::vector< Real > &F, const std::vector< Real > &param)
Real evaluate_target(int i, const std::vector< Real > &param)