xref: /petsc/src/snes/impls/vi/vi.c (revision 4839bfe8be31aea3feb99d87e8d29f54373e0c10)
12b4ed282SShri Abhyankar 
2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/
3c6db04a5SJed Brown #include <../include/private/kspimpl.h>
4c6db04a5SJed Brown #include <../include/private/matimpl.h>
5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h>
6d0af7cd3SBarry Smith 
7d0af7cd3SBarry Smith #undef __FUNCT__
82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds"
92176524cSBarry Smith /*@C
102176524cSBarry Smith    SNESVISetComputeVariableBounds - Sets a function  that is called to compute the variable bounds
112176524cSBarry Smith 
122176524cSBarry Smith    Input parameter
132176524cSBarry Smith +  snes - the SNES context
142176524cSBarry Smith -  compute - computes the bounds
152176524cSBarry Smith 
162bd2b0e6SSatish Balay    Level: advanced
172176524cSBarry Smith 
18aab9d709SJed Brown @*/
1977cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec))
202176524cSBarry Smith {
212176524cSBarry Smith   PetscErrorCode   ierr;
222176524cSBarry Smith   SNES_VI          *vi;
232176524cSBarry Smith 
242176524cSBarry Smith   PetscFunctionBegin;
252176524cSBarry Smith   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
262176524cSBarry Smith   vi = (SNES_VI*)snes->data;
272176524cSBarry Smith   vi->computevariablebounds = compute;
282176524cSBarry Smith   PetscFunctionReturn(0);
292176524cSBarry Smith }
302176524cSBarry Smith 
312176524cSBarry Smith 
322176524cSBarry Smith #undef __FUNCT__
33ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS"
34d0af7cd3SBarry Smith /*
35ed70e96aSJungho Lee    SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables
36d0af7cd3SBarry Smith 
37d0af7cd3SBarry Smith    Input parameter
38d0af7cd3SBarry Smith .  snes - the SNES context
39d0af7cd3SBarry Smith .  X    - the snes solution vector
40d0af7cd3SBarry Smith 
41d0af7cd3SBarry Smith    Output parameter
42d0af7cd3SBarry Smith .  ISact - active set index set
43d0af7cd3SBarry Smith 
44d0af7cd3SBarry Smith  */
45ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
46d0af7cd3SBarry Smith {
47d0af7cd3SBarry Smith   PetscErrorCode   ierr;
48d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
49d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
50d0af7cd3SBarry Smith 
51d0af7cd3SBarry Smith   PetscFunctionBegin;
52d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
53d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
54d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
55d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
56d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
57d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
58d0af7cd3SBarry Smith   /* Compute inactive set size */
59d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
60d0af7cd3SBarry 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++;
61d0af7cd3SBarry Smith   }
62d0af7cd3SBarry Smith 
63d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
64d0af7cd3SBarry Smith 
65d0af7cd3SBarry Smith   /* Set inactive set indices */
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))) idx_act[i1++] = ilow+i;
68d0af7cd3SBarry Smith   }
69d0af7cd3SBarry Smith 
70d0af7cd3SBarry Smith    /* Create inactive set IS */
71d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
72d0af7cd3SBarry Smith 
73d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
74d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
75d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
76d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
77d0af7cd3SBarry Smith   PetscFunctionReturn(0);
78d0af7cd3SBarry Smith }
79d0af7cd3SBarry Smith 
803c0c59f3SBarry Smith /*
813c0c59f3SBarry Smith     Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors
823c0c59f3SBarry Smith   defined by the reduced space method.
833c0c59f3SBarry Smith 
843c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
853c0c59f3SBarry Smith 
86ed70e96aSJungho Lee <*/
873c0c59f3SBarry Smith typedef struct {
883c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
893c0c59f3SBarry Smith   IS             inactive;
903c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
913c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
923c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
934c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
943c0c59f3SBarry Smith } DM_SNESVI;
953c0c59f3SBarry Smith 
96d0af7cd3SBarry Smith #undef __FUNCT__
974dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
984dcab191SBarry Smith /*
994dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
1004dcab191SBarry Smith 
1014dcab191SBarry Smith */
1024dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
1034dcab191SBarry Smith {
1044dcab191SBarry Smith   PetscErrorCode          ierr;
1054dcab191SBarry Smith   PetscContainer          isnes;
1063c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
1074dcab191SBarry Smith 
1084dcab191SBarry Smith   PetscFunctionBegin;
1094dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1104dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
1114dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
1124dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
1134dcab191SBarry Smith   PetscFunctionReturn(0);
1144dcab191SBarry Smith }
1154dcab191SBarry Smith 
1164dcab191SBarry Smith #undef __FUNCT__
117d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
118d0af7cd3SBarry Smith /*
119d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
120d0af7cd3SBarry Smith 
121d0af7cd3SBarry Smith */
122d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
123d0af7cd3SBarry Smith {
124d0af7cd3SBarry Smith   PetscErrorCode          ierr;
125d0af7cd3SBarry Smith   PetscContainer          isnes;
1263c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
127d0af7cd3SBarry Smith   Mat                     interp;
128d0af7cd3SBarry Smith 
129d0af7cd3SBarry Smith   PetscFunctionBegin;
130d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1314c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
132d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
133d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1344c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
135d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
136d0af7cd3SBarry Smith 
137d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1384dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
139d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
14000ac8be1SBarry Smith   *vec = 0;
141d0af7cd3SBarry Smith   PetscFunctionReturn(0);
142d0af7cd3SBarry Smith }
143d0af7cd3SBarry Smith 
1449ce20c35SJungho Lee extern PetscErrorCode  DMSetVI(DM,IS);
145d0af7cd3SBarry Smith 
146d0af7cd3SBarry Smith #undef __FUNCT__
147d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
148d0af7cd3SBarry Smith /*
149d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
150d0af7cd3SBarry Smith 
151d0af7cd3SBarry Smith */
152d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
153d0af7cd3SBarry Smith {
154d0af7cd3SBarry Smith   PetscErrorCode          ierr;
155d0af7cd3SBarry Smith   PetscContainer          isnes;
1563c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
1579ce20c35SJungho Lee   Vec                     finemarked,coarsemarked;
158d0af7cd3SBarry Smith   IS                      inactive;
159d0af7cd3SBarry Smith   VecScatter              inject;
1609ce20c35SJungho Lee   const PetscInt          *index;
1619ce20c35SJungho Lee   PetscInt                n,k,cnt = 0,rstart,*coarseindex;
1629ce20c35SJungho Lee   PetscScalar             *marked;
163d0af7cd3SBarry Smith 
164d0af7cd3SBarry Smith   PetscFunctionBegin;
165d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1664c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
167d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
168d0af7cd3SBarry Smith 
169298cc208SBarry Smith   /* get the original coarsen */
170d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
171298cc208SBarry Smith 
1723c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1733c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1743c0c59f3SBarry Smith 
175298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
176298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
177298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
1789ce20c35SJungho Lee   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
1799ce20c35SJungho Lee   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
1809ce20c35SJungho Lee 
1819ce20c35SJungho Lee   /*
1829ce20c35SJungho Lee      fill finemarked with locations of inactive points
1839ce20c35SJungho Lee   */
1849ce20c35SJungho Lee   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
1859ce20c35SJungho Lee   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
1869ce20c35SJungho Lee   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
1879ce20c35SJungho Lee   for (k=0;k<n;k++){
1889ce20c35SJungho Lee       ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
1899ce20c35SJungho Lee   }
1909ce20c35SJungho Lee   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
1919ce20c35SJungho Lee   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
1929ce20c35SJungho Lee 
193d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
1949ce20c35SJungho Lee   ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1959ce20c35SJungho Lee   ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
1979ce20c35SJungho Lee 
1989ce20c35SJungho Lee   /*
1999ce20c35SJungho Lee      create index set list of coarse inactive points from coarsemarked
2009ce20c35SJungho Lee   */
2019ce20c35SJungho Lee   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
2029ce20c35SJungho Lee   ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr);
2039ce20c35SJungho Lee   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
2049ce20c35SJungho Lee   for (k=0; k<n; k++) {
205ff207688SJed Brown     if (marked[k] != 0.0) cnt++;
2069ce20c35SJungho Lee   }
2079ce20c35SJungho Lee   ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr);
2089ce20c35SJungho Lee   cnt  = 0;
2099ce20c35SJungho Lee   for (k=0; k<n; k++) {
210ff207688SJed Brown     if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart;
2119ce20c35SJungho Lee   }
2129ce20c35SJungho Lee   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
2139ce20c35SJungho Lee   ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
2149ce20c35SJungho Lee 
215298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
216298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
2179ce20c35SJungho Lee   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
2189ce20c35SJungho Lee 
2199ce20c35SJungho Lee   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
2209ce20c35SJungho Lee   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
2213c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
222d0af7cd3SBarry Smith   PetscFunctionReturn(0);
223d0af7cd3SBarry Smith }
224d0af7cd3SBarry Smith 
225d0af7cd3SBarry Smith #undef __FUNCT__
2263c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2273c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
228d0af7cd3SBarry Smith {
229d0af7cd3SBarry Smith   PetscErrorCode ierr;
230d0af7cd3SBarry Smith 
231d0af7cd3SBarry Smith   PetscFunctionBegin;
2324c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2334c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2344c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2354c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
23600ac8be1SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
23700ac8be1SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
23800ac8be1SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
2394c661befSBarry Smith 
240d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
241d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
242d0af7cd3SBarry Smith   PetscFunctionReturn(0);
243d0af7cd3SBarry Smith }
244d0af7cd3SBarry Smith 
245d0af7cd3SBarry Smith #undef __FUNCT__
246d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
247d0af7cd3SBarry Smith /*
248d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
249d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
250d0af7cd3SBarry Smith 
251d0af7cd3SBarry Smith */
2529ce20c35SJungho Lee PetscErrorCode  DMSetVI(DM dm,IS inactive)
253d0af7cd3SBarry Smith {
254d0af7cd3SBarry Smith   PetscErrorCode          ierr;
255d0af7cd3SBarry Smith   PetscContainer          isnes;
2563c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
257d0af7cd3SBarry Smith 
258d0af7cd3SBarry Smith   PetscFunctionBegin;
2594dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
2601c0a9e84SBarry Smith 
261d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
262d0af7cd3SBarry Smith 
263d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
264d0af7cd3SBarry Smith   if (!isnes) {
265d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2663c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2673c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
268d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
269d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2703c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
271d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
272d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
273d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
274d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
275298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2764dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
277d0af7cd3SBarry Smith   } else {
278d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
279d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
280d0af7cd3SBarry Smith   }
2814dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2824dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
283d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2841a223a97SBarry Smith   dmsnesvi->dm       = dm;
285d0af7cd3SBarry Smith   PetscFunctionReturn(0);
286d0af7cd3SBarry Smith }
287d0af7cd3SBarry Smith 
2884c661befSBarry Smith #undef __FUNCT__
2894c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2904c661befSBarry Smith /*
2914c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2924c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2934c661befSBarry Smith */
2944c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2954c661befSBarry Smith {
2964c661befSBarry Smith   PetscErrorCode          ierr;
2974c661befSBarry Smith 
2984c661befSBarry Smith   PetscFunctionBegin;
2994c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
3004c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
3014c661befSBarry Smith   PetscFunctionReturn(0);
3024c661befSBarry Smith }
3034c661befSBarry Smith 
3043c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
3052b4ed282SShri Abhyankar 
3069308c137SBarry Smith #undef __FUNCT__
3079308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3087087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3099308c137SBarry Smith {
3109308c137SBarry Smith   PetscErrorCode    ierr;
3119308c137SBarry Smith   SNES_VI            *vi = (SNES_VI*)snes->data;
312649052a6SBarry Smith   PetscViewer        viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);
3139308c137SBarry Smith   const PetscScalar  *x,*xl,*xu,*f;
3146fd67740SBarry Smith   PetscInt           i,n,act[2] = {0,0},fact[2],N;
3156a9e2d46SJungho Lee   /* Number of components that actually hit the bounds (c.f. active variables) */
3166a9e2d46SJungho Lee   PetscInt           act_bound[2] = {0,0},fact_bound[2];
3179308c137SBarry Smith   PetscReal          rnorm,fnorm;
3189308c137SBarry Smith 
3199308c137SBarry Smith   PetscFunctionBegin;
3209308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3216fd67740SBarry Smith   ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr);
3229308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3239308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3249308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3253f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3269308c137SBarry Smith 
3279308c137SBarry Smith   rnorm = 0.0;
3289308c137SBarry Smith   for (i=0; i<n; i++) {
32910f5ae6bSBarry 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]);
330e400df7aSBarry Smith     else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++;
331e400df7aSBarry Smith     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++;
332e400df7aSBarry Smith     else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here");
3339308c137SBarry Smith   }
3346a9e2d46SJungho Lee 
3356a9e2d46SJungho Lee   for (i=0; i<n; i++) {
3366a9e2d46SJungho Lee     if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++;
3376a9e2d46SJungho Lee     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++;
3386a9e2d46SJungho Lee   }
3393f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3409308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3419308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3429308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
343d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
34421a4c9b1SBarry Smith   ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3456a9e2d46SJungho Lee   ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
346f137e44dSBarry Smith   fnorm = PetscSqrtReal(fnorm);
3476fd67740SBarry Smith 
348649052a6SBarry Smith   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
349*4839bfe8SBarry Smith   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),((double)(fact[0]+fact[1]))/((double)vi->ntruebounds));CHKERRQ(ierr);
3506a9e2d46SJungho Lee 
351649052a6SBarry Smith   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
3529308c137SBarry Smith   PetscFunctionReturn(0);
3539308c137SBarry Smith }
3549308c137SBarry Smith 
3552b4ed282SShri Abhyankar /*
3562b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3572b4ed282SShri 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
3582b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3592b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3602b4ed282SShri Abhyankar */
3612b4ed282SShri Abhyankar #undef __FUNCT__
3622b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
363ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3642b4ed282SShri Abhyankar {
3652b4ed282SShri Abhyankar   PetscReal      a1;
3662b4ed282SShri Abhyankar   PetscErrorCode ierr;
367ace3abfcSBarry Smith   PetscBool     hastranspose;
3682b4ed282SShri Abhyankar 
3692b4ed282SShri Abhyankar   PetscFunctionBegin;
3702b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3712b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3722b4ed282SShri Abhyankar   if (hastranspose) {
3732b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3742b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3752b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
376*4839bfe8SBarry Smith     ierr = PetscInfo1(snes,"|| J^T F|| %g near zero implies found a local minimum\n",(double)(a1/fnorm));CHKERRQ(ierr);
3772b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3782b4ed282SShri Abhyankar   } else {
3792b4ed282SShri Abhyankar     Vec         work;
3802b4ed282SShri Abhyankar     PetscScalar result;
3812b4ed282SShri Abhyankar     PetscReal   wnorm;
3822b4ed282SShri Abhyankar 
3832b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3842b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3852b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3862b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3872b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3886bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3892b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
390*4839bfe8SBarry Smith     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %g near zero implies found a local minimum\n",(double)a1);CHKERRQ(ierr);
3912b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3922b4ed282SShri Abhyankar   }
3932b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3942b4ed282SShri Abhyankar }
3952b4ed282SShri Abhyankar 
3962b4ed282SShri Abhyankar /*
3972b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3982b4ed282SShri Abhyankar */
3992b4ed282SShri Abhyankar #undef __FUNCT__
4002b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
4012b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
4022b4ed282SShri Abhyankar {
4032b4ed282SShri Abhyankar   PetscReal      a1,a2;
4042b4ed282SShri Abhyankar   PetscErrorCode ierr;
405ace3abfcSBarry Smith   PetscBool     hastranspose;
4062b4ed282SShri Abhyankar 
4072b4ed282SShri Abhyankar   PetscFunctionBegin;
4082b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
4092b4ed282SShri Abhyankar   if (hastranspose) {
4102b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
4112b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
4122b4ed282SShri Abhyankar 
4132b4ed282SShri Abhyankar     /* Compute || J^T W|| */
4142b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
4152b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
4162b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
4172b4ed282SShri Abhyankar     if (a1 != 0.0) {
418*4839bfe8SBarry Smith       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %g near zero implies inconsistent rhs\n",(double)(a2/a1));CHKERRQ(ierr);
4192b4ed282SShri Abhyankar     }
4202b4ed282SShri Abhyankar   }
4212b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4222b4ed282SShri Abhyankar }
4232b4ed282SShri Abhyankar 
4242b4ed282SShri Abhyankar /*
4252b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4262b4ed282SShri Abhyankar 
4272b4ed282SShri Abhyankar   Notes:
4282b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4292b4ed282SShri Abhyankar   merit < abstol
4302b4ed282SShri Abhyankar   merit < rtol*merit_initial
4312b4ed282SShri Abhyankar */
4322b4ed282SShri Abhyankar #undef __FUNCT__
4332b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4347fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4352b4ed282SShri Abhyankar {
4362b4ed282SShri Abhyankar   PetscErrorCode ierr;
4372b4ed282SShri Abhyankar 
4382b4ed282SShri Abhyankar   PetscFunctionBegin;
4392b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4402b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4412b4ed282SShri Abhyankar 
4422b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4432b4ed282SShri Abhyankar 
4442b4ed282SShri Abhyankar   if (!it) {
4452b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4467fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4472b4ed282SShri Abhyankar   }
4487fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4492b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4502b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4517fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
452*4839bfe8SBarry Smith     ierr = PetscInfo2(snes,"Converged due to function norm %g < %g\n",(double)fnorm,(double)snes->abstol);CHKERRQ(ierr);
4532b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4542b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4552b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4562b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4572b4ed282SShri Abhyankar   }
4582b4ed282SShri Abhyankar 
4592b4ed282SShri Abhyankar   if (it && !*reason) {
4607fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
461*4839bfe8SBarry Smith       ierr = PetscInfo2(snes,"Converged due to function norm %g < %g (relative tolerance)\n",(double)fnorm,(double)snes->ttol);CHKERRQ(ierr);
4622b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4632b4ed282SShri Abhyankar     }
4642b4ed282SShri Abhyankar   }
4652b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4662b4ed282SShri Abhyankar }
4672b4ed282SShri Abhyankar 
4682b4ed282SShri Abhyankar /*
4692b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4702b4ed282SShri Abhyankar 
4712b4ed282SShri Abhyankar   Input Parameter:
4722b4ed282SShri Abhyankar . phi - the semismooth function
4732b4ed282SShri Abhyankar 
4742b4ed282SShri Abhyankar   Output Parameter:
4752b4ed282SShri Abhyankar . merit - the merit function
4762b4ed282SShri Abhyankar . phinorm - ||phi||
4772b4ed282SShri Abhyankar 
4782b4ed282SShri Abhyankar   Notes:
4792b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4802b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4812b4ed282SShri Abhyankar */
4822b4ed282SShri Abhyankar #undef __FUNCT__
4832b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4842b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4852b4ed282SShri Abhyankar {
4862b4ed282SShri Abhyankar   PetscErrorCode ierr;
4872b4ed282SShri Abhyankar 
4882b4ed282SShri Abhyankar   PetscFunctionBegin;
4895f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4905f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4912b4ed282SShri Abhyankar 
4922b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4932b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4942b4ed282SShri Abhyankar }
4952b4ed282SShri Abhyankar 
4967f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4974c21c6cdSBarry Smith {
498bec29f96SSatish Balay   return a + b - PetscSqrtScalar(a*a + b*b);
4994c21c6cdSBarry Smith }
5004c21c6cdSBarry Smith 
5017f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
5024c21c6cdSBarry Smith {
503bec29f96SSatish Balay   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ PetscSqrtScalar(a*a + b*b);
5045559b345SBarry Smith   else return .5;
5054c21c6cdSBarry Smith }
5064c21c6cdSBarry Smith 
5072b4ed282SShri Abhyankar /*
5081f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
5092b4ed282SShri Abhyankar 
5102b4ed282SShri Abhyankar    Input Parameters:
5112b4ed282SShri Abhyankar .  snes - the SNES context
5122b4ed282SShri Abhyankar .  x - current iterate
5132b4ed282SShri Abhyankar .  functx - user defined function context
5142b4ed282SShri Abhyankar 
5152b4ed282SShri Abhyankar    Output Parameters:
5162b4ed282SShri Abhyankar .  phi - Semismooth function
5172b4ed282SShri Abhyankar 
5182b4ed282SShri Abhyankar */
5192b4ed282SShri Abhyankar #undef __FUNCT__
5201f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5211f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5222b4ed282SShri Abhyankar {
5232b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5242b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5252b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5264c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5272b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5282b4ed282SShri Abhyankar 
5292b4ed282SShri Abhyankar   PetscFunctionBegin;
5302b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5312b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5322b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5332b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5342b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5352b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5362b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5372b4ed282SShri Abhyankar 
5382b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
53910f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5404c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
54110f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5424c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
54310f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5444c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5455559b345SBarry Smith     } else if (l[i] == u[i]) {
5462b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5475559b345SBarry Smith     } else {                                                /* both bounds on variable */
5484c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5492b4ed282SShri Abhyankar     }
5502b4ed282SShri Abhyankar   }
5512b4ed282SShri Abhyankar 
5522b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5532b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5542b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5552b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5562b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5572b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5582b4ed282SShri Abhyankar }
5592b4ed282SShri Abhyankar 
5602b4ed282SShri Abhyankar /*
561a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
562a79edbefSShri Abhyankar                                           the semismooth jacobian.
5632b4ed282SShri Abhyankar */
5642b4ed282SShri Abhyankar #undef __FUNCT__
565a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
566a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5672b4ed282SShri Abhyankar {
5682b4ed282SShri Abhyankar   PetscErrorCode ierr;
5692b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5704c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5712b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5722b4ed282SShri Abhyankar 
5732b4ed282SShri Abhyankar   PetscFunctionBegin;
5742b4ed282SShri Abhyankar 
5752b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5762b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5772b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5782b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
579a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
580a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5812b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5824c21c6cdSBarry Smith 
5832b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
58410f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5854c21c6cdSBarry Smith       da[i] = 0;
5862b4ed282SShri Abhyankar       db[i] = 1;
58710f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5884c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5894c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
59010f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5915559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5925559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5935559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5944c21c6cdSBarry Smith       da[i] = 1;
5952b4ed282SShri Abhyankar       db[i] = 0;
5965559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5974c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5984c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5994c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
6004c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
6014c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
6024c21c6cdSBarry Smith       db[i] = db1*db2;
6032b4ed282SShri Abhyankar     }
6042b4ed282SShri Abhyankar   }
6055559b345SBarry Smith 
6062b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
6072b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
6082b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
6092b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
610a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
611a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
612a79edbefSShri Abhyankar   PetscFunctionReturn(0);
613a79edbefSShri Abhyankar }
614a79edbefSShri Abhyankar 
615a79edbefSShri Abhyankar /*
616a79edbefSShri Abhyankar    SNESVIComputeJacobian - Computes the jacobian of the semismooth function.The Jacobian for the semismooth function is an element of the B-subdifferential of the Fischer-Burmeister function for complementarity problems.
617a79edbefSShri Abhyankar 
618a79edbefSShri Abhyankar    Input Parameters:
619a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
620a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
621a79edbefSShri Abhyankar 
622a79edbefSShri Abhyankar    Output Parameters:
623a79edbefSShri Abhyankar .  jac      - semismooth jacobian
624a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
625a79edbefSShri Abhyankar 
626a79edbefSShri Abhyankar    Notes:
627a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
628a79edbefSShri Abhyankar    jac = Da + Db*jacfun
629a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
630a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
631a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
632a79edbefSShri Abhyankar */
633a79edbefSShri Abhyankar #undef __FUNCT__
634a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
635a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
636a79edbefSShri Abhyankar {
637a79edbefSShri Abhyankar   PetscErrorCode ierr;
638a79edbefSShri Abhyankar 
6392b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
640a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
641a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
642a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
643a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
644a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6452b4ed282SShri Abhyankar   }
6462b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6472b4ed282SShri Abhyankar }
6482b4ed282SShri Abhyankar 
6492b4ed282SShri Abhyankar /*
650ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
651ee657d29SShri Abhyankar 
652ee657d29SShri Abhyankar    Input Parameters:
653ee657d29SShri Abhyankar    phi - semismooth function.
654ee657d29SShri Abhyankar    H   - semismooth jacobian
655ee657d29SShri Abhyankar 
656ee657d29SShri Abhyankar    Output Parameters:
657ee657d29SShri Abhyankar    dpsi - merit function gradient
658ee657d29SShri Abhyankar 
659ee657d29SShri Abhyankar    Notes:
660ee657d29SShri Abhyankar   The merit function gradient is computed as follows
661ee657d29SShri Abhyankar         dpsi = H^T*phi
662ee657d29SShri Abhyankar */
663ee657d29SShri Abhyankar #undef __FUNCT__
664ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
665ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
666ee657d29SShri Abhyankar {
667ee657d29SShri Abhyankar   PetscErrorCode ierr;
668ee657d29SShri Abhyankar 
669ee657d29SShri Abhyankar   PetscFunctionBegin;
6705f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
671ee657d29SShri Abhyankar   PetscFunctionReturn(0);
672ee657d29SShri Abhyankar }
673ee657d29SShri Abhyankar 
674c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
675c1a5e521SShri Abhyankar /*
676c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
677c1a5e521SShri Abhyankar 
678c1a5e521SShri Abhyankar    Input Parameters:
679c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
680c1a5e521SShri Abhyankar 
681c1a5e521SShri Abhyankar    Output Parameters:
682c1a5e521SShri Abhyankar .  X - Bound projected X
683c1a5e521SShri Abhyankar 
684c1a5e521SShri Abhyankar */
685c1a5e521SShri Abhyankar 
686c1a5e521SShri Abhyankar #undef __FUNCT__
687c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
688c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
689c1a5e521SShri Abhyankar {
690c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
691c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
692c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
693c1a5e521SShri Abhyankar   PetscScalar       *x;
694c1a5e521SShri Abhyankar   PetscInt          i,n;
695c1a5e521SShri Abhyankar 
696c1a5e521SShri Abhyankar   PetscFunctionBegin;
697c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
698c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
699c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
700c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
701c1a5e521SShri Abhyankar 
702c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
70310f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
70410f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
705c1a5e521SShri Abhyankar   }
706c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
707c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
708c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
709c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
710c1a5e521SShri Abhyankar }
711c1a5e521SShri Abhyankar 
7122b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
7132b4ed282SShri Abhyankar 
7142b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
7152b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
7162b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
7172b4ed282SShri Abhyankar      respectively.
7182b4ed282SShri Abhyankar 
7192b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7202b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7212b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7222b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7232b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7242b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7252b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7262b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7272b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7282b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7292b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7302b4ed282SShri Abhyankar      for all nonlinear solvers.
7312b4ed282SShri Abhyankar 
7322b4ed282SShri Abhyankar      Another key routine is:
7332b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7342b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7352b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7362b4ed282SShri Abhyankar      SNESSolve() if necessary.
7372b4ed282SShri Abhyankar 
7382b4ed282SShri Abhyankar      Additional basic routines are:
7392b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7402b4ed282SShri Abhyankar                                       have actually been used.
7412b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7422b4ed282SShri Abhyankar      SNESView().
7432b4ed282SShri Abhyankar 
7442b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7452b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7462b4ed282SShri Abhyankar      above description applies to these categories also.
7472b4ed282SShri Abhyankar 
7482b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7492b4ed282SShri Abhyankar /*
75069c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7512b4ed282SShri Abhyankar    method using a line search.
7522b4ed282SShri Abhyankar 
7532b4ed282SShri Abhyankar    Input Parameters:
7542b4ed282SShri Abhyankar .  snes - the SNES context
7552b4ed282SShri Abhyankar 
7562b4ed282SShri Abhyankar    Output Parameter:
7572b4ed282SShri Abhyankar .  outits - number of iterations until termination
7582b4ed282SShri Abhyankar 
7592b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7602b4ed282SShri Abhyankar 
7612b4ed282SShri Abhyankar    Notes:
7622b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
76351defd01SShri Abhyankar    line search. The default line search does not do any line seach
76451defd01SShri Abhyankar    but rather takes a full newton step.
7652b4ed282SShri Abhyankar */
7662b4ed282SShri Abhyankar #undef __FUNCT__
76769c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
76869c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7692b4ed282SShri Abhyankar {
7702b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7712b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7722b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7733b336b49SShri Abhyankar   PetscBool          lssucceed;
7742b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7752b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7762b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7772b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7782b4ed282SShri Abhyankar 
7792b4ed282SShri Abhyankar   PetscFunctionBegin;
7809ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7819ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7829ce7406fSBarry Smith 
7832b4ed282SShri Abhyankar   snes->numFailures            = 0;
7842b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7852b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7862b4ed282SShri Abhyankar 
7872b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7882b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7892b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7902b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7912b4ed282SShri Abhyankar   G		= snes->work[1];
7922b4ed282SShri Abhyankar   W		= snes->work[2];
7932b4ed282SShri Abhyankar 
7942b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7952b4ed282SShri Abhyankar   snes->iter = 0;
7962b4ed282SShri Abhyankar   snes->norm = 0.0;
7972b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7982b4ed282SShri Abhyankar 
7997fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
8002b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar   if (snes->domainerror) {
8022b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8039ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8042b4ed282SShri Abhyankar     PetscFunctionReturn(0);
8052b4ed282SShri Abhyankar   }
8062b4ed282SShri Abhyankar    /* Compute Merit function */
8072b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
8082b4ed282SShri Abhyankar 
8092b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
8102b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
81162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
8122b4ed282SShri Abhyankar 
8132b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8142b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
8152b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8162b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
8177a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8182b4ed282SShri Abhyankar 
8192b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8202b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8212b4ed282SShri Abhyankar   /* test convergence */
8222b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8239ce7406fSBarry Smith   if (snes->reason) {
8249ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8259ce7406fSBarry Smith     PetscFunctionReturn(0);
8269ce7406fSBarry Smith   }
8272b4ed282SShri Abhyankar 
8282b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8292b4ed282SShri Abhyankar 
8302b4ed282SShri Abhyankar     /* Call general purpose update function */
8312b4ed282SShri Abhyankar     if (snes->ops->update) {
8322b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8332b4ed282SShri Abhyankar     }
8342b4ed282SShri Abhyankar 
8352b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
836a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8372b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
838a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
839a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
840a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
841a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
842ee657d29SShri Abhyankar     /* Compute the merit function gradient */
843ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8442b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8452b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8462b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8473b336b49SShri Abhyankar 
8483b336b49SShri Abhyankar     if (kspreason < 0) {
8492b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8502b4ed282SShri Abhyankar         ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
8512b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8522b4ed282SShri Abhyankar         break;
8532b4ed282SShri Abhyankar       }
8542b4ed282SShri Abhyankar     }
8552b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8562b4ed282SShri Abhyankar     snes->linear_its += lits;
8572b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8582b4ed282SShri Abhyankar     /*
8590661309fSPeter Brune     if (snes->ops->precheckstep) {
860ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8610661309fSPeter Brune       ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr);
8622b4ed282SShri Abhyankar     }
8632b4ed282SShri Abhyankar 
8642b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8652b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8662b4ed282SShri Abhyankar     }
8672b4ed282SShri Abhyankar     */
8682b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8692b4ed282SShri Abhyankar          Y <- X - lambda*Y
8702b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8712b4ed282SShri Abhyankar     */
8722b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8732b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8740661309fSPeter Brune     ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,vi->phi,Y,vi->phinorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
875*4839bfe8SBarry Smith     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)vi->phinorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
8762b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8772b4ed282SShri Abhyankar     if (snes->domainerror) {
8782b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8799ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8802b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8812b4ed282SShri Abhyankar     }
8822b4ed282SShri Abhyankar     if (!lssucceed) {
8832b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
884ace3abfcSBarry Smith 	PetscBool ismin;
8852b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8862b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8872b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8882b4ed282SShri Abhyankar         break;
8892b4ed282SShri Abhyankar       }
8902b4ed282SShri Abhyankar     }
8912b4ed282SShri Abhyankar     /* Update function and solution vectors */
8922b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8932b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8942b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8952b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8962b4ed282SShri Abhyankar     /* Monitor convergence */
8972b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8982b4ed282SShri Abhyankar     snes->iter = i+1;
8992b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
9002b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
9012b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
9027a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
9032b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
9042b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
9052b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
9062b4ed282SShri Abhyankar     if (snes->reason) break;
9072b4ed282SShri Abhyankar   }
9082b4ed282SShri Abhyankar   if (i == maxits) {
9092b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
9102b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
9112b4ed282SShri Abhyankar   }
9129ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
9132b4ed282SShri Abhyankar   PetscFunctionReturn(0);
9142b4ed282SShri Abhyankar }
91569c03620SShri Abhyankar 
91669c03620SShri Abhyankar #undef __FUNCT__
917693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
918693ddf92SShri Abhyankar /*
919693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
920693ddf92SShri Abhyankar 
921693ddf92SShri Abhyankar    Input parameter
922693ddf92SShri Abhyankar .  snes - the SNES context
923693ddf92SShri Abhyankar .  X    - the snes solution vector
924693ddf92SShri Abhyankar .  F    - the nonlinear function vector
925693ddf92SShri Abhyankar 
926693ddf92SShri Abhyankar    Output parameter
927693ddf92SShri Abhyankar .  ISact - active set index set
928693ddf92SShri Abhyankar  */
929693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
930d950fb63SShri Abhyankar {
931d950fb63SShri Abhyankar   PetscErrorCode   ierr;
932693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
933693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
934693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
935693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
936d950fb63SShri Abhyankar 
937d950fb63SShri Abhyankar   PetscFunctionBegin;
938d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
939d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
940fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
941fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
942fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
943fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
944693ddf92SShri Abhyankar   /* Compute active set size */
945d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
946e6337399SBarry Smith     if (!vi->ignorefunctionsign) {
94710f5ae6bSBarry 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++;
948e6337399SBarry Smith     } else {
949e6337399SBarry Smith       if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8  && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) nloc_isact++;
950e6337399SBarry Smith     }
951d950fb63SShri Abhyankar   }
952693ddf92SShri Abhyankar 
953d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
954d950fb63SShri Abhyankar 
955693ddf92SShri Abhyankar   /* Set active set indices */
956d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
957e6337399SBarry Smith     if (!vi->ignorefunctionsign) {
95810f5ae6bSBarry 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;
959e6337399SBarry Smith     } else {
960e6337399SBarry Smith       if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8  && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) idx_act[i1++] = ilow+i;
961e6337399SBarry Smith     }
962d950fb63SShri Abhyankar   }
963d950fb63SShri Abhyankar 
964693ddf92SShri Abhyankar    /* Create active set IS */
96562298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
966d950fb63SShri Abhyankar 
967fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
968fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
969fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
970fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
971d950fb63SShri Abhyankar   PetscFunctionReturn(0);
972d950fb63SShri Abhyankar }
973d950fb63SShri Abhyankar 
974693ddf92SShri Abhyankar #undef __FUNCT__
975693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
976693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
977693ddf92SShri Abhyankar {
978693ddf92SShri Abhyankar   PetscErrorCode     ierr;
979693ddf92SShri Abhyankar 
980693ddf92SShri Abhyankar   PetscFunctionBegin;
981693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
982693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
983693ddf92SShri Abhyankar   PetscFunctionReturn(0);
984693ddf92SShri Abhyankar }
985693ddf92SShri Abhyankar 
986dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
987dbd914b8SShri Abhyankar #undef __FUNCT__
988fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
989fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
990dbd914b8SShri Abhyankar {
991dbd914b8SShri Abhyankar   PetscErrorCode ierr;
992dbd914b8SShri Abhyankar   Vec            v;
993dbd914b8SShri Abhyankar 
994dbd914b8SShri Abhyankar   PetscFunctionBegin;
995dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
996dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
997dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
998dbd914b8SShri Abhyankar   *newv = v;
999dbd914b8SShri Abhyankar 
1000dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
1001dbd914b8SShri Abhyankar }
1002dbd914b8SShri Abhyankar 
1003732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
1004732bb160SShri Abhyankar #undef __FUNCT__
1005732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
1006732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
1007732bb160SShri Abhyankar {
1008732bb160SShri Abhyankar   PetscErrorCode         ierr;
1009d0af7cd3SBarry Smith   KSP                    snesksp;
1010dbd914b8SShri Abhyankar 
1011732bb160SShri Abhyankar   PetscFunctionBegin;
1012732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
1013d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
1014c2efdce3SBarry Smith 
1015c2efdce3SBarry Smith   /*
1016d0af7cd3SBarry Smith   KSP                    kspnew;
1017d0af7cd3SBarry Smith   PC                     pcnew;
1018d0af7cd3SBarry Smith   const MatSolverPackage stype;
1019d0af7cd3SBarry Smith 
1020c2efdce3SBarry Smith 
1021732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
1022732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
1023732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
1024732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
1025732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1026732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1027732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1028732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1029732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1030732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1031732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10326bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1033732bb160SShri Abhyankar   snes->ksp = kspnew;
1034732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1035d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1036732bb160SShri Abhyankar   PetscFunctionReturn(0);
1037732bb160SShri Abhyankar }
103869c03620SShri Abhyankar 
103969c03620SShri Abhyankar 
1040fe835674SShri Abhyankar #undef __FUNCT__
1041fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
104210f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1043fe835674SShri Abhyankar {
1044fe835674SShri Abhyankar   PetscErrorCode    ierr;
1045fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1046fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1047fe835674SShri Abhyankar   PetscInt          i,n;
1048fe835674SShri Abhyankar   PetscReal         rnorm;
1049fe835674SShri Abhyankar 
1050fe835674SShri Abhyankar   PetscFunctionBegin;
1051fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1052fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1053fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1054fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1055fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1056fe835674SShri Abhyankar   rnorm = 0.0;
1057e007de34SBarry Smith   if (!vi->ignorefunctionsign) {
1058fe835674SShri Abhyankar     for (i=0; i<n; i++) {
105910f5ae6bSBarry 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]);
1060fe835674SShri Abhyankar     }
1061e007de34SBarry Smith   } else {
1062e007de34SBarry Smith     for (i=0; i<n; i++) {
1063e007de34SBarry Smith       if ((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8) && (PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) rnorm += PetscRealPart(PetscConj(f[i])*f[i]);
1064e007de34SBarry Smith     }
1065e007de34SBarry Smith   }
1066fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1067fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1068fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1069fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1070d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
107162d1f40fSBarry Smith   *fnorm = PetscSqrtReal(*fnorm);
1072fe835674SShri Abhyankar   PetscFunctionReturn(0);
1073fe835674SShri Abhyankar }
1074fe835674SShri Abhyankar 
1075fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1076c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1077c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1078d950fb63SShri Abhyankar #undef __FUNCT__
1079d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1080d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1081d950fb63SShri Abhyankar {
1082d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1083d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1084abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1085d950fb63SShri Abhyankar   PetscBool         lssucceed;
1086d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1087fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1088d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1089d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1090d950fb63SShri Abhyankar 
1091d950fb63SShri Abhyankar   PetscFunctionBegin;
1092d950fb63SShri Abhyankar   snes->numFailures            = 0;
1093d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1094d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1095d950fb63SShri Abhyankar 
1096d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1097d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1098d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1099d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1100d950fb63SShri Abhyankar   G		= snes->work[1];
1101d950fb63SShri Abhyankar   W		= snes->work[2];
1102d950fb63SShri Abhyankar 
1103d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1104d950fb63SShri Abhyankar   snes->iter = 0;
1105d950fb63SShri Abhyankar   snes->norm = 0.0;
1106d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1107d950fb63SShri Abhyankar 
11087fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1109fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1110d950fb63SShri Abhyankar   if (snes->domainerror) {
1111d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1112d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1113d950fb63SShri Abhyankar   }
1114fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1115d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1116d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
111762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1118d950fb63SShri Abhyankar 
1119d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1120fe835674SShri Abhyankar   snes->norm = fnorm;
1121d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1122fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
11237a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1124d950fb63SShri Abhyankar 
1125d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1126fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1127d950fb63SShri Abhyankar   /* test convergence */
1128fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1129d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1130d950fb63SShri Abhyankar 
11319ce20c35SJungho Lee 
1132d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1133d950fb63SShri Abhyankar 
1134d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1135a6b72b01SJungho Lee     IS         IS_redact; /* redundant active set */
1136d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1137abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1138fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1139d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
114062298a1eSBarry Smith     IS         keptrows;
1141abcba341SShri Abhyankar     PetscBool  isequal;
1142d950fb63SShri Abhyankar 
1143d950fb63SShri Abhyankar     /* Call general purpose update function */
1144d950fb63SShri Abhyankar     if (snes->ops->update) {
1145d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1146d950fb63SShri Abhyankar     }
1147d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
114862298a1eSBarry Smith 
11499ce20c35SJungho Lee 
1150d950fb63SShri Abhyankar         /* Create active and inactive index sets */
1151a6b72b01SJungho Lee 
1152a6b72b01SJungho Lee     /*original
1153693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1154a6b72b01SJungho Lee      */
1155a6b72b01SJungho Lee     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
1156a6b72b01SJungho Lee 
1157a6b72b01SJungho Lee     if (vi->checkredundancy) {
1158a6b72b01SJungho Lee       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
1159ed70e96aSJungho Lee       if (IS_redact){
1160ed70e96aSJungho Lee         ierr = ISSort(IS_redact);CHKERRQ(ierr);
1161a6b72b01SJungho Lee         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1162a6b72b01SJungho Lee         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
1163ed70e96aSJungho Lee       }
1164ed70e96aSJungho Lee       else {
1165ed70e96aSJungho Lee         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1166ed70e96aSJungho Lee       }
1167a6b72b01SJungho Lee     } else {
1168a6b72b01SJungho Lee       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1169a6b72b01SJungho Lee     }
1170d950fb63SShri Abhyankar 
11714dcab191SBarry Smith 
1172abcba341SShri Abhyankar     /* Create inactive set submatrix */
117362298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1174a6b72b01SJungho Lee 
1175b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
11769ce20c35SJungho Lee     if (0 && keptrows) {
117762298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
117862298a1eSBarry Smith       const PetscInt *krows,*inact;
117927d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
118062298a1eSBarry Smith 
11816bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11826bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
118362298a1eSBarry Smith 
118462298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
118562298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
118662298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
118762298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
118862298a1eSBarry Smith       for (k=0; k<cnt; k++) {
118927d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
119062298a1eSBarry Smith       }
119162298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
119262298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11936bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11946bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
119562298a1eSBarry Smith 
119627d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
119727d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
119862298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
119962298a1eSBarry Smith     }
12009ce20c35SJungho Lee     ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr);
12019ce20c35SJungho Lee     /* remove later */
12029ce20c35SJungho Lee 
12039ce20c35SJungho Lee     /*
12049ce20c35SJungho Lee   ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12059ce20c35SJungho Lee   ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12069ce20c35SJungho Lee   ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12079ce20c35SJungho Lee   ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12089ce20c35SJungho Lee   ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12099ce20c35SJungho Lee      */
121062298a1eSBarry Smith 
1211d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1212d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1213d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1214d950fb63SShri Abhyankar 
1215d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1216fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1217fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1218fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1219d950fb63SShri Abhyankar 
1220d950fb63SShri Abhyankar     /* Create scatter contexts */
1221d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1222d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1223d950fb63SShri Abhyankar 
1224d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1225fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1226fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1227d950fb63SShri Abhyankar 
1228d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1229d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1230d950fb63SShri Abhyankar 
1231d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1232d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1233d950fb63SShri Abhyankar 
1234d950fb63SShri Abhyankar     /* Active set direction = 0 */
1235d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1236d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1237d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1238d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1239d950fb63SShri Abhyankar 
1240abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1241abcba341SShri Abhyankar     if (!isequal) {
1242732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1243c58c0d17SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
1244d950fb63SShri Abhyankar     }
1245d950fb63SShri Abhyankar 
124613e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
124713e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
124813e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
124913e0d083SBarry Smith 
1250f15307b4SJungho Lee 
12519ce20c35SJungho Lee 
1252d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
125313e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
125413e0d083SBarry Smith     {
125513e0d083SBarry Smith       PC        pc;
125613e0d083SBarry Smith       PetscBool flg;
125713e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
125813e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
125913e0d083SBarry Smith       if (flg) {
126013e0d083SBarry Smith         KSP      *subksps;
126113e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
126213e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
126313e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
126413e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
126513e0d083SBarry Smith         if (flg) {
126613e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
126713e0d083SBarry Smith           const PetscInt *ii;
126813e0d083SBarry Smith 
126913e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
127013e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
127113e0d083SBarry Smith           for (j=0; j<n; j++) {
127213e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
127313e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
127413e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
127513e0d083SBarry Smith           }
127613e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
127713e0d083SBarry Smith 
127813e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
127913e0d083SBarry Smith         }
128013e0d083SBarry Smith       }
128113e0d083SBarry Smith     }
128213e0d083SBarry Smith 
1283fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1284d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1285d950fb63SShri Abhyankar     if (kspreason < 0) {
1286d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1287d950fb63SShri Abhyankar         ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
1288d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1289d950fb63SShri Abhyankar         break;
1290d950fb63SShri Abhyankar       }
1291d950fb63SShri Abhyankar      }
1292d950fb63SShri Abhyankar 
1293d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1294d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1295d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1296d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1297d950fb63SShri Abhyankar 
12986bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12996bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
13006bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
13016bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
13026bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
13036bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1304abcba341SShri Abhyankar     if (!isequal) {
13056bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1306abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1307abcba341SShri Abhyankar     }
13086bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
13096bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1310d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
13116bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1312d950fb63SShri Abhyankar     }
1313d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1314d950fb63SShri Abhyankar     snes->linear_its += lits;
1315d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1316d950fb63SShri Abhyankar     /*
13170661309fSPeter Brune     if (snes->ops->precheckstep) {
1318d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
13190661309fSPeter Brune       ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr);
1320d950fb63SShri Abhyankar     }
1321d950fb63SShri Abhyankar 
1322d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1323d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1324d950fb63SShri Abhyankar     }
1325d950fb63SShri Abhyankar     */
1326d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1327d950fb63SShri Abhyankar          Y <- X - lambda*Y
1328d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1329d950fb63SShri Abhyankar     */
1330d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1331fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
13320661309fSPeter Brune     ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1333*4839bfe8SBarry Smith     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
13342b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
13352b4ed282SShri Abhyankar     if (snes->domainerror) {
13362b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13374c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13382b4ed282SShri Abhyankar       PetscFunctionReturn(0);
13392b4ed282SShri Abhyankar     }
13402b4ed282SShri Abhyankar     if (!lssucceed) {
13412b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
13422b4ed282SShri Abhyankar 	PetscBool ismin;
13432b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
13442b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
13452b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
13462b4ed282SShri Abhyankar         break;
13472b4ed282SShri Abhyankar       }
13482b4ed282SShri Abhyankar     }
13492b4ed282SShri Abhyankar     /* Update function and solution vectors */
1350fe835674SShri Abhyankar     fnorm = gnorm;
1351fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
13522b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
13532b4ed282SShri Abhyankar     /* Monitor convergence */
13542b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13552b4ed282SShri Abhyankar     snes->iter = i+1;
1356fe835674SShri Abhyankar     snes->norm = fnorm;
13572b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13582b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
13597a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
13602b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
13612b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1362fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13632b4ed282SShri Abhyankar     if (snes->reason) break;
13642b4ed282SShri Abhyankar   }
13654c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13662b4ed282SShri Abhyankar   if (i == maxits) {
13672b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13682b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13692b4ed282SShri Abhyankar   }
13702b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13712b4ed282SShri Abhyankar }
13722b4ed282SShri Abhyankar 
13732f63a38cSShri Abhyankar #undef __FUNCT__
1374720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1375cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13762f63a38cSShri Abhyankar {
13772f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13782f63a38cSShri Abhyankar 
13792f63a38cSShri Abhyankar   PetscFunctionBegin;
13802f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13812f63a38cSShri Abhyankar   vi->checkredundancy = func;
1382cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13832f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13842f63a38cSShri Abhyankar }
13852f63a38cSShri Abhyankar 
1386ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1387ff596062SShri Abhyankar #include <engine.h>
1388ff596062SShri Abhyankar #include <mex.h>
1389cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1390ff596062SShri Abhyankar 
1391ff596062SShri Abhyankar #undef __FUNCT__
1392ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1393ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1394ff596062SShri Abhyankar {
1395ff596062SShri Abhyankar   PetscErrorCode      ierr;
1396cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1397cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1398cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1399cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1400fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1401ff596062SShri Abhyankar 
1402ff596062SShri Abhyankar   PetscFunctionBegin;
1403ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1404ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1405ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1406ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1407ff596062SShri Abhyankar 
140809db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
140909db5ad8SShri Abhyankar    bet set by the Matlab function */
1410fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1411cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1412ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1413ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1414cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1415ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1416ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1417cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1418cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1419cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1420ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1421ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1422ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1423ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1424ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1425ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1426ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1427ff596062SShri Abhyankar   PetscFunctionReturn(0);
1428ff596062SShri Abhyankar }
1429ff596062SShri Abhyankar 
1430ff596062SShri Abhyankar #undef __FUNCT__
1431ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1432ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1433ff596062SShri Abhyankar {
1434ff596062SShri Abhyankar   PetscErrorCode      ierr;
1435cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1436ff596062SShri Abhyankar 
1437ff596062SShri Abhyankar   PetscFunctionBegin;
1438ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1439cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1440ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1441ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1442cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1443ff596062SShri Abhyankar   PetscFunctionReturn(0);
1444ff596062SShri Abhyankar }
1445ff596062SShri Abhyankar 
1446ff596062SShri Abhyankar #endif
1447ff596062SShri Abhyankar 
1448ff596062SShri Abhyankar 
14492f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
14502f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1451720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
145256a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
145356a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
14542f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
14552f63a38cSShri Abhyankar */
14562f63a38cSShri Abhyankar #undef __FUNCT__
1457b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1458b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
14592f63a38cSShri Abhyankar {
14602f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
14612f63a38cSShri Abhyankar   PetscErrorCode    ierr;
14622f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
14632f63a38cSShri Abhyankar   PetscBool         lssucceed;
14642f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
14652f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14662f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14672f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14682f63a38cSShri Abhyankar 
14692f63a38cSShri Abhyankar   PetscFunctionBegin;
14702f63a38cSShri Abhyankar   snes->numFailures            = 0;
14712f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14722f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14732f63a38cSShri Abhyankar 
14742f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14752f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14762f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14772f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14782f63a38cSShri Abhyankar   G		= snes->work[1];
14792f63a38cSShri Abhyankar   W		= snes->work[2];
14802f63a38cSShri Abhyankar 
14812f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14822f63a38cSShri Abhyankar   snes->iter = 0;
14832f63a38cSShri Abhyankar   snes->norm = 0.0;
14842f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14852f63a38cSShri Abhyankar 
14862f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14872f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14882f63a38cSShri Abhyankar   if (snes->domainerror) {
14892f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14902f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14912f63a38cSShri Abhyankar   }
14922f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14932f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14942f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
149562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14962f63a38cSShri Abhyankar 
14972f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14982f63a38cSShri Abhyankar   snes->norm = fnorm;
14992f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
15002f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
15017a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
15022f63a38cSShri Abhyankar 
15032f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
15042f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
15052f63a38cSShri Abhyankar   /* test convergence */
15062f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
15072f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
15082f63a38cSShri Abhyankar 
15092f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
15102f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1511cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
151256a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
151356a221efSShri Abhyankar     Vec            F_aug,Y_aug;
151456a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
151556a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
151656a221efSShri Abhyankar     PetscInt       k;
151763ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
151856a221efSShri Abhyankar     PetscScalar    *f,*f2;
15192f63a38cSShri Abhyankar     PetscBool      isequal;
152056a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
15212f63a38cSShri Abhyankar 
15222f63a38cSShri Abhyankar     /* Call general purpose update function */
15232f63a38cSShri Abhyankar     if (snes->ops->update) {
15242f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
15252f63a38cSShri Abhyankar     }
15262f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
15272f63a38cSShri Abhyankar 
15282f63a38cSShri Abhyankar     /* Create active and inactive index sets */
15292f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
15302f63a38cSShri Abhyankar 
153156a221efSShri Abhyankar     /* Get local active set size */
15322f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
153356a221efSShri Abhyankar     if (nis_act) {
1534e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1535e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
153656a221efSShri Abhyankar       if(vi->checkredundancy) {
1537cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
153856a221efSShri Abhyankar       }
15392f63a38cSShri Abhyankar 
154056a221efSShri Abhyankar       if(!IS_redact) {
154156a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
154256a221efSShri Abhyankar            there were no redundant active set variables */
154356a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
154456a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
154556a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
154656a221efSShri Abhyankar 	nkept = nis_act;
154756a221efSShri Abhyankar       } else {
154856a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
154956a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
15502f63a38cSShri Abhyankar 
155156a221efSShri Abhyankar 	/* Create reduced active set list */
155256a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
155356a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1554cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
155556a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
155656a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
155756a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
155856a221efSShri Abhyankar 	}
155956a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
156056a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1561cb5fe31bSShri Abhyankar 
1562cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
156356a221efSShri Abhyankar       }
15642f63a38cSShri Abhyankar 
156556a221efSShri Abhyankar       /* Create augmented F and Y */
156656a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
156756a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
156856a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
156956a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15702f63a38cSShri Abhyankar 
157156a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
157256a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
157356a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
157456a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
157556a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
157656a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15772f63a38cSShri Abhyankar 
157856a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
157956a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
158056a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
158156a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15822f63a38cSShri Abhyankar 
158356a221efSShri Abhyankar 
15849521db3cSSatish Balay       { /* local vars */
1585493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
158656a221efSShri Abhyankar       PetscInt          ncols;
158756a221efSShri Abhyankar       const PetscInt    *cols;
158856a221efSShri Abhyankar       const PetscScalar *vals;
15892969f145SShri Abhyankar       PetscScalar        value[2];
15902969f145SShri Abhyankar       PetscInt           row,col[2];
1591493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15922969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1593493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1594493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1595493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1596493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1597493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1598493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1599493a4f3dSShri Abhyankar       }
1600493a4f3dSShri Abhyankar 
1601493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1602493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
16032969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1604493a4f3dSShri Abhyankar       }
1605493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1606493a4f3dSShri Abhyankar 
1607493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
160856a221efSShri Abhyankar 
160956a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
161056a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
161156a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
161256a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
161356a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
161456a221efSShri Abhyankar       }
161556a221efSShri Abhyankar       /* Add the augmented part */
161656a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
16172969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
16182969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
16192969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
16202969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
162156a221efSShri Abhyankar       }
162256a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
162356a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
162456a221efSShri Abhyankar       /* Only considering prejac = jac for now */
162556a221efSShri Abhyankar       Jpre_aug = J_aug;
16269521db3cSSatish Balay       } /* local vars*/
1627e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1628e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
162956a221efSShri Abhyankar     } else {
163056a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
163156a221efSShri Abhyankar     }
16322f63a38cSShri Abhyankar 
16332f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
16342f63a38cSShri Abhyankar     if (!isequal) {
163556a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
16362f63a38cSShri Abhyankar     }
163756a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
16382f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
163956a221efSShri Abhyankar     /*  {
16402f63a38cSShri Abhyankar       PC        pc;
16412f63a38cSShri Abhyankar       PetscBool flg;
16422f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
16432f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
16442f63a38cSShri Abhyankar       if (flg) {
16452f63a38cSShri Abhyankar         KSP      *subksps;
16462f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
16472f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
16482f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
16492f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
16502f63a38cSShri Abhyankar         if (flg) {
16512f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
16522f63a38cSShri Abhyankar           const PetscInt *ii;
16532f63a38cSShri Abhyankar 
16542f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
16552f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
16562f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
16572f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
16582f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
16592f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
16602f63a38cSShri Abhyankar           }
16612f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
16622f63a38cSShri Abhyankar 
16632f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
16642f63a38cSShri Abhyankar         }
16652f63a38cSShri Abhyankar       }
16662f63a38cSShri Abhyankar     }
166756a221efSShri Abhyankar     */
166856a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16692f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16702f63a38cSShri Abhyankar     if (kspreason < 0) {
16712f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16722f63a38cSShri Abhyankar         ierr = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
16732f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16742f63a38cSShri Abhyankar         break;
16752f63a38cSShri Abhyankar       }
16762f63a38cSShri Abhyankar     }
16772f63a38cSShri Abhyankar 
167856a221efSShri Abhyankar     if(nis_act) {
167956a221efSShri Abhyankar       PetscScalar *y1,*y2;
168056a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
168156a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
168256a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
168356a221efSShri Abhyankar       j1 = 0;
168456a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
168556a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
168656a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
168756a221efSShri Abhyankar       }
168856a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
168956a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16902f63a38cSShri Abhyankar 
16916bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16926bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16936bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
169456a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
169556a221efSShri Abhyankar     }
169656a221efSShri Abhyankar 
16972f63a38cSShri Abhyankar     if (!isequal) {
16986bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16992f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
17002f63a38cSShri Abhyankar     }
17016bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
170256a221efSShri Abhyankar 
17032f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
17042f63a38cSShri Abhyankar     snes->linear_its += lits;
17052f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
17062f63a38cSShri Abhyankar     /*
17070661309fSPeter Brune     if (snes->ops->precheckstep) {
17082f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
17090661309fSPeter Brune       ierr = (*snes->ops->precheckstep)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr);
17102f63a38cSShri Abhyankar     }
17112f63a38cSShri Abhyankar 
17122f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
17132f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
17142f63a38cSShri Abhyankar     }
17152f63a38cSShri Abhyankar     */
17162f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
17172f63a38cSShri Abhyankar          Y <- X - lambda*Y
17182f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
17192f63a38cSShri Abhyankar     */
17202f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
17212f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
17220661309fSPeter Brune     ierr = (*snes->ops->linesearch)(snes,snes->lsP,X,F,Y,fnorm,xnorm,G,W,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1723*4839bfe8SBarry Smith     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
17242f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
17252f63a38cSShri Abhyankar     if (snes->domainerror) {
17262f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
17272f63a38cSShri Abhyankar       PetscFunctionReturn(0);
17282f63a38cSShri Abhyankar     }
17292f63a38cSShri Abhyankar     if (!lssucceed) {
17302f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
17312f63a38cSShri Abhyankar 	PetscBool ismin;
17322f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
17332f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
17342f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
17352f63a38cSShri Abhyankar         break;
17362f63a38cSShri Abhyankar       }
17372f63a38cSShri Abhyankar     }
17382f63a38cSShri Abhyankar     /* Update function and solution vectors */
17392f63a38cSShri Abhyankar     fnorm = gnorm;
17402f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
17412f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
17422f63a38cSShri Abhyankar     /* Monitor convergence */
17432f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
17442f63a38cSShri Abhyankar     snes->iter = i+1;
17452f63a38cSShri Abhyankar     snes->norm = fnorm;
17462f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
17472f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
17487a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
17492f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
17502f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
17512f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
17522f63a38cSShri Abhyankar     if (snes->reason) break;
17532f63a38cSShri Abhyankar   }
17542f63a38cSShri Abhyankar   if (i == maxits) {
17552f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
17562f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
17572f63a38cSShri Abhyankar   }
17582f63a38cSShri Abhyankar   PetscFunctionReturn(0);
17592f63a38cSShri Abhyankar }
17602f63a38cSShri Abhyankar 
17612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17622b4ed282SShri Abhyankar /*
17632b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
17642b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
17652b4ed282SShri Abhyankar 
17662b4ed282SShri Abhyankar    Input Parameter:
17672b4ed282SShri Abhyankar .  snes - the SNES context
17682b4ed282SShri Abhyankar .  x - the solution vector
17692b4ed282SShri Abhyankar 
17702b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17712b4ed282SShri Abhyankar 
17722b4ed282SShri Abhyankar    Notes:
17732b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17742b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17752b4ed282SShri Abhyankar    the call to SNESSolve().
17762b4ed282SShri Abhyankar  */
17772b4ed282SShri Abhyankar #undef __FUNCT__
17782b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17792b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17802b4ed282SShri Abhyankar {
17812b4ed282SShri Abhyankar   PetscErrorCode ierr;
17822b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17832b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17842b4ed282SShri Abhyankar 
17852b4ed282SShri Abhyankar   PetscFunctionBegin;
178658c9b817SLisandro Dalcin 
178758c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17882b4ed282SShri Abhyankar 
17892176524cSBarry Smith   if (vi->computevariablebounds) {
179077cdaf69SJed Brown     if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);}
179177cdaf69SJed Brown     if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);}
179277cdaf69SJed Brown     ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr);
17932176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
17942176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
17952b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
179601f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17972b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
179801f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17992b4ed282SShri Abhyankar   } else {
18002b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
18012b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
18022b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
18032b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
18042b4ed282SShri 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]))
18052b4ed282SShri 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.");
18062b4ed282SShri Abhyankar   }
18072f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1808abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1809abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1810abcba341SShri Abhyankar     PetscInt *indices;
1811abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1812abcba341SShri Abhyankar 
1813abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1814abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1815abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1816abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1817abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1818abcba341SShri Abhyankar   }
18192b4ed282SShri Abhyankar 
18202f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1821fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1822fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1823fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1824fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1825fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1826fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1827fe835674SShri Abhyankar   }
18282b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18292b4ed282SShri Abhyankar }
18302b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18312176524cSBarry Smith #undef __FUNCT__
18322176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
18332176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
18342176524cSBarry Smith {
18352176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
18362176524cSBarry Smith   PetscErrorCode ierr;
18372176524cSBarry Smith 
18382176524cSBarry Smith   PetscFunctionBegin;
18392176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
18402176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1841d655a5daSBarry Smith   if (snes->ops->solve != SNESSolveVI_SS) {
1842d655a5daSBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1843d655a5daSBarry Smith   }
18442176524cSBarry Smith   PetscFunctionReturn(0);
18452176524cSBarry Smith }
18462176524cSBarry Smith 
18472b4ed282SShri Abhyankar /*
18482b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
18492b4ed282SShri Abhyankar    with SNESCreate_VI().
18502b4ed282SShri Abhyankar 
18512b4ed282SShri Abhyankar    Input Parameter:
18522b4ed282SShri Abhyankar .  snes - the SNES context
18532b4ed282SShri Abhyankar 
18542b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
18552b4ed282SShri Abhyankar  */
18562b4ed282SShri Abhyankar #undef __FUNCT__
18572b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
18582b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
18592b4ed282SShri Abhyankar {
18602b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
18612b4ed282SShri Abhyankar   PetscErrorCode ierr;
18622b4ed282SShri Abhyankar 
18632b4ed282SShri Abhyankar   PetscFunctionBegin;
18642b4ed282SShri Abhyankar 
18652f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18662b4ed282SShri Abhyankar     /* clear vectors */
18676bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18686bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18696bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18706bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18716bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18726bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18737fe79bc4SShri Abhyankar   }
18742b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18752b4ed282SShri Abhyankar 
18762b4ed282SShri Abhyankar   /* clear composed functions */
18772b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1878c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18792b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18802b4ed282SShri Abhyankar }
18817fe79bc4SShri Abhyankar 
18822b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18832b4ed282SShri Abhyankar #undef __FUNCT__
18842b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18852b4ed282SShri Abhyankar 
18862b4ed282SShri Abhyankar /*
18877fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18887fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18892b4ed282SShri Abhyankar 
18902b4ed282SShri Abhyankar */
18911e633543SBarry Smith PetscErrorCode SNESLineSearchNo_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
18922b4ed282SShri Abhyankar {
18932b4ed282SShri Abhyankar   PetscErrorCode ierr;
1894ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18952b4ed282SShri Abhyankar 
18962b4ed282SShri Abhyankar   PetscFunctionBegin;
18972b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18982b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18992b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
19002b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1901c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19020661309fSPeter Brune   if (snes->ops->postcheckstep) {
19030661309fSPeter Brune    ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1904c1a5e521SShri Abhyankar   }
1905c1a5e521SShri Abhyankar   if (changed_y) {
1906c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19077fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1908c1a5e521SShri Abhyankar   }
1909c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1910c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1911c1a5e521SShri Abhyankar   if (!snes->domainerror) {
19122f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
19137fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19147fe79bc4SShri Abhyankar     } else {
1915c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
19167fe79bc4SShri Abhyankar     }
191762cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1918c1a5e521SShri Abhyankar   }
19190661309fSPeter Brune   if (snes->ls_monitor) {
19200661309fSPeter Brune     ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
19210661309fSPeter Brune     ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr);
19220661309fSPeter Brune     ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1923c1a5e521SShri Abhyankar   }
1924c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1925c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1926c1a5e521SShri Abhyankar }
1927c1a5e521SShri Abhyankar 
1928c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1929c1a5e521SShri Abhyankar #undef __FUNCT__
19302b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
19312b4ed282SShri Abhyankar 
19322b4ed282SShri Abhyankar /*
19332b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
19342b4ed282SShri Abhyankar */
19351e633543SBarry Smith PetscErrorCode SNESLineSearchNoNorms_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
19362b4ed282SShri Abhyankar {
19372b4ed282SShri Abhyankar   PetscErrorCode ierr;
1938ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
19392b4ed282SShri Abhyankar 
19402b4ed282SShri Abhyankar   PetscFunctionBegin;
19412b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
19422b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19432b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
19447fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19450661309fSPeter Brune   if (snes->ops->postcheckstep) {
19460661309fSPeter Brune    ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
19472b4ed282SShri Abhyankar   }
19482b4ed282SShri Abhyankar   if (changed_y) {
19492b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19507fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19512b4ed282SShri Abhyankar   }
19522b4ed282SShri Abhyankar 
19532b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
19542b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
19552b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19562b4ed282SShri Abhyankar   }
19572b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19582b4ed282SShri Abhyankar   PetscFunctionReturn(0);
19592b4ed282SShri Abhyankar }
19607fe79bc4SShri Abhyankar 
19612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
19622b4ed282SShri Abhyankar #undef __FUNCT__
19632b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19642b4ed282SShri Abhyankar /*
19657fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19662b4ed282SShri Abhyankar */
19671e633543SBarry Smith PetscErrorCode SNESLineSearchCubic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
19682b4ed282SShri Abhyankar {
1969fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1970fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1971fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1972fe835674SShri Abhyankar   PetscScalar    cinitslope;
1973fe835674SShri Abhyankar #endif
1974fe835674SShri Abhyankar   PetscErrorCode ierr;
1975fe835674SShri Abhyankar   PetscInt       count;
1976fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1977fe835674SShri Abhyankar   MPI_Comm       comm;
1978fe835674SShri Abhyankar 
1979fe835674SShri Abhyankar   PetscFunctionBegin;
1980fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1981fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1982fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1983fe835674SShri Abhyankar 
1984fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1985fe835674SShri Abhyankar   if (*ynorm == 0.0) {
19860661309fSPeter Brune     if (snes->ls_monitor) {
19870661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
19880661309fSPeter Brune       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
19890661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1990fe835674SShri Abhyankar     }
1991fe835674SShri Abhyankar     *gnorm = fnorm;
1992fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1993fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1994fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1995fe835674SShri Abhyankar     goto theend1;
1996fe835674SShri Abhyankar   }
19970661309fSPeter Brune   if (*ynorm > snes->maxstep) {	/* Step too big, so scale back */
19980661309fSPeter Brune     if (snes->ls_monitor) {
19990661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
200062d1f40fSBarry Smith       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Scaling step by %g old ynorm %g\n",(double)(snes->maxstep/(*ynorm)),(double)(*ynorm));CHKERRQ(ierr);
20010661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2002fe835674SShri Abhyankar     }
20030661309fSPeter Brune     ierr = VecScale(y,snes->maxstep/(*ynorm));CHKERRQ(ierr);
20040661309fSPeter Brune     *ynorm = snes->maxstep;
2005fe835674SShri Abhyankar   }
2006fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
20070661309fSPeter Brune   minlambda = snes->steptol/rellength;
2008fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
2009fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
2010fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
2011fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
2012fe835674SShri Abhyankar #else
2013fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
2014fe835674SShri Abhyankar #endif
2015fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
2016fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
2017fe835674SShri Abhyankar 
2018fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2019fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2020fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2021fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
2022fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2023fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2024fe835674SShri Abhyankar     goto theend1;
2025fe835674SShri Abhyankar   }
2026fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20272f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2028fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20297fe79bc4SShri Abhyankar   } else {
20307fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20317fe79bc4SShri Abhyankar   }
2032fe835674SShri Abhyankar   if (snes->domainerror) {
2033fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2034fe835674SShri Abhyankar     PetscFunctionReturn(0);
2035fe835674SShri Abhyankar   }
203662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
20370661309fSPeter Brune   ierr = PetscInfo4(snes,"Initial fnorm %g gnorm %g alpha %g initslope %g\n",(double)fnorm,(double)*gnorm,(double)snes->ls_alpha,(double)initslope);CHKERRQ(ierr);
20380661309fSPeter Brune   if ((*gnorm)*(*gnorm) <= (1.0 - snes->ls_alpha)*fnorm*fnorm ) { /* Sufficient reduction */
20390661309fSPeter Brune     if (snes->ls_monitor) {
20400661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
204162d1f40fSBarry Smith       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)(*gnorm));CHKERRQ(ierr);
20420661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2043fe835674SShri Abhyankar     }
2044fe835674SShri Abhyankar     goto theend1;
2045fe835674SShri Abhyankar   }
2046fe835674SShri Abhyankar 
2047fe835674SShri Abhyankar   /* Fit points with quadratic */
2048fe835674SShri Abhyankar   lambda     = 1.0;
2049fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
2050fe835674SShri Abhyankar   lambdaprev = lambda;
2051fe835674SShri Abhyankar   gnormprev  = *gnorm;
2052fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2053fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
2054fe835674SShri Abhyankar   else                         lambda = lambdatemp;
2055fe835674SShri Abhyankar 
2056fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2057fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2058fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2059fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
2060fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2061fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2062fe835674SShri Abhyankar     goto theend1;
2063fe835674SShri Abhyankar   }
2064fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20652f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2066fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20677fe79bc4SShri Abhyankar   } else {
20687fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20697fe79bc4SShri Abhyankar   }
2070fe835674SShri Abhyankar   if (snes->domainerror) {
2071fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2072fe835674SShri Abhyankar     PetscFunctionReturn(0);
2073fe835674SShri Abhyankar   }
207462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
20750661309fSPeter Brune   if (snes->ls_monitor) {
20760661309fSPeter Brune     ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
207762d1f40fSBarry Smith     ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: gnorm after quadratic fit %g\n",(double)(*gnorm));CHKERRQ(ierr);
20780661309fSPeter Brune     ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2079fe835674SShri Abhyankar   }
20800661309fSPeter Brune   if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm ) { /* sufficient reduction */
20810661309fSPeter Brune     if (snes->ls_monitor) {
20820661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2083*4839bfe8SBarry Smith       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",(double)lambda);CHKERRQ(ierr);
20840661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2085fe835674SShri Abhyankar     }
2086fe835674SShri Abhyankar     goto theend1;
2087fe835674SShri Abhyankar   }
2088fe835674SShri Abhyankar 
2089fe835674SShri Abhyankar   /* Fit points with cubic */
2090fe835674SShri Abhyankar   count = 1;
2091fe835674SShri Abhyankar   while (PETSC_TRUE) {
2092fe835674SShri Abhyankar     if (lambda <= minlambda) {
20930661309fSPeter Brune       if (snes->ls_monitor) {
20940661309fSPeter Brune         ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
20950661309fSPeter Brune  	ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
209662d1f40fSBarry Smith 	ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)minlambda,(double)lambda,(double)initslope);CHKERRQ(ierr);
20970661309fSPeter Brune         ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2098fe835674SShri Abhyankar       }
2099fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2100fe835674SShri Abhyankar       break;
2101fe835674SShri Abhyankar     }
2102fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2103fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2104fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2105fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2106fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2107fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2108fe835674SShri Abhyankar     if (a == 0.0) {
2109fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2110fe835674SShri Abhyankar     } else {
211162d1f40fSBarry Smith       lambdatemp = (-b + PetscSqrtReal(d))/(3.0*a);
2112fe835674SShri Abhyankar     }
2113fe835674SShri Abhyankar     lambdaprev = lambda;
2114fe835674SShri Abhyankar     gnormprev  = *gnorm;
2115fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2116fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2117fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2118fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2119fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2120fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2121fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2122*4839bfe8SBarry Smith       ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr);
2123fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2124fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2125fe835674SShri Abhyankar       break;
2126fe835674SShri Abhyankar     }
2127fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21282f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2129fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21307fe79bc4SShri Abhyankar     } else {
21317fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21327fe79bc4SShri Abhyankar     }
2133fe835674SShri Abhyankar     if (snes->domainerror) {
2134fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2135fe835674SShri Abhyankar       PetscFunctionReturn(0);
2136fe835674SShri Abhyankar     }
213762cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21380661309fSPeter Brune     if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* is reduction enough? */
21390661309fSPeter Brune       if (snes->ls_monitor) {
214062d1f40fSBarry Smith 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %g lambda=%18.16e\n",(double)(*gnorm),(double)lambda);CHKERRQ(ierr);
2141fe835674SShri Abhyankar       }
2142fe835674SShri Abhyankar       break;
2143fe835674SShri Abhyankar     } else {
21440661309fSPeter Brune       if (snes->ls_monitor) {
214562d1f40fSBarry Smith         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %g lambda=%18.16e\n",(double)(*gnorm),(double)lambda);CHKERRQ(ierr);
2146fe835674SShri Abhyankar       }
2147fe835674SShri Abhyankar     }
2148fe835674SShri Abhyankar     count++;
2149fe835674SShri Abhyankar   }
2150fe835674SShri Abhyankar   theend1:
2151fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
21520661309fSPeter Brune   if (snes->ops->postcheckstep && *flag) {
21530661309fSPeter Brune     ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2154fe835674SShri Abhyankar     if (changed_y) {
2155fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2156fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2157fe835674SShri Abhyankar     }
2158fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2159fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21602f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2161fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21627fe79bc4SShri Abhyankar       } else {
21637fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21647fe79bc4SShri Abhyankar       }
2165fe835674SShri Abhyankar       if (snes->domainerror) {
2166fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2167fe835674SShri Abhyankar         PetscFunctionReturn(0);
2168fe835674SShri Abhyankar       }
216962cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2170fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2171fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2172fe835674SShri Abhyankar     }
2173fe835674SShri Abhyankar   }
2174fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2175fe835674SShri Abhyankar   PetscFunctionReturn(0);
2176fe835674SShri Abhyankar }
2177fe835674SShri Abhyankar 
21782b4ed282SShri Abhyankar #undef __FUNCT__
21792b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21802b4ed282SShri Abhyankar /*
21817fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21822b4ed282SShri Abhyankar */
21831e633543SBarry Smith PetscErrorCode SNESLineSearchQuadratic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec y,PetscReal fnorm,PetscReal xnorm,Vec g,Vec w,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
21842b4ed282SShri Abhyankar {
21852b4ed282SShri Abhyankar   /*
21862b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21872b4ed282SShri Abhyankar      minimization problem:
21882b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21892b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
21902b4ed282SShri Abhyankar    */
21912b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
21922b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21932b4ed282SShri Abhyankar   PetscScalar    cinitslope;
21942b4ed282SShri Abhyankar #endif
21952b4ed282SShri Abhyankar   PetscErrorCode ierr;
21962b4ed282SShri Abhyankar   PetscInt       count;
2197ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
21982b4ed282SShri Abhyankar 
21992b4ed282SShri Abhyankar   PetscFunctionBegin;
22002b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22012b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
22022b4ed282SShri Abhyankar 
22032b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
22042b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
22050661309fSPeter Brune     if (snes->ls_monitor) {
22060661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22070661309fSPeter Brune       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
22080661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22092b4ed282SShri Abhyankar     }
22102b4ed282SShri Abhyankar     *gnorm = fnorm;
22112b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
22122b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
22132b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
22142b4ed282SShri Abhyankar     goto theend2;
22152b4ed282SShri Abhyankar   }
22160661309fSPeter Brune   if (*ynorm > snes->maxstep) {	/* Step too big, so scale back */
22170661309fSPeter Brune     ierr   = VecScale(y,snes->maxstep/(*ynorm));CHKERRQ(ierr);
22180661309fSPeter Brune     *ynorm = snes->maxstep;
22192b4ed282SShri Abhyankar   }
22202b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
22210661309fSPeter Brune   minlambda = snes->steptol/rellength;
22227fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
22232b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
22247fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
22252b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
22262b4ed282SShri Abhyankar #else
22277fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
22282b4ed282SShri Abhyankar #endif
22292b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
22302b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
2231*4839bfe8SBarry Smith   ierr = PetscInfo1(snes,"Initslope %g \n",(double)initslope);CHKERRQ(ierr);
22322b4ed282SShri Abhyankar 
22332b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22347fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22352b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
22362b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
22372b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
22382b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22392b4ed282SShri Abhyankar     goto theend2;
22402b4ed282SShri Abhyankar   }
22412b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22422f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
22437fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22447fe79bc4SShri Abhyankar   } else {
22457fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22467fe79bc4SShri Abhyankar   }
22472b4ed282SShri Abhyankar   if (snes->domainerror) {
22482b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22492b4ed282SShri Abhyankar     PetscFunctionReturn(0);
22502b4ed282SShri Abhyankar   }
225162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22520661309fSPeter Brune   if ((*gnorm)*(*gnorm) <= (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* Sufficient reduction */
22530661309fSPeter Brune     if (snes->ls_monitor) {
22540661309fSPeter Brune       ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
225562d1f40fSBarry Smith       ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)(*gnorm));CHKERRQ(ierr);
22560661309fSPeter Brune       ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22572b4ed282SShri Abhyankar     }
22582b4ed282SShri Abhyankar     goto theend2;
22592b4ed282SShri Abhyankar   }
22602b4ed282SShri Abhyankar 
22612b4ed282SShri Abhyankar   /* Fit points with quadratic */
22622b4ed282SShri Abhyankar   lambda = 1.0;
22632b4ed282SShri Abhyankar   count = 1;
22642b4ed282SShri Abhyankar   while (PETSC_TRUE) {
22652b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
22660661309fSPeter Brune       if (snes->ls_monitor) {
22670661309fSPeter Brune         ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22680661309fSPeter Brune         ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
226962d1f40fSBarry Smith         ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"Line search: fnorm=%g, gnorm=%g, ynorm=%g, lambda=%g, initial slope=%g\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr);
22700661309fSPeter Brune         ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22712b4ed282SShri Abhyankar       }
22722b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
22732b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22742b4ed282SShri Abhyankar       break;
22752b4ed282SShri Abhyankar     }
22762b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
22772b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
22782b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
22792b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22802b4ed282SShri Abhyankar 
22812b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22827fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22832b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22842b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2285*4839bfe8SBarry Smith       ierr  = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",(double)fnorm,(double)(*gnorm),(double)(*ynorm),(double)lambda,(double)initslope);CHKERRQ(ierr);
22862b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22872b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22882b4ed282SShri Abhyankar       break;
22892b4ed282SShri Abhyankar     }
22902b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22912b4ed282SShri Abhyankar     if (snes->domainerror) {
22922b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22932b4ed282SShri Abhyankar       PetscFunctionReturn(0);
22942b4ed282SShri Abhyankar     }
22952f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
22967fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22977fe79bc4SShri Abhyankar     } else {
22982b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22997fe79bc4SShri Abhyankar     }
230062cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
23010661309fSPeter Brune     if ((*gnorm)*(*gnorm) < (1.0 - snes->ls_alpha)*fnorm*fnorm) { /* sufficient reduction */
23020661309fSPeter Brune       if (snes->ls_monitor) {
23030661309fSPeter Brune         ierr = PetscViewerASCIIAddTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
230462d1f40fSBarry Smith         ierr = PetscViewerASCIIPrintf(snes->ls_monitor,"    Line Search: Quadratically determined step, lambda=%g\n",(double)lambda);CHKERRQ(ierr);
23050661309fSPeter Brune         ierr = PetscViewerASCIISubtractTab(snes->ls_monitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
23062b4ed282SShri Abhyankar       }
23072b4ed282SShri Abhyankar       break;
23082b4ed282SShri Abhyankar     }
23092b4ed282SShri Abhyankar     count++;
23102b4ed282SShri Abhyankar   }
23112b4ed282SShri Abhyankar   theend2:
23122b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
23130661309fSPeter Brune   if (snes->ops->postcheckstep) {
23140661309fSPeter Brune     ierr = (*snes->ops->postcheckstep)(snes,x,y,w,snes->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
23152b4ed282SShri Abhyankar     if (changed_y) {
23162b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
23177fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
23182b4ed282SShri Abhyankar     }
23192b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
23202b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
23212b4ed282SShri Abhyankar       if (snes->domainerror) {
23222b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23232b4ed282SShri Abhyankar         PetscFunctionReturn(0);
23242b4ed282SShri Abhyankar       }
23252f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
23267fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
23277fe79bc4SShri Abhyankar       } else {
23287fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
23297fe79bc4SShri Abhyankar       }
23307fe79bc4SShri Abhyankar 
23312b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
23322b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
233362cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
23342b4ed282SShri Abhyankar     }
23352b4ed282SShri Abhyankar   }
23362b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23372b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23382b4ed282SShri Abhyankar }
23392b4ed282SShri Abhyankar 
23402b4ed282SShri Abhyankar /*
23412b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
23422b4ed282SShri Abhyankar 
23432b4ed282SShri Abhyankar    Input Parameters:
23442b4ed282SShri Abhyankar .  SNES - the SNES context
23452b4ed282SShri Abhyankar .  viewer - visualization context
23462b4ed282SShri Abhyankar 
23472b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
23482b4ed282SShri Abhyankar */
23492b4ed282SShri Abhyankar #undef __FUNCT__
23502b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23512b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23522b4ed282SShri Abhyankar {
235378c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23542b4ed282SShri Abhyankar   PetscErrorCode ierr;
2355ace3abfcSBarry Smith   PetscBool     iascii;
23562b4ed282SShri Abhyankar 
23572b4ed282SShri Abhyankar   PetscFunctionBegin;
23582b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23592b4ed282SShri Abhyankar   if (iascii) {
23600661309fSPeter Brune     cstr = SNESLineSearchTypeName(snes->ls_type);
236178c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
23620a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2363b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
236478c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
236578c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
23662b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
2367*4839bfe8SBarry Smith     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%g, maxstep=%g, minlambda=%g\n",(double)snes->ls_alpha,(double)snes->maxstep,(double)snes->steptol);CHKERRQ(ierr);
23682b4ed282SShri Abhyankar   }
23692b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23702b4ed282SShri Abhyankar }
23712b4ed282SShri Abhyankar 
23725559b345SBarry Smith #undef __FUNCT__
23735559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
23745559b345SBarry Smith /*@
23752b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
23762b4ed282SShri Abhyankar 
23772b4ed282SShri Abhyankar    Input Parameters:
23782b4ed282SShri Abhyankar .  snes - the SNES context.
23792b4ed282SShri Abhyankar .  xl   - lower bound.
23802b4ed282SShri Abhyankar .  xu   - upper bound.
23812b4ed282SShri Abhyankar 
23822b4ed282SShri Abhyankar    Notes:
23832b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
238401f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
238584c105d7SBarry Smith 
23862bd2b0e6SSatish Balay    Level: advanced
23872bd2b0e6SSatish Balay 
23885559b345SBarry Smith @*/
238969c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
23902b4ed282SShri Abhyankar {
2391d923200aSJungho Lee   SNES_VI           *vi;
2392d923200aSJungho Lee   PetscErrorCode    ierr;
23936fd67740SBarry Smith   const PetscScalar *xxl,*xxu;
23946fd67740SBarry Smith   PetscInt          i,n, cnt = 0;
23952b4ed282SShri Abhyankar 
23962b4ed282SShri Abhyankar   PetscFunctionBegin;
23972b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
23982b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
23992b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
24002b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
24012b4ed282SShri Abhyankar   if (xl->map->N != snes->vec_func->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths lower bound = %D solution vector = %D",xl->map->N,snes->vec_func->map->N);
24022b4ed282SShri Abhyankar   if (xu->map->N != snes->vec_func->map->N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector lengths: upper bound = %D solution vector = %D",xu->map->N,snes->vec_func->map->N);
2403d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2404d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
24052176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
24062176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
24072176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
24082176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
24092b4ed282SShri Abhyankar   vi->xl = xl;
24102b4ed282SShri Abhyankar   vi->xu = xu;
24116fd67740SBarry Smith   ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr);
24126fd67740SBarry Smith   ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr);
24136fd67740SBarry Smith   ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr);
24146fd67740SBarry Smith   for (i=0; i<n; i++) {
24156fd67740SBarry Smith     cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF));
24166fd67740SBarry Smith   }
24176fd67740SBarry Smith   ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
24186fd67740SBarry Smith   ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr);
24196fd67740SBarry Smith   ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr);
24202b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24212b4ed282SShri Abhyankar }
2422693ddf92SShri Abhyankar 
24232b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24242b4ed282SShri Abhyankar /*
24252b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
24262b4ed282SShri Abhyankar 
24272b4ed282SShri Abhyankar    Input Parameter:
24282b4ed282SShri Abhyankar .  snes - the SNES context
24292b4ed282SShri Abhyankar 
24302b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
24312b4ed282SShri Abhyankar */
24322b4ed282SShri Abhyankar #undef __FUNCT__
24332b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
24342b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
24352b4ed282SShri Abhyankar {
24362b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI *)snes->data;
2437b350b9c9SBarry Smith   const char         *vies[] = {"ss","rs","rsaug"};
24382b4ed282SShri Abhyankar   PetscErrorCode     ierr;
24392b4ed282SShri Abhyankar   PetscInt           indx;
24400661309fSPeter Brune   PetscBool          flg,flg2;
24412b4ed282SShri Abhyankar 
24422b4ed282SShri Abhyankar   PetscFunctionBegin;
24432b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
24449308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
24459308c137SBarry Smith   if (flg) {
24469308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
24479308c137SBarry Smith   }
24482b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
24495b071b1aSBarry Smith   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"rs",&indx,&flg2);CHKERRQ(ierr);
245069c03620SShri Abhyankar   if (flg2) {
245169c03620SShri Abhyankar     switch (indx) {
245269c03620SShri Abhyankar     case 0:
245369c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
245469c03620SShri Abhyankar       break;
245569c03620SShri Abhyankar     case 1:
2456d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2457d950fb63SShri Abhyankar       break;
24582f63a38cSShri Abhyankar     case 2:
2459b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
246069c03620SShri Abhyankar     }
246169c03620SShri Abhyankar   }
2462e6337399SBarry Smith   ierr = PetscOptionsBool("-snes_vi_ignore_function_sign","Ignore the sign of function for active constraints","None",vi->ignorefunctionsign,&vi->ignorefunctionsign,PETSC_NULL);CHKERRQ(ierr);
24632b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
24642b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24652b4ed282SShri Abhyankar }
246692c02d66SPeter Brune 
246792c02d66SPeter Brune EXTERN_C_BEGIN
246892c02d66SPeter Brune #undef __FUNCT__
246992c02d66SPeter Brune #define __FUNCT__ "SNESLineSearchSetType_VI"
247092c02d66SPeter Brune PetscErrorCode  SNESLineSearchSetType_VI(SNES snes, SNESLineSearchType type)
247192c02d66SPeter Brune {
247292c02d66SPeter Brune   PetscErrorCode ierr;
247392c02d66SPeter Brune   PetscFunctionBegin;
247492c02d66SPeter Brune 
247592c02d66SPeter Brune   switch (type) {
247692c02d66SPeter Brune   case SNES_LS_BASIC:
247792c02d66SPeter Brune     ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
247892c02d66SPeter Brune     break;
247992c02d66SPeter Brune   case SNES_LS_BASIC_NONORMS:
248092c02d66SPeter Brune     ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
248192c02d66SPeter Brune     break;
248292c02d66SPeter Brune   case SNES_LS_QUADRATIC:
248392c02d66SPeter Brune     ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
248492c02d66SPeter Brune     break;
248592c02d66SPeter Brune   case SNES_LS_CUBIC:
248692c02d66SPeter Brune     ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
248792c02d66SPeter Brune     break;
248892c02d66SPeter Brune   default:
248992c02d66SPeter Brune     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP,"Unknown line search type");
249092c02d66SPeter Brune     break;
249192c02d66SPeter Brune   }
249292c02d66SPeter Brune   snes->ls_type = type;
249392c02d66SPeter Brune   PetscFunctionReturn(0);
249492c02d66SPeter Brune }
249592c02d66SPeter Brune EXTERN_C_END
249692c02d66SPeter Brune 
24972b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24982b4ed282SShri Abhyankar /*MC
24998b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
25002b4ed282SShri Abhyankar 
25012b4ed282SShri Abhyankar    Options Database:
25028b4c83edSBarry Smith +   -snes_vi_type <ss,rs,rsaug> a semi-smooth solver, a reduced space active set method and a reduced space active set method that does not eliminate the active constraints from the Jacobian instead augments the Jacobian with
25038b4c83edSBarry Smith                                 additional variables that enforce the constraints
25048b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
25052b4ed282SShri Abhyankar 
25062b4ed282SShri Abhyankar 
25072b4ed282SShri Abhyankar    Level: beginner
25082b4ed282SShri Abhyankar 
25092b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
25102b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
25112b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
25122b4ed282SShri Abhyankar 
25132b4ed282SShri Abhyankar M*/
25142b4ed282SShri Abhyankar EXTERN_C_BEGIN
25152b4ed282SShri Abhyankar #undef __FUNCT__
25162b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
25177087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
25182b4ed282SShri Abhyankar {
25192b4ed282SShri Abhyankar   PetscErrorCode ierr;
25202b4ed282SShri Abhyankar   SNES_VI        *vi;
25212b4ed282SShri Abhyankar 
25222b4ed282SShri Abhyankar   PetscFunctionBegin;
25232176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
25242b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2525edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
25262b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
25272b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
25282b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
25292b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
25302b4ed282SShri Abhyankar 
253142f4f86dSBarry Smith   snes->usesksp             = PETSC_TRUE;
253242f4f86dSBarry Smith   snes->usespc              = PETSC_FALSE;
253342f4f86dSBarry Smith 
25342b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
25352b4ed282SShri Abhyankar   snes->data                 = (void*)vi;
25360661309fSPeter Brune   snes->ls_alpha             = 1.e-4;
25370661309fSPeter Brune   snes->maxstep              = 1.e8;
25380661309fSPeter Brune   snes->steptol              = 1.e-12;
25392b4ed282SShri Abhyankar   vi->const_tol              =  2.2204460492503131e-16;
25402f63a38cSShri Abhyankar   vi->checkredundancy        = PETSC_NULL;
254192c02d66SPeter Brune 
254292c02d66SPeter Brune   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetType_C","SNESLineSearchSetType_VI",SNESLineSearchSetType_VI);CHKERRQ(ierr);
254392c02d66SPeter Brune   ierr = SNESLineSearchSetType(snes, SNES_LS_CUBIC);CHKERRQ(ierr);
254492c02d66SPeter Brune 
25452b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25462b4ed282SShri Abhyankar }
25472b4ed282SShri Abhyankar EXTERN_C_END
2548ed70e96aSJungho Lee 
2549ed70e96aSJungho Lee #undef __FUNCT__
2550ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet"
2551ed70e96aSJungho Lee /*
2552ed70e96aSJungho Lee    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
2553ed70e96aSJungho Lee      system is solved on)
2554ed70e96aSJungho Lee 
2555ed70e96aSJungho Lee    Input parameter
2556ed70e96aSJungho Lee .  snes - the SNES context
2557ed70e96aSJungho Lee 
2558ed70e96aSJungho Lee    Output parameter
2559ed70e96aSJungho Lee .  ISact - active set index set
2560ed70e96aSJungho Lee 
2561ed70e96aSJungho Lee  */
2562ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact)
2563ed70e96aSJungho Lee {
2564ed70e96aSJungho Lee   SNES_VI          *vi = (SNES_VI*)snes->data;
2565ed70e96aSJungho Lee   PetscFunctionBegin;
2566ed70e96aSJungho Lee   *inact = vi->IS_inact_prev;
2567ed70e96aSJungho Lee   PetscFunctionReturn(0);
2568ed70e96aSJungho Lee }
2569