MittelmannBndryCntrlNeum.hpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // Copyright (C) 2005, 2006 International Business Machines and others.
  2. // All Rights Reserved.
  3. // This code is published under the Eclipse Public License.
  4. //
  5. // $Id: MittelmannBndryCntrlNeum.hpp 2005 2011-06-06 12:55:16Z stefan $
  6. //
  7. // Authors: Andreas Waechter IBM 2005-10-18
  8. // based on MyNLP.hpp
  9. #ifndef __MITTELMANNBNDRYCNTRLNEUM_HPP__
  10. #define __MITTELMANNBNDRYCNTRLNEUM_HPP__
  11. #include "IpTNLP.hpp"
  12. #include "RegisteredTNLP.hpp"
  13. #ifdef HAVE_CONFIG_H
  14. #include "config.h"
  15. #else
  16. #include "configall_system.h"
  17. #endif
  18. #ifdef HAVE_CMATH
  19. # include <cmath>
  20. #else
  21. # ifdef HAVE_MATH_H
  22. # include <math.h>
  23. # else
  24. # error "don't have header file for math"
  25. # endif
  26. #endif
  27. #ifdef HAVE_CSTDIO
  28. # include <cstdio>
  29. #else
  30. # ifdef HAVE_STDIO_H
  31. # include <stdio.h>
  32. # else
  33. # error "don't have header file for stdio"
  34. # endif
  35. #endif
  36. using namespace Ipopt;
  37. /** Base class for boundary control problems with Neumann boundary
  38. * conditions, as formulated by Hans Mittelmann as Examples 5-8 in
  39. * "Optimization Techniques for Solving Elliptic Control Problems
  40. * with Control and State Constraints. Part 1: Boundary Control"
  41. */
  42. class MittelmannBndryCntrlNeumBase : public RegisteredTNLP
  43. {
  44. public:
  45. /** Constructor. N is the number of mesh points in one dimension
  46. * (excluding boundary). */
  47. MittelmannBndryCntrlNeumBase();
  48. /** Default destructor */
  49. virtual ~MittelmannBndryCntrlNeumBase();
  50. /**@name Overloaded from TNLP */
  51. //@{
  52. /** Method to return some info about the nlp */
  53. virtual bool get_nlp_info(Index& n, Index& m, Index& nnz_jac_g,
  54. Index& nnz_h_lag, IndexStyleEnum& index_style);
  55. /** Method to return the bounds for my problem */
  56. virtual bool get_bounds_info(Index n, Number* x_l, Number* x_u,
  57. Index m, Number* g_l, Number* g_u);
  58. /** Method to return the starting point for the algorithm */
  59. virtual bool get_starting_point(Index n, bool init_x, Number* x,
  60. bool init_z, Number* z_L, Number* z_U,
  61. Index m, bool init_lambda,
  62. Number* lambda);
  63. /** Method to return the objective value */
  64. virtual bool eval_f(Index n, const Number* x, bool new_x, Number& obj_value);
  65. /** Method to return the gradient of the objective */
  66. virtual bool eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f);
  67. /** Method to return the constraint residuals */
  68. virtual bool eval_g(Index n, const Number* x, bool new_x, Index m, Number* g);
  69. /** Method to return:
  70. * 1) The structure of the jacobian (if "values" is NULL)
  71. * 2) The values of the jacobian (if "values" is not NULL)
  72. */
  73. virtual bool eval_jac_g(Index n, const Number* x, bool new_x,
  74. Index m, Index nele_jac, Index* iRow, Index *jCol,
  75. Number* values);
  76. /** Method to return:
  77. * 1) The structure of the hessian of the lagrangian (if "values" is NULL)
  78. * 2) The values of the hessian of the lagrangian (if "values" is not NULL)
  79. */
  80. virtual bool eval_h(Index n, const Number* x, bool new_x,
  81. Number obj_factor, Index m, const Number* lambda,
  82. bool new_lambda, Index nele_hess, Index* iRow,
  83. Index* jCol, Number* values);
  84. //@}
  85. /** Method for returning scaling parameters */
  86. virtual bool get_scaling_parameters(Number& obj_scaling,
  87. bool& use_x_scaling, Index n,
  88. Number* x_scaling,
  89. bool& use_g_scaling, Index m,
  90. Number* g_scaling);
  91. /** @name Solution Methods */
  92. //@{
  93. /** This method is called after the optimization, and could write an
  94. * output file with the optimal profiles */
  95. virtual void finalize_solution(SolverReturn status,
  96. Index n, const Number* x, const Number* z_L, const Number* z_U,
  97. Index m, const Number* g, const Number* lambda,
  98. Number obj_value,
  99. const IpoptData* ip_data,
  100. IpoptCalculatedQuantities* ip_cq);
  101. //@}
  102. protected:
  103. /** Method for setting the internal parameters that define the
  104. * problem. It must be called by the child class in its
  105. * implementation of InitializeParameters. */
  106. void SetBaseParameters(Index N, Number alpha, Number lb_y,
  107. Number ub_y, Number lb_u, Number ub_u,
  108. Number u_init);
  109. /**@name Functions that defines a particular instance. */
  110. //@{
  111. /** Target profile function for y (and initial guess function) */
  112. virtual Number y_d_cont(Number x1, Number x2) const =0;
  113. /** Forcing function for the elliptic equation */
  114. virtual Number d_cont(Number x1, Number x2, Number y) const =0;
  115. /** First partial derivative of forcing function w.r.t. y */
  116. virtual Number d_cont_dy(Number x1, Number x2, Number y) const =0;
  117. /** Second partial derivative of forcing function w.r.t. y,y */
  118. virtual Number d_cont_dydy(Number x1, Number x2, Number y) const =0;
  119. /** returns true if second partial derivative of d_cont
  120. * w.r.t. y,y is always zero. */
  121. virtual bool d_cont_dydy_alwayszero() const =0;
  122. /** Function in Neuman boundary condition */
  123. virtual Number b_cont(Number x1, Number x2, Number y, Number u) const =0;
  124. /** First partial derivative of b_cont w.r.t. y */
  125. virtual Number b_cont_dy(Number x1, Number x2, Number y, Number u) const =0;
  126. /** First partial derivative of b_cont w.r.t. u */
  127. virtual Number b_cont_du(Number x1, Number x2, Number y, Number u) const =0;
  128. /** Second partial derivative of b_cont w.r.t. y,y */
  129. virtual Number b_cont_dydy(Number x1, Number x2, Number y, Number u) const =0;
  130. /** returns true if second partial derivative of b_cont
  131. * w.r.t. y,y is always zero. */
  132. virtual bool b_cont_dydy_alwayszero() const =0;
  133. //@}
  134. private:
  135. /**@name Methods to block default compiler methods.
  136. * The compiler automatically generates the following three methods.
  137. * Since the default compiler implementation is generally not what
  138. * you want (for all but the most simple classes), we usually
  139. * put the declarations of these methods in the private section
  140. * and never implement them. This prevents the compiler from
  141. * implementing an incorrect "default" behavior without us
  142. * knowing. (See Scott Meyers book, "Effective C++")
  143. *
  144. */
  145. //@{
  146. MittelmannBndryCntrlNeumBase(const MittelmannBndryCntrlNeumBase&);
  147. MittelmannBndryCntrlNeumBase& operator=(const MittelmannBndryCntrlNeumBase&);
  148. //@}
  149. /**@name Problem specification */
  150. //@{
  151. /** Number of mesh points in one dimension (excluding boundary) */
  152. Index N_;
  153. /** Step size */
  154. Number h_;
  155. /** h_ squaredd */
  156. Number hh_;
  157. /** overall lower bound on y */
  158. Number lb_y_;
  159. /** overall upper bound on y */
  160. Number ub_y_;
  161. /** overall lower bound on u */
  162. Number lb_u_;
  163. /** overall upper bound on u */
  164. Number ub_u_;
  165. /** Initial value for the constrols u */
  166. Number u_init_;
  167. /** Weighting parameter for the control target deviation functional
  168. * in the objective */
  169. Number alpha_;
  170. /** Array for the target profile for y */
  171. Number* y_d_;
  172. //@}
  173. /**@name Auxilliary methods */
  174. //@{
  175. /** Translation of mesh point indices to NLP variable indices for
  176. * y(x_ij) */
  177. inline Index y_index(Index i, Index j) const
  178. {
  179. return j + (N_+2)*i;
  180. }
  181. /** Translation of mesh point indices to NLP variable indices for
  182. * u(x_ij) on {0} x (0,1) boudnary*/
  183. inline Index u0j_index(Index j) const
  184. {
  185. return (N_+2)*(N_+2) + j-1;
  186. }
  187. /** Translation of mesh point indices to NLP variable indices for
  188. * u(x_ij) on {1} x (0,1) boudnary*/
  189. inline Index u1j_index(Index j) const
  190. {
  191. return (N_+2)*(N_+2) + N_ + j-1;
  192. }
  193. /** Translation of mesh point indices to NLP variable indices for
  194. * u(x_ij) on (0,1) x {0} boudnary*/
  195. inline Index ui0_index(Index j) const
  196. {
  197. return (N_+2)*(N_+2) + 2*N_ + j-1;
  198. }
  199. /** Translation of mesh point indices to NLP variable indices for
  200. * u(x_ij) on (0,1) x {1} boudnary*/
  201. inline Index ui1_index(Index j) const
  202. {
  203. return (N_+2)*(N_+2) + 3*N_ + j-1;
  204. }
  205. /** Compute the grid coordinate for given index in x1 direction */
  206. inline Number x1_grid(Index i) const
  207. {
  208. return h_*(Number)i;
  209. }
  210. /** Compute the grid coordinate for given index in x2 direction */
  211. inline Number x2_grid(Index j) const
  212. {
  213. return h_*(Number)j;
  214. }
  215. //@}
  216. };
  217. /** Class implementating Example 5 */
  218. class MittelmannBndryCntrlNeum1 : public MittelmannBndryCntrlNeumBase
  219. {
  220. public:
  221. MittelmannBndryCntrlNeum1()
  222. {}
  223. virtual ~MittelmannBndryCntrlNeum1()
  224. {}
  225. virtual bool InitializeProblem(Index N)
  226. {
  227. if (N<1) {
  228. printf("N has to be at least 1.");
  229. return false;
  230. }
  231. Number alpha = 0.01;
  232. Number lb_y = -1e20;
  233. Number ub_y = 2.071;
  234. Number lb_u = 3.7;
  235. Number ub_u = 4.5;
  236. Number u_init = (ub_u+lb_u)/2.;
  237. SetBaseParameters(N, alpha, lb_y, ub_y, lb_u, ub_u, u_init);
  238. return true;
  239. }
  240. protected:
  241. /** Target profile function for y */
  242. virtual Number y_d_cont(Number x1, Number x2) const
  243. {
  244. return 2. - 2.*(x1*(x1-1.) + x2*(x2-1.));
  245. }
  246. /** Forcing function for the elliptic equation */
  247. virtual Number d_cont(Number x1, Number x2, Number y) const
  248. {
  249. return 0.;
  250. }
  251. /** First partial derivative of forcing function w.r.t. y */
  252. virtual Number d_cont_dy(Number x1, Number x2, Number y) const
  253. {
  254. return 0.;
  255. }
  256. /** Second partial derivative of forcing function w.r.t y,y */
  257. virtual Number d_cont_dydy(Number x1, Number x2, Number y) const
  258. {
  259. return 0.;
  260. }
  261. /** returns true if second partial derivative of d_cont
  262. * w.r.t. y,y is always zero. */
  263. virtual bool d_cont_dydy_alwayszero() const
  264. {
  265. return true;
  266. }
  267. /** Function in Neuman boundary condition */
  268. virtual Number b_cont(Number x1, Number x2, Number y, Number u) const
  269. {
  270. return u - y*y;
  271. }
  272. /** First partial derivative of b_cont w.r.t. y */
  273. virtual Number b_cont_dy(Number x1, Number x2, Number y, Number u) const
  274. {
  275. return - 2.*y;
  276. }
  277. /** First partial derivative of b_cont w.r.t. u */
  278. virtual Number b_cont_du(Number x1, Number x2, Number y, Number u) const
  279. {
  280. return 1.;
  281. }
  282. /** Second partial derivative of b_cont w.r.t. y,y */
  283. virtual Number b_cont_dydy(Number x1, Number x2, Number y, Number u) const
  284. {
  285. return -2.;
  286. }
  287. /** returns true if second partial derivative of b_cont
  288. * w.r.t. y,y is always zero. */
  289. virtual bool b_cont_dydy_alwayszero() const
  290. {
  291. return false;
  292. }
  293. private:
  294. /**@name hide implicitly defined contructors copy operators */
  295. //@{
  296. MittelmannBndryCntrlNeum1(const MittelmannBndryCntrlNeum1&);
  297. MittelmannBndryCntrlNeum1& operator=(const MittelmannBndryCntrlNeum1&);
  298. //@}
  299. };
  300. /** Class implementating Example 6 */
  301. class MittelmannBndryCntrlNeum2 : public MittelmannBndryCntrlNeumBase
  302. {
  303. public:
  304. MittelmannBndryCntrlNeum2()
  305. {}
  306. virtual ~MittelmannBndryCntrlNeum2()
  307. {}
  308. virtual bool InitializeProblem(Index N)
  309. {
  310. if (N<1) {
  311. printf("N has to be at least 1.");
  312. return false;
  313. }
  314. Number alpha = 0.;
  315. Number lb_y = -1e20;
  316. Number ub_y = 2.835;
  317. Number lb_u = 6.;
  318. Number ub_u = 9.;
  319. Number u_init = (ub_u+lb_u)/2.;
  320. SetBaseParameters(N, alpha, lb_y, ub_y, lb_u, ub_u, u_init);
  321. return true;
  322. }
  323. protected:
  324. /** Target profile function for y */
  325. virtual Number y_d_cont(Number x1, Number x2) const
  326. {
  327. return 2. - 2.*(x1*(x1-1.) + x2*(x2-1.));
  328. }
  329. /** Forcing function for the elliptic equation */
  330. virtual Number d_cont(Number x1, Number x2, Number y) const
  331. {
  332. return 0.;
  333. }
  334. /** First partial derivative of forcing function w.r.t. y */
  335. virtual Number d_cont_dy(Number x1, Number x2, Number y) const
  336. {
  337. return 0.;
  338. }
  339. /** Second partial derivative of forcing function w.r.t y,y */
  340. virtual Number d_cont_dydy(Number x1, Number x2, Number y) const
  341. {
  342. return 0.;
  343. }
  344. /** returns true if second partial derivative of d_cont
  345. * w.r.t. y,y is always zero. */
  346. virtual bool d_cont_dydy_alwayszero() const
  347. {
  348. return true;
  349. }
  350. /** Function in Neuman boundary condition */
  351. virtual Number b_cont(Number x1, Number x2, Number y, Number u) const
  352. {
  353. return u - y*y;
  354. }
  355. /** First partial derivative of b_cont w.r.t. y */
  356. virtual Number b_cont_dy(Number x1, Number x2, Number y, Number u) const
  357. {
  358. return - 2.*y;
  359. }
  360. /** First partial derivative of b_cont w.r.t. u */
  361. virtual Number b_cont_du(Number x1, Number x2, Number y, Number u) const
  362. {
  363. return 1.;
  364. }
  365. /** Second partial derivative of b_cont w.r.t. y,y */
  366. virtual Number b_cont_dydy(Number x1, Number x2, Number y, Number u) const
  367. {
  368. return -2.;
  369. }
  370. /** returns true if second partial derivative of b_cont
  371. * w.r.t. y,y is always zero. */
  372. virtual bool b_cont_dydy_alwayszero() const
  373. {
  374. return false;
  375. }
  376. private:
  377. /**@name hide implicitly defined contructors copy operators */
  378. //@{
  379. MittelmannBndryCntrlNeum2(const MittelmannBndryCntrlNeum2&);
  380. MittelmannBndryCntrlNeum2& operator=(const MittelmannBndryCntrlNeum2&);
  381. //@}
  382. };
  383. /** Class implementating Example 7 */
  384. class MittelmannBndryCntrlNeum3 : public MittelmannBndryCntrlNeumBase
  385. {
  386. public:
  387. MittelmannBndryCntrlNeum3()
  388. {}
  389. virtual ~MittelmannBndryCntrlNeum3()
  390. {}
  391. virtual bool InitializeProblem(Index N)
  392. {
  393. if (N<1) {
  394. printf("N has to be at least 1.");
  395. return false;
  396. }
  397. Number alpha = 0.01;
  398. Number lb_y = -1e20;
  399. Number ub_y = 2.7;
  400. Number lb_u = 1.8;
  401. Number ub_u = 2.5;
  402. Number u_init = (ub_u+lb_u)/2.;
  403. SetBaseParameters(N, alpha, lb_y, ub_y, lb_u, ub_u, u_init);
  404. return true;
  405. }
  406. protected:
  407. /** Target profile function for y */
  408. virtual Number y_d_cont(Number x1, Number x2) const
  409. {
  410. return 2. - 2.*(x1*(x1-1.) + x2*(x2-1.));
  411. }
  412. /** Forcing function for the elliptic equation */
  413. virtual Number d_cont(Number x1, Number x2, Number y) const
  414. {
  415. return y*y*y-y;
  416. }
  417. /** First partial derivative of forcing function w.r.t. y */
  418. virtual Number d_cont_dy(Number x1, Number x2, Number y) const
  419. {
  420. return 3.*y*y-1.;
  421. }
  422. /** Second partial derivative of forcing function w.r.t y,y */
  423. virtual Number d_cont_dydy(Number x1, Number x2, Number y) const
  424. {
  425. return 6.*y;
  426. }
  427. /** returns true if second partial derivative of d_cont
  428. * w.r.t. y,y is always zero. */
  429. virtual bool d_cont_dydy_alwayszero() const
  430. {
  431. return false;
  432. }
  433. /** Function in Neuman boundary condition */
  434. virtual Number b_cont(Number x1, Number x2, Number y, Number u) const
  435. {
  436. return u;
  437. }
  438. /** First partial derivative of b_cont w.r.t. y */
  439. virtual Number b_cont_dy(Number x1, Number x2, Number y, Number u) const
  440. {
  441. return 0.;
  442. }
  443. /** First partial derivative of b_cont w.r.t. u */
  444. virtual Number b_cont_du(Number x1, Number x2, Number y, Number u) const
  445. {
  446. return 1.;
  447. }
  448. /** Second partial derivative of b_cont w.r.t. y,y */
  449. virtual Number b_cont_dydy(Number x1, Number x2, Number y, Number u) const
  450. {
  451. return 0.;
  452. }
  453. /** returns true if second partial derivative of b_cont
  454. * w.r.t. y,y is always zero. */
  455. virtual bool b_cont_dydy_alwayszero() const
  456. {
  457. return true;
  458. }
  459. private:
  460. /**@name hide implicitly defined contructors copy operators */
  461. //@{
  462. MittelmannBndryCntrlNeum3(const MittelmannBndryCntrlNeum3&);
  463. MittelmannBndryCntrlNeum3& operator=(const MittelmannBndryCntrlNeum3&);
  464. //@}
  465. };
  466. /** Class implementating Example 8 */
  467. class MittelmannBndryCntrlNeum4 : public MittelmannBndryCntrlNeumBase
  468. {
  469. public:
  470. MittelmannBndryCntrlNeum4()
  471. {}
  472. virtual ~MittelmannBndryCntrlNeum4()
  473. {}
  474. virtual bool InitializeProblem(Index N)
  475. {
  476. if (N<1) {
  477. printf("N has to be at least 1.");
  478. return false;
  479. }
  480. Number alpha = 0.;
  481. Number lb_y = -1e20;
  482. Number ub_y = 2.7;
  483. Number lb_u = 1.8;
  484. Number ub_u = 2.5;
  485. Number u_init = (ub_u+lb_u)/2.;
  486. SetBaseParameters(N, alpha, lb_y, ub_y, lb_u, ub_u, u_init);
  487. return true;
  488. }
  489. protected:
  490. /** Target profile function for y */
  491. virtual Number y_d_cont(Number x1, Number x2) const
  492. {
  493. return 2. - 2.*(x1*(x1-1.) + x2*(x2-1.));
  494. }
  495. /** Forcing function for the elliptic equation */
  496. virtual Number d_cont(Number x1, Number x2, Number y) const
  497. {
  498. return y*y*y-y;
  499. }
  500. /** First partial derivative of forcing function w.r.t. y */
  501. virtual Number d_cont_dy(Number x1, Number x2, Number y) const
  502. {
  503. return 3.*y*y-1.;
  504. }
  505. /** Second partial derivative of forcing function w.r.t y,y */
  506. virtual Number d_cont_dydy(Number x1, Number x2, Number y) const
  507. {
  508. return 6.*y;
  509. }
  510. /** returns true if second partial derivative of d_cont
  511. * w.r.t. y,y is always zero. */
  512. virtual bool d_cont_dydy_alwayszero() const
  513. {
  514. return false;
  515. }
  516. /** Function in Neuman boundary condition */
  517. virtual Number b_cont(Number x1, Number x2, Number y, Number u) const
  518. {
  519. return u;
  520. }
  521. /** First partial derivative of b_cont w.r.t. y */
  522. virtual Number b_cont_dy(Number x1, Number x2, Number y, Number u) const
  523. {
  524. return 0.;
  525. }
  526. /** First partial derivative of b_cont w.r.t. u */
  527. virtual Number b_cont_du(Number x1, Number x2, Number y, Number u) const
  528. {
  529. return 1.;
  530. }
  531. /** Second partial derivative of b_cont w.r.t. y,y */
  532. virtual Number b_cont_dydy(Number x1, Number x2, Number y, Number u) const
  533. {
  534. return 0.;
  535. }
  536. /** returns true if second partial derivative of b_cont
  537. * w.r.t. y,y is always zero. */
  538. virtual bool b_cont_dydy_alwayszero() const
  539. {
  540. return true;
  541. }
  542. private:
  543. /**@name hide implicitly defined contructors copy operators */
  544. //@{
  545. MittelmannBndryCntrlNeum4(const MittelmannBndryCntrlNeum4&);
  546. MittelmannBndryCntrlNeum4& operator=(const MittelmannBndryCntrlNeum4&);
  547. //@}
  548. };
  549. #endif