1*e0ed867bSAlp Dener #include <../src/tao/bound/impls/bqnk/bqnk.h> 2*e0ed867bSAlp Dener #include <petscksp.h> 3*e0ed867bSAlp Dener 4*e0ed867bSAlp Dener /* Routine for computing the approximate quasi-Newton Hessian */ 5*e0ed867bSAlp Dener 6*e0ed867bSAlp Dener static PetscErrorCode TaoBQNKComputeHessian(Tao tao) 7*e0ed867bSAlp Dener { 8*e0ed867bSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 9*e0ed867bSAlp Dener TAO_BQNK *bqnk = (TAO_BQNK*)bnk->ctx; 10*e0ed867bSAlp Dener PetscErrorCode ierr; 11*e0ed867bSAlp Dener 12*e0ed867bSAlp Dener PetscFunctionBegin; 13*e0ed867bSAlp Dener /* Alias the LMVM matrix into the TAO hessian */ 14*e0ed867bSAlp Dener if (tao->hessian) { 15*e0ed867bSAlp Dener ierr = MatDestroy(&tao->hessian);CHKERRQ(ierr); 16*e0ed867bSAlp Dener } 17*e0ed867bSAlp Dener if (tao->hessian_pre) { 18*e0ed867bSAlp Dener ierr = MatDestroy(&tao->hessian_pre);CHKERRQ(ierr); 19*e0ed867bSAlp Dener } 20*e0ed867bSAlp Dener ierr = PetscObjectReference((PetscObject)bqnk->B);CHKERRQ(ierr); 21*e0ed867bSAlp Dener tao->hessian = bqnk->B; 22*e0ed867bSAlp Dener ierr = PetscObjectReference((PetscObject)bqnk->B);CHKERRQ(ierr); 23*e0ed867bSAlp Dener tao->hessian_pre = bqnk->B; 24*e0ed867bSAlp Dener /* Update the Hessian with the latest solution */ 25*e0ed867bSAlp Dener ierr = MatLMVMUpdate(tao->hessian, tao->solution, bnk->unprojected_gradient);CHKERRQ(ierr); 26*e0ed867bSAlp Dener ierr = MatLMVMResetShift(tao->hessian);CHKERRQ(ierr); 27*e0ed867bSAlp Dener /* Prepare the reduced sub-matrices for the inactive set */ 28*e0ed867bSAlp Dener if (bnk->active_idx) { 29*e0ed867bSAlp Dener ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr); 30*e0ed867bSAlp Dener ierr = MatCreateSubMatrixVirtual(tao->hessian, bnk->inactive_idx, bnk->inactive_idx, &bnk->H_inactive);CHKERRQ(ierr); 31*e0ed867bSAlp Dener } else { 32*e0ed867bSAlp Dener ierr = MatDestroy(&bnk->H_inactive);CHKERRQ(ierr); 33*e0ed867bSAlp Dener ierr = PetscObjectReference((PetscObject)tao->hessian);CHKERRQ(ierr); 34*e0ed867bSAlp Dener bnk->H_inactive = tao->hessian; 35*e0ed867bSAlp Dener } 36*e0ed867bSAlp Dener bnk->Hpre_inactive = bnk->H_inactive; 37*e0ed867bSAlp Dener PetscFunctionReturn(0); 38*e0ed867bSAlp Dener } 39*e0ed867bSAlp Dener 40*e0ed867bSAlp Dener static PetscErrorCode TaoBQNKComputeStep(Tao tao, PetscBool shift, KSPConvergedReason *ksp_reason) 41*e0ed867bSAlp Dener { 42*e0ed867bSAlp Dener TAO_BNK *bnk = (TAO_BNK *)tao->data; 43*e0ed867bSAlp Dener TAO_BQNK *bqnk = (TAO_BQNK*)bnk->ctx; 44*e0ed867bSAlp Dener PetscErrorCode ierr; 45*e0ed867bSAlp Dener 46*e0ed867bSAlp Dener PetscFunctionBegin; 47*e0ed867bSAlp Dener ierr = TaoBNKComputeStep(tao, shift, ksp_reason);CHKERRQ(ierr); 48*e0ed867bSAlp Dener if (*ksp_reason < 0) { 49*e0ed867bSAlp Dener /* Krylov solver failed to converge so reset the LMVM matrix */ 50*e0ed867bSAlp Dener ierr = MatLMVMReset(bqnk->B, PETSC_FALSE);CHKERRQ(ierr); 51*e0ed867bSAlp Dener } 52*e0ed867bSAlp Dener PetscFunctionReturn(0); 53*e0ed867bSAlp Dener } 54*e0ed867bSAlp Dener 55*e0ed867bSAlp Dener static PetscErrorCode TaoSetFromOptions_BQNK(PetscOptionItems *PetscOptionsObject, Tao tao) 56*e0ed867bSAlp Dener { 57*e0ed867bSAlp Dener TAO_BNK *bnk = (TAO_BNK*)tao->data; 58*e0ed867bSAlp Dener TAO_BQNK *bqnk = (TAO_BQNK*)bnk->ctx; 59*e0ed867bSAlp Dener PetscErrorCode ierr; 60*e0ed867bSAlp Dener PC pc; 61*e0ed867bSAlp Dener PetscBool is_lmvm, is_sym; 62*e0ed867bSAlp Dener 63*e0ed867bSAlp Dener PetscFunctionBegin; 64*e0ed867bSAlp Dener ierr = TaoSetFromOptions_BNK(PetscOptionsObject, tao);CHKERRQ(ierr); 65*e0ed867bSAlp Dener /* Make sure the interpolation method is disabled for trust region initialization */ 66*e0ed867bSAlp Dener if (bnk->init_type == BNK_INIT_INTERPOLATION) bnk->init_type = BNK_INIT_DIRECTION; 67*e0ed867bSAlp Dener /* Make sure the KSP solver is a CG method and the preconditioner is disabled */ 68*e0ed867bSAlp Dener if (!bnk->is_nash && !bnk->is_stcg && !bnk->is_gltr) SETERRQ(PETSC_COMM_SELF,1,"Must use a trust-region CG method for KSP (KSPNASH, KSPSTCG, KSPGLTR)"); 69*e0ed867bSAlp Dener ierr = KSPGetPC(tao->ksp, &pc);CHKERRQ(ierr); 70*e0ed867bSAlp Dener ierr = PCSetType(pc, PCNONE);CHKERRQ(ierr); 71*e0ed867bSAlp Dener /* Read mat options and check type and properties */ 72*e0ed867bSAlp Dener ierr = MatSetFromOptions(bqnk->B);CHKERRQ(ierr); 73*e0ed867bSAlp Dener ierr = PetscObjectBaseTypeCompare((PetscObject)bqnk->B, MATLMVM, &is_lmvm);CHKERRQ(ierr); 74*e0ed867bSAlp Dener if (!is_lmvm) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "Matrix must be an LMVM-type"); 75*e0ed867bSAlp Dener ierr = MatGetOption(bqnk->B, MAT_SYMMETRIC, &is_sym);CHKERRQ(ierr); 76*e0ed867bSAlp Dener if (!is_sym) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ARG_INCOMP, "LMVM matrix must be symmetric"); 77*e0ed867bSAlp Dener PetscFunctionReturn(0); 78*e0ed867bSAlp Dener } 79*e0ed867bSAlp Dener 80*e0ed867bSAlp Dener static PetscErrorCode TaoView_BQNK(Tao tao, PetscViewer viewer) 81*e0ed867bSAlp Dener { 82*e0ed867bSAlp Dener TAO_BNK *bnk = (TAO_BNK*)tao->data; 83*e0ed867bSAlp Dener TAO_BQNK *bqnk = (TAO_BQNK*)bnk->ctx; 84*e0ed867bSAlp Dener PetscErrorCode ierr; 85*e0ed867bSAlp Dener PetscBool isascii; 86*e0ed867bSAlp Dener 87*e0ed867bSAlp Dener PetscFunctionBegin; 88*e0ed867bSAlp Dener ierr = TaoView_BNK(tao, viewer);CHKERRQ(ierr); 89*e0ed867bSAlp Dener PetscFunctionBegin; 90*e0ed867bSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr); 91*e0ed867bSAlp Dener if (isascii) { 92*e0ed867bSAlp Dener ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr); 93*e0ed867bSAlp Dener ierr = MatView(bqnk->B, viewer);CHKERRQ(ierr); 94*e0ed867bSAlp Dener ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 95*e0ed867bSAlp Dener } 96*e0ed867bSAlp Dener PetscFunctionReturn(0); 97*e0ed867bSAlp Dener } 98*e0ed867bSAlp Dener 99*e0ed867bSAlp Dener static PetscErrorCode TaoDestroy_BQNK(Tao tao) 100*e0ed867bSAlp Dener { 101*e0ed867bSAlp Dener TAO_BNK *bnk = (TAO_BNK*)tao->data; 102*e0ed867bSAlp Dener TAO_BQNK *bqnk = (TAO_BQNK*)bnk->ctx; 103*e0ed867bSAlp Dener PetscErrorCode ierr; 104*e0ed867bSAlp Dener 105*e0ed867bSAlp Dener PetscFunctionBegin; 106*e0ed867bSAlp Dener ierr = MatDestroy(&bqnk->B);CHKERRQ(ierr); 107*e0ed867bSAlp Dener ierr = PetscFree(bnk->ctx);CHKERRQ(ierr); 108*e0ed867bSAlp Dener ierr = TaoDestroy_BNK(tao);CHKERRQ(ierr); 109*e0ed867bSAlp Dener PetscFunctionReturn(0); 110*e0ed867bSAlp Dener } 111*e0ed867bSAlp Dener 112*e0ed867bSAlp Dener PETSC_INTERN PetscErrorCode TaoCreate_BQNK(Tao tao) 113*e0ed867bSAlp Dener { 114*e0ed867bSAlp Dener TAO_BNK *bnk; 115*e0ed867bSAlp Dener TAO_BQNK *bqnk; 116*e0ed867bSAlp Dener PetscErrorCode ierr; 117*e0ed867bSAlp Dener 118*e0ed867bSAlp Dener PetscFunctionBegin; 119*e0ed867bSAlp Dener ierr = TaoCreate_BNK(tao);CHKERRQ(ierr); 120*e0ed867bSAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BQNK; 121*e0ed867bSAlp Dener tao->ops->destroy = TaoDestroy_BQNK; 122*e0ed867bSAlp Dener tao->ops->view = TaoView_BQNK; 123*e0ed867bSAlp Dener 124*e0ed867bSAlp Dener bnk = (TAO_BNK *)tao->data; 125*e0ed867bSAlp Dener bnk->computehessian = TaoBQNKComputeHessian; 126*e0ed867bSAlp Dener bnk->computestep = TaoBQNKComputeStep; 127*e0ed867bSAlp Dener bnk->init_type = BNK_INIT_DIRECTION; 128*e0ed867bSAlp Dener 129*e0ed867bSAlp Dener ierr = PetscNewLog(tao,&bqnk);CHKERRQ(ierr); 130*e0ed867bSAlp Dener bnk->ctx = (void*)bqnk; 131*e0ed867bSAlp Dener 132*e0ed867bSAlp Dener ierr = MatCreate(PetscObjectComm((PetscObject)tao), &bqnk->B);CHKERRQ(ierr); 133*e0ed867bSAlp Dener ierr = PetscObjectIncrementTabLevel((PetscObject)bqnk->B, (PetscObject)tao, 1);CHKERRQ(ierr); 134*e0ed867bSAlp Dener ierr = MatSetOptionsPrefix(bqnk->B, "tao_bqnk_");CHKERRQ(ierr); 135*e0ed867bSAlp Dener ierr = MatSetType(bqnk->B, MATLMVMSR1);CHKERRQ(ierr); 136*e0ed867bSAlp Dener PetscFunctionReturn(0); 137*e0ed867bSAlp Dener }