xref: /petsc/src/tao/interface/taosolver_hj.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
1 #include <petsc/private/taoimpl.h> /*I "petsctao.h" I*/
2 
3 /*@C
4   TaoSetHessian - Sets the function to compute the Hessian as well as the location to store the matrix.
5 
6   Logically Collective
7 
8   Input Parameters:
9 + tao  - the `Tao` context
10 . H    - Matrix used for the hessian
11 . Hpre - Matrix that will be used to construct the preconditioner, can be same as `H`
12 . func - Hessian evaluation routine
13 - ctx  - [optional] user-defined context for private data for the
14          Hessian evaluation routine (may be `NULL`)
15 
16   Calling sequence of `func`:
17 + tao  - the `Tao`  context
18 . x    - input vector
19 . H    - Hessian matrix
20 . Hpre - matrix used to construct the preconditioner, usually the same as `H`
21 - ctx  - [optional] user-defined Hessian context
22 
23   Level: beginner
24 
25 .seealso: [](ch_tao), `Tao`, `TaoTypes`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetObjectiveAndGradient()`, `TaoGetHessian()`
26 @*/
TaoSetHessian(Tao tao,Mat H,Mat Hpre,PetscErrorCode (* func)(Tao tao,Vec x,Mat H,Mat Hpre,PetscCtx ctx),PetscCtx ctx)27 PetscErrorCode TaoSetHessian(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat H, Mat Hpre, PetscCtx ctx), PetscCtx ctx)
28 {
29   PetscFunctionBegin;
30   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
31   if (H) {
32     PetscValidHeaderSpecific(H, MAT_CLASSID, 2);
33     PetscCheckSameComm(tao, 1, H, 2);
34   }
35   if (Hpre) {
36     PetscValidHeaderSpecific(Hpre, MAT_CLASSID, 3);
37     PetscCheckSameComm(tao, 1, Hpre, 3);
38   }
39   if (ctx) tao->user_hessP = ctx;
40   if (func) tao->ops->computehessian = func;
41   if (H) {
42     PetscCall(PetscObjectReference((PetscObject)H));
43     PetscCall(MatDestroy(&tao->hessian));
44     tao->hessian = H;
45   }
46   if (Hpre) {
47     PetscCall(PetscObjectReference((PetscObject)Hpre));
48     PetscCall(MatDestroy(&tao->hessian_pre));
49     tao->hessian_pre = Hpre;
50   }
51   PetscFunctionReturn(PETSC_SUCCESS);
52 }
53 
54 /*@C
55   TaoGetHessian - Gets the function to compute the Hessian as well as the location to store the matrix.
56 
57   Not Collective
58 
59   Input Parameter:
60 . tao - the `Tao` context
61 
62   Output Parameters:
63 + H    - Matrix used for the hessian
64 . Hpre - Matrix that will be used to construct the preconditioner, can be the same as `H`
65 . func - Hessian evaluation routine
66 - ctx  - user-defined context for private data for the Hessian evaluation routine
67 
68   Calling sequence of `func`:
69 + tao  - the `Tao`  context
70 . x    - input vector
71 . H    - Hessian matrix
72 . Hpre - matrix used to construct the preconditioner, usually the same as `H`
73 - ctx  - [optional] user-defined Hessian context
74 
75   Level: beginner
76 
77 .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoGetObjective()`, `TaoGetGradient()`, `TaoGetObjectiveAndGradient()`, `TaoSetHessian()`
78 @*/
TaoGetHessian(Tao tao,Mat * H,Mat * Hpre,PetscErrorCode (** func)(Tao tao,Vec x,Mat H,Mat Hpre,PetscCtx ctx),PetscCtxRt ctx)79 PetscErrorCode TaoGetHessian(Tao tao, Mat *H, Mat *Hpre, PetscErrorCode (**func)(Tao tao, Vec x, Mat H, Mat Hpre, PetscCtx ctx), PetscCtxRt ctx)
80 {
81   PetscFunctionBegin;
82   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
83   if (H) *H = tao->hessian;
84   if (Hpre) *Hpre = tao->hessian_pre;
85   if (ctx) *(void **)ctx = tao->user_hessP;
86   if (func) *func = tao->ops->computehessian;
87   PetscFunctionReturn(PETSC_SUCCESS);
88 }
89 
TaoTestHessian(Tao tao)90 PetscErrorCode TaoTestHessian(Tao tao)
91 {
92   Mat               A, B, C, D, hessian;
93   Vec               x = tao->solution;
94   PetscReal         nrm, gnorm;
95   PetscReal         threshold = 1.e-5;
96   PetscInt          m, n, M, N;
97   PetscBool         complete_print = PETSC_FALSE, test = PETSC_FALSE, flg;
98   PetscViewer       viewer, mviewer;
99   MPI_Comm          comm;
100   PetscInt          tabs;
101   static PetscBool  directionsprinted = PETSC_FALSE;
102   PetscViewerFormat format;
103 
104   PetscFunctionBegin;
105   PetscObjectOptionsBegin((PetscObject)tao);
106   PetscCall(PetscOptionsName("-tao_test_hessian", "Compare hand-coded and finite difference Hessians", "None", &test));
107   PetscCall(PetscOptionsReal("-tao_test_hessian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold, NULL));
108   PetscCall(PetscOptionsViewer("-tao_test_hessian_view", "View difference between hand-coded and finite difference Hessians element entries", "None", &mviewer, &format, &complete_print));
109   PetscOptionsEnd();
110   if (!test) PetscFunctionReturn(PETSC_SUCCESS);
111 
112   PetscCall(PetscObjectGetComm((PetscObject)tao, &comm));
113   PetscCall(PetscViewerASCIIGetStdout(comm, &viewer));
114   PetscCall(PetscViewerASCIIGetTab(viewer, &tabs));
115   PetscCall(PetscViewerASCIISetTab(viewer, ((PetscObject)tao)->tablevel));
116   PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Hessian -------------\n"));
117   if (!complete_print && !directionsprinted) {
118     PetscCall(PetscViewerASCIIPrintf(viewer, "  Run with -tao_test_hessian_view and optionally -tao_test_hessian <threshold> to show difference\n"));
119     PetscCall(PetscViewerASCIIPrintf(viewer, "    of hand-coded and finite difference Hessian entries greater than <threshold>.\n"));
120   }
121   if (!directionsprinted) {
122     PetscCall(PetscViewerASCIIPrintf(viewer, "  Testing hand-coded Hessian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n"));
123     PetscCall(PetscViewerASCIIPrintf(viewer, "    O(1.e-8), the hand-coded Hessian is probably correct.\n"));
124     directionsprinted = PETSC_TRUE;
125   }
126   if (complete_print) PetscCall(PetscViewerPushFormat(mviewer, format));
127 
128   PetscCall(PetscObjectTypeCompare((PetscObject)tao->hessian, MATMFFD, &flg));
129   if (!flg) hessian = tao->hessian;
130   else hessian = tao->hessian_pre;
131 
132   while (hessian) {
133     PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)hessian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPISBAIJ, ""));
134     if (flg) {
135       A = hessian;
136       PetscCall(PetscObjectReference((PetscObject)A));
137     } else {
138       PetscCall(MatComputeOperator(hessian, MATAIJ, &A));
139     }
140 
141     PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &B));
142     PetscCall(MatGetSize(A, &M, &N));
143     PetscCall(MatGetLocalSize(A, &m, &n));
144     PetscCall(MatSetSizes(B, m, n, M, N));
145     PetscCall(MatSetType(B, ((PetscObject)A)->type_name));
146     PetscCall(MatSetUp(B));
147     PetscCall(MatSetOption(B, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
148 
149     PetscCall(TaoDefaultComputeHessian(tao, x, B, B, NULL));
150 
151     PetscCall(MatDuplicate(B, MAT_COPY_VALUES, &D));
152     PetscCall(MatAYPX(D, -1.0, A, DIFFERENT_NONZERO_PATTERN));
153     PetscCall(MatNorm(D, NORM_FROBENIUS, &nrm));
154     PetscCall(MatNorm(A, NORM_FROBENIUS, &gnorm));
155     PetscCall(MatDestroy(&D));
156     if (!gnorm) gnorm = 1; /* just in case */
157     PetscCall(PetscViewerASCIIPrintf(viewer, "  ||H - Hfd||_F/||H||_F = %g, ||H - Hfd||_F = %g\n", (double)(nrm / gnorm), (double)nrm));
158 
159     if (complete_print) {
160       PetscCall(PetscViewerASCIIPrintf(viewer, "  Hand-coded Hessian ----------\n"));
161       PetscCall(MatView(A, mviewer));
162       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite difference Hessian ----------\n"));
163       PetscCall(MatView(B, mviewer));
164     }
165 
166     if (complete_print) {
167       PetscInt           Istart, Iend, *ccols, bncols, cncols, j, row;
168       PetscScalar       *cvals;
169       const PetscInt    *bcols;
170       const PetscScalar *bvals;
171 
172       PetscCall(MatAYPX(B, -1.0, A, DIFFERENT_NONZERO_PATTERN));
173       PetscCall(MatCreate(PetscObjectComm((PetscObject)A), &C));
174       PetscCall(MatSetSizes(C, m, n, M, N));
175       PetscCall(MatSetType(C, ((PetscObject)A)->type_name));
176       PetscCall(MatSetUp(C));
177       PetscCall(MatSetOption(C, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
178       PetscCall(MatGetOwnershipRange(B, &Istart, &Iend));
179 
180       for (row = Istart; row < Iend; row++) {
181         PetscCall(MatGetRow(B, row, &bncols, &bcols, &bvals));
182         PetscCall(PetscMalloc2(bncols, &ccols, bncols, &cvals));
183         for (j = 0, cncols = 0; j < bncols; j++) {
184           if (PetscAbsScalar(bvals[j]) > threshold) {
185             ccols[cncols] = bcols[j];
186             cvals[cncols] = bvals[j];
187             cncols += 1;
188           }
189         }
190         if (cncols) PetscCall(MatSetValues(C, 1, &row, cncols, ccols, cvals, INSERT_VALUES));
191         PetscCall(MatRestoreRow(B, row, &bncols, &bcols, &bvals));
192         PetscCall(PetscFree2(ccols, cvals));
193       }
194       PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
195       PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
196       PetscCall(PetscViewerASCIIPrintf(viewer, "  Finite-difference minus hand-coded Hessian with tolerance %g ----------\n", (double)threshold));
197       PetscCall(MatView(C, mviewer));
198       PetscCall(MatDestroy(&C));
199     }
200     PetscCall(MatDestroy(&A));
201     PetscCall(MatDestroy(&B));
202 
203     if (hessian != tao->hessian_pre) {
204       hessian = tao->hessian_pre;
205       PetscCall(PetscViewerASCIIPrintf(viewer, "  ---------- Testing Hessian for preconditioner -------------\n"));
206     } else hessian = NULL;
207   }
208   if (complete_print) {
209     PetscCall(PetscViewerPopFormat(mviewer));
210     PetscCall(PetscViewerDestroy(&mviewer));
211   }
212   PetscCall(PetscViewerASCIISetTab(viewer, tabs));
213   PetscFunctionReturn(PETSC_SUCCESS);
214 }
215 
216 /*@
217   TaoComputeHessian - Computes the Hessian matrix that has been
218   set with `TaoSetHessian()`.
219 
220   Collective
221 
222   Input Parameters:
223 + tao - the Tao solver context
224 - X   - input vector
225 
226   Output Parameters:
227 + H    - Hessian matrix
228 - Hpre - matrix used to construct the preconditioner, usually the same as `H`
229 
230   Options Database Keys:
231 + -tao_test_hessian                   - compare the user provided Hessian with one compute via finite differences to check for errors
232 . -tao_test_hessian <numerical value> - display entries in the difference between the user provided Hessian and finite difference Hessian that are greater than a certain value to help users detect errors
233 - -tao_test_hessian_view              - display the user provided Hessian, the finite difference Hessian and the difference between them to help users detect the location of errors in the user provided Hessian
234 
235   Level: developer
236 
237   Notes:
238   Most users should not need to explicitly call this routine, as it
239   is used internally within the minimization solvers.
240 
241   `TaoComputeHessian()` is typically used within optimization algorithms,
242   so most users would not generally call this routine
243   themselves.
244 
245   Developer Notes:
246   The Hessian test mechanism follows `SNESTestJacobian()`.
247 
248 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetHessian()`
249 @*/
TaoComputeHessian(Tao tao,Vec X,Mat H,Mat Hpre)250 PetscErrorCode TaoComputeHessian(Tao tao, Vec X, Mat H, Mat Hpre)
251 {
252   PetscFunctionBegin;
253   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
254   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
255   PetscCheckSameComm(tao, 1, X, 2);
256   PetscCheck(tao->ops->computehessian, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetHessian() not called");
257 
258   ++tao->nhess;
259   PetscCall(VecLockReadPush(X));
260   PetscCall(PetscLogEventBegin(TAO_HessianEval, tao, X, H, Hpre));
261   PetscCallBack("Tao callback Hessian", (*tao->ops->computehessian)(tao, X, H, Hpre, tao->user_hessP));
262   PetscCall(PetscLogEventEnd(TAO_HessianEval, tao, X, H, Hpre));
263   PetscCall(VecLockReadPop(X));
264 
265   PetscCall(TaoTestHessian(tao));
266   PetscFunctionReturn(PETSC_SUCCESS);
267 }
268 
269 /*@
270   TaoComputeJacobian - Computes the Jacobian matrix that has been
271   set with TaoSetJacobianRoutine().
272 
273   Collective
274 
275   Input Parameters:
276 + tao - the Tao solver context
277 - X   - input vector
278 
279   Output Parameters:
280 + J    - Jacobian matrix
281 - Jpre - matrix used to compute the preconditioner, often the same as `J`
282 
283   Level: developer
284 
285   Notes:
286   Most users should not need to explicitly call this routine, as it
287   is used internally within the minimization solvers.
288 
289   `TaoComputeJacobian()` is typically used within minimization
290   implementations, so most users would not generally call this routine
291   themselves.
292 
293 .seealso: [](ch_tao), `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianRoutine()`
294 @*/
TaoComputeJacobian(Tao tao,Vec X,Mat J,Mat Jpre)295 PetscErrorCode TaoComputeJacobian(Tao tao, Vec X, Mat J, Mat Jpre)
296 {
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
299   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
300   PetscCheckSameComm(tao, 1, X, 2);
301   ++tao->njac;
302   PetscCall(VecLockReadPush(X));
303   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, Jpre));
304   PetscCallBack("Tao callback Jacobian", (*tao->ops->computejacobian)(tao, X, J, Jpre, tao->user_jacP));
305   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, Jpre));
306   PetscCall(VecLockReadPop(X));
307   PetscFunctionReturn(PETSC_SUCCESS);
308 }
309 
310 /*@
311   TaoComputeResidualJacobian - Computes the least-squares residual Jacobian matrix that has been
312   set with `TaoSetJacobianResidual()`.
313 
314   Collective
315 
316   Input Parameters:
317 + tao - the Tao solver context
318 - X   - input vector
319 
320   Output Parameters:
321 + J    - Jacobian matrix
322 - Jpre - matrix used to compute the preconditioner, often the same as `J`
323 
324   Level: developer
325 
326   Notes:
327   Most users should not need to explicitly call this routine, as it
328   is used internally within the minimization solvers.
329 
330   `TaoComputeResidualJacobian()` is typically used within least-squares
331   implementations, so most users would not generally call this routine
332   themselves.
333 
334 .seealso: [](ch_tao), `Tao`, `TaoComputeResidual()`, `TaoSetJacobianResidual()`
335 @*/
TaoComputeResidualJacobian(Tao tao,Vec X,Mat J,Mat Jpre)336 PetscErrorCode TaoComputeResidualJacobian(Tao tao, Vec X, Mat J, Mat Jpre)
337 {
338   PetscFunctionBegin;
339   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
340   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
341   PetscCheckSameComm(tao, 1, X, 2);
342   ++tao->njac;
343   PetscCall(VecLockReadPush(X));
344   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, Jpre));
345   PetscCallBack("Tao callback least-squares residual Jacobian", (*tao->ops->computeresidualjacobian)(tao, X, J, Jpre, tao->user_lsjacP));
346   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, Jpre));
347   PetscCall(VecLockReadPop(X));
348   PetscFunctionReturn(PETSC_SUCCESS);
349 }
350 
351 /*@
352   TaoComputeJacobianState - Computes the Jacobian matrix that has been
353   set with `TaoSetJacobianStateRoutine()`.
354 
355   Collective
356 
357   Input Parameters:
358 + tao - the `Tao` solver context
359 - X   - input vector
360 
361   Output Parameters:
362 + J    - Jacobian matrix
363 . Jpre - matrix used to construct the preconditioner, often the same as `J`
364 - Jinv - unknown
365 
366   Level: developer
367 
368   Note:
369   Most users should not need to explicitly call this routine, as it
370   is used internally within the optimization algorithms.
371 
372 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
373 @*/
TaoComputeJacobianState(Tao tao,Vec X,Mat J,Mat Jpre,Mat Jinv)374 PetscErrorCode TaoComputeJacobianState(Tao tao, Vec X, Mat J, Mat Jpre, Mat Jinv)
375 {
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
378   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
379   PetscCheckSameComm(tao, 1, X, 2);
380   ++tao->njac_state;
381   PetscCall(VecLockReadPush(X));
382   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, Jpre));
383   PetscCallBack("Tao callback Jacobian(state)", (*tao->ops->computejacobianstate)(tao, X, J, Jpre, Jinv, tao->user_jac_stateP));
384   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, Jpre));
385   PetscCall(VecLockReadPop(X));
386   PetscFunctionReturn(PETSC_SUCCESS);
387 }
388 
389 /*@
390   TaoComputeJacobianDesign - Computes the Jacobian matrix that has been
391   set with `TaoSetJacobianDesignRoutine()`.
392 
393   Collective
394 
395   Input Parameters:
396 + tao - the Tao solver context
397 - X   - input vector
398 
399   Output Parameter:
400 . J - Jacobian matrix
401 
402   Level: developer
403 
404   Note:
405   Most users should not need to explicitly call this routine, as it
406   is used internally within the optimization algorithms.
407 
408 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianDesignRoutine()`, `TaoSetStateDesignIS()`
409 @*/
TaoComputeJacobianDesign(Tao tao,Vec X,Mat J)410 PetscErrorCode TaoComputeJacobianDesign(Tao tao, Vec X, Mat J)
411 {
412   PetscFunctionBegin;
413   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
414   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
415   PetscCheckSameComm(tao, 1, X, 2);
416   ++tao->njac_design;
417   PetscCall(VecLockReadPush(X));
418   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, NULL));
419   PetscCallBack("Tao callback Jacobian(design)", (*tao->ops->computejacobiandesign)(tao, X, J, tao->user_jac_designP));
420   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, NULL));
421   PetscCall(VecLockReadPop(X));
422   PetscFunctionReturn(PETSC_SUCCESS);
423 }
424 
425 /*@C
426   TaoSetJacobianRoutine - Sets the function to compute the Jacobian as well as the location to store the matrix.
427 
428   Logically Collective
429 
430   Input Parameters:
431 + tao  - the `Tao` context
432 . J    - Matrix used for the Jacobian
433 . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`
434 . func - Jacobian evaluation routine
435 - ctx  - [optional] user-defined context for private data for the
436           Jacobian evaluation routine (may be `NULL`)
437 
438   Calling sequence of `func`:
439 + tao  - the `Tao` context
440 . x    - input vector
441 . J    - Jacobian matrix
442 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
443 - ctx  - [optional] user-defined Jacobian context
444 
445   Level: intermediate
446 
447 .seealso: [](ch_tao), `Tao`, `TaoSetGradient()`, `TaoSetObjective()`
448 @*/
TaoSetJacobianRoutine(Tao tao,Mat J,Mat Jpre,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtx ctx)449 PetscErrorCode TaoSetJacobianRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtx ctx)
450 {
451   PetscFunctionBegin;
452   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
453   if (J) {
454     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
455     PetscCheckSameComm(tao, 1, J, 2);
456   }
457   if (Jpre) {
458     PetscValidHeaderSpecific(Jpre, MAT_CLASSID, 3);
459     PetscCheckSameComm(tao, 1, Jpre, 3);
460   }
461   if (ctx) tao->user_jacP = ctx;
462   if (func) tao->ops->computejacobian = func;
463   if (J) {
464     PetscCall(PetscObjectReference((PetscObject)J));
465     PetscCall(MatDestroy(&tao->jacobian));
466     tao->jacobian = J;
467   }
468   if (Jpre) {
469     PetscCall(PetscObjectReference((PetscObject)Jpre));
470     PetscCall(MatDestroy(&tao->jacobian_pre));
471     tao->jacobian_pre = Jpre;
472   }
473   PetscFunctionReturn(PETSC_SUCCESS);
474 }
475 
476 /*@C
477   TaoSetJacobianResidualRoutine - Sets the function to compute the least-squares residual Jacobian as well as the
478   location to store the matrix.
479 
480   Logically Collective
481 
482   Input Parameters:
483 + tao  - the `Tao` context
484 . J    - Matrix used for the jacobian
485 . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`
486 . func - Jacobian evaluation routine
487 - ctx  - [optional] user-defined context for private data for the
488           Jacobian evaluation routine (may be `NULL`)
489 
490   Calling sequence of `func`:
491 + tao  - the `Tao`  context
492 . x    - input vector
493 . J    - Jacobian matrix
494 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
495 - ctx  - [optional] user-defined Jacobian context
496 
497   Level: intermediate
498 
499 .seealso: [](ch_tao), `Tao`, `TaoSetGradient()`, `TaoSetObjective()`
500 @*/
TaoSetJacobianResidualRoutine(Tao tao,Mat J,Mat Jpre,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtx ctx)501 PetscErrorCode TaoSetJacobianResidualRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtx ctx)
502 {
503   PetscFunctionBegin;
504   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
505   if (J) {
506     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
507     PetscCheckSameComm(tao, 1, J, 2);
508   }
509   if (Jpre) {
510     PetscValidHeaderSpecific(Jpre, MAT_CLASSID, 3);
511     PetscCheckSameComm(tao, 1, Jpre, 3);
512   }
513   if (ctx) tao->user_lsjacP = ctx;
514   if (func) tao->ops->computeresidualjacobian = func;
515   if (J) {
516     PetscCall(PetscObjectReference((PetscObject)J));
517     PetscCall(MatDestroy(&tao->ls_jac));
518     tao->ls_jac = J;
519   }
520   if (Jpre) {
521     PetscCall(PetscObjectReference((PetscObject)Jpre));
522     PetscCall(MatDestroy(&tao->ls_jac_pre));
523     tao->ls_jac_pre = Jpre;
524   }
525   PetscFunctionReturn(PETSC_SUCCESS);
526 }
527 
528 /*@C
529   TaoSetJacobianStateRoutine - Sets the function to compute the Jacobian
530   (and its inverse) of the constraint function with respect to the state variables.
531   Used only for PDE-constrained optimization.
532 
533   Logically Collective
534 
535   Input Parameters:
536 + tao  - the `Tao` context
537 . J    - Matrix used for the Jacobian
538 . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`.  Only used if `Jinv` is `NULL`
539 . Jinv - [optional] Matrix used to apply the inverse of the state Jacobian. Use `NULL` to default to PETSc `KSP` solvers to apply the inverse.
540 . func - Jacobian evaluation routine
541 - ctx  - [optional] user-defined context for private data for the
542           Jacobian evaluation routine (may be `NULL`)
543 
544   Calling sequence of `func`:
545 + tao  - the `Tao` context
546 . x    - input vector
547 . J    - Jacobian matrix
548 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
549 . Jinv - inverse of `J`
550 - ctx  - [optional] user-defined Jacobian context
551 
552   Level: intermediate
553 
554 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianState()`, `TaoSetJacobianDesignRoutine()`, `TaoSetStateDesignIS()`
555 @*/
TaoSetJacobianStateRoutine(Tao tao,Mat J,Mat Jpre,Mat Jinv,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,Mat Jpre,Mat Jinv,PetscCtx ctx),PetscCtx ctx)556 PetscErrorCode TaoSetJacobianStateRoutine(Tao tao, Mat J, Mat Jpre, Mat Jinv, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, Mat Jinv, PetscCtx ctx), PetscCtx ctx)
557 {
558   PetscFunctionBegin;
559   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
560   if (J) {
561     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
562     PetscCheckSameComm(tao, 1, J, 2);
563   }
564   if (Jpre) {
565     PetscValidHeaderSpecific(Jpre, MAT_CLASSID, 3);
566     PetscCheckSameComm(tao, 1, Jpre, 3);
567   }
568   if (Jinv) {
569     PetscValidHeaderSpecific(Jinv, MAT_CLASSID, 4);
570     PetscCheckSameComm(tao, 1, Jinv, 4);
571   }
572   if (ctx) tao->user_jac_stateP = ctx;
573   if (func) tao->ops->computejacobianstate = func;
574   if (J) {
575     PetscCall(PetscObjectReference((PetscObject)J));
576     PetscCall(MatDestroy(&tao->jacobian_state));
577     tao->jacobian_state = J;
578   }
579   if (Jpre) {
580     PetscCall(PetscObjectReference((PetscObject)Jpre));
581     PetscCall(MatDestroy(&tao->jacobian_state_pre));
582     tao->jacobian_state_pre = Jpre;
583   }
584   if (Jinv) {
585     PetscCall(PetscObjectReference((PetscObject)Jinv));
586     PetscCall(MatDestroy(&tao->jacobian_state_inv));
587     tao->jacobian_state_inv = Jinv;
588   }
589   PetscFunctionReturn(PETSC_SUCCESS);
590 }
591 
592 /*@C
593   TaoSetJacobianDesignRoutine - Sets the function to compute the Jacobian of
594   the constraint function with respect to the design variables.  Used only for
595   PDE-constrained optimization.
596 
597   Logically Collective
598 
599   Input Parameters:
600 + tao  - the `Tao` context
601 . J    - Matrix used for the Jacobian
602 . func - Jacobian evaluation routine
603 - ctx  - [optional] user-defined context for private data for the
604           Jacobian evaluation routine (may be `NULL`)
605 
606   Calling sequence of `func`:
607 + tao - the `Tao` context
608 . x   - input vector
609 . J   - Jacobian matrix
610 - ctx - [optional] user-defined Jacobian context
611 
612   Level: intermediate
613 
614 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianDesign()`, `TaoSetJacobianStateRoutine()`, `TaoSetStateDesignIS()`
615 @*/
TaoSetJacobianDesignRoutine(Tao tao,Mat J,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,PetscCtx ctx),PetscCtx ctx)616 PetscErrorCode TaoSetJacobianDesignRoutine(Tao tao, Mat J, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, PetscCtx ctx), PetscCtx ctx)
617 {
618   PetscFunctionBegin;
619   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
620   if (J) {
621     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
622     PetscCheckSameComm(tao, 1, J, 2);
623   }
624   if (ctx) tao->user_jac_designP = ctx;
625   if (func) tao->ops->computejacobiandesign = func;
626   if (J) {
627     PetscCall(PetscObjectReference((PetscObject)J));
628     PetscCall(MatDestroy(&tao->jacobian_design));
629     tao->jacobian_design = J;
630   }
631   PetscFunctionReturn(PETSC_SUCCESS);
632 }
633 
634 /*@
635   TaoSetStateDesignIS - Indicate to the `Tao` object which variables in the
636   solution vector are state variables and which are design.  Only applies to
637   PDE-constrained optimization.
638 
639   Logically Collective
640 
641   Input Parameters:
642 + tao  - The `Tao` context
643 . s_is - the index set corresponding to the state variables
644 - d_is - the index set corresponding to the design variables
645 
646   Level: intermediate
647 
648 .seealso: [](ch_tao), `Tao`, `TaoSetJacobianStateRoutine()`, `TaoSetJacobianDesignRoutine()`
649 @*/
TaoSetStateDesignIS(Tao tao,IS s_is,IS d_is)650 PetscErrorCode TaoSetStateDesignIS(Tao tao, IS s_is, IS d_is)
651 {
652   PetscFunctionBegin;
653   PetscCall(PetscObjectReference((PetscObject)s_is));
654   PetscCall(ISDestroy(&tao->state_is));
655   tao->state_is = s_is;
656   PetscCall(PetscObjectReference((PetscObject)d_is));
657   PetscCall(ISDestroy(&tao->design_is));
658   tao->design_is = d_is;
659   PetscFunctionReturn(PETSC_SUCCESS);
660 }
661 
662 /*@
663   TaoComputeJacobianEquality - Computes the Jacobian matrix that has been
664   set with `TaoSetJacobianEqualityRoutine()`.
665 
666   Collective
667 
668   Input Parameters:
669 + tao - the `Tao` solver context
670 - X   - input vector
671 
672   Output Parameters:
673 + J    - Jacobian matrix
674 - Jpre - matrix used to construct the preconditioner, often the same as `J`
675 
676   Level: developer
677 
678   Notes:
679   Most users should not need to explicitly call this routine, as it
680   is used internally within the optimization algorithms.
681 
682 .seealso: [](ch_tao), `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
683 @*/
TaoComputeJacobianEquality(Tao tao,Vec X,Mat J,Mat Jpre)684 PetscErrorCode TaoComputeJacobianEquality(Tao tao, Vec X, Mat J, Mat Jpre)
685 {
686   PetscFunctionBegin;
687   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
688   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
689   PetscCheckSameComm(tao, 1, X, 2);
690   ++tao->njac_equality;
691   PetscCall(VecLockReadPush(X));
692   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, Jpre));
693   PetscCallBack("Tao callback Jacobian(equality)", (*tao->ops->computejacobianequality)(tao, X, J, Jpre, tao->user_jac_equalityP));
694   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, Jpre));
695   PetscCall(VecLockReadPop(X));
696   PetscFunctionReturn(PETSC_SUCCESS);
697 }
698 
699 /*@
700   TaoComputeJacobianInequality - Computes the Jacobian matrix that has been
701   set with `TaoSetJacobianInequalityRoutine()`.
702 
703   Collective
704 
705   Input Parameters:
706 + tao - the `Tao` solver context
707 - X   - input vector
708 
709   Output Parameters:
710 + J    - Jacobian matrix
711 - Jpre - matrix used to construct the preconditioner
712 
713   Level: developer
714 
715   Note:
716   Most users should not need to explicitly call this routine, as it
717   is used internally within the minimization solvers.
718 
719 .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
720 @*/
TaoComputeJacobianInequality(Tao tao,Vec X,Mat J,Mat Jpre)721 PetscErrorCode TaoComputeJacobianInequality(Tao tao, Vec X, Mat J, Mat Jpre)
722 {
723   PetscFunctionBegin;
724   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
725   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
726   PetscCheckSameComm(tao, 1, X, 2);
727   ++tao->njac_inequality;
728   PetscCall(VecLockReadPush(X));
729   PetscCall(PetscLogEventBegin(TAO_JacobianEval, tao, X, J, Jpre));
730   PetscCallBack("Tao callback Jacobian (inequality)", (*tao->ops->computejacobianinequality)(tao, X, J, Jpre, tao->user_jac_inequalityP));
731   PetscCall(PetscLogEventEnd(TAO_JacobianEval, tao, X, J, Jpre));
732   PetscCall(VecLockReadPop(X));
733   PetscFunctionReturn(PETSC_SUCCESS);
734 }
735 
736 /*@C
737   TaoSetJacobianEqualityRoutine - Sets the function to compute the Jacobian
738   (and its inverse) of the constraint function with respect to the equality variables.
739   Used only for PDE-constrained optimization.
740 
741   Logically Collective
742 
743   Input Parameters:
744 + tao  - the `Tao` context
745 . J    - Matrix used for the Jacobian
746 . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`.
747 . func - Jacobian evaluation routine
748 - ctx  - [optional] user-defined context for private data for the
749           Jacobian evaluation routine (may be `NULL`)
750 
751   Calling sequence of `func`:
752 + tao  - the `Tao` context
753 . x    - input vector
754 . J    - Jacobian matrix
755 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
756 - ctx  - [optional] user-defined Jacobian context
757 
758   Level: intermediate
759 
760 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianEquality()`, `TaoSetJacobianDesignRoutine()`, `TaoSetEqualityDesignIS()`
761 @*/
TaoSetJacobianEqualityRoutine(Tao tao,Mat J,Mat Jpre,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtx ctx)762 PetscErrorCode TaoSetJacobianEqualityRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtx ctx)
763 {
764   PetscFunctionBegin;
765   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
766   if (J) {
767     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
768     PetscCheckSameComm(tao, 1, J, 2);
769   }
770   if (Jpre) {
771     PetscValidHeaderSpecific(Jpre, MAT_CLASSID, 3);
772     PetscCheckSameComm(tao, 1, Jpre, 3);
773   }
774   if (ctx) tao->user_jac_equalityP = ctx;
775   if (func) tao->ops->computejacobianequality = func;
776   if (J) {
777     PetscCall(PetscObjectReference((PetscObject)J));
778     PetscCall(MatDestroy(&tao->jacobian_equality));
779     tao->jacobian_equality = J;
780   }
781   if (Jpre) {
782     PetscCall(PetscObjectReference((PetscObject)Jpre));
783     PetscCall(MatDestroy(&tao->jacobian_equality_pre));
784     tao->jacobian_equality_pre = Jpre;
785   }
786   PetscFunctionReturn(PETSC_SUCCESS);
787 }
788 
789 /*@C
790   TaoGetJacobianEqualityRoutine - Gets the function used to compute equality constraint Jacobian.
791 
792   Not Collective
793 
794   Input Parameter:
795 . tao - the `Tao` context
796 
797   Output Parameters:
798 + J    - the matrix to internally hold the constraint computation
799 . Jpre - the matrix used to construct the preconditioner
800 . func - Jacobian evaluation routine
801 - ctx  - the (optional) user-defined context
802 
803   Calling sequence of `func`:
804 + tao  - the `Tao` context
805 . x    - input vector
806 . J    - Jacobian matrix
807 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
808 - ctx  - [optional] user-defined Jacobian context
809 
810   Level: intermediate
811 
812 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianEquality()`, `TaoSetJacobianEqualityRoutine()`
813 @*/
TaoGetJacobianEqualityRoutine(Tao tao,Mat * J,Mat * Jpre,PetscErrorCode (** func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtxRt ctx)814 PetscErrorCode TaoGetJacobianEqualityRoutine(Tao tao, Mat *J, Mat *Jpre, PetscErrorCode (**func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtxRt ctx)
815 {
816   PetscFunctionBegin;
817   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
818   if (J) *J = tao->jacobian_equality;
819   if (Jpre) *Jpre = tao->jacobian_equality_pre;
820   if (func) *func = tao->ops->computejacobianequality;
821   if (ctx) *(void **)ctx = tao->user_jac_equalityP;
822   PetscFunctionReturn(PETSC_SUCCESS);
823 }
824 
825 /*@C
826   TaoSetJacobianInequalityRoutine - Sets the function to compute the Jacobian
827   (and its inverse) of the constraint function with respect to the inequality variables.
828   Used only for PDE-constrained optimization.
829 
830   Logically Collective
831 
832   Input Parameters:
833 + tao  - the `Tao` context
834 . J    - Matrix used for the Jacobian
835 . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`.
836 . func - Jacobian evaluation routine
837 - ctx  - [optional] user-defined context for private data for the
838           Jacobian evaluation routine (may be `NULL`)
839 
840   Calling sequence of `func`:
841 + tao  - the `Tao` context
842 . x    - input vector
843 . J    - Jacobian matrix
844 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
845 - ctx  - [optional] user-defined Jacobian context
846 
847   Level: intermediate
848 
849 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianInequality()`, `TaoSetJacobianDesignRoutine()`, `TaoSetInequalityDesignIS()`
850 @*/
TaoSetJacobianInequalityRoutine(Tao tao,Mat J,Mat Jpre,PetscErrorCode (* func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtx ctx)851 PetscErrorCode TaoSetJacobianInequalityRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtx ctx)
852 {
853   PetscFunctionBegin;
854   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
855   if (J) {
856     PetscValidHeaderSpecific(J, MAT_CLASSID, 2);
857     PetscCheckSameComm(tao, 1, J, 2);
858   }
859   if (Jpre) {
860     PetscValidHeaderSpecific(Jpre, MAT_CLASSID, 3);
861     PetscCheckSameComm(tao, 1, Jpre, 3);
862   }
863   if (ctx) tao->user_jac_inequalityP = ctx;
864   if (func) tao->ops->computejacobianinequality = func;
865   if (J) {
866     PetscCall(PetscObjectReference((PetscObject)J));
867     PetscCall(MatDestroy(&tao->jacobian_inequality));
868     tao->jacobian_inequality = J;
869   }
870   if (Jpre) {
871     PetscCall(PetscObjectReference((PetscObject)Jpre));
872     PetscCall(MatDestroy(&tao->jacobian_inequality_pre));
873     tao->jacobian_inequality_pre = Jpre;
874   }
875   PetscFunctionReturn(PETSC_SUCCESS);
876 }
877 
878 /*@C
879   TaoGetJacobianInequalityRoutine - Gets the function used to compute inequality constraint Jacobian.
880 
881   Not Collective
882 
883   Input Parameter:
884 . tao - the `Tao` context
885 
886   Output Parameters:
887 + J    - the matrix to internally hold the constraint computation
888 . Jpre - the matrix used to construct the preconditioner
889 . func - Jacobian evaluation routine
890 - ctx  - the (optional) user-defined context
891 
892   Calling sequence of `func`:
893 + tao  - the `Tao` context
894 . x    - input vector
895 . J    - Jacobian matrix
896 . Jpre - matrix used to construct the preconditioner, usually the same as `J`
897 - ctx  - [optional] user-defined Jacobian context
898 
899   Level: intermediate
900 
901 .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianInequality()`, `TaoSetJacobianInequalityRoutine()`
902 @*/
TaoGetJacobianInequalityRoutine(Tao tao,Mat * J,Mat * Jpre,PetscErrorCode (** func)(Tao tao,Vec x,Mat J,Mat Jpre,PetscCtx ctx),PetscCtxRt ctx)903 PetscErrorCode TaoGetJacobianInequalityRoutine(Tao tao, Mat *J, Mat *Jpre, PetscErrorCode (**func)(Tao tao, Vec x, Mat J, Mat Jpre, PetscCtx ctx), PetscCtxRt ctx)
904 {
905   PetscFunctionBegin;
906   PetscValidHeaderSpecific(tao, TAO_CLASSID, 1);
907   if (J) *J = tao->jacobian_inequality;
908   if (Jpre) *Jpre = tao->jacobian_inequality_pre;
909   if (func) *func = tao->ops->computejacobianinequality;
910   if (ctx) *(void **)ctx = tao->user_jac_inequalityP;
911   PetscFunctionReturn(PETSC_SUCCESS);
912 }
913