xref: /petsc/src/snes/impls/vi/vi.c (revision 2176524cb94b9af842f9e8459f83df3e4e740f55)
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__
8*2176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds"
9*2176524cSBarry Smith /*@C
10*2176524cSBarry Smith    SNESVISetComputeVariableBounds - Sets a function  that is called to compute the variable bounds
11*2176524cSBarry Smith 
12*2176524cSBarry Smith    Input parameter
13*2176524cSBarry Smith +  snes - the SNES context
14*2176524cSBarry Smith -  compute - computes the bounds
15*2176524cSBarry Smith 
16*2176524cSBarry Smith 
17*2176524cSBarry Smith C@*/
18*2176524cSBarry Smith PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec*,Vec*))
19*2176524cSBarry Smith {
20*2176524cSBarry Smith   PetscErrorCode   ierr;
21*2176524cSBarry Smith   SNES_VI          *vi;
22*2176524cSBarry Smith 
23*2176524cSBarry Smith   PetscFunctionBegin;
24*2176524cSBarry Smith   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
25*2176524cSBarry Smith   vi = (SNES_VI*)snes->data;
26*2176524cSBarry Smith   vi->computevariablebounds = compute;
27*2176524cSBarry Smith   PetscFunctionReturn(0);
28*2176524cSBarry Smith }
29*2176524cSBarry Smith 
30*2176524cSBarry Smith 
31*2176524cSBarry Smith #undef __FUNCT__
32d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS"
33d0af7cd3SBarry Smith /*
34d0af7cd3SBarry Smith    SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables
35d0af7cd3SBarry Smith 
36d0af7cd3SBarry Smith    Input parameter
37d0af7cd3SBarry Smith .  snes - the SNES context
38d0af7cd3SBarry Smith .  X    - the snes solution vector
39d0af7cd3SBarry Smith 
40d0af7cd3SBarry Smith    Output parameter
41d0af7cd3SBarry Smith .  ISact - active set index set
42d0af7cd3SBarry Smith 
43d0af7cd3SBarry Smith  */
44d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
45d0af7cd3SBarry Smith {
46d0af7cd3SBarry Smith   PetscErrorCode   ierr;
47d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
48d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
49d0af7cd3SBarry Smith 
50d0af7cd3SBarry Smith   PetscFunctionBegin;
51d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
52d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
53d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
54d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
55d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
56d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
57d0af7cd3SBarry Smith   /* Compute inactive set size */
58d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
59d0af7cd3SBarry 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++;
60d0af7cd3SBarry Smith   }
61d0af7cd3SBarry Smith 
62d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
63d0af7cd3SBarry Smith 
64d0af7cd3SBarry Smith   /* Set inactive set indices */
65d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
66d0af7cd3SBarry 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;
67d0af7cd3SBarry Smith   }
68d0af7cd3SBarry Smith 
69d0af7cd3SBarry Smith    /* Create inactive set IS */
70d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
71d0af7cd3SBarry Smith 
72d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
73d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
74d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
75d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
76d0af7cd3SBarry Smith   PetscFunctionReturn(0);
77d0af7cd3SBarry Smith }
78d0af7cd3SBarry Smith 
793c0c59f3SBarry Smith /*
803c0c59f3SBarry 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
813c0c59f3SBarry Smith   defined by the reduced space method.
823c0c59f3SBarry Smith 
833c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
843c0c59f3SBarry Smith 
853c0c59f3SBarry Smith */
863c0c59f3SBarry Smith typedef struct {
873c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
883c0c59f3SBarry Smith   IS             inactive;
893c0c59f3SBarry Smith   Vec            upper,lower,values,F;                    /* upper and lower bounds of all variables on this level, the values and the function values */
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);
140d0af7cd3SBarry Smith   PetscFunctionReturn(0);
141d0af7cd3SBarry Smith }
142d0af7cd3SBarry Smith 
143d0af7cd3SBarry Smith extern PetscErrorCode  DMSetVI(DM,Vec,Vec,Vec,Vec,IS);
144d0af7cd3SBarry Smith 
145d0af7cd3SBarry Smith #undef __FUNCT__
146d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
147d0af7cd3SBarry Smith /*
148d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
149d0af7cd3SBarry Smith 
150d0af7cd3SBarry Smith */
151d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
152d0af7cd3SBarry Smith {
153d0af7cd3SBarry Smith   PetscErrorCode          ierr;
154d0af7cd3SBarry Smith   PetscContainer          isnes;
1553c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
156d0af7cd3SBarry Smith   Vec                     upper,lower,values,F;
157d0af7cd3SBarry Smith   IS                      inactive;
158d0af7cd3SBarry Smith   VecScatter              inject;
159d0af7cd3SBarry Smith 
160d0af7cd3SBarry Smith   PetscFunctionBegin;
161d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1624c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
163d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
164d0af7cd3SBarry Smith 
165298cc208SBarry Smith   /* get the original coarsen */
166d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
167298cc208SBarry Smith 
1683c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1693c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1703c0c59f3SBarry Smith 
171298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
172298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
173298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
174d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
175d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr);
176d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
177d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
178d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr);
179d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
180d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
181d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr);
182d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
183d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr);
185d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
186d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
188298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
189298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
190d0af7cd3SBarry Smith   ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr);
191d0af7cd3SBarry Smith   ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr);
1923c0c59f3SBarry Smith   ierr = VecDestroy(&upper);CHKERRQ(ierr);
1933c0c59f3SBarry Smith   ierr = VecDestroy(&lower);CHKERRQ(ierr);
1943c0c59f3SBarry Smith   ierr = VecDestroy(&values);CHKERRQ(ierr);
1953c0c59f3SBarry Smith   ierr = VecDestroy(&F);CHKERRQ(ierr);
1963c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
197d0af7cd3SBarry Smith   PetscFunctionReturn(0);
198d0af7cd3SBarry Smith }
199d0af7cd3SBarry Smith 
200d0af7cd3SBarry Smith #undef __FUNCT__
2013c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2023c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
203d0af7cd3SBarry Smith {
204d0af7cd3SBarry Smith   PetscErrorCode ierr;
205d0af7cd3SBarry Smith 
206d0af7cd3SBarry Smith   PetscFunctionBegin;
2074c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2084c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2094c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2104c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
2114c661befSBarry Smith 
212d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
213d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
214d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
215d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
216d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
217d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
218d0af7cd3SBarry Smith   PetscFunctionReturn(0);
219d0af7cd3SBarry Smith }
220d0af7cd3SBarry Smith 
221d0af7cd3SBarry Smith #undef __FUNCT__
222d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
223d0af7cd3SBarry Smith /*
224d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
225d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
226d0af7cd3SBarry Smith 
227d0af7cd3SBarry Smith */
228d0af7cd3SBarry Smith PetscErrorCode  DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive)
229d0af7cd3SBarry Smith {
230d0af7cd3SBarry Smith   PetscErrorCode          ierr;
231d0af7cd3SBarry Smith   PetscContainer          isnes;
2323c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
233d0af7cd3SBarry Smith 
234d0af7cd3SBarry Smith   PetscFunctionBegin;
2354dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
236d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr);
237d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr);
238d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr);
239d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
240d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
241d0af7cd3SBarry Smith 
242d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
243d0af7cd3SBarry Smith   if (!isnes) {
244d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2453c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2463c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
247d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
248d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2493c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
250d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
251d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
252d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
253d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
254298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2554dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
2566ba4bc90SBarry Smith     /* since these vectors may reference the DM, need to remove circle referencing */
2576ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr);
2586ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr);
2596ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr);
2606ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr);
261d0af7cd3SBarry Smith   } else {
262d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
263d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
264d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
265d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
266d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
267d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
268d0af7cd3SBarry Smith   }
2694dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2704dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
271d0af7cd3SBarry Smith   dmsnesvi->upper    = upper;
272d0af7cd3SBarry Smith   dmsnesvi->lower    = lower;
273d0af7cd3SBarry Smith   dmsnesvi->values   = values;
274d0af7cd3SBarry Smith   dmsnesvi->F        = F;
275d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2761a223a97SBarry Smith   dmsnesvi->dm       = dm;
277d0af7cd3SBarry Smith   PetscFunctionReturn(0);
278d0af7cd3SBarry Smith }
279d0af7cd3SBarry Smith 
2804c661befSBarry Smith #undef __FUNCT__
2814c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2824c661befSBarry Smith /*
2834c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2844c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2854c661befSBarry Smith */
2864c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2874c661befSBarry Smith {
2884c661befSBarry Smith   PetscErrorCode          ierr;
2894c661befSBarry Smith 
2904c661befSBarry Smith   PetscFunctionBegin;
2914c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
2924c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
2934c661befSBarry Smith   PetscFunctionReturn(0);
2944c661befSBarry Smith }
2954c661befSBarry Smith 
2963c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
2972b4ed282SShri Abhyankar 
2989308c137SBarry Smith #undef __FUNCT__
2999308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3007087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3019308c137SBarry Smith {
3029308c137SBarry Smith   PetscErrorCode          ierr;
3039308c137SBarry Smith   SNES_VI                 *vi = (SNES_VI*)snes->data;
3049308c137SBarry Smith   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
3059308c137SBarry Smith   const PetscScalar       *x,*xl,*xu,*f;
30609573ac7SBarry Smith   PetscInt                i,n,act = 0;
3079308c137SBarry Smith   PetscReal               rnorm,fnorm;
3089308c137SBarry Smith 
3099308c137SBarry Smith   PetscFunctionBegin;
3109308c137SBarry Smith   if (!dummy) {
3119308c137SBarry Smith     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
3129308c137SBarry Smith   }
3139308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3149308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3159308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3169308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3173f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3189308c137SBarry Smith 
3199308c137SBarry Smith   rnorm = 0.0;
3209308c137SBarry Smith   for (i=0; i<n; i++) {
32110f5ae6bSBarry 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]);
32209573ac7SBarry Smith     else act++;
3239308c137SBarry Smith   }
3243f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3259308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3269308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3279308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
328d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3299308c137SBarry Smith   fnorm = sqrt(fnorm);
33009573ac7SBarry Smith   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
3319308c137SBarry Smith   if (!dummy) {
3326bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr);
3339308c137SBarry Smith   }
3349308c137SBarry Smith   PetscFunctionReturn(0);
3359308c137SBarry Smith }
3369308c137SBarry Smith 
3372b4ed282SShri Abhyankar /*
3382b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3392b4ed282SShri 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
3402b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3412b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3422b4ed282SShri Abhyankar */
3432b4ed282SShri Abhyankar #undef __FUNCT__
3442b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
345ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3462b4ed282SShri Abhyankar {
3472b4ed282SShri Abhyankar   PetscReal      a1;
3482b4ed282SShri Abhyankar   PetscErrorCode ierr;
349ace3abfcSBarry Smith   PetscBool     hastranspose;
3502b4ed282SShri Abhyankar 
3512b4ed282SShri Abhyankar   PetscFunctionBegin;
3522b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3532b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3542b4ed282SShri Abhyankar   if (hastranspose) {
3552b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3562b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3572b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3582b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3592b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3602b4ed282SShri Abhyankar   } else {
3612b4ed282SShri Abhyankar     Vec         work;
3622b4ed282SShri Abhyankar     PetscScalar result;
3632b4ed282SShri Abhyankar     PetscReal   wnorm;
3642b4ed282SShri Abhyankar 
3652b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3662b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3672b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3682b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3692b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3706bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3712b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3722b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3732b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3742b4ed282SShri Abhyankar   }
3752b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3762b4ed282SShri Abhyankar }
3772b4ed282SShri Abhyankar 
3782b4ed282SShri Abhyankar /*
3792b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3802b4ed282SShri Abhyankar */
3812b4ed282SShri Abhyankar #undef __FUNCT__
3822b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3832b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3842b4ed282SShri Abhyankar {
3852b4ed282SShri Abhyankar   PetscReal      a1,a2;
3862b4ed282SShri Abhyankar   PetscErrorCode ierr;
387ace3abfcSBarry Smith   PetscBool     hastranspose;
3882b4ed282SShri Abhyankar 
3892b4ed282SShri Abhyankar   PetscFunctionBegin;
3902b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3912b4ed282SShri Abhyankar   if (hastranspose) {
3922b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3932b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3942b4ed282SShri Abhyankar 
3952b4ed282SShri Abhyankar     /* Compute || J^T W|| */
3962b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
3972b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
3982b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
3992b4ed282SShri Abhyankar     if (a1 != 0.0) {
4002b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
4012b4ed282SShri Abhyankar     }
4022b4ed282SShri Abhyankar   }
4032b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4042b4ed282SShri Abhyankar }
4052b4ed282SShri Abhyankar 
4062b4ed282SShri Abhyankar /*
4072b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4082b4ed282SShri Abhyankar 
4092b4ed282SShri Abhyankar   Notes:
4102b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4112b4ed282SShri Abhyankar   merit < abstol
4122b4ed282SShri Abhyankar   merit < rtol*merit_initial
4132b4ed282SShri Abhyankar */
4142b4ed282SShri Abhyankar #undef __FUNCT__
4152b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4167fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4172b4ed282SShri Abhyankar {
4182b4ed282SShri Abhyankar   PetscErrorCode ierr;
4192b4ed282SShri Abhyankar 
4202b4ed282SShri Abhyankar   PetscFunctionBegin;
4212b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4222b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4232b4ed282SShri Abhyankar 
4242b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4252b4ed282SShri Abhyankar 
4262b4ed282SShri Abhyankar   if (!it) {
4272b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4287fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4292b4ed282SShri Abhyankar   }
4307fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4312b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4322b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4337fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4347fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4352b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4362b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4372b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4382b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4392b4ed282SShri Abhyankar   }
4402b4ed282SShri Abhyankar 
4412b4ed282SShri Abhyankar   if (it && !*reason) {
4427fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4437fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4442b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4452b4ed282SShri Abhyankar     }
4462b4ed282SShri Abhyankar   }
4472b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4482b4ed282SShri Abhyankar }
4492b4ed282SShri Abhyankar 
4502b4ed282SShri Abhyankar /*
4512b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4522b4ed282SShri Abhyankar 
4532b4ed282SShri Abhyankar   Input Parameter:
4542b4ed282SShri Abhyankar . phi - the semismooth function
4552b4ed282SShri Abhyankar 
4562b4ed282SShri Abhyankar   Output Parameter:
4572b4ed282SShri Abhyankar . merit - the merit function
4582b4ed282SShri Abhyankar . phinorm - ||phi||
4592b4ed282SShri Abhyankar 
4602b4ed282SShri Abhyankar   Notes:
4612b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4622b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4632b4ed282SShri Abhyankar */
4642b4ed282SShri Abhyankar #undef __FUNCT__
4652b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4662b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4672b4ed282SShri Abhyankar {
4682b4ed282SShri Abhyankar   PetscErrorCode ierr;
4692b4ed282SShri Abhyankar 
4702b4ed282SShri Abhyankar   PetscFunctionBegin;
4715f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4725f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4732b4ed282SShri Abhyankar 
4742b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4752b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4762b4ed282SShri Abhyankar }
4772b4ed282SShri Abhyankar 
4787f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4794c21c6cdSBarry Smith {
4804c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4814c21c6cdSBarry Smith }
4824c21c6cdSBarry Smith 
4837f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4844c21c6cdSBarry Smith {
4855559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4865559b345SBarry Smith   else return .5;
4874c21c6cdSBarry Smith }
4884c21c6cdSBarry Smith 
4892b4ed282SShri Abhyankar /*
4901f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4912b4ed282SShri Abhyankar 
4922b4ed282SShri Abhyankar    Input Parameters:
4932b4ed282SShri Abhyankar .  snes - the SNES context
4942b4ed282SShri Abhyankar .  x - current iterate
4952b4ed282SShri Abhyankar .  functx - user defined function context
4962b4ed282SShri Abhyankar 
4972b4ed282SShri Abhyankar    Output Parameters:
4982b4ed282SShri Abhyankar .  phi - Semismooth function
4992b4ed282SShri Abhyankar 
5002b4ed282SShri Abhyankar */
5012b4ed282SShri Abhyankar #undef __FUNCT__
5021f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5031f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5042b4ed282SShri Abhyankar {
5052b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5062b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5072b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5084c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5092b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5102b4ed282SShri Abhyankar 
5112b4ed282SShri Abhyankar   PetscFunctionBegin;
5122b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5132b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5142b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5152b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5162b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5172b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5182b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5192b4ed282SShri Abhyankar 
5202b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
52110f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5224c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
52310f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5244c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
52510f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5264c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5275559b345SBarry Smith     } else if (l[i] == u[i]) {
5282b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5295559b345SBarry Smith     } else {                                                /* both bounds on variable */
5304c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5312b4ed282SShri Abhyankar     }
5322b4ed282SShri Abhyankar   }
5332b4ed282SShri Abhyankar 
5342b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5352b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5362b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5372b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5382b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5392b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5402b4ed282SShri Abhyankar }
5412b4ed282SShri Abhyankar 
5422b4ed282SShri Abhyankar /*
543a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
544a79edbefSShri Abhyankar                                           the semismooth jacobian.
5452b4ed282SShri Abhyankar */
5462b4ed282SShri Abhyankar #undef __FUNCT__
547a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
548a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5492b4ed282SShri Abhyankar {
5502b4ed282SShri Abhyankar   PetscErrorCode ierr;
5512b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5524c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5532b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5542b4ed282SShri Abhyankar 
5552b4ed282SShri Abhyankar   PetscFunctionBegin;
5562b4ed282SShri Abhyankar 
5572b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5582b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5592b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5602b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
561a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
562a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5632b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5644c21c6cdSBarry Smith 
5652b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
56610f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5674c21c6cdSBarry Smith       da[i] = 0;
5682b4ed282SShri Abhyankar       db[i] = 1;
56910f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5704c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5714c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
57210f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5735559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5745559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5755559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5764c21c6cdSBarry Smith       da[i] = 1;
5772b4ed282SShri Abhyankar       db[i] = 0;
5785559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5794c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5804c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5814c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5824c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5834c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5844c21c6cdSBarry Smith       db[i] = db1*db2;
5852b4ed282SShri Abhyankar     }
5862b4ed282SShri Abhyankar   }
5875559b345SBarry Smith 
5882b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5892b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5902b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5912b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
592a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
593a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
594a79edbefSShri Abhyankar   PetscFunctionReturn(0);
595a79edbefSShri Abhyankar }
596a79edbefSShri Abhyankar 
597a79edbefSShri Abhyankar /*
598a79edbefSShri 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.
599a79edbefSShri Abhyankar 
600a79edbefSShri Abhyankar    Input Parameters:
601a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
602a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
603a79edbefSShri Abhyankar 
604a79edbefSShri Abhyankar    Output Parameters:
605a79edbefSShri Abhyankar .  jac      - semismooth jacobian
606a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
607a79edbefSShri Abhyankar 
608a79edbefSShri Abhyankar    Notes:
609a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
610a79edbefSShri Abhyankar    jac = Da + Db*jacfun
611a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
612a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
613a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
614a79edbefSShri Abhyankar */
615a79edbefSShri Abhyankar #undef __FUNCT__
616a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
617a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
618a79edbefSShri Abhyankar {
619a79edbefSShri Abhyankar   PetscErrorCode ierr;
620a79edbefSShri Abhyankar 
6212b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
622a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
623a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
624a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
625a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
626a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6272b4ed282SShri Abhyankar   }
6282b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6292b4ed282SShri Abhyankar }
6302b4ed282SShri Abhyankar 
6312b4ed282SShri Abhyankar /*
632ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
633ee657d29SShri Abhyankar 
634ee657d29SShri Abhyankar    Input Parameters:
635ee657d29SShri Abhyankar    phi - semismooth function.
636ee657d29SShri Abhyankar    H   - semismooth jacobian
637ee657d29SShri Abhyankar 
638ee657d29SShri Abhyankar    Output Parameters:
639ee657d29SShri Abhyankar    dpsi - merit function gradient
640ee657d29SShri Abhyankar 
641ee657d29SShri Abhyankar    Notes:
642ee657d29SShri Abhyankar   The merit function gradient is computed as follows
643ee657d29SShri Abhyankar         dpsi = H^T*phi
644ee657d29SShri Abhyankar */
645ee657d29SShri Abhyankar #undef __FUNCT__
646ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
647ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
648ee657d29SShri Abhyankar {
649ee657d29SShri Abhyankar   PetscErrorCode ierr;
650ee657d29SShri Abhyankar 
651ee657d29SShri Abhyankar   PetscFunctionBegin;
6525f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
653ee657d29SShri Abhyankar   PetscFunctionReturn(0);
654ee657d29SShri Abhyankar }
655ee657d29SShri Abhyankar 
656c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
657c1a5e521SShri Abhyankar /*
658c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
659c1a5e521SShri Abhyankar 
660c1a5e521SShri Abhyankar    Input Parameters:
661c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
662c1a5e521SShri Abhyankar 
663c1a5e521SShri Abhyankar    Output Parameters:
664c1a5e521SShri Abhyankar .  X - Bound projected X
665c1a5e521SShri Abhyankar 
666c1a5e521SShri Abhyankar */
667c1a5e521SShri Abhyankar 
668c1a5e521SShri Abhyankar #undef __FUNCT__
669c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
670c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
671c1a5e521SShri Abhyankar {
672c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
673c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
674c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
675c1a5e521SShri Abhyankar   PetscScalar       *x;
676c1a5e521SShri Abhyankar   PetscInt          i,n;
677c1a5e521SShri Abhyankar 
678c1a5e521SShri Abhyankar   PetscFunctionBegin;
679c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
680c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
681c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
682c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
683c1a5e521SShri Abhyankar 
684c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
68510f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
68610f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
687c1a5e521SShri Abhyankar   }
688c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
689c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
690c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
691c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
692c1a5e521SShri Abhyankar }
693c1a5e521SShri Abhyankar 
6942b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
6952b4ed282SShri Abhyankar 
6962b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
6972b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
6982b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
6992b4ed282SShri Abhyankar      respectively.
7002b4ed282SShri Abhyankar 
7012b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7022b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7032b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7042b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7052b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7062b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7072b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7082b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7092b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7102b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7112b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7122b4ed282SShri Abhyankar      for all nonlinear solvers.
7132b4ed282SShri Abhyankar 
7142b4ed282SShri Abhyankar      Another key routine is:
7152b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7162b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7172b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7182b4ed282SShri Abhyankar      SNESSolve() if necessary.
7192b4ed282SShri Abhyankar 
7202b4ed282SShri Abhyankar      Additional basic routines are:
7212b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7222b4ed282SShri Abhyankar                                       have actually been used.
7232b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7242b4ed282SShri Abhyankar      SNESView().
7252b4ed282SShri Abhyankar 
7262b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7272b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7282b4ed282SShri Abhyankar      above description applies to these categories also.
7292b4ed282SShri Abhyankar 
7302b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7312b4ed282SShri Abhyankar /*
73269c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7332b4ed282SShri Abhyankar    method using a line search.
7342b4ed282SShri Abhyankar 
7352b4ed282SShri Abhyankar    Input Parameters:
7362b4ed282SShri Abhyankar .  snes - the SNES context
7372b4ed282SShri Abhyankar 
7382b4ed282SShri Abhyankar    Output Parameter:
7392b4ed282SShri Abhyankar .  outits - number of iterations until termination
7402b4ed282SShri Abhyankar 
7412b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7422b4ed282SShri Abhyankar 
7432b4ed282SShri Abhyankar    Notes:
7442b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
74551defd01SShri Abhyankar    line search. The default line search does not do any line seach
74651defd01SShri Abhyankar    but rather takes a full newton step.
7472b4ed282SShri Abhyankar */
7482b4ed282SShri Abhyankar #undef __FUNCT__
74969c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
75069c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7512b4ed282SShri Abhyankar {
7522b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7532b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7542b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7553b336b49SShri Abhyankar   PetscBool          lssucceed;
7562b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7572b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7582b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7592b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7602b4ed282SShri Abhyankar 
7612b4ed282SShri Abhyankar   PetscFunctionBegin;
7629ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7639ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7649ce7406fSBarry Smith 
7652b4ed282SShri Abhyankar   snes->numFailures            = 0;
7662b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7672b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7682b4ed282SShri Abhyankar 
7692b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7702b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7712b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7722b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7732b4ed282SShri Abhyankar   G		= snes->work[1];
7742b4ed282SShri Abhyankar   W		= snes->work[2];
7752b4ed282SShri Abhyankar 
7762b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7772b4ed282SShri Abhyankar   snes->iter = 0;
7782b4ed282SShri Abhyankar   snes->norm = 0.0;
7792b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7802b4ed282SShri Abhyankar 
7817fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7822b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7832b4ed282SShri Abhyankar   if (snes->domainerror) {
7842b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7859ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7862b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7872b4ed282SShri Abhyankar   }
7882b4ed282SShri Abhyankar    /* Compute Merit function */
7892b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7902b4ed282SShri Abhyankar 
7912b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7922b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
79362cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7942b4ed282SShri Abhyankar 
7952b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7962b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
7972b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7982b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
7997a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8002b4ed282SShri Abhyankar 
8012b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8022b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8032b4ed282SShri Abhyankar   /* test convergence */
8042b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8059ce7406fSBarry Smith   if (snes->reason) {
8069ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8079ce7406fSBarry Smith     PetscFunctionReturn(0);
8089ce7406fSBarry Smith   }
8092b4ed282SShri Abhyankar 
8102b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8112b4ed282SShri Abhyankar 
8122b4ed282SShri Abhyankar     /* Call general purpose update function */
8132b4ed282SShri Abhyankar     if (snes->ops->update) {
8142b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8152b4ed282SShri Abhyankar     }
8162b4ed282SShri Abhyankar 
8172b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
818a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8192b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
820a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
821a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
822a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
823a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
824ee657d29SShri Abhyankar     /* Compute the merit function gradient */
825ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8262b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8272b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8282b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8293b336b49SShri Abhyankar 
8303b336b49SShri Abhyankar     if (kspreason < 0) {
8312b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8322b4ed282SShri 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);
8332b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8342b4ed282SShri Abhyankar         break;
8352b4ed282SShri Abhyankar       }
8362b4ed282SShri Abhyankar     }
8372b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8382b4ed282SShri Abhyankar     snes->linear_its += lits;
8392b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8402b4ed282SShri Abhyankar     /*
8412b4ed282SShri Abhyankar     if (vi->precheckstep) {
842ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8432b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8442b4ed282SShri Abhyankar     }
8452b4ed282SShri Abhyankar 
8462b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8472b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8482b4ed282SShri Abhyankar     }
8492b4ed282SShri Abhyankar     */
8502b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8512b4ed282SShri Abhyankar          Y <- X - lambda*Y
8522b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8532b4ed282SShri Abhyankar     */
8542b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8552b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8562b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8572b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8582b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8592b4ed282SShri Abhyankar     if (snes->domainerror) {
8602b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8619ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8622b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8632b4ed282SShri Abhyankar     }
8642b4ed282SShri Abhyankar     if (!lssucceed) {
8652b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
866ace3abfcSBarry Smith 	PetscBool ismin;
8672b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8682b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8692b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8702b4ed282SShri Abhyankar         break;
8712b4ed282SShri Abhyankar       }
8722b4ed282SShri Abhyankar     }
8732b4ed282SShri Abhyankar     /* Update function and solution vectors */
8742b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8752b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8762b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8772b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8782b4ed282SShri Abhyankar     /* Monitor convergence */
8792b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8802b4ed282SShri Abhyankar     snes->iter = i+1;
8812b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8822b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8832b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8847a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8852b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8862b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8872b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8882b4ed282SShri Abhyankar     if (snes->reason) break;
8892b4ed282SShri Abhyankar   }
8902b4ed282SShri Abhyankar   if (i == maxits) {
8912b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8922b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8932b4ed282SShri Abhyankar   }
8949ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
8952b4ed282SShri Abhyankar   PetscFunctionReturn(0);
8962b4ed282SShri Abhyankar }
89769c03620SShri Abhyankar 
89869c03620SShri Abhyankar #undef __FUNCT__
899693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
900693ddf92SShri Abhyankar /*
901693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
902693ddf92SShri Abhyankar 
903693ddf92SShri Abhyankar    Input parameter
904693ddf92SShri Abhyankar .  snes - the SNES context
905693ddf92SShri Abhyankar .  X    - the snes solution vector
906693ddf92SShri Abhyankar .  F    - the nonlinear function vector
907693ddf92SShri Abhyankar 
908693ddf92SShri Abhyankar    Output parameter
909693ddf92SShri Abhyankar .  ISact - active set index set
910693ddf92SShri Abhyankar  */
911693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
912d950fb63SShri Abhyankar {
913d950fb63SShri Abhyankar   PetscErrorCode   ierr;
914693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
915693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
916693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
917693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
918d950fb63SShri Abhyankar 
919d950fb63SShri Abhyankar   PetscFunctionBegin;
920d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
921d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
922fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
923fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
924fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
925fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
926693ddf92SShri Abhyankar   /* Compute active set size */
927d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
92810f5ae6bSBarry 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++;
929d950fb63SShri Abhyankar   }
930693ddf92SShri Abhyankar 
931d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
932d950fb63SShri Abhyankar 
933693ddf92SShri Abhyankar   /* Set active set indices */
934d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
93510f5ae6bSBarry 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;
936d950fb63SShri Abhyankar   }
937d950fb63SShri Abhyankar 
938693ddf92SShri Abhyankar    /* Create active set IS */
93962298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
940d950fb63SShri Abhyankar 
941fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
942fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
943fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
944fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
945d950fb63SShri Abhyankar   PetscFunctionReturn(0);
946d950fb63SShri Abhyankar }
947d950fb63SShri Abhyankar 
948693ddf92SShri Abhyankar #undef __FUNCT__
949693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
950693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
951693ddf92SShri Abhyankar {
952693ddf92SShri Abhyankar   PetscErrorCode     ierr;
953693ddf92SShri Abhyankar 
954693ddf92SShri Abhyankar   PetscFunctionBegin;
955693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
956693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
957693ddf92SShri Abhyankar   PetscFunctionReturn(0);
958693ddf92SShri Abhyankar }
959693ddf92SShri Abhyankar 
960dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
961dbd914b8SShri Abhyankar #undef __FUNCT__
962fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
963fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
964dbd914b8SShri Abhyankar {
965dbd914b8SShri Abhyankar   PetscErrorCode ierr;
966dbd914b8SShri Abhyankar   Vec            v;
967dbd914b8SShri Abhyankar 
968dbd914b8SShri Abhyankar   PetscFunctionBegin;
969dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
970dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
971dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
972dbd914b8SShri Abhyankar   *newv = v;
973dbd914b8SShri Abhyankar 
974dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
975dbd914b8SShri Abhyankar }
976dbd914b8SShri Abhyankar 
977732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
978732bb160SShri Abhyankar #undef __FUNCT__
979732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
980732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
981732bb160SShri Abhyankar {
982732bb160SShri Abhyankar   PetscErrorCode         ierr;
983d0af7cd3SBarry Smith   KSP                    snesksp;
984dbd914b8SShri Abhyankar 
985732bb160SShri Abhyankar   PetscFunctionBegin;
986732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
987d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
988c2efdce3SBarry Smith 
989c2efdce3SBarry Smith   /*
990d0af7cd3SBarry Smith   KSP                    kspnew;
991d0af7cd3SBarry Smith   PC                     pcnew;
992d0af7cd3SBarry Smith   const MatSolverPackage stype;
993d0af7cd3SBarry Smith 
994c2efdce3SBarry Smith 
995732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
996732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
997732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
998732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
999732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1000732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1001732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1002732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1003732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1004732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1005732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10066bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1007732bb160SShri Abhyankar   snes->ksp = kspnew;
1008732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1009d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1010732bb160SShri Abhyankar   PetscFunctionReturn(0);
1011732bb160SShri Abhyankar }
101269c03620SShri Abhyankar 
101369c03620SShri Abhyankar 
1014fe835674SShri Abhyankar #undef __FUNCT__
1015fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
101610f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1017fe835674SShri Abhyankar {
1018fe835674SShri Abhyankar   PetscErrorCode    ierr;
1019fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1020fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1021fe835674SShri Abhyankar   PetscInt          i,n;
1022fe835674SShri Abhyankar   PetscReal         rnorm;
1023fe835674SShri Abhyankar 
1024fe835674SShri Abhyankar   PetscFunctionBegin;
1025fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1026fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1027fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1028fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1029fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1030fe835674SShri Abhyankar   rnorm = 0.0;
1031fe835674SShri Abhyankar   for (i=0; i<n; i++) {
103210f5ae6bSBarry 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]);
1033fe835674SShri Abhyankar   }
1034fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1035fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1036fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1037fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1038d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1039fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1040fe835674SShri Abhyankar   PetscFunctionReturn(0);
1041fe835674SShri Abhyankar }
1042fe835674SShri Abhyankar 
1043fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1044c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1045c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1046d950fb63SShri Abhyankar #undef __FUNCT__
1047d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1048d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1049d950fb63SShri Abhyankar {
1050d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1051d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1052abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1053d950fb63SShri Abhyankar   PetscBool         lssucceed;
1054d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1055fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1056d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1057d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1058d950fb63SShri Abhyankar 
1059d950fb63SShri Abhyankar   PetscFunctionBegin;
1060d950fb63SShri Abhyankar   snes->numFailures            = 0;
1061d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1062d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1063d950fb63SShri Abhyankar 
1064d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1065d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1066d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1067d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1068d950fb63SShri Abhyankar   G		= snes->work[1];
1069d950fb63SShri Abhyankar   W		= snes->work[2];
1070d950fb63SShri Abhyankar 
1071d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1072d950fb63SShri Abhyankar   snes->iter = 0;
1073d950fb63SShri Abhyankar   snes->norm = 0.0;
1074d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1075d950fb63SShri Abhyankar 
10767fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1077fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1078d950fb63SShri Abhyankar   if (snes->domainerror) {
1079d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1080d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1081d950fb63SShri Abhyankar   }
1082fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1083d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1084d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
108562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1086d950fb63SShri Abhyankar 
1087d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1088fe835674SShri Abhyankar   snes->norm = fnorm;
1089d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1090fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10917a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1092d950fb63SShri Abhyankar 
1093d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1094fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1095d950fb63SShri Abhyankar   /* test convergence */
1096fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1097d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1098d950fb63SShri Abhyankar 
1099d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1100d950fb63SShri Abhyankar 
1101d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1102d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1103abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1104fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1105d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
110662298a1eSBarry Smith     IS         keptrows;
1107abcba341SShri Abhyankar     PetscBool  isequal;
1108d950fb63SShri Abhyankar 
1109d950fb63SShri Abhyankar     /* Call general purpose update function */
1110d950fb63SShri Abhyankar     if (snes->ops->update) {
1111d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1112d950fb63SShri Abhyankar     }
1113d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
111462298a1eSBarry Smith 
1115d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1116693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1117d950fb63SShri Abhyankar 
11184dcab191SBarry Smith 
1119abcba341SShri Abhyankar     /* Create inactive set submatrix */
112062298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1121b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
112262298a1eSBarry Smith     if (keptrows) {
112362298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
112462298a1eSBarry Smith       const PetscInt *krows,*inact;
112527d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
112662298a1eSBarry Smith 
11276bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11286bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
112962298a1eSBarry Smith 
113062298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
113162298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
113262298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
113362298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
113462298a1eSBarry Smith       for (k=0; k<cnt; k++) {
113527d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
113662298a1eSBarry Smith       }
113762298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
113862298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11396bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11406bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
114162298a1eSBarry Smith 
114227d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
114327d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
114462298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
114562298a1eSBarry Smith     }
11469e516c8fSBarry Smith     ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr);
114762298a1eSBarry Smith 
1148d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1149d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1150d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1151d950fb63SShri Abhyankar 
1152d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1153fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1154fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1155fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1156d950fb63SShri Abhyankar 
1157d950fb63SShri Abhyankar     /* Create scatter contexts */
1158d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1159d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1160d950fb63SShri Abhyankar 
1161d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1162fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1163fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1164d950fb63SShri Abhyankar 
1165d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1166d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1167d950fb63SShri Abhyankar 
1168d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1169d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1170d950fb63SShri Abhyankar 
1171d950fb63SShri Abhyankar     /* Active set direction = 0 */
1172d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1173d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1174d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1175d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1176d950fb63SShri Abhyankar 
1177abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1178abcba341SShri Abhyankar     if (!isequal) {
1179732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1180d950fb63SShri Abhyankar     }
1181d950fb63SShri Abhyankar 
118213e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
118313e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
118413e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
118513e0d083SBarry Smith 
1186d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
118713e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
118813e0d083SBarry Smith     {
118913e0d083SBarry Smith       PC        pc;
119013e0d083SBarry Smith       PetscBool flg;
119113e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
119213e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
119313e0d083SBarry Smith       if (flg) {
119413e0d083SBarry Smith         KSP      *subksps;
119513e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
119613e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
119713e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
119813e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
119913e0d083SBarry Smith         if (flg) {
120013e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
120113e0d083SBarry Smith           const PetscInt *ii;
120213e0d083SBarry Smith 
120313e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
120413e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
120513e0d083SBarry Smith           for (j=0; j<n; j++) {
120613e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
120713e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
120813e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
120913e0d083SBarry Smith           }
121013e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
121113e0d083SBarry Smith 
121213e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
121313e0d083SBarry Smith         }
121413e0d083SBarry Smith       }
121513e0d083SBarry Smith     }
121613e0d083SBarry Smith 
1217fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1218d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1219d950fb63SShri Abhyankar     if (kspreason < 0) {
1220d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1221d950fb63SShri 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);
1222d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1223d950fb63SShri Abhyankar         break;
1224d950fb63SShri Abhyankar       }
1225d950fb63SShri Abhyankar      }
1226d950fb63SShri Abhyankar 
1227d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1228d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1229d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1230d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1231d950fb63SShri Abhyankar 
12326bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12336bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
12346bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
12356bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
12366bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
12376bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1238abcba341SShri Abhyankar     if (!isequal) {
12396bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1240abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1241abcba341SShri Abhyankar     }
12426bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
12436bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1244d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
12456bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1246d950fb63SShri Abhyankar     }
1247d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1248d950fb63SShri Abhyankar     snes->linear_its += lits;
1249d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1250d950fb63SShri Abhyankar     /*
1251d950fb63SShri Abhyankar     if (vi->precheckstep) {
1252d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1253d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1254d950fb63SShri Abhyankar     }
1255d950fb63SShri Abhyankar 
1256d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1257d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1258d950fb63SShri Abhyankar     }
1259d950fb63SShri Abhyankar     */
1260d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1261d950fb63SShri Abhyankar          Y <- X - lambda*Y
1262d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1263d950fb63SShri Abhyankar     */
1264d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1265fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1266fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1267fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
12682b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
12692b4ed282SShri Abhyankar     if (snes->domainerror) {
12702b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
12714c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
12722b4ed282SShri Abhyankar       PetscFunctionReturn(0);
12732b4ed282SShri Abhyankar     }
12742b4ed282SShri Abhyankar     if (!lssucceed) {
12752b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
12762b4ed282SShri Abhyankar 	PetscBool ismin;
12772b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
12782b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
12792b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
12802b4ed282SShri Abhyankar         break;
12812b4ed282SShri Abhyankar       }
12822b4ed282SShri Abhyankar     }
12832b4ed282SShri Abhyankar     /* Update function and solution vectors */
1284fe835674SShri Abhyankar     fnorm = gnorm;
1285fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
12862b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
12872b4ed282SShri Abhyankar     /* Monitor convergence */
12882b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
12892b4ed282SShri Abhyankar     snes->iter = i+1;
1290fe835674SShri Abhyankar     snes->norm = fnorm;
12912b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
12922b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
12937a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
12942b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
12952b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1296fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
12972b4ed282SShri Abhyankar     if (snes->reason) break;
12982b4ed282SShri Abhyankar   }
12994c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13002b4ed282SShri Abhyankar   if (i == maxits) {
13012b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13022b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13032b4ed282SShri Abhyankar   }
13042b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13052b4ed282SShri Abhyankar }
13062b4ed282SShri Abhyankar 
13072f63a38cSShri Abhyankar #undef __FUNCT__
1308720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1309cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13102f63a38cSShri Abhyankar {
13112f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13122f63a38cSShri Abhyankar 
13132f63a38cSShri Abhyankar   PetscFunctionBegin;
13142f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13152f63a38cSShri Abhyankar   vi->checkredundancy = func;
1316cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13172f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13182f63a38cSShri Abhyankar }
13192f63a38cSShri Abhyankar 
1320ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1321ff596062SShri Abhyankar #include <engine.h>
1322ff596062SShri Abhyankar #include <mex.h>
1323cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1324ff596062SShri Abhyankar 
1325ff596062SShri Abhyankar #undef __FUNCT__
1326ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1327ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1328ff596062SShri Abhyankar {
1329ff596062SShri Abhyankar   PetscErrorCode      ierr;
1330cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1331cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1332cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1333cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1334fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1335ff596062SShri Abhyankar 
1336ff596062SShri Abhyankar   PetscFunctionBegin;
1337ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1338ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1339ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1340ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1341ff596062SShri Abhyankar 
134209db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
134309db5ad8SShri Abhyankar    bet set by the Matlab function */
1344fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1345cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1346ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1347ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1348cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1349ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1350ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1351cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1352cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1353cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1354ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1355ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1356ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1357ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1358ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1359ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1360ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1361ff596062SShri Abhyankar   PetscFunctionReturn(0);
1362ff596062SShri Abhyankar }
1363ff596062SShri Abhyankar 
1364ff596062SShri Abhyankar #undef __FUNCT__
1365ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1366ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1367ff596062SShri Abhyankar {
1368ff596062SShri Abhyankar   PetscErrorCode      ierr;
1369cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1370ff596062SShri Abhyankar 
1371ff596062SShri Abhyankar   PetscFunctionBegin;
1372ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1373cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1374ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1375ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1376cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1377ff596062SShri Abhyankar   PetscFunctionReturn(0);
1378ff596062SShri Abhyankar }
1379ff596062SShri Abhyankar 
1380ff596062SShri Abhyankar #endif
1381ff596062SShri Abhyankar 
1382ff596062SShri Abhyankar 
13832f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
13842f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1385720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
138656a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
138756a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
13882f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
13892f63a38cSShri Abhyankar */
13902f63a38cSShri Abhyankar #undef __FUNCT__
1391b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1392b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
13932f63a38cSShri Abhyankar {
13942f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
13952f63a38cSShri Abhyankar   PetscErrorCode    ierr;
13962f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
13972f63a38cSShri Abhyankar   PetscBool         lssucceed;
13982f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
13992f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14002f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14012f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14022f63a38cSShri Abhyankar 
14032f63a38cSShri Abhyankar   PetscFunctionBegin;
14042f63a38cSShri Abhyankar   snes->numFailures            = 0;
14052f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14062f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14072f63a38cSShri Abhyankar 
14082f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14092f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14102f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14112f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14122f63a38cSShri Abhyankar   G		= snes->work[1];
14132f63a38cSShri Abhyankar   W		= snes->work[2];
14142f63a38cSShri Abhyankar 
14152f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14162f63a38cSShri Abhyankar   snes->iter = 0;
14172f63a38cSShri Abhyankar   snes->norm = 0.0;
14182f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14192f63a38cSShri Abhyankar 
14202f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14212f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14222f63a38cSShri Abhyankar   if (snes->domainerror) {
14232f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14242f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14252f63a38cSShri Abhyankar   }
14262f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14272f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14282f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
142962cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14302f63a38cSShri Abhyankar 
14312f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14322f63a38cSShri Abhyankar   snes->norm = fnorm;
14332f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14342f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
14357a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
14362f63a38cSShri Abhyankar 
14372f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
14382f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
14392f63a38cSShri Abhyankar   /* test convergence */
14402f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
14412f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
14422f63a38cSShri Abhyankar 
14432f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
14442f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1445cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
144656a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
144756a221efSShri Abhyankar     Vec            F_aug,Y_aug;
144856a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
144956a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
145056a221efSShri Abhyankar     PetscInt       k;
145163ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
145256a221efSShri Abhyankar     PetscScalar    *f,*f2;
14532f63a38cSShri Abhyankar     PetscBool      isequal;
145456a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
14552f63a38cSShri Abhyankar 
14562f63a38cSShri Abhyankar     /* Call general purpose update function */
14572f63a38cSShri Abhyankar     if (snes->ops->update) {
14582f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
14592f63a38cSShri Abhyankar     }
14602f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
14612f63a38cSShri Abhyankar 
14622f63a38cSShri Abhyankar     /* Create active and inactive index sets */
14632f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
14642f63a38cSShri Abhyankar 
146556a221efSShri Abhyankar     /* Get local active set size */
14662f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
146756a221efSShri Abhyankar     if (nis_act) {
1468e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1469e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
147056a221efSShri Abhyankar       if(vi->checkredundancy) {
1471cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
147256a221efSShri Abhyankar       }
14732f63a38cSShri Abhyankar 
147456a221efSShri Abhyankar       if(!IS_redact) {
147556a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
147656a221efSShri Abhyankar            there were no redundant active set variables */
147756a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
147856a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
147956a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
148056a221efSShri Abhyankar 	nkept = nis_act;
148156a221efSShri Abhyankar       } else {
148256a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
148356a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
14842f63a38cSShri Abhyankar 
148556a221efSShri Abhyankar 	/* Create reduced active set list */
148656a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
148756a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1488cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
148956a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
149056a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
149156a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
149256a221efSShri Abhyankar 	}
149356a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
149456a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1495cb5fe31bSShri Abhyankar 
1496cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
149756a221efSShri Abhyankar       }
14982f63a38cSShri Abhyankar 
149956a221efSShri Abhyankar       /* Create augmented F and Y */
150056a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
150156a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
150256a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
150356a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15042f63a38cSShri Abhyankar 
150556a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
150656a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
150756a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
150856a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
150956a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
151056a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15112f63a38cSShri Abhyankar 
151256a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
151356a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
151456a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
151556a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15162f63a38cSShri Abhyankar 
151756a221efSShri Abhyankar 
15189521db3cSSatish Balay       { /* local vars */
1519493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
152056a221efSShri Abhyankar       PetscInt          ncols;
152156a221efSShri Abhyankar       const PetscInt    *cols;
152256a221efSShri Abhyankar       const PetscScalar *vals;
15232969f145SShri Abhyankar       PetscScalar        value[2];
15242969f145SShri Abhyankar       PetscInt           row,col[2];
1525493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15262969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1527493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1528493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1529493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1530493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1531493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1532493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1533493a4f3dSShri Abhyankar       }
1534493a4f3dSShri Abhyankar 
1535493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1536493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
15372969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1538493a4f3dSShri Abhyankar       }
1539493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1540493a4f3dSShri Abhyankar 
1541493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
154256a221efSShri Abhyankar 
154356a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
154456a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
154556a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
154656a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
154756a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
154856a221efSShri Abhyankar       }
154956a221efSShri Abhyankar       /* Add the augmented part */
155056a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
15512969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
15522969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
15532969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
15542969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
155556a221efSShri Abhyankar       }
155656a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
155756a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
155856a221efSShri Abhyankar       /* Only considering prejac = jac for now */
155956a221efSShri Abhyankar       Jpre_aug = J_aug;
15609521db3cSSatish Balay       } /* local vars*/
1561e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1562e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
156356a221efSShri Abhyankar     } else {
156456a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
156556a221efSShri Abhyankar     }
15662f63a38cSShri Abhyankar 
15672f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
15682f63a38cSShri Abhyankar     if (!isequal) {
156956a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
15702f63a38cSShri Abhyankar     }
157156a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
15722f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
157356a221efSShri Abhyankar     /*  {
15742f63a38cSShri Abhyankar       PC        pc;
15752f63a38cSShri Abhyankar       PetscBool flg;
15762f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
15772f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15782f63a38cSShri Abhyankar       if (flg) {
15792f63a38cSShri Abhyankar         KSP      *subksps;
15802f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
15812f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
15822f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
15832f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
15842f63a38cSShri Abhyankar         if (flg) {
15852f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
15862f63a38cSShri Abhyankar           const PetscInt *ii;
15872f63a38cSShri Abhyankar 
15882f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
15892f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
15902f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
15912f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
15922f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
15932f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
15942f63a38cSShri Abhyankar           }
15952f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
15962f63a38cSShri Abhyankar 
15972f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
15982f63a38cSShri Abhyankar         }
15992f63a38cSShri Abhyankar       }
16002f63a38cSShri Abhyankar     }
160156a221efSShri Abhyankar     */
160256a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16032f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16042f63a38cSShri Abhyankar     if (kspreason < 0) {
16052f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16062f63a38cSShri 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);
16072f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16082f63a38cSShri Abhyankar         break;
16092f63a38cSShri Abhyankar       }
16102f63a38cSShri Abhyankar     }
16112f63a38cSShri Abhyankar 
161256a221efSShri Abhyankar     if(nis_act) {
161356a221efSShri Abhyankar       PetscScalar *y1,*y2;
161456a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
161556a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
161656a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
161756a221efSShri Abhyankar       j1 = 0;
161856a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
161956a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
162056a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
162156a221efSShri Abhyankar       }
162256a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
162356a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16242f63a38cSShri Abhyankar 
16256bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16266bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16276bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
162856a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
162956a221efSShri Abhyankar     }
163056a221efSShri Abhyankar 
16312f63a38cSShri Abhyankar     if (!isequal) {
16326bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16332f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
16342f63a38cSShri Abhyankar     }
16356bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
163656a221efSShri Abhyankar 
16372f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
16382f63a38cSShri Abhyankar     snes->linear_its += lits;
16392f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
16402f63a38cSShri Abhyankar     /*
16412f63a38cSShri Abhyankar     if (vi->precheckstep) {
16422f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
16432f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
16442f63a38cSShri Abhyankar     }
16452f63a38cSShri Abhyankar 
16462f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
16472f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
16482f63a38cSShri Abhyankar     }
16492f63a38cSShri Abhyankar     */
16502f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
16512f63a38cSShri Abhyankar          Y <- X - lambda*Y
16522f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
16532f63a38cSShri Abhyankar     */
16542f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
16552f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
16562f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
16572f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
16582f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
16592f63a38cSShri Abhyankar     if (snes->domainerror) {
16602f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
16612f63a38cSShri Abhyankar       PetscFunctionReturn(0);
16622f63a38cSShri Abhyankar     }
16632f63a38cSShri Abhyankar     if (!lssucceed) {
16642f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
16652f63a38cSShri Abhyankar 	PetscBool ismin;
16662f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
16672f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
16682f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
16692f63a38cSShri Abhyankar         break;
16702f63a38cSShri Abhyankar       }
16712f63a38cSShri Abhyankar     }
16722f63a38cSShri Abhyankar     /* Update function and solution vectors */
16732f63a38cSShri Abhyankar     fnorm = gnorm;
16742f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
16752f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
16762f63a38cSShri Abhyankar     /* Monitor convergence */
16772f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
16782f63a38cSShri Abhyankar     snes->iter = i+1;
16792f63a38cSShri Abhyankar     snes->norm = fnorm;
16802f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
16812f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
16827a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16832f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
16842f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
16852f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
16862f63a38cSShri Abhyankar     if (snes->reason) break;
16872f63a38cSShri Abhyankar   }
16882f63a38cSShri Abhyankar   if (i == maxits) {
16892f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
16902f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
16912f63a38cSShri Abhyankar   }
16922f63a38cSShri Abhyankar   PetscFunctionReturn(0);
16932f63a38cSShri Abhyankar }
16942f63a38cSShri Abhyankar 
16952b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
16962b4ed282SShri Abhyankar /*
16972b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
16982b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
16992b4ed282SShri Abhyankar 
17002b4ed282SShri Abhyankar    Input Parameter:
17012b4ed282SShri Abhyankar .  snes - the SNES context
17022b4ed282SShri Abhyankar .  x - the solution vector
17032b4ed282SShri Abhyankar 
17042b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17052b4ed282SShri Abhyankar 
17062b4ed282SShri Abhyankar    Notes:
17072b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17082b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17092b4ed282SShri Abhyankar    the call to SNESSolve().
17102b4ed282SShri Abhyankar  */
17112b4ed282SShri Abhyankar #undef __FUNCT__
17122b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17132b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17142b4ed282SShri Abhyankar {
17152b4ed282SShri Abhyankar   PetscErrorCode ierr;
17162b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17172b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17182b4ed282SShri Abhyankar 
17192b4ed282SShri Abhyankar   PetscFunctionBegin;
172058c9b817SLisandro Dalcin 
172158c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17222b4ed282SShri Abhyankar 
1723*2176524cSBarry Smith   if (vi->computevariablebounds) {
1724*2176524cSBarry Smith     ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
1725*2176524cSBarry Smith     ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1726*2176524cSBarry Smith     ierr = (*vi->computevariablebounds)(snes,&vi->xl,&vi->xu);CHKERRQ(ierr);
1727*2176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
1728*2176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
17292b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
173001f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17312b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
173201f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17332b4ed282SShri Abhyankar   } else {
17342b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
17352b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
17362b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
17372b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
17382b4ed282SShri 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]))
17392b4ed282SShri 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.");
17402b4ed282SShri Abhyankar   }
17412f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1742abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1743abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1744abcba341SShri Abhyankar     PetscInt *indices;
1745abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1746abcba341SShri Abhyankar 
1747abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1748abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1749abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1750abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1751abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1752abcba341SShri Abhyankar   }
17532b4ed282SShri Abhyankar 
17542f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1755fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1756fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1757fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1758fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1759fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1760fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1761fe835674SShri Abhyankar   }
17622b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17632b4ed282SShri Abhyankar }
17642b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
1765*2176524cSBarry Smith #undef __FUNCT__
1766*2176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
1767*2176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
1768*2176524cSBarry Smith {
1769*2176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
1770*2176524cSBarry Smith   PetscErrorCode ierr;
1771*2176524cSBarry Smith 
1772*2176524cSBarry Smith   PetscFunctionBegin;
1773*2176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
1774*2176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1775*2176524cSBarry Smith   PetscFunctionReturn(0);
1776*2176524cSBarry Smith }
1777*2176524cSBarry Smith 
17782b4ed282SShri Abhyankar /*
17792b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
17802b4ed282SShri Abhyankar    with SNESCreate_VI().
17812b4ed282SShri Abhyankar 
17822b4ed282SShri Abhyankar    Input Parameter:
17832b4ed282SShri Abhyankar .  snes - the SNES context
17842b4ed282SShri Abhyankar 
17852b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
17862b4ed282SShri Abhyankar  */
17872b4ed282SShri Abhyankar #undef __FUNCT__
17882b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
17892b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
17902b4ed282SShri Abhyankar {
17912b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17922b4ed282SShri Abhyankar   PetscErrorCode ierr;
17932b4ed282SShri Abhyankar 
17942b4ed282SShri Abhyankar   PetscFunctionBegin;
17952f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
17966bf464f9SBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);
1797abcba341SShri Abhyankar   }
17982b4ed282SShri Abhyankar 
17992f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18002b4ed282SShri Abhyankar     /* clear vectors */
18016bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18026bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18036bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18046bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18056bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18066bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18077fe79bc4SShri Abhyankar   }
18087fe79bc4SShri Abhyankar 
18096bf464f9SBarry Smith   ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
18102b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18112b4ed282SShri Abhyankar 
18122b4ed282SShri Abhyankar   /* clear composed functions */
18132b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1814c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18152b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18162b4ed282SShri Abhyankar }
18177fe79bc4SShri Abhyankar 
18182b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18192b4ed282SShri Abhyankar #undef __FUNCT__
18202b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18212b4ed282SShri Abhyankar 
18222b4ed282SShri Abhyankar /*
18237fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18247fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18252b4ed282SShri Abhyankar 
18262b4ed282SShri Abhyankar */
1827ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNo_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
18282b4ed282SShri Abhyankar {
18292b4ed282SShri Abhyankar   PetscErrorCode ierr;
18302b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1831ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18322b4ed282SShri Abhyankar 
18332b4ed282SShri Abhyankar   PetscFunctionBegin;
18342b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18352b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18362b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
18372b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1838c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1839c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1840c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1841c1a5e521SShri Abhyankar   }
1842c1a5e521SShri Abhyankar   if (changed_y) {
1843c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18447fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1845c1a5e521SShri Abhyankar   }
1846c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1847c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1848c1a5e521SShri Abhyankar   if (!snes->domainerror) {
18492f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
18507fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
18517fe79bc4SShri Abhyankar     } else {
1852c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
18537fe79bc4SShri Abhyankar     }
185462cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1855c1a5e521SShri Abhyankar   }
1856c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1857c1a5e521SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1858c1a5e521SShri Abhyankar   }
1859c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1860c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1861c1a5e521SShri Abhyankar }
1862c1a5e521SShri Abhyankar 
1863c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1864c1a5e521SShri Abhyankar #undef __FUNCT__
18652b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
18662b4ed282SShri Abhyankar 
18672b4ed282SShri Abhyankar /*
18682b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
18692b4ed282SShri Abhyankar */
1870ace3abfcSBarry Smith PetscErrorCode SNESLineSearchNoNorms_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
18712b4ed282SShri Abhyankar {
18722b4ed282SShri Abhyankar   PetscErrorCode ierr;
18732b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1874ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18752b4ed282SShri Abhyankar 
18762b4ed282SShri Abhyankar   PetscFunctionBegin;
18772b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18782b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18792b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
18807fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18812b4ed282SShri Abhyankar   if (vi->postcheckstep) {
18822b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
18832b4ed282SShri Abhyankar   }
18842b4ed282SShri Abhyankar   if (changed_y) {
18852b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18867fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18872b4ed282SShri Abhyankar   }
18882b4ed282SShri Abhyankar 
18892b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
18902b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
18912b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18922b4ed282SShri Abhyankar   }
18932b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18942b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18952b4ed282SShri Abhyankar }
18967fe79bc4SShri Abhyankar 
18972b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18982b4ed282SShri Abhyankar #undef __FUNCT__
18992b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19002b4ed282SShri Abhyankar /*
19017fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19022b4ed282SShri Abhyankar */
1903ace3abfcSBarry Smith PetscErrorCode SNESLineSearchCubic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
19042b4ed282SShri Abhyankar {
1905fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1906fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1907fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1908fe835674SShri Abhyankar   PetscScalar    cinitslope;
1909fe835674SShri Abhyankar #endif
1910fe835674SShri Abhyankar   PetscErrorCode ierr;
1911fe835674SShri Abhyankar   PetscInt       count;
1912fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1913fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1914fe835674SShri Abhyankar   MPI_Comm       comm;
1915fe835674SShri Abhyankar 
1916fe835674SShri Abhyankar   PetscFunctionBegin;
1917fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1918fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1919fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1920fe835674SShri Abhyankar 
1921fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1922fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1923fe835674SShri Abhyankar     if (vi->lsmonitor) {
1924fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1925fe835674SShri Abhyankar     }
1926fe835674SShri Abhyankar     *gnorm = fnorm;
1927fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1928fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1929fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1930fe835674SShri Abhyankar     goto theend1;
1931fe835674SShri Abhyankar   }
1932fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1933fe835674SShri Abhyankar     if (vi->lsmonitor) {
1934fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1935fe835674SShri Abhyankar     }
1936fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1937fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1938fe835674SShri Abhyankar   }
1939fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1940fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1941fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1942fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1943fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1944fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1945fe835674SShri Abhyankar #else
1946fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1947fe835674SShri Abhyankar #endif
1948fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1949fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1950fe835674SShri Abhyankar 
1951fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
1952fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1953fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1954fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
1955fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1956fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1957fe835674SShri Abhyankar     goto theend1;
1958fe835674SShri Abhyankar   }
1959fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19602f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1961fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19627fe79bc4SShri Abhyankar   } else {
19637fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19647fe79bc4SShri Abhyankar   }
1965fe835674SShri Abhyankar   if (snes->domainerror) {
1966fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1967fe835674SShri Abhyankar     PetscFunctionReturn(0);
1968fe835674SShri Abhyankar   }
196962cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1970fe835674SShri Abhyankar   ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1971fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
1972fe835674SShri Abhyankar     if (vi->lsmonitor) {
1973fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1974fe835674SShri Abhyankar     }
1975fe835674SShri Abhyankar     goto theend1;
1976fe835674SShri Abhyankar   }
1977fe835674SShri Abhyankar 
1978fe835674SShri Abhyankar   /* Fit points with quadratic */
1979fe835674SShri Abhyankar   lambda     = 1.0;
1980fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
1981fe835674SShri Abhyankar   lambdaprev = lambda;
1982fe835674SShri Abhyankar   gnormprev  = *gnorm;
1983fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1984fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
1985fe835674SShri Abhyankar   else                         lambda = lambdatemp;
1986fe835674SShri Abhyankar 
1987fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1988fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1989fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1990fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
1991fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1992fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1993fe835674SShri Abhyankar     goto theend1;
1994fe835674SShri Abhyankar   }
1995fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19962f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1997fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19987fe79bc4SShri Abhyankar   } else {
19997fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20007fe79bc4SShri Abhyankar   }
2001fe835674SShri Abhyankar   if (snes->domainerror) {
2002fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2003fe835674SShri Abhyankar     PetscFunctionReturn(0);
2004fe835674SShri Abhyankar   }
200562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2006fe835674SShri Abhyankar   if (vi->lsmonitor) {
2007fe835674SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
2008fe835674SShri Abhyankar   }
2009fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2010fe835674SShri Abhyankar     if (vi->lsmonitor) {
2011fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
2012fe835674SShri Abhyankar     }
2013fe835674SShri Abhyankar     goto theend1;
2014fe835674SShri Abhyankar   }
2015fe835674SShri Abhyankar 
2016fe835674SShri Abhyankar   /* Fit points with cubic */
2017fe835674SShri Abhyankar   count = 1;
2018fe835674SShri Abhyankar   while (PETSC_TRUE) {
2019fe835674SShri Abhyankar     if (lambda <= minlambda) {
2020fe835674SShri Abhyankar       if (vi->lsmonitor) {
2021fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
2022fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr);
2023fe835674SShri Abhyankar       }
2024fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2025fe835674SShri Abhyankar       break;
2026fe835674SShri Abhyankar     }
2027fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2028fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2029fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2030fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2031fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2032fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2033fe835674SShri Abhyankar     if (a == 0.0) {
2034fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2035fe835674SShri Abhyankar     } else {
2036fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2037fe835674SShri Abhyankar     }
2038fe835674SShri Abhyankar     lambdaprev = lambda;
2039fe835674SShri Abhyankar     gnormprev  = *gnorm;
2040fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2041fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2042fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2043fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2044fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2045fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2046fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2047fe835674SShri Abhyankar       ierr = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr);
2048fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2049fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2050fe835674SShri Abhyankar       break;
2051fe835674SShri Abhyankar     }
2052fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20532f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2054fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20557fe79bc4SShri Abhyankar     } else {
20567fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20577fe79bc4SShri Abhyankar     }
2058fe835674SShri Abhyankar     if (snes->domainerror) {
2059fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2060fe835674SShri Abhyankar       PetscFunctionReturn(0);
2061fe835674SShri Abhyankar     }
206262cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2063fe835674SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */
2064fe835674SShri Abhyankar       if (vi->lsmonitor) {
2065fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2066fe835674SShri Abhyankar       }
2067fe835674SShri Abhyankar       break;
2068fe835674SShri Abhyankar     } else {
2069fe835674SShri Abhyankar       if (vi->lsmonitor) {
2070fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2071fe835674SShri Abhyankar       }
2072fe835674SShri Abhyankar     }
2073fe835674SShri Abhyankar     count++;
2074fe835674SShri Abhyankar   }
2075fe835674SShri Abhyankar   theend1:
2076fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2077fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2078fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2079fe835674SShri Abhyankar     if (changed_y) {
2080fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2081fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2082fe835674SShri Abhyankar     }
2083fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2084fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20852f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2086fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20877fe79bc4SShri Abhyankar       } else {
20887fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20897fe79bc4SShri Abhyankar       }
2090fe835674SShri Abhyankar       if (snes->domainerror) {
2091fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2092fe835674SShri Abhyankar         PetscFunctionReturn(0);
2093fe835674SShri Abhyankar       }
209462cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2095fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2096fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2097fe835674SShri Abhyankar     }
2098fe835674SShri Abhyankar   }
2099fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2100fe835674SShri Abhyankar   PetscFunctionReturn(0);
2101fe835674SShri Abhyankar }
2102fe835674SShri Abhyankar 
21032b4ed282SShri Abhyankar #undef __FUNCT__
21042b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21052b4ed282SShri Abhyankar /*
21067fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21072b4ed282SShri Abhyankar */
2108ace3abfcSBarry Smith PetscErrorCode SNESLineSearchQuadratic_VI(SNES snes,void *lsctx,Vec x,Vec f,Vec g,Vec y,Vec w,PetscReal fnorm,PetscReal xnorm,PetscReal *ynorm,PetscReal *gnorm,PetscBool *flag)
21092b4ed282SShri Abhyankar {
21102b4ed282SShri Abhyankar   /*
21112b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21122b4ed282SShri Abhyankar      minimization problem:
21132b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21142b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
21152b4ed282SShri Abhyankar    */
21162b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
21172b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21182b4ed282SShri Abhyankar   PetscScalar    cinitslope;
21192b4ed282SShri Abhyankar #endif
21202b4ed282SShri Abhyankar   PetscErrorCode ierr;
21212b4ed282SShri Abhyankar   PetscInt       count;
21222b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2123ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
21242b4ed282SShri Abhyankar 
21252b4ed282SShri Abhyankar   PetscFunctionBegin;
21262b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21272b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
21282b4ed282SShri Abhyankar 
21292b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
21302b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2131c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2132c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
21332b4ed282SShri Abhyankar     }
21342b4ed282SShri Abhyankar     *gnorm = fnorm;
21352b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
21362b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
21372b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
21382b4ed282SShri Abhyankar     goto theend2;
21392b4ed282SShri Abhyankar   }
21402b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
21412b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
21422b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
21432b4ed282SShri Abhyankar   }
21442b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
21452b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
21467fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
21472b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21487fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
21492b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
21502b4ed282SShri Abhyankar #else
21517fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
21522b4ed282SShri Abhyankar #endif
21532b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
21542b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
21552b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
21562b4ed282SShri Abhyankar 
21572b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21587fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21592b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
21602b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
21612b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
21622b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21632b4ed282SShri Abhyankar     goto theend2;
21642b4ed282SShri Abhyankar   }
21652b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21662f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
21677fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21687fe79bc4SShri Abhyankar   } else {
21697fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21707fe79bc4SShri Abhyankar   }
21712b4ed282SShri Abhyankar   if (snes->domainerror) {
21722b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21732b4ed282SShri Abhyankar     PetscFunctionReturn(0);
21742b4ed282SShri Abhyankar   }
217562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21762b4ed282SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
2177c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2178c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
21792b4ed282SShri Abhyankar     }
21802b4ed282SShri Abhyankar     goto theend2;
21812b4ed282SShri Abhyankar   }
21822b4ed282SShri Abhyankar 
21832b4ed282SShri Abhyankar   /* Fit points with quadratic */
21842b4ed282SShri Abhyankar   lambda = 1.0;
21852b4ed282SShri Abhyankar   count = 1;
21862b4ed282SShri Abhyankar   while (PETSC_TRUE) {
21872b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2188c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2189c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2190c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr);
21912b4ed282SShri Abhyankar       }
21922b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
21932b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21942b4ed282SShri Abhyankar       break;
21952b4ed282SShri Abhyankar     }
21962b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
21972b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
21982b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
21992b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22002b4ed282SShri Abhyankar 
22012b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22027fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22032b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22042b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
22052b4ed282SShri Abhyankar       ierr  = PetscInfo5(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr);
22062b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22072b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22082b4ed282SShri Abhyankar       break;
22092b4ed282SShri Abhyankar     }
22102b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22112b4ed282SShri Abhyankar     if (snes->domainerror) {
22122b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22132b4ed282SShri Abhyankar       PetscFunctionReturn(0);
22142b4ed282SShri Abhyankar     }
22152f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
22167fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22177fe79bc4SShri Abhyankar     } else {
22182b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22197fe79bc4SShri Abhyankar     }
222062cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22212b4ed282SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2222c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2223c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
22242b4ed282SShri Abhyankar       }
22252b4ed282SShri Abhyankar       break;
22262b4ed282SShri Abhyankar     }
22272b4ed282SShri Abhyankar     count++;
22282b4ed282SShri Abhyankar   }
22292b4ed282SShri Abhyankar   theend2:
22302b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
22312b4ed282SShri Abhyankar   if (vi->postcheckstep) {
22322b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
22332b4ed282SShri Abhyankar     if (changed_y) {
22342b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22357fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22362b4ed282SShri Abhyankar     }
22372b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
22382b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
22392b4ed282SShri Abhyankar       if (snes->domainerror) {
22402b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22412b4ed282SShri Abhyankar         PetscFunctionReturn(0);
22422b4ed282SShri Abhyankar       }
22432f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
22447fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22457fe79bc4SShri Abhyankar       } else {
22467fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22477fe79bc4SShri Abhyankar       }
22487fe79bc4SShri Abhyankar 
22492b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
22502b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
225162cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22522b4ed282SShri Abhyankar     }
22532b4ed282SShri Abhyankar   }
22542b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22552b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22562b4ed282SShri Abhyankar }
22572b4ed282SShri Abhyankar 
2258ace3abfcSBarry Smith typedef PetscErrorCode (*FCN2)(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscBool*); /* force argument to next function to not be extern C*/
22592b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22602b4ed282SShri Abhyankar EXTERN_C_BEGIN
22612b4ed282SShri Abhyankar #undef __FUNCT__
22622b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
22637087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
22642b4ed282SShri Abhyankar {
22652b4ed282SShri Abhyankar   PetscFunctionBegin;
22662b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
22672b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
22682b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22692b4ed282SShri Abhyankar }
22702b4ed282SShri Abhyankar EXTERN_C_END
22712b4ed282SShri Abhyankar 
22722b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22732b4ed282SShri Abhyankar EXTERN_C_BEGIN
22742b4ed282SShri Abhyankar #undef __FUNCT__
22752b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
22767087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
22772b4ed282SShri Abhyankar {
22782b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
22792b4ed282SShri Abhyankar   PetscErrorCode ierr;
22802b4ed282SShri Abhyankar 
22812b4ed282SShri Abhyankar   PetscFunctionBegin;
2282c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2283c92abb8aSShri Abhyankar     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr);
2284c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
22856bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
22862b4ed282SShri Abhyankar   }
22872b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22882b4ed282SShri Abhyankar }
22892b4ed282SShri Abhyankar EXTERN_C_END
22902b4ed282SShri Abhyankar 
22912b4ed282SShri Abhyankar /*
22922b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
22932b4ed282SShri Abhyankar 
22942b4ed282SShri Abhyankar    Input Parameters:
22952b4ed282SShri Abhyankar .  SNES - the SNES context
22962b4ed282SShri Abhyankar .  viewer - visualization context
22972b4ed282SShri Abhyankar 
22982b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
22992b4ed282SShri Abhyankar */
23002b4ed282SShri Abhyankar #undef __FUNCT__
23012b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23022b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23032b4ed282SShri Abhyankar {
23042b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
230578c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23062b4ed282SShri Abhyankar   PetscErrorCode ierr;
2307ace3abfcSBarry Smith   PetscBool     iascii;
23082b4ed282SShri Abhyankar 
23092b4ed282SShri Abhyankar   PetscFunctionBegin;
23102b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23112b4ed282SShri Abhyankar   if (iascii) {
23122b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
23132b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
23142b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
23152b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
231678c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
23170a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2318b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
231978c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
232078c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
23212b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
23222b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
23232b4ed282SShri Abhyankar   } else {
23242b4ed282SShri Abhyankar     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name);
23252b4ed282SShri Abhyankar   }
23262b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23272b4ed282SShri Abhyankar }
23282b4ed282SShri Abhyankar 
23295559b345SBarry Smith #undef __FUNCT__
23305559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
23315559b345SBarry Smith /*@
23322b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
23332b4ed282SShri Abhyankar 
23342b4ed282SShri Abhyankar    Input Parameters:
23352b4ed282SShri Abhyankar .  snes - the SNES context.
23362b4ed282SShri Abhyankar .  xl   - lower bound.
23372b4ed282SShri Abhyankar .  xu   - upper bound.
23382b4ed282SShri Abhyankar 
23392b4ed282SShri Abhyankar    Notes:
23402b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
234101f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
234284c105d7SBarry Smith 
23435559b345SBarry Smith @*/
234469c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
23452b4ed282SShri Abhyankar {
2346d923200aSJungho Lee   SNES_VI        *vi;
2347d923200aSJungho Lee   PetscErrorCode ierr;
23482b4ed282SShri Abhyankar 
23492b4ed282SShri Abhyankar   PetscFunctionBegin;
23502b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
23512b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
23522b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
23532b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
23542b4ed282SShri 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);
23552b4ed282SShri 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);
2356d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2357d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
2358*2176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
2359*2176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
2360*2176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
2361*2176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
23622b4ed282SShri Abhyankar   vi->xl = xl;
23632b4ed282SShri Abhyankar   vi->xu = xu;
23642b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23652b4ed282SShri Abhyankar }
2366693ddf92SShri Abhyankar 
23672b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23682b4ed282SShri Abhyankar /*
23692b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
23702b4ed282SShri Abhyankar 
23712b4ed282SShri Abhyankar    Input Parameter:
23722b4ed282SShri Abhyankar .  snes - the SNES context
23732b4ed282SShri Abhyankar 
23742b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
23752b4ed282SShri Abhyankar */
23762b4ed282SShri Abhyankar #undef __FUNCT__
23772b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
23782b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
23792b4ed282SShri Abhyankar {
23802b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
23817fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2382b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
23832b4ed282SShri Abhyankar   PetscErrorCode ierr;
23842b4ed282SShri Abhyankar   PetscInt       indx;
238569c03620SShri Abhyankar   PetscBool      flg,set,flg2;
23862b4ed282SShri Abhyankar 
23872b4ed282SShri Abhyankar   PetscFunctionBegin;
23882b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
23899308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
23909308c137SBarry Smith   if (flg) {
23919308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
23929308c137SBarry Smith   }
2393be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2394be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2395be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
23962b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2397be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
23982b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
23992f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
240069c03620SShri Abhyankar   if (flg2) {
240169c03620SShri Abhyankar     switch (indx) {
240269c03620SShri Abhyankar     case 0:
240369c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
240469c03620SShri Abhyankar       break;
240569c03620SShri Abhyankar     case 1:
2406d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2407d950fb63SShri Abhyankar       break;
24082f63a38cSShri Abhyankar     case 2:
2409b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
241069c03620SShri Abhyankar     }
241169c03620SShri Abhyankar   }
2412be6adb11SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr);
24132b4ed282SShri Abhyankar   if (flg) {
24142b4ed282SShri Abhyankar     switch (indx) {
24152b4ed282SShri Abhyankar     case 0:
24162b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
24172b4ed282SShri Abhyankar       break;
24182b4ed282SShri Abhyankar     case 1:
24192b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
24202b4ed282SShri Abhyankar       break;
24212b4ed282SShri Abhyankar     case 2:
24222b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
24232b4ed282SShri Abhyankar       break;
24242b4ed282SShri Abhyankar     case 3:
24252b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
24262b4ed282SShri Abhyankar       break;
24272b4ed282SShri Abhyankar     }
2428fe835674SShri Abhyankar   }
24292b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
24302b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24312b4ed282SShri Abhyankar }
24322b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24332b4ed282SShri Abhyankar /*MC
24348b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
24352b4ed282SShri Abhyankar 
24362b4ed282SShri Abhyankar    Options Database:
24378b4c83edSBarry 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
24388b4c83edSBarry Smith                                 additional variables that enforce the constraints
24398b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
24402b4ed282SShri Abhyankar 
24412b4ed282SShri Abhyankar 
24422b4ed282SShri Abhyankar    Level: beginner
24432b4ed282SShri Abhyankar 
24442b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
24452b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
24462b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
24472b4ed282SShri Abhyankar 
24482b4ed282SShri Abhyankar M*/
24492b4ed282SShri Abhyankar EXTERN_C_BEGIN
24502b4ed282SShri Abhyankar #undef __FUNCT__
24512b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
24527087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
24532b4ed282SShri Abhyankar {
24542b4ed282SShri Abhyankar   PetscErrorCode ierr;
24552b4ed282SShri Abhyankar   SNES_VI        *vi;
24562b4ed282SShri Abhyankar 
24572b4ed282SShri Abhyankar   PetscFunctionBegin;
2458*2176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
24592b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2460edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
24612b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
24622b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
24632b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
24642b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
24652b4ed282SShri Abhyankar 
24662b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
24672b4ed282SShri Abhyankar   snes->data            = (void*)vi;
24682b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
24692b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
24702b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
24717fe79bc4SShri Abhyankar   vi->LineSearch        = SNESLineSearchNo_VI;
24722b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
24732b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
24742b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
24752b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
24762b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
24772b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
24782f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
24792b4ed282SShri Abhyankar 
24802b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
24812b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
24822b4ed282SShri Abhyankar 
24832b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24842b4ed282SShri Abhyankar }
24852b4ed282SShri Abhyankar EXTERN_C_END
2486