MittelmannBndryCntrlDiri3Dsin.cpp 23 KB

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