MittelmannBndryCntrlDiri.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  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: MittelmannBndryCntrlDiri.cpp 2005 2011-06-06 12:55:16Z stefan $
  6. //
  7. // Authors: Andreas Waechter IBM 2005-10-18
  8. // based on MyNLP.cpp
  9. #include "MittelmannBndryCntrlDiri.hpp"
  10. #ifdef HAVE_CASSERT
  11. # include <cassert>
  12. #else
  13. # ifdef HAVE_ASSERT_H
  14. # include <assert.h>
  15. # else
  16. # error "don't have header file for assert"
  17. # endif
  18. #endif
  19. using namespace Ipopt;
  20. /* Constructor. */
  21. MittelmannBndryCntrlDiriBase::MittelmannBndryCntrlDiriBase()
  22. :
  23. y_d_(NULL)
  24. {}
  25. MittelmannBndryCntrlDiriBase::~MittelmannBndryCntrlDiriBase()
  26. {
  27. delete [] y_d_;
  28. }
  29. void
  30. MittelmannBndryCntrlDiriBase::SetBaseParameters(Index N, Number alpha, Number lb_y,
  31. Number ub_y, Number lb_u, Number ub_u,
  32. Number d_const)
  33. {
  34. N_ = N;
  35. h_ = 1./(N+1);
  36. hh_ = h_*h_;
  37. lb_y_ = lb_y;
  38. ub_y_ = ub_y;
  39. lb_u_ = lb_u;
  40. ub_u_ = ub_u;
  41. d_const_ = d_const;
  42. alpha_ = alpha;
  43. // Initialize the target profile variables
  44. delete [] y_d_;
  45. y_d_ = new Number[(N_+2)*(N_+2)];
  46. for (Index j=0; j<= N_+1; j++) {
  47. for (Index i=0; i<= N_+1; i++) {
  48. y_d_[y_index(i,j)] = y_d_cont(x1_grid(i),x2_grid(j));
  49. }
  50. }
  51. }
  52. bool MittelmannBndryCntrlDiriBase::get_nlp_info(
  53. Index& n, Index& m, Index& nnz_jac_g,
  54. Index& nnz_h_lag, IndexStyleEnum& index_style)
  55. {
  56. // We for each of the N_+2 times N_+2 mesh points we have the value
  57. // of the functions y, including the control parameters on the boundary
  58. n = (N_+2)*(N_+2);
  59. // For each of the N_ times N_ interior mesh points we have the
  60. // discretized PDE.
  61. m = N_*N_;
  62. // y(i,j), y(i-1,j), y(i+1,j), y(i,j-1), y(i,j+1) for each
  63. // of the N_*N_ discretized PDEs
  64. nnz_jac_g = 5*N_*N_;
  65. // diagonal entry for each y(i,j) in the interior
  66. nnz_h_lag = N_*N_;
  67. if (alpha_>0.) {
  68. // and one entry for u(i,j) in the bundary if alpha is not zero
  69. nnz_h_lag += 4*N_;
  70. }
  71. // We use the C indexing style for row/col entries (corresponding to
  72. // the C notation, starting at 0)
  73. index_style = C_STYLE;
  74. return true;
  75. }
  76. bool
  77. MittelmannBndryCntrlDiriBase::get_bounds_info(Index n, Number* x_l, Number* x_u,
  78. Index m, Number* g_l, Number* g_u)
  79. {
  80. // Set overall bounds on the y variables
  81. for (Index i=0; i<=N_+1; i++) {
  82. for (Index j=0; j<=N_+1; j++) {
  83. Index iy = y_index(i,j);
  84. x_l[iy] = lb_y_;
  85. x_u[iy] = ub_y_;
  86. }
  87. }
  88. // Set the overall bounds on the control variables
  89. for (Index i=1; i<=N_; i++) {
  90. Index iu = y_index(i,0);
  91. x_l[iu] = lb_u_;
  92. x_u[iu] = ub_u_;
  93. }
  94. for (Index i=1; i<=N_; i++) {
  95. Index iu = y_index(i,N_+1);
  96. x_l[iu] = lb_u_;
  97. x_u[iu] = ub_u_;
  98. }
  99. for (Index j=1; j<=N_; j++) {
  100. Index iu = y_index(0,j);
  101. x_l[iu] = lb_u_;
  102. x_u[iu] = ub_u_;
  103. }
  104. for (Index j=1; j<=N_; j++) {
  105. Index iu = y_index(N_+1,j);
  106. x_l[iu] = lb_u_;
  107. x_u[iu] = ub_u_;
  108. }
  109. // The values of y on the corners doens't appear anywhere, so we fix
  110. // them to zero
  111. x_l[y_index(0,0)] = x_u[y_index(0,0)] = 0.;
  112. x_l[y_index(0,N_+1)] = x_u[y_index(0,N_+1)] = 0.;
  113. x_l[y_index(N_+1,0)] = x_u[y_index(N_+1,0)] = 0.;
  114. x_l[y_index(N_+1,N_+1)] = x_u[y_index(N_+1,N_+1)] = 0.;
  115. // all discretized PDE constraints have right hand side equal to
  116. // minus the constant value of the function d
  117. for (Index i=0; i<m; i++) {
  118. g_l[i] = -hh_*d_const_;
  119. g_u[i] = -hh_*d_const_;
  120. }
  121. return true;
  122. }
  123. bool
  124. MittelmannBndryCntrlDiriBase::get_starting_point(Index n, bool init_x, Number* x,
  125. bool init_z, Number* z_L, Number* z_U,
  126. Index m, bool init_lambda,
  127. Number* lambda)
  128. {
  129. // Here, we assume we only have starting values for x, if you code
  130. // your own NLP, you can provide starting values for the others if
  131. // you wish.
  132. assert(init_x == true);
  133. assert(init_z == false);
  134. assert(init_lambda == false);
  135. // set all y's to the perfect match with y_d
  136. for (Index i=0; i<= N_+1; i++) {
  137. for (Index j=0; j<= N_+1; j++) {
  138. x[y_index(i,j)] = y_d_[y_index(i,j)]; // 0 in AMPL model
  139. }
  140. }
  141. Number umid = (ub_u_ + lb_u_)/2.;
  142. for (Index i=1; i<=N_; i++) {
  143. Index iu = y_index(i,0);
  144. x[iu] = umid;
  145. }
  146. for (Index i=1; i<=N_; i++) {
  147. Index iu = y_index(i,N_+1);
  148. x[iu] = umid;
  149. }
  150. for (Index j=1; j<=N_; j++) {
  151. Index iu = y_index(0,j);
  152. x[iu] = umid;
  153. }
  154. for (Index j=1; j<=N_; j++) {
  155. Index iu = y_index(N_+1,j);
  156. x[iu] = umid;
  157. }
  158. return true;
  159. }
  160. bool
  161. MittelmannBndryCntrlDiriBase::get_scaling_parameters(Number& obj_scaling,
  162. bool& use_x_scaling, Index n, Number* x_scaling,
  163. bool& use_g_scaling, Index m, Number* g_scaling)
  164. {
  165. obj_scaling = 1./hh_;
  166. use_x_scaling = false;
  167. use_g_scaling = false;
  168. return true;
  169. }
  170. bool
  171. MittelmannBndryCntrlDiriBase::eval_f(Index n, const Number* x,
  172. bool new_x, Number& obj_value)
  173. {
  174. // return the value of the objective function
  175. obj_value = 0.;
  176. // First the integration of y-td over the interior
  177. for (Index i=1; i<=N_; i++) {
  178. for (Index j=1; j<= N_; j++) {
  179. Index iy = y_index(i,j);
  180. Number tmp = x[iy] - y_d_[iy];
  181. obj_value += tmp*tmp;
  182. }
  183. }
  184. obj_value *= hh_/2.;
  185. // Now the integration of u over the boundary
  186. if (alpha_>0.) {
  187. Number usum = 0.;
  188. for (Index i=1; i<=N_; i++) {
  189. Index iu = y_index(i,0);
  190. usum += x[iu]*x[iu];
  191. }
  192. for (Index i=1; i<=N_; i++) {
  193. Index iu = y_index(i,N_+1);
  194. usum += x[iu]*x[iu];
  195. }
  196. for (Index j=1; j<=N_; j++) {
  197. Index iu = y_index(0,j);
  198. usum += x[iu]*x[iu];
  199. }
  200. for (Index j=1; j<=N_; j++) {
  201. Index iu = y_index(N_+1,j);
  202. usum += x[iu]*x[iu];
  203. }
  204. obj_value += alpha_*h_/2.*usum;
  205. }
  206. return true;
  207. }
  208. bool
  209. MittelmannBndryCntrlDiriBase::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
  210. {
  211. // return the gradient of the objective function grad_{x} f(x)
  212. // now let's take care of the nonzero values coming from the
  213. // integrant over the interior
  214. for (Index i=1; i<=N_; i++) {
  215. for (Index j=1; j<= N_; j++) {
  216. Index iy = y_index(i,j);
  217. grad_f[iy] = hh_*(x[iy] - y_d_[iy]);
  218. }
  219. }
  220. // The values for variables on the boundary
  221. if (alpha_>0.) {
  222. for (Index i=1; i<= N_; i++) {
  223. Index iu = y_index(i,0);
  224. grad_f[iu] = alpha_*h_*x[iu];
  225. }
  226. for (Index i=1; i<= N_; i++) {
  227. Index iu = y_index(i,N_+1);
  228. grad_f[iu] = alpha_*h_*x[iu];
  229. }
  230. for (Index j=1; j<= N_; j++) {
  231. Index iu = y_index(0,j);
  232. grad_f[iu] = alpha_*h_*x[iu];
  233. }
  234. for (Index j=1; j<= N_; j++) {
  235. Index iu = y_index(N_+1,j);
  236. grad_f[iu] = alpha_*h_*x[iu];
  237. }
  238. }
  239. else {
  240. for (Index i=1; i<= N_; i++) {
  241. grad_f[y_index(i,0)] = 0.;
  242. }
  243. for (Index i=1; i<= N_; i++) {
  244. grad_f[y_index(i,N_+1)] = 0.;
  245. }
  246. for (Index j=1; j<= N_; j++) {
  247. grad_f[y_index(0,j)] = 0.;
  248. }
  249. for (Index j=1; j<= N_; j++) {
  250. grad_f[y_index(N_+1,j)] = 0.;
  251. }
  252. }
  253. // Nothing on the corner points
  254. grad_f[y_index(0,0)] = 0.;
  255. grad_f[y_index(0,N_+1)] = 0.;
  256. grad_f[y_index(N_+1,0)] = 0.;
  257. grad_f[y_index(N_+1,N_+1)] = 0.;
  258. return true;
  259. }
  260. bool MittelmannBndryCntrlDiriBase::eval_g(Index n, const Number* x, bool new_x,
  261. Index m, Number* g)
  262. {
  263. // return the value of the constraints: g(x)
  264. // compute the discretized PDE for each interior grid point
  265. Index ig = 0;
  266. for (Index i=1; i<=N_; i++) {
  267. for (Index j=1; j<=N_; j++) {
  268. Number val;
  269. // Start with the discretized Laplacian operator
  270. val = 4.* x[y_index(i,j)]
  271. - x[y_index(i-1,j)] - x[y_index(i+1,j)]
  272. - x[y_index(i,j-1)] - x[y_index(i,j+1)];
  273. g[ig] = val;
  274. ig++;
  275. }
  276. }
  277. DBG_ASSERT(ig==m);
  278. return true;
  279. }
  280. bool MittelmannBndryCntrlDiriBase::eval_jac_g(Index n, const Number* x, bool new_x,
  281. Index m, Index nele_jac, Index* iRow, Index *jCol,
  282. Number* values)
  283. {
  284. if (values == NULL) {
  285. // return the structure of the jacobian of the constraints
  286. Index ijac = 0;
  287. Index ig = 0;
  288. for (Index i=1; i<= N_; i++) {
  289. for (Index j=1; j<= N_; j++) {
  290. // y(i,j)
  291. iRow[ijac] = ig;
  292. jCol[ijac] = y_index(i,j);
  293. ijac++;
  294. // y(i-1,j)
  295. iRow[ijac] = ig;
  296. jCol[ijac] = y_index(i-1,j);
  297. ijac++;
  298. // y(i+1,j)
  299. iRow[ijac] = ig;
  300. jCol[ijac] = y_index(i+1,j);
  301. ijac++;
  302. // y(i,j-1)
  303. iRow[ijac] = ig;
  304. jCol[ijac] = y_index(i,j-1);
  305. ijac++;
  306. // y(i,j+1)
  307. iRow[ijac] = ig;
  308. jCol[ijac] = y_index(i,j+1);
  309. ijac++;
  310. ig++;
  311. }
  312. }
  313. DBG_ASSERT(ijac==nele_jac);
  314. }
  315. else {
  316. // return the values of the jacobian of the constraints
  317. Index ijac = 0;
  318. for (Index i=1; i<= N_; i++) {
  319. for (Index j=1; j<= N_; j++) {
  320. // y(i,j)
  321. values[ijac] = 4.;
  322. ijac++;
  323. // y(i-1,j)
  324. values[ijac] = -1.;
  325. ijac++;
  326. // y(i+1,j)
  327. values[ijac] = -1.;
  328. ijac++;
  329. // y(1,j-1)
  330. values[ijac] = -1.;
  331. ijac++;
  332. // y(1,j+1)
  333. values[ijac] = -1.;
  334. ijac++;
  335. }
  336. }
  337. DBG_ASSERT(ijac==nele_jac);
  338. }
  339. return true;
  340. }
  341. bool
  342. MittelmannBndryCntrlDiriBase::eval_h(Index n, const Number* x, bool new_x,
  343. Number obj_factor, Index m,
  344. const Number* lambda,
  345. bool new_lambda, Index nele_hess, Index* iRow,
  346. Index* jCol, Number* values)
  347. {
  348. if (values == NULL) {
  349. // return the structure. This is a symmetric matrix, fill the lower left
  350. // triangle only.
  351. Index ihes=0;
  352. // First the diagonal entries for y(i,j)
  353. for (Index i=1; i<= N_; i++) {
  354. for (Index j=1; j<= N_; j++) {
  355. iRow[ihes] = y_index(i,j);
  356. jCol[ihes] = y_index(i,j);
  357. ihes++;
  358. }
  359. }
  360. if (alpha_>0.) {
  361. // Now the diagonal entries for u at the boundary
  362. for (Index i=1; i<=N_; i++) {
  363. Index iu = y_index(i,0);
  364. iRow[ihes] = iu;
  365. jCol[ihes] = iu;
  366. ihes++;
  367. }
  368. for (Index i=1; i<=N_; i++) {
  369. Index iu = y_index(i,N_+1);
  370. iRow[ihes] = iu;
  371. jCol[ihes] = iu;
  372. ihes++;
  373. }
  374. for (Index j=1; j<=N_; j++) {
  375. Index iu = y_index(0,j);
  376. iRow[ihes] = iu;
  377. jCol[ihes] = iu;
  378. ihes++;
  379. }
  380. for (Index j=1; j<=N_; j++) {
  381. Index iu = y_index(N_+1,j);
  382. iRow[ihes] = iu;
  383. jCol[ihes] = iu;
  384. ihes++;
  385. }
  386. }
  387. DBG_ASSERT(ihes==nele_hess);
  388. }
  389. else {
  390. // return the values
  391. Index ihes=0;
  392. // First the diagonal entries for y(i,j)
  393. for (Index i=1; i<= N_; i++) {
  394. for (Index j=1; j<= N_; j++) {
  395. // Contribution from the objective function
  396. values[ihes] = obj_factor*hh_;
  397. ihes++;
  398. }
  399. }
  400. // Now the diagonal entries for u(i,j)
  401. if (alpha_>0.) {
  402. // Now the diagonal entries for u at the boundary
  403. for (Index i=1; i<=N_; i++) {
  404. values[ihes] = obj_factor*h_*alpha_;
  405. ihes++;
  406. }
  407. for (Index i=1; i<=N_; i++) {
  408. values[ihes] = obj_factor*h_*alpha_;
  409. ihes++;
  410. }
  411. for (Index j=1; j<=N_; j++) {
  412. values[ihes] = obj_factor*h_*alpha_;
  413. ihes++;
  414. }
  415. for (Index i=1; i<=N_; i++) {
  416. values[ihes] = obj_factor*h_*alpha_;
  417. ihes++;
  418. }
  419. }
  420. }
  421. return true;
  422. }
  423. void
  424. MittelmannBndryCntrlDiriBase::finalize_solution(SolverReturn status,
  425. Index n, const Number* x, const Number* z_L, const Number* z_U,
  426. Index m, const Number* g, const Number* lambda, Number obj_value,
  427. const IpoptData* ip_data,
  428. IpoptCalculatedQuantities* ip_cq)
  429. {
  430. /*
  431. FILE* fp = fopen("solution.txt", "w+");
  432. for (Index i=0; i<=N_+1; i++) {
  433. for (Index j=0; j<=N_+1; j++) {
  434. fprintf(fp, "y[%6d,%6d] = %15.8e\n", i, j, x[y_index(i,j)]);
  435. }
  436. }
  437. fclose(fp);
  438. */
  439. }