1*d4c6564cSPatrick Farrell #include <petsc-private/linesearchimpl.h> /*I "petscsnes.h" I*/ 2*d4c6564cSPatrick Farrell #include <petsc-private/snesimpl.h> 3*d4c6564cSPatrick Farrell 4*d4c6564cSPatrick Farrell typedef struct { 5*d4c6564cSPatrick Farrell PetscReal norm_delta_x_prev; /* norm of previous update */ 6*d4c6564cSPatrick Farrell PetscReal norm_bar_delta_x_prev; /* norm of previous bar update */ 7*d4c6564cSPatrick Farrell PetscReal mu_curr; /* current local Lipschitz estimate */ 8*d4c6564cSPatrick Farrell PetscReal lambda_prev; /* previous step length: for some reason SNESLineSearchGetLambda returns 1 instead of the previous step length */ 9*d4c6564cSPatrick Farrell } SNESLineSearch_NLEQERR; 10*d4c6564cSPatrick Farrell 11*d4c6564cSPatrick Farrell PetscBool NLEQERR_cited = PETSC_FALSE; 12*d4c6564cSPatrick Farrell const char NLEQERR_citation[] = "@book{deuflhard2011,\n" 13*d4c6564cSPatrick Farrell " title = {Newton Methods for Nonlinear Problems},\n" 14*d4c6564cSPatrick Farrell " author = {Peter Deuflhard},\n" 15*d4c6564cSPatrick Farrell " volume = 35,\n" 16*d4c6564cSPatrick Farrell " year = 2011,\n" 17*d4c6564cSPatrick Farrell " isbn = {978-3-642-23898-7},\n" 18*d4c6564cSPatrick Farrell " doi = {10.1007/978-3-642-23899-4},\n" 19*d4c6564cSPatrick Farrell " publisher = {Springer-Verlag},\n" 20*d4c6564cSPatrick Farrell " address = {Berlin, Heidelberg}\n}\n"; 21*d4c6564cSPatrick Farrell 22*d4c6564cSPatrick Farrell #undef __FUNCT__ 23*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchApply_NLEQERR" 24*d4c6564cSPatrick Farrell static PetscErrorCode SNESLineSearchApply_NLEQERR(SNESLineSearch linesearch) 25*d4c6564cSPatrick Farrell { 26*d4c6564cSPatrick Farrell PetscBool changed_y,changed_w; 27*d4c6564cSPatrick Farrell PetscErrorCode ierr; 28*d4c6564cSPatrick Farrell Vec X,F,Y,W,G; 29*d4c6564cSPatrick Farrell SNES snes; 30*d4c6564cSPatrick Farrell PetscReal fnorm, xnorm, ynorm, gnorm, wnorm; 31*d4c6564cSPatrick Farrell PetscReal lambda, minlambda, stol; 32*d4c6564cSPatrick Farrell PetscViewer monitor; 33*d4c6564cSPatrick Farrell PetscInt max_its,count; 34*d4c6564cSPatrick Farrell PetscReal theta, mudash, lambdadash; 35*d4c6564cSPatrick Farrell SNESLineSearch_NLEQERR *nleqerr; 36*d4c6564cSPatrick Farrell KSPConvergedReason kspreason; 37*d4c6564cSPatrick Farrell 38*d4c6564cSPatrick Farrell PetscFunctionBegin; 39*d4c6564cSPatrick Farrell ierr = PetscCitationsRegister(NLEQERR_citation, &NLEQERR_cited);CHKERRQ(ierr); 40*d4c6564cSPatrick Farrell 41*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, &G);CHKERRQ(ierr); 42*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 43*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetLambda(linesearch, &lambda);CHKERRQ(ierr); 44*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 45*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetMonitor(linesearch, &monitor);CHKERRQ(ierr); 46*d4c6564cSPatrick Farrell ierr = SNESLineSearchGetTolerances(linesearch,&minlambda,NULL,NULL,NULL,NULL,&max_its);CHKERRQ(ierr); 47*d4c6564cSPatrick Farrell ierr = SNESGetTolerances(snes,NULL,NULL,&stol,NULL,NULL);CHKERRQ(ierr); 48*d4c6564cSPatrick Farrell nleqerr = (SNESLineSearch_NLEQERR*)linesearch->data; 49*d4c6564cSPatrick Farrell 50*d4c6564cSPatrick Farrell /* precheck */ 51*d4c6564cSPatrick Farrell ierr = SNESLineSearchPreCheck(linesearch,X,Y,&changed_y);CHKERRQ(ierr); 52*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetSuccess(linesearch, PETSC_TRUE);CHKERRQ(ierr); 53*d4c6564cSPatrick Farrell 54*d4c6564cSPatrick Farrell ierr = VecNormBegin(Y, NORM_2, &ynorm);CHKERRQ(ierr); 55*d4c6564cSPatrick Farrell ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); 56*d4c6564cSPatrick Farrell ierr = VecNormEnd(Y, NORM_2, &ynorm);CHKERRQ(ierr); 57*d4c6564cSPatrick Farrell ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); 58*d4c6564cSPatrick Farrell 59*d4c6564cSPatrick Farrell /* Note: Y is *minus* the Newton step. For whatever reason PETSc doesn't solve with the minus on 60*d4c6564cSPatrick Farrell the RHS. */ 61*d4c6564cSPatrick Farrell 62*d4c6564cSPatrick Farrell if (ynorm == 0.0) { 63*d4c6564cSPatrick Farrell if (monitor) { 64*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 65*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 66*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 67*d4c6564cSPatrick Farrell } 68*d4c6564cSPatrick Farrell ierr = VecCopy(X,W);CHKERRQ(ierr); 69*d4c6564cSPatrick Farrell ierr = VecCopy(F,G);CHKERRQ(ierr); 70*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetNorms(linesearch,xnorm,fnorm,ynorm);CHKERRQ(ierr); 71*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr); 72*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 73*d4c6564cSPatrick Farrell } 74*d4c6564cSPatrick Farrell 75*d4c6564cSPatrick Farrell /* At this point, we've solved the Newton system for delta_x, and we assume that 76*d4c6564cSPatrick Farrell its norm is greater than the solution tolerance (otherwise we wouldn't be in 77*d4c6564cSPatrick Farrell here). So let's go ahead and estimate the Lipschitz constant. 78*d4c6564cSPatrick Farrell 79*d4c6564cSPatrick Farrell W contains bar_delta_x_prev at this point. */ 80*d4c6564cSPatrick Farrell 81*d4c6564cSPatrick Farrell if (monitor) { 82*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 83*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: norm of Newton step: %14.12e\n", (double) ynorm);CHKERRQ(ierr); 84*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 85*d4c6564cSPatrick Farrell } 86*d4c6564cSPatrick Farrell 87*d4c6564cSPatrick Farrell /* this needs information from a previous iteration, so can't do it on the first one */ 88*d4c6564cSPatrick Farrell if (nleqerr->norm_delta_x_prev > 0 && nleqerr->norm_bar_delta_x_prev > 0) { 89*d4c6564cSPatrick Farrell ierr = VecWAXPY(G, +1.0, Y, W);CHKERRQ(ierr); /* bar_delta_x - delta_x; +1 because Y is -delta_x */ 90*d4c6564cSPatrick Farrell ierr = VecNormBegin(G, NORM_2, &gnorm);CHKERRQ(ierr); 91*d4c6564cSPatrick Farrell ierr = VecNormEnd(G, NORM_2, &gnorm);CHKERRQ(ierr); 92*d4c6564cSPatrick Farrell 93*d4c6564cSPatrick Farrell nleqerr->mu_curr = nleqerr->lambda_prev * (nleqerr->norm_delta_x_prev * nleqerr->norm_bar_delta_x_prev) / (gnorm * ynorm); 94*d4c6564cSPatrick Farrell lambda = PetscMin(1.0, nleqerr->mu_curr); 95*d4c6564cSPatrick Farrell 96*d4c6564cSPatrick Farrell if (monitor) { 97*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 98*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: Lipschitz estimate: %14.12e; lambda: %14.12e\n", (double) nleqerr->mu_curr, (double) lambda);CHKERRQ(ierr); 99*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 100*d4c6564cSPatrick Farrell } 101*d4c6564cSPatrick Farrell } 102*d4c6564cSPatrick Farrell else { 103*d4c6564cSPatrick Farrell lambda = linesearch->damping; 104*d4c6564cSPatrick Farrell } 105*d4c6564cSPatrick Farrell 106*d4c6564cSPatrick Farrell 107*d4c6564cSPatrick Farrell /* The main while loop of the algorithm. 108*d4c6564cSPatrick Farrell At the end of this while loop, G should have the accepted new X in it. */ 109*d4c6564cSPatrick Farrell 110*d4c6564cSPatrick Farrell count = 0; 111*d4c6564cSPatrick Farrell while (true) { 112*d4c6564cSPatrick Farrell if (monitor) { 113*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 114*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: entering iteration with lambda: %14.12e\n", lambda);CHKERRQ(ierr); 115*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 116*d4c6564cSPatrick Farrell } 117*d4c6564cSPatrick Farrell 118*d4c6564cSPatrick Farrell /* Check that we haven't performed too many iterations */ 119*d4c6564cSPatrick Farrell count += 1; 120*d4c6564cSPatrick Farrell if (count >= max_its) 121*d4c6564cSPatrick Farrell { 122*d4c6564cSPatrick Farrell if (monitor) { 123*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 124*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: maximum iterations reached\n");CHKERRQ(ierr); 125*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 126*d4c6564cSPatrick Farrell } 127*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr); 128*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 129*d4c6564cSPatrick Farrell } 130*d4c6564cSPatrick Farrell 131*d4c6564cSPatrick Farrell /* Now comes the Regularity Test. */ 132*d4c6564cSPatrick Farrell if (lambda <= minlambda) { 133*d4c6564cSPatrick Farrell /* This isn't what is suggested by Deuflhard, but it works better in my experience */ 134*d4c6564cSPatrick Farrell if (monitor) { 135*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 136*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: lambda has reached lambdamin, taking full Newton step\n");CHKERRQ(ierr); 137*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 138*d4c6564cSPatrick Farrell } 139*d4c6564cSPatrick Farrell lambda = 1.0; 140*d4c6564cSPatrick Farrell ierr = VecWAXPY(G, -lambda, Y, X);CHKERRQ(ierr); 141*d4c6564cSPatrick Farrell break; 142*d4c6564cSPatrick Farrell } 143*d4c6564cSPatrick Farrell 144*d4c6564cSPatrick Farrell /* Compute new trial iterate */ 145*d4c6564cSPatrick Farrell ierr = VecWAXPY(W, -lambda, Y, X);CHKERRQ(ierr); 146*d4c6564cSPatrick Farrell ierr = SNESComputeFunction(snes, W, G);CHKERRQ(ierr); 147*d4c6564cSPatrick Farrell 148*d4c6564cSPatrick Farrell /* Solve linear system for bar_delta_x_curr: old Jacobian, new RHS. Note absence of minus sign, compared to Deuflhard, in keeping with PETSc convention */ 149*d4c6564cSPatrick Farrell ierr = KSPSolve(snes->ksp, G, W);CHKERRQ(ierr); 150*d4c6564cSPatrick Farrell ierr = KSPGetConvergedReason(snes->ksp, &kspreason);CHKERRQ(ierr); 151*d4c6564cSPatrick Farrell if (kspreason < 0) { 152*d4c6564cSPatrick Farrell ierr = PetscInfo(snes,"Solution for \\bar{delta x}^{k+1} failed.");CHKERRQ(ierr); 153*d4c6564cSPatrick Farrell } 154*d4c6564cSPatrick Farrell 155*d4c6564cSPatrick Farrell /* W now contains -bar_delta_x_curr. */ 156*d4c6564cSPatrick Farrell 157*d4c6564cSPatrick Farrell ierr = VecNorm(W, NORM_2, &wnorm);CHKERRQ(ierr); 158*d4c6564cSPatrick Farrell if (monitor) { 159*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 160*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: norm of simplified Newton update: %14.12e\n", (double) wnorm);CHKERRQ(ierr); 161*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 162*d4c6564cSPatrick Farrell } 163*d4c6564cSPatrick Farrell 164*d4c6564cSPatrick Farrell /* compute the monitoring quantities theta and mudash. */ 165*d4c6564cSPatrick Farrell 166*d4c6564cSPatrick Farrell theta = wnorm / ynorm; 167*d4c6564cSPatrick Farrell 168*d4c6564cSPatrick Farrell ierr = VecWAXPY(G, -(1.0 - lambda), Y, W);CHKERRQ(ierr); 169*d4c6564cSPatrick Farrell ierr = VecNorm(G, NORM_2, &gnorm);CHKERRQ(ierr); 170*d4c6564cSPatrick Farrell 171*d4c6564cSPatrick Farrell mudash = (0.5 * ynorm * lambda * lambda) / gnorm; 172*d4c6564cSPatrick Farrell 173*d4c6564cSPatrick Farrell /* Check for termination of the linesearch */ 174*d4c6564cSPatrick Farrell if (theta >= 1.0) { 175*d4c6564cSPatrick Farrell /* need to go around again with smaller lambda */ 176*d4c6564cSPatrick Farrell if (monitor) { 177*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 178*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(monitor," Line search: monotonicity check failed, ratio: %14.12e\n", (double) theta);CHKERRQ(ierr); 179*d4c6564cSPatrick Farrell ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 180*d4c6564cSPatrick Farrell } 181*d4c6564cSPatrick Farrell lambda = PetscMin(mudash, 0.5 * lambda); 182*d4c6564cSPatrick Farrell lambda = PetscMax(lambda, minlambda); 183*d4c6564cSPatrick Farrell /* continue through the loop, i.e. go back to regularity test */ 184*d4c6564cSPatrick Farrell } 185*d4c6564cSPatrick Farrell else { 186*d4c6564cSPatrick Farrell /* linesearch terminated */ 187*d4c6564cSPatrick Farrell lambdadash = PetscMin(1.0, mudash); 188*d4c6564cSPatrick Farrell 189*d4c6564cSPatrick Farrell if (lambdadash == 1.0 && lambda == 1.0 && wnorm <= stol) { 190*d4c6564cSPatrick Farrell /* store the updated state, X - Y - W, in G: 191*d4c6564cSPatrick Farrell I need to keep W for the next linesearch */ 192*d4c6564cSPatrick Farrell ierr = VecZeroEntries(G);CHKERRQ(ierr); 193*d4c6564cSPatrick Farrell ierr = VecAXPY(G, +1.0, X);CHKERRQ(ierr); 194*d4c6564cSPatrick Farrell ierr = VecAXPY(G, -1.0, Y);CHKERRQ(ierr); 195*d4c6564cSPatrick Farrell ierr = VecAXPY(G, -1.0, W);CHKERRQ(ierr); 196*d4c6564cSPatrick Farrell break; 197*d4c6564cSPatrick Farrell } 198*d4c6564cSPatrick Farrell 199*d4c6564cSPatrick Farrell /* Deuflhard suggests to add the following: 200*d4c6564cSPatrick Farrell else if (lambdadash >= 4.0 * lambda) { 201*d4c6564cSPatrick Farrell lambda = lambdadash; 202*d4c6564cSPatrick Farrell } 203*d4c6564cSPatrick Farrell to continue through the loop, i.e. go back to regularity test. 204*d4c6564cSPatrick Farrell I deliberately exclude this, as I have practical experience of this 205*d4c6564cSPatrick Farrell getting stuck in infinite loops (on e.g. an Allen--Cahn problem). */ 206*d4c6564cSPatrick Farrell 207*d4c6564cSPatrick Farrell else { 208*d4c6564cSPatrick Farrell /* accept iterate without adding on, i.e. don't use bar_delta_x; 209*d4c6564cSPatrick Farrell again, I need to keep W for the next linesearch */ 210*d4c6564cSPatrick Farrell ierr = VecWAXPY(G, -lambda, Y, X);CHKERRQ(ierr); 211*d4c6564cSPatrick Farrell break; 212*d4c6564cSPatrick Farrell } 213*d4c6564cSPatrick Farrell } 214*d4c6564cSPatrick Farrell } 215*d4c6564cSPatrick Farrell 216*d4c6564cSPatrick Farrell if (linesearch->ops->viproject) { 217*d4c6564cSPatrick Farrell ierr = (*linesearch->ops->viproject)(snes, G);CHKERRQ(ierr); 218*d4c6564cSPatrick Farrell } 219*d4c6564cSPatrick Farrell 220*d4c6564cSPatrick Farrell /* W currently contains -bar_delta_u. Scale it so that it contains bar_delta_u. */ 221*d4c6564cSPatrick Farrell ierr = VecScale(W, -1.0);CHKERRQ(ierr); 222*d4c6564cSPatrick Farrell 223*d4c6564cSPatrick Farrell /* postcheck */ 224*d4c6564cSPatrick Farrell ierr = SNESLineSearchPostCheck(linesearch,X,Y,G,&changed_y,&changed_w);CHKERRQ(ierr); 225*d4c6564cSPatrick Farrell if (changed_y || changed_w) { 226*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetSuccess(linesearch, PETSC_FALSE);CHKERRQ(ierr); 227*d4c6564cSPatrick Farrell ierr = PetscInfo(snes,"Changing the search direction here doesn't make sense.\n");CHKERRQ(ierr); 228*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 229*d4c6564cSPatrick Farrell } 230*d4c6564cSPatrick Farrell 231*d4c6564cSPatrick Farrell /* copy the solution and information from this iteration over */ 232*d4c6564cSPatrick Farrell nleqerr->norm_delta_x_prev = ynorm; 233*d4c6564cSPatrick Farrell nleqerr->norm_bar_delta_x_prev = wnorm; 234*d4c6564cSPatrick Farrell nleqerr->lambda_prev = lambda; 235*d4c6564cSPatrick Farrell 236*d4c6564cSPatrick Farrell ierr = VecCopy(G, X);CHKERRQ(ierr); 237*d4c6564cSPatrick Farrell ierr = SNESComputeFunction(snes, X, F);CHKERRQ(ierr); 238*d4c6564cSPatrick Farrell ierr = VecNorm(X, NORM_2, &xnorm);CHKERRQ(ierr); 239*d4c6564cSPatrick Farrell ierr = VecNorm(F, NORM_2, &fnorm);CHKERRQ(ierr); 240*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetLambda(linesearch, lambda);CHKERRQ(ierr); 241*d4c6564cSPatrick Farrell ierr = SNESLineSearchSetNorms(linesearch, xnorm, fnorm, ynorm);CHKERRQ(ierr); 242*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 243*d4c6564cSPatrick Farrell } 244*d4c6564cSPatrick Farrell 245*d4c6564cSPatrick Farrell #undef __FUNCT__ 246*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchView_NLEQERR" 247*d4c6564cSPatrick Farrell PetscErrorCode SNESLineSearchView_NLEQERR(SNESLineSearch linesearch, PetscViewer viewer) 248*d4c6564cSPatrick Farrell { 249*d4c6564cSPatrick Farrell PetscErrorCode ierr; 250*d4c6564cSPatrick Farrell PetscBool iascii; 251*d4c6564cSPatrick Farrell SNESLineSearch_NLEQERR *nleqerr; 252*d4c6564cSPatrick Farrell 253*d4c6564cSPatrick Farrell PetscFunctionBegin; 254*d4c6564cSPatrick Farrell ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 255*d4c6564cSPatrick Farrell nleqerr = (SNESLineSearch_NLEQERR*)linesearch->data; 256*d4c6564cSPatrick Farrell if (iascii) { 257*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(viewer, " NLEQ-ERR affine-covariant linesearch");CHKERRQ(ierr); 258*d4c6564cSPatrick Farrell ierr = PetscViewerASCIIPrintf(viewer, " current local Lipschitz estimate omega=%e\n", (double)nleqerr->mu_curr);CHKERRQ(ierr); 259*d4c6564cSPatrick Farrell } 260*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 261*d4c6564cSPatrick Farrell } 262*d4c6564cSPatrick Farrell 263*d4c6564cSPatrick Farrell #undef __FUNCT__ 264*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchDestroy_NLEQERR" 265*d4c6564cSPatrick Farrell static PetscErrorCode SNESLineSearchDestroy_NLEQERR(SNESLineSearch linesearch) 266*d4c6564cSPatrick Farrell { 267*d4c6564cSPatrick Farrell PetscErrorCode ierr; 268*d4c6564cSPatrick Farrell 269*d4c6564cSPatrick Farrell PetscFunctionBegin; 270*d4c6564cSPatrick Farrell ierr = PetscFree(linesearch->data);CHKERRQ(ierr); 271*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 272*d4c6564cSPatrick Farrell } 273*d4c6564cSPatrick Farrell 274*d4c6564cSPatrick Farrell #undef __FUNCT__ 275*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchReset_NLEQERR" 276*d4c6564cSPatrick Farrell static PetscErrorCode SNESLineSearchReset_NLEQERR(SNESLineSearch linesearch) 277*d4c6564cSPatrick Farrell { 278*d4c6564cSPatrick Farrell SNESLineSearch_NLEQERR *nleqerr; 279*d4c6564cSPatrick Farrell 280*d4c6564cSPatrick Farrell nleqerr = (SNESLineSearch_NLEQERR*)linesearch->data; 281*d4c6564cSPatrick Farrell nleqerr->mu_curr = 0.0; 282*d4c6564cSPatrick Farrell nleqerr->norm_delta_x_prev = -1.0; 283*d4c6564cSPatrick Farrell nleqerr->norm_bar_delta_x_prev = -1.0; 284*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 285*d4c6564cSPatrick Farrell } 286*d4c6564cSPatrick Farrell 287*d4c6564cSPatrick Farrell #undef __FUNCT__ 288*d4c6564cSPatrick Farrell #define __FUNCT__ "SNESLineSearchCreate_NLEQERR" 289*d4c6564cSPatrick Farrell /*MC 290*d4c6564cSPatrick Farrell SNESLINESEARCHNLEQERR - Error-oriented affine-covariant globalised Newton algorithm of Deuflhard (2011). 291*d4c6564cSPatrick Farrell 292*d4c6564cSPatrick Farrell This linesearch is intended for Newton-type methods which are affine covariant. Affine covariance 293*d4c6564cSPatrick Farrell means that Newton's method will give the same iterations for F(x) = 0 and AF(x) = 0 for a nonsingular 294*d4c6564cSPatrick Farrell matrix A. This is a fundamental property; the philosophy of this linesearch is that globalisations 295*d4c6564cSPatrick Farrell of Newton's method should carefully preserve it. 296*d4c6564cSPatrick Farrell 297*d4c6564cSPatrick Farrell For a discussion of the theory behind this algorithm, see 298*d4c6564cSPatrick Farrell 299*d4c6564cSPatrick Farrell @book{deuflhard2011, 300*d4c6564cSPatrick Farrell title={Newton Methods for Nonlinear Problems}, 301*d4c6564cSPatrick Farrell author={Deuflhard, P.}, 302*d4c6564cSPatrick Farrell volume={35}, 303*d4c6564cSPatrick Farrell year={2011}, 304*d4c6564cSPatrick Farrell publisher={Springer-Verlag}, 305*d4c6564cSPatrick Farrell address={Berlin, Heidelberg} 306*d4c6564cSPatrick Farrell } 307*d4c6564cSPatrick Farrell 308*d4c6564cSPatrick Farrell Pseudocode is given on page 148. 309*d4c6564cSPatrick Farrell 310*d4c6564cSPatrick Farrell Options Database Keys: 311*d4c6564cSPatrick Farrell + -snes_linesearch_damping<1.0> - initial step length 312*d4c6564cSPatrick Farrell - -snes_linesearch_minlambda<1e-12> - minimum step length allowed 313*d4c6564cSPatrick Farrell 314*d4c6564cSPatrick Farrell Contributed by Patrick Farrell <patrick.farrell@maths.ox.ac.uk> 315*d4c6564cSPatrick Farrell 316*d4c6564cSPatrick Farrell Level: advanced 317*d4c6564cSPatrick Farrell 318*d4c6564cSPatrick Farrell .keywords: SNES, SNESLineSearch, damping 319*d4c6564cSPatrick Farrell 320*d4c6564cSPatrick Farrell .seealso: SNESLineSearchCreate(), SNESLineSearchSetType() 321*d4c6564cSPatrick Farrell M*/ 322*d4c6564cSPatrick Farrell PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_NLEQERR(SNESLineSearch linesearch) 323*d4c6564cSPatrick Farrell { 324*d4c6564cSPatrick Farrell 325*d4c6564cSPatrick Farrell SNESLineSearch_NLEQERR *nleqerr; 326*d4c6564cSPatrick Farrell PetscErrorCode ierr; 327*d4c6564cSPatrick Farrell 328*d4c6564cSPatrick Farrell PetscFunctionBegin; 329*d4c6564cSPatrick Farrell linesearch->ops->apply = SNESLineSearchApply_NLEQERR; 330*d4c6564cSPatrick Farrell linesearch->ops->destroy = SNESLineSearchDestroy_NLEQERR; 331*d4c6564cSPatrick Farrell linesearch->ops->setfromoptions = NULL; 332*d4c6564cSPatrick Farrell linesearch->ops->reset = SNESLineSearchReset_NLEQERR; 333*d4c6564cSPatrick Farrell linesearch->ops->view = SNESLineSearchView_NLEQERR; 334*d4c6564cSPatrick Farrell linesearch->ops->setup = NULL; 335*d4c6564cSPatrick Farrell 336*d4c6564cSPatrick Farrell ierr = PetscNewLog(linesearch,&nleqerr);CHKERRQ(ierr); 337*d4c6564cSPatrick Farrell 338*d4c6564cSPatrick Farrell linesearch->data = (void*)nleqerr; 339*d4c6564cSPatrick Farrell linesearch->max_its = 40; 340*d4c6564cSPatrick Farrell nleqerr->mu_curr = 0.0; 341*d4c6564cSPatrick Farrell nleqerr->norm_delta_x_prev = -1.0; 342*d4c6564cSPatrick Farrell nleqerr->norm_bar_delta_x_prev = -1.0; 343*d4c6564cSPatrick Farrell PetscFunctionReturn(0); 344*d4c6564cSPatrick Farrell } 345