xref: /petsc/src/tao/leastsquares/impls/brgn/brgn.c (revision 737f463ab30e8a11bf8f036b04a75b5d358c645b)
1*737f463aSAlp Dener #include <../src/tao/leastsquares/impls/brgn/brgn.h>
2*737f463aSAlp Dener 
3*737f463aSAlp Dener static PetscErrorCode GNHessianProd(Mat H, Vec in, Vec out)
4*737f463aSAlp Dener {
5*737f463aSAlp Dener   TAO_BRGN       *gn;
6*737f463aSAlp Dener   PetscErrorCode        ierr;
7*737f463aSAlp Dener 
8*737f463aSAlp Dener   PetscFunctionBegin;
9*737f463aSAlp Dener   ierr = MatShellGetContext(H, &gn);CHKERRQ(ierr);
10*737f463aSAlp Dener   ierr = MatMult(gn->subsolver->ls_jac, in, gn->r_work);CHKERRQ(ierr);
11*737f463aSAlp Dener   ierr = MatMultTranspose(gn->subsolver->ls_jac, gn->r_work, out);CHKERRQ(ierr);
12*737f463aSAlp Dener   ierr = VecAXPY(out, gn->lambda, in);CHKERRQ(ierr);
13*737f463aSAlp Dener   PetscFunctionReturn(0);
14*737f463aSAlp Dener }
15*737f463aSAlp Dener 
16*737f463aSAlp Dener static PetscErrorCode GNObjectiveGradientEval(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr)
17*737f463aSAlp Dener {
18*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)ptr;
19*737f463aSAlp Dener   PetscScalar           xnorm2;
20*737f463aSAlp Dener   PetscErrorCode        ierr;
21*737f463aSAlp Dener 
22*737f463aSAlp Dener   PetscFunctionBegin;
23*737f463aSAlp Dener   ierr = TaoComputeResidual(tao, X, tao->ls_res);CHKERRQ(ierr);
24*737f463aSAlp Dener   ierr = VecDotBegin(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr);
25*737f463aSAlp Dener   ierr = VecAXPBY(gn->x_work, gn->lambda, 0.0, X);CHKERRQ(ierr);
26*737f463aSAlp Dener   ierr = VecDotBegin(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr);
27*737f463aSAlp Dener   ierr = VecDotEnd(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr);
28*737f463aSAlp Dener   ierr = VecDotEnd(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr);
29*737f463aSAlp Dener   *fcn += xnorm2;
30*737f463aSAlp Dener 
31*737f463aSAlp Dener   ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr);
32*737f463aSAlp Dener   ierr = MatMultTranspose(tao->ls_jac, tao->ls_res, G);CHKERRQ(ierr);
33*737f463aSAlp Dener   ierr = VecAXPY(G, gn->lambda, X);CHKERRQ(ierr);
34*737f463aSAlp Dener   PetscFunctionReturn(0);
35*737f463aSAlp Dener }
36*737f463aSAlp Dener 
37*737f463aSAlp Dener static PetscErrorCode GNComputeHessian(Tao tao, Vec X, Mat H, Mat Hpre, void *ptr)
38*737f463aSAlp Dener {
39*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)ptr;
40*737f463aSAlp Dener   PetscErrorCode        ierr;
41*737f463aSAlp Dener 
42*737f463aSAlp Dener   PetscFunctionBegin;
43*737f463aSAlp Dener   if (gn->explicit_H) {
44*737f463aSAlp Dener     ierr = MatTransposeMatMult(tao->ls_jac, tao->ls_jac, MAT_REUSE_MATRIX, PETSC_DEFAULT, &H);CHKERRQ(ierr);
45*737f463aSAlp Dener     ierr = MatShift(H, gn->lambda);CHKERRQ(ierr);
46*737f463aSAlp Dener   }
47*737f463aSAlp Dener   PetscFunctionReturn(0);
48*737f463aSAlp Dener }
49*737f463aSAlp Dener 
50*737f463aSAlp Dener static PetscErrorCode TaoSolve_BRGN(Tao tao)
51*737f463aSAlp Dener {
52*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)tao->data;
53*737f463aSAlp Dener   PetscErrorCode        ierr;
54*737f463aSAlp Dener 
55*737f463aSAlp Dener   PetscFunctionBegin;
56*737f463aSAlp Dener   ierr = TaoSolve(gn->subsolver);CHKERRQ(ierr);
57*737f463aSAlp Dener   PetscFunctionReturn(0);
58*737f463aSAlp Dener }
59*737f463aSAlp Dener 
60*737f463aSAlp Dener static PetscErrorCode TaoSetFromOptions_BRGN(PetscOptionItems *PetscOptionsObject,Tao tao)
61*737f463aSAlp Dener {
62*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)tao->data;
63*737f463aSAlp Dener   PetscErrorCode        ierr;
64*737f463aSAlp Dener 
65*737f463aSAlp Dener   PetscFunctionBegin;
66*737f463aSAlp Dener   ierr = PetscOptionsHead(PetscOptionsObject,"Gauss-Newton method for least-squares problems using Tikhonov regularization");CHKERRQ(ierr);
67*737f463aSAlp Dener   ierr = PetscOptionsReal("-tao_brgn_lambda", "Tikhonov regularization factor", "", gn->lambda, &gn->lambda, NULL);CHKERRQ(ierr);
68*737f463aSAlp Dener   ierr = PetscOptionsBool("-tao_brgn_explicit_hessian","(developer) explicitly perform MatTransposeMatMult for the least squares Jacobian","",gn->explicit_H,&gn->explicit_H,NULL);CHKERRQ(ierr);
69*737f463aSAlp Dener   ierr = PetscOptionsTail();CHKERRQ(ierr);
70*737f463aSAlp Dener   ierr = TaoSetFromOptions(gn->subsolver);CHKERRQ(ierr);
71*737f463aSAlp Dener   PetscFunctionReturn(0);
72*737f463aSAlp Dener }
73*737f463aSAlp Dener 
74*737f463aSAlp Dener static PetscErrorCode TaoView_BRGN(Tao tao, PetscViewer viewer)
75*737f463aSAlp Dener {
76*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)tao->data;
77*737f463aSAlp Dener   PetscErrorCode        ierr;
78*737f463aSAlp Dener 
79*737f463aSAlp Dener   PetscFunctionBegin;
80*737f463aSAlp Dener   ierr = TaoView(gn->subsolver, viewer);CHKERRQ(ierr);
81*737f463aSAlp Dener   PetscFunctionReturn(0);
82*737f463aSAlp Dener }
83*737f463aSAlp Dener 
84*737f463aSAlp Dener static PetscErrorCode TaoSetUp_BRGN(Tao tao)
85*737f463aSAlp Dener {
86*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)tao->data;
87*737f463aSAlp Dener   PetscErrorCode        ierr;
88*737f463aSAlp Dener   PetscBool             is_bnls, is_bntr, is_bntl;
89*737f463aSAlp Dener   PetscInt              i, nx, Nx;
90*737f463aSAlp Dener 
91*737f463aSAlp Dener   PetscFunctionBegin;
92*737f463aSAlp Dener   if (!tao->ls_res) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualRoutine() must be called before setup!");
93*737f463aSAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNLS, &is_bnls);CHKERRQ(ierr);
94*737f463aSAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTR, &is_bntr);CHKERRQ(ierr);
95*737f463aSAlp Dener   ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTL, &is_bntl);CHKERRQ(ierr);
96*737f463aSAlp Dener   if ((is_bnls || is_bntr || is_bntl) && !tao->ls_jac) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualJacobianRoutine() must be called before setup!");
97*737f463aSAlp Dener   if (!gn->x_work){
98*737f463aSAlp Dener     ierr = VecDuplicate(tao->solution, &gn->x_work);CHKERRQ(ierr);
99*737f463aSAlp Dener   }
100*737f463aSAlp Dener   if (!gn->r_work){
101*737f463aSAlp Dener     ierr = VecDuplicate(tao->ls_res, &gn->r_work);CHKERRQ(ierr);
102*737f463aSAlp Dener   }
103*737f463aSAlp Dener   /* Hessian setup */
104*737f463aSAlp Dener   if (gn->explicit_H) {
105*737f463aSAlp Dener     ierr = MatDestroy(&gn->H);CHKERRQ(ierr);
106*737f463aSAlp Dener     ierr = MatTransposeMatMult(tao->ls_jac, tao->ls_jac, MAT_INITIAL_MATRIX, PETSC_DEFAULT, &gn->H);CHKERRQ(ierr);
107*737f463aSAlp Dener   } else {
108*737f463aSAlp Dener     ierr = VecGetLocalSize(tao->solution, &nx);CHKERRQ(ierr);
109*737f463aSAlp Dener     ierr = VecGetSize(tao->solution, &Nx);CHKERRQ(ierr);
110*737f463aSAlp Dener     ierr = MatSetSizes(gn->H, nx, nx, Nx, Nx);CHKERRQ(ierr);
111*737f463aSAlp Dener     ierr = MatSetType(gn->H, MATSHELL);CHKERRQ(ierr);
112*737f463aSAlp Dener     ierr = MatSetUp(gn->H);CHKERRQ(ierr);
113*737f463aSAlp Dener     ierr = MatShellSetOperation(gn->H, MATOP_MULT, (void (*)(void))GNHessianProd);CHKERRQ(ierr);
114*737f463aSAlp Dener     ierr = MatShellSetContext(gn->H, (void*)gn);CHKERRQ(ierr);
115*737f463aSAlp Dener   }
116*737f463aSAlp Dener   /* Subsolver setup */
117*737f463aSAlp Dener   ierr = TaoSetInitialVector(gn->subsolver, tao->solution);CHKERRQ(ierr);
118*737f463aSAlp Dener   ierr = TaoSetTolerances(gn->subsolver, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr);
119*737f463aSAlp Dener   if (tao->bounded) {
120*737f463aSAlp Dener     ierr = TaoSetVariableBounds(gn->subsolver, tao->XL, tao->XU);CHKERRQ(ierr);
121*737f463aSAlp Dener   }
122*737f463aSAlp Dener   ierr = TaoSetResidualRoutine(gn->subsolver, tao->ls_res, tao->ops->computeresidual, tao->user_lsresP);CHKERRQ(ierr);
123*737f463aSAlp Dener   ierr = TaoSetResidualJacobianRoutine(gn->subsolver, tao->ls_jac, tao->ls_jac, tao->ops->computeresidualjacobian, tao->user_lsjacP);CHKERRQ(ierr);
124*737f463aSAlp Dener   ierr = TaoSetObjectiveAndGradientRoutine(gn->subsolver, GNObjectiveGradientEval, (void*)gn);CHKERRQ(ierr);
125*737f463aSAlp Dener   ierr = TaoSetHessianRoutine(gn->subsolver, gn->H, gn->H, GNComputeHessian, (void*)gn);CHKERRQ(ierr);
126*737f463aSAlp Dener   for (i=0; i<tao->numbermonitors; ++i) {
127*737f463aSAlp Dener     ierr = TaoSetMonitor(gn->subsolver, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr);
128*737f463aSAlp Dener     ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr);
129*737f463aSAlp Dener   }
130*737f463aSAlp Dener   ierr = TaoSetUp(gn->subsolver);CHKERRQ(ierr);
131*737f463aSAlp Dener   PetscFunctionReturn(0);
132*737f463aSAlp Dener }
133*737f463aSAlp Dener 
134*737f463aSAlp Dener static PetscErrorCode TaoDestroy_BRGN(Tao tao)
135*737f463aSAlp Dener {
136*737f463aSAlp Dener   TAO_BRGN              *gn = (TAO_BRGN *)tao->data;
137*737f463aSAlp Dener   PetscErrorCode        ierr;
138*737f463aSAlp Dener 
139*737f463aSAlp Dener   PetscFunctionBegin;
140*737f463aSAlp Dener   if (tao->setupcalled) {
141*737f463aSAlp Dener     ierr = VecDestroy(&gn->x_work);CHKERRQ(ierr);
142*737f463aSAlp Dener     ierr = VecDestroy(&gn->r_work);CHKERRQ(ierr);
143*737f463aSAlp Dener   }
144*737f463aSAlp Dener   ierr = MatDestroy(&gn->H);CHKERRQ(ierr);
145*737f463aSAlp Dener   ierr = TaoDestroy(&gn->subsolver);CHKERRQ(ierr);
146*737f463aSAlp Dener   ierr = PetscFree(tao->data);CHKERRQ(ierr);
147*737f463aSAlp Dener   PetscFunctionReturn(0);
148*737f463aSAlp Dener }
149*737f463aSAlp Dener 
150*737f463aSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BRGN(Tao tao)
151*737f463aSAlp Dener {
152*737f463aSAlp Dener   TAO_BRGN       *gn;
153*737f463aSAlp Dener   PetscErrorCode ierr;
154*737f463aSAlp Dener 
155*737f463aSAlp Dener   PetscFunctionBegin;
156*737f463aSAlp Dener   ierr = PetscNewLog(tao,&gn);CHKERRQ(ierr);
157*737f463aSAlp Dener 
158*737f463aSAlp Dener   tao->ops->destroy = TaoDestroy_BRGN;
159*737f463aSAlp Dener   tao->ops->setup = TaoSetUp_BRGN;
160*737f463aSAlp Dener   tao->ops->setfromoptions = TaoSetFromOptions_BRGN;
161*737f463aSAlp Dener   tao->ops->view = TaoView_BRGN;
162*737f463aSAlp Dener   tao->ops->solve = TaoSolve_BRGN;
163*737f463aSAlp Dener 
164*737f463aSAlp Dener   tao->data = (void*)gn;
165*737f463aSAlp Dener   gn->lambda = 1.0;
166*737f463aSAlp Dener   gn->explicit_H = PETSC_FALSE;
167*737f463aSAlp Dener   gn->assembled_H = PETSC_FALSE;
168*737f463aSAlp Dener 
169*737f463aSAlp Dener   ierr = MatCreate(PetscObjectComm((PetscObject)tao), &gn->H);CHKERRQ(ierr);
170*737f463aSAlp Dener   ierr = MatSetOptionsPrefix(gn->H, "tao_brgn_hessian_");CHKERRQ(ierr);
171*737f463aSAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)gn->H, (PetscObject)tao, 1);CHKERRQ(ierr);
172*737f463aSAlp Dener 
173*737f463aSAlp Dener   ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &gn->subsolver);CHKERRQ(ierr);
174*737f463aSAlp Dener   ierr = TaoSetType(gn->subsolver, TAOBNLS);CHKERRQ(ierr);
175*737f463aSAlp Dener   ierr = TaoSetOptionsPrefix(gn->subsolver, "tao_brgn_subsolver_");CHKERRQ(ierr);
176*737f463aSAlp Dener   ierr = PetscObjectIncrementTabLevel((PetscObject)gn->subsolver, (PetscObject)tao, 1);CHKERRQ(ierr);
177*737f463aSAlp Dener   PetscFunctionReturn(0);
178*737f463aSAlp Dener }
179*737f463aSAlp Dener 
180*737f463aSAlp Dener /*@C
181*737f463aSAlp Dener   TaoBRGNSetTikhonovLambda - Set the Tikhonov regularization factor for the Gauss-Newton least-squares algorithm
182*737f463aSAlp Dener 
183*737f463aSAlp Dener   Collective on Tao
184*737f463aSAlp Dener 
185*737f463aSAlp Dener   Level: developer
186*737f463aSAlp Dener 
187*737f463aSAlp Dener   Input Parameters:
188*737f463aSAlp Dener +  tao - the Tao solver context
189*737f463aSAlp Dener -  lambda - Tikhonov regularization factor
190*737f463aSAlp Dener @*/
191*737f463aSAlp Dener PetscErrorCode TaoBRGNSetTikhonovLambda(Tao tao, PetscReal lambda)
192*737f463aSAlp Dener {
193*737f463aSAlp Dener   TAO_BRGN       *gn = (TAO_BRGN *)tao->data;
194*737f463aSAlp Dener 
195*737f463aSAlp Dener   PetscFunctionBegin;
196*737f463aSAlp Dener   gn->lambda = lambda;
197*737f463aSAlp Dener   PetscFunctionReturn(0);
198*737f463aSAlp Dener }
199