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