xref: /petsc/src/snes/impls/vi/vi.c (revision de34d3e9c00d3cbb522f45d3e672d22fa8d6368a)
1639ea3faSPeter Brune #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);
25f450aa47SBarry Smith   if (!f) {ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr);}
2661589011SJed Brown   ierr = PetscUseMethod(snes,"SNESVISetComputeVariableBounds_C",(SNES,PetscErrorCode (*)(SNES,Vec,Vec)),(snes,compute));CHKERRQ(ierr);
272176524cSBarry Smith   PetscFunctionReturn(0);
282176524cSBarry Smith }
292176524cSBarry Smith 
3061589011SJed Brown #undef __FUNCT__
3161589011SJed Brown #define __FUNCT__ "SNESVISetComputeVariableBounds_VI"
3261589011SJed Brown PetscErrorCode SNESVISetComputeVariableBounds_VI(SNES snes,SNESVIComputeVariableBoundsFunction compute)
3361589011SJed Brown {
3461589011SJed Brown   PetscFunctionBegin;
3561589011SJed Brown   snes->ops->computevariablebounds = compute;
3661589011SJed Brown   PetscFunctionReturn(0);
3761589011SJed Brown }
382176524cSBarry Smith 
392176524cSBarry Smith #undef __FUNCT__
40ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS"
41d0af7cd3SBarry Smith /*
42ed70e96aSJungho Lee    SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables
43d0af7cd3SBarry Smith 
44d0af7cd3SBarry Smith    Input parameter
45d0af7cd3SBarry Smith .  snes - the SNES context
46d0af7cd3SBarry Smith .  X    - the snes solution vector
47d0af7cd3SBarry Smith 
48d0af7cd3SBarry Smith    Output parameter
49d0af7cd3SBarry Smith .  ISact - active set index set
50d0af7cd3SBarry Smith 
51d0af7cd3SBarry Smith  */
52ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS *inact)
53d0af7cd3SBarry Smith {
54d0af7cd3SBarry Smith   PetscErrorCode    ierr;
55d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
56d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
57d0af7cd3SBarry Smith 
58d0af7cd3SBarry Smith   PetscFunctionBegin;
59d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
60d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
61d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
62d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
63d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
64d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
65d0af7cd3SBarry Smith   /* Compute inactive set size */
66d0af7cd3SBarry Smith   for (i=0; i < nlocal; i++) {
67d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
68d0af7cd3SBarry Smith   }
69d0af7cd3SBarry Smith 
70785e854fSJed Brown   ierr = PetscMalloc1(nloc_isact,&idx_act);CHKERRQ(ierr);
71d0af7cd3SBarry Smith 
72d0af7cd3SBarry Smith   /* Set inactive set indices */
73d0af7cd3SBarry Smith   for (i=0; i < nlocal; i++) {
74d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
75d0af7cd3SBarry Smith   }
76d0af7cd3SBarry Smith 
77d0af7cd3SBarry Smith   /* Create inactive set IS */
78ce94432eSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)upper),nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
79d0af7cd3SBarry Smith 
80d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
81d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
82d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
83d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
84d0af7cd3SBarry Smith   PetscFunctionReturn(0);
85d0af7cd3SBarry Smith }
86d0af7cd3SBarry Smith 
873c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
882b4ed282SShri Abhyankar 
899308c137SBarry Smith #undef __FUNCT__
90ffdf2a20SBarry Smith #define __FUNCT__ "SNESVIMonitorResidual"
91ffdf2a20SBarry Smith PetscErrorCode  SNESVIMonitorResidual(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
92ffdf2a20SBarry Smith {
93ffdf2a20SBarry Smith   PetscErrorCode ierr;
94ffdf2a20SBarry Smith   Vec            X, F, Finactive;
95ffdf2a20SBarry Smith   IS             isactive;
96ffdf2a20SBarry Smith   PetscViewer    viewer = (PetscViewer) dummy;
97ffdf2a20SBarry Smith 
98ffdf2a20SBarry Smith   PetscFunctionBegin;
99ffdf2a20SBarry Smith   ierr = SNESGetFunction(snes,&F,0,0);CHKERRQ(ierr);
100ffdf2a20SBarry Smith   ierr = SNESGetSolution(snes,&X);CHKERRQ(ierr);
10187e98922SBarry Smith   ierr = SNESVIGetActiveSetIS(snes,X,F,&isactive);CHKERRQ(ierr);
102ffdf2a20SBarry Smith   ierr = VecDuplicate(F,&Finactive);CHKERRQ(ierr);
103ffdf2a20SBarry Smith   ierr = VecCopy(F,Finactive);CHKERRQ(ierr);
10487e98922SBarry Smith   ierr = VecISSet(Finactive,isactive,0.0);CHKERRQ(ierr);
105*de34d3e9SBarry Smith   ierr = ISDestroy(&isactive);CHKERRQ(ierr);
106ffdf2a20SBarry Smith   if (!viewer) {
107ffdf2a20SBarry Smith     viewer = PETSC_VIEWER_DRAW_(PetscObjectComm((PetscObject)snes));
108ffdf2a20SBarry Smith   }
10987e98922SBarry Smith   ierr = VecView(Finactive,viewer);CHKERRQ(ierr);
110ffdf2a20SBarry Smith   ierr = VecDestroy(&Finactive);CHKERRQ(ierr);
111ffdf2a20SBarry Smith   PetscFunctionReturn(0);
112ffdf2a20SBarry Smith }
113ffdf2a20SBarry Smith 
114ffdf2a20SBarry Smith #undef __FUNCT__
1159308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
1167087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
1179308c137SBarry Smith {
1189308c137SBarry Smith   PetscErrorCode    ierr;
119ce94432eSBarry Smith   PetscViewer       viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes));
1209308c137SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
1216fd67740SBarry Smith   PetscInt          i,n,act[2] = {0,0},fact[2],N;
1226a9e2d46SJungho Lee   /* Number of components that actually hit the bounds (c.f. active variables) */
1236a9e2d46SJungho Lee   PetscInt  act_bound[2] = {0,0},fact_bound[2];
1249308c137SBarry Smith   PetscReal rnorm,fnorm;
1259d1809e2SSatish Balay   double    tmp;
1269308c137SBarry Smith 
1279308c137SBarry Smith   PetscFunctionBegin;
1289308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1296fd67740SBarry Smith   ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr);
130c2fc9fa9SBarry Smith   ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr);
131c2fc9fa9SBarry Smith   ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr);
1329308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
1333f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
1349308c137SBarry Smith 
1359308c137SBarry Smith   rnorm = 0.0;
1369308c137SBarry Smith   for (i=0; i<n; i++) {
13710f5ae6bSBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]);
138e400df7aSBarry Smith     else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++;
139e400df7aSBarry Smith     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++;
140ce94432eSBarry Smith     else SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"Can never get here");
1419308c137SBarry Smith   }
1426a9e2d46SJungho Lee 
1436a9e2d46SJungho Lee   for (i=0; i<n; i++) {
1446a9e2d46SJungho Lee     if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++;
1456a9e2d46SJungho Lee     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++;
1466a9e2d46SJungho Lee   }
1473f731af5SBarry Smith   ierr  = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
148c2fc9fa9SBarry Smith   ierr  = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr);
149c2fc9fa9SBarry Smith   ierr  = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr);
1509308c137SBarry Smith   ierr  = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
151ce94432eSBarry Smith   ierr  = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
152ce94432eSBarry Smith   ierr  = MPI_Allreduce(act,fact,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
153ce94432eSBarry Smith   ierr  = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
154f137e44dSBarry Smith   fnorm = PetscSqrtReal(fnorm);
1556fd67740SBarry Smith 
156649052a6SBarry Smith   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1579d1809e2SSatish Balay   if (snes->ntruebounds) tmp = ((double)(fact[0]+fact[1]))/((double)snes->ntruebounds);
1589d1809e2SSatish Balay   else tmp = 0.0;
1599d1809e2SSatish 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);
1606a9e2d46SJungho Lee 
161649052a6SBarry Smith   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1629308c137SBarry Smith   PetscFunctionReturn(0);
1639308c137SBarry Smith }
1649308c137SBarry Smith 
1652b4ed282SShri Abhyankar /*
1662b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
1672b4ed282SShri 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
1682b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
1692b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
1702b4ed282SShri Abhyankar */
1712b4ed282SShri Abhyankar #undef __FUNCT__
1722b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
173ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
1742b4ed282SShri Abhyankar {
1752b4ed282SShri Abhyankar   PetscReal      a1;
1762b4ed282SShri Abhyankar   PetscErrorCode ierr;
177ace3abfcSBarry Smith   PetscBool      hastranspose;
1782b4ed282SShri Abhyankar 
1792b4ed282SShri Abhyankar   PetscFunctionBegin;
1802b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
1812b4ed282SShri Abhyankar   ierr   = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
1822b4ed282SShri Abhyankar   if (hastranspose) {
1832b4ed282SShri Abhyankar     /* Compute || J^T F|| */
1842b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
1852b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
1864839bfe8SBarry Smith     ierr = PetscInfo1(snes,"|| J^T F|| %g near zero implies found a local minimum\n",(double)(a1/fnorm));CHKERRQ(ierr);
1872b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
1882b4ed282SShri Abhyankar   } else {
1892b4ed282SShri Abhyankar     Vec         work;
1902b4ed282SShri Abhyankar     PetscScalar result;
1912b4ed282SShri Abhyankar     PetscReal   wnorm;
1922b4ed282SShri Abhyankar 
1930298fd71SBarry Smith     ierr = VecSetRandom(W,NULL);CHKERRQ(ierr);
1942b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
1952b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
1962b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
1972b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
1986bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
1992b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
2004839bfe8SBarry Smith     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %g near zero implies found a local minimum\n",(double)a1);CHKERRQ(ierr);
2012b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
2022b4ed282SShri Abhyankar   }
2032b4ed282SShri Abhyankar   PetscFunctionReturn(0);
2042b4ed282SShri Abhyankar }
2052b4ed282SShri Abhyankar 
2062b4ed282SShri Abhyankar /*
2072b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
2082b4ed282SShri Abhyankar */
2092b4ed282SShri Abhyankar #undef __FUNCT__
2102b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
2112b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
2122b4ed282SShri Abhyankar {
2132b4ed282SShri Abhyankar   PetscReal      a1,a2;
2142b4ed282SShri Abhyankar   PetscErrorCode ierr;
215ace3abfcSBarry Smith   PetscBool      hastranspose;
2162b4ed282SShri Abhyankar 
2172b4ed282SShri Abhyankar   PetscFunctionBegin;
2182b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
2192b4ed282SShri Abhyankar   if (hastranspose) {
2202b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
2212b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
2222b4ed282SShri Abhyankar 
2232b4ed282SShri Abhyankar     /* Compute || J^T W|| */
2242b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
2252b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
2262b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
2272b4ed282SShri Abhyankar     if (a1 != 0.0) {
2284839bfe8SBarry Smith       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %g near zero implies inconsistent rhs\n",(double)(a2/a1));CHKERRQ(ierr);
2292b4ed282SShri Abhyankar     }
2302b4ed282SShri Abhyankar   }
2312b4ed282SShri Abhyankar   PetscFunctionReturn(0);
2322b4ed282SShri Abhyankar }
2332b4ed282SShri Abhyankar 
2342b4ed282SShri Abhyankar /*
2358d359177SBarry Smith   SNESConvergedDefault_VI - Checks the convergence of the semismooth newton algorithm.
2362b4ed282SShri Abhyankar 
2372b4ed282SShri Abhyankar   Notes:
2382b4ed282SShri Abhyankar   The convergence criterion currently implemented is
2392b4ed282SShri Abhyankar   merit < abstol
2402b4ed282SShri Abhyankar   merit < rtol*merit_initial
2412b4ed282SShri Abhyankar */
2422b4ed282SShri Abhyankar #undef __FUNCT__
2438d359177SBarry Smith #define __FUNCT__ "SNESConvergedDefault_VI"
2448d359177SBarry Smith PetscErrorCode SNESConvergedDefault_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
2452b4ed282SShri Abhyankar {
2462b4ed282SShri Abhyankar   PetscErrorCode ierr;
2472b4ed282SShri Abhyankar 
2482b4ed282SShri Abhyankar   PetscFunctionBegin;
2492b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
2502b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
2512b4ed282SShri Abhyankar 
2522b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
2532b4ed282SShri Abhyankar 
2542b4ed282SShri Abhyankar   if (!it) {
2552b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
2567fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
2572b4ed282SShri Abhyankar   }
2587fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
2592b4ed282SShri Abhyankar     ierr    = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
2602b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
2617fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
2624839bfe8SBarry Smith     ierr    = PetscInfo2(snes,"Converged due to function norm %g < %g\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr);
2632b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
2642b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
2652b4ed282SShri Abhyankar     ierr    = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
2662b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
2672b4ed282SShri Abhyankar   }
2682b4ed282SShri Abhyankar 
2692b4ed282SShri Abhyankar   if (it && !*reason) {
2707fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
2714839bfe8SBarry Smith       ierr    = PetscInfo2(snes,"Converged due to function norm %g < %g (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr);
2722b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
2732b4ed282SShri Abhyankar     }
2742b4ed282SShri Abhyankar   }
2752b4ed282SShri Abhyankar   PetscFunctionReturn(0);
2762b4ed282SShri Abhyankar }
2772b4ed282SShri Abhyankar 
278ee657d29SShri Abhyankar 
279c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
280c1a5e521SShri Abhyankar /*
281c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
282c1a5e521SShri Abhyankar 
283c1a5e521SShri Abhyankar    Input Parameters:
284c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
285c1a5e521SShri Abhyankar 
286c1a5e521SShri Abhyankar    Output Parameters:
287c1a5e521SShri Abhyankar .  X - Bound projected X
288c1a5e521SShri Abhyankar 
289c1a5e521SShri Abhyankar */
290c1a5e521SShri Abhyankar 
291c1a5e521SShri Abhyankar #undef __FUNCT__
292c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
293c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
294c1a5e521SShri Abhyankar {
295c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
296c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
297c1a5e521SShri Abhyankar   PetscScalar       *x;
298c1a5e521SShri Abhyankar   PetscInt          i,n;
299c1a5e521SShri Abhyankar 
300c1a5e521SShri Abhyankar   PetscFunctionBegin;
301c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
302c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
303c2fc9fa9SBarry Smith   ierr = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr);
304c2fc9fa9SBarry Smith   ierr = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr);
305c1a5e521SShri Abhyankar 
306c1a5e521SShri Abhyankar   for (i = 0; i<n; i++) {
30710f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
30810f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
309c1a5e521SShri Abhyankar   }
310c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
311c2fc9fa9SBarry Smith   ierr = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr);
312c2fc9fa9SBarry Smith   ierr = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr);
313c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
314c1a5e521SShri Abhyankar }
315c1a5e521SShri Abhyankar 
31669c03620SShri Abhyankar 
31769c03620SShri Abhyankar #undef __FUNCT__
318693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
319693ddf92SShri Abhyankar /*
320693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
321693ddf92SShri Abhyankar 
322693ddf92SShri Abhyankar    Input parameter
323693ddf92SShri Abhyankar .  snes - the SNES context
324693ddf92SShri Abhyankar .  X    - the snes solution vector
325693ddf92SShri Abhyankar .  F    - the nonlinear function vector
326693ddf92SShri Abhyankar 
327693ddf92SShri Abhyankar    Output parameter
328693ddf92SShri Abhyankar .  ISact - active set index set
329693ddf92SShri Abhyankar  */
330693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS *ISact)
331d950fb63SShri Abhyankar {
332d950fb63SShri Abhyankar   PetscErrorCode    ierr;
333c2fc9fa9SBarry Smith   Vec               Xl=snes->xl,Xu=snes->xu;
334693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
335693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
336d950fb63SShri Abhyankar 
337d950fb63SShri Abhyankar   PetscFunctionBegin;
338d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
339d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
340fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
341fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
342fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
343fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
344693ddf92SShri Abhyankar   /* Compute active set size */
345d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
34610f5ae6bSBarry Smith     if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
347d950fb63SShri Abhyankar   }
348693ddf92SShri Abhyankar 
349785e854fSJed Brown   ierr = PetscMalloc1(nloc_isact,&idx_act);CHKERRQ(ierr);
350d950fb63SShri Abhyankar 
351693ddf92SShri Abhyankar   /* Set active set indices */
352d950fb63SShri Abhyankar   for (i=0; i < nlocal; i++) {
35310f5ae6bSBarry Smith     if (!((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
354d950fb63SShri Abhyankar   }
355d950fb63SShri Abhyankar 
356693ddf92SShri Abhyankar   /* Create active set IS */
357ce94432eSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
358d950fb63SShri Abhyankar 
359fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
360fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
361fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
362fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
363d950fb63SShri Abhyankar   PetscFunctionReturn(0);
364d950fb63SShri Abhyankar }
365d950fb63SShri Abhyankar 
366693ddf92SShri Abhyankar #undef __FUNCT__
367693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
368693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS *ISact,IS *ISinact)
369693ddf92SShri Abhyankar {
370693ddf92SShri Abhyankar   PetscErrorCode ierr;
371077aedafSJed Brown   PetscInt       rstart,rend;
372693ddf92SShri Abhyankar 
373693ddf92SShri Abhyankar   PetscFunctionBegin;
374693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
375077aedafSJed Brown   ierr = VecGetOwnershipRange(X,&rstart,&rend);CHKERRQ(ierr);
376077aedafSJed Brown   ierr = ISComplement(*ISact,rstart,rend,ISinact);CHKERRQ(ierr);
377693ddf92SShri Abhyankar   PetscFunctionReturn(0);
378693ddf92SShri Abhyankar }
379693ddf92SShri Abhyankar 
380fe835674SShri Abhyankar #undef __FUNCT__
381fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
38210f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X, PetscReal *fnorm)
383fe835674SShri Abhyankar {
384fe835674SShri Abhyankar   PetscErrorCode    ierr;
385fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
386fe835674SShri Abhyankar   PetscInt          i,n;
387fe835674SShri Abhyankar   PetscReal         rnorm;
388fe835674SShri Abhyankar 
389fe835674SShri Abhyankar   PetscFunctionBegin;
390fe835674SShri Abhyankar   ierr  = VecGetLocalSize(X,&n);CHKERRQ(ierr);
391c2fc9fa9SBarry Smith   ierr  = VecGetArrayRead(snes->xl,&xl);CHKERRQ(ierr);
392c2fc9fa9SBarry Smith   ierr  = VecGetArrayRead(snes->xu,&xu);CHKERRQ(ierr);
393fe835674SShri Abhyankar   ierr  = VecGetArrayRead(X,&x);CHKERRQ(ierr);
394fe835674SShri Abhyankar   ierr  = VecGetArrayRead(F,&f);CHKERRQ(ierr);
395fe835674SShri Abhyankar   rnorm = 0.0;
396fe835674SShri Abhyankar   for (i=0; i<n; i++) {
39710f5ae6bSBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) rnorm += PetscRealPart(PetscConj(f[i])*f[i]);
3988f918527SKarl Rupp   }
399fe835674SShri Abhyankar   ierr   = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
400c2fc9fa9SBarry Smith   ierr   = VecRestoreArrayRead(snes->xl,&xl);CHKERRQ(ierr);
401c2fc9fa9SBarry Smith   ierr   = VecRestoreArrayRead(snes->xu,&xu);CHKERRQ(ierr);
402fe835674SShri Abhyankar   ierr   = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
403ce94432eSBarry Smith   ierr   = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
40462d1f40fSBarry Smith   *fnorm = PetscSqrtReal(*fnorm);
405fe835674SShri Abhyankar   PetscFunctionReturn(0);
406fe835674SShri Abhyankar }
407fe835674SShri Abhyankar 
40808da532bSDmitry Karpeev #undef __FUNCT__
40908da532bSDmitry Karpeev #define __FUNCT__ "SNESVIDMComputeVariableBounds"
41008da532bSDmitry Karpeev PetscErrorCode SNESVIDMComputeVariableBounds(SNES snes,Vec xl, Vec xu)
41108da532bSDmitry Karpeev {
41208da532bSDmitry Karpeev   PetscErrorCode ierr;
4136e111a19SKarl Rupp 
41408da532bSDmitry Karpeev   PetscFunctionBegin;
41508da532bSDmitry Karpeev   ierr = DMComputeVariableBounds(snes->dm, xl, xu);CHKERRQ(ierr);
41608da532bSDmitry Karpeev   PetscFunctionReturn(0);
41708da532bSDmitry Karpeev }
41808da532bSDmitry Karpeev 
4192f63a38cSShri Abhyankar 
4202b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
4212b4ed282SShri Abhyankar /*
422c2fc9fa9SBarry Smith    SNESSetUp_VI - Does setup common to all VI solvers -- basically makes sure bounds have been properly set up
4232b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
4242b4ed282SShri Abhyankar 
4252b4ed282SShri Abhyankar    Input Parameter:
4262b4ed282SShri Abhyankar .  snes - the SNES context
4272b4ed282SShri Abhyankar .  x - the solution vector
4282b4ed282SShri Abhyankar 
4292b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
4302b4ed282SShri Abhyankar 
4312b4ed282SShri Abhyankar    Notes:
4322b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
4332b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
4342b4ed282SShri Abhyankar    the call to SNESSolve().
4352b4ed282SShri Abhyankar  */
4362b4ed282SShri Abhyankar #undef __FUNCT__
4372b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
4382b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
4392b4ed282SShri Abhyankar {
4402b4ed282SShri Abhyankar   PetscErrorCode ierr;
4412b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
4422b4ed282SShri Abhyankar 
4432b4ed282SShri Abhyankar   PetscFunctionBegin;
444fa0ddf94SBarry Smith   ierr = SNESSetWorkVecs(snes,1);CHKERRQ(ierr);
4456cab3a1bSJed Brown   ierr = SNESSetUpMatrices(snes);CHKERRQ(ierr);
4462b4ed282SShri Abhyankar 
44708da532bSDmitry Karpeev   if (!snes->ops->computevariablebounds && snes->dm) {
448a201590fSDmitry Karpeev     PetscBool flag;
449a201590fSDmitry Karpeev     ierr = DMHasVariableBounds(snes->dm, &flag);CHKERRQ(ierr);
4501aa26658SKarl Rupp 
45108da532bSDmitry Karpeev     snes->ops->computevariablebounds = SNESVIDMComputeVariableBounds;
45208da532bSDmitry Karpeev   }
453a201590fSDmitry Karpeev   if (!snes->usersetbounds) {
454c2fc9fa9SBarry Smith     if (snes->ops->computevariablebounds) {
455c2fc9fa9SBarry Smith       if (!snes->xl) {ierr = VecDuplicate(snes->vec_sol,&snes->xl);CHKERRQ(ierr);}
456c2fc9fa9SBarry Smith       if (!snes->xu) {ierr = VecDuplicate(snes->vec_sol,&snes->xu);CHKERRQ(ierr);}
457c2fc9fa9SBarry Smith       ierr = (*snes->ops->computevariablebounds)(snes,snes->xl,snes->xu);CHKERRQ(ierr);
4581aa26658SKarl Rupp     } else if (!snes->xl && !snes->xu) {
4592176524cSBarry Smith       /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
460c2fc9fa9SBarry Smith       ierr = VecDuplicate(snes->vec_sol, &snes->xl);CHKERRQ(ierr);
461e270355aSBarry Smith       ierr = VecSet(snes->xl,PETSC_NINFINITY);CHKERRQ(ierr);
462c2fc9fa9SBarry Smith       ierr = VecDuplicate(snes->vec_sol, &snes->xu);CHKERRQ(ierr);
463e270355aSBarry Smith       ierr = VecSet(snes->xu,PETSC_INFINITY);CHKERRQ(ierr);
4642b4ed282SShri Abhyankar     } else {
4652b4ed282SShri Abhyankar       /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
4662b4ed282SShri Abhyankar       ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
467c2fc9fa9SBarry Smith       ierr = VecGetOwnershipRange(snes->xl,i_start+1,i_end+1);CHKERRQ(ierr);
468c2fc9fa9SBarry Smith       ierr = VecGetOwnershipRange(snes->xu,i_start+2,i_end+2);CHKERRQ(ierr);
4692b4ed282SShri 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]))
4702b4ed282SShri 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.");
4712b4ed282SShri Abhyankar     }
472a201590fSDmitry Karpeev   }
4732b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4742b4ed282SShri Abhyankar }
4752b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
4762176524cSBarry Smith #undef __FUNCT__
4772176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
4782176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
4792176524cSBarry Smith {
4802176524cSBarry Smith   PetscErrorCode ierr;
4812176524cSBarry Smith 
4822176524cSBarry Smith   PetscFunctionBegin;
483c2fc9fa9SBarry Smith   ierr                = VecDestroy(&snes->xl);CHKERRQ(ierr);
484c2fc9fa9SBarry Smith   ierr                = VecDestroy(&snes->xu);CHKERRQ(ierr);
4852d6615e8SDmitry Karpeev   snes->usersetbounds = PETSC_FALSE;
4862176524cSBarry Smith   PetscFunctionReturn(0);
4872176524cSBarry Smith }
4882176524cSBarry Smith 
4892b4ed282SShri Abhyankar /*
4902b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
4912b4ed282SShri Abhyankar    with SNESCreate_VI().
4922b4ed282SShri Abhyankar 
4932b4ed282SShri Abhyankar    Input Parameter:
4942b4ed282SShri Abhyankar .  snes - the SNES context
4952b4ed282SShri Abhyankar 
4962b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
4972b4ed282SShri Abhyankar  */
4982b4ed282SShri Abhyankar #undef __FUNCT__
4992b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
5002b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
5012b4ed282SShri Abhyankar {
5022b4ed282SShri Abhyankar   PetscErrorCode ierr;
5032b4ed282SShri Abhyankar 
5042b4ed282SShri Abhyankar   PetscFunctionBegin;
5052b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
5062b4ed282SShri Abhyankar 
5072b4ed282SShri Abhyankar   /* clear composed functions */
508bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSet_C",NULL);CHKERRQ(ierr);
509bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESLineSearchSetMonitor_C",NULL);CHKERRQ(ierr);
5102b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5112b4ed282SShri Abhyankar }
5127fe79bc4SShri Abhyankar 
5135559b345SBarry Smith #undef __FUNCT__
5145559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
5155559b345SBarry Smith /*@
5162b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
5172b4ed282SShri Abhyankar 
5182b4ed282SShri Abhyankar    Input Parameters:
5192b4ed282SShri Abhyankar .  snes - the SNES context.
5202b4ed282SShri Abhyankar .  xl   - lower bound.
5212b4ed282SShri Abhyankar .  xu   - upper bound.
5222b4ed282SShri Abhyankar 
5232b4ed282SShri Abhyankar    Notes:
5242b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
525e270355aSBarry Smith    PETSC_INFINITY and PETSC_NINFINITY respectively during SNESSetUp().
52684c105d7SBarry Smith 
5272bd2b0e6SSatish Balay    Level: advanced
5282bd2b0e6SSatish Balay 
5295559b345SBarry Smith @*/
53069c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
5312b4ed282SShri Abhyankar {
53261589011SJed Brown   PetscErrorCode ierr,(*f)(SNES,Vec,Vec);
5332b4ed282SShri Abhyankar 
5342b4ed282SShri Abhyankar   PetscFunctionBegin;
5352b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
5362b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
5372b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
5380005d66cSJed Brown   ierr = PetscObjectQueryFunction((PetscObject)snes,"SNESVISetVariableBounds_C",&f);CHKERRQ(ierr);
539f450aa47SBarry Smith   if (!f) {ierr = SNESSetType(snes,SNESVINEWTONRSLS);CHKERRQ(ierr);}
54061589011SJed Brown   ierr                = PetscUseMethod(snes,"SNESVISetVariableBounds_C",(SNES,Vec,Vec),(snes,xl,xu));CHKERRQ(ierr);
541a201590fSDmitry Karpeev   snes->usersetbounds = PETSC_TRUE;
54261589011SJed Brown   PetscFunctionReturn(0);
54361589011SJed Brown }
54461589011SJed Brown 
54561589011SJed Brown #undef __FUNCT__
54661589011SJed Brown #define __FUNCT__ "SNESVISetVariableBounds_VI"
54761589011SJed Brown PetscErrorCode SNESVISetVariableBounds_VI(SNES snes,Vec xl,Vec xu)
54861589011SJed Brown {
54961589011SJed Brown   PetscErrorCode    ierr;
55061589011SJed Brown   const PetscScalar *xxl,*xxu;
55161589011SJed Brown   PetscInt          i,n, cnt = 0;
55261589011SJed Brown 
55361589011SJed Brown   PetscFunctionBegin;
5540298fd71SBarry Smith   ierr = SNESGetFunction(snes,&snes->vec_func,NULL,NULL);CHKERRQ(ierr);
555a63bb30eSJed Brown   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() or SNESSetDM() first");
556077aedafSJed Brown   {
557077aedafSJed Brown     PetscInt xlN,xuN,N;
558077aedafSJed Brown     ierr = VecGetSize(xl,&xlN);CHKERRQ(ierr);
559077aedafSJed Brown     ierr = VecGetSize(xu,&xuN);CHKERRQ(ierr);
560077aedafSJed Brown     ierr = VecGetSize(snes->vec_func,&N);CHKERRQ(ierr);
561077aedafSJed Brown     if (xlN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xlN,N);
562077aedafSJed Brown     if (xuN != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xuN,N);
563077aedafSJed Brown   }
5642176524cSBarry Smith   ierr     = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
5652176524cSBarry Smith   ierr     = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
566c2fc9fa9SBarry Smith   ierr     = VecDestroy(&snes->xl);CHKERRQ(ierr);
567c2fc9fa9SBarry Smith   ierr     = VecDestroy(&snes->xu);CHKERRQ(ierr);
568c2fc9fa9SBarry Smith   snes->xl = xl;
569c2fc9fa9SBarry Smith   snes->xu = xu;
5706fd67740SBarry Smith   ierr     = VecGetLocalSize(xl,&n);CHKERRQ(ierr);
5716fd67740SBarry Smith   ierr     = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr);
5726fd67740SBarry Smith   ierr     = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr);
573e270355aSBarry Smith   for (i=0; i<n; i++) cnt += ((xxl[i] != PETSC_NINFINITY) || (xxu[i] != PETSC_INFINITY));
5741aa26658SKarl Rupp 
575ce94432eSBarry Smith   ierr = MPI_Allreduce(&cnt,&snes->ntruebounds,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)snes));CHKERRQ(ierr);
5766fd67740SBarry Smith   ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr);
5776fd67740SBarry Smith   ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr);
5782b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5792b4ed282SShri Abhyankar }
58092c02d66SPeter Brune 
5812b4ed282SShri Abhyankar #undef __FUNCT__
582c2fc9fa9SBarry Smith #define __FUNCT__ "SNESSetFromOptions_VI"
5838c34d3f5SBarry Smith PetscErrorCode SNESSetFromOptions_VI(PetscOptions *PetscOptionsObject,SNES snes)
5842b4ed282SShri Abhyankar {
5852b4ed282SShri Abhyankar   PetscErrorCode ierr;
5868afaa268SBarry Smith   PetscBool      flg = PETSC_FALSE;
587639ea3faSPeter Brune   SNESLineSearch linesearch;
5882b4ed282SShri Abhyankar 
5892b4ed282SShri Abhyankar   PetscFunctionBegin;
590e55864a3SBarry Smith   ierr = PetscOptionsHead(PetscOptionsObject,"SNES VI options");CHKERRQ(ierr);
591ffdf2a20SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","SNESMonitorResidual",flg,&flg,NULL);CHKERRQ(ierr);
592c2fc9fa9SBarry Smith   if (flg) {
593c2fc9fa9SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
5942b4ed282SShri Abhyankar   }
595*de34d3e9SBarry Smith   flg = PETSC_FALSE;
596ffdf2a20SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor_residual","Monitor residual all non-active variables; using zero for active constraints","SNESMonitorVIResidual",flg,&flg,NULL);CHKERRQ(ierr);
597ffdf2a20SBarry Smith   if (flg) {
598ffdf2a20SBarry Smith     ierr = SNESMonitorSet(snes,SNESVIMonitorResidual,PETSC_VIEWER_DRAW_(PetscObjectComm((PetscObject)snes)),NULL);CHKERRQ(ierr);
599ffdf2a20SBarry Smith   }
600639ea3faSPeter Brune   if (!snes->linesearch) {
6017601faf0SJed Brown     ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
602639ea3faSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
603639ea3faSPeter Brune     ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr);
604639ea3faSPeter Brune   }
605c2fc9fa9SBarry Smith   ierr = PetscOptionsTail();CHKERRQ(ierr);
606ed70e96aSJungho Lee   PetscFunctionReturn(0);
607ed70e96aSJungho Lee }
608