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