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); 6187e98922SBarry Smith ierr = VecView(Finactive,viewer);CHKERRQ(ierr); 62ffdf2a20SBarry Smith ierr = VecDestroy(&Finactive);CHKERRQ(ierr); 63ffdf2a20SBarry Smith PetscFunctionReturn(0); 64ffdf2a20SBarry Smith } 65ffdf2a20SBarry Smith 66ffdf2a20SBarry Smith #undef __FUNCT__ 679308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI" 687087cfbeSBarry Smith PetscErrorCode SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy) 699308c137SBarry Smith { 709308c137SBarry Smith PetscErrorCode ierr; 71ce94432eSBarry Smith PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)); 729308c137SBarry Smith const PetscScalar *x,*xl,*xu,*f; 736fd67740SBarry Smith PetscInt i,n,act[2] = {0,0},fact[2],N; 746a9e2d46SJungho Lee /* Number of components that actually hit the bounds (c.f. active variables) */ 756a9e2d46SJungho Lee PetscInt act_bound[2] = {0,0},fact_bound[2]; 76349187a7SBarry Smith PetscReal rnorm,fnorm,zerotolerance = snes->vizerotolerance; 779d1809e2SSatish Balay double tmp; 789308c137SBarry Smith 799308c137SBarry Smith PetscFunctionBegin; 809308c137SBarry Smith ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr); 816fd67740SBarry Smith ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr); 82c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 83c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 849308c137SBarry Smith ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 853f731af5SBarry Smith ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 869308c137SBarry Smith 879308c137SBarry Smith rnorm = 0.0; 889308c137SBarry Smith for (i=0; i<n; i++) { 89349187a7SBarry 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]); 90349187a7SBarry Smith else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + zerotolerance && PetscRealPart(f[i]) > 0.0) act[0]++; 91349187a7SBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - zerotolerance && PetscRealPart(f[i]) < 0.0) act[1]++; 92ce94432eSBarry Smith else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Can never get here"); 939308c137SBarry Smith } 946a9e2d46SJungho Lee 956a9e2d46SJungho Lee for (i=0; i<n; i++) { 96349187a7SBarry Smith if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + zerotolerance) act_bound[0]++; 97349187a7SBarry Smith else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - zerotolerance) act_bound[1]++; 986a9e2d46SJungho Lee } 993f731af5SBarry Smith ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr); 100c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 101c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 1029308c137SBarry Smith ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr); 103ce94432eSBarry Smith ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 104ce94432eSBarry Smith ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 105ce94432eSBarry Smith ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 106f137e44dSBarry Smith fnorm = PetscSqrtReal(fnorm); 1076fd67740SBarry Smith 108649052a6SBarry Smith ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1099d1809e2SSatish Balay if (snes->ntruebounds) tmp = ((double)(fact[0]+fact[1]))/((double)snes->ntruebounds); 1109d1809e2SSatish Balay else tmp = 0.0; 111*62151390SBarry Smith ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %g 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); 1126a9e2d46SJungho Lee 113649052a6SBarry Smith ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 1149308c137SBarry Smith PetscFunctionReturn(0); 1159308c137SBarry Smith } 1169308c137SBarry Smith 1172b4ed282SShri Abhyankar /* 1182b4ed282SShri Abhyankar Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function, 1192b4ed282SShri 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 1202b4ed282SShri Abhyankar 0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More 1212b4ed282SShri Abhyankar for this trick. One assumes that the probability that W is in the null space of J is very, very small. 1222b4ed282SShri Abhyankar */ 1232b4ed282SShri Abhyankar #undef __FUNCT__ 1242b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private" 125ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin) 1262b4ed282SShri Abhyankar { 1272b4ed282SShri Abhyankar PetscReal a1; 1282b4ed282SShri Abhyankar PetscErrorCode ierr; 129ace3abfcSBarry Smith PetscBool hastranspose; 1302b4ed282SShri Abhyankar 1312b4ed282SShri Abhyankar PetscFunctionBegin; 1322b4ed282SShri Abhyankar *ismin = PETSC_FALSE; 1332b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 1342b4ed282SShri Abhyankar if (hastranspose) { 1352b4ed282SShri Abhyankar /* Compute || J^T F|| */ 1362b4ed282SShri Abhyankar ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr); 1372b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr); 1384839bfe8SBarry Smith ierr = PetscInfo1(snes,"|| J^T F|| %g near zero implies found a local minimum\n",(double)(a1/fnorm));CHKERRQ(ierr); 1392b4ed282SShri Abhyankar if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE; 1402b4ed282SShri Abhyankar } else { 1412b4ed282SShri Abhyankar Vec work; 1422b4ed282SShri Abhyankar PetscScalar result; 1432b4ed282SShri Abhyankar PetscReal wnorm; 1442b4ed282SShri Abhyankar 1450298fd71SBarry Smith ierr = VecSetRandom(W,NULL);CHKERRQ(ierr); 1462b4ed282SShri Abhyankar ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr); 1472b4ed282SShri Abhyankar ierr = VecDuplicate(W,&work);CHKERRQ(ierr); 1482b4ed282SShri Abhyankar ierr = MatMult(A,W,work);CHKERRQ(ierr); 1492b4ed282SShri Abhyankar ierr = VecDot(F,work,&result);CHKERRQ(ierr); 1506bf464f9SBarry Smith ierr = VecDestroy(&work);CHKERRQ(ierr); 1512b4ed282SShri Abhyankar a1 = PetscAbsScalar(result)/(fnorm*wnorm); 1524839bfe8SBarry Smith ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %g near zero implies found a local minimum\n",(double)a1);CHKERRQ(ierr); 1532b4ed282SShri Abhyankar if (a1 < 1.e-4) *ismin = PETSC_TRUE; 1542b4ed282SShri Abhyankar } 1552b4ed282SShri Abhyankar PetscFunctionReturn(0); 1562b4ed282SShri Abhyankar } 1572b4ed282SShri Abhyankar 1582b4ed282SShri Abhyankar /* 1592b4ed282SShri Abhyankar Checks if J^T(F - J*X) = 0 1602b4ed282SShri Abhyankar */ 1612b4ed282SShri Abhyankar #undef __FUNCT__ 1622b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private" 1632b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2) 1642b4ed282SShri Abhyankar { 1652b4ed282SShri Abhyankar PetscReal a1,a2; 1662b4ed282SShri Abhyankar PetscErrorCode ierr; 167ace3abfcSBarry Smith PetscBool hastranspose; 1682b4ed282SShri Abhyankar 1692b4ed282SShri Abhyankar PetscFunctionBegin; 1702b4ed282SShri Abhyankar ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr); 1712b4ed282SShri Abhyankar if (hastranspose) { 1722b4ed282SShri Abhyankar ierr = MatMult(A,X,W1);CHKERRQ(ierr); 1732b4ed282SShri Abhyankar ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr); 1742b4ed282SShri Abhyankar 1752b4ed282SShri Abhyankar /* Compute || J^T W|| */ 1762b4ed282SShri Abhyankar ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr); 1772b4ed282SShri Abhyankar ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr); 1782b4ed282SShri Abhyankar ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr); 1792b4ed282SShri Abhyankar if (a1 != 0.0) { 1804839bfe8SBarry Smith ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %g near zero implies inconsistent rhs\n",(double)(a2/a1));CHKERRQ(ierr); 1812b4ed282SShri Abhyankar } 1822b4ed282SShri Abhyankar } 1832b4ed282SShri Abhyankar PetscFunctionReturn(0); 1842b4ed282SShri Abhyankar } 1852b4ed282SShri Abhyankar 1862b4ed282SShri Abhyankar /* 1878d359177SBarry Smith SNESConvergedDefault_VI - Checks the convergence of the semismooth newton algorithm. 1882b4ed282SShri Abhyankar 1892b4ed282SShri Abhyankar Notes: 1902b4ed282SShri Abhyankar The convergence criterion currently implemented is 1912b4ed282SShri Abhyankar merit < abstol 1922b4ed282SShri Abhyankar merit < rtol*merit_initial 1932b4ed282SShri Abhyankar */ 1942b4ed282SShri Abhyankar #undef __FUNCT__ 1958d359177SBarry Smith #define __FUNCT__ "SNESConvergedDefault_VI" 1968d359177SBarry Smith PetscErrorCode SNESConvergedDefault_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy) 1972b4ed282SShri Abhyankar { 1982b4ed282SShri Abhyankar PetscErrorCode ierr; 1992b4ed282SShri Abhyankar 2002b4ed282SShri Abhyankar PetscFunctionBegin; 2012b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2022b4ed282SShri Abhyankar PetscValidPointer(reason,6); 2032b4ed282SShri Abhyankar 2042b4ed282SShri Abhyankar *reason = SNES_CONVERGED_ITERATING; 2052b4ed282SShri Abhyankar 2062b4ed282SShri Abhyankar if (!it) { 2072b4ed282SShri Abhyankar /* set parameter for default relative tolerance convergence test */ 2087fe79bc4SShri Abhyankar snes->ttol = fnorm*snes->rtol; 2092b4ed282SShri Abhyankar } 2107fe79bc4SShri Abhyankar if (fnorm != fnorm) { 2112b4ed282SShri Abhyankar ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr); 2122b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FNORM_NAN; 2137fe79bc4SShri Abhyankar } else if (fnorm < snes->abstol) { 2144839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr); 2152b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_ABS; 2162b4ed282SShri Abhyankar } else if (snes->nfuncs >= snes->max_funcs) { 2172b4ed282SShri Abhyankar ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr); 2182b4ed282SShri Abhyankar *reason = SNES_DIVERGED_FUNCTION_COUNT; 2192b4ed282SShri Abhyankar } 2202b4ed282SShri Abhyankar 2212b4ed282SShri Abhyankar if (it && !*reason) { 2227fe79bc4SShri Abhyankar if (fnorm < snes->ttol) { 2234839bfe8SBarry Smith ierr = PetscInfo2(snes,"Converged due to function norm %g < %g (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr); 2242b4ed282SShri Abhyankar *reason = SNES_CONVERGED_FNORM_RELATIVE; 2252b4ed282SShri Abhyankar } 2262b4ed282SShri Abhyankar } 2272b4ed282SShri Abhyankar PetscFunctionReturn(0); 2282b4ed282SShri Abhyankar } 2292b4ed282SShri Abhyankar 230ee657d29SShri Abhyankar 231c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */ 232c1a5e521SShri Abhyankar /* 233c1a5e521SShri Abhyankar SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n. 234c1a5e521SShri Abhyankar 235c1a5e521SShri Abhyankar Input Parameters: 236c1a5e521SShri Abhyankar . SNES - nonlinear solver context 237c1a5e521SShri Abhyankar 238c1a5e521SShri Abhyankar Output Parameters: 239c1a5e521SShri Abhyankar . X - Bound projected X 240c1a5e521SShri Abhyankar 241c1a5e521SShri Abhyankar */ 242c1a5e521SShri Abhyankar 243c1a5e521SShri Abhyankar #undef __FUNCT__ 244c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds" 245c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X) 246c1a5e521SShri Abhyankar { 247c1a5e521SShri Abhyankar PetscErrorCode ierr; 248c1a5e521SShri Abhyankar const PetscScalar *xl,*xu; 249c1a5e521SShri Abhyankar PetscScalar *x; 250c1a5e521SShri Abhyankar PetscInt i,n; 251c1a5e521SShri Abhyankar 252c1a5e521SShri Abhyankar PetscFunctionBegin; 253c1a5e521SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 254c1a5e521SShri Abhyankar ierr = VecGetArray(X,&x);CHKERRQ(ierr); 255c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 256c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 257c1a5e521SShri Abhyankar 258c1a5e521SShri Abhyankar for (i = 0; i<n; i++) { 25910f5ae6bSBarry Smith if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i]; 26010f5ae6bSBarry Smith else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i]; 261c1a5e521SShri Abhyankar } 262c1a5e521SShri Abhyankar ierr = VecRestoreArray(X,&x);CHKERRQ(ierr); 263c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 264c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 265c1a5e521SShri Abhyankar PetscFunctionReturn(0); 266c1a5e521SShri Abhyankar } 267c1a5e521SShri Abhyankar 26869c03620SShri Abhyankar 26969c03620SShri Abhyankar #undef __FUNCT__ 270693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS" 271693ddf92SShri Abhyankar /* 272693ddf92SShri Abhyankar SNESVIGetActiveSetIndices - Gets the global indices for the active set variables 273693ddf92SShri Abhyankar 274693ddf92SShri Abhyankar Input parameter 275693ddf92SShri Abhyankar . snes - the SNES context 276693ddf92SShri Abhyankar . X - the snes solution vector 277693ddf92SShri Abhyankar . F - the nonlinear function vector 278693ddf92SShri Abhyankar 279693ddf92SShri Abhyankar Output parameter 280693ddf92SShri Abhyankar . ISact - active set index set 281693ddf92SShri Abhyankar */ 282693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS *ISact) 283d950fb63SShri Abhyankar { 284d950fb63SShri Abhyankar PetscErrorCode ierr; 285c2fc9fa9SBarry Smith Vec Xl=snes->xl,Xu=snes->xu; 286693ddf92SShri Abhyankar const PetscScalar *x,*f,*xl,*xu; 287693ddf92SShri Abhyankar PetscInt *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0; 288349187a7SBarry Smith PetscReal zerotolerance = snes->vizerotolerance; 289d950fb63SShri Abhyankar 290d950fb63SShri Abhyankar PetscFunctionBegin; 291d950fb63SShri Abhyankar ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr); 292d950fb63SShri Abhyankar ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr); 293fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 294fe835674SShri Abhyankar ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr); 295fe835674SShri Abhyankar ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr); 296fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 297693ddf92SShri Abhyankar /* Compute active set size */ 298d950fb63SShri Abhyankar for (i=0; i < nlocal;i++) { 299349187a7SBarry 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++; 300d950fb63SShri Abhyankar } 301693ddf92SShri Abhyankar 302785e854fSJed Brown ierr = PetscMalloc1(nloc_isact,&idx_act);CHKERRQ(ierr); 303d950fb63SShri Abhyankar 304693ddf92SShri Abhyankar /* Set active set indices */ 305d950fb63SShri Abhyankar for (i=0; i < nlocal; i++) { 306349187a7SBarry 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; 307d950fb63SShri Abhyankar } 308d950fb63SShri Abhyankar 309693ddf92SShri Abhyankar /* Create active set IS */ 310ce94432eSBarry Smith ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr); 311d950fb63SShri Abhyankar 312fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 313fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr); 314fe835674SShri Abhyankar ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr); 315fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 316d950fb63SShri Abhyankar PetscFunctionReturn(0); 317d950fb63SShri Abhyankar } 318d950fb63SShri Abhyankar 319693ddf92SShri Abhyankar #undef __FUNCT__ 320693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS" 321693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS *ISact,IS *ISinact) 322693ddf92SShri Abhyankar { 323693ddf92SShri Abhyankar PetscErrorCode ierr; 324077aedafSJed Brown PetscInt rstart,rend; 325693ddf92SShri Abhyankar 326693ddf92SShri Abhyankar PetscFunctionBegin; 327693ddf92SShri Abhyankar ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr); 328077aedafSJed Brown ierr = VecGetOwnershipRange(X,&rstart,&rend);CHKERRQ(ierr); 329077aedafSJed Brown ierr = ISComplement(*ISact,rstart,rend,ISinact);CHKERRQ(ierr); 330693ddf92SShri Abhyankar PetscFunctionReturn(0); 331693ddf92SShri Abhyankar } 332693ddf92SShri Abhyankar 333fe835674SShri Abhyankar #undef __FUNCT__ 334fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm" 33510f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X, PetscReal *fnorm) 336fe835674SShri Abhyankar { 337fe835674SShri Abhyankar PetscErrorCode ierr; 338fe835674SShri Abhyankar const PetscScalar *x,*xl,*xu,*f; 339fe835674SShri Abhyankar PetscInt i,n; 340349187a7SBarry Smith PetscReal rnorm,zerotolerance = snes->vizerotolerance;; 341fe835674SShri Abhyankar 342fe835674SShri Abhyankar PetscFunctionBegin; 343fe835674SShri Abhyankar ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr); 344c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr); 345c2fc9fa9SBarry Smith ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr); 346fe835674SShri Abhyankar ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 347fe835674SShri Abhyankar ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr); 348fe835674SShri Abhyankar rnorm = 0.0; 349fe835674SShri Abhyankar for (i=0; i<n; i++) { 350349187a7SBarry 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]); 3518f918527SKarl Rupp } 352fe835674SShri Abhyankar ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr); 353c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr); 354c2fc9fa9SBarry Smith ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr); 355fe835674SShri Abhyankar ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 356ce94432eSBarry Smith ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 35762d1f40fSBarry Smith *fnorm = PetscSqrtReal(*fnorm); 358fe835674SShri Abhyankar PetscFunctionReturn(0); 359fe835674SShri Abhyankar } 360fe835674SShri Abhyankar 36108da532bSDmitry Karpeev #undef __FUNCT__ 36208da532bSDmitry Karpeev #define __FUNCT__ "SNESVIDMComputeVariableBounds" 36308da532bSDmitry Karpeev PetscErrorCode SNESVIDMComputeVariableBounds(SNES snes,Vec xl, Vec xu) 36408da532bSDmitry Karpeev { 36508da532bSDmitry Karpeev PetscErrorCode ierr; 3666e111a19SKarl Rupp 36708da532bSDmitry Karpeev PetscFunctionBegin; 36808da532bSDmitry Karpeev ierr = DMComputeVariableBounds(snes->dm, xl, xu);CHKERRQ(ierr); 36908da532bSDmitry Karpeev PetscFunctionReturn(0); 37008da532bSDmitry Karpeev } 37108da532bSDmitry Karpeev 3722f63a38cSShri Abhyankar 3732b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 3742b4ed282SShri Abhyankar /* 375c2fc9fa9SBarry Smith SNESSetUp_VI - Does setup common to all VI solvers -- basically makes sure bounds have been properly set up 3762b4ed282SShri Abhyankar of the SNESVI nonlinear solver. 3772b4ed282SShri Abhyankar 3782b4ed282SShri Abhyankar Input Parameter: 3792b4ed282SShri Abhyankar . snes - the SNES context 3802b4ed282SShri Abhyankar 3812b4ed282SShri Abhyankar Application Interface Routine: SNESSetUp() 3822b4ed282SShri Abhyankar 3832b4ed282SShri Abhyankar Notes: 3842b4ed282SShri Abhyankar For basic use of the SNES solvers, the user need not explicitly call 3852b4ed282SShri Abhyankar SNESSetUp(), since these actions will automatically occur during 3862b4ed282SShri Abhyankar the call to SNESSolve(). 3872b4ed282SShri Abhyankar */ 3882b4ed282SShri Abhyankar #undef __FUNCT__ 3892b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI" 3902b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes) 3912b4ed282SShri Abhyankar { 3922b4ed282SShri Abhyankar PetscErrorCode ierr; 3932b4ed282SShri Abhyankar PetscInt i_start[3],i_end[3]; 3942b4ed282SShri Abhyankar 3952b4ed282SShri Abhyankar PetscFunctionBegin; 396fa0ddf94SBarry Smith ierr = SNESSetWorkVecs(snes,1);CHKERRQ(ierr); 3976cab3a1bSJed Brown ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr); 3982b4ed282SShri Abhyankar 39908da532bSDmitry Karpeev if (!snes->ops->computevariablebounds && snes->dm) { 400a201590fSDmitry Karpeev PetscBool flag; 401a201590fSDmitry Karpeev ierr = DMHasVariableBounds(snes->dm, &flag);CHKERRQ(ierr); 4021aa26658SKarl Rupp 40308da532bSDmitry Karpeev snes->ops->computevariablebounds = SNESVIDMComputeVariableBounds; 40408da532bSDmitry Karpeev } 405a201590fSDmitry Karpeev if (!snes->usersetbounds) { 406c2fc9fa9SBarry Smith if (snes->ops->computevariablebounds) { 407c2fc9fa9SBarry Smith if (!snes->xl) {ierr = VecDuplicate(snes->vec_sol,&snes->xl);CHKERRQ(ierr);} 408c2fc9fa9SBarry Smith if (!snes->xu) {ierr = VecDuplicate(snes->vec_sol,&snes->xu);CHKERRQ(ierr);} 409c2fc9fa9SBarry Smith ierr = (*snes->ops->computevariablebounds)(snes,snes->xl,snes->xu);CHKERRQ(ierr); 4101aa26658SKarl Rupp } else if (!snes->xl && !snes->xu) { 4112176524cSBarry Smith /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */ 412c2fc9fa9SBarry Smith ierr = VecDuplicate(snes->vec_sol, &snes->xl);CHKERRQ(ierr); 413e270355aSBarry Smith ierr = VecSet(snes->xl,PETSC_NINFINITY);CHKERRQ(ierr); 414c2fc9fa9SBarry Smith ierr = VecDuplicate(snes->vec_sol, &snes->xu);CHKERRQ(ierr); 415e270355aSBarry Smith ierr = VecSet(snes->xu,PETSC_INFINITY);CHKERRQ(ierr); 4162b4ed282SShri Abhyankar } else { 4172b4ed282SShri Abhyankar /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */ 4182b4ed282SShri Abhyankar ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr); 419c2fc9fa9SBarry Smith ierr = VecGetOwnershipRange(snes->xl,i_start+1,i_end+1);CHKERRQ(ierr); 420c2fc9fa9SBarry Smith ierr = VecGetOwnershipRange(snes->xu,i_start+2,i_end+2);CHKERRQ(ierr); 4212b4ed282SShri 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])) 4222b4ed282SShri 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."); 4232b4ed282SShri Abhyankar } 424a201590fSDmitry Karpeev } 4252b4ed282SShri Abhyankar PetscFunctionReturn(0); 4262b4ed282SShri Abhyankar } 4272b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */ 4282176524cSBarry Smith #undef __FUNCT__ 4292176524cSBarry Smith #define __FUNCT__ "SNESReset_VI" 4302176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes) 4312176524cSBarry Smith { 4322176524cSBarry Smith PetscErrorCode ierr; 4332176524cSBarry Smith 4342176524cSBarry Smith PetscFunctionBegin; 435c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xl);CHKERRQ(ierr); 436c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xu);CHKERRQ(ierr); 4372d6615e8SDmitry Karpeev snes->usersetbounds = PETSC_FALSE; 4382176524cSBarry Smith PetscFunctionReturn(0); 4392176524cSBarry Smith } 4402176524cSBarry Smith 4412b4ed282SShri Abhyankar /* 4422b4ed282SShri Abhyankar SNESDestroy_VI - Destroys the private SNES_VI context that was created 4432b4ed282SShri Abhyankar with SNESCreate_VI(). 4442b4ed282SShri Abhyankar 4452b4ed282SShri Abhyankar Input Parameter: 4462b4ed282SShri Abhyankar . snes - the SNES context 4472b4ed282SShri Abhyankar 4482b4ed282SShri Abhyankar Application Interface Routine: SNESDestroy() 4492b4ed282SShri Abhyankar */ 4502b4ed282SShri Abhyankar #undef __FUNCT__ 4512b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI" 4522b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes) 4532b4ed282SShri Abhyankar { 4542b4ed282SShri Abhyankar PetscErrorCode ierr; 4552b4ed282SShri Abhyankar 4562b4ed282SShri Abhyankar PetscFunctionBegin; 4572b4ed282SShri Abhyankar ierr = PetscFree(snes->data);CHKERRQ(ierr); 4582b4ed282SShri Abhyankar 4592b4ed282SShri Abhyankar /* clear composed functions */ 460bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSet_C",NULL);CHKERRQ(ierr); 461bdf89e91SBarry Smith ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSetMonitor_C",NULL);CHKERRQ(ierr); 4622b4ed282SShri Abhyankar PetscFunctionReturn(0); 4632b4ed282SShri Abhyankar } 4647fe79bc4SShri Abhyankar 4655559b345SBarry Smith #undef __FUNCT__ 4665559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds" 4675559b345SBarry Smith /*@ 4682b4ed282SShri Abhyankar SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu. 4692b4ed282SShri Abhyankar 4702b4ed282SShri Abhyankar Input Parameters: 4712b4ed282SShri Abhyankar . snes - the SNES context. 4722b4ed282SShri Abhyankar . xl - lower bound. 4732b4ed282SShri Abhyankar . xu - upper bound. 4742b4ed282SShri Abhyankar 4752b4ed282SShri Abhyankar Notes: 4762b4ed282SShri Abhyankar If this routine is not called then the lower and upper bounds are set to 47729eed3a4SBarry Smith PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp(). 47884c105d7SBarry Smith 4792bd2b0e6SSatish Balay Level: advanced 4802bd2b0e6SSatish Balay 4815559b345SBarry Smith @*/ 48269c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu) 4832b4ed282SShri Abhyankar { 48461589011SJed Brown PetscErrorCode ierr,(*f)(SNES,Vec,Vec); 4852b4ed282SShri Abhyankar 4862b4ed282SShri Abhyankar PetscFunctionBegin; 4872b4ed282SShri Abhyankar PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4882b4ed282SShri Abhyankar PetscValidHeaderSpecific(xl,VEC_CLASSID,2); 4892b4ed282SShri Abhyankar PetscValidHeaderSpecific(xu,VEC_CLASSID,3); 4900005d66cSJed Brown ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetVariableBounds_C",&f);CHKERRQ(ierr); 49156e5e3feSPatrick Farrell if (!f) { 49256e5e3feSPatrick Farrell ierr = SNESVISetVariableBounds_VI(snes, xl, xu);CHKERRQ(ierr); 49356e5e3feSPatrick Farrell } else { 49461589011SJed Brown ierr = PetscUseMethod(snes,"SNESVISetVariableBounds_C",(SNES,Vec,Vec),(snes,xl,xu));CHKERRQ(ierr); 49556e5e3feSPatrick Farrell } 496a201590fSDmitry Karpeev snes->usersetbounds = PETSC_TRUE; 49761589011SJed Brown PetscFunctionReturn(0); 49861589011SJed Brown } 49961589011SJed Brown 50061589011SJed Brown #undef __FUNCT__ 50161589011SJed Brown #define __FUNCT__ "SNESVISetVariableBounds_VI" 50261589011SJed Brown PetscErrorCode SNESVISetVariableBounds_VI(SNES snes,Vec xl,Vec xu) 50361589011SJed Brown { 50461589011SJed Brown PetscErrorCode ierr; 50561589011SJed Brown const PetscScalar *xxl,*xxu; 50661589011SJed Brown PetscInt i,n, cnt = 0; 50761589011SJed Brown 50861589011SJed Brown PetscFunctionBegin; 5090298fd71SBarry Smith ierr = SNESGetFunction(snes,&snes->vec_func,NULL,NULL);CHKERRQ(ierr); 510a63bb30eSJed Brown if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first"); 511077aedafSJed Brown { 512077aedafSJed Brown PetscInt xlN,xuN,N; 513077aedafSJed Brown ierr = VecGetSize(xl,&xlN);CHKERRQ(ierr); 514077aedafSJed Brown ierr = VecGetSize(xu,&xuN);CHKERRQ(ierr); 515077aedafSJed Brown ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr); 516077aedafSJed Brown if (xlN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xlN,N); 517077aedafSJed Brown if (xuN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xuN,N); 518077aedafSJed Brown } 5192176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr); 5202176524cSBarry Smith ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr); 521c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xl);CHKERRQ(ierr); 522c2fc9fa9SBarry Smith ierr = VecDestroy(&snes->xu);CHKERRQ(ierr); 523c2fc9fa9SBarry Smith snes->xl = xl; 524c2fc9fa9SBarry Smith snes->xu = xu; 5256fd67740SBarry Smith ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr); 5266fd67740SBarry Smith ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr); 5276fd67740SBarry Smith ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr); 528e270355aSBarry Smith for (i=0; i<n; i++) cnt += ((xxl[i] != PETSC_NINFINITY) || (xxu[i] != PETSC_INFINITY)); 5291aa26658SKarl Rupp 530ce94432eSBarry Smith ierr = MPI_Allreduce(&cnt,&snes->ntruebounds,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr); 5316fd67740SBarry Smith ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr); 5326fd67740SBarry Smith ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr); 5332b4ed282SShri Abhyankar PetscFunctionReturn(0); 5342b4ed282SShri Abhyankar } 53592c02d66SPeter Brune 5362b4ed282SShri Abhyankar #undef __FUNCT__ 537c2fc9fa9SBarry Smith #define __FUNCT__ "SNESSetFromOptions_VI" 5388c34d3f5SBarry Smith PetscErrorCode SNESSetFromOptions_VI(PetscOptions *PetscOptionsObject,SNES snes) 5392b4ed282SShri Abhyankar { 5402b4ed282SShri Abhyankar PetscErrorCode ierr; 5418afaa268SBarry Smith PetscBool flg = PETSC_FALSE; 542639ea3faSPeter Brune SNESLineSearch linesearch; 5432b4ed282SShri Abhyankar 5442b4ed282SShri Abhyankar PetscFunctionBegin; 545e55864a3SBarry Smith ierr = PetscOptionsHead(PetscOptionsObject,"SNES VI options");CHKERRQ(ierr); 546349187a7SBarry 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); 547ffdf2a20SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","SNESMonitorResidual",flg,&flg,NULL);CHKERRQ(ierr); 548c2fc9fa9SBarry Smith if (flg) { 549c2fc9fa9SBarry Smith ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr); 5502b4ed282SShri Abhyankar } 551de34d3e9SBarry Smith flg = PETSC_FALSE; 552ffdf2a20SBarry Smith ierr = PetscOptionsBool("-snes_vi_monitor_residual","Monitor residual all non-active variables; using zero for active constraints","SNESMonitorVIResidual",flg,&flg,NULL);CHKERRQ(ierr); 553ffdf2a20SBarry Smith if (flg) { 554ffdf2a20SBarry Smith ierr = SNESMonitorSet(snes,SNESVIMonitorResidual,PETSC_VIEWER_DRAW_(PetscObjectComm((PetscObject)snes)),NULL);CHKERRQ(ierr); 555ffdf2a20SBarry Smith } 556639ea3faSPeter Brune if (!snes->linesearch) { 5577601faf0SJed Brown ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 558639ea3faSPeter Brune ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr); 559639ea3faSPeter Brune ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr); 560639ea3faSPeter Brune } 561c2fc9fa9SBarry Smith ierr = PetscOptionsTail();CHKERRQ(ierr); 562ed70e96aSJungho Lee PetscFunctionReturn(0); 563ed70e96aSJungho Lee } 564