1af0996ceSBarry Smith #include <petsc/private/linesearchimpl.h> /*I "petscsnes.h" I*/ 2af0996ceSBarry Smith #include <petsc/private/snesimpl.h> 371b4ebd2SPeter Brune 471b4ebd2SPeter Brune typedef struct { 571b4ebd2SPeter Brune PetscReal alpha; /* sufficient decrease parameter */ 6f1c6b773SPeter Brune } SNESLineSearch_BT; 771b4ebd2SPeter Brune 871b4ebd2SPeter Brune #undef __FUNCT__ 92f4102e2SPeter Brune #define __FUNCT__ "SNESLineSearchBTSetAlpha" 102f4102e2SPeter Brune /*@ 112f4102e2SPeter Brune SNESLineSearchBTSetAlpha - Sets the descent parameter, alpha, in the BT linesearch variant. 122f4102e2SPeter Brune 132f4102e2SPeter Brune Input Parameters: 142f4102e2SPeter Brune + linesearch - linesearch context 152f4102e2SPeter Brune - alpha - The descent parameter 162f4102e2SPeter Brune 172f4102e2SPeter Brune Level: intermediate 182f4102e2SPeter Brune 191a4f838cSPeter Brune .seealso: SNESLineSearchSetLambda(), SNESLineSearchGetTolerances() SNESLINESEARCHBT 202f4102e2SPeter Brune @*/ 212f4102e2SPeter Brune PetscErrorCode SNESLineSearchBTSetAlpha(SNESLineSearch linesearch, PetscReal alpha) 222f4102e2SPeter Brune { 232f4102e2SPeter Brune SNESLineSearch_BT *bt; 246e111a19SKarl Rupp 252f4102e2SPeter Brune PetscFunctionBegin; 262f4102e2SPeter Brune PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 272f4102e2SPeter Brune bt = (SNESLineSearch_BT*)linesearch->data; 282f4102e2SPeter Brune bt->alpha = alpha; 292f4102e2SPeter Brune PetscFunctionReturn(0); 302f4102e2SPeter Brune } 312f4102e2SPeter Brune 322f4102e2SPeter Brune 332f4102e2SPeter Brune #undef __FUNCT__ 342f4102e2SPeter Brune #define __FUNCT__ "SNESLineSearchBTGetAlpha" 352f4102e2SPeter Brune /*@ 362f4102e2SPeter Brune SNESLineSearchBTGetAlpha - Gets the descent parameter, alpha, in the BT linesearch variant. 372f4102e2SPeter Brune 382f4102e2SPeter Brune Input Parameters: 392f4102e2SPeter Brune . linesearch - linesearch context 408e557f58SPeter Brune 418e557f58SPeter Brune Output Parameters: 422f4102e2SPeter Brune . alpha - The descent parameter 432f4102e2SPeter Brune 442f4102e2SPeter Brune Level: intermediate 452f4102e2SPeter Brune 461a4f838cSPeter Brune .seealso: SNESLineSearchGetLambda(), SNESLineSearchGetTolerances() SNESLINESEARCHBT 472f4102e2SPeter Brune @*/ 482f4102e2SPeter Brune PetscErrorCode SNESLineSearchBTGetAlpha(SNESLineSearch linesearch, PetscReal *alpha) 492f4102e2SPeter Brune { 502f4102e2SPeter Brune SNESLineSearch_BT *bt; 516e111a19SKarl Rupp 522f4102e2SPeter Brune PetscFunctionBegin; 532f4102e2SPeter Brune PetscValidHeaderSpecific(linesearch,SNESLINESEARCH_CLASSID,1); 542f4102e2SPeter Brune bt = (SNESLineSearch_BT*)linesearch->data; 552f4102e2SPeter Brune *alpha = bt->alpha; 562f4102e2SPeter Brune PetscFunctionReturn(0); 572f4102e2SPeter Brune } 582f4102e2SPeter Brune 592f4102e2SPeter Brune #undef __FUNCT__ 60f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchApply_BT" 61f1c6b773SPeter Brune static PetscErrorCode SNESLineSearchApply_BT(SNESLineSearch linesearch) 6271b4ebd2SPeter Brune { 6371b4ebd2SPeter Brune PetscBool changed_y,changed_w; 6471b4ebd2SPeter Brune PetscErrorCode ierr; 6571b4ebd2SPeter Brune Vec X,F,Y,W,G; 6671b4ebd2SPeter Brune SNES snes; 678a430afbSPeter Brune PetscReal fnorm, xnorm, ynorm, gnorm; 683b288129SPeter Brune PetscReal lambda,lambdatemp,lambdaprev,minlambda,maxstep,initslope,alpha,stol; 69dfcd3828SPeter Brune PetscReal t1,t2,a,b,d; 708a430afbSPeter Brune PetscReal f; 718a430afbSPeter Brune PetscReal g,gprev; 7271b4ebd2SPeter Brune PetscViewer monitor; 7371b4ebd2SPeter Brune PetscInt max_its,count; 74f1c6b773SPeter Brune SNESLineSearch_BT *bt; 7571b4ebd2SPeter Brune Mat jac; 76bd4a8a71SBarry Smith PetscErrorCode (*objective)(SNES,Vec,PetscReal*,void*); 7771b4ebd2SPeter Brune 7871b4ebd2SPeter Brune PetscFunctionBegin; 79f1c6b773SPeter Brune ierr = SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, &G);CHKERRQ(ierr); 80f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &fnorm, &ynorm);CHKERRQ(ierr); 81f1c6b773SPeter Brune ierr = SNESLineSearchGetLambda(linesearch, &lambda);CHKERRQ(ierr); 82f1c6b773SPeter Brune ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 83*dcf2fd19SBarry Smith ierr = SNESLineSearchGetDefaultMonitor(linesearch, &monitor);CHKERRQ(ierr); 840298fd71SBarry Smith ierr = SNESLineSearchGetTolerances(linesearch,&minlambda,&maxstep,NULL,NULL,NULL,&max_its);CHKERRQ(ierr); 850298fd71SBarry Smith ierr = SNESGetTolerances(snes,NULL,NULL,&stol,NULL,NULL);CHKERRQ(ierr); 860298fd71SBarry Smith ierr = SNESGetObjective(snes,&objective,NULL);CHKERRQ(ierr); 87f1c6b773SPeter Brune bt = (SNESLineSearch_BT*)linesearch->data; 8871b4ebd2SPeter Brune alpha = bt->alpha; 8971b4ebd2SPeter Brune 900298fd71SBarry Smith ierr = SNESGetJacobian(snes, &jac, NULL, NULL, NULL);CHKERRQ(ierr); 91ce94432eSBarry Smith if (!jac && !objective) SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_USER, "SNESLineSearchBT requires a Jacobian matrix"); 92c69d1a72SBarry Smith 937b1df9c1SPeter Brune ierr = SNESLineSearchPreCheck(linesearch,X,Y,&changed_y);CHKERRQ(ierr); 94422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_SUCCEEDED);CHKERRQ(ierr); 9571b4ebd2SPeter Brune 963b288129SPeter Brune ierr = VecNormBegin(Y, NORM_2, &ynorm);CHKERRQ(ierr); 973b288129SPeter Brune ierr = VecNormBegin(X, NORM_2, &xnorm);CHKERRQ(ierr); 983b288129SPeter Brune ierr = VecNormEnd(Y, NORM_2, &ynorm);CHKERRQ(ierr); 993b288129SPeter Brune ierr = VecNormEnd(X, NORM_2, &xnorm);CHKERRQ(ierr); 1003b288129SPeter Brune 10171b4ebd2SPeter Brune if (ynorm == 0.0) { 10271b4ebd2SPeter Brune if (monitor) { 103ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 10471b4ebd2SPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Initial direction and size is 0\n");CHKERRQ(ierr); 105ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 10671b4ebd2SPeter Brune } 10771b4ebd2SPeter Brune ierr = VecCopy(X,W);CHKERRQ(ierr); 10871b4ebd2SPeter Brune ierr = VecCopy(F,G);CHKERRQ(ierr); 10971cee68bSPeter Brune ierr = SNESLineSearchSetNorms(linesearch,xnorm,fnorm,ynorm);CHKERRQ(ierr); 110e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_REDUCT);CHKERRQ(ierr); 11171b4ebd2SPeter Brune PetscFunctionReturn(0); 11271b4ebd2SPeter Brune } 11371b4ebd2SPeter Brune if (ynorm > maxstep) { /* Step too big, so scale back */ 11471b4ebd2SPeter Brune if (monitor) { 115ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 116c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Scaling step by %14.12e old ynorm %14.12e\n", (double)(maxstep/ynorm),(double)ynorm);CHKERRQ(ierr); 117ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 11871b4ebd2SPeter Brune } 11971b4ebd2SPeter Brune ierr = VecScale(Y,maxstep/(ynorm));CHKERRQ(ierr); 12071b4ebd2SPeter Brune ynorm = maxstep; 12171b4ebd2SPeter Brune } 1228a430afbSPeter Brune 1238a430afbSPeter Brune /* if the SNES has an objective set, use that instead of the function value */ 124bd4a8a71SBarry Smith if (objective) { 1258a430afbSPeter Brune ierr = SNESComputeObjective(snes,X,&f);CHKERRQ(ierr); 1268a430afbSPeter Brune } else { 1278a430afbSPeter Brune f = fnorm*fnorm; 1288a430afbSPeter Brune } 1298a430afbSPeter Brune 1308a430afbSPeter Brune /* compute the initial slope */ 131bd4a8a71SBarry Smith if (objective) { 1328a430afbSPeter Brune /* slope comes from the function (assumed to be the gradient of the objective */ 13367392de3SBarry Smith ierr = VecDotRealPart(Y,F,&initslope);CHKERRQ(ierr); 1348a430afbSPeter Brune } else { 1358a430afbSPeter Brune /* slope comes from the normal equations */ 13671b4ebd2SPeter Brune ierr = MatMult(jac,Y,W);CHKERRQ(ierr); 13767392de3SBarry Smith ierr = VecDotRealPart(F,W,&initslope);CHKERRQ(ierr); 13871b4ebd2SPeter Brune if (initslope > 0.0) initslope = -initslope; 13971b4ebd2SPeter Brune if (initslope == 0.0) initslope = -1.0; 1408a430afbSPeter Brune } 14171b4ebd2SPeter Brune 142c427506bSPeter Brune ierr = VecWAXPY(W,-lambda,Y,X);CHKERRQ(ierr); 1439bd66eb0SPeter Brune if (linesearch->ops->viproject) { 1449bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 1459bd66eb0SPeter Brune } 14671b4ebd2SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 14771b4ebd2SPeter Brune ierr = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr); 14871b4ebd2SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 149e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_FUNCTION);CHKERRQ(ierr); 15071b4ebd2SPeter Brune PetscFunctionReturn(0); 15171b4ebd2SPeter Brune } 1528a430afbSPeter Brune 153bd4a8a71SBarry Smith if (objective) { 1548a430afbSPeter Brune ierr = SNESComputeObjective(snes,W,&g);CHKERRQ(ierr); 1558a430afbSPeter Brune } else { 156ce5a860aSPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,G);CHKERRQ(ierr); 1579bd66eb0SPeter Brune if (linesearch->ops->vinorm) { 1589bd66eb0SPeter Brune gnorm = fnorm; 1599bd66eb0SPeter Brune ierr = (*linesearch->ops->vinorm)(snes, G, W, &gnorm);CHKERRQ(ierr); 1609bd66eb0SPeter Brune } else { 16171b4ebd2SPeter Brune ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); 1628a430afbSPeter Brune } 16379e7e81bSJed Brown g = PetscSqr(gnorm); 1649bd66eb0SPeter Brune } 165*dcf2fd19SBarry Smith ierr = SNESLineSearchMonitor(linesearch);CHKERRQ(ierr); 1669bd66eb0SPeter Brune 167c98378a5SBarry Smith if (PetscIsInfOrNanReal(g)) { 168422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_NANORINF);CHKERRQ(ierr); 169c61ba1e2SPeter Brune ierr = PetscInfo(snes,"Aborted due to Nan or Inf in function evaluation\n");CHKERRQ(ierr); 170c98378a5SBarry Smith PetscFunctionReturn(0); 171c98378a5SBarry Smith } 172bd4a8a71SBarry Smith if (!objective) { 173c69d1a72SBarry Smith ierr = PetscInfo2(snes,"Initial fnorm %14.12e gnorm %14.12e\n", (double)fnorm, (double)gnorm);CHKERRQ(ierr); 1748a430afbSPeter Brune } 1758a430afbSPeter Brune if (.5*g <= .5*f + lambda*alpha*initslope) { /* Sufficient reduction or step tolerance convergence */ 17671b4ebd2SPeter Brune if (monitor) { 177ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 178bd4a8a71SBarry Smith if (!objective) { 179c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Using full step: fnorm %14.12e gnorm %14.12e\n", (double)fnorm, (double)gnorm);CHKERRQ(ierr); 1808a430afbSPeter Brune } else { 1818a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Using full step: obj0 %14.12e obj %14.12e\n", (double)f, (double)g);CHKERRQ(ierr); 1828a430afbSPeter Brune } 183ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 18471b4ebd2SPeter Brune } 18571b4ebd2SPeter Brune } else { 186c21ba15cSPeter Brune /* Since the full step didn't work and the step is tiny, quit */ 187c21ba15cSPeter Brune if (stol*xnorm > ynorm) { 188ced04f9dSPeter Brune ierr = SNESLineSearchSetNorms(linesearch,xnorm,fnorm,ynorm);CHKERRQ(ierr); 189e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_REDUCT);CHKERRQ(ierr); 190c61ba1e2SPeter Brune if (monitor) { 191c61ba1e2SPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 19208ed2907SPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Aborted due to ynorm < stol*xnorm (%14.12e < %14.12e) and inadequate full step.\n",(double)ynorm,(double)stol*xnorm);CHKERRQ(ierr); 193c61ba1e2SPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 194c61ba1e2SPeter Brune } 195c21ba15cSPeter Brune PetscFunctionReturn(0); 196c21ba15cSPeter Brune } 19771b4ebd2SPeter Brune /* Fit points with quadratic */ 1988a430afbSPeter Brune lambdatemp = -initslope/(g - f - 2.0*lambda*initslope); 19971b4ebd2SPeter Brune lambdaprev = lambda; 2008a430afbSPeter Brune gprev = g; 20171b4ebd2SPeter Brune if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 20271b4ebd2SPeter Brune if (lambdatemp <= .1*lambda) lambda = .1*lambda; 20371b4ebd2SPeter Brune else lambda = lambdatemp; 20471b4ebd2SPeter Brune 20571b4ebd2SPeter Brune ierr = VecWAXPY(W,-lambda,Y,X);CHKERRQ(ierr); 2069bd66eb0SPeter Brune if (linesearch->ops->viproject) { 2079bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 2089bd66eb0SPeter Brune } 20971b4ebd2SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 21071b4ebd2SPeter Brune ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr); 21171b4ebd2SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 212e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_FUNCTION);CHKERRQ(ierr); 21371b4ebd2SPeter Brune PetscFunctionReturn(0); 21471b4ebd2SPeter Brune } 215bd4a8a71SBarry Smith if (objective) { 2168a430afbSPeter Brune ierr = SNESComputeObjective(snes,W,&g);CHKERRQ(ierr); 2178a430afbSPeter Brune } else { 218ce5a860aSPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,G);CHKERRQ(ierr); 2199bd66eb0SPeter Brune if (linesearch->ops->vinorm) { 2209bd66eb0SPeter Brune gnorm = fnorm; 2219bd66eb0SPeter Brune ierr = (*linesearch->ops->vinorm)(snes, G, W, &gnorm);CHKERRQ(ierr); 2229bd66eb0SPeter Brune } else { 22371b4ebd2SPeter Brune ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); 2249bd66eb0SPeter Brune } 225f1ab69e3SPeter Brune g = PetscSqr(gnorm); 2268a430afbSPeter Brune } 227c98378a5SBarry Smith if (PetscIsInfOrNanReal(g)) { 228422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_NANORINF);CHKERRQ(ierr); 229c61ba1e2SPeter Brune ierr = PetscInfo(snes,"Aborted due to Nan or Inf in function evaluation\n");CHKERRQ(ierr); 230c98378a5SBarry Smith PetscFunctionReturn(0); 231c98378a5SBarry Smith } 23271b4ebd2SPeter Brune if (monitor) { 233ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 234bd4a8a71SBarry Smith if (!objective) { 235c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: gnorm after quadratic fit %14.12e\n",(double)gnorm);CHKERRQ(ierr); 2368a430afbSPeter Brune } else { 2378a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: obj after quadratic fit %14.12e\n",(double)g);CHKERRQ(ierr); 2388a430afbSPeter Brune } 239ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 24071b4ebd2SPeter Brune } 2418a430afbSPeter Brune if (.5*g < .5*f + lambda*alpha*initslope) { /* sufficient reduction */ 24271b4ebd2SPeter Brune if (monitor) { 243ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 24471b4ebd2SPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Quadratically determined step, lambda=%18.16e\n",(double)lambda);CHKERRQ(ierr); 245ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 24671b4ebd2SPeter Brune } 24771b4ebd2SPeter Brune } else { 24871b4ebd2SPeter Brune /* Fit points with cubic */ 24971b4ebd2SPeter Brune for (count = 0; count < max_its; count++) { 25071b4ebd2SPeter Brune if (lambda <= minlambda) { 25171b4ebd2SPeter Brune if (monitor) { 252ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 25371b4ebd2SPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr); 254bd4a8a71SBarry Smith if (!objective) { 25571b4ebd2SPeter Brune ierr = PetscViewerASCIIPrintf(monitor, 25671b4ebd2SPeter Brune " Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n", 257c69d1a72SBarry Smith (double)fnorm, (double)gnorm, (double)ynorm, (double)minlambda, (double)lambda, (double)initslope);CHKERRQ(ierr); 2588a430afbSPeter Brune } else { 2598a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor, 2608a430afbSPeter Brune " Line search: obj(0)=%18.16e, obj=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n", 2618a430afbSPeter Brune (double)f, (double)g, (double)ynorm, (double)minlambda, (double)lambda, (double)initslope);CHKERRQ(ierr); 2628a430afbSPeter Brune } 263ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 26471b4ebd2SPeter Brune } 265e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_REDUCT);CHKERRQ(ierr); 26671b4ebd2SPeter Brune PetscFunctionReturn(0); 26771b4ebd2SPeter Brune } 268b000cd8dSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 2698a430afbSPeter Brune t1 = .5*(g - f) - lambda*initslope; 2708a430afbSPeter Brune t2 = .5*(gprev - f) - lambdaprev*initslope; 27171b4ebd2SPeter Brune a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 27271b4ebd2SPeter Brune b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 27371b4ebd2SPeter Brune d = b*b - 3*a*initslope; 27471b4ebd2SPeter Brune if (d < 0.0) d = 0.0; 275f5af7f23SKarl Rupp if (a == 0.0) lambdatemp = -initslope/(2.0*b); 276f5af7f23SKarl Rupp else lambdatemp = (-b + PetscSqrtReal(d))/(3.0*a); 277f5af7f23SKarl Rupp 278b000cd8dSPeter Brune } else if (linesearch->order == SNES_LINESEARCH_ORDER_QUADRATIC) { 2798a430afbSPeter Brune lambdatemp = -initslope/(g - f - 2.0*initslope); 280ce94432eSBarry Smith } else SETERRQ(PetscObjectComm((PetscObject)linesearch), PETSC_ERR_SUP, "unsupported line search order for type bt"); 28171b4ebd2SPeter Brune lambdaprev = lambda; 2828a430afbSPeter Brune gprev = g; 28371b4ebd2SPeter Brune if (lambdatemp > .5*lambda) lambdatemp = .5*lambda; 28471b4ebd2SPeter Brune if (lambdatemp <= .1*lambda) lambda = .1*lambda; 28571b4ebd2SPeter Brune else lambda = lambdatemp; 28671b4ebd2SPeter Brune ierr = VecWAXPY(W,-lambda,Y,X);CHKERRQ(ierr); 287b7b2e573SPeter Brune if (linesearch->ops->viproject) { 288b7b2e573SPeter Brune ierr = (*linesearch->ops->viproject)(snes,W);CHKERRQ(ierr); 289b7b2e573SPeter Brune } 29071b4ebd2SPeter Brune if (snes->nfuncs >= snes->max_funcs) { 29171b4ebd2SPeter Brune ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr); 292bd4a8a71SBarry Smith if (!objective) { 29371b4ebd2SPeter Brune ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n", 294c69d1a72SBarry Smith (double)fnorm,(double)gnorm,(double)ynorm,(double)lambda,(double)initslope);CHKERRQ(ierr); 2958a430afbSPeter Brune } 296e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_FUNCTION);CHKERRQ(ierr); 29771b4ebd2SPeter Brune snes->reason = SNES_DIVERGED_FUNCTION_COUNT; 29871b4ebd2SPeter Brune PetscFunctionReturn(0); 29971b4ebd2SPeter Brune } 300bd4a8a71SBarry Smith if (objective) { 3018a430afbSPeter Brune ierr = SNESComputeObjective(snes,W,&g);CHKERRQ(ierr); 3028a430afbSPeter Brune } else { 303ce5a860aSPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,G);CHKERRQ(ierr); 3049bd66eb0SPeter Brune if (linesearch->ops->vinorm) { 3059bd66eb0SPeter Brune gnorm = fnorm; 3069bd66eb0SPeter Brune ierr = (*linesearch->ops->vinorm)(snes, G, W, &gnorm);CHKERRQ(ierr); 3079bd66eb0SPeter Brune } else { 30871b4ebd2SPeter Brune ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); 3098a430afbSPeter Brune } 310f1ab69e3SPeter Brune g = PetscSqr(gnorm); 3119bd66eb0SPeter Brune } 312c98378a5SBarry Smith if (PetscIsInfOrNanReal(gnorm)) { 313422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_NANORINF);CHKERRQ(ierr); 314c61ba1e2SPeter Brune ierr = PetscInfo(snes,"Aborted due to Nan or Inf in function evaluation\n");CHKERRQ(ierr); 315c98378a5SBarry Smith PetscFunctionReturn(0); 316c98378a5SBarry Smith } 3178a430afbSPeter Brune if (.5*g < .5*f + lambda*alpha*initslope) { /* is reduction enough? */ 31871b4ebd2SPeter Brune if (monitor) { 319ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 320bd4a8a71SBarry Smith if (!objective) { 321b000cd8dSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 322c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Cubically determined step, current gnorm %14.12e lambda=%18.16e\n",(double)gnorm,(double)lambda);CHKERRQ(ierr); 32371b4ebd2SPeter Brune } else { 324c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Quadratically determined step, current gnorm %14.12e lambda=%18.16e\n",(double)gnorm,(double)lambda);CHKERRQ(ierr); 32571b4ebd2SPeter Brune } 326ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 3278a430afbSPeter Brune } else { 3288a430afbSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 3298a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Cubically determined step, obj %14.12e lambda=%18.16e\n",(double)g,(double)lambda);CHKERRQ(ierr); 3308a430afbSPeter Brune } else { 3318a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Quadratically determined step, obj %14.12e lambda=%18.16e\n",(double)g,(double)lambda);CHKERRQ(ierr); 3328a430afbSPeter Brune } 3338a430afbSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 3348a430afbSPeter Brune } 33571b4ebd2SPeter Brune } 33671b4ebd2SPeter Brune break; 337f5af7f23SKarl Rupp } else if (monitor) { 338ea5d4fccSPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 339bd4a8a71SBarry Smith if (!objective) { 340b000cd8dSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 341c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Cubic step no good, shrinking lambda, current gnorm %12.12e lambda=%18.16e\n",(double)gnorm,(double)lambda);CHKERRQ(ierr); 34271b4ebd2SPeter Brune } else { 343c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: Quadratic step no good, shrinking lambda, current gnorm %12.12e lambda=%18.16e\n",(double)gnorm,(double)lambda);CHKERRQ(ierr); 34471b4ebd2SPeter Brune } 345ea5d4fccSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 3468a430afbSPeter Brune } else { 3478a430afbSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 3488a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Cubic step no good, shrinking lambda, obj %12.12e lambda=%18.16e\n",(double)g,(double)lambda);CHKERRQ(ierr); 3498a430afbSPeter Brune } else { 3508a430afbSPeter Brune ierr = PetscViewerASCIIPrintf(monitor," Line search: Quadratic step no good, shrinking lambda, obj %12.12e lambda=%18.16e\n",(double)g,(double)lambda);CHKERRQ(ierr); 3518a430afbSPeter Brune } 3528a430afbSPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 3538a430afbSPeter Brune } 35471b4ebd2SPeter Brune } 35571b4ebd2SPeter Brune } 35671b4ebd2SPeter Brune } 35771b4ebd2SPeter Brune } 35871b4ebd2SPeter Brune 35971b4ebd2SPeter Brune /* postcheck */ 3607b1df9c1SPeter Brune ierr = SNESLineSearchPostCheck(linesearch,X,Y,W,&changed_y,&changed_w);CHKERRQ(ierr); 36171b4ebd2SPeter Brune if (changed_y) { 36271b4ebd2SPeter Brune ierr = VecWAXPY(W,-lambda,Y,X);CHKERRQ(ierr); 3639bd66eb0SPeter Brune if (linesearch->ops->viproject) { 3649bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 3659bd66eb0SPeter Brune } 36671b4ebd2SPeter Brune } 367bd4a8a71SBarry Smith if (changed_y || changed_w || objective) { /* recompute the function norm if the step has changed or the objective isn't the norm */ 368ce5a860aSPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,G);CHKERRQ(ierr); 3699bd66eb0SPeter Brune if (linesearch->ops->vinorm) { 3709bd66eb0SPeter Brune gnorm = fnorm; 3719bd66eb0SPeter Brune ierr = (*linesearch->ops->vinorm)(snes, G, W, &gnorm);CHKERRQ(ierr); 3729bd66eb0SPeter Brune } else { 3739bd66eb0SPeter Brune ierr = VecNorm(G,NORM_2,&gnorm);CHKERRQ(ierr); 3749bd66eb0SPeter Brune } 3759bd66eb0SPeter Brune ierr = VecNorm(Y,NORM_2,&ynorm);CHKERRQ(ierr); 376c98378a5SBarry Smith if (PetscIsInfOrNanReal(gnorm)) { 377422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch,SNES_LINESEARCH_FAILED_NANORINF);CHKERRQ(ierr); 378c61ba1e2SPeter Brune ierr = PetscInfo(snes,"Aborted due to Nan or Inf in function evaluation\n");CHKERRQ(ierr); 379c98378a5SBarry Smith PetscFunctionReturn(0); 380c98378a5SBarry Smith } 381c427506bSPeter Brune } 38271b4ebd2SPeter Brune 38371b4ebd2SPeter Brune /* copy the solution over */ 38471b4ebd2SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 385c427506bSPeter Brune ierr = VecCopy(G, F);CHKERRQ(ierr); 386c427506bSPeter Brune ierr = VecNorm(X, NORM_2, &xnorm);CHKERRQ(ierr); 387f1c6b773SPeter Brune ierr = SNESLineSearchSetLambda(linesearch, lambda);CHKERRQ(ierr); 388f1c6b773SPeter Brune ierr = SNESLineSearchSetNorms(linesearch, xnorm, gnorm, ynorm);CHKERRQ(ierr); 38971b4ebd2SPeter Brune PetscFunctionReturn(0); 39071b4ebd2SPeter Brune } 39171b4ebd2SPeter Brune 39271b4ebd2SPeter Brune #undef __FUNCT__ 3937f1410a3SPeter Brune #define __FUNCT__ "SNESLineSearchView_BT" 3947f1410a3SPeter Brune PetscErrorCode SNESLineSearchView_BT(SNESLineSearch linesearch, PetscViewer viewer) 3957f1410a3SPeter Brune { 3967f1410a3SPeter Brune PetscErrorCode ierr; 3977f1410a3SPeter Brune PetscBool iascii; 3987f1410a3SPeter Brune SNESLineSearch_BT *bt; 399075cc632SBarry Smith 4007f1410a3SPeter Brune PetscFunctionBegin; 401251f4c67SDmitry Karpeev ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 4027f1410a3SPeter Brune bt = (SNESLineSearch_BT*)linesearch->data; 4037f1410a3SPeter Brune if (iascii) { 404b000cd8dSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_CUBIC) { 4057f1410a3SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " interpolation: cubic\n");CHKERRQ(ierr); 406b000cd8dSPeter Brune } else if (linesearch->order == SNES_LINESEARCH_ORDER_QUADRATIC) { 4077f1410a3SPeter Brune ierr = PetscViewerASCIIPrintf(viewer, " interpolation: quadratic\n");CHKERRQ(ierr); 4087f1410a3SPeter Brune } 4097904a332SBarry Smith ierr = PetscViewerASCIIPrintf(viewer, " alpha=%e\n", (double)bt->alpha);CHKERRQ(ierr); 4107f1410a3SPeter Brune } 4117f1410a3SPeter Brune PetscFunctionReturn(0); 4127f1410a3SPeter Brune } 4137f1410a3SPeter Brune 4147f1410a3SPeter Brune 4157f1410a3SPeter Brune #undef __FUNCT__ 416f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchDestroy_BT" 417f1c6b773SPeter Brune static PetscErrorCode SNESLineSearchDestroy_BT(SNESLineSearch linesearch) 418731c067cSJed Brown { 419731c067cSJed Brown PetscErrorCode ierr; 42071b4ebd2SPeter Brune 42171b4ebd2SPeter Brune PetscFunctionBegin; 422731c067cSJed Brown ierr = PetscFree(linesearch->data);CHKERRQ(ierr); 42371b4ebd2SPeter Brune PetscFunctionReturn(0); 42471b4ebd2SPeter Brune } 42571b4ebd2SPeter Brune 42671b4ebd2SPeter Brune 42771b4ebd2SPeter Brune #undef __FUNCT__ 428f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchSetFromOptions_BT" 4294416b707SBarry Smith static PetscErrorCode SNESLineSearchSetFromOptions_BT(PetscOptionItems *PetscOptionsObject,SNESLineSearch linesearch) 43071b4ebd2SPeter Brune { 43171b4ebd2SPeter Brune 43271b4ebd2SPeter Brune PetscErrorCode ierr; 433eb23ba39SBarry Smith SNESLineSearch_BT *bt = (SNESLineSearch_BT*)linesearch->data; 43471b4ebd2SPeter Brune 4356e111a19SKarl Rupp PetscFunctionBegin; 436e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNESLineSearch BT options");CHKERRQ(ierr); 4370298fd71SBarry Smith ierr = PetscOptionsReal("-snes_linesearch_alpha", "Descent tolerance", "SNESLineSearchBT", bt->alpha, &bt->alpha, NULL);CHKERRQ(ierr); 43871b4ebd2SPeter Brune ierr = PetscOptionsTail();CHKERRQ(ierr); 43971b4ebd2SPeter Brune PetscFunctionReturn(0); 44071b4ebd2SPeter Brune } 44171b4ebd2SPeter Brune 44271b4ebd2SPeter Brune 44371b4ebd2SPeter Brune #undef __FUNCT__ 444f1c6b773SPeter Brune #define __FUNCT__ "SNESLineSearchCreate_BT" 445954494b2SJed Brown /*MC 446db609ea7SPeter Brune SNESLINESEARCHBT - Backtracking line search. 447954494b2SJed Brown 448db609ea7SPeter Brune This line search finds the minimum of a polynomial fitting of the L2 norm of the 449eb23ba39SBarry Smith function or the objective function if it is provided with SNESSetObjective(). If this fit does not satisfy the conditions for progress, the interval shrinks 450db609ea7SPeter Brune and the fit is reattempted at most max_it times or until lambda is below minlambda. 451954494b2SJed Brown 452cd7522eaSPeter Brune Options Database Keys: 453cd7522eaSPeter Brune + -snes_linesearch_alpha<1e-4> - slope descent parameter 454db609ea7SPeter Brune . -snes_linesearch_damping<1.0> - initial step length 455eb23ba39SBarry Smith . -snes_linesearch_maxstep <length> - if the length the initial step is larger than this then the 456e1bc860dSBarry Smith step is scaled back to be of this length at the beginning of the line search 457db609ea7SPeter Brune . -snes_linesearch_max_it<40> - maximum number of shrinking step 458db609ea7SPeter Brune . -snes_linesearch_minlambda<1e-12> - minimum step length allowed 459cd7522eaSPeter Brune - -snes_linesearch_order<cubic,quadratic> - order of the approximation 460cd7522eaSPeter Brune 461954494b2SJed Brown Level: advanced 462954494b2SJed Brown 463db609ea7SPeter Brune Notes: 464db609ea7SPeter Brune This line search is taken from "Numerical Methods for Unconstrained 465db609ea7SPeter Brune Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325. 466db609ea7SPeter Brune 467f1c6b773SPeter Brune .keywords: SNES, SNESLineSearch, damping 468954494b2SJed Brown 469f1c6b773SPeter Brune .seealso: SNESLineSearchCreate(), SNESLineSearchSetType() 470954494b2SJed Brown M*/ 4718cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_BT(SNESLineSearch linesearch) 47271b4ebd2SPeter Brune { 47371b4ebd2SPeter Brune 474f1c6b773SPeter Brune SNESLineSearch_BT *bt; 47571b4ebd2SPeter Brune PetscErrorCode ierr; 47671b4ebd2SPeter Brune 47771b4ebd2SPeter Brune PetscFunctionBegin; 478f1c6b773SPeter Brune linesearch->ops->apply = SNESLineSearchApply_BT; 479f1c6b773SPeter Brune linesearch->ops->destroy = SNESLineSearchDestroy_BT; 480f1c6b773SPeter Brune linesearch->ops->setfromoptions = SNESLineSearchSetFromOptions_BT; 4810298fd71SBarry Smith linesearch->ops->reset = NULL; 4827f1410a3SPeter Brune linesearch->ops->view = SNESLineSearchView_BT; 4830298fd71SBarry Smith linesearch->ops->setup = NULL; 48471b4ebd2SPeter Brune 485b00a9115SJed Brown ierr = PetscNewLog(linesearch,&bt);CHKERRQ(ierr); 486f5af7f23SKarl Rupp 48771b4ebd2SPeter Brune linesearch->data = (void*)bt; 48871b4ebd2SPeter Brune linesearch->max_its = 40; 489b000cd8dSPeter Brune linesearch->order = SNES_LINESEARCH_ORDER_CUBIC; 49071b4ebd2SPeter Brune bt->alpha = 1e-4; 49171b4ebd2SPeter Brune PetscFunctionReturn(0); 49271b4ebd2SPeter Brune } 493