1af0996ceSBarry Smith #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 21e25c274SJed Brown #include <petscdm.h> 3d0af7cd3SBarry Smith 4d0af7cd3SBarry Smith #undef __FUNCT__ 52176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds" 62176524cSBarry Smith /*@C 72176524cSBarry Smith SNESVISetComputeVariableBounds - Sets a function that is called to compute the variable bounds 82176524cSBarry Smith 92176524cSBarry Smith Input parameter 102176524cSBarry Smith + snes - the SNES context 112176524cSBarry Smith - compute - computes the bounds 122176524cSBarry Smith 132bd2b0e6SSatish Balay Level: advanced 142176524cSBarry Smith 15c1c3a0ecSBarry Smith .seealso: SNESVISetVariableBounds() 16c1c3a0ecSBarry Smith 17aab9d709SJed Brown @*/ 1877cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec)) 192176524cSBarry Smith { 2061589011SJed Brown PetscErrorCode ierr,(*f)(SNES,PetscErrorCode (*)(SNES,Vec,Vec)); 212176524cSBarry Smith 222176524cSBarry Smith PetscFunctionBegin; 2361589011SJed Brown PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 240005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetComputeVariableBounds_C",&f);CHKERRQ(ierr); 2563cdc2bdSPatrick Farrell if (!f) { 2663cdc2bdSPatrick Farrell ierr = SNESVISetComputeVariableBounds_VI(snes,compute);CHKERRQ(ierr); 2763cdc2bdSPatrick Farrell } else { 2861589011SJed Brown ierr = PetscUseMethod(snes,"SNESVISetComputeVariableBounds_C",(SNES,PetscErrorCode (*)(SNES,Vec,Vec)),(snes,compute));CHKERRQ(ierr); 2963cdc2bdSPatrick Farrell } 302176524cSBarry Smith PetscFunctionReturn(0); 312176524cSBarry Smith } 322176524cSBarry Smith 3361589011SJed Brown #undef __FUNCT__ 3461589011SJed Brown #define __FUNCT__ "SNESVISetComputeVariableBounds_VI" 3561589011SJed Brown PetscErrorCode SNESVISetComputeVariableBounds_VI(SNES snes,SNESVIComputeVariableBoundsFunction compute) 3661589011SJed Brown { 3761589011SJed Brown PetscFunctionBegin; 3861589011SJed Brown snes->ops->computevariablebounds = compute; 3961589011SJed Brown PetscFunctionReturn(0); 4061589011SJed Brown } 412176524cSBarry Smith 423c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/ 432b4ed282SShri Abhyankar 449308c137SBarry Smith #undef __FUNCT__ 45ffdf2a20SBarry Smith #define __FUNCT__ "SNESVIMonitorResidual" 46ffdf2a20SBarry Smith PetscErrorCode SNESVIMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 47ffdf2a20SBarry Smith { 48ffdf2a20SBarry Smith PetscErrorCode ierr; 49ffdf2a20SBarry Smith Vec X, F, Finactive; 50ffdf2a20SBarry Smith IS isactive; 51ffdf2a20SBarry Smith PetscViewer viewer = (PetscViewer) dummy; 52ffdf2a20SBarry Smith 53ffdf2a20SBarry Smith PetscFunctionBegin; 54ffdf2a20SBarry Smith ierr = SNESGetFunction(snes,&F,0,0);CHKERRQ(ierr); 55ffdf2a20SBarry Smith ierr = SNESGetSolution(snes,&X);CHKERRQ(ierr); 5687e98922SBarry Smith ierr = SNESVIGetActiveSetIS(snes,X,F,&isactive);CHKERRQ(ierr); 57ffdf2a20SBarry Smith ierr = VecDuplicate(F,&Finactive);CHKERRQ(ierr); 58ffdf2a20SBarry Smith ierr = VecCopy(F,Finactive);CHKERRQ(ierr); 5987e98922SBarry Smith ierr = VecISSet(Finactive,isactive,0.0);CHKERRQ(ierr); 60de34d3e9SBarry Smith ierr = ISDestroy(&isactive);CHKERRQ(ierr); 61ffdf2a20SBarry Smith if (!viewer) { 62ffdf2a20SBarry Smith viewer = PETSC_VIEWER_DRAW_(PetscObjectComm((PetscObject)snes)); 63ffdf2a20SBarry Smith } 6487e98922SBarry Smith ierr = VecView(Finactive,viewer);CHKERRQ(ierr); 65ffdf2a20SBarry Smith ierr = VecDestroy(&Finactive);CHKERRQ(ierr); 66ffdf2a20SBarry Smith PetscFunctionReturn(0); 67ffdf2a20SBarry Smith } 68ffdf2a20SBarry Smith 69ffdf2a20SBarry Smith #undef __FUNCT__ 709308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 717087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 729308c137SBarry Smith { 739308c137SBarry Smith PetscErrorCode ierr; 74ce94432eSBarry Smith PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 759308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 766fd67740SBarry Smith PetscInt i,n,act[2] = {0,0},fact[2],N; 776a9e2d46SJungho Lee /* Number of components that actually hit the bounds (c.f. active variables) */ 786a9e2d46SJungho Lee PetscInt act_bound[2] = {0,0},fact_bound[2]; 79*349187a7SBarry Smith PetscReal rnorm,fnorm,zerotolerance = snes->vizerotolerance; 809d1809e2SSatish Balay double tmp; 819308c137SBarry Smith 829308c137SBarry Smith PetscFunctionBegin; 839308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 846fd67740SBarry Smith ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); 85c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 86c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 879308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 883f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 899308c137SBarry Smith 909308c137SBarry Smith rnorm = 0.0; 919308c137SBarry Smith for (i=0; i<n; i++) { 92*349187a7SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + zerotolerance || (PetscRealPart(f[i]) <= 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - zerotolerance) || PetscRealPart(f[i]) >= 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 93*349187a7SBarry Smith else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + zerotolerance && PetscRealPart(f[i]) > 0.0) act[0]++; 94*349187a7SBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - zerotolerance && PetscRealPart(f[i]) < 0.0) act[1]++; 95ce94432eSBarry Smith else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Can never get here"); 969308c137SBarry Smith } 976a9e2d46SJungho Lee 986a9e2d46SJungho Lee for (i=0; i<n; i++) { 99*349187a7SBarry Smith if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + zerotolerance) act_bound[0]++; 100*349187a7SBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - zerotolerance) act_bound[1]++; 1016a9e2d46SJungho Lee } 1023f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 103c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 104c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 1059308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 106ce94432eSBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 107ce94432eSBarry Smith ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 108ce94432eSBarry Smith ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 109f137e44dSBarry Smith fnorm = PetscSqrtReal(fnorm); 1106fd67740SBarry Smith 111649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1129d1809e2SSatish Balay if (snes->ntruebounds) tmp = ((double)(fact[0]+fact[1]))/((double)snes->ntruebounds); 1139d1809e2SSatish Balay else tmp = 0.0; 1149d1809e2SSatish Balay ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active lower constraints %D/%D upper constraints %D/%D Percent of total %g Percent of bounded %g\n",its,(double)fnorm,fact[0],fact_bound[0],fact[1],fact_bound[1],((double)(fact[0]+fact[1]))/((double)N),tmp);CHKERRQ(ierr); 1156a9e2d46SJungho Lee 116649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1179308c137SBarry Smith PetscFunctionReturn(0); 1189308c137SBarry Smith } 1199308c137SBarry Smith 1202b4ed282SShri Abhyankar /* 1212b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 1222b4ed282SShri Abhyankar || F(u) ||_2 but not a zero, F(u) = 0. In the case when one cannot compute J^T F we use the fact that 1232b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 1242b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 1252b4ed282SShri Abhyankar */ 1262b4ed282SShri Abhyankar #undef __FUNCT__ 1272b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 128ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 1292b4ed282SShri Abhyankar { 1302b4ed282SShri Abhyankar PetscReal a1; 1312b4ed282SShri Abhyankar PetscErrorCode ierr; 132ace3abfcSBarry Smith PetscBool hastranspose; 1332b4ed282SShri Abhyankar 1342b4ed282SShri Abhyankar PetscFunctionBegin; 1352b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 1362b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 1372b4ed282SShri Abhyankar if (hastranspose) { 1382b4ed282SShri Abhyankar /* Compute || J^T F|| */ 1392b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 1402b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 1414839bfe8SBarry Smith ierr = PetscInfo1(snes,"|| J^T F|| %g near zero implies found a local minimum\n",(double)(a1/fnorm));CHKERRQ(ierr); 1422b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 1432b4ed282SShri Abhyankar } else { 1442b4ed282SShri Abhyankar Vec work; 1452b4ed282SShri Abhyankar PetscScalar result; 1462b4ed282SShri Abhyankar PetscReal wnorm; 1472b4ed282SShri Abhyankar 1480298fd71SBarry Smith ierr = VecSetRandom(W,NULL);CHKERRQ(ierr); 1492b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 1502b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 1512b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 1522b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 1536bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 1542b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 1554839bfe8SBarry Smith ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %g near zero implies found a local minimum\n",(double)a1);CHKERRQ(ierr); 1562b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 1572b4ed282SShri Abhyankar } 1582b4ed282SShri Abhyankar PetscFunctionReturn(0); 1592b4ed282SShri Abhyankar } 1602b4ed282SShri Abhyankar 1612b4ed282SShri Abhyankar /* 1622b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 1632b4ed282SShri Abhyankar */ 1642b4ed282SShri Abhyankar #undef __FUNCT__ 1652b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 1662b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 1672b4ed282SShri Abhyankar { 1682b4ed282SShri Abhyankar PetscReal a1,a2; 1692b4ed282SShri Abhyankar PetscErrorCode ierr; 170ace3abfcSBarry Smith PetscBool hastranspose; 1712b4ed282SShri Abhyankar 1722b4ed282SShri Abhyankar PetscFunctionBegin; 1732b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 1742b4ed282SShri Abhyankar if (hastranspose) { 1752b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 1762b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 1772b4ed282SShri Abhyankar 1782b4ed282SShri Abhyankar /* Compute || J^T W|| */ 1792b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 1802b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 1812b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 1822b4ed282SShri Abhyankar if (a1 != 0.0) { 1834839bfe8SBarry Smith ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %g near zero implies inconsistent rhs\n",(double)(a2/a1));CHKERRQ(ierr); 1842b4ed282SShri Abhyankar } 1852b4ed282SShri Abhyankar } 1862b4ed282SShri Abhyankar PetscFunctionReturn(0); 1872b4ed282SShri Abhyankar } 1882b4ed282SShri Abhyankar 1892b4ed282SShri Abhyankar /* 1908d359177SBarry Smith SNESConvergedDefault_VI - Checks the convergence of the semismooth newton algorithm. 1912b4ed282SShri Abhyankar 1922b4ed282SShri Abhyankar Notes: 1932b4ed282SShri Abhyankar The convergence criterion currently implemented is 1942b4ed282SShri Abhyankar merit < abstol 1952b4ed282SShri Abhyankar merit < rtol*merit_initial 1962b4ed282SShri Abhyankar */ 1972b4ed282SShri Abhyankar #undef __FUNCT__ 1988d359177SBarry Smith #define __FUNCT__ "SNESConvergedDefault_VI" 1998d359177SBarry Smith PetscErrorCode SNESConvergedDefault_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 2002b4ed282SShri Abhyankar { 2012b4ed282SShri Abhyankar PetscErrorCode ierr; 2022b4ed282SShri Abhyankar 2032b4ed282SShri Abhyankar PetscFunctionBegin; 2042b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2052b4ed282SShri Abhyankar PetscValidPointer(reason,6); 2062b4ed282SShri Abhyankar 2072b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 2082b4ed282SShri Abhyankar 2092b4ed282SShri Abhyankar if (!it) { 2102b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 2117fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 2122b4ed282SShri Abhyankar } 2137fe79bc4SShri Abhyankar if (fnorm != fnorm) { 2142b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 2152b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 2167fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 2174839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 2182b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 2192b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 2202b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 2212b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 2222b4ed282SShri Abhyankar } 2232b4ed282SShri Abhyankar 2242b4ed282SShri Abhyankar if (it && !*reason) { 2257fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 2264839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 2272b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 2282b4ed282SShri Abhyankar } 2292b4ed282SShri Abhyankar } 2302b4ed282SShri Abhyankar PetscFunctionReturn(0); 2312b4ed282SShri Abhyankar } 2322b4ed282SShri Abhyankar 233ee657d29SShri Abhyankar 234c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 235c1a5e521SShri Abhyankar /* 236c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 237c1a5e521SShri Abhyankar 238c1a5e521SShri Abhyankar Input Parameters: 239c1a5e521SShri Abhyankar . SNES - nonlinear solver context 240c1a5e521SShri Abhyankar 241c1a5e521SShri Abhyankar Output Parameters: 242c1a5e521SShri Abhyankar . X - Bound projected X 243c1a5e521SShri Abhyankar 244c1a5e521SShri Abhyankar */ 245c1a5e521SShri Abhyankar 246c1a5e521SShri Abhyankar #undef __FUNCT__ 247c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 248c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 249c1a5e521SShri Abhyankar { 250c1a5e521SShri Abhyankar PetscErrorCode ierr; 251c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 252c1a5e521SShri Abhyankar PetscScalar *x; 253c1a5e521SShri Abhyankar PetscInt i,n; 254c1a5e521SShri Abhyankar 255c1a5e521SShri Abhyankar PetscFunctionBegin; 256c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 257c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 258c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 259c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 260c1a5e521SShri Abhyankar 261c1a5e521SShri Abhyankar for (i = 0; i<n; i++) { 26210f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 26310f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 264c1a5e521SShri Abhyankar } 265c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 266c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 267c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 268c1a5e521SShri Abhyankar PetscFunctionReturn(0); 269c1a5e521SShri Abhyankar } 270c1a5e521SShri Abhyankar 27169c03620SShri Abhyankar 27269c03620SShri Abhyankar #undef __FUNCT__ 273693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 274693ddf92SShri Abhyankar /* 275693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 276693ddf92SShri Abhyankar 277693ddf92SShri Abhyankar Input parameter 278693ddf92SShri Abhyankar . snes - the SNES context 279693ddf92SShri Abhyankar . X - the snes solution vector 280693ddf92SShri Abhyankar . F - the nonlinear function vector 281693ddf92SShri Abhyankar 282693ddf92SShri Abhyankar Output parameter 283693ddf92SShri Abhyankar . ISact - active set index set 284693ddf92SShri Abhyankar */ 285693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS *ISact) 286d950fb63SShri Abhyankar { 287d950fb63SShri Abhyankar PetscErrorCode ierr; 288c2fc9fa9SBarry Smith Vec Xl=snes->xl,Xu=snes->xu; 289693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 290693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 291*349187a7SBarry Smith PetscReal zerotolerance = snes->vizerotolerance; 292d950fb63SShri Abhyankar 293d950fb63SShri Abhyankar PetscFunctionBegin; 294d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 295d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 296fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 297fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 298fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 299fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 300693ddf92SShri Abhyankar /* Compute active set size */ 301d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 302*349187a7SBarry Smith if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + zerotolerance || (PetscRealPart(f[i]) <= 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - zerotolerance) || PetscRealPart(f[i]) >= 0.0))) nloc_isact++; 303d950fb63SShri Abhyankar } 304693ddf92SShri Abhyankar 305785e854fSJed Brown ierr = PetscMalloc1(nloc_isact,&idx_act);CHKERRQ(ierr); 306d950fb63SShri Abhyankar 307693ddf92SShri Abhyankar /* Set active set indices */ 308d950fb63SShri Abhyankar for (i=0; i < nlocal; i++) { 309*349187a7SBarry Smith if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + zerotolerance || (PetscRealPart(f[i]) <= 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - zerotolerance) || PetscRealPart(f[i]) >= 0.0))) idx_act[i1++] = ilow+i; 310d950fb63SShri Abhyankar } 311d950fb63SShri Abhyankar 312693ddf92SShri Abhyankar /* Create active set IS */ 313ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 314d950fb63SShri Abhyankar 315fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 316fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 317fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 318fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 319d950fb63SShri Abhyankar PetscFunctionReturn(0); 320d950fb63SShri Abhyankar } 321d950fb63SShri Abhyankar 322693ddf92SShri Abhyankar #undef __FUNCT__ 323693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 324693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS *ISact,IS *ISinact) 325693ddf92SShri Abhyankar { 326693ddf92SShri Abhyankar PetscErrorCode ierr; 327077aedafSJed Brown PetscInt rstart,rend; 328693ddf92SShri Abhyankar 329693ddf92SShri Abhyankar PetscFunctionBegin; 330693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 331077aedafSJed Brown ierr = VecGetOwnershipRange(X,&rstart,&rend);CHKERRQ(ierr); 332077aedafSJed Brown ierr = ISComplement(*ISact,rstart,rend,ISinact);CHKERRQ(ierr); 333693ddf92SShri Abhyankar PetscFunctionReturn(0); 334693ddf92SShri Abhyankar } 335693ddf92SShri Abhyankar 336fe835674SShri Abhyankar #undef __FUNCT__ 337fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 33810f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X, PetscReal *fnorm) 339fe835674SShri Abhyankar { 340fe835674SShri Abhyankar PetscErrorCode ierr; 341fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 342fe835674SShri Abhyankar PetscInt i,n; 343*349187a7SBarry Smith PetscReal rnorm,zerotolerance = snes->vizerotolerance;; 344fe835674SShri Abhyankar 345fe835674SShri Abhyankar PetscFunctionBegin; 346fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 347c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 348c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 349fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 350fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 351fe835674SShri Abhyankar rnorm = 0.0; 352fe835674SShri Abhyankar for (i=0; i<n; i++) { 353*349187a7SBarry Smith if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + zerotolerance || (PetscRealPart(f[i]) <= 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - zerotolerance) || PetscRealPart(f[i]) >= 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]); 3548f918527SKarl Rupp } 355fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 356c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 357c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 358fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 359ce94432eSBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 36062d1f40fSBarry Smith *fnorm = PetscSqrtReal(*fnorm); 361fe835674SShri Abhyankar PetscFunctionReturn(0); 362fe835674SShri Abhyankar } 363fe835674SShri Abhyankar 36408da532bSDmitry Karpeev #undef __FUNCT__ 36508da532bSDmitry Karpeev #define __FUNCT__ "SNESVIDMComputeVariableBounds" 36608da532bSDmitry Karpeev PetscErrorCode SNESVIDMComputeVariableBounds(SNES snes,Vec xl, Vec xu) 36708da532bSDmitry Karpeev { 36808da532bSDmitry Karpeev PetscErrorCode ierr; 3696e111a19SKarl Rupp 37008da532bSDmitry Karpeev PetscFunctionBegin; 37108da532bSDmitry Karpeev ierr = DMComputeVariableBounds(snes->dm, xl, xu);CHKERRQ(ierr); 37208da532bSDmitry Karpeev PetscFunctionReturn(0); 37308da532bSDmitry Karpeev } 37408da532bSDmitry Karpeev 3752f63a38cSShri Abhyankar 3762b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 3772b4ed282SShri Abhyankar /* 378c2fc9fa9SBarry Smith SNESSetUp_VI - Does setup common to all VI solvers -- basically makes sure bounds have been properly set up 3792b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 3802b4ed282SShri Abhyankar 3812b4ed282SShri Abhyankar Input Parameter: 3822b4ed282SShri Abhyankar . snes - the SNES context 3832b4ed282SShri Abhyankar 3842b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 3852b4ed282SShri Abhyankar 3862b4ed282SShri Abhyankar Notes: 3872b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 3882b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 3892b4ed282SShri Abhyankar the call to SNESSolve(). 3902b4ed282SShri Abhyankar */ 3912b4ed282SShri Abhyankar #undef __FUNCT__ 3922b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 3932b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 3942b4ed282SShri Abhyankar { 3952b4ed282SShri Abhyankar PetscErrorCode ierr; 3962b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 3972b4ed282SShri Abhyankar 3982b4ed282SShri Abhyankar PetscFunctionBegin; 399fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,1);CHKERRQ(ierr); 4006cab3a1bSJed Brown ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 4012b4ed282SShri Abhyankar 40208da532bSDmitry Karpeev if (!snes->ops->computevariablebounds && snes->dm) { 403a201590fSDmitry Karpeev PetscBool flag; 404a201590fSDmitry Karpeev ierr = DMHasVariableBounds(snes->dm, &flag);CHKERRQ(ierr); 4051aa26658SKarl Rupp 40608da532bSDmitry Karpeev snes->ops->computevariablebounds = SNESVIDMComputeVariableBounds; 40708da532bSDmitry Karpeev } 408a201590fSDmitry Karpeev if (!snes->usersetbounds) { 409c2fc9fa9SBarry Smith if (snes->ops->computevariablebounds) { 410c2fc9fa9SBarry Smith if (!snes->xl) {ierr = VecDuplicate(snes->vec_sol,&snes->xl);CHKERRQ(ierr);} 411c2fc9fa9SBarry Smith if (!snes->xu) {ierr = VecDuplicate(snes->vec_sol,&snes->xu);CHKERRQ(ierr);} 412c2fc9fa9SBarry Smith ierr = (*snes->ops->computevariablebounds)(snes,snes->xl,snes->xu);CHKERRQ(ierr); 4131aa26658SKarl Rupp } else if (!snes->xl && !snes->xu) { 4142176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 415c2fc9fa9SBarry Smith ierr = VecDuplicate(snes->vec_sol, &snes->xl);CHKERRQ(ierr); 416e270355aSBarry Smith ierr = VecSet(snes->xl,PETSC_NINFINITY);CHKERRQ(ierr); 417c2fc9fa9SBarry Smith ierr = VecDuplicate(snes->vec_sol, &snes->xu);CHKERRQ(ierr); 418e270355aSBarry Smith ierr = VecSet(snes->xu,PETSC_INFINITY);CHKERRQ(ierr); 4192b4ed282SShri Abhyankar } else { 4202b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 4212b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 422c2fc9fa9SBarry Smith ierr = VecGetOwnershipRange(snes->xl,i_start+1,i_end+1);CHKERRQ(ierr); 423c2fc9fa9SBarry Smith ierr = VecGetOwnershipRange(snes->xu,i_start+2,i_end+2);CHKERRQ(ierr); 4242b4ed282SShri Abhyankar if ((i_start[0] != i_start[1]) || (i_start[0] != i_start[2]) || (i_end[0] != i_end[1]) || (i_end[0] != i_end[2])) 4252b4ed282SShri Abhyankar SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Distribution of lower bound, upper bound and the solution vector should be identical across all the processors."); 4262b4ed282SShri Abhyankar } 427a201590fSDmitry Karpeev } 4282b4ed282SShri Abhyankar PetscFunctionReturn(0); 4292b4ed282SShri Abhyankar } 4302b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 4312176524cSBarry Smith #undef __FUNCT__ 4322176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 4332176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 4342176524cSBarry Smith { 4352176524cSBarry Smith PetscErrorCode ierr; 4362176524cSBarry Smith 4372176524cSBarry Smith PetscFunctionBegin; 438c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xl);CHKERRQ(ierr); 439c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xu);CHKERRQ(ierr); 4402d6615e8SDmitry Karpeev snes->usersetbounds = PETSC_FALSE; 4412176524cSBarry Smith PetscFunctionReturn(0); 4422176524cSBarry Smith } 4432176524cSBarry Smith 4442b4ed282SShri Abhyankar /* 4452b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 4462b4ed282SShri Abhyankar with SNESCreate_VI(). 4472b4ed282SShri Abhyankar 4482b4ed282SShri Abhyankar Input Parameter: 4492b4ed282SShri Abhyankar . snes - the SNES context 4502b4ed282SShri Abhyankar 4512b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 4522b4ed282SShri Abhyankar */ 4532b4ed282SShri Abhyankar #undef __FUNCT__ 4542b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 4552b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 4562b4ed282SShri Abhyankar { 4572b4ed282SShri Abhyankar PetscErrorCode ierr; 4582b4ed282SShri Abhyankar 4592b4ed282SShri Abhyankar PetscFunctionBegin; 4602b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 4612b4ed282SShri Abhyankar 4622b4ed282SShri Abhyankar /* clear composed functions */ 463bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSet_C",NULL);CHKERRQ(ierr); 464bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSetMonitor_C",NULL);CHKERRQ(ierr); 4652b4ed282SShri Abhyankar PetscFunctionReturn(0); 4662b4ed282SShri Abhyankar } 4677fe79bc4SShri Abhyankar 4685559b345SBarry Smith #undef __FUNCT__ 4695559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 4705559b345SBarry Smith /*@ 4712b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 4722b4ed282SShri Abhyankar 4732b4ed282SShri Abhyankar Input Parameters: 4742b4ed282SShri Abhyankar . snes - the SNES context. 4752b4ed282SShri Abhyankar . xl - lower bound. 4762b4ed282SShri Abhyankar . xu - upper bound. 4772b4ed282SShri Abhyankar 4782b4ed282SShri Abhyankar Notes: 4792b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 48029eed3a4SBarry Smith PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp(). 48184c105d7SBarry Smith 4822bd2b0e6SSatish Balay Level: advanced 4832bd2b0e6SSatish Balay 4845559b345SBarry Smith @*/ 48569c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 4862b4ed282SShri Abhyankar { 48761589011SJed Brown PetscErrorCode ierr,(*f)(SNES,Vec,Vec); 4882b4ed282SShri Abhyankar 4892b4ed282SShri Abhyankar PetscFunctionBegin; 4902b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4912b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 4922b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 4930005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetVariableBounds_C",&f);CHKERRQ(ierr); 49456e5e3feSPatrick Farrell if (!f) { 49556e5e3feSPatrick Farrell ierr = SNESVISetVariableBounds_VI(snes, xl, xu);CHKERRQ(ierr); 49656e5e3feSPatrick Farrell } else { 49761589011SJed Brown ierr = PetscUseMethod(snes,"SNESVISetVariableBounds_C",(SNES,Vec,Vec),(snes,xl,xu));CHKERRQ(ierr); 49856e5e3feSPatrick Farrell } 499a201590fSDmitry Karpeev snes->usersetbounds = PETSC_TRUE; 50061589011SJed Brown PetscFunctionReturn(0); 50161589011SJed Brown } 50261589011SJed Brown 50361589011SJed Brown #undef __FUNCT__ 50461589011SJed Brown #define __FUNCT__ "SNESVISetVariableBounds_VI" 50561589011SJed Brown PetscErrorCode SNESVISetVariableBounds_VI(SNES snes,Vec xl,Vec xu) 50661589011SJed Brown { 50761589011SJed Brown PetscErrorCode ierr; 50861589011SJed Brown const PetscScalar *xxl,*xxu; 50961589011SJed Brown PetscInt i,n, cnt = 0; 51061589011SJed Brown 51161589011SJed Brown PetscFunctionBegin; 5120298fd71SBarry Smith ierr = SNESGetFunction(snes,&snes->vec_func,NULL,NULL);CHKERRQ(ierr); 513a63bb30eSJed Brown if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first"); 514077aedafSJed Brown { 515077aedafSJed Brown PetscInt xlN,xuN,N; 516077aedafSJed Brown ierr = VecGetSize(xl,&xlN);CHKERRQ(ierr); 517077aedafSJed Brown ierr = VecGetSize(xu,&xuN);CHKERRQ(ierr); 518077aedafSJed Brown ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr); 519077aedafSJed Brown if (xlN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xlN,N); 520077aedafSJed Brown if (xuN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xuN,N); 521077aedafSJed Brown } 5222176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 5232176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 524c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xl);CHKERRQ(ierr); 525c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xu);CHKERRQ(ierr); 526c2fc9fa9SBarry Smith snes->xl = xl; 527c2fc9fa9SBarry Smith snes->xu = xu; 5286fd67740SBarry Smith ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); 5296fd67740SBarry Smith ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); 5306fd67740SBarry Smith ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); 531e270355aSBarry Smith for (i=0; i<n; i++) cnt += ((xxl[i] != PETSC_NINFINITY) || (xxu[i] != PETSC_INFINITY)); 5321aa26658SKarl Rupp 533ce94432eSBarry Smith ierr = MPI_Allreduce(&cnt,&snes->ntruebounds,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 5346fd67740SBarry Smith ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); 5356fd67740SBarry Smith ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); 5362b4ed282SShri Abhyankar PetscFunctionReturn(0); 5372b4ed282SShri Abhyankar } 53892c02d66SPeter Brune 5392b4ed282SShri Abhyankar #undef __FUNCT__ 540c2fc9fa9SBarry Smith #define __FUNCT__ "SNESSetFromOptions_VI" 5418c34d3f5SBarry Smith PetscErrorCode SNESSetFromOptions_VI(PetscOptions *PetscOptionsObject,SNES snes) 5422b4ed282SShri Abhyankar { 5432b4ed282SShri Abhyankar PetscErrorCode ierr; 5448afaa268SBarry Smith PetscBool flg = PETSC_FALSE; 545639ea3faSPeter Brune SNESLineSearch linesearch; 5462b4ed282SShri Abhyankar 5472b4ed282SShri Abhyankar PetscFunctionBegin; 548e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNES VI options");CHKERRQ(ierr); 549*349187a7SBarry Smith ierr = PetscOptionsReal("-snes_vi_zero_tolerance","Tolerance for considering x[] value to be on a bound","None",snes->vizerotolerance,&snes->vizerotolerance,NULL);CHKERRQ(ierr); 550ffdf2a20SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","SNESMonitorResidual",flg,&flg,NULL);CHKERRQ(ierr); 551c2fc9fa9SBarry Smith if (flg) { 552c2fc9fa9SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 5532b4ed282SShri Abhyankar } 554de34d3e9SBarry Smith flg = PETSC_FALSE; 555ffdf2a20SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor_residual","Monitor residual all non-active variables; using zero for active constraints","SNESMonitorVIResidual",flg,&flg,NULL);CHKERRQ(ierr); 556ffdf2a20SBarry Smith if (flg) { 557ffdf2a20SBarry Smith ierr = SNESMonitorSet(snes,SNESVIMonitorResidual,PETSC_VIEWER_DRAW_(PetscObjectComm((PetscObject)snes)),NULL);CHKERRQ(ierr); 558ffdf2a20SBarry Smith } 559639ea3faSPeter Brune if (!snes->linesearch) { 5607601faf0SJed Brown ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 561639ea3faSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr); 562639ea3faSPeter Brune ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr); 563639ea3faSPeter Brune } 564c2fc9fa9SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 565ed70e96aSJungho Lee PetscFunctionReturn(0); 566ed70e96aSJungho Lee } 567