xref: /petsc/src/tao/bound/impls/bqnk/bqnk.c (revision 9566063d113dddea24716c546802770db7481bc0)
1414d97d3SAlp Dener #include <../src/tao/bound/impls/bqnk/bqnk.h> /*I "petsctao.h" I*/ /*I "petscmat.h" I*/
2e0ed867bSAlp Dener #include <petscksp.h>
3e0ed867bSAlp Dener 
4e0ed867bSAlp Dener static PetscErrorCode TaoBQNKComputeHessian(Tao tao)
5e0ed867bSAlp Dener {
6e0ed867bSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
7e0ed867bSAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
865f5217aSAlp Dener   PetscReal      gnorm2, delta;
9e0ed867bSAlp Dener 
10e0ed867bSAlp Dener   PetscFunctionBegin;
11e0ed867bSAlp Dener   /* Alias the LMVM matrix into the TAO hessian */
12e0ed867bSAlp Dener   if (tao->hessian) {
13*9566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&tao->hessian));
14e0ed867bSAlp Dener   }
15e0ed867bSAlp Dener   if (tao->hessian_pre) {
16*9566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&tao->hessian_pre));
17e0ed867bSAlp Dener   }
18*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bqnk->B));
19e0ed867bSAlp Dener   tao->hessian = bqnk->B;
20*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bqnk->B));
21e0ed867bSAlp Dener   tao->hessian_pre = bqnk->B;
22e0ed867bSAlp Dener   /* Update the Hessian with the latest solution */
23f5766c09SAlp Dener   if (bqnk->is_spd) {
2465f5217aSAlp Dener     gnorm2 = bnk->gnorm*bnk->gnorm;
258cabe928SAlp Dener     if (gnorm2 == 0.0) gnorm2 = PETSC_MACHINE_EPSILON;
268cabe928SAlp Dener     if (bnk->f == 0.0) {
278cabe928SAlp Dener       delta = 2.0 / gnorm2;
288cabe928SAlp Dener     } else {
298cabe928SAlp Dener       delta = 2.0 * PetscAbsScalar(bnk->f) / gnorm2;
308cabe928SAlp Dener     }
31*9566063dSJacob Faibussowitsch     PetscCall(MatLMVMSymBroydenSetDelta(bqnk->B, delta));
32f5766c09SAlp Dener   }
33*9566063dSJacob Faibussowitsch   PetscCall(MatLMVMUpdate(tao->hessian, tao->solution, bnk->unprojected_gradient));
34*9566063dSJacob Faibussowitsch   PetscCall(MatLMVMResetShift(tao->hessian));
35e0ed867bSAlp Dener   /* Prepare the reduced sub-matrices for the inactive set */
36*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&bnk->H_inactive));
37e0ed867bSAlp Dener   if (bnk->active_idx) {
38*9566063dSJacob Faibussowitsch     PetscCall(MatCreateSubMatrixVirtual(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, &bnk->H_inactive));
39*9566063dSJacob Faibussowitsch     PetscCall(PCLMVMSetIS(bqnk->pc, bnk->inactive_idx));
40e0ed867bSAlp Dener   } else {
41*9566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference((PetscObject)tao->hessian));
42e0ed867bSAlp Dener     bnk->H_inactive = tao->hessian;
43*9566063dSJacob Faibussowitsch     PetscCall(PCLMVMClearIS(bqnk->pc));
44e0ed867bSAlp Dener   }
45*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&bnk->Hpre_inactive));
46*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)bnk->H_inactive));
47e0ed867bSAlp Dener   bnk->Hpre_inactive = bnk->H_inactive;
48e0ed867bSAlp Dener   PetscFunctionReturn(0);
49e0ed867bSAlp Dener }
50e0ed867bSAlp Dener 
516b591159SAlp Dener static PetscErrorCode TaoBQNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason, PetscInt *step_type)
52e0ed867bSAlp Dener {
53e0ed867bSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
54e0ed867bSAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
55e0ed867bSAlp Dener 
56e0ed867bSAlp Dener   PetscFunctionBegin;
57*9566063dSJacob Faibussowitsch   PetscCall(TaoBNKComputeStep(tao, shift, ksp_reason, step_type));
58e0ed867bSAlp Dener   if (*ksp_reason < 0) {
59e0ed867bSAlp Dener     /* Krylov solver failed to converge so reset the LMVM matrix */
60*9566063dSJacob Faibussowitsch     PetscCall(MatLMVMReset(bqnk->B, PETSC_FALSE));
61*9566063dSJacob Faibussowitsch     PetscCall(MatLMVMUpdate(bqnk->B, tao->solution, bnk->unprojected_gradient));
62e0ed867bSAlp Dener   }
63e0ed867bSAlp Dener   PetscFunctionReturn(0);
64e0ed867bSAlp Dener }
65e0ed867bSAlp Dener 
66414d97d3SAlp Dener PetscErrorCode TaoSolve_BQNK(Tao tao)
67414d97d3SAlp Dener {
68414d97d3SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
69414d97d3SAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
70414d97d3SAlp Dener   Mat_LMVM       *lmvm = (Mat_LMVM*)bqnk->B->data;
71414d97d3SAlp Dener   Mat_LMVM       *J0;
72414d97d3SAlp Dener   Mat_SymBrdn    *diag_ctx;
73414d97d3SAlp Dener   PetscBool      flg = PETSC_FALSE;
74414d97d3SAlp Dener 
75414d97d3SAlp Dener   PetscFunctionBegin;
76414d97d3SAlp Dener   if (!tao->recycle) {
77*9566063dSJacob Faibussowitsch     PetscCall(MatLMVMReset(bqnk->B, PETSC_FALSE));
78414d97d3SAlp Dener     lmvm->nresets = 0;
79414d97d3SAlp Dener     if (lmvm->J0) {
80*9566063dSJacob Faibussowitsch       PetscCall(PetscObjectBaseTypeCompare((PetscObject)lmvm->J0, MATLMVM, &flg));
81414d97d3SAlp Dener       if (flg) {
82414d97d3SAlp Dener         J0 = (Mat_LMVM*)lmvm->J0->data;
83414d97d3SAlp Dener         J0->nresets = 0;
84414d97d3SAlp Dener       }
85414d97d3SAlp Dener     }
86414d97d3SAlp Dener     flg = PETSC_FALSE;
87*9566063dSJacob Faibussowitsch     PetscCall(PetscObjectTypeCompareAny((PetscObject)bqnk->B, &flg, MATLMVMSYMBROYDEN, MATLMVMSYMBADBROYDEN, MATLMVMBFGS, MATLMVMDFP, ""));
88414d97d3SAlp Dener     if (flg) {
89414d97d3SAlp Dener       diag_ctx = (Mat_SymBrdn*)lmvm->ctx;
90414d97d3SAlp Dener       J0 = (Mat_LMVM*)diag_ctx->D->data;
91414d97d3SAlp Dener       J0->nresets = 0;
92414d97d3SAlp Dener     }
93414d97d3SAlp Dener   }
94*9566063dSJacob Faibussowitsch   PetscCall((*bqnk->solve)(tao));
95414d97d3SAlp Dener   PetscFunctionReturn(0);
96414d97d3SAlp Dener }
97414d97d3SAlp Dener 
986b591159SAlp Dener PetscErrorCode TaoSetUp_BQNK(Tao tao)
994f4fdda4SAlp Dener {
1004f4fdda4SAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
1014f4fdda4SAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
1024f4fdda4SAlp Dener   PetscInt       n, N;
1036b591159SAlp Dener   PetscBool      is_lmvm, is_sym, is_spd;
1044f4fdda4SAlp Dener 
1054f4fdda4SAlp Dener   PetscFunctionBegin;
106*9566063dSJacob Faibussowitsch   PetscCall(TaoSetUp_BNK(tao));
107*9566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(tao->solution,&n));
108*9566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->solution,&N));
109*9566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(bqnk->B, n, n, N, N));
110*9566063dSJacob Faibussowitsch   PetscCall(MatLMVMAllocate(bqnk->B,tao->solution,bnk->unprojected_gradient));
111*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)bqnk->B, MATLMVM, &is_lmvm));
1123c859ba3SBarry Smith   PetscCheck(is_lmvm,PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Matrix must be an LMVM-type");
113*9566063dSJacob Faibussowitsch   PetscCall(MatGetOption(bqnk->B, MAT_SYMMETRIC, &is_sym));
1143c859ba3SBarry Smith   PetscCheck(is_sym,PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix must be symmetric");
115*9566063dSJacob Faibussowitsch   PetscCall(MatGetOption(bqnk->B, MAT_SPD, &is_spd));
116*9566063dSJacob Faibussowitsch   PetscCall(KSPGetPC(tao->ksp, &bqnk->pc));
117*9566063dSJacob Faibussowitsch   PetscCall(PCSetType(bqnk->pc, PCLMVM));
118*9566063dSJacob Faibussowitsch   PetscCall(PCLMVMSetMatLMVM(bqnk->pc, bqnk->B));
1194f4fdda4SAlp Dener   PetscFunctionReturn(0);
1204f4fdda4SAlp Dener }
1214f4fdda4SAlp Dener 
122e0ed867bSAlp Dener static PetscErrorCode TaoSetFromOptions_BQNK(PetscOptionItems *PetscOptionsObject,Tao tao)
123e0ed867bSAlp Dener {
124e0ed867bSAlp Dener   TAO_BNK        *bnk = (TAO_BNK *)tao->data;
125e0ed867bSAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
126e0ed867bSAlp Dener 
127e0ed867bSAlp Dener   PetscFunctionBegin;
128*9566063dSJacob Faibussowitsch   PetscCall(TaoSetFromOptions_BNK(PetscOptionsObject,tao));
129e0ed867bSAlp Dener   if (bnk->init_type == BNK_INIT_INTERPOLATION) bnk->init_type = BNK_INIT_DIRECTION;
130*9566063dSJacob Faibussowitsch   PetscCall(MatSetOptionsPrefix(bqnk->B, ((PetscObject)tao)->prefix));
131*9566063dSJacob Faibussowitsch   PetscCall(MatAppendOptionsPrefix(bqnk->B, "tao_bqnk_"));
132*9566063dSJacob Faibussowitsch   PetscCall(MatSetFromOptions(bqnk->B));
133*9566063dSJacob Faibussowitsch   PetscCall(MatGetOption(bqnk->B, MAT_SPD, &bqnk->is_spd));
134e0ed867bSAlp Dener   PetscFunctionReturn(0);
135e0ed867bSAlp Dener }
136e0ed867bSAlp Dener 
137e0ed867bSAlp Dener static PetscErrorCode TaoView_BQNK(Tao tao, PetscViewer viewer)
138e0ed867bSAlp Dener {
139e0ed867bSAlp Dener   TAO_BNK        *bnk = (TAO_BNK*)tao->data;
140e0ed867bSAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
141e0ed867bSAlp Dener   PetscBool      isascii;
142e0ed867bSAlp Dener 
143e0ed867bSAlp Dener   PetscFunctionBegin;
144*9566063dSJacob Faibussowitsch   PetscCall(TaoView_BNK(tao, viewer));
145*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
146e0ed867bSAlp Dener   if (isascii) {
147*9566063dSJacob Faibussowitsch     PetscCall(PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO));
148*9566063dSJacob Faibussowitsch     PetscCall(MatView(bqnk->B, viewer));
149*9566063dSJacob Faibussowitsch     PetscCall(PetscViewerPopFormat(viewer));
150e0ed867bSAlp Dener   }
151e0ed867bSAlp Dener   PetscFunctionReturn(0);
152e0ed867bSAlp Dener }
153e0ed867bSAlp Dener 
154e0ed867bSAlp Dener static PetscErrorCode TaoDestroy_BQNK(Tao tao)
155e0ed867bSAlp Dener {
156e0ed867bSAlp Dener   TAO_BNK        *bnk = (TAO_BNK*)tao->data;
157e0ed867bSAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
158e0ed867bSAlp Dener 
159e0ed867bSAlp Dener   PetscFunctionBegin;
160*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&bnk->Hpre_inactive));
161*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&bnk->H_inactive));
162*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&bqnk->B));
163*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(bnk->ctx));
164*9566063dSJacob Faibussowitsch   PetscCall(TaoDestroy_BNK(tao));
165e0ed867bSAlp Dener   PetscFunctionReturn(0);
166e0ed867bSAlp Dener }
167e0ed867bSAlp Dener 
168e0ed867bSAlp Dener PETSC_INTERN PetscErrorCode TaoCreate_BQNK(Tao tao)
169e0ed867bSAlp Dener {
170e0ed867bSAlp Dener   TAO_BNK        *bnk;
171e0ed867bSAlp Dener   TAO_BQNK       *bqnk;
172e0ed867bSAlp Dener 
173e0ed867bSAlp Dener   PetscFunctionBegin;
174*9566063dSJacob Faibussowitsch   PetscCall(TaoCreate_BNK(tao));
175414d97d3SAlp Dener   tao->ops->solve = TaoSolve_BQNK;
176e0ed867bSAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BQNK;
177e0ed867bSAlp Dener   tao->ops->destroy = TaoDestroy_BQNK;
178e0ed867bSAlp Dener   tao->ops->view = TaoView_BQNK;
1794f4fdda4SAlp Dener   tao->ops->setup = TaoSetUp_BQNK;
180e0ed867bSAlp Dener 
181e0ed867bSAlp Dener   bnk = (TAO_BNK *)tao->data;
182e0ed867bSAlp Dener   bnk->computehessian = TaoBQNKComputeHessian;
183e0ed867bSAlp Dener   bnk->computestep = TaoBQNKComputeStep;
184e0ed867bSAlp Dener   bnk->init_type = BNK_INIT_DIRECTION;
185e0ed867bSAlp Dener 
186*9566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(tao,&bqnk));
187e0ed867bSAlp Dener   bnk->ctx = (void*)bqnk;
188f5766c09SAlp Dener   bqnk->is_spd = PETSC_TRUE;
189e0ed867bSAlp Dener 
190*9566063dSJacob Faibussowitsch   PetscCall(MatCreate(PetscObjectComm((PetscObject)tao), &bqnk->B));
191*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)bqnk->B, (PetscObject)tao, 1));
192*9566063dSJacob Faibussowitsch   PetscCall(MatSetType(bqnk->B, MATLMVMSR1));
193e0ed867bSAlp Dener   PetscFunctionReturn(0);
194e0ed867bSAlp Dener }
195f5766c09SAlp Dener 
196414d97d3SAlp Dener /*@
197414d97d3SAlp Dener    TaoGetLMVMMatrix - Returns a pointer to the internal LMVM matrix. Valid
198414d97d3SAlp Dener    only for quasi-Newton family of methods.
199414d97d3SAlp Dener 
200414d97d3SAlp Dener    Input Parameters:
201414d97d3SAlp Dener .  tao - Tao solver context
202414d97d3SAlp Dener 
203414d97d3SAlp Dener    Output Parameters:
204414d97d3SAlp Dener .  B - LMVM matrix
205414d97d3SAlp Dener 
206414d97d3SAlp Dener    Level: advanced
207414d97d3SAlp Dener 
208414d97d3SAlp Dener .seealso: TAOBQNLS, TAOBQNKLS, TAOBQNKTL, TAOBQNKTR, MATLMVM, TaoSetLMVMMatrix()
209414d97d3SAlp Dener @*/
210f5766c09SAlp Dener PetscErrorCode TaoGetLMVMMatrix(Tao tao, Mat *B)
211f5766c09SAlp Dener {
212f5766c09SAlp Dener   TAO_BNK        *bnk = (TAO_BNK*)tao->data;
213f5766c09SAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
214414d97d3SAlp Dener   PetscBool      flg = PETSC_FALSE;
215f5766c09SAlp Dener 
216f5766c09SAlp Dener   PetscFunctionBegin;
217*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)tao, &flg, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, ""));
2183c859ba3SBarry Smith   PetscCheck(flg,PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM Matrix only exists for quasi-Newton algorithms");
219f5766c09SAlp Dener   *B = bqnk->B;
220f5766c09SAlp Dener   PetscFunctionReturn(0);
221f5766c09SAlp Dener }
222414d97d3SAlp Dener 
223414d97d3SAlp Dener /*@
224414d97d3SAlp Dener    TaoSetLMVMMatrix - Sets an external LMVM matrix into the Tao solver. Valid
225414d97d3SAlp Dener    only for quasi-Newton family of methods.
226414d97d3SAlp Dener 
227414d97d3SAlp Dener    QN family of methods create their own LMVM matrices and users who wish to
228414d97d3SAlp Dener    manipulate this matrix should use TaoGetLMVMMatrix() instead.
229414d97d3SAlp Dener 
230414d97d3SAlp Dener    Input Parameters:
231414d97d3SAlp Dener +  tao - Tao solver context
232414d97d3SAlp Dener -  B - LMVM matrix
233414d97d3SAlp Dener 
234414d97d3SAlp Dener    Level: advanced
235414d97d3SAlp Dener 
236414d97d3SAlp Dener .seealso: TAOBQNLS, TAOBQNKLS, TAOBQNKTL, TAOBQNKTR, MATLMVM, TaoGetLMVMMatrix()
237414d97d3SAlp Dener @*/
238414d97d3SAlp Dener PetscErrorCode TaoSetLMVMMatrix(Tao tao, Mat B)
239414d97d3SAlp Dener {
240414d97d3SAlp Dener   TAO_BNK        *bnk = (TAO_BNK*)tao->data;
241414d97d3SAlp Dener   TAO_BQNK       *bqnk = (TAO_BQNK*)bnk->ctx;
242414d97d3SAlp Dener   PetscBool      flg = PETSC_FALSE;
243414d97d3SAlp Dener 
244414d97d3SAlp Dener   PetscFunctionBegin;
245*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompareAny((PetscObject)tao, &flg, TAOBQNLS, TAOBQNKLS, TAOBQNKTR, TAOBQNKTL, ""));
2463c859ba3SBarry Smith   PetscCheck(flg,PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM Matrix only exists for quasi-Newton algorithms");
247*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectBaseTypeCompare((PetscObject)B, MATLMVM, &flg));
2483c859ba3SBarry Smith   PetscCheck(flg,PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Given matrix is not an LMVM matrix");
249414d97d3SAlp Dener   if (bqnk->B) {
250*9566063dSJacob Faibussowitsch     PetscCall(MatDestroy(&bqnk->B));
251414d97d3SAlp Dener   }
252*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectReference((PetscObject)B));
253414d97d3SAlp Dener   bqnk->B = B;
254414d97d3SAlp Dener   PetscFunctionReturn(0);
255414d97d3SAlp Dener }
256