MittelmannDistCntrlDiri.cpp 11 KB

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