MittelmannBndryCntrlDiri3D.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734
  1. // Copyright (C) 2005, 2007 International Business Machines and others.
  2. // All Rights Reserved.
  3. // This code is published under the Eclipse Public License.
  4. //
  5. // $Id: MittelmannBndryCntrlDiri3D.cpp 2005 2011-06-06 12:55:16Z stefan $
  6. //
  7. // Authors: Andreas Waechter IBM 2005-10-18
  8. // Olaf Schenk (Univ. of Basel) 2007-08-01
  9. // modified MittelmannBndryCntrlDiri.cpp for 3-dim problem
  10. #include "MittelmannBndryCntrlDiri3D.hpp"
  11. #ifdef HAVE_CASSERT
  12. # include <cassert>
  13. #else
  14. # ifdef HAVE_ASSERT_H
  15. # include <assert.h>
  16. # else
  17. # error "don't have header file for assert"
  18. # endif
  19. #endif
  20. using namespace Ipopt;
  21. /* Constructor. */
  22. MittelmannBndryCntrlDiriBase3D::MittelmannBndryCntrlDiriBase3D()
  23. :
  24. y_d_(NULL)
  25. {}
  26. MittelmannBndryCntrlDiriBase3D::~MittelmannBndryCntrlDiriBase3D()
  27. {
  28. delete [] y_d_;
  29. }
  30. void
  31. MittelmannBndryCntrlDiriBase3D::SetBaseParameters(Index N, Number alpha, Number lb_y,
  32. Number ub_y, Number lb_u, Number ub_u,
  33. Number d_const, Number B, Number C)
  34. {
  35. N_ = N;
  36. h_ = 1./(N+1);
  37. hh_ = h_*h_;
  38. hhh_ = hh_*h_;
  39. lb_y_ = lb_y;
  40. ub_y_ = ub_y;
  41. lb_u_ = lb_u;
  42. ub_u_ = ub_u;
  43. d_const_ = d_const;
  44. alpha_ = alpha;
  45. B_ = B;
  46. C_ = C;
  47. PenA_ = 1.5 - 1.125*C_/B_;
  48. PenB_ = 1.75*C_/pow(B_,3) - 1.5/(B_*B_);
  49. PenC_ = 0.5/pow(B_,4) - 0.625*C_/pow(B_,5);
  50. // Initialize the target profile variables
  51. delete [] y_d_;
  52. y_d_ = new Number[(N_+2)*(N_+2)*(N_+2)];
  53. for (Index k=0; k<= N_+1; k++) {
  54. for (Index j=0; j<= N_+1; j++) {
  55. for (Index i=0; i<= N_+1; i++) {
  56. y_d_[y_index(i,j,k)] = y_d_cont(x1_grid(i),x2_grid(j),x3_grid(k));
  57. }
  58. }
  59. }
  60. }
  61. bool MittelmannBndryCntrlDiriBase3D::get_nlp_info(
  62. Index& n, Index& m, Index& nnz_jac_g,
  63. Index& nnz_h_lag, IndexStyleEnum& index_style)
  64. {
  65. // We for each of the N_+2 times N_+2 times N_+2 mesh points we have
  66. // the value of the functions y, including the control parameters on
  67. // the boundary
  68. n = (N_+2)*(N_+2)*(N_+2);
  69. // For each of the N_ times N_ times N_ interior mesh points we have the
  70. // discretized PDE.
  71. m = N_*N_*N_;
  72. // y(i,j,k), y(i-1,j,k), y(i+1,j,k), y(i,j-1,k), y(i,j+1,k),
  73. // y(i-1,j,k-1), y(i,j,k+1)
  74. // of the N_*N_*N_ discretized PDEs
  75. nnz_jac_g = 7*N_*N_*N_;
  76. // diagonal entry for each y(i,j) in the interior
  77. nnz_h_lag = N_*N_*N_;
  78. if (alpha_>0.) {
  79. // and one entry for u(i,j) in the bundary if alpha is not zero
  80. nnz_h_lag += 6*N_*N_;
  81. }
  82. // We use the C indexing style for row/col entries (corresponding to
  83. // the C notation, starting at 0)
  84. index_style = C_STYLE;
  85. return true;
  86. }
  87. bool
  88. MittelmannBndryCntrlDiriBase3D::get_bounds_info(Index n, Number* x_l, Number* x_u,
  89. Index m, Number* g_l, Number* g_u)
  90. {
  91. // Set overall bounds on the y variables
  92. for (Index i=0; i<=N_+1; i++) {
  93. for (Index j=0; j<=N_+1; j++) {
  94. for (Index k=0; k<=N_+1; k++) {
  95. Index iy = y_index(i,j,k);
  96. x_l[iy] = lb_y_;
  97. x_u[iy] = ub_y_;
  98. }
  99. }
  100. }
  101. // Set the overall 3D bounds on the control variables
  102. for (Index i=0; i<=N_+1; i++) {
  103. for (Index j=0; j<=N_+1; j++) {
  104. Index iu = y_index(i,j,0);
  105. x_l[iu] = lb_u_;
  106. x_u[iu] = ub_u_;
  107. }
  108. }
  109. for (Index i=0; i<=N_+1; i++) {
  110. for (Index j=0; j<=N_+1; j++) {
  111. Index iu = y_index(i,j,N_+1);
  112. x_l[iu] = lb_u_;
  113. x_u[iu] = ub_u_;
  114. }
  115. }
  116. for (Index i=0; i<=N_+1; i++) {
  117. for (Index k=0; k<=N_+1; k++) {
  118. Index iu = y_index(i,0,k);
  119. x_l[iu] = lb_u_;
  120. x_u[iu] = ub_u_;
  121. }
  122. }
  123. for (Index i=0; i<=N_+1; i++) {
  124. for (Index k=0; k<=N_+1; k++) {
  125. Index iu = y_index(i,N_+1,k);
  126. x_l[iu] = lb_u_;
  127. x_u[iu] = ub_u_;
  128. }
  129. }
  130. for (Index j=0; j<=N_+1; j++) {
  131. for (Index k=0; k<=N_+1; k++) {
  132. Index iu = y_index(0,j,k);
  133. x_l[iu] = lb_u_;
  134. x_u[iu] = ub_u_;
  135. }
  136. }
  137. for (Index j=0; j<=N_+1; j++) {
  138. for (Index k=0; k<=N_+1; k++) {
  139. Index iu = y_index(N_+1,j,k);
  140. x_l[iu] = lb_u_;
  141. x_u[iu] = ub_u_;
  142. }
  143. }
  144. // The values of y on the corners doens't appear anywhere, so we fix
  145. // them to zero
  146. for (Index j=0; j<=N_+1; j++) {
  147. x_l[y_index(0,j,0)] = x_u[y_index(0,j,0)] = 0.;
  148. x_l[y_index(0,j,N_+1)] = x_u[y_index(0,j,N_+1)] = 0.;
  149. x_l[y_index(N_+1,j,0)] = x_u[y_index(N_+1,j,0)] = 0.;
  150. x_l[y_index(N_+1,j,N_+1)] = x_u[y_index(N_+1,j,N_+1)] = 0.;
  151. }
  152. for (Index k=0; k<=N_+1; k++) {
  153. x_l[y_index(0,0,k)] = x_u[y_index(0,0,k)] = 0.;
  154. x_l[y_index(0,N_+1,k)] = x_u[y_index(0,N_+1,k)] = 0.;
  155. x_l[y_index(N_+1,0,k)] = x_u[y_index(N_+1,0,k)] = 0.;
  156. x_l[y_index(N_+1,N_+1,k)] = x_u[y_index(N_+1,N_+1,k)] = 0.;
  157. }
  158. for (Index i=0; i<=N_+1; i++) {
  159. x_l[y_index(i,0,0)] = x_u[y_index(i,0,0)] = 0.;
  160. x_l[y_index(i,0,N_+1)] = x_u[y_index(i,0,N_+1)] = 0.;
  161. x_l[y_index(i,N_+1,0)] = x_u[y_index(i,N_+1,0)] = 0.;
  162. x_l[y_index(i,N_+1,N_+1)] = x_u[y_index(i,N_+1,N_+1)] = 0.;
  163. }
  164. // all discretized PDE constraints have right hand side equal to
  165. // minus the constant value of the function d
  166. for (Index i=0; i<m; i++) {
  167. g_l[i] = -hh_*d_const_;
  168. g_u[i] = -hh_*d_const_;
  169. }
  170. return true;
  171. }
  172. bool
  173. MittelmannBndryCntrlDiriBase3D::get_starting_point(Index n, bool init_x, Number* x,
  174. bool init_z, Number* z_L, Number* z_U,
  175. Index m, bool init_lambda,
  176. Number* lambda)
  177. {
  178. // Here, we assume we only have starting values for x, if you code
  179. // your own NLP, you can provide starting values for the others if
  180. // you wish.
  181. assert(init_x == true);
  182. assert(init_z == false);
  183. assert(init_lambda == false);
  184. // set all y's to the perfect match with y_d
  185. for (Index i=0; i<= N_+1; i++) {
  186. for (Index j=0; j<= N_+1; j++) {
  187. for (Index k=0; k<= N_+1; k++) {
  188. x[y_index(i,j,k)] = y_d_[y_index(i,j,k)]; // 0 in AMPL model
  189. }
  190. }
  191. }
  192. Number umid = (ub_u_ + lb_u_)/2.;
  193. for (Index i=0; i<=N_+1; i++) {
  194. for (Index j=0; j<=N_+1; j++) {
  195. Index iu = y_index(i,j,0);
  196. x[iu] = umid;
  197. }
  198. }
  199. for (Index i=0; i<=N_+1; i++) {
  200. for (Index j=0; j<=N_+1; j++) {
  201. Index iu = y_index(i,j,N_+1);
  202. x[iu] = umid;
  203. }
  204. }
  205. for (Index i=0; i<=N_+1; i++) {
  206. for (Index k=0; k<=N_+1; k++) {
  207. Index iu = y_index(i,0,k);
  208. x[iu] = umid;
  209. }
  210. }
  211. for (Index i=0; i<=N_+1; i++) {
  212. for (Index k=0; k<=N_+1; k++) {
  213. Index iu = y_index(i,N_+1,k);
  214. x[iu] = umid;
  215. }
  216. }
  217. for (Index k=0; k<=N_+1; k++) {
  218. for (Index j=0; j<=N_+1; j++) {
  219. Index iu = y_index(0,j,k);
  220. x[iu] = umid;
  221. }
  222. }
  223. for (Index k=0; k<=N_+1; k++) {
  224. for (Index j=0; j<=N_+1; j++) {
  225. Index iu = y_index(N_+1,j,k);
  226. x[iu] = umid;
  227. }
  228. }
  229. return true;
  230. }
  231. bool
  232. MittelmannBndryCntrlDiriBase3D::get_scaling_parameters(Number& obj_scaling,
  233. bool& use_x_scaling, Index n, Number* x_scaling,
  234. bool& use_g_scaling, Index m, Number* g_scaling)
  235. {
  236. obj_scaling = 1./hhh_;
  237. use_x_scaling = false;
  238. use_g_scaling = false;
  239. return true;
  240. }
  241. bool
  242. MittelmannBndryCntrlDiriBase3D::eval_f(Index n, const Number* x,
  243. bool new_x, Number& obj_value)
  244. {
  245. // return the value of the objective function
  246. obj_value = 0.;
  247. // First the integration of y-td over the interior
  248. for (Index i=1; i<=N_; i++) {
  249. for (Index j=1; j<= N_; j++) {
  250. for (Index k=1; k<= N_; k++) {
  251. Index iy = y_index(i,j,k);
  252. Number tmp = x[iy] - y_d_[iy];
  253. obj_value += PenObj(tmp);
  254. //obj_value += tmp*tmp;
  255. }
  256. }
  257. }
  258. obj_value *= hhh_;
  259. // Now the integration of u over the boundary
  260. if (alpha_>0.) {
  261. Number usum = 0.;
  262. for (Index i=1; i<=N_; i++) {
  263. for (Index j=1; j<=N_; j++) {
  264. Index iu = y_index(i,j,0);
  265. usum += x[iu]*x[iu];
  266. }
  267. }
  268. for (Index i=1; i<=N_; i++) {
  269. for (Index j=1; j<=N_; j++) {
  270. Index iu = y_index(i,j,N_+1);
  271. usum += x[iu]*x[iu];
  272. }
  273. }
  274. for (Index k=1; k<=N_; k++) {
  275. for (Index j=1; j<=N_; j++) {
  276. Index iu = y_index(0,j,k);
  277. usum += x[iu]*x[iu];
  278. }
  279. }
  280. for (Index k=1; k<=N_; k++) {
  281. for (Index j=1; j<=N_; j++) {
  282. Index iu = y_index(N_+1,j,k);
  283. usum += x[iu]*x[iu];
  284. }
  285. }
  286. for (Index i=1; i<=N_; i++) {
  287. for (Index k=1; k<=N_; k++) {
  288. Index iu = y_index(i,0,k);
  289. usum += x[iu]*x[iu];
  290. }
  291. }
  292. for (Index i=1; i<=N_; i++) {
  293. for (Index k=1; k<=N_; k++) {
  294. Index iu = y_index(i,N_+1,k);
  295. usum += x[iu]*x[iu];
  296. }
  297. }
  298. obj_value += alpha_*hh_*0.5*usum;
  299. }
  300. return true;
  301. }
  302. bool
  303. MittelmannBndryCntrlDiriBase3D::eval_grad_f(Index n, const Number* x, bool new_x, Number* grad_f)
  304. {
  305. // return the gradient of the objective function grad_{x} f(x)
  306. // now let's take care of the nonzero values coming from the
  307. // integrant over the interior
  308. for (Index i=1; i<=N_; i++) {
  309. for (Index j=1; j<= N_; j++) {
  310. for (Index k=1; k<= N_; k++) {
  311. Index iy = y_index(i,j,k);
  312. grad_f[iy] = hhh_*PenObj_1(x[iy] - y_d_[iy]);
  313. }
  314. }
  315. }
  316. // The values for variables on the boundary
  317. if (alpha_>0.) {
  318. for (Index i=1; i<= N_; i++) {
  319. for (Index j=1; j<= N_; j++) {
  320. Index iu = y_index(i,j,0);
  321. grad_f[iu] = alpha_*hh_*x[iu];
  322. }
  323. }
  324. for (Index i=1; i<= N_; i++) {
  325. for (Index j=1; j<= N_; j++) {
  326. Index iu = y_index(i,j,N_+1);
  327. grad_f[iu] = alpha_*hh_*x[iu];
  328. }
  329. }
  330. for (Index k=1; k<= N_; k++) {
  331. for (Index j=1; j<= N_; j++) {
  332. Index iu = y_index(0,j,k);
  333. grad_f[iu] = alpha_*hh_*x[iu];
  334. }
  335. }
  336. for (Index k=1; k<= N_; k++) {
  337. for (Index j=1; j<= N_; j++) {
  338. Index iu = y_index(N_+1,j,k);
  339. grad_f[iu] = alpha_*hh_*x[iu];
  340. }
  341. }
  342. for (Index i=1; i<= N_; i++) {
  343. for (Index k=1; k<= N_; k++) {
  344. Index iu = y_index(i,0,k);
  345. grad_f[iu] = alpha_*hh_*x[iu];
  346. }
  347. }
  348. for (Index i=1; i<= N_; i++) {
  349. for (Index k=1; k<= N_; k++) {
  350. Index iu = y_index(i,N_+1,k);
  351. grad_f[iu] = alpha_*hh_*x[iu];
  352. }
  353. }
  354. }
  355. else {
  356. for (Index i=1; i<= N_; i++) {
  357. for (Index j=1; j<= N_; j++) {
  358. grad_f[y_index(i,j,0)] = 0.;
  359. }
  360. }
  361. for (Index i=1; i<= N_; i++) {
  362. for (Index j=1; j<= N_; j++) {
  363. grad_f[y_index(i,j,N_+1)] = 0.;
  364. }
  365. }
  366. for (Index k=1; k<= N_; k++) {
  367. for (Index j=1; j<= N_; j++) {
  368. grad_f[y_index(0,j,k)] = 0.;
  369. }
  370. }
  371. for (Index k=1; k<= N_; k++) {
  372. for (Index j=1; j<= N_; j++) {
  373. grad_f[y_index(N_+1,j,k)] = 0.;
  374. }
  375. }
  376. for (Index i=1; i<= N_; i++) {
  377. for (Index k=1; k<= N_; k++) {
  378. grad_f[y_index(i,0,k)] = 0.;
  379. }
  380. }
  381. for (Index i=1; i<= N_; i++) {
  382. for (Index k=1; k<= N_; k++) {
  383. grad_f[y_index(i,N_+1,k)] = 0.;
  384. }
  385. }
  386. }
  387. // Nothing on the corner points
  388. for (Index i=0; i<= N_+1; i++) {
  389. grad_f[y_index(i,0 ,0 )] = 0.;
  390. grad_f[y_index(i,0 ,N_+1)] = 0.;
  391. grad_f[y_index(i,N_+1,0 )] = 0.;
  392. grad_f[y_index(i,N_+1,N_+1)] = 0.;
  393. }
  394. for (Index j=0; j<= N_+1; j++) {
  395. grad_f[y_index(0, j,0 )] = 0.;
  396. grad_f[y_index(N_+1,j,0 )] = 0.;
  397. grad_f[y_index(0, j,N_+1)] = 0.;
  398. grad_f[y_index(N_+1,j,N_+1)] = 0.;
  399. }
  400. for (Index k=0; k<= N_+1; k++) {
  401. grad_f[y_index(0, 0, k)] = 0.;
  402. grad_f[y_index(N_+1,0, k)] = 0.;
  403. grad_f[y_index(0, N_+1,k)] = 0.;
  404. grad_f[y_index(N_+1,N_+1,k)] = 0.;
  405. }
  406. return true;
  407. }
  408. bool MittelmannBndryCntrlDiriBase3D::eval_g(Index n, const Number* x, bool new_x,
  409. Index m, Number* g)
  410. {
  411. // return the value of the constraints: g(x)
  412. // compute the discretized PDE for each interior grid point
  413. Index ig = 0;
  414. for (Index i=1; i<=N_; i++) {
  415. for (Index j=1; j<=N_; j++) {
  416. for (Index k=1; k<=N_; k++) {
  417. Number val;
  418. // Start with the discretized Laplacian operator
  419. val = 6.* x[y_index(i,j,k)]
  420. - x[y_index(i-1,j,k)] - x[y_index(i+1,j,k)]
  421. - x[y_index(i,j-1,k)] - x[y_index(i,j+1,k)]
  422. - x[y_index(i,j,k-1)] - x[y_index(i,j,k+1)];
  423. g[ig] = val;
  424. ig++;
  425. }
  426. }
  427. }
  428. DBG_ASSERT(ig==m);
  429. return true;
  430. }
  431. bool MittelmannBndryCntrlDiriBase3D::eval_jac_g(Index n, const Number* x, bool new_x,
  432. Index m, Index nele_jac, Index* iRow, Index *jCol,
  433. Number* values)
  434. {
  435. if (values == NULL) {
  436. // return the structure of the jacobian of the constraints
  437. Index ijac = 0;
  438. Index ig = 0;
  439. for (Index i=1; i<= N_; i++) {
  440. for (Index j=1; j<= N_; j++) {
  441. for (Index k=1; k<= N_; k++) {
  442. // y(i,j,k)
  443. iRow[ijac] = ig;
  444. jCol[ijac] = y_index(i,j,k);
  445. ijac++;
  446. // y(i-1,j,k)
  447. iRow[ijac] = ig;
  448. jCol[ijac] = y_index(i-1,j,k);
  449. ijac++;
  450. // y(i+1,j,k)
  451. iRow[ijac] = ig;
  452. jCol[ijac] = y_index(i+1,j,k);
  453. ijac++;
  454. // y(i,j-1,k)
  455. iRow[ijac] = ig;
  456. jCol[ijac] = y_index(i,j-1,k);
  457. ijac++;
  458. // y(i,j+1,k)
  459. iRow[ijac] = ig;
  460. jCol[ijac] = y_index(i,j+1,k);
  461. ijac++;
  462. // y(i,j,k-1)
  463. iRow[ijac] = ig;
  464. jCol[ijac] = y_index(i,j,k-1);
  465. ijac++;
  466. // y(i,j,k+1)
  467. iRow[ijac] = ig;
  468. jCol[ijac] = y_index(i,j,k+1);
  469. ijac++;
  470. ig++;
  471. }
  472. }
  473. }
  474. DBG_ASSERT(ijac==nele_jac);
  475. }
  476. else {
  477. // return the values of the jacobian of the constraints
  478. Index ijac = 0;
  479. for (Index i=1; i<= N_; i++) {
  480. for (Index j=1; j<= N_; j++) {
  481. for (Index k=1; k<= N_; k++) {
  482. // y(i,j,k)
  483. values[ijac] = 6.;
  484. ijac++;
  485. // y(i-1,j,k)
  486. values[ijac] = -1.;
  487. ijac++;
  488. // y(i+1,j,k)
  489. values[ijac] = -1.;
  490. ijac++;
  491. // y(1,j-1,k)
  492. values[ijac] = -1.;
  493. ijac++;
  494. // y(1,j+1,k)
  495. values[ijac] = -1.;
  496. ijac++;
  497. // y(1,j,k-1)
  498. values[ijac] = -1.;
  499. ijac++;
  500. // y(1,j,k+1)
  501. values[ijac] = -1.;
  502. ijac++;
  503. }
  504. }
  505. }
  506. DBG_ASSERT(ijac==nele_jac);
  507. }
  508. return true;
  509. }
  510. bool
  511. MittelmannBndryCntrlDiriBase3D::eval_h(Index n, const Number* x, bool new_x,
  512. Number obj_factor, Index m,
  513. const Number* lambda,
  514. bool new_lambda, Index nele_hess, Index* iRow,
  515. Index* jCol, Number* values)
  516. {
  517. if (values == NULL) {
  518. // return the structure. This is a symmetric matrix, fill the lower left
  519. // triangle only.
  520. Index ihes=0;
  521. // First the diagonal entries for y(i,j)
  522. for (Index i=1; i<= N_; i++) {
  523. for (Index j=1; j<= N_; j++) {
  524. for (Index k=1; k<= N_; k++) {
  525. iRow[ihes] = y_index(i,j,k);
  526. jCol[ihes] = y_index(i,j,k);
  527. ihes++;
  528. }
  529. }
  530. }
  531. if (alpha_>0.) {
  532. // Now the diagonal entries for u at the boundary
  533. for (Index i=1; i<=N_; i++) {
  534. for (Index j=1; j<=N_; j++) {
  535. Index iu = y_index(i,j,0);
  536. iRow[ihes] = iu;
  537. jCol[ihes] = iu;
  538. ihes++;
  539. }
  540. }
  541. for (Index i=1; i<=N_; i++) {
  542. for (Index j=1; j<=N_; j++) {
  543. Index iu = y_index(i,j,N_+1);
  544. iRow[ihes] = iu;
  545. jCol[ihes] = iu;
  546. ihes++;
  547. }
  548. }
  549. for (Index k=1; k<=N_; k++) {
  550. for (Index j=1; j<=N_; j++) {
  551. Index iu = y_index(0,j,k);
  552. iRow[ihes] = iu;
  553. jCol[ihes] = iu;
  554. ihes++;
  555. }
  556. }
  557. for (Index k=1; k<=N_; k++) {
  558. for (Index j=1; j<=N_; j++) {
  559. Index iu = y_index(N_+1,j,k);
  560. iRow[ihes] = iu;
  561. jCol[ihes] = iu;
  562. ihes++;
  563. }
  564. }
  565. for (Index i=1; i<=N_; i++) {
  566. for (Index k=1; k<=N_; k++) {
  567. Index iu = y_index(i,0,k);
  568. iRow[ihes] = iu;
  569. jCol[ihes] = iu;
  570. ihes++;
  571. }
  572. }
  573. for (Index i=1; i<=N_; i++) {
  574. for (Index k=1; k<=N_; k++) {
  575. Index iu = y_index(i,N_+1,k);
  576. iRow[ihes] = iu;
  577. jCol[ihes] = iu;
  578. ihes++;
  579. }
  580. }
  581. }
  582. DBG_ASSERT(ihes==nele_hess);
  583. }
  584. else {
  585. // return the values
  586. Index ihes=0;
  587. // First the diagonal entries for y(i,j)
  588. for (Index i=1; i<= N_; i++) {
  589. for (Index j=1; j<= N_; j++) {
  590. for (Index k=1; k<= N_; k++) {
  591. // Contribution from the objective function
  592. Index iy = y_index(i,j,k);
  593. values[ihes] = obj_factor*hhh_*PenObj_2(x[iy] - y_d_[iy]);
  594. ihes++;
  595. }
  596. }
  597. }
  598. // Now the diagonal entries for u(i,j)
  599. if (alpha_>0.) {
  600. // Now the diagonal entries for u at the boundary
  601. for (Index i=1; i<=N_; i++) {
  602. for (Index j=1; j<=N_; j++) {
  603. values[ihes] = obj_factor*hh_*alpha_;
  604. ihes++;
  605. }
  606. }
  607. for (Index i=1; i<=N_; i++) {
  608. for (Index j=1; j<=N_; j++) {
  609. values[ihes] = obj_factor*hh_*alpha_;
  610. ihes++;
  611. }
  612. }
  613. for (Index i=1; i<=N_; i++) {
  614. for (Index j=1; j<=N_; j++) {
  615. values[ihes] = obj_factor*hh_*alpha_;
  616. ihes++;
  617. }
  618. }
  619. for (Index i=1; i<=N_; i++) {
  620. for (Index j=1; j<=N_; j++) {
  621. values[ihes] = obj_factor*hh_*alpha_;
  622. ihes++;
  623. }
  624. }
  625. for (Index i=1; i<=N_; i++) {
  626. for (Index j=1; j<=N_; j++) {
  627. values[ihes] = obj_factor*hh_*alpha_;
  628. ihes++;
  629. }
  630. }
  631. for (Index i=1; i<=N_; i++) {
  632. for (Index j=1; j<=N_; j++) {
  633. values[ihes] = obj_factor*hh_*alpha_;
  634. ihes++;
  635. }
  636. }
  637. }
  638. }
  639. return true;
  640. }
  641. void
  642. MittelmannBndryCntrlDiriBase3D::finalize_solution(SolverReturn status,
  643. Index n, const Number* x, const Number* z_L, const Number* z_U,
  644. Index m, const Number* g, const Number* lambda, Number obj_value,
  645. const IpoptData* ip_data,
  646. IpoptCalculatedQuantities* ip_cq)
  647. {
  648. /*
  649. FILE* fp = fopen("solution.txt", "w+");
  650. for (Index i=0; i<=N_+1; i++) {
  651. for (Index j=0; j<=N_+1; j++) {
  652. fprintf(fp, "y[%6d,%6d] = %15.8e\n", i, j, x[y_index(i,j)]);
  653. }
  654. }
  655. fclose(fp);
  656. */
  657. }