Actual source code: taosolver_hj.c
1: #include <petsc/private/taoimpl.h>
3: /*@C
4: TaoSetHessian - Sets the function to compute the Hessian as well as the location to store the matrix.
6: Logically Collective
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`)
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
23: Level: beginner
25: .seealso: [](ch_tao), `Tao`, `TaoTypes`, `TaoSetObjective()`, `TaoSetGradient()`, `TaoSetObjectiveAndGradient()`, `TaoGetHessian()`
26: @*/
27: PetscErrorCode TaoSetHessian(Tao tao, Mat H, Mat Hpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat H, Mat Hpre, void *ctx), void *ctx)
28: {
29: PetscFunctionBegin;
31: if (H) {
33: PetscCheckSameComm(tao, 1, H, 2);
34: }
35: if (Hpre) {
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: }
54: /*@C
55: TaoGetHessian - Gets the function to compute the Hessian as well as the location to store the matrix.
57: Not Collective
59: Input Parameter:
60: . tao - the `Tao` context
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
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
75: Level: beginner
77: .seealso: [](ch_tao), `Tao`, `TaoType`, `TaoGetObjective()`, `TaoGetGradient()`, `TaoGetObjectiveAndGradient()`, `TaoSetHessian()`
78: @*/
79: PetscErrorCode TaoGetHessian(Tao tao, Mat *H, Mat *Hpre, PetscErrorCode (**func)(Tao tao, Vec x, Mat H, Mat Hpre, void *ctx), void **ctx)
80: {
81: PetscFunctionBegin;
83: if (H) *H = tao->hessian;
84: if (Hpre) *Hpre = tao->hessian_pre;
85: if (ctx) *ctx = tao->user_hessP;
86: if (func) *func = tao->ops->computehessian;
87: PetscFunctionReturn(PETSC_SUCCESS);
88: }
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;
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);
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));
128: PetscCall(PetscObjectTypeCompare((PetscObject)tao->hessian, MATMFFD, &flg));
129: if (!flg) hessian = tao->hessian;
130: else hessian = tao->hessian_pre;
132: while (hessian) {
133: PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)hessian, &flg, MATSEQAIJ, MATMPIAIJ, MATSEQDENSE, MATMPIDENSE, MATSEQBAIJ, MATMPIBAIJ, MATSEQSBAIJ, MATMPIBAIJ, ""));
134: if (flg) {
135: A = hessian;
136: PetscCall(PetscObjectReference((PetscObject)A));
137: } else {
138: PetscCall(MatComputeOperator(hessian, MATAIJ, &A));
139: }
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));
149: PetscCall(TaoDefaultComputeHessian(tao, x, B, B, NULL));
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));
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: }
166: if (complete_print) {
167: PetscInt Istart, Iend, *ccols, bncols, cncols, j, row;
168: PetscScalar *cvals;
169: const PetscInt *bcols;
170: const PetscScalar *bvals;
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));
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));
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: }
216: /*@C
217: TaoComputeHessian - Computes the Hessian matrix that has been
218: set with `TaoSetHessian()`.
220: Collective
222: Input Parameters:
223: + tao - the Tao solver context
224: - X - input vector
226: Output Parameters:
227: + H - Hessian matrix
228: - Hpre - Preconditioning matrix
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
235: Level: developer
237: Notes:
238: Most users should not need to explicitly call this routine, as it
239: is used internally within the minimization solvers.
241: `TaoComputeHessian()` is typically used within optimization algorithms,
242: so most users would not generally call this routine
243: themselves.
245: Developer Notes:
246: The Hessian test mechanism follows `SNESTestJacobian()`.
248: .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetHessian()`
249: @*/
250: PetscErrorCode TaoComputeHessian(Tao tao, Vec X, Mat H, Mat Hpre)
251: {
252: PetscFunctionBegin;
255: PetscCheckSameComm(tao, 1, X, 2);
256: PetscCheck(tao->ops->computehessian, PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_WRONGSTATE, "TaoSetHessian() not called");
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));
265: PetscCall(TaoTestHessian(tao));
266: PetscFunctionReturn(PETSC_SUCCESS);
267: }
269: /*@C
270: TaoComputeJacobian - Computes the Jacobian matrix that has been
271: set with TaoSetJacobianRoutine().
273: Collective
275: Input Parameters:
276: + tao - the Tao solver context
277: - X - input vector
279: Output Parameters:
280: + J - Jacobian matrix
281: - Jpre - Preconditioning matrix
283: Level: developer
285: Notes:
286: Most users should not need to explicitly call this routine, as it
287: is used internally within the minimization solvers.
289: `TaoComputeJacobian()` is typically used within minimization
290: implementations, so most users would not generally call this routine
291: themselves.
293: .seealso: [](ch_tao), `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianRoutine()`
294: @*/
295: PetscErrorCode TaoComputeJacobian(Tao tao, Vec X, Mat J, Mat Jpre)
296: {
297: PetscFunctionBegin;
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: }
310: /*@C
311: TaoComputeResidualJacobian - Computes the least-squares residual Jacobian matrix that has been
312: set with `TaoSetJacobianResidual()`.
314: Collective
316: Input Parameters:
317: + tao - the Tao solver context
318: - X - input vector
320: Output Parameters:
321: + J - Jacobian matrix
322: - Jpre - Preconditioning matrix
324: Level: developer
326: Notes:
327: Most users should not need to explicitly call this routine, as it
328: is used internally within the minimization solvers.
330: `TaoComputeResidualJacobian()` is typically used within least-squares
331: implementations, so most users would not generally call this routine
332: themselves.
334: .seealso: [](ch_tao), `Tao`, `TaoComputeResidual()`, `TaoSetJacobianResidual()`
335: @*/
336: PetscErrorCode TaoComputeResidualJacobian(Tao tao, Vec X, Mat J, Mat Jpre)
337: {
338: PetscFunctionBegin;
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: }
351: /*@C
352: TaoComputeJacobianState - Computes the Jacobian matrix that has been
353: set with `TaoSetJacobianStateRoutine()`.
355: Collective
357: Input Parameters:
358: + tao - the `Tao` solver context
359: - X - input vector
361: Output Parameters:
362: + J - Jacobian matrix
363: . Jpre - matrix used to construct the preconditioner, often the same as `J`
364: - Jinv - unknown
366: Level: developer
368: Note:
369: Most users should not need to explicitly call this routine, as it
370: is used internally within the optimization algorithms.
372: .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
373: @*/
374: PetscErrorCode TaoComputeJacobianState(Tao tao, Vec X, Mat J, Mat Jpre, Mat Jinv)
375: {
376: PetscFunctionBegin;
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: }
389: /*@C
390: TaoComputeJacobianDesign - Computes the Jacobian matrix that has been
391: set with `TaoSetJacobianDesignRoutine()`.
393: Collective
395: Input Parameters:
396: + tao - the Tao solver context
397: - X - input vector
399: Output Parameter:
400: . J - Jacobian matrix
402: Level: developer
404: Note:
405: Most users should not need to explicitly call this routine, as it
406: is used internally within the optimization algorithms.
408: .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianDesignRoutine()`, `TaoSetStateDesignIS()`
409: @*/
410: PetscErrorCode TaoComputeJacobianDesign(Tao tao, Vec X, Mat J)
411: {
412: PetscFunctionBegin;
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: }
425: /*@C
426: TaoSetJacobianRoutine - Sets the function to compute the Jacobian as well as the location to store the matrix.
428: Logically Collective
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`)
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
445: Level: intermediate
447: .seealso: [](ch_tao), `Tao`, `TaoSetGradient()`, `TaoSetObjective()`
448: @*/
449: PetscErrorCode TaoSetJacobianRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx), void *ctx)
450: {
451: PetscFunctionBegin;
453: if (J) {
455: PetscCheckSameComm(tao, 1, J, 2);
456: }
457: if (Jpre) {
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: }
476: /*@C
477: TaoSetJacobianResidualRoutine - Sets the function to compute the least-squares residual Jacobian as well as the
478: location to store the matrix.
480: Logically Collective
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`)
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
497: Level: intermediate
499: .seealso: [](ch_tao), `Tao`, `TaoSetGradient()`, `TaoSetObjective()`
500: @*/
501: PetscErrorCode TaoSetJacobianResidualRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx), void *ctx)
502: {
503: PetscFunctionBegin;
505: if (J) {
507: PetscCheckSameComm(tao, 1, J, 2);
508: }
509: if (Jpre) {
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: }
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.
533: Logically Collective
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`)
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
552: Level: intermediate
554: .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianState()`, `TaoSetJacobianDesignRoutine()`, `TaoSetStateDesignIS()`
555: @*/
556: PetscErrorCode TaoSetJacobianStateRoutine(Tao tao, Mat J, Mat Jpre, Mat Jinv, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, Mat Jinv, void *ctx), void *ctx)
557: {
558: PetscFunctionBegin;
560: if (J) {
562: PetscCheckSameComm(tao, 1, J, 2);
563: }
564: if (Jpre) {
566: PetscCheckSameComm(tao, 1, Jpre, 3);
567: }
568: if (Jinv) {
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: }
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.
597: Logically Collective
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`)
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
612: Level: intermediate
614: .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianDesign()`, `TaoSetJacobianStateRoutine()`, `TaoSetStateDesignIS()`
615: @*/
616: PetscErrorCode TaoSetJacobianDesignRoutine(Tao tao, Mat J, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, void *ctx), void *ctx)
617: {
618: PetscFunctionBegin;
620: if (J) {
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: }
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.
639: Logically Collective
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
646: Level: intermediate
648: .seealso: [](ch_tao), `Tao`, `TaoSetJacobianStateRoutine()`, `TaoSetJacobianDesignRoutine()`
649: @*/
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: }
662: /*@C
663: TaoComputeJacobianEquality - Computes the Jacobian matrix that has been
664: set with `TaoSetJacobianEqualityRoutine()`.
666: Collective
668: Input Parameters:
669: + tao - the `Tao` solver context
670: - X - input vector
672: Output Parameters:
673: + J - Jacobian matrix
674: - Jpre - matrix used to construct the preconditioner, often the same as `J`
676: Level: developer
678: Notes:
679: Most users should not need to explicitly call this routine, as it
680: is used internally within the optimization algorithms.
682: .seealso: [](ch_tao), `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
683: @*/
684: PetscErrorCode TaoComputeJacobianEquality(Tao tao, Vec X, Mat J, Mat Jpre)
685: {
686: PetscFunctionBegin;
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: }
699: /*@C
700: TaoComputeJacobianInequality - Computes the Jacobian matrix that has been
701: set with `TaoSetJacobianInequalityRoutine()`.
703: Collective
705: Input Parameters:
706: + tao - the `Tao` solver context
707: - X - input vector
709: Output Parameters:
710: + J - Jacobian matrix
711: - Jpre - matrix used to construct the preconditioner
713: Level: developer
715: Note:
716: Most users should not need to explicitly call this routine, as it
717: is used internally within the minimization solvers.
719: .seealso: [](ch_tao), `Tao`, `TaoComputeObjective()`, `TaoComputeObjectiveAndGradient()`, `TaoSetJacobianStateRoutine()`, `TaoComputeJacobianDesign()`, `TaoSetStateDesignIS()`
720: @*/
721: PetscErrorCode TaoComputeJacobianInequality(Tao tao, Vec X, Mat J, Mat Jpre)
722: {
723: PetscFunctionBegin;
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: }
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.
741: Logically Collective
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`)
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
758: Level: intermediate
760: .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianEquality()`, `TaoSetJacobianDesignRoutine()`, `TaoSetEqualityDesignIS()`
761: @*/
762: PetscErrorCode TaoSetJacobianEqualityRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx), void *ctx)
763: {
764: PetscFunctionBegin;
766: if (J) {
768: PetscCheckSameComm(tao, 1, J, 2);
769: }
770: if (Jpre) {
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: }
789: /*@C
790: TaoSetJacobianInequalityRoutine - Sets the function to compute the Jacobian
791: (and its inverse) of the constraint function with respect to the inequality variables.
792: Used only for PDE-constrained optimization.
794: Logically Collective
796: Input Parameters:
797: + tao - the `Tao` context
798: . J - Matrix used for the Jacobian
799: . Jpre - Matrix that will be used to construct the preconditioner, can be same as `J`.
800: . func - Jacobian evaluation routine
801: - ctx - [optional] user-defined context for private data for the
802: Jacobian evaluation routine (may be `NULL`)
804: Calling sequence of `func`:
805: + tao - the `Tao` context
806: . x - input vector
807: . J - Jacobian matrix
808: . Jpre - matrix used to construct the preconditioner, usually the same as `J`
809: - ctx - [optional] user-defined Jacobian context
811: Level: intermediate
813: .seealso: [](ch_tao), `Tao`, `TaoComputeJacobianInequality()`, `TaoSetJacobianDesignRoutine()`, `TaoSetInequalityDesignIS()`
814: @*/
815: PetscErrorCode TaoSetJacobianInequalityRoutine(Tao tao, Mat J, Mat Jpre, PetscErrorCode (*func)(Tao tao, Vec x, Mat J, Mat Jpre, void *ctx), void *ctx)
816: {
817: PetscFunctionBegin;
819: if (J) {
821: PetscCheckSameComm(tao, 1, J, 2);
822: }
823: if (Jpre) {
825: PetscCheckSameComm(tao, 1, Jpre, 3);
826: }
827: if (ctx) tao->user_jac_inequalityP = ctx;
828: if (func) tao->ops->computejacobianinequality = func;
829: if (J) {
830: PetscCall(PetscObjectReference((PetscObject)J));
831: PetscCall(MatDestroy(&tao->jacobian_inequality));
832: tao->jacobian_inequality = J;
833: }
834: if (Jpre) {
835: PetscCall(PetscObjectReference((PetscObject)Jpre));
836: PetscCall(MatDestroy(&tao->jacobian_inequality_pre));
837: tao->jacobian_inequality_pre = Jpre;
838: }
839: PetscFunctionReturn(PETSC_SUCCESS);
840: }