1af0996ceSBarry Smith #include <petsc/private/linesearchimpl.h> 26a388c36SPeter Brune #include <petscsnes.h> 3bbd5d0b3SPeter Brune 4f1c6b773SPeter Brune static PetscErrorCode SNESLineSearchApply_CP(SNESLineSearch linesearch) 5bbd5d0b3SPeter Brune { 6422a814eSBarry Smith PetscBool changed_y, changed_w; 7bbd5d0b3SPeter Brune PetscErrorCode ierr; 86a388c36SPeter Brune Vec X, Y, F, W; 96a388c36SPeter Brune SNES snes; 10516fe3c3SPeter Brune PetscReal xnorm, ynorm, gnorm, steptol, atol, rtol, ltol, maxstep; 11bbd5d0b3SPeter Brune 12bbd5d0b3SPeter Brune PetscReal lambda, lambda_old, lambda_update, delLambda; 13b8ac21a2SPeter Brune PetscScalar fty, fty_init, fty_old, fty_mid1, fty_mid2, s; 146a388c36SPeter Brune PetscInt i, max_its; 156a388c36SPeter Brune 166a388c36SPeter Brune PetscViewer monitor; 17bbd5d0b3SPeter Brune 18bbd5d0b3SPeter Brune PetscFunctionBegin; 190298fd71SBarry Smith ierr = SNESLineSearchGetVecs(linesearch, &X, &F, &Y, &W, NULL);CHKERRQ(ierr); 20f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr); 21f1c6b773SPeter Brune ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 22f1c6b773SPeter Brune ierr = SNESLineSearchGetLambda(linesearch, &lambda);CHKERRQ(ierr); 23f1c6b773SPeter Brune ierr = SNESLineSearchGetTolerances(linesearch, &steptol, &maxstep, &rtol, &atol, <ol, &max_its);CHKERRQ(ierr); 24422a814eSBarry Smith ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_SUCCEEDED);CHKERRQ(ierr); 25dcf2fd19SBarry Smith ierr = SNESLineSearchGetDefaultMonitor(linesearch, &monitor);CHKERRQ(ierr); 266a388c36SPeter Brune 27bbd5d0b3SPeter Brune /* precheck */ 287b1df9c1SPeter Brune ierr = SNESLineSearchPreCheck(linesearch,X,Y,&changed_y);CHKERRQ(ierr); 29bbd5d0b3SPeter Brune lambda_old = 0.0; 3062893cf2SPeter Brune 31e0e0c2afSPeter Brune ierr = VecDot(F,Y,&fty_old);CHKERRQ(ierr); 32*9e0a2ef9SBarry Smith if (PetscAbsScalar(fty_old) < atol) { 33*9e0a2ef9SBarry Smith if (monitor) { 34*9e0a2ef9SBarry Smith ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 35*9e0a2ef9SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search terminated ended at initial point because dot(F,Y) = %g < atol = %g\n",(double)fty_old, (double)atol);CHKERRQ(ierr); 36*9e0a2ef9SBarry Smith ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 37*9e0a2ef9SBarry Smith } 38*9e0a2ef9SBarry Smith PetscFunctionReturn(0); 39*9e0a2ef9SBarry Smith } 40*9e0a2ef9SBarry Smith 4162893cf2SPeter Brune fty_init = fty_old; 42c0b2db79SJed Brown 43c0b2db79SJed Brown for (i = 0; i < max_its; i++) { 44bbd5d0b3SPeter Brune /* compute the norm at lambda */ 45bbd5d0b3SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 46bbd5d0b3SPeter Brune ierr = VecAXPY(W, -lambda, Y);CHKERRQ(ierr); 479bd66eb0SPeter Brune if (linesearch->ops->viproject) { 489bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 499bd66eb0SPeter Brune } 50fb8e56e0SPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,F);CHKERRQ(ierr); 51e0e0c2afSPeter Brune ierr = VecDot(F,Y,&fty);CHKERRQ(ierr); 52bbd5d0b3SPeter Brune 53bbd5d0b3SPeter Brune delLambda = lambda - lambda_old; 54b8ac21a2SPeter Brune 55b8ac21a2SPeter Brune /* check for convergence */ 56b8ac21a2SPeter Brune if (PetscAbsReal(delLambda) < steptol*lambda) break; 57b8ac21a2SPeter Brune if (PetscAbsScalar(fty) / PetscAbsScalar(fty_init) < rtol) break; 58a7370c10SPeter Brune if (PetscAbsScalar(fty) < atol && i > 0) break; 596a388c36SPeter Brune if (monitor) { 606a388c36SPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 61c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search: lambdas = [%g, %g], ftys = [%g, %g]\n",(double)lambda, (double)lambda_old, (double)PetscRealPart(fty), (double)PetscRealPart(fty_old));CHKERRQ(ierr); 626a388c36SPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 63bbd5d0b3SPeter Brune } 64bbd5d0b3SPeter Brune 65bbd5d0b3SPeter Brune /* compute the search direction */ 66b000cd8dSPeter Brune if (linesearch->order == SNES_LINESEARCH_ORDER_LINEAR) { 67b8ac21a2SPeter Brune s = (fty - fty_old) / delLambda; 68b000cd8dSPeter Brune } else if (linesearch->order == SNES_LINESEARCH_ORDER_QUADRATIC) { 69b8ac21a2SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 70b8ac21a2SPeter Brune ierr = VecAXPY(W, -0.5*(lambda + lambda_old), Y);CHKERRQ(ierr); 71b8ac21a2SPeter Brune if (linesearch->ops->viproject) { 72b8ac21a2SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 73b8ac21a2SPeter Brune } 74fb8e56e0SPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,F);CHKERRQ(ierr); 75b8ac21a2SPeter Brune ierr = VecDot(F, Y, &fty_mid1);CHKERRQ(ierr); 76b8ac21a2SPeter Brune s = (3.*fty - 4.*fty_mid1 + fty_old) / delLambda; 77b8ac21a2SPeter Brune } else { 78b8ac21a2SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 79b8ac21a2SPeter Brune ierr = VecAXPY(W, -0.5*(lambda + lambda_old), Y);CHKERRQ(ierr); 80b8ac21a2SPeter Brune if (linesearch->ops->viproject) { 81b8ac21a2SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 82b8ac21a2SPeter Brune } 83fb8e56e0SPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,W,F);CHKERRQ(ierr); 84e0e0c2afSPeter Brune ierr = VecDot(F, Y, &fty_mid1);CHKERRQ(ierr); 85b8ac21a2SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 86b8ac21a2SPeter Brune ierr = VecAXPY(W, -(lambda + 0.5*(lambda - lambda_old)), Y);CHKERRQ(ierr); 87b8ac21a2SPeter Brune if (linesearch->ops->viproject) { 88b8ac21a2SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 89b8ac21a2SPeter Brune } 90fb8e56e0SPeter Brune ierr = (*linesearch->ops->snesfunc)(snes, W, F);CHKERRQ(ierr); 91e0e0c2afSPeter Brune ierr = VecDot(F, Y, &fty_mid2);CHKERRQ(ierr); 92b8ac21a2SPeter Brune s = (2.*fty_mid2 + 3.*fty - 6.*fty_mid1 + fty_old) / (3.*delLambda); 93b8ac21a2SPeter Brune } 94b8ac21a2SPeter Brune /* if the solve is going in the wrong direction, fix it */ 95b8ac21a2SPeter Brune if (PetscRealPart(s) > 0.) s = -s; 96b8ac21a2SPeter Brune lambda_update = lambda - PetscRealPart(fty / s); 97b8ac21a2SPeter Brune 98b8ac21a2SPeter Brune /* switch directions if we stepped out of bounds */ 99f5af7f23SKarl Rupp if (lambda_update < steptol) lambda_update = lambda + PetscRealPart(fty / s); 100b8ac21a2SPeter Brune 101620fc8aaSSatish Balay if (PetscIsInfOrNanReal(lambda_update)) break; 102f5af7f23SKarl Rupp if (lambda_update > maxstep) break; 103bbd5d0b3SPeter Brune 104bbd5d0b3SPeter Brune /* compute the new state of the line search */ 105bbd5d0b3SPeter Brune lambda_old = lambda; 106bbd5d0b3SPeter Brune lambda = lambda_update; 107bbd5d0b3SPeter Brune fty_old = fty; 108bbd5d0b3SPeter Brune } 109bbd5d0b3SPeter Brune /* construct the solution */ 110bbd5d0b3SPeter Brune ierr = VecCopy(X, W);CHKERRQ(ierr); 111bbd5d0b3SPeter Brune ierr = VecAXPY(W, -lambda, Y);CHKERRQ(ierr); 1129bd66eb0SPeter Brune if (linesearch->ops->viproject) { 1139bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, W);CHKERRQ(ierr); 1149bd66eb0SPeter Brune } 115bbd5d0b3SPeter Brune /* postcheck */ 1167b1df9c1SPeter Brune ierr = SNESLineSearchPostCheck(linesearch,X,Y,W,&changed_y,&changed_w);CHKERRQ(ierr); 117bbd5d0b3SPeter Brune if (changed_y) { 118bbd5d0b3SPeter Brune ierr = VecAXPY(X, -lambda, Y);CHKERRQ(ierr); 1199bd66eb0SPeter Brune if (linesearch->ops->viproject) { 1209bd66eb0SPeter Brune ierr = (*linesearch->ops->viproject)(snes, X);CHKERRQ(ierr); 1219bd66eb0SPeter Brune } 122bbd5d0b3SPeter Brune } else { 123bbd5d0b3SPeter Brune ierr = VecCopy(W, X);CHKERRQ(ierr); 124bbd5d0b3SPeter Brune } 125fb8e56e0SPeter Brune ierr = (*linesearch->ops->snesfunc)(snes,X,F);CHKERRQ(ierr); 126bbd5d0b3SPeter Brune 127f1c6b773SPeter Brune ierr = SNESLineSearchComputeNorms(linesearch);CHKERRQ(ierr); 128f1c6b773SPeter Brune ierr = SNESLineSearchGetNorms(linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr); 129bbd5d0b3SPeter Brune 130f1c6b773SPeter Brune ierr = SNESLineSearchSetLambda(linesearch, lambda);CHKERRQ(ierr); 1316a388c36SPeter Brune 1326a388c36SPeter Brune if (monitor) { 1336a388c36SPeter Brune ierr = PetscViewerASCIIAddTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 134c69d1a72SBarry Smith ierr = PetscViewerASCIIPrintf(monitor," Line search terminated: lambda = %g, fnorms = %g\n", (double)lambda, (double)gnorm);CHKERRQ(ierr); 1356a388c36SPeter Brune ierr = PetscViewerASCIISubtractTab(monitor,((PetscObject)linesearch)->tablevel);CHKERRQ(ierr); 136bbd5d0b3SPeter Brune } 1376a388c36SPeter Brune if (lambda <= steptol) { 138e9b602ebSSatish Balay ierr = SNESLineSearchSetReason(linesearch, SNES_LINESEARCH_FAILED_REDUCT);CHKERRQ(ierr); 139bbd5d0b3SPeter Brune } 140bbd5d0b3SPeter Brune PetscFunctionReturn(0); 141bbd5d0b3SPeter Brune } 142bbd5d0b3SPeter Brune 143954494b2SJed Brown /*MC 1441a4f838cSPeter Brune SNESLINESEARCHCP - Critical point line search. This line search assumes that there exists some 145cd7522eaSPeter Brune artificial G(x) for which the SNESFunction F(x) = grad G(x). Therefore, this line search seeks 146db609ea7SPeter Brune to find roots of dot(F, Y) via a secant method. 147cd7522eaSPeter Brune 148cd7522eaSPeter Brune Options Database Keys: 149eb23ba39SBarry Smith + -snes_linesearch_minlambda <minlambda> - the minimum acceptable lambda 150eb23ba39SBarry Smith . -snes_linesearch_maxstep <length> - the algorithm insures that a step length is never longer than this value 151eb23ba39SBarry Smith . -snes_linesearch_damping <damping> - initial trial step length is scaled by this factor, default is 1.0 152eb23ba39SBarry Smith - -snes_linesearch_max_it <max_it> - the maximum number of secant steps performed. 153cd7522eaSPeter Brune 154cd7522eaSPeter Brune Notes: 155eb23ba39SBarry Smith This method does NOT use the objective function if it is provided with SNESSetObjective(). 156eb23ba39SBarry Smith 157cd7522eaSPeter Brune This method is the preferred line search for SNESQN and SNESNCG. 158954494b2SJed Brown 159954494b2SJed Brown Level: advanced 160954494b2SJed Brown 161f1c6b773SPeter Brune .keywords: SNES, SNESLineSearch, damping 162954494b2SJed Brown 163f1c6b773SPeter Brune .seealso: SNESLineSearchCreate(), SNESLineSearchSetType() 164954494b2SJed Brown M*/ 1658cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESLineSearchCreate_CP(SNESLineSearch linesearch) 166bbd5d0b3SPeter Brune { 167bbd5d0b3SPeter Brune PetscFunctionBegin; 168f1c6b773SPeter Brune linesearch->ops->apply = SNESLineSearchApply_CP; 1690298fd71SBarry Smith linesearch->ops->destroy = NULL; 1700298fd71SBarry Smith linesearch->ops->setfromoptions = NULL; 1710298fd71SBarry Smith linesearch->ops->reset = NULL; 1720298fd71SBarry Smith linesearch->ops->view = NULL; 1730298fd71SBarry Smith linesearch->ops->setup = NULL; 174b000cd8dSPeter Brune linesearch->order = SNES_LINESEARCH_ORDER_LINEAR; 175a491bab8SPeter Brune 176a491bab8SPeter Brune linesearch->max_its = 1; 177bbd5d0b3SPeter Brune PetscFunctionReturn(0); 178bbd5d0b3SPeter Brune } 179