1737f463aSAlp Dener #include <../src/tao/leastsquares/impls/brgn/brgn.h> 2737f463aSAlp Dener 3*0d71dc2bSXiang Huang /* Old code 4737f463aSAlp Dener static PetscErrorCode GNHessianProd(Mat H, Vec in, Vec out) 5737f463aSAlp Dener { 6737f463aSAlp Dener TAO_BRGN *gn; 7737f463aSAlp Dener PetscErrorCode ierr; 8737f463aSAlp Dener 9737f463aSAlp Dener PetscFunctionBegin; 10737f463aSAlp Dener ierr = MatShellGetContext(H, &gn);CHKERRQ(ierr); 11737f463aSAlp Dener ierr = MatMult(gn->subsolver->ls_jac, in, gn->r_work);CHKERRQ(ierr); 12737f463aSAlp Dener ierr = MatMultTranspose(gn->subsolver->ls_jac, gn->r_work, out);CHKERRQ(ierr); 13737f463aSAlp Dener ierr = VecAXPY(out, gn->lambda, in);CHKERRQ(ierr); 14737f463aSAlp Dener PetscFunctionReturn(0); 15737f463aSAlp Dener } 16737f463aSAlp Dener 17737f463aSAlp Dener static PetscErrorCode GNObjectiveGradientEval(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr) 18737f463aSAlp Dener { 19737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)ptr; 20737f463aSAlp Dener PetscScalar xnorm2; 21737f463aSAlp Dener PetscErrorCode ierr; 22737f463aSAlp Dener 23737f463aSAlp Dener PetscFunctionBegin; 24737f463aSAlp Dener ierr = TaoComputeResidual(tao, X, tao->ls_res);CHKERRQ(ierr); 25737f463aSAlp Dener ierr = VecDotBegin(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 26e1e80dc8SAlp Dener ierr = VecAXPBYPCZ(gn->x_work, 1.0, -1.0, 0.0, X, gn->x_old);CHKERRQ(ierr); 27737f463aSAlp Dener ierr = VecDotBegin(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr); 28737f463aSAlp Dener ierr = VecDotEnd(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 29737f463aSAlp Dener ierr = VecDotEnd(gn->x_work, gn->x_work, &xnorm2);CHKERRQ(ierr); 30e1e80dc8SAlp Dener *fcn = 0.5*(*fcn) + 0.5*gn->lambda*xnorm2; 31737f463aSAlp Dener 32737f463aSAlp Dener ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 33737f463aSAlp Dener ierr = MatMultTranspose(tao->ls_jac, tao->ls_res, G);CHKERRQ(ierr); 34e1e80dc8SAlp Dener ierr = VecAXPBYPCZ(G, gn->lambda, -gn->lambda, 1.0, X, gn->x_old);CHKERRQ(ierr); 35737f463aSAlp Dener PetscFunctionReturn(0); 36737f463aSAlp Dener } 37*0d71dc2bSXiang Huang */ 38*0d71dc2bSXiang Huang 39*0d71dc2bSXiang Huang static PetscErrorCode GNHessianProd(Mat H, Vec in, Vec out) 40*0d71dc2bSXiang Huang { 41*0d71dc2bSXiang Huang TAO_BRGN *gn; 42*0d71dc2bSXiang Huang PetscInt N = 3; /* dimension of X hack, to change size 3 to VecGetSize() from Vec X*/ 43*0d71dc2bSXiang Huang PetscScalar epsilon = 1e-6; /*XH: added epsilon to approximate L1-norm with sqrt(x^2+epsilon^2)-epsilon*/ 44*0d71dc2bSXiang Huang PetscErrorCode ierr; 45*0d71dc2bSXiang Huang Vec xE, tmp; /* xE: vector sqrt(x.^2 + epsilon^2) that is reused multiple times */ 46*0d71dc2bSXiang Huang 47*0d71dc2bSXiang Huang PetscFunctionBegin; 48*0d71dc2bSXiang Huang /* Allocate vectors */ 49*0d71dc2bSXiang Huang 50*0d71dc2bSXiang Huang /* XH: Use x_work or r_work instead and do not create new vectors */ 51*0d71dc2bSXiang Huang ierr = VecCreateSeq(MPI_COMM_SELF,N,&xE);CHKERRQ(ierr); 52*0d71dc2bSXiang Huang ierr = VecCreateSeq(MPI_COMM_SELF,N,&tmp);CHKERRQ(ierr); 53*0d71dc2bSXiang Huang 54*0d71dc2bSXiang Huang ierr = MatShellGetContext(H, &gn);CHKERRQ(ierr); 55*0d71dc2bSXiang Huang ierr = MatMult(gn->subsolver->ls_jac, in, gn->r_work);CHKERRQ(ierr); 56*0d71dc2bSXiang Huang ierr = MatMultTranspose(gn->subsolver->ls_jac, gn->r_work, out);CHKERRQ(ierr); 57*0d71dc2bSXiang Huang 58*0d71dc2bSXiang Huang /* XH: Use the sparse diagonal vector diag that has already been computed. Code should just be the VecAXPY() */ 59*0d71dc2bSXiang Huang 60*0d71dc2bSXiang Huang /* out = out + lambda*epsilon^2*(in./xE.^3) */ 61*0d71dc2bSXiang Huang /* xE = sqrt(x.^2+epsilon^2). Should we reuse code/result of xE from GNObjectiveGradientEval()?*/ 62*0d71dc2bSXiang Huang ierr = VecPointwiseMult(xE, gn->x_old, gn->x_old);CHKERRQ(ierr); /* hack, todo: change to X, how to add X? */ 63*0d71dc2bSXiang Huang ierr = VecShift(xE, epsilon*epsilon);CHKERRQ(ierr); 64*0d71dc2bSXiang Huang ierr = VecCopy(xE, tmp);CHKERRQ(ierr); /* tmp = xE.^2 */ 65*0d71dc2bSXiang Huang ierr = VecSqrtAbs(xE);CHKERRQ(ierr); 66*0d71dc2bSXiang Huang ierr = VecPointwiseMult(tmp, tmp, xE);CHKERRQ(ierr); /* tmp = xE.^3 */ 67*0d71dc2bSXiang Huang ierr = VecPointwiseDivide(tmp, in, tmp);CHKERRQ(ierr); /* tmp = in./xE.^3 */ 68*0d71dc2bSXiang Huang ierr = VecAXPY(out, gn->lambda * epsilon * epsilon, tmp);CHKERRQ(ierr); 69*0d71dc2bSXiang Huang 70*0d71dc2bSXiang Huang /* Free PETSc data structures */ 71*0d71dc2bSXiang Huang ierr = VecDestroy(&xE);CHKERRQ(ierr); 72*0d71dc2bSXiang Huang ierr = VecDestroy(&tmp);CHKERRQ(ierr); 73*0d71dc2bSXiang Huang PetscFunctionReturn(0); 74*0d71dc2bSXiang Huang } 75*0d71dc2bSXiang Huang 76*0d71dc2bSXiang Huang static PetscErrorCode GNObjectiveGradientEval(Tao tao, Vec X, PetscReal *fcn, Vec G, void *ptr) 77*0d71dc2bSXiang Huang { 78*0d71dc2bSXiang Huang TAO_BRGN *gn = (TAO_BRGN *)ptr; 79*0d71dc2bSXiang Huang PetscInt N = 3; /* dimension of X hack, to change size 3 to VecGetSize() from Vec X*/ 80*0d71dc2bSXiang Huang PetscScalar xESum, epsilon = 1e-6;/* epsilon to approximate L1-norm with sqrt(x^2+epsilon^2)-epsilon*/ 81*0d71dc2bSXiang Huang PetscErrorCode ierr; 82*0d71dc2bSXiang Huang Vec xE; /* xE: vector sqrt(x.^2 + epsilon^2) that is reused multiple times */ 83*0d71dc2bSXiang Huang 84*0d71dc2bSXiang Huang PetscFunctionBegin; 85*0d71dc2bSXiang Huang /* Allocate vectors */ 86*0d71dc2bSXiang Huang 87*0d71dc2bSXiang Huang /* XH: Do no create vectors; use x_work or r_work */ 88*0d71dc2bSXiang Huang ierr = VecCreateSeq(MPI_COMM_SELF,N,&xE);CHKERRQ(ierr); 89*0d71dc2bSXiang Huang 90*0d71dc2bSXiang Huang ierr = TaoComputeResidual(tao, X, tao->ls_res);CHKERRQ(ierr); 91*0d71dc2bSXiang Huang ierr = VecDotBegin(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 92*0d71dc2bSXiang Huang ierr = VecDotEnd(tao->ls_res, tao->ls_res, fcn);CHKERRQ(ierr); 93*0d71dc2bSXiang Huang 94*0d71dc2bSXiang Huang /* Compute xE = sqrt(x.^2+epsilon^2) */ 95*0d71dc2bSXiang Huang 96*0d71dc2bSXiang Huang /* XH: Use epsilon from the gn structure */ 97*0d71dc2bSXiang Huang /* XH: Use VecGetSize() rather than N */ 98*0d71dc2bSXiang Huang 99*0d71dc2bSXiang Huang ierr = VecPointwiseMult(xE, X, X);CHKERRQ(ierr); 100*0d71dc2bSXiang Huang ierr = VecShift(xE, epsilon*epsilon);CHKERRQ(ierr); 101*0d71dc2bSXiang Huang ierr = VecSqrtAbs(xE);CHKERRQ(ierr); 102*0d71dc2bSXiang Huang 103*0d71dc2bSXiang Huang ierr = VecSum(xE,&xESum);CHKERRQ(ierr);CHKERRQ(ierr); 104*0d71dc2bSXiang Huang *fcn = 0.5*(*fcn) + gn->lambda*(xESum - N*epsilon); 105*0d71dc2bSXiang Huang 106*0d71dc2bSXiang Huang ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 107*0d71dc2bSXiang Huang ierr = MatMultTranspose(tao->ls_jac, tao->ls_res, G);CHKERRQ(ierr); 108*0d71dc2bSXiang Huang /* G = G + lambda*(X./xE) */ 109*0d71dc2bSXiang Huang ierr = VecPointwiseDivide(xE, X, xE);CHKERRQ(ierr); /* reuse xE = X./xE */ 110*0d71dc2bSXiang Huang ierr = VecAXPY(G, gn->lambda, xE);CHKERRQ(ierr); 111*0d71dc2bSXiang Huang 112*0d71dc2bSXiang Huang /* Free PETSc data structures */ 113*0d71dc2bSXiang Huang ierr = VecDestroy(&xE);CHKERRQ(ierr); 114*0d71dc2bSXiang Huang 115*0d71dc2bSXiang Huang PetscFunctionReturn(0); 116*0d71dc2bSXiang Huang } 117*0d71dc2bSXiang Huang 118737f463aSAlp Dener 119737f463aSAlp Dener static PetscErrorCode GNComputeHessian(Tao tao, Vec X, Mat H, Mat Hpre, void *ptr) 120737f463aSAlp Dener { 121737f463aSAlp Dener PetscErrorCode ierr; 122737f463aSAlp Dener 123737f463aSAlp Dener PetscFunctionBegin; 124e1e80dc8SAlp Dener ierr = TaoComputeResidualJacobian(tao, X, tao->ls_jac, tao->ls_jac_pre);CHKERRQ(ierr); 125*0d71dc2bSXiang Huang 126*0d71dc2bSXiang Huang /* XH: Calculate and store diagonal matrix as a vector; diag in the structure */ 127e1e80dc8SAlp Dener PetscFunctionReturn(0); 128e1e80dc8SAlp Dener } 129e1e80dc8SAlp Dener 130e1e80dc8SAlp Dener static PetscErrorCode GNHookFunction(Tao tao, PetscInt iter) 131e1e80dc8SAlp Dener { 132e1e80dc8SAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->user_update; 133e1e80dc8SAlp Dener PetscErrorCode ierr; 134e1e80dc8SAlp Dener 135e1e80dc8SAlp Dener PetscFunctionBegin; 136e1e80dc8SAlp Dener /* Update basic tao information from the subsolver */ 137e1e80dc8SAlp Dener gn->parent->nfuncs = tao->nfuncs; 138e1e80dc8SAlp Dener gn->parent->ngrads = tao->ngrads; 139e1e80dc8SAlp Dener gn->parent->nfuncgrads = tao->nfuncgrads; 140e1e80dc8SAlp Dener gn->parent->nhess = tao->nhess; 141e1e80dc8SAlp Dener gn->parent->niter = tao->niter; 142e1e80dc8SAlp Dener gn->parent->ksp_its = tao->ksp_its; 143e1e80dc8SAlp Dener gn->parent->ksp_tot_its = tao->ksp_tot_its; 144e1e80dc8SAlp Dener ierr = TaoGetConvergedReason(tao, &gn->parent->reason);CHKERRQ(ierr); 145e1e80dc8SAlp Dener /* Update the solution vectors */ 146e1e80dc8SAlp Dener if (iter == 0) { 147e1e80dc8SAlp Dener ierr = VecSet(gn->x_old, 0.0);CHKERRQ(ierr); 148e1e80dc8SAlp Dener } else { 149e1e80dc8SAlp Dener ierr = VecCopy(tao->solution, gn->x_old);CHKERRQ(ierr); 150e1e80dc8SAlp Dener ierr = VecCopy(tao->solution, gn->parent->solution);CHKERRQ(ierr); 151e1e80dc8SAlp Dener } 152e1e80dc8SAlp Dener /* Update the gradient */ 153e1e80dc8SAlp Dener ierr = VecCopy(tao->gradient, gn->parent->gradient);CHKERRQ(ierr); 154e1e80dc8SAlp Dener /* Call general purpose update function */ 155e1e80dc8SAlp Dener if (gn->parent->ops->update) { 156e1e80dc8SAlp Dener ierr = (*gn->parent->ops->update)(gn->parent, gn->parent->niter);CHKERRQ(ierr); 157737f463aSAlp Dener } 158737f463aSAlp Dener PetscFunctionReturn(0); 159737f463aSAlp Dener } 160737f463aSAlp Dener 161737f463aSAlp Dener static PetscErrorCode TaoSolve_BRGN(Tao tao) 162737f463aSAlp Dener { 163737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 164737f463aSAlp Dener PetscErrorCode ierr; 165737f463aSAlp Dener 166737f463aSAlp Dener PetscFunctionBegin; 167737f463aSAlp Dener ierr = TaoSolve(gn->subsolver);CHKERRQ(ierr); 168e1e80dc8SAlp Dener /* Update basic tao information from the subsolver */ 169e1e80dc8SAlp Dener tao->nfuncs = gn->subsolver->nfuncs; 170e1e80dc8SAlp Dener tao->ngrads = gn->subsolver->ngrads; 171e1e80dc8SAlp Dener tao->nfuncgrads = gn->subsolver->nfuncgrads; 172e1e80dc8SAlp Dener tao->nhess = gn->subsolver->nhess; 173e1e80dc8SAlp Dener tao->niter = gn->subsolver->niter; 174e1e80dc8SAlp Dener tao->ksp_its = gn->subsolver->ksp_its; 175e1e80dc8SAlp Dener tao->ksp_tot_its = gn->subsolver->ksp_tot_its; 176e1e80dc8SAlp Dener ierr = TaoGetConvergedReason(gn->subsolver, &tao->reason);CHKERRQ(ierr); 177e1e80dc8SAlp Dener /* Update vectors */ 178e1e80dc8SAlp Dener ierr = VecCopy(gn->subsolver->solution, tao->solution);CHKERRQ(ierr); 179e1e80dc8SAlp Dener ierr = VecCopy(gn->subsolver->gradient, tao->gradient);CHKERRQ(ierr); 180737f463aSAlp Dener PetscFunctionReturn(0); 181737f463aSAlp Dener } 182737f463aSAlp Dener 183737f463aSAlp Dener static PetscErrorCode TaoSetFromOptions_BRGN(PetscOptionItems *PetscOptionsObject,Tao tao) 184737f463aSAlp Dener { 185737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 186737f463aSAlp Dener PetscErrorCode ierr; 187737f463aSAlp Dener 188*0d71dc2bSXiang Huang /* XH: Read an option to change epsilon in the structure; follow the lambda function below */ 189*0d71dc2bSXiang Huang 190737f463aSAlp Dener PetscFunctionBegin; 191737f463aSAlp Dener ierr = PetscOptionsHead(PetscOptionsObject,"Gauss-Newton method for least-squares problems using Tikhonov regularization");CHKERRQ(ierr); 192737f463aSAlp Dener ierr = PetscOptionsReal("-tao_brgn_lambda", "Tikhonov regularization factor", "", gn->lambda, &gn->lambda, NULL);CHKERRQ(ierr); 193737f463aSAlp Dener ierr = PetscOptionsTail();CHKERRQ(ierr); 194737f463aSAlp Dener ierr = TaoSetFromOptions(gn->subsolver);CHKERRQ(ierr); 195737f463aSAlp Dener PetscFunctionReturn(0); 196737f463aSAlp Dener } 197737f463aSAlp Dener 198737f463aSAlp Dener static PetscErrorCode TaoView_BRGN(Tao tao, PetscViewer viewer) 199737f463aSAlp Dener { 200737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 201737f463aSAlp Dener PetscErrorCode ierr; 202737f463aSAlp Dener 203737f463aSAlp Dener PetscFunctionBegin; 204e1e80dc8SAlp Dener ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 205737f463aSAlp Dener ierr = TaoView(gn->subsolver, viewer);CHKERRQ(ierr); 206e1e80dc8SAlp Dener ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 207737f463aSAlp Dener PetscFunctionReturn(0); 208737f463aSAlp Dener } 209737f463aSAlp Dener 210737f463aSAlp Dener static PetscErrorCode TaoSetUp_BRGN(Tao tao) 211737f463aSAlp Dener { 212737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 213737f463aSAlp Dener PetscErrorCode ierr; 214737f463aSAlp Dener PetscBool is_bnls, is_bntr, is_bntl; 215737f463aSAlp Dener PetscInt i, nx, Nx; 216737f463aSAlp Dener 217737f463aSAlp Dener PetscFunctionBegin; 218737f463aSAlp Dener if (!tao->ls_res) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualRoutine() must be called before setup!"); 219737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNLS, &is_bnls);CHKERRQ(ierr); 220737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTR, &is_bntr);CHKERRQ(ierr); 221737f463aSAlp Dener ierr = PetscObjectTypeCompare((PetscObject)gn->subsolver, TAOBNTL, &is_bntl);CHKERRQ(ierr); 222737f463aSAlp Dener if ((is_bnls || is_bntr || is_bntl) && !tao->ls_jac) SETERRQ(PetscObjectComm((PetscObject)tao), PETSC_ERR_ORDER, "TaoSetResidualJacobianRoutine() must be called before setup!"); 223e1e80dc8SAlp Dener if (!tao->gradient){ 224e1e80dc8SAlp Dener ierr = VecDuplicate(tao->solution, &tao->gradient);CHKERRQ(ierr); 225e1e80dc8SAlp Dener } 226737f463aSAlp Dener if (!gn->x_work){ 227737f463aSAlp Dener ierr = VecDuplicate(tao->solution, &gn->x_work);CHKERRQ(ierr); 228737f463aSAlp Dener } 229737f463aSAlp Dener if (!gn->r_work){ 230737f463aSAlp Dener ierr = VecDuplicate(tao->ls_res, &gn->r_work);CHKERRQ(ierr); 231737f463aSAlp Dener } 232e1e80dc8SAlp Dener if (!gn->x_old) { 233e1e80dc8SAlp Dener ierr = VecDuplicate(tao->solution, &gn->x_old);CHKERRQ(ierr); 234e1e80dc8SAlp Dener ierr = VecSet(gn->x_old, 0.0);CHKERRQ(ierr); 235e1e80dc8SAlp Dener } 236*0d71dc2bSXiang Huang 237*0d71dc2bSXiang Huang /* XH: Create diag vector */ 238*0d71dc2bSXiang Huang 239e1e80dc8SAlp Dener if (!tao->setupcalled) { 240737f463aSAlp Dener /* Hessian setup */ 241737f463aSAlp Dener ierr = VecGetLocalSize(tao->solution, &nx);CHKERRQ(ierr); 242737f463aSAlp Dener ierr = VecGetSize(tao->solution, &Nx);CHKERRQ(ierr); 243737f463aSAlp Dener ierr = MatSetSizes(gn->H, nx, nx, Nx, Nx);CHKERRQ(ierr); 244737f463aSAlp Dener ierr = MatSetType(gn->H, MATSHELL);CHKERRQ(ierr); 245737f463aSAlp Dener ierr = MatSetUp(gn->H);CHKERRQ(ierr); 246737f463aSAlp Dener ierr = MatShellSetOperation(gn->H, MATOP_MULT, (void (*)(void))GNHessianProd);CHKERRQ(ierr); 247737f463aSAlp Dener ierr = MatShellSetContext(gn->H, (void*)gn);CHKERRQ(ierr); 248737f463aSAlp Dener /* Subsolver setup */ 249e1e80dc8SAlp Dener ierr = TaoSetUpdate(gn->subsolver, GNHookFunction, (void*)gn);CHKERRQ(ierr); 250737f463aSAlp Dener ierr = TaoSetInitialVector(gn->subsolver, tao->solution);CHKERRQ(ierr); 251737f463aSAlp Dener if (tao->bounded) { 252737f463aSAlp Dener ierr = TaoSetVariableBounds(gn->subsolver, tao->XL, tao->XU);CHKERRQ(ierr); 253737f463aSAlp Dener } 254737f463aSAlp Dener ierr = TaoSetResidualRoutine(gn->subsolver, tao->ls_res, tao->ops->computeresidual, tao->user_lsresP);CHKERRQ(ierr); 2554ffbe8acSAlp Dener ierr = TaoSetJacobianResidualRoutine(gn->subsolver, tao->ls_jac, tao->ls_jac, tao->ops->computeresidualjacobian, tao->user_lsjacP);CHKERRQ(ierr); 256737f463aSAlp Dener ierr = TaoSetObjectiveAndGradientRoutine(gn->subsolver, GNObjectiveGradientEval, (void*)gn);CHKERRQ(ierr); 257737f463aSAlp Dener ierr = TaoSetHessianRoutine(gn->subsolver, gn->H, gn->H, GNComputeHessian, (void*)gn);CHKERRQ(ierr); 258e1e80dc8SAlp Dener /* Propagate some options down */ 259e1e80dc8SAlp Dener ierr = TaoSetTolerances(gn->subsolver, tao->gatol, tao->grtol, tao->gttol);CHKERRQ(ierr); 260e1e80dc8SAlp Dener ierr = TaoSetMaximumIterations(gn->subsolver, tao->max_it);CHKERRQ(ierr); 261e1e80dc8SAlp Dener ierr = TaoSetMaximumFunctionEvaluations(gn->subsolver, tao->max_funcs);CHKERRQ(ierr); 262737f463aSAlp Dener for (i=0; i<tao->numbermonitors; ++i) { 263737f463aSAlp Dener ierr = TaoSetMonitor(gn->subsolver, tao->monitor[i], tao->monitorcontext[i], tao->monitordestroy[i]);CHKERRQ(ierr); 264737f463aSAlp Dener ierr = PetscObjectReference((PetscObject)(tao->monitorcontext[i]));CHKERRQ(ierr); 265737f463aSAlp Dener } 266737f463aSAlp Dener ierr = TaoSetUp(gn->subsolver);CHKERRQ(ierr); 267e1e80dc8SAlp Dener } 268737f463aSAlp Dener PetscFunctionReturn(0); 269737f463aSAlp Dener } 270737f463aSAlp Dener 271737f463aSAlp Dener static PetscErrorCode TaoDestroy_BRGN(Tao tao) 272737f463aSAlp Dener { 273737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 274737f463aSAlp Dener PetscErrorCode ierr; 275737f463aSAlp Dener 276737f463aSAlp Dener PetscFunctionBegin; 277737f463aSAlp Dener if (tao->setupcalled) { 278e1e80dc8SAlp Dener ierr = VecDestroy(&tao->gradient);CHKERRQ(ierr); 279737f463aSAlp Dener ierr = VecDestroy(&gn->x_work);CHKERRQ(ierr); 280737f463aSAlp Dener ierr = VecDestroy(&gn->r_work);CHKERRQ(ierr); 281e1e80dc8SAlp Dener ierr = VecDestroy(&gn->x_old);CHKERRQ(ierr); 282*0d71dc2bSXiang Huang 283*0d71dc2bSXiang Huang /* XH: Destroy diagonal vector */ 284737f463aSAlp Dener } 285737f463aSAlp Dener ierr = MatDestroy(&gn->H);CHKERRQ(ierr); 286737f463aSAlp Dener ierr = TaoDestroy(&gn->subsolver);CHKERRQ(ierr); 287e1e80dc8SAlp Dener gn->parent = NULL; 288737f463aSAlp Dener ierr = PetscFree(tao->data);CHKERRQ(ierr); 289737f463aSAlp Dener PetscFunctionReturn(0); 290737f463aSAlp Dener } 291737f463aSAlp Dener 2923850be85SAlp Dener /*MC 2933850be85SAlp Dener TAOBRGN - Bounded Regularized Gauss-Newton method for solving nonlinear least-squares 2943850be85SAlp Dener problems with bound constraints. This algorithm is a thin wrapper around TAOBNTL 2953850be85SAlp Dener that constructs the Guass-Newton problem with the user-provided least-squares 2963850be85SAlp Dener residual and Jacobian. The problem is regularized with an L2-norm proximal point 2973850be85SAlp Dener term. 2983850be85SAlp Dener 2993850be85SAlp Dener Options Database Keys: 3003850be85SAlp Dener + -tao_bqnk_max_cg_its - maximum number of bounded conjugate-gradient iterations taken in each Newton loop 3013850be85SAlp Dener . -tao_bqnk_init_type - trust radius initialization method ("constant", "direction", "interpolation") 3023850be85SAlp Dener . -tao_bqnk_update_type - trust radius update method ("step", "direction", "interpolation") 3033850be85SAlp Dener - -tao_bqnk_as_type - active-set estimation method ("none", "bertsekas") 3043850be85SAlp Dener 3053850be85SAlp Dener Level: beginner 3063850be85SAlp Dener M*/ 307737f463aSAlp Dener PETSC_EXTERN PetscErrorCode TaoCreate_BRGN(Tao tao) 308737f463aSAlp Dener { 309737f463aSAlp Dener TAO_BRGN *gn; 310737f463aSAlp Dener PetscErrorCode ierr; 311737f463aSAlp Dener 312737f463aSAlp Dener PetscFunctionBegin; 313737f463aSAlp Dener ierr = PetscNewLog(tao,&gn);CHKERRQ(ierr); 314737f463aSAlp Dener 315737f463aSAlp Dener tao->ops->destroy = TaoDestroy_BRGN; 316737f463aSAlp Dener tao->ops->setup = TaoSetUp_BRGN; 317737f463aSAlp Dener tao->ops->setfromoptions = TaoSetFromOptions_BRGN; 318737f463aSAlp Dener tao->ops->view = TaoView_BRGN; 319737f463aSAlp Dener tao->ops->solve = TaoSolve_BRGN; 320737f463aSAlp Dener 321*0d71dc2bSXiang Huang /* XH: initialize the epsilon */ 322*0d71dc2bSXiang Huang 323737f463aSAlp Dener tao->data = (void*)gn; 324e1e80dc8SAlp Dener gn->lambda = 1e-4; 325e1e80dc8SAlp Dener gn->parent = tao; 326737f463aSAlp Dener 327737f463aSAlp Dener ierr = MatCreate(PetscObjectComm((PetscObject)tao), &gn->H);CHKERRQ(ierr); 328737f463aSAlp Dener ierr = MatSetOptionsPrefix(gn->H, "tao_brgn_hessian_");CHKERRQ(ierr); 329737f463aSAlp Dener 330737f463aSAlp Dener ierr = TaoCreate(PetscObjectComm((PetscObject)tao), &gn->subsolver);CHKERRQ(ierr); 331737f463aSAlp Dener ierr = TaoSetType(gn->subsolver, TAOBNLS);CHKERRQ(ierr); 332737f463aSAlp Dener ierr = TaoSetOptionsPrefix(gn->subsolver, "tao_brgn_subsolver_");CHKERRQ(ierr); 333e1e80dc8SAlp Dener PetscFunctionReturn(0); 334e1e80dc8SAlp Dener } 335e1e80dc8SAlp Dener 336e1e80dc8SAlp Dener /*@C 337e1e80dc8SAlp Dener TaoBRGNGetSubsolver - Get the pointer to the subsolver inside BRGN 338e1e80dc8SAlp Dener 339e1e80dc8SAlp Dener Collective on Tao 340e1e80dc8SAlp Dener 341e1e80dc8SAlp Dener Level: developer 342e1e80dc8SAlp Dener 343e1e80dc8SAlp Dener Input Parameters: 344e1e80dc8SAlp Dener + tao - the Tao solver context 345e1e80dc8SAlp Dener - subsolver - the Tao sub-solver context 346e1e80dc8SAlp Dener @*/ 347e1e80dc8SAlp Dener PetscErrorCode TaoBRGNGetSubsolver(Tao tao, Tao *subsolver) 348e1e80dc8SAlp Dener { 349e1e80dc8SAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 350e1e80dc8SAlp Dener 351e1e80dc8SAlp Dener PetscFunctionBegin; 352e1e80dc8SAlp Dener *subsolver = gn->subsolver; 353737f463aSAlp Dener PetscFunctionReturn(0); 354737f463aSAlp Dener } 355737f463aSAlp Dener 356737f463aSAlp Dener /*@C 357737f463aSAlp Dener TaoBRGNSetTikhonovLambda - Set the Tikhonov regularization factor for the Gauss-Newton least-squares algorithm 358737f463aSAlp Dener 359737f463aSAlp Dener Collective on Tao 360737f463aSAlp Dener 361737f463aSAlp Dener Level: developer 362737f463aSAlp Dener 363737f463aSAlp Dener Input Parameters: 364737f463aSAlp Dener + tao - the Tao solver context 365737f463aSAlp Dener - lambda - Tikhonov regularization factor 366737f463aSAlp Dener @*/ 367737f463aSAlp Dener PetscErrorCode TaoBRGNSetTikhonovLambda(Tao tao, PetscReal lambda) 368737f463aSAlp Dener { 369737f463aSAlp Dener TAO_BRGN *gn = (TAO_BRGN *)tao->data; 370737f463aSAlp Dener 371*0d71dc2bSXiang Huang /* Initialize epsilon here */ 372*0d71dc2bSXiang Huang 373737f463aSAlp Dener PetscFunctionBegin; 374737f463aSAlp Dener gn->lambda = lambda; 375737f463aSAlp Dener PetscFunctionReturn(0); 376737f463aSAlp Dener } 377*0d71dc2bSXiang Huang 378*0d71dc2bSXiang Huang /* XH: Add a routine to TaoBRGNSetEpsilon; follow the SetTikhonovLambda function including the comment */ 379*0d71dc2bSXiang Huang /* XH: Look for BRGNSetTikhonovLambda in the rest of the code; it will appear in a header file somewhere and add TaoBRGNSetEpsilon to that header with the same format */ 380*0d71dc2bSXiang Huang /* XH: Need to add a line to the ftn-custom for the TaoBRGNSetEpsilon function */ 381