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