xref: /petsc/src/snes/impls/vi/vi.c (revision 4c661bef694cbadc180fa90f364b54b4556f5197)
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__
8d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS"
9d0af7cd3SBarry Smith /*
10d0af7cd3SBarry Smith    SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables
11d0af7cd3SBarry Smith 
12d0af7cd3SBarry Smith    Input parameter
13d0af7cd3SBarry Smith .  snes - the SNES context
14d0af7cd3SBarry Smith .  X    - the snes solution vector
15d0af7cd3SBarry Smith 
16d0af7cd3SBarry Smith    Output parameter
17d0af7cd3SBarry Smith .  ISact - active set index set
18d0af7cd3SBarry Smith 
19d0af7cd3SBarry Smith  */
20d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
21d0af7cd3SBarry Smith {
22d0af7cd3SBarry Smith   PetscErrorCode   ierr;
23d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
24d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
25d0af7cd3SBarry Smith 
26d0af7cd3SBarry Smith   PetscFunctionBegin;
27d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
28d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
29d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
30d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
31d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
32d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
33d0af7cd3SBarry Smith   /* Compute inactive set size */
34d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
35d0af7cd3SBarry 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++;
36d0af7cd3SBarry Smith   }
37d0af7cd3SBarry Smith 
38d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
39d0af7cd3SBarry Smith 
40d0af7cd3SBarry Smith   /* Set inactive set indices */
41d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
42d0af7cd3SBarry 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;
43d0af7cd3SBarry Smith   }
44d0af7cd3SBarry Smith 
45d0af7cd3SBarry Smith    /* Create inactive set IS */
46d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
47d0af7cd3SBarry Smith 
48d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
49d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
50d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
51d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
52d0af7cd3SBarry Smith   PetscFunctionReturn(0);
53d0af7cd3SBarry Smith }
54d0af7cd3SBarry Smith 
553c0c59f3SBarry Smith /*
563c0c59f3SBarry 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
573c0c59f3SBarry Smith   defined by the reduced space method.
583c0c59f3SBarry Smith 
593c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
603c0c59f3SBarry Smith 
613c0c59f3SBarry Smith */
623c0c59f3SBarry Smith typedef struct {
633c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
643c0c59f3SBarry Smith   IS             inactive;
653c0c59f3SBarry Smith   Vec            upper,lower,values,F;                    /* upper and lower bounds of all variables on this level, the values and the function values */
663c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
673c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
683c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
69*4c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
703c0c59f3SBarry Smith } DM_SNESVI;
713c0c59f3SBarry Smith 
72d0af7cd3SBarry Smith #undef __FUNCT__
734dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
744dcab191SBarry Smith /*
754dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
764dcab191SBarry Smith 
774dcab191SBarry Smith */
784dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
794dcab191SBarry Smith {
804dcab191SBarry Smith   PetscErrorCode          ierr;
814dcab191SBarry Smith   PetscContainer          isnes;
823c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
834dcab191SBarry Smith 
844dcab191SBarry Smith   PetscFunctionBegin;
854dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
864dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
874dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
884dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
894dcab191SBarry Smith   PetscFunctionReturn(0);
904dcab191SBarry Smith }
914dcab191SBarry Smith 
924dcab191SBarry Smith #undef __FUNCT__
93d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
94d0af7cd3SBarry Smith /*
95d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
96d0af7cd3SBarry Smith 
97d0af7cd3SBarry Smith */
98d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
99d0af7cd3SBarry Smith {
100d0af7cd3SBarry Smith   PetscErrorCode          ierr;
101d0af7cd3SBarry Smith   PetscContainer          isnes;
1023c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
103d0af7cd3SBarry Smith   Mat                     interp;
104d0af7cd3SBarry Smith 
105d0af7cd3SBarry Smith   PetscFunctionBegin;
106d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
107*4c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
108d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
109d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
110*4c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
111d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
112d0af7cd3SBarry Smith 
113d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1144dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
115d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
116d0af7cd3SBarry Smith   PetscFunctionReturn(0);
117d0af7cd3SBarry Smith }
118d0af7cd3SBarry Smith 
119d0af7cd3SBarry Smith extern PetscErrorCode  DMSetVI(DM,Vec,Vec,Vec,Vec,IS);
120d0af7cd3SBarry Smith 
121d0af7cd3SBarry Smith #undef __FUNCT__
122d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
123d0af7cd3SBarry Smith /*
124d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
125d0af7cd3SBarry Smith 
126d0af7cd3SBarry Smith */
127d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
128d0af7cd3SBarry Smith {
129d0af7cd3SBarry Smith   PetscErrorCode          ierr;
130d0af7cd3SBarry Smith   PetscContainer          isnes;
1313c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
132d0af7cd3SBarry Smith   Vec                     upper,lower,values,F;
133d0af7cd3SBarry Smith   IS                      inactive;
134d0af7cd3SBarry Smith   VecScatter              inject;
135d0af7cd3SBarry Smith 
136d0af7cd3SBarry Smith   PetscFunctionBegin;
137d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
138*4c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
139d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
140d0af7cd3SBarry Smith 
141298cc208SBarry Smith   /* get the original coarsen */
142d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
143298cc208SBarry Smith 
1443c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1453c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1463c0c59f3SBarry Smith 
147298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
148298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
149298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
150d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
151d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr);
152d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
153d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
154d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr);
155d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
156d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
157d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr);
158d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
159d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
160d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr);
161d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
162d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
163d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
164298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
165298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
166d0af7cd3SBarry Smith   ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr);
167d0af7cd3SBarry Smith   ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr);
1683c0c59f3SBarry Smith   ierr = VecDestroy(&upper);CHKERRQ(ierr);
1693c0c59f3SBarry Smith   ierr = VecDestroy(&lower);CHKERRQ(ierr);
1703c0c59f3SBarry Smith   ierr = VecDestroy(&values);CHKERRQ(ierr);
1713c0c59f3SBarry Smith   ierr = VecDestroy(&F);CHKERRQ(ierr);
1723c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
173d0af7cd3SBarry Smith   PetscFunctionReturn(0);
174d0af7cd3SBarry Smith }
175d0af7cd3SBarry Smith 
176d0af7cd3SBarry Smith #undef __FUNCT__
1773c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
1783c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
179d0af7cd3SBarry Smith {
180d0af7cd3SBarry Smith   PetscErrorCode ierr;
181d0af7cd3SBarry Smith 
182d0af7cd3SBarry Smith   PetscFunctionBegin;
183*4c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
184*4c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
185*4c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
186*4c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
187*4c661befSBarry Smith 
188d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
189d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
190d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
191d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
192d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
193d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
194d0af7cd3SBarry Smith   PetscFunctionReturn(0);
195d0af7cd3SBarry Smith }
196d0af7cd3SBarry Smith 
197d0af7cd3SBarry Smith #undef __FUNCT__
198d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
199d0af7cd3SBarry Smith /*
200d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
201d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
202d0af7cd3SBarry Smith 
203d0af7cd3SBarry Smith */
204d0af7cd3SBarry Smith PetscErrorCode  DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive)
205d0af7cd3SBarry Smith {
206d0af7cd3SBarry Smith   PetscErrorCode          ierr;
207d0af7cd3SBarry Smith   PetscContainer          isnes;
2083c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
209d0af7cd3SBarry Smith 
210d0af7cd3SBarry Smith   PetscFunctionBegin;
2114dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
212d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr);
213d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr);
214d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr);
215d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
216d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
217d0af7cd3SBarry Smith 
218d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
219d0af7cd3SBarry Smith   if (!isnes) {
220d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2213c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2223c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
223d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
224d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2253c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
226d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
227d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
228d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
229d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
230298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2314dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
2326ba4bc90SBarry Smith     /* since these vectors may reference the DM, need to remove circle referencing */
2336ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr);
2346ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr);
2356ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr);
2366ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr);
237d0af7cd3SBarry Smith   } else {
238d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
239d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
240d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
241d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
242d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
243d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
244d0af7cd3SBarry Smith   }
2454dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2464dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
247d0af7cd3SBarry Smith   dmsnesvi->upper    = upper;
248d0af7cd3SBarry Smith   dmsnesvi->lower    = lower;
249d0af7cd3SBarry Smith   dmsnesvi->values   = values;
250d0af7cd3SBarry Smith   dmsnesvi->F        = F;
251d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
252d0af7cd3SBarry Smith   PetscFunctionReturn(0);
253d0af7cd3SBarry Smith }
254d0af7cd3SBarry Smith 
255*4c661befSBarry Smith #undef __FUNCT__
256*4c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
257*4c661befSBarry Smith /*
258*4c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
259*4c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
260*4c661befSBarry Smith */
261*4c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
262*4c661befSBarry Smith {
263*4c661befSBarry Smith   PetscErrorCode          ierr;
264*4c661befSBarry Smith 
265*4c661befSBarry Smith   PetscFunctionBegin;
266*4c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
267*4c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
268*4c661befSBarry Smith   PetscFunctionReturn(0);
269*4c661befSBarry Smith }
270*4c661befSBarry Smith 
2713c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
2722b4ed282SShri Abhyankar 
2739308c137SBarry Smith #undef __FUNCT__
2749308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
2757087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
2769308c137SBarry Smith {
2779308c137SBarry Smith   PetscErrorCode          ierr;
2789308c137SBarry Smith   SNES_VI                 *vi = (SNES_VI*)snes->data;
2799308c137SBarry Smith   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
2809308c137SBarry Smith   const PetscScalar       *x,*xl,*xu,*f;
28109573ac7SBarry Smith   PetscInt                i,n,act = 0;
2829308c137SBarry Smith   PetscReal               rnorm,fnorm;
2839308c137SBarry Smith 
2849308c137SBarry Smith   PetscFunctionBegin;
2859308c137SBarry Smith   if (!dummy) {
2869308c137SBarry Smith     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
2879308c137SBarry Smith   }
2889308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
2899308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
2909308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
2919308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
2923f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
2939308c137SBarry Smith 
2949308c137SBarry Smith   rnorm = 0.0;
2959308c137SBarry Smith   for (i=0; i<n; i++) {
29610f5ae6bSBarry 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]);
29709573ac7SBarry Smith     else act++;
2989308c137SBarry Smith   }
2993f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3009308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3019308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3029308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
303d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3049308c137SBarry Smith   fnorm = sqrt(fnorm);
30509573ac7SBarry Smith   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
3069308c137SBarry Smith   if (!dummy) {
3076bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr);
3089308c137SBarry Smith   }
3099308c137SBarry Smith   PetscFunctionReturn(0);
3109308c137SBarry Smith }
3119308c137SBarry Smith 
3122b4ed282SShri Abhyankar /*
3132b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3142b4ed282SShri 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
3152b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3162b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3172b4ed282SShri Abhyankar */
3182b4ed282SShri Abhyankar #undef __FUNCT__
3192b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
320ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3212b4ed282SShri Abhyankar {
3222b4ed282SShri Abhyankar   PetscReal      a1;
3232b4ed282SShri Abhyankar   PetscErrorCode ierr;
324ace3abfcSBarry Smith   PetscBool     hastranspose;
3252b4ed282SShri Abhyankar 
3262b4ed282SShri Abhyankar   PetscFunctionBegin;
3272b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3282b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3292b4ed282SShri Abhyankar   if (hastranspose) {
3302b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3312b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3322b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3332b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3342b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3352b4ed282SShri Abhyankar   } else {
3362b4ed282SShri Abhyankar     Vec         work;
3372b4ed282SShri Abhyankar     PetscScalar result;
3382b4ed282SShri Abhyankar     PetscReal   wnorm;
3392b4ed282SShri Abhyankar 
3402b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3412b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3422b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3432b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3442b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3456bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3462b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3472b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3482b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3492b4ed282SShri Abhyankar   }
3502b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3512b4ed282SShri Abhyankar }
3522b4ed282SShri Abhyankar 
3532b4ed282SShri Abhyankar /*
3542b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3552b4ed282SShri Abhyankar */
3562b4ed282SShri Abhyankar #undef __FUNCT__
3572b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3582b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3592b4ed282SShri Abhyankar {
3602b4ed282SShri Abhyankar   PetscReal      a1,a2;
3612b4ed282SShri Abhyankar   PetscErrorCode ierr;
362ace3abfcSBarry Smith   PetscBool     hastranspose;
3632b4ed282SShri Abhyankar 
3642b4ed282SShri Abhyankar   PetscFunctionBegin;
3652b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3662b4ed282SShri Abhyankar   if (hastranspose) {
3672b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3682b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3692b4ed282SShri Abhyankar 
3702b4ed282SShri Abhyankar     /* Compute || J^T W|| */
3712b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
3722b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
3732b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
3742b4ed282SShri Abhyankar     if (a1 != 0.0) {
3752b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
3762b4ed282SShri Abhyankar     }
3772b4ed282SShri Abhyankar   }
3782b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3792b4ed282SShri Abhyankar }
3802b4ed282SShri Abhyankar 
3812b4ed282SShri Abhyankar /*
3822b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
3832b4ed282SShri Abhyankar 
3842b4ed282SShri Abhyankar   Notes:
3852b4ed282SShri Abhyankar   The convergence criterion currently implemented is
3862b4ed282SShri Abhyankar   merit < abstol
3872b4ed282SShri Abhyankar   merit < rtol*merit_initial
3882b4ed282SShri Abhyankar */
3892b4ed282SShri Abhyankar #undef __FUNCT__
3902b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
3917fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
3922b4ed282SShri Abhyankar {
3932b4ed282SShri Abhyankar   PetscErrorCode ierr;
3942b4ed282SShri Abhyankar 
3952b4ed282SShri Abhyankar   PetscFunctionBegin;
3962b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3972b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
3982b4ed282SShri Abhyankar 
3992b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4002b4ed282SShri Abhyankar 
4012b4ed282SShri Abhyankar   if (!it) {
4022b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4037fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4042b4ed282SShri Abhyankar   }
4057fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4062b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4072b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4087fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4097fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4102b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4112b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4122b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4132b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4142b4ed282SShri Abhyankar   }
4152b4ed282SShri Abhyankar 
4162b4ed282SShri Abhyankar   if (it && !*reason) {
4177fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4187fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4192b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4202b4ed282SShri Abhyankar     }
4212b4ed282SShri Abhyankar   }
4222b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4232b4ed282SShri Abhyankar }
4242b4ed282SShri Abhyankar 
4252b4ed282SShri Abhyankar /*
4262b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4272b4ed282SShri Abhyankar 
4282b4ed282SShri Abhyankar   Input Parameter:
4292b4ed282SShri Abhyankar . phi - the semismooth function
4302b4ed282SShri Abhyankar 
4312b4ed282SShri Abhyankar   Output Parameter:
4322b4ed282SShri Abhyankar . merit - the merit function
4332b4ed282SShri Abhyankar . phinorm - ||phi||
4342b4ed282SShri Abhyankar 
4352b4ed282SShri Abhyankar   Notes:
4362b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4372b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4382b4ed282SShri Abhyankar */
4392b4ed282SShri Abhyankar #undef __FUNCT__
4402b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4412b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4422b4ed282SShri Abhyankar {
4432b4ed282SShri Abhyankar   PetscErrorCode ierr;
4442b4ed282SShri Abhyankar 
4452b4ed282SShri Abhyankar   PetscFunctionBegin;
4465f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4475f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4482b4ed282SShri Abhyankar 
4492b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4502b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4512b4ed282SShri Abhyankar }
4522b4ed282SShri Abhyankar 
4537f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4544c21c6cdSBarry Smith {
4554c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4564c21c6cdSBarry Smith }
4574c21c6cdSBarry Smith 
4587f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4594c21c6cdSBarry Smith {
4605559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4615559b345SBarry Smith   else return .5;
4624c21c6cdSBarry Smith }
4634c21c6cdSBarry Smith 
4642b4ed282SShri Abhyankar /*
4651f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4662b4ed282SShri Abhyankar 
4672b4ed282SShri Abhyankar    Input Parameters:
4682b4ed282SShri Abhyankar .  snes - the SNES context
4692b4ed282SShri Abhyankar .  x - current iterate
4702b4ed282SShri Abhyankar .  functx - user defined function context
4712b4ed282SShri Abhyankar 
4722b4ed282SShri Abhyankar    Output Parameters:
4732b4ed282SShri Abhyankar .  phi - Semismooth function
4742b4ed282SShri Abhyankar 
4752b4ed282SShri Abhyankar */
4762b4ed282SShri Abhyankar #undef __FUNCT__
4771f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
4781f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
4792b4ed282SShri Abhyankar {
4802b4ed282SShri Abhyankar   PetscErrorCode  ierr;
4812b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
4822b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
4834c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
4842b4ed282SShri Abhyankar   PetscInt        i,nlocal;
4852b4ed282SShri Abhyankar 
4862b4ed282SShri Abhyankar   PetscFunctionBegin;
4872b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
4882b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
4892b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
4902b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
4912b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
4922b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
4932b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
4942b4ed282SShri Abhyankar 
4952b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
49610f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
4974c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
49810f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
4994c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
50010f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5014c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5025559b345SBarry Smith     } else if (l[i] == u[i]) {
5032b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5045559b345SBarry Smith     } else {                                                /* both bounds on variable */
5054c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5062b4ed282SShri Abhyankar     }
5072b4ed282SShri Abhyankar   }
5082b4ed282SShri Abhyankar 
5092b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5102b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5112b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5122b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5132b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5142b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5152b4ed282SShri Abhyankar }
5162b4ed282SShri Abhyankar 
5172b4ed282SShri Abhyankar /*
518a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
519a79edbefSShri Abhyankar                                           the semismooth jacobian.
5202b4ed282SShri Abhyankar */
5212b4ed282SShri Abhyankar #undef __FUNCT__
522a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
523a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5242b4ed282SShri Abhyankar {
5252b4ed282SShri Abhyankar   PetscErrorCode ierr;
5262b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5274c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5282b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5292b4ed282SShri Abhyankar 
5302b4ed282SShri Abhyankar   PetscFunctionBegin;
5312b4ed282SShri Abhyankar 
5322b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5332b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5342b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5352b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
536a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
537a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5382b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5394c21c6cdSBarry Smith 
5402b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
54110f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5424c21c6cdSBarry Smith       da[i] = 0;
5432b4ed282SShri Abhyankar       db[i] = 1;
54410f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5454c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5464c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
54710f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5485559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5495559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5505559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5514c21c6cdSBarry Smith       da[i] = 1;
5522b4ed282SShri Abhyankar       db[i] = 0;
5535559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5544c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5554c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5564c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5574c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5584c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5594c21c6cdSBarry Smith       db[i] = db1*db2;
5602b4ed282SShri Abhyankar     }
5612b4ed282SShri Abhyankar   }
5625559b345SBarry Smith 
5632b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5642b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5652b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5662b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
567a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
568a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
569a79edbefSShri Abhyankar   PetscFunctionReturn(0);
570a79edbefSShri Abhyankar }
571a79edbefSShri Abhyankar 
572a79edbefSShri Abhyankar /*
573a79edbefSShri 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.
574a79edbefSShri Abhyankar 
575a79edbefSShri Abhyankar    Input Parameters:
576a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
577a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
578a79edbefSShri Abhyankar 
579a79edbefSShri Abhyankar    Output Parameters:
580a79edbefSShri Abhyankar .  jac      - semismooth jacobian
581a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
582a79edbefSShri Abhyankar 
583a79edbefSShri Abhyankar    Notes:
584a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
585a79edbefSShri Abhyankar    jac = Da + Db*jacfun
586a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
587a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
588a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
589a79edbefSShri Abhyankar */
590a79edbefSShri Abhyankar #undef __FUNCT__
591a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
592a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
593a79edbefSShri Abhyankar {
594a79edbefSShri Abhyankar   PetscErrorCode ierr;
595a79edbefSShri Abhyankar 
5962b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
597a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
598a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
599a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
600a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
601a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6022b4ed282SShri Abhyankar   }
6032b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6042b4ed282SShri Abhyankar }
6052b4ed282SShri Abhyankar 
6062b4ed282SShri Abhyankar /*
607ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
608ee657d29SShri Abhyankar 
609ee657d29SShri Abhyankar    Input Parameters:
610ee657d29SShri Abhyankar    phi - semismooth function.
611ee657d29SShri Abhyankar    H   - semismooth jacobian
612ee657d29SShri Abhyankar 
613ee657d29SShri Abhyankar    Output Parameters:
614ee657d29SShri Abhyankar    dpsi - merit function gradient
615ee657d29SShri Abhyankar 
616ee657d29SShri Abhyankar    Notes:
617ee657d29SShri Abhyankar   The merit function gradient is computed as follows
618ee657d29SShri Abhyankar         dpsi = H^T*phi
619ee657d29SShri Abhyankar */
620ee657d29SShri Abhyankar #undef __FUNCT__
621ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
622ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
623ee657d29SShri Abhyankar {
624ee657d29SShri Abhyankar   PetscErrorCode ierr;
625ee657d29SShri Abhyankar 
626ee657d29SShri Abhyankar   PetscFunctionBegin;
6275f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
628ee657d29SShri Abhyankar   PetscFunctionReturn(0);
629ee657d29SShri Abhyankar }
630ee657d29SShri Abhyankar 
631c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
632c1a5e521SShri Abhyankar /*
633c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
634c1a5e521SShri Abhyankar 
635c1a5e521SShri Abhyankar    Input Parameters:
636c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
637c1a5e521SShri Abhyankar 
638c1a5e521SShri Abhyankar    Output Parameters:
639c1a5e521SShri Abhyankar .  X - Bound projected X
640c1a5e521SShri Abhyankar 
641c1a5e521SShri Abhyankar */
642c1a5e521SShri Abhyankar 
643c1a5e521SShri Abhyankar #undef __FUNCT__
644c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
645c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
646c1a5e521SShri Abhyankar {
647c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
648c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
649c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
650c1a5e521SShri Abhyankar   PetscScalar       *x;
651c1a5e521SShri Abhyankar   PetscInt          i,n;
652c1a5e521SShri Abhyankar 
653c1a5e521SShri Abhyankar   PetscFunctionBegin;
654c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
655c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
656c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
657c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
658c1a5e521SShri Abhyankar 
659c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
66010f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
66110f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
662c1a5e521SShri Abhyankar   }
663c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
664c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
665c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
666c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
667c1a5e521SShri Abhyankar }
668c1a5e521SShri Abhyankar 
6692b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
6702b4ed282SShri Abhyankar 
6712b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
6722b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
6732b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
6742b4ed282SShri Abhyankar      respectively.
6752b4ed282SShri Abhyankar 
6762b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
6772b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
6782b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
6792b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
6802b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
6812b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
6822b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
6832b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
6842b4ed282SShri Abhyankar      These routines are actually called via the common user interface
6852b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
6862b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
6872b4ed282SShri Abhyankar      for all nonlinear solvers.
6882b4ed282SShri Abhyankar 
6892b4ed282SShri Abhyankar      Another key routine is:
6902b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
6912b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
6922b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
6932b4ed282SShri Abhyankar      SNESSolve() if necessary.
6942b4ed282SShri Abhyankar 
6952b4ed282SShri Abhyankar      Additional basic routines are:
6962b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
6972b4ed282SShri Abhyankar                                       have actually been used.
6982b4ed282SShri Abhyankar      These are called by application codes via the interface routines
6992b4ed282SShri Abhyankar      SNESView().
7002b4ed282SShri Abhyankar 
7012b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7022b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7032b4ed282SShri Abhyankar      above description applies to these categories also.
7042b4ed282SShri Abhyankar 
7052b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7062b4ed282SShri Abhyankar /*
70769c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7082b4ed282SShri Abhyankar    method using a line search.
7092b4ed282SShri Abhyankar 
7102b4ed282SShri Abhyankar    Input Parameters:
7112b4ed282SShri Abhyankar .  snes - the SNES context
7122b4ed282SShri Abhyankar 
7132b4ed282SShri Abhyankar    Output Parameter:
7142b4ed282SShri Abhyankar .  outits - number of iterations until termination
7152b4ed282SShri Abhyankar 
7162b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7172b4ed282SShri Abhyankar 
7182b4ed282SShri Abhyankar    Notes:
7192b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
72051defd01SShri Abhyankar    line search. The default line search does not do any line seach
72151defd01SShri Abhyankar    but rather takes a full newton step.
7222b4ed282SShri Abhyankar */
7232b4ed282SShri Abhyankar #undef __FUNCT__
72469c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
72569c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7262b4ed282SShri Abhyankar {
7272b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7282b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7292b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7303b336b49SShri Abhyankar   PetscBool          lssucceed;
7312b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7322b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7332b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7342b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7352b4ed282SShri Abhyankar 
7362b4ed282SShri Abhyankar   PetscFunctionBegin;
7379ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7389ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7399ce7406fSBarry Smith 
7402b4ed282SShri Abhyankar   snes->numFailures            = 0;
7412b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7422b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7432b4ed282SShri Abhyankar 
7442b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7452b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7462b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7472b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7482b4ed282SShri Abhyankar   G		= snes->work[1];
7492b4ed282SShri Abhyankar   W		= snes->work[2];
7502b4ed282SShri Abhyankar 
7512b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7522b4ed282SShri Abhyankar   snes->iter = 0;
7532b4ed282SShri Abhyankar   snes->norm = 0.0;
7542b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7552b4ed282SShri Abhyankar 
7567fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7572b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7582b4ed282SShri Abhyankar   if (snes->domainerror) {
7592b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7609ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7612b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7622b4ed282SShri Abhyankar   }
7632b4ed282SShri Abhyankar    /* Compute Merit function */
7642b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7652b4ed282SShri Abhyankar 
7662b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7672b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
76862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7692b4ed282SShri Abhyankar 
7702b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7712b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
7722b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7732b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
7747a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
7752b4ed282SShri Abhyankar 
7762b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
7772b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
7782b4ed282SShri Abhyankar   /* test convergence */
7792b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
7809ce7406fSBarry Smith   if (snes->reason) {
7819ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7829ce7406fSBarry Smith     PetscFunctionReturn(0);
7839ce7406fSBarry Smith   }
7842b4ed282SShri Abhyankar 
7852b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
7862b4ed282SShri Abhyankar 
7872b4ed282SShri Abhyankar     /* Call general purpose update function */
7882b4ed282SShri Abhyankar     if (snes->ops->update) {
7892b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
7902b4ed282SShri Abhyankar     }
7912b4ed282SShri Abhyankar 
7922b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
793a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
7942b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
795a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
796a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
797a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
798a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
799ee657d29SShri Abhyankar     /* Compute the merit function gradient */
800ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8022b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8032b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8043b336b49SShri Abhyankar 
8053b336b49SShri Abhyankar     if (kspreason < 0) {
8062b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8072b4ed282SShri 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);
8082b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8092b4ed282SShri Abhyankar         break;
8102b4ed282SShri Abhyankar       }
8112b4ed282SShri Abhyankar     }
8122b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8132b4ed282SShri Abhyankar     snes->linear_its += lits;
8142b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8152b4ed282SShri Abhyankar     /*
8162b4ed282SShri Abhyankar     if (vi->precheckstep) {
817ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8182b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8192b4ed282SShri Abhyankar     }
8202b4ed282SShri Abhyankar 
8212b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8222b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8232b4ed282SShri Abhyankar     }
8242b4ed282SShri Abhyankar     */
8252b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8262b4ed282SShri Abhyankar          Y <- X - lambda*Y
8272b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8282b4ed282SShri Abhyankar     */
8292b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8302b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8312b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8322b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8332b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8342b4ed282SShri Abhyankar     if (snes->domainerror) {
8352b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8369ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8372b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8382b4ed282SShri Abhyankar     }
8392b4ed282SShri Abhyankar     if (!lssucceed) {
8402b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
841ace3abfcSBarry Smith 	PetscBool ismin;
8422b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8432b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8442b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8452b4ed282SShri Abhyankar         break;
8462b4ed282SShri Abhyankar       }
8472b4ed282SShri Abhyankar     }
8482b4ed282SShri Abhyankar     /* Update function and solution vectors */
8492b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8502b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8512b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8522b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8532b4ed282SShri Abhyankar     /* Monitor convergence */
8542b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8552b4ed282SShri Abhyankar     snes->iter = i+1;
8562b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8572b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8582b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8597a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8602b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8612b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8622b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8632b4ed282SShri Abhyankar     if (snes->reason) break;
8642b4ed282SShri Abhyankar   }
8652b4ed282SShri Abhyankar   if (i == maxits) {
8662b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8672b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8682b4ed282SShri Abhyankar   }
8699ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
8702b4ed282SShri Abhyankar   PetscFunctionReturn(0);
8712b4ed282SShri Abhyankar }
87269c03620SShri Abhyankar 
87369c03620SShri Abhyankar #undef __FUNCT__
874693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
875693ddf92SShri Abhyankar /*
876693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
877693ddf92SShri Abhyankar 
878693ddf92SShri Abhyankar    Input parameter
879693ddf92SShri Abhyankar .  snes - the SNES context
880693ddf92SShri Abhyankar .  X    - the snes solution vector
881693ddf92SShri Abhyankar .  F    - the nonlinear function vector
882693ddf92SShri Abhyankar 
883693ddf92SShri Abhyankar    Output parameter
884693ddf92SShri Abhyankar .  ISact - active set index set
885693ddf92SShri Abhyankar  */
886693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
887d950fb63SShri Abhyankar {
888d950fb63SShri Abhyankar   PetscErrorCode   ierr;
889693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
890693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
891693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
892693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
893d950fb63SShri Abhyankar 
894d950fb63SShri Abhyankar   PetscFunctionBegin;
895d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
896d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
897fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
898fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
899fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
900fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
901693ddf92SShri Abhyankar   /* Compute active set size */
902d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
90310f5ae6bSBarry 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++;
904d950fb63SShri Abhyankar   }
905693ddf92SShri Abhyankar 
906d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
907d950fb63SShri Abhyankar 
908693ddf92SShri Abhyankar   /* Set active set indices */
909d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
91010f5ae6bSBarry 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;
911d950fb63SShri Abhyankar   }
912d950fb63SShri Abhyankar 
913693ddf92SShri Abhyankar    /* Create active set IS */
91462298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
915d950fb63SShri Abhyankar 
916fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
917fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
918fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
919fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
920d950fb63SShri Abhyankar   PetscFunctionReturn(0);
921d950fb63SShri Abhyankar }
922d950fb63SShri Abhyankar 
923693ddf92SShri Abhyankar #undef __FUNCT__
924693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
925693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
926693ddf92SShri Abhyankar {
927693ddf92SShri Abhyankar   PetscErrorCode     ierr;
928693ddf92SShri Abhyankar 
929693ddf92SShri Abhyankar   PetscFunctionBegin;
930693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
931693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
932693ddf92SShri Abhyankar   PetscFunctionReturn(0);
933693ddf92SShri Abhyankar }
934693ddf92SShri Abhyankar 
935dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
936dbd914b8SShri Abhyankar #undef __FUNCT__
937fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
938fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
939dbd914b8SShri Abhyankar {
940dbd914b8SShri Abhyankar   PetscErrorCode ierr;
941dbd914b8SShri Abhyankar   Vec            v;
942dbd914b8SShri Abhyankar 
943dbd914b8SShri Abhyankar   PetscFunctionBegin;
944dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
945dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
946dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
947dbd914b8SShri Abhyankar   *newv = v;
948dbd914b8SShri Abhyankar 
949dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
950dbd914b8SShri Abhyankar }
951dbd914b8SShri Abhyankar 
952732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
953732bb160SShri Abhyankar #undef __FUNCT__
954732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
955732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
956732bb160SShri Abhyankar {
957732bb160SShri Abhyankar   PetscErrorCode         ierr;
958d0af7cd3SBarry Smith   KSP                    snesksp;
959dbd914b8SShri Abhyankar 
960732bb160SShri Abhyankar   PetscFunctionBegin;
961732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
962d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
963c2efdce3SBarry Smith 
964c2efdce3SBarry Smith   /*
965d0af7cd3SBarry Smith   KSP                    kspnew;
966d0af7cd3SBarry Smith   PC                     pcnew;
967d0af7cd3SBarry Smith   const MatSolverPackage stype;
968d0af7cd3SBarry Smith 
969c2efdce3SBarry Smith 
970732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
971732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
972732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
973732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
974732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
975732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
976732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
977732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
978732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
979732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
980732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
9816bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
982732bb160SShri Abhyankar   snes->ksp = kspnew;
983732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
984d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
985732bb160SShri Abhyankar   PetscFunctionReturn(0);
986732bb160SShri Abhyankar }
98769c03620SShri Abhyankar 
98869c03620SShri Abhyankar 
989fe835674SShri Abhyankar #undef __FUNCT__
990fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
99110f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
992fe835674SShri Abhyankar {
993fe835674SShri Abhyankar   PetscErrorCode    ierr;
994fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
995fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
996fe835674SShri Abhyankar   PetscInt          i,n;
997fe835674SShri Abhyankar   PetscReal         rnorm;
998fe835674SShri Abhyankar 
999fe835674SShri Abhyankar   PetscFunctionBegin;
1000fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1001fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1002fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1003fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1004fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1005fe835674SShri Abhyankar   rnorm = 0.0;
1006fe835674SShri Abhyankar   for (i=0; i<n; i++) {
100710f5ae6bSBarry 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]);
1008fe835674SShri Abhyankar   }
1009fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1010fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1011fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1012fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1013d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1014fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1015fe835674SShri Abhyankar   PetscFunctionReturn(0);
1016fe835674SShri Abhyankar }
1017fe835674SShri Abhyankar 
1018fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1019c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1020c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1021d950fb63SShri Abhyankar #undef __FUNCT__
1022d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1023d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1024d950fb63SShri Abhyankar {
1025d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1026d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1027abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1028d950fb63SShri Abhyankar   PetscBool         lssucceed;
1029d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1030fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1031d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1032d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1033d950fb63SShri Abhyankar 
1034d950fb63SShri Abhyankar   PetscFunctionBegin;
1035d950fb63SShri Abhyankar   snes->numFailures            = 0;
1036d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1037d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1038d950fb63SShri Abhyankar 
1039d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1040d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1041d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1042d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1043d950fb63SShri Abhyankar   G		= snes->work[1];
1044d950fb63SShri Abhyankar   W		= snes->work[2];
1045d950fb63SShri Abhyankar 
1046d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1047d950fb63SShri Abhyankar   snes->iter = 0;
1048d950fb63SShri Abhyankar   snes->norm = 0.0;
1049d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1050d950fb63SShri Abhyankar 
10517fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1052fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1053d950fb63SShri Abhyankar   if (snes->domainerror) {
1054d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1055d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1056d950fb63SShri Abhyankar   }
1057fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1058d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1059d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
106062cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1061d950fb63SShri Abhyankar 
1062d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1063fe835674SShri Abhyankar   snes->norm = fnorm;
1064d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1065fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10667a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1067d950fb63SShri Abhyankar 
1068d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1069fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1070d950fb63SShri Abhyankar   /* test convergence */
1071fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1072d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1073d950fb63SShri Abhyankar 
1074d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1075d950fb63SShri Abhyankar 
1076d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1077d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1078abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1079fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1080d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
108162298a1eSBarry Smith     IS         keptrows;
1082abcba341SShri Abhyankar     PetscBool  isequal;
1083d950fb63SShri Abhyankar 
1084d950fb63SShri Abhyankar     /* Call general purpose update function */
1085d950fb63SShri Abhyankar     if (snes->ops->update) {
1086d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1087d950fb63SShri Abhyankar     }
1088d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
108962298a1eSBarry Smith 
1090d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1091693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1092d950fb63SShri Abhyankar 
10934dcab191SBarry Smith 
1094abcba341SShri Abhyankar     /* Create inactive set submatrix */
109562298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1096b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
109762298a1eSBarry Smith     if (keptrows) {
109862298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
109962298a1eSBarry Smith       const PetscInt *krows,*inact;
110027d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
110162298a1eSBarry Smith 
11026bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11036bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
110462298a1eSBarry Smith 
110562298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
110662298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
110762298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
110862298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
110962298a1eSBarry Smith       for (k=0; k<cnt; k++) {
111027d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
111162298a1eSBarry Smith       }
111262298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
111362298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11146bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11156bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
111662298a1eSBarry Smith 
111727d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
111827d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
111962298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
112062298a1eSBarry Smith     }
11219e516c8fSBarry Smith     ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr);
112262298a1eSBarry Smith 
1123d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1124d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1125d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1126d950fb63SShri Abhyankar 
1127d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1128fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1129fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1130fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1131d950fb63SShri Abhyankar 
1132d950fb63SShri Abhyankar     /* Create scatter contexts */
1133d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1134d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1135d950fb63SShri Abhyankar 
1136d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1137fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1138fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1139d950fb63SShri Abhyankar 
1140d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1141d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1142d950fb63SShri Abhyankar 
1143d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1144d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1145d950fb63SShri Abhyankar 
1146d950fb63SShri Abhyankar     /* Active set direction = 0 */
1147d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1148d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1149d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1150d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1151d950fb63SShri Abhyankar 
1152abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1153abcba341SShri Abhyankar     if (!isequal) {
1154732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1155d950fb63SShri Abhyankar     }
1156d950fb63SShri Abhyankar 
115713e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
115813e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
115913e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
116013e0d083SBarry Smith 
1161d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
116213e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
116313e0d083SBarry Smith     {
116413e0d083SBarry Smith       PC        pc;
116513e0d083SBarry Smith       PetscBool flg;
116613e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
116713e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
116813e0d083SBarry Smith       if (flg) {
116913e0d083SBarry Smith         KSP      *subksps;
117013e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
117113e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
117213e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
117313e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
117413e0d083SBarry Smith         if (flg) {
117513e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
117613e0d083SBarry Smith           const PetscInt *ii;
117713e0d083SBarry Smith 
117813e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
117913e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
118013e0d083SBarry Smith           for (j=0; j<n; j++) {
118113e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
118213e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
118313e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
118413e0d083SBarry Smith           }
118513e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
118613e0d083SBarry Smith 
118713e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
118813e0d083SBarry Smith         }
118913e0d083SBarry Smith       }
119013e0d083SBarry Smith     }
119113e0d083SBarry Smith 
1192fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1193d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1194d950fb63SShri Abhyankar     if (kspreason < 0) {
1195d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1196d950fb63SShri 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);
1197d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1198d950fb63SShri Abhyankar         break;
1199d950fb63SShri Abhyankar       }
1200d950fb63SShri Abhyankar      }
1201d950fb63SShri Abhyankar 
1202d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1203d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1204d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1205d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1206d950fb63SShri Abhyankar 
12076bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12086bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
12096bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
12106bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
12116bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
12126bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1213abcba341SShri Abhyankar     if (!isequal) {
12146bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1215abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1216abcba341SShri Abhyankar     }
12176bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
12186bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1219d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
12206bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1221d950fb63SShri Abhyankar     }
1222d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1223d950fb63SShri Abhyankar     snes->linear_its += lits;
1224d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1225d950fb63SShri Abhyankar     /*
1226d950fb63SShri Abhyankar     if (vi->precheckstep) {
1227d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1228d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1229d950fb63SShri Abhyankar     }
1230d950fb63SShri Abhyankar 
1231d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1232d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1233d950fb63SShri Abhyankar     }
1234d950fb63SShri Abhyankar     */
1235d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1236d950fb63SShri Abhyankar          Y <- X - lambda*Y
1237d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1238d950fb63SShri Abhyankar     */
1239d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1240fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1241fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1242fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
12432b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
12442b4ed282SShri Abhyankar     if (snes->domainerror) {
12452b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1246*4c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
12472b4ed282SShri Abhyankar       PetscFunctionReturn(0);
12482b4ed282SShri Abhyankar     }
12492b4ed282SShri Abhyankar     if (!lssucceed) {
12502b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
12512b4ed282SShri Abhyankar 	PetscBool ismin;
12522b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
12532b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
12542b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
12552b4ed282SShri Abhyankar         break;
12562b4ed282SShri Abhyankar       }
12572b4ed282SShri Abhyankar     }
12582b4ed282SShri Abhyankar     /* Update function and solution vectors */
1259fe835674SShri Abhyankar     fnorm = gnorm;
1260fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
12612b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
12622b4ed282SShri Abhyankar     /* Monitor convergence */
12632b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
12642b4ed282SShri Abhyankar     snes->iter = i+1;
1265fe835674SShri Abhyankar     snes->norm = fnorm;
12662b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
12672b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
12687a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
12692b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
12702b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1271fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
12722b4ed282SShri Abhyankar     if (snes->reason) break;
12732b4ed282SShri Abhyankar   }
1274*4c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
12752b4ed282SShri Abhyankar   if (i == maxits) {
12762b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
12772b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
12782b4ed282SShri Abhyankar   }
12792b4ed282SShri Abhyankar   PetscFunctionReturn(0);
12802b4ed282SShri Abhyankar }
12812b4ed282SShri Abhyankar 
12822f63a38cSShri Abhyankar #undef __FUNCT__
1283720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1284cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
12852f63a38cSShri Abhyankar {
12862f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
12872f63a38cSShri Abhyankar 
12882f63a38cSShri Abhyankar   PetscFunctionBegin;
12892f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
12902f63a38cSShri Abhyankar   vi->checkredundancy = func;
1291cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
12922f63a38cSShri Abhyankar   PetscFunctionReturn(0);
12932f63a38cSShri Abhyankar }
12942f63a38cSShri Abhyankar 
1295ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1296ff596062SShri Abhyankar #include <engine.h>
1297ff596062SShri Abhyankar #include <mex.h>
1298cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1299ff596062SShri Abhyankar 
1300ff596062SShri Abhyankar #undef __FUNCT__
1301ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1302ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1303ff596062SShri Abhyankar {
1304ff596062SShri Abhyankar   PetscErrorCode      ierr;
1305cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1306cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1307cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1308cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1309fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1310ff596062SShri Abhyankar 
1311ff596062SShri Abhyankar   PetscFunctionBegin;
1312ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1313ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1314ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1315ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1316ff596062SShri Abhyankar 
131709db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
131809db5ad8SShri Abhyankar    bet set by the Matlab function */
1319fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1320cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1321ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1322ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1323cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1324ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1325ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1326cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1327cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1328cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1329ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1330ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1331ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1332ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1333ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1334ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1335ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1336ff596062SShri Abhyankar   PetscFunctionReturn(0);
1337ff596062SShri Abhyankar }
1338ff596062SShri Abhyankar 
1339ff596062SShri Abhyankar #undef __FUNCT__
1340ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1341ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1342ff596062SShri Abhyankar {
1343ff596062SShri Abhyankar   PetscErrorCode      ierr;
1344cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1345ff596062SShri Abhyankar 
1346ff596062SShri Abhyankar   PetscFunctionBegin;
1347ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1348cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1349ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1350ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1351cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1352ff596062SShri Abhyankar   PetscFunctionReturn(0);
1353ff596062SShri Abhyankar }
1354ff596062SShri Abhyankar 
1355ff596062SShri Abhyankar #endif
1356ff596062SShri Abhyankar 
1357ff596062SShri Abhyankar 
13582f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
13592f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1360720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
136156a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
136256a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
13632f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
13642f63a38cSShri Abhyankar */
13652f63a38cSShri Abhyankar #undef __FUNCT__
1366b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1367b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
13682f63a38cSShri Abhyankar {
13692f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
13702f63a38cSShri Abhyankar   PetscErrorCode    ierr;
13712f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
13722f63a38cSShri Abhyankar   PetscBool         lssucceed;
13732f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
13742f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
13752f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
13762f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
13772f63a38cSShri Abhyankar 
13782f63a38cSShri Abhyankar   PetscFunctionBegin;
13792f63a38cSShri Abhyankar   snes->numFailures            = 0;
13802f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
13812f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
13822f63a38cSShri Abhyankar 
13832f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
13842f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
13852f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
13862f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
13872f63a38cSShri Abhyankar   G		= snes->work[1];
13882f63a38cSShri Abhyankar   W		= snes->work[2];
13892f63a38cSShri Abhyankar 
13902f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13912f63a38cSShri Abhyankar   snes->iter = 0;
13922f63a38cSShri Abhyankar   snes->norm = 0.0;
13932f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13942f63a38cSShri Abhyankar 
13952f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
13962f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
13972f63a38cSShri Abhyankar   if (snes->domainerror) {
13982f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13992f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14002f63a38cSShri Abhyankar   }
14012f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14022f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14032f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
140462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14052f63a38cSShri Abhyankar 
14062f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14072f63a38cSShri Abhyankar   snes->norm = fnorm;
14082f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14092f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
14107a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
14112f63a38cSShri Abhyankar 
14122f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
14132f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
14142f63a38cSShri Abhyankar   /* test convergence */
14152f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
14162f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
14172f63a38cSShri Abhyankar 
14182f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
14192f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1420cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
142156a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
142256a221efSShri Abhyankar     Vec            F_aug,Y_aug;
142356a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
142456a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
142556a221efSShri Abhyankar     PetscInt       k;
142663ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
142756a221efSShri Abhyankar     PetscScalar    *f,*f2;
14282f63a38cSShri Abhyankar     PetscBool      isequal;
142956a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
14302f63a38cSShri Abhyankar 
14312f63a38cSShri Abhyankar     /* Call general purpose update function */
14322f63a38cSShri Abhyankar     if (snes->ops->update) {
14332f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
14342f63a38cSShri Abhyankar     }
14352f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
14362f63a38cSShri Abhyankar 
14372f63a38cSShri Abhyankar     /* Create active and inactive index sets */
14382f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
14392f63a38cSShri Abhyankar 
144056a221efSShri Abhyankar     /* Get local active set size */
14412f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
144256a221efSShri Abhyankar     if (nis_act) {
1443e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1444e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
144556a221efSShri Abhyankar       if(vi->checkredundancy) {
1446cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
144756a221efSShri Abhyankar       }
14482f63a38cSShri Abhyankar 
144956a221efSShri Abhyankar       if(!IS_redact) {
145056a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
145156a221efSShri Abhyankar            there were no redundant active set variables */
145256a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
145356a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
145456a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
145556a221efSShri Abhyankar 	nkept = nis_act;
145656a221efSShri Abhyankar       } else {
145756a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
145856a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
14592f63a38cSShri Abhyankar 
146056a221efSShri Abhyankar 	/* Create reduced active set list */
146156a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
146256a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1463cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
146456a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
146556a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
146656a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
146756a221efSShri Abhyankar 	}
146856a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
146956a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1470cb5fe31bSShri Abhyankar 
1471cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
147256a221efSShri Abhyankar       }
14732f63a38cSShri Abhyankar 
147456a221efSShri Abhyankar       /* Create augmented F and Y */
147556a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
147656a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
147756a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
147856a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
14792f63a38cSShri Abhyankar 
148056a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
148156a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
148256a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
148356a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
148456a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
148556a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
14862f63a38cSShri Abhyankar 
148756a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
148856a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
148956a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
149056a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
14912f63a38cSShri Abhyankar 
149256a221efSShri Abhyankar 
14939521db3cSSatish Balay       { /* local vars */
1494493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
149556a221efSShri Abhyankar       PetscInt          ncols;
149656a221efSShri Abhyankar       const PetscInt    *cols;
149756a221efSShri Abhyankar       const PetscScalar *vals;
14982969f145SShri Abhyankar       PetscScalar        value[2];
14992969f145SShri Abhyankar       PetscInt           row,col[2];
1500493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15012969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1502493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1503493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1504493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1505493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1506493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1507493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1508493a4f3dSShri Abhyankar       }
1509493a4f3dSShri Abhyankar 
1510493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1511493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
15122969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1513493a4f3dSShri Abhyankar       }
1514493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1515493a4f3dSShri Abhyankar 
1516493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
151756a221efSShri Abhyankar 
151856a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
151956a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
152056a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
152156a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
152256a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
152356a221efSShri Abhyankar       }
152456a221efSShri Abhyankar       /* Add the augmented part */
152556a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
15262969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
15272969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
15282969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
15292969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
153056a221efSShri Abhyankar       }
153156a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
153256a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
153356a221efSShri Abhyankar       /* Only considering prejac = jac for now */
153456a221efSShri Abhyankar       Jpre_aug = J_aug;
15359521db3cSSatish Balay       } /* local vars*/
1536e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1537e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
153856a221efSShri Abhyankar     } else {
153956a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
154056a221efSShri Abhyankar     }
15412f63a38cSShri Abhyankar 
15422f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
15432f63a38cSShri Abhyankar     if (!isequal) {
154456a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
15452f63a38cSShri Abhyankar     }
154656a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
15472f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
154856a221efSShri Abhyankar     /*  {
15492f63a38cSShri Abhyankar       PC        pc;
15502f63a38cSShri Abhyankar       PetscBool flg;
15512f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
15522f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15532f63a38cSShri Abhyankar       if (flg) {
15542f63a38cSShri Abhyankar         KSP      *subksps;
15552f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
15562f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
15572f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
15582f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
15592f63a38cSShri Abhyankar         if (flg) {
15602f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
15612f63a38cSShri Abhyankar           const PetscInt *ii;
15622f63a38cSShri Abhyankar 
15632f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
15642f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
15652f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
15662f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
15672f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
15682f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
15692f63a38cSShri Abhyankar           }
15702f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
15712f63a38cSShri Abhyankar 
15722f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
15732f63a38cSShri Abhyankar         }
15742f63a38cSShri Abhyankar       }
15752f63a38cSShri Abhyankar     }
157656a221efSShri Abhyankar     */
157756a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
15782f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
15792f63a38cSShri Abhyankar     if (kspreason < 0) {
15802f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
15812f63a38cSShri 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);
15822f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
15832f63a38cSShri Abhyankar         break;
15842f63a38cSShri Abhyankar       }
15852f63a38cSShri Abhyankar     }
15862f63a38cSShri Abhyankar 
158756a221efSShri Abhyankar     if(nis_act) {
158856a221efSShri Abhyankar       PetscScalar *y1,*y2;
158956a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
159056a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
159156a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
159256a221efSShri Abhyankar       j1 = 0;
159356a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
159456a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
159556a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
159656a221efSShri Abhyankar       }
159756a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
159856a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
15992f63a38cSShri Abhyankar 
16006bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16016bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16026bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
160356a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
160456a221efSShri Abhyankar     }
160556a221efSShri Abhyankar 
16062f63a38cSShri Abhyankar     if (!isequal) {
16076bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16082f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
16092f63a38cSShri Abhyankar     }
16106bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
161156a221efSShri Abhyankar 
16122f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
16132f63a38cSShri Abhyankar     snes->linear_its += lits;
16142f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
16152f63a38cSShri Abhyankar     /*
16162f63a38cSShri Abhyankar     if (vi->precheckstep) {
16172f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
16182f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
16192f63a38cSShri Abhyankar     }
16202f63a38cSShri Abhyankar 
16212f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
16222f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
16232f63a38cSShri Abhyankar     }
16242f63a38cSShri Abhyankar     */
16252f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
16262f63a38cSShri Abhyankar          Y <- X - lambda*Y
16272f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
16282f63a38cSShri Abhyankar     */
16292f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
16302f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
16312f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
16322f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
16332f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
16342f63a38cSShri Abhyankar     if (snes->domainerror) {
16352f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
16362f63a38cSShri Abhyankar       PetscFunctionReturn(0);
16372f63a38cSShri Abhyankar     }
16382f63a38cSShri Abhyankar     if (!lssucceed) {
16392f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
16402f63a38cSShri Abhyankar 	PetscBool ismin;
16412f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
16422f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
16432f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
16442f63a38cSShri Abhyankar         break;
16452f63a38cSShri Abhyankar       }
16462f63a38cSShri Abhyankar     }
16472f63a38cSShri Abhyankar     /* Update function and solution vectors */
16482f63a38cSShri Abhyankar     fnorm = gnorm;
16492f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
16502f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
16512f63a38cSShri Abhyankar     /* Monitor convergence */
16522f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
16532f63a38cSShri Abhyankar     snes->iter = i+1;
16542f63a38cSShri Abhyankar     snes->norm = fnorm;
16552f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
16562f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
16577a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16582f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
16592f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
16602f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
16612f63a38cSShri Abhyankar     if (snes->reason) break;
16622f63a38cSShri Abhyankar   }
16632f63a38cSShri Abhyankar   if (i == maxits) {
16642f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
16652f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
16662f63a38cSShri Abhyankar   }
16672f63a38cSShri Abhyankar   PetscFunctionReturn(0);
16682f63a38cSShri Abhyankar }
16692f63a38cSShri Abhyankar 
16702b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
16712b4ed282SShri Abhyankar /*
16722b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
16732b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
16742b4ed282SShri Abhyankar 
16752b4ed282SShri Abhyankar    Input Parameter:
16762b4ed282SShri Abhyankar .  snes - the SNES context
16772b4ed282SShri Abhyankar .  x - the solution vector
16782b4ed282SShri Abhyankar 
16792b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
16802b4ed282SShri Abhyankar 
16812b4ed282SShri Abhyankar    Notes:
16822b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
16832b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
16842b4ed282SShri Abhyankar    the call to SNESSolve().
16852b4ed282SShri Abhyankar  */
16862b4ed282SShri Abhyankar #undef __FUNCT__
16872b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
16882b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
16892b4ed282SShri Abhyankar {
16902b4ed282SShri Abhyankar   PetscErrorCode ierr;
16912b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
16922b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
16932b4ed282SShri Abhyankar 
16942b4ed282SShri Abhyankar   PetscFunctionBegin;
169558c9b817SLisandro Dalcin 
169658c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
16972b4ed282SShri Abhyankar 
16982b4ed282SShri Abhyankar   /* If the lower and upper bound on variables are not set, set it to
16992b4ed282SShri Abhyankar      -Inf and Inf */
17002b4ed282SShri Abhyankar   if (!vi->xl && !vi->xu) {
17012b4ed282SShri Abhyankar     vi->usersetxbounds = PETSC_FALSE;
17022b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr);
170301f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17042b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr);
170501f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17062b4ed282SShri Abhyankar   } else {
17072b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
17082b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
17092b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
17102b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
17112b4ed282SShri 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]))
17122b4ed282SShri 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.");
17132b4ed282SShri Abhyankar   }
17142f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1715abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1716abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1717abcba341SShri Abhyankar     PetscInt *indices;
1718abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1719abcba341SShri Abhyankar 
1720abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1721abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1722abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1723abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1724abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1725abcba341SShri Abhyankar   }
17262b4ed282SShri Abhyankar 
17272f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1728fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1729fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr);
1730fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr);
1731fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr);
1732fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1733fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr);
1734fe835674SShri Abhyankar   }
17352b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17362b4ed282SShri Abhyankar }
17372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17382b4ed282SShri Abhyankar /*
17392b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
17402b4ed282SShri Abhyankar    with SNESCreate_VI().
17412b4ed282SShri Abhyankar 
17422b4ed282SShri Abhyankar    Input Parameter:
17432b4ed282SShri Abhyankar .  snes - the SNES context
17442b4ed282SShri Abhyankar 
17452b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
17462b4ed282SShri Abhyankar  */
17472b4ed282SShri Abhyankar #undef __FUNCT__
17482b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
17492b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
17502b4ed282SShri Abhyankar {
17512b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17522b4ed282SShri Abhyankar   PetscErrorCode ierr;
17532b4ed282SShri Abhyankar 
17542b4ed282SShri Abhyankar   PetscFunctionBegin;
17552f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
17566bf464f9SBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);
1757abcba341SShri Abhyankar   }
17582b4ed282SShri Abhyankar 
17592f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
17602b4ed282SShri Abhyankar     /* clear vectors */
17616bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
17626bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi); CHKERRQ(ierr);
17636bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da); CHKERRQ(ierr);
17646bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db); CHKERRQ(ierr);
17656bf464f9SBarry Smith     ierr = VecDestroy(&vi->z); CHKERRQ(ierr);
17666bf464f9SBarry Smith     ierr = VecDestroy(&vi->t); CHKERRQ(ierr);
17677fe79bc4SShri Abhyankar   }
17687fe79bc4SShri Abhyankar 
17692b4ed282SShri Abhyankar   if (!vi->usersetxbounds) {
17706bf464f9SBarry Smith     ierr = VecDestroy(&vi->xl); CHKERRQ(ierr);
17716bf464f9SBarry Smith     ierr = VecDestroy(&vi->xu); CHKERRQ(ierr);
17722b4ed282SShri Abhyankar   }
17737fe79bc4SShri Abhyankar 
17746bf464f9SBarry Smith   ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
17752b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
17762b4ed282SShri Abhyankar 
17772b4ed282SShri Abhyankar   /* clear composed functions */
17782b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1779c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
17802b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17812b4ed282SShri Abhyankar }
17827fe79bc4SShri Abhyankar 
17832b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17842b4ed282SShri Abhyankar #undef __FUNCT__
17852b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
17862b4ed282SShri Abhyankar 
17872b4ed282SShri Abhyankar /*
17887fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
17897fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
17902b4ed282SShri Abhyankar 
17912b4ed282SShri Abhyankar */
1792ace3abfcSBarry 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)
17932b4ed282SShri Abhyankar {
17942b4ed282SShri Abhyankar   PetscErrorCode ierr;
17952b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1796ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
17972b4ed282SShri Abhyankar 
17982b4ed282SShri Abhyankar   PetscFunctionBegin;
17992b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18002b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18012b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
18022b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1803c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1804c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1805c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1806c1a5e521SShri Abhyankar   }
1807c1a5e521SShri Abhyankar   if (changed_y) {
1808c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18097fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1810c1a5e521SShri Abhyankar   }
1811c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1812c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1813c1a5e521SShri Abhyankar   if (!snes->domainerror) {
18142f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
18157fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
18167fe79bc4SShri Abhyankar     } else {
1817c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
18187fe79bc4SShri Abhyankar     }
181962cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1820c1a5e521SShri Abhyankar   }
1821c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1822c1a5e521SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1823c1a5e521SShri Abhyankar   }
1824c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1825c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1826c1a5e521SShri Abhyankar }
1827c1a5e521SShri Abhyankar 
1828c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1829c1a5e521SShri Abhyankar #undef __FUNCT__
18302b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
18312b4ed282SShri Abhyankar 
18322b4ed282SShri Abhyankar /*
18332b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
18342b4ed282SShri Abhyankar */
1835ace3abfcSBarry 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)
18362b4ed282SShri Abhyankar {
18372b4ed282SShri Abhyankar   PetscErrorCode ierr;
18382b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1839ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18402b4ed282SShri Abhyankar 
18412b4ed282SShri Abhyankar   PetscFunctionBegin;
18422b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18432b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18442b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
18457fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18462b4ed282SShri Abhyankar   if (vi->postcheckstep) {
18472b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
18482b4ed282SShri Abhyankar   }
18492b4ed282SShri Abhyankar   if (changed_y) {
18502b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18517fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18522b4ed282SShri Abhyankar   }
18532b4ed282SShri Abhyankar 
18542b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
18552b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
18562b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18572b4ed282SShri Abhyankar   }
18582b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18592b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18602b4ed282SShri Abhyankar }
18617fe79bc4SShri Abhyankar 
18622b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18632b4ed282SShri Abhyankar #undef __FUNCT__
18642b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
18652b4ed282SShri Abhyankar /*
18667fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
18672b4ed282SShri Abhyankar */
1868ace3abfcSBarry 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)
18692b4ed282SShri Abhyankar {
1870fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1871fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1872fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1873fe835674SShri Abhyankar   PetscScalar    cinitslope;
1874fe835674SShri Abhyankar #endif
1875fe835674SShri Abhyankar   PetscErrorCode ierr;
1876fe835674SShri Abhyankar   PetscInt       count;
1877fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1878fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1879fe835674SShri Abhyankar   MPI_Comm       comm;
1880fe835674SShri Abhyankar 
1881fe835674SShri Abhyankar   PetscFunctionBegin;
1882fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1883fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1884fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1885fe835674SShri Abhyankar 
1886fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1887fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1888fe835674SShri Abhyankar     if (vi->lsmonitor) {
1889fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1890fe835674SShri Abhyankar     }
1891fe835674SShri Abhyankar     *gnorm = fnorm;
1892fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1893fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1894fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1895fe835674SShri Abhyankar     goto theend1;
1896fe835674SShri Abhyankar   }
1897fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1898fe835674SShri Abhyankar     if (vi->lsmonitor) {
1899fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1900fe835674SShri Abhyankar     }
1901fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1902fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1903fe835674SShri Abhyankar   }
1904fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1905fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1906fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1907fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1908fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1909fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1910fe835674SShri Abhyankar #else
1911fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1912fe835674SShri Abhyankar #endif
1913fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1914fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1915fe835674SShri Abhyankar 
1916fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
1917fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1918fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1919fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
1920fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1921fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1922fe835674SShri Abhyankar     goto theend1;
1923fe835674SShri Abhyankar   }
1924fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19252f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1926fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19277fe79bc4SShri Abhyankar   } else {
19287fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19297fe79bc4SShri Abhyankar   }
1930fe835674SShri Abhyankar   if (snes->domainerror) {
1931fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1932fe835674SShri Abhyankar     PetscFunctionReturn(0);
1933fe835674SShri Abhyankar   }
193462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1935fe835674SShri Abhyankar   ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1936fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
1937fe835674SShri Abhyankar     if (vi->lsmonitor) {
1938fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1939fe835674SShri Abhyankar     }
1940fe835674SShri Abhyankar     goto theend1;
1941fe835674SShri Abhyankar   }
1942fe835674SShri Abhyankar 
1943fe835674SShri Abhyankar   /* Fit points with quadratic */
1944fe835674SShri Abhyankar   lambda     = 1.0;
1945fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
1946fe835674SShri Abhyankar   lambdaprev = lambda;
1947fe835674SShri Abhyankar   gnormprev  = *gnorm;
1948fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1949fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
1950fe835674SShri Abhyankar   else                         lambda = lambdatemp;
1951fe835674SShri Abhyankar 
1952fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1953fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1954fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1955fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
1956fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1957fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1958fe835674SShri Abhyankar     goto theend1;
1959fe835674SShri Abhyankar   }
1960fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19612f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1962fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19637fe79bc4SShri Abhyankar   } else {
19647fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19657fe79bc4SShri Abhyankar   }
1966fe835674SShri Abhyankar   if (snes->domainerror) {
1967fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1968fe835674SShri Abhyankar     PetscFunctionReturn(0);
1969fe835674SShri Abhyankar   }
197062cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1971fe835674SShri Abhyankar   if (vi->lsmonitor) {
1972fe835674SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
1973fe835674SShri Abhyankar   }
1974fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
1975fe835674SShri Abhyankar     if (vi->lsmonitor) {
1976fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
1977fe835674SShri Abhyankar     }
1978fe835674SShri Abhyankar     goto theend1;
1979fe835674SShri Abhyankar   }
1980fe835674SShri Abhyankar 
1981fe835674SShri Abhyankar   /* Fit points with cubic */
1982fe835674SShri Abhyankar   count = 1;
1983fe835674SShri Abhyankar   while (PETSC_TRUE) {
1984fe835674SShri Abhyankar     if (lambda <= minlambda) {
1985fe835674SShri Abhyankar       if (vi->lsmonitor) {
1986fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
1987fe835674SShri 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);
1988fe835674SShri Abhyankar       }
1989fe835674SShri Abhyankar       *flag = PETSC_FALSE;
1990fe835674SShri Abhyankar       break;
1991fe835674SShri Abhyankar     }
1992fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
1993fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
1994fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1995fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1996fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
1997fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
1998fe835674SShri Abhyankar     if (a == 0.0) {
1999fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2000fe835674SShri Abhyankar     } else {
2001fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2002fe835674SShri Abhyankar     }
2003fe835674SShri Abhyankar     lambdaprev = lambda;
2004fe835674SShri Abhyankar     gnormprev  = *gnorm;
2005fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2006fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2007fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2008fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2009fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2010fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2011fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2012fe835674SShri 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);
2013fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2014fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2015fe835674SShri Abhyankar       break;
2016fe835674SShri Abhyankar     }
2017fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20182f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2019fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20207fe79bc4SShri Abhyankar     } else {
20217fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20227fe79bc4SShri Abhyankar     }
2023fe835674SShri Abhyankar     if (snes->domainerror) {
2024fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2025fe835674SShri Abhyankar       PetscFunctionReturn(0);
2026fe835674SShri Abhyankar     }
202762cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2028fe835674SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */
2029fe835674SShri Abhyankar       if (vi->lsmonitor) {
2030fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2031fe835674SShri Abhyankar       }
2032fe835674SShri Abhyankar       break;
2033fe835674SShri Abhyankar     } else {
2034fe835674SShri Abhyankar       if (vi->lsmonitor) {
2035fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2036fe835674SShri Abhyankar       }
2037fe835674SShri Abhyankar     }
2038fe835674SShri Abhyankar     count++;
2039fe835674SShri Abhyankar   }
2040fe835674SShri Abhyankar   theend1:
2041fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2042fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2043fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2044fe835674SShri Abhyankar     if (changed_y) {
2045fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2046fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2047fe835674SShri Abhyankar     }
2048fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2049fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20502f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2051fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20527fe79bc4SShri Abhyankar       } else {
20537fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20547fe79bc4SShri Abhyankar       }
2055fe835674SShri Abhyankar       if (snes->domainerror) {
2056fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2057fe835674SShri Abhyankar         PetscFunctionReturn(0);
2058fe835674SShri Abhyankar       }
205962cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2060fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2061fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2062fe835674SShri Abhyankar     }
2063fe835674SShri Abhyankar   }
2064fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2065fe835674SShri Abhyankar   PetscFunctionReturn(0);
2066fe835674SShri Abhyankar }
2067fe835674SShri Abhyankar 
20682b4ed282SShri Abhyankar #undef __FUNCT__
20692b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
20702b4ed282SShri Abhyankar /*
20717fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
20722b4ed282SShri Abhyankar */
2073ace3abfcSBarry 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)
20742b4ed282SShri Abhyankar {
20752b4ed282SShri Abhyankar   /*
20762b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
20772b4ed282SShri Abhyankar      minimization problem:
20782b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
20792b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
20802b4ed282SShri Abhyankar    */
20812b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
20822b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
20832b4ed282SShri Abhyankar   PetscScalar    cinitslope;
20842b4ed282SShri Abhyankar #endif
20852b4ed282SShri Abhyankar   PetscErrorCode ierr;
20862b4ed282SShri Abhyankar   PetscInt       count;
20872b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2088ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
20892b4ed282SShri Abhyankar 
20902b4ed282SShri Abhyankar   PetscFunctionBegin;
20912b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
20922b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
20932b4ed282SShri Abhyankar 
20942b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
20952b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2096c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2097c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
20982b4ed282SShri Abhyankar     }
20992b4ed282SShri Abhyankar     *gnorm = fnorm;
21002b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
21012b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
21022b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
21032b4ed282SShri Abhyankar     goto theend2;
21042b4ed282SShri Abhyankar   }
21052b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
21062b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
21072b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
21082b4ed282SShri Abhyankar   }
21092b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
21102b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
21117fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
21122b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21137fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
21142b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
21152b4ed282SShri Abhyankar #else
21167fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
21172b4ed282SShri Abhyankar #endif
21182b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
21192b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
21202b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
21212b4ed282SShri Abhyankar 
21222b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21237fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21242b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
21252b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
21262b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
21272b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21282b4ed282SShri Abhyankar     goto theend2;
21292b4ed282SShri Abhyankar   }
21302b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21312f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
21327fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21337fe79bc4SShri Abhyankar   } else {
21347fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21357fe79bc4SShri Abhyankar   }
21362b4ed282SShri Abhyankar   if (snes->domainerror) {
21372b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21382b4ed282SShri Abhyankar     PetscFunctionReturn(0);
21392b4ed282SShri Abhyankar   }
214062cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21412b4ed282SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
2142c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2143c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
21442b4ed282SShri Abhyankar     }
21452b4ed282SShri Abhyankar     goto theend2;
21462b4ed282SShri Abhyankar   }
21472b4ed282SShri Abhyankar 
21482b4ed282SShri Abhyankar   /* Fit points with quadratic */
21492b4ed282SShri Abhyankar   lambda = 1.0;
21502b4ed282SShri Abhyankar   count = 1;
21512b4ed282SShri Abhyankar   while (PETSC_TRUE) {
21522b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2153c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2154c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2155c92abb8aSShri 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);
21562b4ed282SShri Abhyankar       }
21572b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
21582b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21592b4ed282SShri Abhyankar       break;
21602b4ed282SShri Abhyankar     }
21612b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
21622b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
21632b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
21642b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
21652b4ed282SShri Abhyankar 
21662b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
21677fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21682b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
21692b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
21702b4ed282SShri 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);
21712b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21722b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21732b4ed282SShri Abhyankar       break;
21742b4ed282SShri Abhyankar     }
21752b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21762b4ed282SShri Abhyankar     if (snes->domainerror) {
21772b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21782b4ed282SShri Abhyankar       PetscFunctionReturn(0);
21792b4ed282SShri Abhyankar     }
21802f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
21817fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21827fe79bc4SShri Abhyankar     } else {
21832b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21847fe79bc4SShri Abhyankar     }
218562cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21862b4ed282SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2187c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2188c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
21892b4ed282SShri Abhyankar       }
21902b4ed282SShri Abhyankar       break;
21912b4ed282SShri Abhyankar     }
21922b4ed282SShri Abhyankar     count++;
21932b4ed282SShri Abhyankar   }
21942b4ed282SShri Abhyankar   theend2:
21952b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
21962b4ed282SShri Abhyankar   if (vi->postcheckstep) {
21972b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
21982b4ed282SShri Abhyankar     if (changed_y) {
21992b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22007fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22012b4ed282SShri Abhyankar     }
22022b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
22032b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
22042b4ed282SShri Abhyankar       if (snes->domainerror) {
22052b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22062b4ed282SShri Abhyankar         PetscFunctionReturn(0);
22072b4ed282SShri Abhyankar       }
22082f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
22097fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22107fe79bc4SShri Abhyankar       } else {
22117fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22127fe79bc4SShri Abhyankar       }
22137fe79bc4SShri Abhyankar 
22142b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
22152b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
221662cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22172b4ed282SShri Abhyankar     }
22182b4ed282SShri Abhyankar   }
22192b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22202b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22212b4ed282SShri Abhyankar }
22222b4ed282SShri Abhyankar 
2223ace3abfcSBarry 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*/
22242b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22252b4ed282SShri Abhyankar EXTERN_C_BEGIN
22262b4ed282SShri Abhyankar #undef __FUNCT__
22272b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
22287087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
22292b4ed282SShri Abhyankar {
22302b4ed282SShri Abhyankar   PetscFunctionBegin;
22312b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
22322b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
22332b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22342b4ed282SShri Abhyankar }
22352b4ed282SShri Abhyankar EXTERN_C_END
22362b4ed282SShri Abhyankar 
22372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22382b4ed282SShri Abhyankar EXTERN_C_BEGIN
22392b4ed282SShri Abhyankar #undef __FUNCT__
22402b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
22417087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
22422b4ed282SShri Abhyankar {
22432b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
22442b4ed282SShri Abhyankar   PetscErrorCode ierr;
22452b4ed282SShri Abhyankar 
22462b4ed282SShri Abhyankar   PetscFunctionBegin;
2247c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2248c92abb8aSShri Abhyankar     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr);
2249c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
22506bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
22512b4ed282SShri Abhyankar   }
22522b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22532b4ed282SShri Abhyankar }
22542b4ed282SShri Abhyankar EXTERN_C_END
22552b4ed282SShri Abhyankar 
22562b4ed282SShri Abhyankar /*
22572b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
22582b4ed282SShri Abhyankar 
22592b4ed282SShri Abhyankar    Input Parameters:
22602b4ed282SShri Abhyankar .  SNES - the SNES context
22612b4ed282SShri Abhyankar .  viewer - visualization context
22622b4ed282SShri Abhyankar 
22632b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
22642b4ed282SShri Abhyankar */
22652b4ed282SShri Abhyankar #undef __FUNCT__
22662b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
22672b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
22682b4ed282SShri Abhyankar {
22692b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
227078c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
22712b4ed282SShri Abhyankar   PetscErrorCode ierr;
2272ace3abfcSBarry Smith   PetscBool     iascii;
22732b4ed282SShri Abhyankar 
22742b4ed282SShri Abhyankar   PetscFunctionBegin;
22752b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
22762b4ed282SShri Abhyankar   if (iascii) {
22772b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
22782b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
22792b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
22802b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
228178c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
22820a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2283b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
228478c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
228578c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
22862b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
22872b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
22882b4ed282SShri Abhyankar   } else {
22892b4ed282SShri Abhyankar     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name);
22902b4ed282SShri Abhyankar   }
22912b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22922b4ed282SShri Abhyankar }
22932b4ed282SShri Abhyankar 
22945559b345SBarry Smith #undef __FUNCT__
22955559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
22965559b345SBarry Smith /*@
22972b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
22982b4ed282SShri Abhyankar 
22992b4ed282SShri Abhyankar    Input Parameters:
23002b4ed282SShri Abhyankar .  snes - the SNES context.
23012b4ed282SShri Abhyankar .  xl   - lower bound.
23022b4ed282SShri Abhyankar .  xu   - upper bound.
23032b4ed282SShri Abhyankar 
23042b4ed282SShri Abhyankar    Notes:
23052b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
230601f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
230784c105d7SBarry Smith 
23085559b345SBarry Smith @*/
230969c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
23102b4ed282SShri Abhyankar {
2311d923200aSJungho Lee   SNES_VI        *vi;
2312d923200aSJungho Lee   PetscErrorCode ierr;
23132b4ed282SShri Abhyankar 
23142b4ed282SShri Abhyankar   PetscFunctionBegin;
23152b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
23162b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
23172b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
23182b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
23192b4ed282SShri 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);
23202b4ed282SShri 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);
2321d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2322d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
23232b4ed282SShri Abhyankar   vi->usersetxbounds = PETSC_TRUE;
23242b4ed282SShri Abhyankar   vi->xl = xl;
23252b4ed282SShri Abhyankar   vi->xu = xu;
23262b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23272b4ed282SShri Abhyankar }
2328693ddf92SShri Abhyankar 
23292b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23302b4ed282SShri Abhyankar /*
23312b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
23322b4ed282SShri Abhyankar 
23332b4ed282SShri Abhyankar    Input Parameter:
23342b4ed282SShri Abhyankar .  snes - the SNES context
23352b4ed282SShri Abhyankar 
23362b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
23372b4ed282SShri Abhyankar */
23382b4ed282SShri Abhyankar #undef __FUNCT__
23392b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
23402b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
23412b4ed282SShri Abhyankar {
23422b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
23437fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2344b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
23452b4ed282SShri Abhyankar   PetscErrorCode ierr;
23462b4ed282SShri Abhyankar   PetscInt       indx;
234769c03620SShri Abhyankar   PetscBool      flg,set,flg2;
23482b4ed282SShri Abhyankar 
23492b4ed282SShri Abhyankar   PetscFunctionBegin;
23502b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
23519308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
23529308c137SBarry Smith   if (flg) {
23539308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
23549308c137SBarry Smith   }
2355be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2356be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2357be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
23582b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2359be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
23602b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
23612f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
236269c03620SShri Abhyankar   if (flg2) {
236369c03620SShri Abhyankar     switch (indx) {
236469c03620SShri Abhyankar     case 0:
236569c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
236669c03620SShri Abhyankar       break;
236769c03620SShri Abhyankar     case 1:
2368d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2369d950fb63SShri Abhyankar       break;
23702f63a38cSShri Abhyankar     case 2:
2371b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
237269c03620SShri Abhyankar     }
237369c03620SShri Abhyankar   }
2374be6adb11SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr);
23752b4ed282SShri Abhyankar   if (flg) {
23762b4ed282SShri Abhyankar     switch (indx) {
23772b4ed282SShri Abhyankar     case 0:
23782b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
23792b4ed282SShri Abhyankar       break;
23802b4ed282SShri Abhyankar     case 1:
23812b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
23822b4ed282SShri Abhyankar       break;
23832b4ed282SShri Abhyankar     case 2:
23842b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
23852b4ed282SShri Abhyankar       break;
23862b4ed282SShri Abhyankar     case 3:
23872b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
23882b4ed282SShri Abhyankar       break;
23892b4ed282SShri Abhyankar     }
2390fe835674SShri Abhyankar   }
23912b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
23922b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23932b4ed282SShri Abhyankar }
23942b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23952b4ed282SShri Abhyankar /*MC
23968b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
23972b4ed282SShri Abhyankar 
23982b4ed282SShri Abhyankar    Options Database:
23998b4c83edSBarry 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
24008b4c83edSBarry Smith                                 additional variables that enforce the constraints
24018b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
24022b4ed282SShri Abhyankar 
24032b4ed282SShri Abhyankar 
24042b4ed282SShri Abhyankar    Level: beginner
24052b4ed282SShri Abhyankar 
24062b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
24072b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
24082b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
24092b4ed282SShri Abhyankar 
24102b4ed282SShri Abhyankar M*/
24112b4ed282SShri Abhyankar EXTERN_C_BEGIN
24122b4ed282SShri Abhyankar #undef __FUNCT__
24132b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
24147087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
24152b4ed282SShri Abhyankar {
24162b4ed282SShri Abhyankar   PetscErrorCode ierr;
24172b4ed282SShri Abhyankar   SNES_VI      *vi;
24182b4ed282SShri Abhyankar 
24192b4ed282SShri Abhyankar   PetscFunctionBegin;
24202b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2421edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
24222b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
24232b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
24242b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
242537596af1SLisandro Dalcin   snes->ops->reset           = 0; /* XXX Implement!!! */
24262b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
24272b4ed282SShri Abhyankar 
24282b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
24292b4ed282SShri Abhyankar   snes->data            = (void*)vi;
24302b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
24312b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
24322b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
24337fe79bc4SShri Abhyankar   vi->LineSearch        = SNESLineSearchNo_VI;
24342b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
24352b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
24362b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
24372b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
24382b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
24392b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
24402f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
24412b4ed282SShri Abhyankar 
24422b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
24432b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
24442b4ed282SShri Abhyankar 
24452b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24462b4ed282SShri Abhyankar }
24472b4ed282SShri Abhyankar EXTERN_C_END
2448