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