1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER 2*fee21e36SBarry Smith static char vcid[] = "$Id: ls.c,v 1.104 1998/04/09 04:18:17 bsmith Exp bsmith $"; 35e76c431SBarry Smith #endif 45e76c431SBarry Smith 55e76c431SBarry Smith #include <math.h> 670f55243SBarry Smith #include "src/snes/impls/ls/ls.h" 7b16a3bb1SBarry Smith #include "pinclude/pviewer.h" 85e42470aSBarry Smith 95e42470aSBarry Smith /* 105e42470aSBarry Smith Implements a line search variant of Newton's Method 115e76c431SBarry Smith for solving systems of nonlinear equations. 125e76c431SBarry Smith 135e76c431SBarry Smith Input parameters: 145e42470aSBarry Smith . snes - nonlinear context obtained from SNESCreate() 155e76c431SBarry Smith 165e42470aSBarry Smith Output Parameters: 17a935fc98SLois Curfman McInnes . outits - Number of global iterations until termination. 185e76c431SBarry Smith 195e76c431SBarry Smith Notes: 205e76c431SBarry Smith This implements essentially a truncated Newton method with a 215e76c431SBarry Smith line search. By default a cubic backtracking line search 225e76c431SBarry Smith is employed, as described in the text "Numerical Methods for 235e76c431SBarry Smith Unconstrained Optimization and Nonlinear Equations" by Dennis 24393d2d9aSLois Curfman McInnes and Schnabel. 255e76c431SBarry Smith */ 265e76c431SBarry Smith 275615d1e5SSatish Balay #undef __FUNC__ 285615d1e5SSatish Balay #define __FUNC__ "SNESSolve_EQ_LS" 29f63b844aSLois Curfman McInnes int SNESSolve_EQ_LS(SNES snes,int *outits) 305e76c431SBarry Smith { 315e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 32761aaf1bSLois Curfman McInnes int maxits, i, history_len, ierr, lits, lsfail; 33112a2221SBarry Smith MatStructure flg = DIFFERENT_NONZERO_PATTERN; 346b5873e3SBarry Smith double fnorm, gnorm, xnorm, ynorm, *history; 355e42470aSBarry Smith Vec Y, X, F, G, W, TMP; 365e76c431SBarry Smith 373a40ed3dSBarry Smith PetscFunctionBegin; 385e42470aSBarry Smith history = snes->conv_hist; /* convergence history */ 3951979daaSLois Curfman McInnes history_len = snes->conv_hist_size; /* convergence history length */ 405e42470aSBarry Smith maxits = snes->max_its; /* maximum number of iterations */ 415e42470aSBarry Smith X = snes->vec_sol; /* solution vector */ 4239e2f89bSBarry Smith F = snes->vec_func; /* residual vector */ 435e42470aSBarry Smith Y = snes->work[0]; /* work vectors */ 445e42470aSBarry Smith G = snes->work[1]; 455e42470aSBarry Smith W = snes->work[2]; 465e76c431SBarry Smith 4725ed9cd1SBarry Smith snes->iter = 0; 485334005bSBarry Smith ierr = SNESComputeFunction(snes,X,F); CHKERRQ(ierr); /* F(X) */ 49cddf8d76SBarry Smith ierr = VecNorm(F,NORM_2,&fnorm); CHKERRQ(ierr); /* fnorm <- ||F|| */ 505e42470aSBarry Smith snes->norm = fnorm; 5151979daaSLois Curfman McInnes if (history) history[0] = fnorm; 5294a424c1SBarry Smith SNESMonitor(snes,0,fnorm); 535e76c431SBarry Smith 543a40ed3dSBarry Smith if (fnorm < snes->atol) {*outits = 0; PetscFunctionReturn(0);} 5594a9d846SBarry Smith 56d034289bSBarry Smith /* set parameter for default relative tolerance convergence test */ 57d034289bSBarry Smith snes->ttol = fnorm*snes->rtol; 58d034289bSBarry Smith 595e76c431SBarry Smith for ( i=0; i<maxits; i++ ) { 605e42470aSBarry Smith snes->iter = i+1; 615e76c431SBarry Smith 62ea4d3ed3SLois Curfman McInnes /* Solve J Y = F, where J is Jacobian matrix */ 635334005bSBarry Smith ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg); CHKERRQ(ierr); 645334005bSBarry Smith ierr = SLESSetOperators(snes->sles,snes->jacobian,snes->jacobian_pre,flg); CHKERRQ(ierr); 6578b31e54SBarry Smith ierr = SLESSolve(snes->sles,F,Y,&lits); CHKERRQ(ierr); 667a00f4a9SLois Curfman McInnes snes->linear_its += PetscAbsInt(lits); 67af1ccdebSLois Curfman McInnes PLogInfo(snes,"SNESSolve_EQ_LS: iter=%d, linear solve iterations=%d\n",snes->iter,lits); 68ea4d3ed3SLois Curfman McInnes 69ea4d3ed3SLois Curfman McInnes /* Compute a (scaled) negative update in the line search routine: 70ea4d3ed3SLois Curfman McInnes Y <- X - lambda*Y 71ea4d3ed3SLois Curfman McInnes and evaluate G(Y) = function(Y)) 72ea4d3ed3SLois Curfman McInnes */ 7381b6cf68SLois Curfman McInnes ierr = VecCopy(Y,snes->vec_sol_update_always); CHKERRQ(ierr); 74ddd12767SBarry Smith ierr = (*neP->LineSearch)(snes,X,F,G,Y,W,fnorm,&ynorm,&gnorm,&lsfail); CHKERRQ(ierr); 75af1ccdebSLois Curfman McInnes PLogInfo(snes,"SNESSolve_EQ_LS: fnorm=%g, gnorm=%g, ynorm=%g, lsfail=%d\n",fnorm,gnorm,ynorm,lsfail); 76761aaf1bSLois Curfman McInnes if (lsfail) snes->nfailures++; 775e76c431SBarry Smith 7839e2f89bSBarry Smith TMP = F; F = G; snes->vec_func_always = F; G = TMP; 7939e2f89bSBarry Smith TMP = X; X = Y; snes->vec_sol_always = X; Y = TMP; 805e76c431SBarry Smith fnorm = gnorm; 815e76c431SBarry Smith 825e42470aSBarry Smith snes->norm = fnorm; 835e76c431SBarry Smith if (history && history_len > i+1) history[i+1] = fnorm; 8494a424c1SBarry Smith SNESMonitor(snes,i+1,fnorm); 855e76c431SBarry Smith 865e76c431SBarry Smith /* Test for convergence */ 8729e0b56fSBarry Smith if (snes->converged) { 8829e0b56fSBarry Smith ierr = VecNorm(X,NORM_2,&xnorm); CHKERRQ(ierr); /* xnorm = || X || */ 89bbb6d6a8SBarry Smith if ((*snes->converged)(snes,xnorm,ynorm,fnorm,snes->cnvP)) { 9016c95cacSBarry Smith break; 9116c95cacSBarry Smith } 9216c95cacSBarry Smith } 9329e0b56fSBarry Smith } 9439e2f89bSBarry Smith if (X != snes->vec_sol) { 95393d2d9aSLois Curfman McInnes ierr = VecCopy(X,snes->vec_sol); CHKERRQ(ierr); 9639e2f89bSBarry Smith snes->vec_sol_always = snes->vec_sol; 9739e2f89bSBarry Smith snes->vec_func_always = snes->vec_func; 9839e2f89bSBarry Smith } 9952392280SLois Curfman McInnes if (i == maxits) { 100981c4779SBarry Smith PLogInfo(snes,"SNESSolve_EQ_LS: Maximum number of iterations has been reached: %d\n",maxits); 10152392280SLois Curfman McInnes i--; 10252392280SLois Curfman McInnes } 10351979daaSLois Curfman McInnes if (history) snes->conv_act_size = (history_len < i+1) ? history_len : i+1; 1045e42470aSBarry Smith *outits = i+1; 1053a40ed3dSBarry Smith PetscFunctionReturn(0); 1065e76c431SBarry Smith } 1075e76c431SBarry Smith /* ------------------------------------------------------------ */ 1085615d1e5SSatish Balay #undef __FUNC__ 1095615d1e5SSatish Balay #define __FUNC__ "SNESSetUp_EQ_LS" 110f63b844aSLois Curfman McInnes int SNESSetUp_EQ_LS(SNES snes ) 1115e76c431SBarry Smith { 1125e42470aSBarry Smith int ierr; 1133a40ed3dSBarry Smith 1143a40ed3dSBarry Smith PetscFunctionBegin; 11581b6cf68SLois Curfman McInnes snes->nwork = 4; 116d7e8b826SBarry Smith ierr = VecDuplicateVecs(snes->vec_sol,snes->nwork,&snes->work);CHKERRQ(ierr); 1175e42470aSBarry Smith PLogObjectParents(snes,snes->nwork,snes->work); 11881b6cf68SLois Curfman McInnes snes->vec_sol_update_always = snes->work[3]; 1193a40ed3dSBarry Smith PetscFunctionReturn(0); 1205e76c431SBarry Smith } 1215e76c431SBarry Smith /* ------------------------------------------------------------ */ 1225615d1e5SSatish Balay #undef __FUNC__ 123d4bb536fSBarry Smith #define __FUNC__ "SNESDestroy_EQ_LS" 124e1311b90SBarry Smith int SNESDestroy_EQ_LS(SNES snes) 1255e76c431SBarry Smith { 126393d2d9aSLois Curfman McInnes int ierr; 1273a40ed3dSBarry Smith 1283a40ed3dSBarry Smith PetscFunctionBegin; 1295baf8537SBarry Smith if (snes->nwork) { 1304b0e389bSBarry Smith ierr = VecDestroyVecs(snes->work,snes->nwork); CHKERRQ(ierr); 13121c89e3eSBarry Smith } 1320452661fSBarry Smith PetscFree(snes->data); 1333a40ed3dSBarry Smith PetscFunctionReturn(0); 1345e76c431SBarry Smith } 1355e76c431SBarry Smith /* ------------------------------------------------------------ */ 1365615d1e5SSatish Balay #undef __FUNC__ 1375615d1e5SSatish Balay #define __FUNC__ "SNESNoLineSearch" 13882bf6240SBarry Smith 1394b828684SBarry Smith /*@C 1405e42470aSBarry Smith SNESNoLineSearch - This routine is not a line search at all; 1415e76c431SBarry Smith it simply uses the full Newton step. Thus, this routine is intended 1425e76c431SBarry Smith to serve as a template and is not recommended for general use. 1435e76c431SBarry Smith 1445e76c431SBarry Smith Input Parameters: 1455e42470aSBarry Smith . snes - nonlinear context 1465e76c431SBarry Smith . x - current iterate 1475e76c431SBarry Smith . f - residual evaluated at x 1485e76c431SBarry Smith . y - search direction (contains new iterate on output) 1495e76c431SBarry Smith . w - work vector 1505e76c431SBarry Smith . fnorm - 2-norm of f 1515e76c431SBarry Smith 152c4a48953SLois Curfman McInnes Output Parameters: 1535e76c431SBarry Smith . g - residual evaluated at new iterate y 1545e76c431SBarry Smith . y - new iterate (contains search direction on input) 1555e76c431SBarry Smith . gnorm - 2-norm of g 1565e76c431SBarry Smith . ynorm - 2-norm of search length 157761aaf1bSLois Curfman McInnes . flag - set to 0, indicating a successful line search 1585e76c431SBarry Smith 159*fee21e36SBarry Smith Collective on SNES and Vec 160*fee21e36SBarry Smith 161c4a48953SLois Curfman McInnes Options Database Key: 16209d61ba7SLois Curfman McInnes $ -snes_eq_ls basic 163c4a48953SLois Curfman McInnes 16428ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 16528ae5a21SLois Curfman McInnes 166f59ffdedSLois Curfman McInnes .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 16777c4ece6SBarry Smith SNESSetLineSearch() 1685e76c431SBarry Smith @*/ 1695e42470aSBarry Smith int SNESNoLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 170761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag ) 1715e76c431SBarry Smith { 1725e42470aSBarry Smith int ierr; 1735334005bSBarry Smith Scalar mone = -1.0; 1745334005bSBarry Smith 1753a40ed3dSBarry Smith PetscFunctionBegin; 176761aaf1bSLois Curfman McInnes *flag = 0; 1777857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 178cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); /* ynorm = || y || */ 179ea4d3ed3SLois Curfman McInnes ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 180ea4d3ed3SLois Curfman McInnes ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 181cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); /* gnorm = || g || */ 1827857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 1833a40ed3dSBarry Smith PetscFunctionReturn(0); 1845e76c431SBarry Smith } 1855e76c431SBarry Smith /* ------------------------------------------------------------------ */ 1865615d1e5SSatish Balay #undef __FUNC__ 18729e0b56fSBarry Smith #define __FUNC__ "SNESNoLineSearchNoNorms" 18882bf6240SBarry Smith 18929e0b56fSBarry Smith /*@C 19029e0b56fSBarry Smith SNESNoLineSearchNoNorms - This routine is not a line search at 19129e0b56fSBarry Smith all; it simply uses the full Newton step. This version does not 19229e0b56fSBarry Smith even compute the norm of the function or search direction; this 19329e0b56fSBarry Smith is intended only when you know the full step is fine and are 19429e0b56fSBarry Smith not checking for convergence of the nonlinear iteration (for 19529e0b56fSBarry Smith example, you are running always for a fixed number of Newton 19629e0b56fSBarry Smith steps). 19729e0b56fSBarry Smith 19829e0b56fSBarry Smith Input Parameters: 19929e0b56fSBarry Smith . snes - nonlinear context 20029e0b56fSBarry Smith . x - current iterate 20129e0b56fSBarry Smith . f - residual evaluated at x 20229e0b56fSBarry Smith . y - search direction (contains new iterate on output) 20329e0b56fSBarry Smith . w - work vector 20429e0b56fSBarry Smith . fnorm - 2-norm of f 20529e0b56fSBarry Smith 20629e0b56fSBarry Smith Output Parameters: 20729e0b56fSBarry Smith . g - residual evaluated at new iterate y 20829e0b56fSBarry Smith . gnorm - not changed 20929e0b56fSBarry Smith . ynorm - not changed 21029e0b56fSBarry Smith . flag - set to 0, indicating a successful line search 21129e0b56fSBarry Smith 212*fee21e36SBarry Smith Collective on SNES and Vec 213*fee21e36SBarry Smith 21429e0b56fSBarry Smith Options Database Key: 21529e0b56fSBarry Smith $ -snes_eq_ls basicnonorms 21629e0b56fSBarry Smith 21729e0b56fSBarry Smith .keywords: SNES, nonlinear, line search, cubic 21829e0b56fSBarry Smith 21929e0b56fSBarry Smith .seealso: SNESCubicLineSearch(), SNESQuadraticLineSearch(), 22029e0b56fSBarry Smith SNESSetLineSearch(), SNESNoLineSearch() 22129e0b56fSBarry Smith @*/ 22229e0b56fSBarry Smith int SNESNoLineSearchNoNorms(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 22329e0b56fSBarry Smith double fnorm, double *ynorm, double *gnorm,int *flag ) 22429e0b56fSBarry Smith { 22529e0b56fSBarry Smith int ierr; 22629e0b56fSBarry Smith Scalar mone = -1.0; 22729e0b56fSBarry Smith 2283a40ed3dSBarry Smith PetscFunctionBegin; 22929e0b56fSBarry Smith *flag = 0; 23029e0b56fSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 23129e0b56fSBarry Smith ierr = VecAYPX(&mone,x,y); CHKERRQ(ierr); /* y <- y - x */ 23229e0b56fSBarry Smith ierr = SNESComputeFunction(snes,y,g); CHKERRQ(ierr); /* Compute F(y) */ 23329e0b56fSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 2343a40ed3dSBarry Smith PetscFunctionReturn(0); 23529e0b56fSBarry Smith } 23629e0b56fSBarry Smith /* ------------------------------------------------------------------ */ 23729e0b56fSBarry Smith #undef __FUNC__ 2385615d1e5SSatish Balay #define __FUNC__ "SNESCubicLineSearch" 2394b828684SBarry Smith /*@C 240f525115eSLois Curfman McInnes SNESCubicLineSearch - Performs a cubic line search (default line search method). 2415e76c431SBarry Smith 2425e76c431SBarry Smith Input Parameters: 2435e42470aSBarry Smith . snes - nonlinear context 2445e76c431SBarry Smith . x - current iterate 2455e76c431SBarry Smith . f - residual evaluated at x 2465e76c431SBarry Smith . y - search direction (contains new iterate on output) 2475e76c431SBarry Smith . w - work vector 2485e76c431SBarry Smith . fnorm - 2-norm of f 2495e76c431SBarry Smith 250393d2d9aSLois Curfman McInnes Output Parameters: 2515e76c431SBarry Smith . g - residual evaluated at new iterate y 2525e76c431SBarry Smith . y - new iterate (contains search direction on input) 2535e76c431SBarry Smith . gnorm - 2-norm of g 2545e76c431SBarry Smith . ynorm - 2-norm of search length 255761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 2565e76c431SBarry Smith 257*fee21e36SBarry Smith Collective on SNES 258*fee21e36SBarry Smith 259c4a48953SLois Curfman McInnes Options Database Key: 26009d61ba7SLois Curfman McInnes $ -snes_eq_ls cubic 261c4a48953SLois Curfman McInnes 2625e76c431SBarry Smith Notes: 2635e76c431SBarry Smith This line search is taken from "Numerical Methods for Unconstrained 2645e76c431SBarry Smith Optimization and Nonlinear Equations" by Dennis and Schnabel, page 325. 2655e76c431SBarry Smith 26628ae5a21SLois Curfman McInnes .keywords: SNES, nonlinear, line search, cubic 26728ae5a21SLois Curfman McInnes 26877c4ece6SBarry Smith .seealso: SNESNoLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 2695e76c431SBarry Smith @*/ 2705e42470aSBarry Smith int SNESCubicLineSearch(SNES snes,Vec x,Vec f,Vec g,Vec y,Vec w, 271761aaf1bSLois Curfman McInnes double fnorm,double *ynorm,double *gnorm,int *flag) 2725e76c431SBarry Smith { 273406556e6SLois Curfman McInnes /* 274406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 275406556e6SLois Curfman McInnes minimization problem: 276406556e6SLois Curfman McInnes min z(x): R^n -> R, 277406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 278406556e6SLois Curfman McInnes */ 279406556e6SLois Curfman McInnes 280ddd12767SBarry Smith double steptol, initslope, lambdaprev, gnormprev, a, b, d, t1, t2; 281ea4d3ed3SLois Curfman McInnes double maxstep, minlambda, alpha, lambda, lambdatemp, lambdaneg; 2823a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 2835e42470aSBarry Smith Scalar cinitslope, clambda; 2846b5873e3SBarry Smith #endif 2855e42470aSBarry Smith int ierr, count; 2865e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 2875334005bSBarry Smith Scalar mone = -1.0,scale; 2885e76c431SBarry Smith 2893a40ed3dSBarry Smith PetscFunctionBegin; 2907857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 291761aaf1bSLois Curfman McInnes *flag = 0; 2925e76c431SBarry Smith alpha = neP->alpha; 2935e76c431SBarry Smith maxstep = neP->maxstep; 2945e76c431SBarry Smith steptol = neP->steptol; 2955e76c431SBarry Smith 296cddf8d76SBarry Smith ierr = VecNorm(y,NORM_2,ynorm); CHKERRQ(ierr); 297a1c2b6eeSLois Curfman McInnes if (*ynorm < snes->atol) { 298a1c2b6eeSLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Search direction and size are nearly 0\n"); 299a1c2b6eeSLois Curfman McInnes *gnorm = fnorm; 300a1c2b6eeSLois Curfman McInnes ierr = VecCopy(x,y); CHKERRQ(ierr); 301a1c2b6eeSLois Curfman McInnes ierr = VecCopy(f,g); CHKERRQ(ierr); 302ad922ac9SBarry Smith goto theend1; 30394a9d846SBarry Smith } 3045e76c431SBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 3055e42470aSBarry Smith scale = maxstep/(*ynorm); 3063a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 30794a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",real(scale)); 3086b5873e3SBarry Smith #else 30994a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Scaling step by %g\n",scale); 3106b5873e3SBarry Smith #endif 311393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 3125e76c431SBarry Smith *ynorm = maxstep; 3135e76c431SBarry Smith } 3145e76c431SBarry Smith minlambda = steptol/(*ynorm); 315a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 3163a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 317a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 3185e42470aSBarry Smith initslope = real(cinitslope); 3195e42470aSBarry Smith #else 320a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 3215e42470aSBarry Smith #endif 3225e76c431SBarry Smith if (initslope > 0.0) initslope = -initslope; 3235e76c431SBarry Smith if (initslope == 0.0) initslope = -1.0; 3245e76c431SBarry Smith 325393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 3265334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 32778b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 328cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); 329406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 330393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 33194a424c1SBarry Smith PLogInfo(snes,"SNESCubicLineSearch: Using full step\n"); 332ad922ac9SBarry Smith goto theend1; 3335e76c431SBarry Smith } 3345e76c431SBarry Smith 3355e76c431SBarry Smith /* Fit points with quadratic */ 3365e76c431SBarry Smith lambda = 1.0; count = 0; 337a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 3385e76c431SBarry Smith lambdaprev = lambda; 3395e76c431SBarry Smith gnormprev = *gnorm; 340ddd12767SBarry Smith if (lambdatemp <= .1*lambda) lambda = .1*lambda; 341ddd12767SBarry Smith else lambda = lambdatemp; 342393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 343ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3443a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 345ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3465e42470aSBarry Smith #else 347ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3485e42470aSBarry Smith #endif 34978b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 350cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 351406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 352393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 353ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Quadratically determined step, lambda=%g\n",lambda); 354ad922ac9SBarry Smith goto theend1; 3555e76c431SBarry Smith } 3565e76c431SBarry Smith 3575e76c431SBarry Smith /* Fit points with cubic */ 3585e76c431SBarry Smith count = 1; 3595e76c431SBarry Smith while (1) { 3605e76c431SBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 3612b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:Unable to find good step length! %d \n",count); 3622b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 363ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 364393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 365761aaf1bSLois Curfman McInnes *flag = -1; break; 3665e76c431SBarry Smith } 367406556e6SLois Curfman McInnes t1 = ((*gnorm)*(*gnorm) - fnorm*fnorm)*0.5 - lambda*initslope; 368406556e6SLois Curfman McInnes t2 = (gnormprev*gnormprev - fnorm*fnorm)*0.5 - lambdaprev*initslope; 369ddd12767SBarry Smith a = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3702b022350SLois Curfman McInnes b = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev); 3715e76c431SBarry Smith d = b*b - 3*a*initslope; 3725e76c431SBarry Smith if (d < 0.0) d = 0.0; 3735e76c431SBarry Smith if (a == 0.0) { 3745e76c431SBarry Smith lambdatemp = -initslope/(2.0*b); 3755e76c431SBarry Smith } else { 3765e76c431SBarry Smith lambdatemp = (-b + sqrt(d))/(3.0*a); 3775e76c431SBarry Smith } 3785e76c431SBarry Smith if (lambdatemp > .5*lambda) { 3795e76c431SBarry Smith lambdatemp = .5*lambda; 3805e76c431SBarry Smith } 3815e76c431SBarry Smith lambdaprev = lambda; 3825e76c431SBarry Smith gnormprev = *gnorm; 3835e76c431SBarry Smith if (lambdatemp <= .1*lambda) { 3845e76c431SBarry Smith lambda = .1*lambda; 3855e76c431SBarry Smith } 3865e76c431SBarry Smith else lambda = lambdatemp; 387393d2d9aSLois Curfman McInnes ierr = VecCopy( x, w ); CHKERRQ(ierr); 388ea4d3ed3SLois Curfman McInnes lambdaneg = -lambda; 3893a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 390ea4d3ed3SLois Curfman McInnes clambda = lambdaneg; 391393d2d9aSLois Curfman McInnes ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 3925e42470aSBarry Smith #else 393ea4d3ed3SLois Curfman McInnes ierr = VecAXPY(&lambdaneg,y,w); CHKERRQ(ierr); 3945e42470aSBarry Smith #endif 39578b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 396cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 397406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* is reduction enough? */ 398393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 399ea4d3ed3SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubically determined step, lambda=%g\n",lambda); 4002715565aSLois Curfman McInnes goto theend1; 4012b022350SLois Curfman McInnes } else { 4022b022350SLois Curfman McInnes PLogInfo(snes,"SNESCubicLineSearch: Cubic step no good, shrinking lambda, lambda=%g\n",lambda); 4035e76c431SBarry Smith } 4045e76c431SBarry Smith count++; 4055e76c431SBarry Smith } 406ad922ac9SBarry Smith theend1: 4077857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 4083a40ed3dSBarry Smith PetscFunctionReturn(0); 4095e76c431SBarry Smith } 41052392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 4115615d1e5SSatish Balay #undef __FUNC__ 4125615d1e5SSatish Balay #define __FUNC__ "SNESQuadraticLineSearch" 4134b828684SBarry Smith /*@C 414f525115eSLois Curfman McInnes SNESQuadraticLineSearch - Performs a quadratic line search. 4155e76c431SBarry Smith 4165e42470aSBarry Smith Input Parameters: 417f59ffdedSLois Curfman McInnes . snes - the SNES context 4185e42470aSBarry Smith . x - current iterate 4195e42470aSBarry Smith . f - residual evaluated at x 4205e42470aSBarry Smith . y - search direction (contains new iterate on output) 4215e42470aSBarry Smith . w - work vector 4225e42470aSBarry Smith . fnorm - 2-norm of f 4235e42470aSBarry Smith 424c4a48953SLois Curfman McInnes Output Parameters: 4255e42470aSBarry Smith . g - residual evaluated at new iterate y 4265e42470aSBarry Smith . y - new iterate (contains search direction on input) 4275e42470aSBarry Smith . gnorm - 2-norm of g 4285e42470aSBarry Smith . ynorm - 2-norm of search length 429761aaf1bSLois Curfman McInnes . flag - 0 if line search succeeds; -1 on failure. 4305e42470aSBarry Smith 431*fee21e36SBarry Smith Collective on SNES and Vec 432*fee21e36SBarry Smith 433c4a48953SLois Curfman McInnes Options Database Key: 43409d61ba7SLois Curfman McInnes $ -snes_eq_ls quadratic 435c4a48953SLois Curfman McInnes 4365e42470aSBarry Smith Notes: 43777c4ece6SBarry Smith Use SNESSetLineSearch() 438f63b844aSLois Curfman McInnes to set this routine within the SNES_EQ_LS method. 4395e42470aSBarry Smith 440f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, quadratic, line search 441f59ffdedSLois Curfman McInnes 44277c4ece6SBarry Smith .seealso: SNESCubicLineSearch(), SNESNoLineSearch(), SNESSetLineSearch() 4435e42470aSBarry Smith @*/ 4445e42470aSBarry Smith int SNESQuadraticLineSearch(SNES snes, Vec x, Vec f, Vec g, Vec y, Vec w, 445761aaf1bSLois Curfman McInnes double fnorm, double *ynorm, double *gnorm,int *flag) 4465e76c431SBarry Smith { 447406556e6SLois Curfman McInnes /* 448406556e6SLois Curfman McInnes Note that for line search purposes we work with with the related 449406556e6SLois Curfman McInnes minimization problem: 450406556e6SLois Curfman McInnes min z(x): R^n -> R, 451406556e6SLois Curfman McInnes where z(x) = .5 * fnorm*fnorm, and fnorm = || f ||_2. 452406556e6SLois Curfman McInnes */ 45340011551SBarry Smith double steptol,initslope,maxstep,minlambda,alpha,lambda,lambdatemp; 4543a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 4555e42470aSBarry Smith Scalar cinitslope,clambda; 4566b5873e3SBarry Smith #endif 4575e42470aSBarry Smith int ierr,count; 4585e42470aSBarry Smith SNES_LS *neP = (SNES_LS *) snes->data; 4595334005bSBarry Smith Scalar mone = -1.0,scale; 4605e76c431SBarry Smith 4613a40ed3dSBarry Smith PetscFunctionBegin; 4627857610eSBarry Smith PLogEventBegin(SNES_LineSearch,snes,x,f,g); 463761aaf1bSLois Curfman McInnes *flag = 0; 4645e42470aSBarry Smith alpha = neP->alpha; 4655e42470aSBarry Smith maxstep = neP->maxstep; 4665e42470aSBarry Smith steptol = neP->steptol; 4675e76c431SBarry Smith 468cddf8d76SBarry Smith VecNorm(y, NORM_2,ynorm ); 469b37302c6SLois Curfman McInnes if (*ynorm < snes->atol) { 47094a9d846SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Search direction and size is 0\n"); 471b37302c6SLois Curfman McInnes *gnorm = fnorm; 472b37302c6SLois Curfman McInnes ierr = VecCopy(x,y); CHKERRQ(ierr); 473b37302c6SLois Curfman McInnes ierr = VecCopy(f,g); CHKERRQ(ierr); 474ad922ac9SBarry Smith goto theend2; 47594a9d846SBarry Smith } 4765e42470aSBarry Smith if (*ynorm > maxstep) { /* Step too big, so scale back */ 4775e42470aSBarry Smith scale = maxstep/(*ynorm); 478393d2d9aSLois Curfman McInnes ierr = VecScale(&scale,y); CHKERRQ(ierr); 4795e42470aSBarry Smith *ynorm = maxstep; 4805e76c431SBarry Smith } 4815e42470aSBarry Smith minlambda = steptol/(*ynorm); 482a703fe33SLois Curfman McInnes ierr = MatMult(snes->jacobian,y,w); CHKERRQ(ierr); 4833a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 484a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&cinitslope); CHKERRQ(ierr); 4855e42470aSBarry Smith initslope = real(cinitslope); 4865e42470aSBarry Smith #else 487a703fe33SLois Curfman McInnes ierr = VecDot(f,w,&initslope); CHKERRQ(ierr); 4885e42470aSBarry Smith #endif 4895e42470aSBarry Smith if (initslope > 0.0) initslope = -initslope; 4905e42470aSBarry Smith if (initslope == 0.0) initslope = -1.0; 4915e42470aSBarry Smith 492393d2d9aSLois Curfman McInnes ierr = VecCopy(y,w); CHKERRQ(ierr); 4935334005bSBarry Smith ierr = VecAYPX(&mone,x,w); CHKERRQ(ierr); 49478b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 495cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 496406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* Sufficient reduction */ 497393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 49894a424c1SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch: Using full step\n"); 499ad922ac9SBarry Smith goto theend2; 5005e42470aSBarry Smith } 5015e42470aSBarry Smith 5025e42470aSBarry Smith /* Fit points with quadratic */ 5035e42470aSBarry Smith lambda = 1.0; count = 0; 5045e42470aSBarry Smith count = 1; 5055e42470aSBarry Smith while (1) { 5065e42470aSBarry Smith if (lambda <= minlambda) { /* bad luck; use full step */ 507981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:Unable to find good step length! %d \n",count); 508981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n", 509ea4d3ed3SLois Curfman McInnes fnorm,*gnorm,*ynorm,lambda,initslope); 510393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 511761aaf1bSLois Curfman McInnes *flag = -1; break; 5125e42470aSBarry Smith } 513a703fe33SLois Curfman McInnes lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope); 5145e42470aSBarry Smith if (lambdatemp <= .1*lambda) { 5155e42470aSBarry Smith lambda = .1*lambda; 5165e42470aSBarry Smith } else lambda = lambdatemp; 517393d2d9aSLois Curfman McInnes ierr = VecCopy(x,w); CHKERRQ(ierr); 5185334005bSBarry Smith lambda = -lambda; 5193a40ed3dSBarry Smith #if defined(USE_PETSC_COMPLEX) 520393d2d9aSLois Curfman McInnes clambda = lambda; ierr = VecAXPY(&clambda,y,w); CHKERRQ(ierr); 5215e42470aSBarry Smith #else 522393d2d9aSLois Curfman McInnes ierr = VecAXPY(&lambda,y,w); CHKERRQ(ierr); 5235e42470aSBarry Smith #endif 52478b31e54SBarry Smith ierr = SNESComputeFunction(snes,w,g); CHKERRQ(ierr); 525cddf8d76SBarry Smith ierr = VecNorm(g,NORM_2,gnorm); CHKERRQ(ierr); 526406556e6SLois Curfman McInnes if ((*gnorm)*(*gnorm)*0.5 <= fnorm*fnorm*0.5 + alpha*initslope) { /* sufficient reduction */ 527393d2d9aSLois Curfman McInnes ierr = VecCopy(w,y); CHKERRQ(ierr); 528981c4779SBarry Smith PLogInfo(snes,"SNESQuadraticLineSearch:Quadratically determined step, lambda=%g\n",lambda); 52906259719SBarry Smith break; 5305e42470aSBarry Smith } 5315e42470aSBarry Smith count++; 5325e42470aSBarry Smith } 533ad922ac9SBarry Smith theend2: 5347857610eSBarry Smith PLogEventEnd(SNES_LineSearch,snes,x,f,g); 5353a40ed3dSBarry Smith PetscFunctionReturn(0); 5365e76c431SBarry Smith } 53782bf6240SBarry Smith 5385e76c431SBarry Smith /* ------------------------------------------------------------ */ 5395615d1e5SSatish Balay #undef __FUNC__ 540d4bb536fSBarry Smith #define __FUNC__ "SNESSetLineSearch" 541c9e6a524SLois Curfman McInnes /*@C 54277c4ece6SBarry Smith SNESSetLineSearch - Sets the line search routine to be used 543f63b844aSLois Curfman McInnes by the method SNES_EQ_LS. 5445e76c431SBarry Smith 5455e76c431SBarry Smith Input Parameters: 546eafb4bcbSBarry Smith . snes - nonlinear context obtained from SNESCreate() 5475e76c431SBarry Smith . func - pointer to int function 5485e76c431SBarry Smith 549*fee21e36SBarry Smith Collective on SNES 550*fee21e36SBarry Smith 551c4a48953SLois Curfman McInnes Available Routines: 552f59ffdedSLois Curfman McInnes . SNESCubicLineSearch() - default line search 553f59ffdedSLois Curfman McInnes . SNESQuadraticLineSearch() - quadratic line search 554f59ffdedSLois Curfman McInnes . SNESNoLineSearch() - the full Newton step (actually not a line search) 55582bf6240SBarry Smith . SNESNoLineSearchNoNorms() - use the full Newton step (calculate no norms; faster in parallel) 5565e76c431SBarry Smith 557c4a48953SLois Curfman McInnes Options Database Keys: 55809d61ba7SLois Curfman McInnes $ -snes_eq_ls [basic,quadratic,cubic] 559912ebf9aSLois Curfman McInnes $ -snes_eq_ls_alpha <alpha> 560912ebf9aSLois Curfman McInnes $ -snes_eq_ls_maxstep <max> 561912ebf9aSLois Curfman McInnes $ -snes_eq_ls_steptol <steptol> 562c4a48953SLois Curfman McInnes 5635e76c431SBarry Smith Calling sequence of func: 564f59ffdedSLois Curfman McInnes func (SNES snes, Vec x, Vec f, Vec g, Vec y, 565761aaf1bSLois Curfman McInnes Vec w, double fnorm, double *ynorm, 566761aaf1bSLois Curfman McInnes double *gnorm, *flag) 5675e76c431SBarry Smith 5685e76c431SBarry Smith Input parameters for func: 5695e42470aSBarry Smith . snes - nonlinear context 5705e76c431SBarry Smith . x - current iterate 5715e76c431SBarry Smith . f - residual evaluated at x 5725e76c431SBarry Smith . y - search direction (contains new iterate on output) 5735e76c431SBarry Smith . w - work vector 5745e76c431SBarry Smith . fnorm - 2-norm of f 5755e76c431SBarry Smith 5765e76c431SBarry Smith Output parameters for func: 5775e76c431SBarry Smith . g - residual evaluated at new iterate y 5785e76c431SBarry Smith . y - new iterate (contains search direction on input) 5795e76c431SBarry Smith . gnorm - 2-norm of g 5805e76c431SBarry Smith . ynorm - 2-norm of search length 581761aaf1bSLois Curfman McInnes . flag - set to 0 if the line search succeeds; a nonzero integer 582761aaf1bSLois Curfman McInnes on failure. 583f59ffdedSLois Curfman McInnes 584f59ffdedSLois Curfman McInnes .keywords: SNES, nonlinear, set, line search, routine 585f59ffdedSLois Curfman McInnes 586f59ffdedSLois Curfman McInnes .seealso: SNESNoLineSearch(), SNESQuadraticLineSearch(), SNESCubicLineSearch() 5875e76c431SBarry Smith @*/ 58877c4ece6SBarry Smith int SNESSetLineSearch(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 589761aaf1bSLois Curfman McInnes double,double*,double*,int*)) 5905e76c431SBarry Smith { 59182bf6240SBarry Smith int ierr, (*f)(SNES,int (*f)(SNES,Vec,Vec,Vec,Vec,Vec,double,double*,double*,int*)); 59282bf6240SBarry Smith 5933a40ed3dSBarry Smith PetscFunctionBegin; 594e1311b90SBarry Smith ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESSetLineSearch",(void **)&f);CHKERRQ(ierr); 59582bf6240SBarry Smith if (f) { 59682bf6240SBarry Smith ierr = (*f)(snes,func);CHKERRQ(ierr); 59782bf6240SBarry Smith } 5983a40ed3dSBarry Smith PetscFunctionReturn(0); 5995e76c431SBarry Smith } 60082bf6240SBarry Smith 60182bf6240SBarry Smith #undef __FUNC__ 60282bf6240SBarry Smith #define __FUNC__ "SNESSetLineSearch_LS" 60382bf6240SBarry Smith int SNESSetLineSearch_LS(SNES snes,int (*func)(SNES,Vec,Vec,Vec,Vec,Vec, 60482bf6240SBarry Smith double,double*,double*,int*)) 60582bf6240SBarry Smith { 60682bf6240SBarry Smith PetscFunctionBegin; 60782bf6240SBarry Smith ((SNES_LS *)(snes->data))->LineSearch = func; 60882bf6240SBarry Smith PetscFunctionReturn(0); 60982bf6240SBarry Smith } 61082bf6240SBarry Smith 61152392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6125615d1e5SSatish Balay #undef __FUNC__ 613d4bb536fSBarry Smith #define __FUNC__ "SNESPrintHelp_EQ_LS" 614f63b844aSLois Curfman McInnes static int SNESPrintHelp_EQ_LS(SNES snes,char *p) 6155e42470aSBarry Smith { 6165e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6176daaf66cSBarry Smith 6183a40ed3dSBarry Smith PetscFunctionBegin; 61976be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," method SNES_EQ_LS (ls) for systems of nonlinear equations:\n"); 62076be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls [basic,quadratic,cubic]\n",p); 62176be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_alpha <alpha> (default %g)\n",p,ls->alpha); 62276be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_maxstep <max> (default %g)\n",p,ls->maxstep); 62376be9ce4SBarry Smith (*PetscHelpPrintf)(snes->comm," %ssnes_eq_ls_steptol <tol> (default %g)\n",p,ls->steptol); 6243a40ed3dSBarry Smith PetscFunctionReturn(0); 6255e42470aSBarry Smith } 62652392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6275615d1e5SSatish Balay #undef __FUNC__ 628d4bb536fSBarry Smith #define __FUNC__ "SNESView_EQ_LS" 629e1311b90SBarry Smith static int SNESView_EQ_LS(SNES snes,Viewer viewer) 630a935fc98SLois Curfman McInnes { 631a935fc98SLois Curfman McInnes SNES_LS *ls = (SNES_LS *)snes->data; 632d636dbe3SBarry Smith FILE *fd; 63319bcc07fSBarry Smith char *cstr; 63451695f54SLois Curfman McInnes int ierr; 63519bcc07fSBarry Smith ViewerType vtype; 636a935fc98SLois Curfman McInnes 6373a40ed3dSBarry Smith PetscFunctionBegin; 63819bcc07fSBarry Smith ierr = ViewerGetType(viewer,&vtype); CHKERRQ(ierr); 63919bcc07fSBarry Smith if (vtype == ASCII_FILE_VIEWER || vtype == ASCII_FILES_VIEWER) { 64090ace30eSBarry Smith ierr = ViewerASCIIGetPointer(viewer,&fd); CHKERRQ(ierr); 64119bcc07fSBarry Smith if (ls->LineSearch == SNESNoLineSearch) cstr = "SNESNoLineSearch"; 64219bcc07fSBarry Smith else if (ls->LineSearch == SNESQuadraticLineSearch) cstr = "SNESQuadraticLineSearch"; 64319bcc07fSBarry Smith else if (ls->LineSearch == SNESCubicLineSearch) cstr = "SNESCubicLineSearch"; 64419bcc07fSBarry Smith else cstr = "unknown"; 64577c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," line search variant: %s\n",cstr); 64677c4ece6SBarry Smith PetscFPrintf(snes->comm,fd," alpha=%g, maxstep=%g, steptol=%g\n", 647a935fc98SLois Curfman McInnes ls->alpha,ls->maxstep,ls->steptol); 6485cd90555SBarry Smith } else { 6495cd90555SBarry Smith SETERRQ(1,1,"Viewer type not supported for this object"); 65019bcc07fSBarry Smith } 6513a40ed3dSBarry Smith PetscFunctionReturn(0); 652a935fc98SLois Curfman McInnes } 65352392280SLois Curfman McInnes /* ------------------------------------------------------------------ */ 6545615d1e5SSatish Balay #undef __FUNC__ 6555615d1e5SSatish Balay #define __FUNC__ "SNESSetFromOptions_EQ_LS" 656f63b844aSLois Curfman McInnes static int SNESSetFromOptions_EQ_LS(SNES snes) 6575e42470aSBarry Smith { 6585e42470aSBarry Smith SNES_LS *ls = (SNES_LS *)snes->data; 6595e42470aSBarry Smith char ver[16]; 6605e42470aSBarry Smith double tmp; 66125cdf11fSBarry Smith int ierr,flg; 6625e42470aSBarry Smith 6633a40ed3dSBarry Smith PetscFunctionBegin; 66409d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_alpha",&tmp, &flg);CHKERRQ(ierr); 66525cdf11fSBarry Smith if (flg) { 6665e42470aSBarry Smith ls->alpha = tmp; 6675e42470aSBarry Smith } 66809d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_maxstep",&tmp, &flg);CHKERRQ(ierr); 66925cdf11fSBarry Smith if (flg) { 6705e42470aSBarry Smith ls->maxstep = tmp; 6715e42470aSBarry Smith } 67209d61ba7SLois Curfman McInnes ierr = OptionsGetDouble(snes->prefix,"-snes_eq_ls_steptol",&tmp, &flg);CHKERRQ(ierr); 67325cdf11fSBarry Smith if (flg) { 6745e42470aSBarry Smith ls->steptol = tmp; 6755e42470aSBarry Smith } 67609d61ba7SLois Curfman McInnes ierr = OptionsGetString(snes->prefix,"-snes_eq_ls",ver,16, &flg); CHKERRQ(ierr); 67725cdf11fSBarry Smith if (flg) { 67848d91487SBarry Smith if (!PetscStrcmp(ver,"basic")) { 67977c4ece6SBarry Smith SNESSetLineSearch(snes,SNESNoLineSearch); 6805e42470aSBarry Smith } 68129e0b56fSBarry Smith else if (!PetscStrcmp(ver,"basicnonorms")) { 68229e0b56fSBarry Smith SNESSetLineSearch(snes,SNESNoLineSearchNoNorms); 68329e0b56fSBarry Smith } 68448d91487SBarry Smith else if (!PetscStrcmp(ver,"quadratic")) { 68577c4ece6SBarry Smith SNESSetLineSearch(snes,SNESQuadraticLineSearch); 6865e42470aSBarry Smith } 68748d91487SBarry Smith else if (!PetscStrcmp(ver,"cubic")) { 68877c4ece6SBarry Smith SNESSetLineSearch(snes,SNESCubicLineSearch); 6895e42470aSBarry Smith } 690a8c6a408SBarry Smith else {SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,0,"Unknown line search");} 6915e42470aSBarry Smith } 6923a40ed3dSBarry Smith PetscFunctionReturn(0); 6935e42470aSBarry Smith } 6945e42470aSBarry Smith /* ------------------------------------------------------------ */ 6955615d1e5SSatish Balay #undef __FUNC__ 6965615d1e5SSatish Balay #define __FUNC__ "SNESCreate_EQ_LS" 697f63b844aSLois Curfman McInnes int SNESCreate_EQ_LS(SNES snes ) 6985e42470aSBarry Smith { 69982bf6240SBarry Smith int ierr; 7005e42470aSBarry Smith SNES_LS *neP; 7015e42470aSBarry Smith 7023a40ed3dSBarry Smith PetscFunctionBegin; 703a8c6a408SBarry Smith if (snes->method_class != SNES_NONLINEAR_EQUATIONS) { 704a8c6a408SBarry Smith SETERRQ(PETSC_ERR_ARG_WRONG,0,"For SNES_NONLINEAR_EQUATIONS only"); 705a8c6a408SBarry Smith } 70682bf6240SBarry Smith 707f63b844aSLois Curfman McInnes snes->setup = SNESSetUp_EQ_LS; 708f63b844aSLois Curfman McInnes snes->solve = SNESSolve_EQ_LS; 709f63b844aSLois Curfman McInnes snes->destroy = SNESDestroy_EQ_LS; 710f63b844aSLois Curfman McInnes snes->converged = SNESConverged_EQ_LS; 711f63b844aSLois Curfman McInnes snes->printhelp = SNESPrintHelp_EQ_LS; 712f63b844aSLois Curfman McInnes snes->setfromoptions = SNESSetFromOptions_EQ_LS; 713f63b844aSLois Curfman McInnes snes->view = SNESView_EQ_LS; 7145baf8537SBarry Smith snes->nwork = 0; 7155e42470aSBarry Smith 7160452661fSBarry Smith neP = PetscNew(SNES_LS); CHKPTRQ(neP); 717ff782a9fSLois Curfman McInnes PLogObjectMemory(snes,sizeof(SNES_LS)); 7185e42470aSBarry Smith snes->data = (void *) neP; 7195e42470aSBarry Smith neP->alpha = 1.e-4; 7205e42470aSBarry Smith neP->maxstep = 1.e8; 7215e42470aSBarry Smith neP->steptol = 1.e-12; 7225e42470aSBarry Smith neP->LineSearch = SNESCubicLineSearch; 72382bf6240SBarry Smith 724e1311b90SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESSetLineSearch","SNESSetLineSearch_LS", 725e1311b90SBarry Smith (void*)SNESSetLineSearch_LS);CHKERRQ(ierr); 72682bf6240SBarry Smith 7273a40ed3dSBarry Smith PetscFunctionReturn(0); 7285e42470aSBarry Smith } 7295e42470aSBarry Smith 73082bf6240SBarry Smith 73182bf6240SBarry Smith 73282bf6240SBarry Smith 733