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