xref: /petsc/src/snes/impls/vi/vi.c (revision 00ac8be1419b46f104fcdb8335f77affb930ddf0)
12b4ed282SShri Abhyankar 
2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/
3c6db04a5SJed Brown #include <../include/private/kspimpl.h>
4c6db04a5SJed Brown #include <../include/private/matimpl.h>
5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h>
6d0af7cd3SBarry Smith 
7d0af7cd3SBarry Smith #undef __FUNCT__
82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds"
92176524cSBarry Smith /*@C
102176524cSBarry Smith    SNESVISetComputeVariableBounds - Sets a function  that is called to compute the variable bounds
112176524cSBarry Smith 
122176524cSBarry Smith    Input parameter
132176524cSBarry Smith +  snes - the SNES context
142176524cSBarry Smith -  compute - computes the bounds
152176524cSBarry Smith 
162176524cSBarry Smith 
17aab9d709SJed Brown @*/
182176524cSBarry Smith PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec*,Vec*))
192176524cSBarry Smith {
202176524cSBarry Smith   PetscErrorCode   ierr;
212176524cSBarry Smith   SNES_VI          *vi;
222176524cSBarry Smith 
232176524cSBarry Smith   PetscFunctionBegin;
242176524cSBarry Smith   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
252176524cSBarry Smith   vi = (SNES_VI*)snes->data;
262176524cSBarry Smith   vi->computevariablebounds = compute;
272176524cSBarry Smith   PetscFunctionReturn(0);
282176524cSBarry Smith }
292176524cSBarry Smith 
302176524cSBarry Smith 
312176524cSBarry Smith #undef __FUNCT__
32d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS"
33d0af7cd3SBarry Smith /*
34d0af7cd3SBarry Smith    SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables
35d0af7cd3SBarry Smith 
36d0af7cd3SBarry Smith    Input parameter
37d0af7cd3SBarry Smith .  snes - the SNES context
38d0af7cd3SBarry Smith .  X    - the snes solution vector
39d0af7cd3SBarry Smith 
40d0af7cd3SBarry Smith    Output parameter
41d0af7cd3SBarry Smith .  ISact - active set index set
42d0af7cd3SBarry Smith 
43d0af7cd3SBarry Smith  */
44d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
45d0af7cd3SBarry Smith {
46d0af7cd3SBarry Smith   PetscErrorCode   ierr;
47d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
48d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
49d0af7cd3SBarry Smith 
50d0af7cd3SBarry Smith   PetscFunctionBegin;
51d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
52d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
53d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
54d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
55d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
56d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
57d0af7cd3SBarry Smith   /* Compute inactive set size */
58d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
59d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
60d0af7cd3SBarry Smith   }
61d0af7cd3SBarry Smith 
62d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
63d0af7cd3SBarry Smith 
64d0af7cd3SBarry Smith   /* Set inactive set indices */
65d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
66d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
67d0af7cd3SBarry Smith   }
68d0af7cd3SBarry Smith 
69d0af7cd3SBarry Smith    /* Create inactive set IS */
70d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
71d0af7cd3SBarry Smith 
72d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
73d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
74d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
75d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
76d0af7cd3SBarry Smith   PetscFunctionReturn(0);
77d0af7cd3SBarry Smith }
78d0af7cd3SBarry Smith 
793c0c59f3SBarry Smith /*
803c0c59f3SBarry Smith     Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors
813c0c59f3SBarry Smith   defined by the reduced space method.
823c0c59f3SBarry Smith 
833c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
843c0c59f3SBarry Smith 
853c0c59f3SBarry Smith */
863c0c59f3SBarry Smith typedef struct {
873c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
883c0c59f3SBarry Smith   IS             inactive;
893c0c59f3SBarry Smith   Vec            upper,lower,values,F;                    /* upper and lower bounds of all variables on this level, the values and the function values */
903c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
913c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
923c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
934c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
943c0c59f3SBarry Smith } DM_SNESVI;
953c0c59f3SBarry Smith 
96d0af7cd3SBarry Smith #undef __FUNCT__
974dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
984dcab191SBarry Smith /*
994dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
1004dcab191SBarry Smith 
1014dcab191SBarry Smith */
1024dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
1034dcab191SBarry Smith {
1044dcab191SBarry Smith   PetscErrorCode          ierr;
1054dcab191SBarry Smith   PetscContainer          isnes;
1063c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
1074dcab191SBarry Smith 
1084dcab191SBarry Smith   PetscFunctionBegin;
1094dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1104dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
1114dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
1124dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
1134dcab191SBarry Smith   PetscFunctionReturn(0);
1144dcab191SBarry Smith }
1154dcab191SBarry Smith 
1164dcab191SBarry Smith #undef __FUNCT__
117d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
118d0af7cd3SBarry Smith /*
119d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
120d0af7cd3SBarry Smith 
121d0af7cd3SBarry Smith */
122d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
123d0af7cd3SBarry Smith {
124d0af7cd3SBarry Smith   PetscErrorCode          ierr;
125d0af7cd3SBarry Smith   PetscContainer          isnes;
1263c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
127d0af7cd3SBarry Smith   Mat                     interp;
128d0af7cd3SBarry Smith 
129d0af7cd3SBarry Smith   PetscFunctionBegin;
130d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1314c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
132d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
133d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1344c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
135d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
136d0af7cd3SBarry Smith 
137d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1384dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
139d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
140*00ac8be1SBarry Smith   *vec = 0;
141d0af7cd3SBarry Smith   PetscFunctionReturn(0);
142d0af7cd3SBarry Smith }
143d0af7cd3SBarry Smith 
144d0af7cd3SBarry Smith extern PetscErrorCode  DMSetVI(DM,Vec,Vec,Vec,Vec,IS);
145d0af7cd3SBarry Smith 
146d0af7cd3SBarry Smith #undef __FUNCT__
147d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
148d0af7cd3SBarry Smith /*
149d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
150d0af7cd3SBarry Smith 
151d0af7cd3SBarry Smith */
152d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
153d0af7cd3SBarry Smith {
154d0af7cd3SBarry Smith   PetscErrorCode          ierr;
155d0af7cd3SBarry Smith   PetscContainer          isnes;
1563c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
157d0af7cd3SBarry Smith   Vec                     upper,lower,values,F;
158d0af7cd3SBarry Smith   IS                      inactive;
159d0af7cd3SBarry Smith   VecScatter              inject;
160d0af7cd3SBarry Smith 
161d0af7cd3SBarry Smith   PetscFunctionBegin;
162d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1634c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
164d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
165d0af7cd3SBarry Smith 
166298cc208SBarry Smith   /* get the original coarsen */
167d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
168298cc208SBarry Smith 
1693c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1703c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1713c0c59f3SBarry Smith 
172298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
173298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
174298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
175d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
176d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr);
177d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
178d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
179d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr);
180d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
181d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
182d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr);
183d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
184d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
185d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr);
186d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
187d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
188d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
189298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
190298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
191d0af7cd3SBarry Smith   ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr);
192d0af7cd3SBarry Smith   ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr);
1933c0c59f3SBarry Smith   ierr = VecDestroy(&upper);CHKERRQ(ierr);
1943c0c59f3SBarry Smith   ierr = VecDestroy(&lower);CHKERRQ(ierr);
1953c0c59f3SBarry Smith   ierr = VecDestroy(&values);CHKERRQ(ierr);
1963c0c59f3SBarry Smith   ierr = VecDestroy(&F);CHKERRQ(ierr);
1973c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
198d0af7cd3SBarry Smith   PetscFunctionReturn(0);
199d0af7cd3SBarry Smith }
200d0af7cd3SBarry Smith 
201d0af7cd3SBarry Smith #undef __FUNCT__
2023c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2033c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
204d0af7cd3SBarry Smith {
205d0af7cd3SBarry Smith   PetscErrorCode ierr;
206d0af7cd3SBarry Smith 
207d0af7cd3SBarry Smith   PetscFunctionBegin;
2084c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2094c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2104c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2114c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
212*00ac8be1SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
213*00ac8be1SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
214*00ac8be1SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
2154c661befSBarry Smith 
216d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
217d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
218d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
219d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
220d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
221d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
222d0af7cd3SBarry Smith   PetscFunctionReturn(0);
223d0af7cd3SBarry Smith }
224d0af7cd3SBarry Smith 
225d0af7cd3SBarry Smith #undef __FUNCT__
226d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
227d0af7cd3SBarry Smith /*
228d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
229d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
230d0af7cd3SBarry Smith 
231d0af7cd3SBarry Smith */
232d0af7cd3SBarry Smith PetscErrorCode  DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive)
233d0af7cd3SBarry Smith {
234d0af7cd3SBarry Smith   PetscErrorCode          ierr;
235d0af7cd3SBarry Smith   PetscContainer          isnes;
2363c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
237d0af7cd3SBarry Smith 
238d0af7cd3SBarry Smith   PetscFunctionBegin;
2394dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
2401c0a9e84SBarry Smith 
241d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr);
242d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr);
243d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr);
244d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
245d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
246d0af7cd3SBarry Smith 
247d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
248d0af7cd3SBarry Smith   if (!isnes) {
249d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2503c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2513c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
252d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
253d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2543c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
255d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
256d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
257d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
258d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
259298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2604dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
2616ba4bc90SBarry Smith     /* since these vectors may reference the DM, need to remove circle referencing */
2626ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)upper,"DM");CHKERRQ(ierr);
2636ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)lower,"DM");CHKERRQ(ierr);
2646ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)values,"DM");CHKERRQ(ierr);
2656ba4bc90SBarry Smith     ierr = PetscObjectRemoveReference((PetscObject)F,"DM");CHKERRQ(ierr);
266d0af7cd3SBarry Smith   } else {
267d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
268d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
269d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
270d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
271d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
272d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
273d0af7cd3SBarry Smith   }
2744dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2754dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
276d0af7cd3SBarry Smith   dmsnesvi->upper    = upper;
277d0af7cd3SBarry Smith   dmsnesvi->lower    = lower;
278d0af7cd3SBarry Smith   dmsnesvi->values   = values;
279d0af7cd3SBarry Smith   dmsnesvi->F        = F;
280d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2811a223a97SBarry Smith   dmsnesvi->dm       = dm;
282d0af7cd3SBarry Smith   PetscFunctionReturn(0);
283d0af7cd3SBarry Smith }
284d0af7cd3SBarry Smith 
2854c661befSBarry Smith #undef __FUNCT__
2864c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2874c661befSBarry Smith /*
2884c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2894c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2904c661befSBarry Smith */
2914c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2924c661befSBarry Smith {
2934c661befSBarry Smith   PetscErrorCode          ierr;
2944c661befSBarry Smith 
2954c661befSBarry Smith   PetscFunctionBegin;
2964c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
2974c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
2984c661befSBarry Smith   PetscFunctionReturn(0);
2994c661befSBarry Smith }
3004c661befSBarry Smith 
3013c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
3022b4ed282SShri Abhyankar 
3039308c137SBarry Smith #undef __FUNCT__
3049308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3057087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3069308c137SBarry Smith {
3079308c137SBarry Smith   PetscErrorCode          ierr;
3089308c137SBarry Smith   SNES_VI                 *vi = (SNES_VI*)snes->data;
3099308c137SBarry Smith   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
3109308c137SBarry Smith   const PetscScalar       *x,*xl,*xu,*f;
31109573ac7SBarry Smith   PetscInt                i,n,act = 0;
3129308c137SBarry Smith   PetscReal               rnorm,fnorm;
3139308c137SBarry Smith 
3149308c137SBarry Smith   PetscFunctionBegin;
3159308c137SBarry Smith   if (!dummy) {
3169308c137SBarry Smith     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
3179308c137SBarry Smith   }
3189308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3199308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3209308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3219308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3223f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3239308c137SBarry Smith 
3249308c137SBarry Smith   rnorm = 0.0;
3259308c137SBarry Smith   for (i=0; i<n; i++) {
32610f5ae6bSBarry 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]);
32709573ac7SBarry Smith     else act++;
3289308c137SBarry Smith   }
3293f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3309308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3319308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3329308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
333d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3349308c137SBarry Smith   fnorm = sqrt(fnorm);
33509573ac7SBarry Smith   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
3369308c137SBarry Smith   if (!dummy) {
3376bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr);
3389308c137SBarry Smith   }
3399308c137SBarry Smith   PetscFunctionReturn(0);
3409308c137SBarry Smith }
3419308c137SBarry Smith 
3422b4ed282SShri Abhyankar /*
3432b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3442b4ed282SShri 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
3452b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3462b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3472b4ed282SShri Abhyankar */
3482b4ed282SShri Abhyankar #undef __FUNCT__
3492b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
350ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3512b4ed282SShri Abhyankar {
3522b4ed282SShri Abhyankar   PetscReal      a1;
3532b4ed282SShri Abhyankar   PetscErrorCode ierr;
354ace3abfcSBarry Smith   PetscBool     hastranspose;
3552b4ed282SShri Abhyankar 
3562b4ed282SShri Abhyankar   PetscFunctionBegin;
3572b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3582b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3592b4ed282SShri Abhyankar   if (hastranspose) {
3602b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3612b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3622b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3632b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3642b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3652b4ed282SShri Abhyankar   } else {
3662b4ed282SShri Abhyankar     Vec         work;
3672b4ed282SShri Abhyankar     PetscScalar result;
3682b4ed282SShri Abhyankar     PetscReal   wnorm;
3692b4ed282SShri Abhyankar 
3702b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3712b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3722b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3732b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3742b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3756bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3762b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3772b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3782b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3792b4ed282SShri Abhyankar   }
3802b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3812b4ed282SShri Abhyankar }
3822b4ed282SShri Abhyankar 
3832b4ed282SShri Abhyankar /*
3842b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3852b4ed282SShri Abhyankar */
3862b4ed282SShri Abhyankar #undef __FUNCT__
3872b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3882b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3892b4ed282SShri Abhyankar {
3902b4ed282SShri Abhyankar   PetscReal      a1,a2;
3912b4ed282SShri Abhyankar   PetscErrorCode ierr;
392ace3abfcSBarry Smith   PetscBool     hastranspose;
3932b4ed282SShri Abhyankar 
3942b4ed282SShri Abhyankar   PetscFunctionBegin;
3952b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3962b4ed282SShri Abhyankar   if (hastranspose) {
3972b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3982b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3992b4ed282SShri Abhyankar 
4002b4ed282SShri Abhyankar     /* Compute || J^T W|| */
4012b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
4022b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
4032b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
4042b4ed282SShri Abhyankar     if (a1 != 0.0) {
4052b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
4062b4ed282SShri Abhyankar     }
4072b4ed282SShri Abhyankar   }
4082b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4092b4ed282SShri Abhyankar }
4102b4ed282SShri Abhyankar 
4112b4ed282SShri Abhyankar /*
4122b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4132b4ed282SShri Abhyankar 
4142b4ed282SShri Abhyankar   Notes:
4152b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4162b4ed282SShri Abhyankar   merit < abstol
4172b4ed282SShri Abhyankar   merit < rtol*merit_initial
4182b4ed282SShri Abhyankar */
4192b4ed282SShri Abhyankar #undef __FUNCT__
4202b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4217fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4222b4ed282SShri Abhyankar {
4232b4ed282SShri Abhyankar   PetscErrorCode ierr;
4242b4ed282SShri Abhyankar 
4252b4ed282SShri Abhyankar   PetscFunctionBegin;
4262b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4272b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4282b4ed282SShri Abhyankar 
4292b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4302b4ed282SShri Abhyankar 
4312b4ed282SShri Abhyankar   if (!it) {
4322b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4337fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4342b4ed282SShri Abhyankar   }
4357fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4362b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4372b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4387fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4397fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4402b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4412b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4422b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4432b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4442b4ed282SShri Abhyankar   }
4452b4ed282SShri Abhyankar 
4462b4ed282SShri Abhyankar   if (it && !*reason) {
4477fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4487fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4492b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4502b4ed282SShri Abhyankar     }
4512b4ed282SShri Abhyankar   }
4522b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4532b4ed282SShri Abhyankar }
4542b4ed282SShri Abhyankar 
4552b4ed282SShri Abhyankar /*
4562b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4572b4ed282SShri Abhyankar 
4582b4ed282SShri Abhyankar   Input Parameter:
4592b4ed282SShri Abhyankar . phi - the semismooth function
4602b4ed282SShri Abhyankar 
4612b4ed282SShri Abhyankar   Output Parameter:
4622b4ed282SShri Abhyankar . merit - the merit function
4632b4ed282SShri Abhyankar . phinorm - ||phi||
4642b4ed282SShri Abhyankar 
4652b4ed282SShri Abhyankar   Notes:
4662b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4672b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4682b4ed282SShri Abhyankar */
4692b4ed282SShri Abhyankar #undef __FUNCT__
4702b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4712b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4722b4ed282SShri Abhyankar {
4732b4ed282SShri Abhyankar   PetscErrorCode ierr;
4742b4ed282SShri Abhyankar 
4752b4ed282SShri Abhyankar   PetscFunctionBegin;
4765f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4775f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4782b4ed282SShri Abhyankar 
4792b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4802b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4812b4ed282SShri Abhyankar }
4822b4ed282SShri Abhyankar 
4837f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4844c21c6cdSBarry Smith {
4854c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4864c21c6cdSBarry Smith }
4874c21c6cdSBarry Smith 
4887f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4894c21c6cdSBarry Smith {
4905559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4915559b345SBarry Smith   else return .5;
4924c21c6cdSBarry Smith }
4934c21c6cdSBarry Smith 
4942b4ed282SShri Abhyankar /*
4951f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4962b4ed282SShri Abhyankar 
4972b4ed282SShri Abhyankar    Input Parameters:
4982b4ed282SShri Abhyankar .  snes - the SNES context
4992b4ed282SShri Abhyankar .  x - current iterate
5002b4ed282SShri Abhyankar .  functx - user defined function context
5012b4ed282SShri Abhyankar 
5022b4ed282SShri Abhyankar    Output Parameters:
5032b4ed282SShri Abhyankar .  phi - Semismooth function
5042b4ed282SShri Abhyankar 
5052b4ed282SShri Abhyankar */
5062b4ed282SShri Abhyankar #undef __FUNCT__
5071f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5081f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5092b4ed282SShri Abhyankar {
5102b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5112b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5122b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5134c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5142b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5152b4ed282SShri Abhyankar 
5162b4ed282SShri Abhyankar   PetscFunctionBegin;
5172b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5182b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5192b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5202b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5212b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5222b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5232b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5242b4ed282SShri Abhyankar 
5252b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
52610f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5274c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
52810f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5294c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
53010f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5314c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5325559b345SBarry Smith     } else if (l[i] == u[i]) {
5332b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5345559b345SBarry Smith     } else {                                                /* both bounds on variable */
5354c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5362b4ed282SShri Abhyankar     }
5372b4ed282SShri Abhyankar   }
5382b4ed282SShri Abhyankar 
5392b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5402b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5412b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5422b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5432b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5442b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5452b4ed282SShri Abhyankar }
5462b4ed282SShri Abhyankar 
5472b4ed282SShri Abhyankar /*
548a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
549a79edbefSShri Abhyankar                                           the semismooth jacobian.
5502b4ed282SShri Abhyankar */
5512b4ed282SShri Abhyankar #undef __FUNCT__
552a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
553a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5542b4ed282SShri Abhyankar {
5552b4ed282SShri Abhyankar   PetscErrorCode ierr;
5562b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5574c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5582b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5592b4ed282SShri Abhyankar 
5602b4ed282SShri Abhyankar   PetscFunctionBegin;
5612b4ed282SShri Abhyankar 
5622b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5632b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5642b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5652b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
566a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
567a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5682b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5694c21c6cdSBarry Smith 
5702b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
57110f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5724c21c6cdSBarry Smith       da[i] = 0;
5732b4ed282SShri Abhyankar       db[i] = 1;
57410f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5754c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5764c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
57710f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5785559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5795559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5805559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5814c21c6cdSBarry Smith       da[i] = 1;
5822b4ed282SShri Abhyankar       db[i] = 0;
5835559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5844c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5854c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5864c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5874c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5884c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5894c21c6cdSBarry Smith       db[i] = db1*db2;
5902b4ed282SShri Abhyankar     }
5912b4ed282SShri Abhyankar   }
5925559b345SBarry Smith 
5932b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5942b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5952b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5962b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
597a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
598a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
599a79edbefSShri Abhyankar   PetscFunctionReturn(0);
600a79edbefSShri Abhyankar }
601a79edbefSShri Abhyankar 
602a79edbefSShri Abhyankar /*
603a79edbefSShri 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.
604a79edbefSShri Abhyankar 
605a79edbefSShri Abhyankar    Input Parameters:
606a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
607a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
608a79edbefSShri Abhyankar 
609a79edbefSShri Abhyankar    Output Parameters:
610a79edbefSShri Abhyankar .  jac      - semismooth jacobian
611a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
612a79edbefSShri Abhyankar 
613a79edbefSShri Abhyankar    Notes:
614a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
615a79edbefSShri Abhyankar    jac = Da + Db*jacfun
616a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
617a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
618a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
619a79edbefSShri Abhyankar */
620a79edbefSShri Abhyankar #undef __FUNCT__
621a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
622a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
623a79edbefSShri Abhyankar {
624a79edbefSShri Abhyankar   PetscErrorCode ierr;
625a79edbefSShri Abhyankar 
6262b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
627a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
628a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
629a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
630a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
631a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6322b4ed282SShri Abhyankar   }
6332b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6342b4ed282SShri Abhyankar }
6352b4ed282SShri Abhyankar 
6362b4ed282SShri Abhyankar /*
637ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
638ee657d29SShri Abhyankar 
639ee657d29SShri Abhyankar    Input Parameters:
640ee657d29SShri Abhyankar    phi - semismooth function.
641ee657d29SShri Abhyankar    H   - semismooth jacobian
642ee657d29SShri Abhyankar 
643ee657d29SShri Abhyankar    Output Parameters:
644ee657d29SShri Abhyankar    dpsi - merit function gradient
645ee657d29SShri Abhyankar 
646ee657d29SShri Abhyankar    Notes:
647ee657d29SShri Abhyankar   The merit function gradient is computed as follows
648ee657d29SShri Abhyankar         dpsi = H^T*phi
649ee657d29SShri Abhyankar */
650ee657d29SShri Abhyankar #undef __FUNCT__
651ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
652ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
653ee657d29SShri Abhyankar {
654ee657d29SShri Abhyankar   PetscErrorCode ierr;
655ee657d29SShri Abhyankar 
656ee657d29SShri Abhyankar   PetscFunctionBegin;
6575f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
658ee657d29SShri Abhyankar   PetscFunctionReturn(0);
659ee657d29SShri Abhyankar }
660ee657d29SShri Abhyankar 
661c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
662c1a5e521SShri Abhyankar /*
663c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
664c1a5e521SShri Abhyankar 
665c1a5e521SShri Abhyankar    Input Parameters:
666c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
667c1a5e521SShri Abhyankar 
668c1a5e521SShri Abhyankar    Output Parameters:
669c1a5e521SShri Abhyankar .  X - Bound projected X
670c1a5e521SShri Abhyankar 
671c1a5e521SShri Abhyankar */
672c1a5e521SShri Abhyankar 
673c1a5e521SShri Abhyankar #undef __FUNCT__
674c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
675c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
676c1a5e521SShri Abhyankar {
677c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
678c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
679c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
680c1a5e521SShri Abhyankar   PetscScalar       *x;
681c1a5e521SShri Abhyankar   PetscInt          i,n;
682c1a5e521SShri Abhyankar 
683c1a5e521SShri Abhyankar   PetscFunctionBegin;
684c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
685c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
686c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
687c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
688c1a5e521SShri Abhyankar 
689c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
69010f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
69110f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
692c1a5e521SShri Abhyankar   }
693c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
694c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
695c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
696c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
697c1a5e521SShri Abhyankar }
698c1a5e521SShri Abhyankar 
6992b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
7002b4ed282SShri Abhyankar 
7012b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
7022b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
7032b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
7042b4ed282SShri Abhyankar      respectively.
7052b4ed282SShri Abhyankar 
7062b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7072b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7082b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7092b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7102b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7112b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7122b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7132b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7142b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7152b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7162b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7172b4ed282SShri Abhyankar      for all nonlinear solvers.
7182b4ed282SShri Abhyankar 
7192b4ed282SShri Abhyankar      Another key routine is:
7202b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7212b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7222b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7232b4ed282SShri Abhyankar      SNESSolve() if necessary.
7242b4ed282SShri Abhyankar 
7252b4ed282SShri Abhyankar      Additional basic routines are:
7262b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7272b4ed282SShri Abhyankar                                       have actually been used.
7282b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7292b4ed282SShri Abhyankar      SNESView().
7302b4ed282SShri Abhyankar 
7312b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7322b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7332b4ed282SShri Abhyankar      above description applies to these categories also.
7342b4ed282SShri Abhyankar 
7352b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7362b4ed282SShri Abhyankar /*
73769c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7382b4ed282SShri Abhyankar    method using a line search.
7392b4ed282SShri Abhyankar 
7402b4ed282SShri Abhyankar    Input Parameters:
7412b4ed282SShri Abhyankar .  snes - the SNES context
7422b4ed282SShri Abhyankar 
7432b4ed282SShri Abhyankar    Output Parameter:
7442b4ed282SShri Abhyankar .  outits - number of iterations until termination
7452b4ed282SShri Abhyankar 
7462b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7472b4ed282SShri Abhyankar 
7482b4ed282SShri Abhyankar    Notes:
7492b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
75051defd01SShri Abhyankar    line search. The default line search does not do any line seach
75151defd01SShri Abhyankar    but rather takes a full newton step.
7522b4ed282SShri Abhyankar */
7532b4ed282SShri Abhyankar #undef __FUNCT__
75469c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
75569c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7562b4ed282SShri Abhyankar {
7572b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7582b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7592b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7603b336b49SShri Abhyankar   PetscBool          lssucceed;
7612b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7622b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7632b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7642b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7652b4ed282SShri Abhyankar 
7662b4ed282SShri Abhyankar   PetscFunctionBegin;
7679ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7689ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7699ce7406fSBarry Smith 
7702b4ed282SShri Abhyankar   snes->numFailures            = 0;
7712b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7722b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7732b4ed282SShri Abhyankar 
7742b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7752b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7762b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7772b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7782b4ed282SShri Abhyankar   G		= snes->work[1];
7792b4ed282SShri Abhyankar   W		= snes->work[2];
7802b4ed282SShri Abhyankar 
7812b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7822b4ed282SShri Abhyankar   snes->iter = 0;
7832b4ed282SShri Abhyankar   snes->norm = 0.0;
7842b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7852b4ed282SShri Abhyankar 
7867fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7872b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7882b4ed282SShri Abhyankar   if (snes->domainerror) {
7892b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7909ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7912b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7922b4ed282SShri Abhyankar   }
7932b4ed282SShri Abhyankar    /* Compute Merit function */
7942b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7952b4ed282SShri Abhyankar 
7962b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7972b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
79862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7992b4ed282SShri Abhyankar 
8002b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
8022b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8032b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
8047a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8052b4ed282SShri Abhyankar 
8062b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8072b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8082b4ed282SShri Abhyankar   /* test convergence */
8092b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8109ce7406fSBarry Smith   if (snes->reason) {
8119ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8129ce7406fSBarry Smith     PetscFunctionReturn(0);
8139ce7406fSBarry Smith   }
8142b4ed282SShri Abhyankar 
8152b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8162b4ed282SShri Abhyankar 
8172b4ed282SShri Abhyankar     /* Call general purpose update function */
8182b4ed282SShri Abhyankar     if (snes->ops->update) {
8192b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8202b4ed282SShri Abhyankar     }
8212b4ed282SShri Abhyankar 
8222b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
823a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8242b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
825a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
826a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
827a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
828a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
829ee657d29SShri Abhyankar     /* Compute the merit function gradient */
830ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8312b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8322b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8332b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8343b336b49SShri Abhyankar 
8353b336b49SShri Abhyankar     if (kspreason < 0) {
8362b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8372b4ed282SShri 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);
8382b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8392b4ed282SShri Abhyankar         break;
8402b4ed282SShri Abhyankar       }
8412b4ed282SShri Abhyankar     }
8422b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8432b4ed282SShri Abhyankar     snes->linear_its += lits;
8442b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8452b4ed282SShri Abhyankar     /*
8462b4ed282SShri Abhyankar     if (vi->precheckstep) {
847ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8482b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8492b4ed282SShri Abhyankar     }
8502b4ed282SShri Abhyankar 
8512b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8522b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8532b4ed282SShri Abhyankar     }
8542b4ed282SShri Abhyankar     */
8552b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8562b4ed282SShri Abhyankar          Y <- X - lambda*Y
8572b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8582b4ed282SShri Abhyankar     */
8592b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8602b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8612b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8622b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8632b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8642b4ed282SShri Abhyankar     if (snes->domainerror) {
8652b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8669ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8672b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8682b4ed282SShri Abhyankar     }
8692b4ed282SShri Abhyankar     if (!lssucceed) {
8702b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
871ace3abfcSBarry Smith 	PetscBool ismin;
8722b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8732b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8742b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8752b4ed282SShri Abhyankar         break;
8762b4ed282SShri Abhyankar       }
8772b4ed282SShri Abhyankar     }
8782b4ed282SShri Abhyankar     /* Update function and solution vectors */
8792b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8802b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8812b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8822b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8832b4ed282SShri Abhyankar     /* Monitor convergence */
8842b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8852b4ed282SShri Abhyankar     snes->iter = i+1;
8862b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8872b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8882b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8897a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8902b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8912b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8922b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8932b4ed282SShri Abhyankar     if (snes->reason) break;
8942b4ed282SShri Abhyankar   }
8952b4ed282SShri Abhyankar   if (i == maxits) {
8962b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8972b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8982b4ed282SShri Abhyankar   }
8999ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
9002b4ed282SShri Abhyankar   PetscFunctionReturn(0);
9012b4ed282SShri Abhyankar }
90269c03620SShri Abhyankar 
90369c03620SShri Abhyankar #undef __FUNCT__
904693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
905693ddf92SShri Abhyankar /*
906693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
907693ddf92SShri Abhyankar 
908693ddf92SShri Abhyankar    Input parameter
909693ddf92SShri Abhyankar .  snes - the SNES context
910693ddf92SShri Abhyankar .  X    - the snes solution vector
911693ddf92SShri Abhyankar .  F    - the nonlinear function vector
912693ddf92SShri Abhyankar 
913693ddf92SShri Abhyankar    Output parameter
914693ddf92SShri Abhyankar .  ISact - active set index set
915693ddf92SShri Abhyankar  */
916693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
917d950fb63SShri Abhyankar {
918d950fb63SShri Abhyankar   PetscErrorCode   ierr;
919693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
920693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
921693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
922693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
923d950fb63SShri Abhyankar 
924d950fb63SShri Abhyankar   PetscFunctionBegin;
925d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
926d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
927fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
928fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
929fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
930fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
931693ddf92SShri Abhyankar   /* Compute active set size */
932d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
93310f5ae6bSBarry 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++;
934d950fb63SShri Abhyankar   }
935693ddf92SShri Abhyankar 
936d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
937d950fb63SShri Abhyankar 
938693ddf92SShri Abhyankar   /* Set active set indices */
939d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
94010f5ae6bSBarry 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;
941d950fb63SShri Abhyankar   }
942d950fb63SShri Abhyankar 
943693ddf92SShri Abhyankar    /* Create active set IS */
94462298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
945d950fb63SShri Abhyankar 
946fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
947fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
948fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
949fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
950d950fb63SShri Abhyankar   PetscFunctionReturn(0);
951d950fb63SShri Abhyankar }
952d950fb63SShri Abhyankar 
953693ddf92SShri Abhyankar #undef __FUNCT__
954693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
955693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
956693ddf92SShri Abhyankar {
957693ddf92SShri Abhyankar   PetscErrorCode     ierr;
958693ddf92SShri Abhyankar 
959693ddf92SShri Abhyankar   PetscFunctionBegin;
960693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
961693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
962693ddf92SShri Abhyankar   PetscFunctionReturn(0);
963693ddf92SShri Abhyankar }
964693ddf92SShri Abhyankar 
965dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
966dbd914b8SShri Abhyankar #undef __FUNCT__
967fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
968fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
969dbd914b8SShri Abhyankar {
970dbd914b8SShri Abhyankar   PetscErrorCode ierr;
971dbd914b8SShri Abhyankar   Vec            v;
972dbd914b8SShri Abhyankar 
973dbd914b8SShri Abhyankar   PetscFunctionBegin;
974dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
975dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
976dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
977dbd914b8SShri Abhyankar   *newv = v;
978dbd914b8SShri Abhyankar 
979dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
980dbd914b8SShri Abhyankar }
981dbd914b8SShri Abhyankar 
982732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
983732bb160SShri Abhyankar #undef __FUNCT__
984732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
985732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
986732bb160SShri Abhyankar {
987732bb160SShri Abhyankar   PetscErrorCode         ierr;
988d0af7cd3SBarry Smith   KSP                    snesksp;
989dbd914b8SShri Abhyankar 
990732bb160SShri Abhyankar   PetscFunctionBegin;
991732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
992d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
993c2efdce3SBarry Smith 
994c2efdce3SBarry Smith   /*
995d0af7cd3SBarry Smith   KSP                    kspnew;
996d0af7cd3SBarry Smith   PC                     pcnew;
997d0af7cd3SBarry Smith   const MatSolverPackage stype;
998d0af7cd3SBarry Smith 
999c2efdce3SBarry Smith 
1000732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
1001732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
1002732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
1003732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
1004732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1005732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1006732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1007732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1008732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1009732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1010732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10116bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1012732bb160SShri Abhyankar   snes->ksp = kspnew;
1013732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1014d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1015732bb160SShri Abhyankar   PetscFunctionReturn(0);
1016732bb160SShri Abhyankar }
101769c03620SShri Abhyankar 
101869c03620SShri Abhyankar 
1019fe835674SShri Abhyankar #undef __FUNCT__
1020fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
102110f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1022fe835674SShri Abhyankar {
1023fe835674SShri Abhyankar   PetscErrorCode    ierr;
1024fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1025fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1026fe835674SShri Abhyankar   PetscInt          i,n;
1027fe835674SShri Abhyankar   PetscReal         rnorm;
1028fe835674SShri Abhyankar 
1029fe835674SShri Abhyankar   PetscFunctionBegin;
1030fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1031fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1032fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1033fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1034fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1035fe835674SShri Abhyankar   rnorm = 0.0;
1036fe835674SShri Abhyankar   for (i=0; i<n; i++) {
103710f5ae6bSBarry 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]);
1038fe835674SShri Abhyankar   }
1039fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1040fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1041fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1042fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1043d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1044fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1045fe835674SShri Abhyankar   PetscFunctionReturn(0);
1046fe835674SShri Abhyankar }
1047fe835674SShri Abhyankar 
1048fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1049c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1050c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1051d950fb63SShri Abhyankar #undef __FUNCT__
1052d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1053d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1054d950fb63SShri Abhyankar {
1055d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1056d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1057abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1058d950fb63SShri Abhyankar   PetscBool         lssucceed;
1059d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1060fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1061d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1062d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1063d950fb63SShri Abhyankar 
1064d950fb63SShri Abhyankar   PetscFunctionBegin;
1065d950fb63SShri Abhyankar   snes->numFailures            = 0;
1066d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1067d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1068d950fb63SShri Abhyankar 
1069d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1070d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1071d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1072d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1073d950fb63SShri Abhyankar   G		= snes->work[1];
1074d950fb63SShri Abhyankar   W		= snes->work[2];
1075d950fb63SShri Abhyankar 
1076d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1077d950fb63SShri Abhyankar   snes->iter = 0;
1078d950fb63SShri Abhyankar   snes->norm = 0.0;
1079d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1080d950fb63SShri Abhyankar 
10817fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1082fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1083d950fb63SShri Abhyankar   if (snes->domainerror) {
1084d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1085d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1086d950fb63SShri Abhyankar   }
1087fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1088d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1089d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
109062cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1091d950fb63SShri Abhyankar 
1092d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1093fe835674SShri Abhyankar   snes->norm = fnorm;
1094d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1095fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10967a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1097d950fb63SShri Abhyankar 
1098d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1099fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1100d950fb63SShri Abhyankar   /* test convergence */
1101fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1102d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1103d950fb63SShri Abhyankar 
1104d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1105d950fb63SShri Abhyankar 
1106d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1107d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1108abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1109fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1110d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
111162298a1eSBarry Smith     IS         keptrows;
1112abcba341SShri Abhyankar     PetscBool  isequal;
1113d950fb63SShri Abhyankar 
1114d950fb63SShri Abhyankar     /* Call general purpose update function */
1115d950fb63SShri Abhyankar     if (snes->ops->update) {
1116d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1117d950fb63SShri Abhyankar     }
1118d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
111962298a1eSBarry Smith 
1120d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1121693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1122d950fb63SShri Abhyankar 
11234dcab191SBarry Smith 
1124abcba341SShri Abhyankar     /* Create inactive set submatrix */
112562298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1126b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
112762298a1eSBarry Smith     if (keptrows) {
112862298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
112962298a1eSBarry Smith       const PetscInt *krows,*inact;
113027d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
113162298a1eSBarry Smith 
11326bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11336bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
113462298a1eSBarry Smith 
113562298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
113662298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
113762298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
113862298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
113962298a1eSBarry Smith       for (k=0; k<cnt; k++) {
114027d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
114162298a1eSBarry Smith       }
114262298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
114362298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11446bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11456bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
114662298a1eSBarry Smith 
114727d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
114827d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
114962298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
115062298a1eSBarry Smith     }
11519e516c8fSBarry Smith     ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr);
115262298a1eSBarry Smith 
1153d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1154d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1155d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1156d950fb63SShri Abhyankar 
1157d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1158fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1159fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1160fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1161d950fb63SShri Abhyankar 
1162d950fb63SShri Abhyankar     /* Create scatter contexts */
1163d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1164d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1165d950fb63SShri Abhyankar 
1166d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1167fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1168fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1169d950fb63SShri Abhyankar 
1170d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1171d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1172d950fb63SShri Abhyankar 
1173d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1174d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1175d950fb63SShri Abhyankar 
1176d950fb63SShri Abhyankar     /* Active set direction = 0 */
1177d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1178d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1179d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1180d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1181d950fb63SShri Abhyankar 
1182abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1183abcba341SShri Abhyankar     if (!isequal) {
1184732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1185c58c0d17SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
1186d950fb63SShri Abhyankar     }
1187d950fb63SShri Abhyankar 
118813e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
118913e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
119013e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
119113e0d083SBarry Smith 
1192d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
119313e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
119413e0d083SBarry Smith     {
119513e0d083SBarry Smith       PC        pc;
119613e0d083SBarry Smith       PetscBool flg;
119713e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
119813e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
119913e0d083SBarry Smith       if (flg) {
120013e0d083SBarry Smith         KSP      *subksps;
120113e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
120213e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
120313e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
120413e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
120513e0d083SBarry Smith         if (flg) {
120613e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
120713e0d083SBarry Smith           const PetscInt *ii;
120813e0d083SBarry Smith 
120913e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
121013e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
121113e0d083SBarry Smith           for (j=0; j<n; j++) {
121213e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
121313e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
121413e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
121513e0d083SBarry Smith           }
121613e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
121713e0d083SBarry Smith 
121813e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
121913e0d083SBarry Smith         }
122013e0d083SBarry Smith       }
122113e0d083SBarry Smith     }
122213e0d083SBarry Smith 
1223fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1224d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1225d950fb63SShri Abhyankar     if (kspreason < 0) {
1226d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1227d950fb63SShri 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);
1228d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1229d950fb63SShri Abhyankar         break;
1230d950fb63SShri Abhyankar       }
1231d950fb63SShri Abhyankar      }
1232d950fb63SShri Abhyankar 
1233d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1234d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1235d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1236d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1237d950fb63SShri Abhyankar 
12386bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12396bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
12406bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
12416bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
12426bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
12436bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1244abcba341SShri Abhyankar     if (!isequal) {
12456bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1246abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1247abcba341SShri Abhyankar     }
12486bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
12496bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1250d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
12516bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1252d950fb63SShri Abhyankar     }
1253d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1254d950fb63SShri Abhyankar     snes->linear_its += lits;
1255d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1256d950fb63SShri Abhyankar     /*
1257d950fb63SShri Abhyankar     if (vi->precheckstep) {
1258d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1259d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1260d950fb63SShri Abhyankar     }
1261d950fb63SShri Abhyankar 
1262d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1263d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1264d950fb63SShri Abhyankar     }
1265d950fb63SShri Abhyankar     */
1266d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1267d950fb63SShri Abhyankar          Y <- X - lambda*Y
1268d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1269d950fb63SShri Abhyankar     */
1270d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1271fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1272fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1273fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
12742b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
12752b4ed282SShri Abhyankar     if (snes->domainerror) {
12762b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
12774c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
12782b4ed282SShri Abhyankar       PetscFunctionReturn(0);
12792b4ed282SShri Abhyankar     }
12802b4ed282SShri Abhyankar     if (!lssucceed) {
12812b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
12822b4ed282SShri Abhyankar 	PetscBool ismin;
12832b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
12842b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
12852b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
12862b4ed282SShri Abhyankar         break;
12872b4ed282SShri Abhyankar       }
12882b4ed282SShri Abhyankar     }
12892b4ed282SShri Abhyankar     /* Update function and solution vectors */
1290fe835674SShri Abhyankar     fnorm = gnorm;
1291fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
12922b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
12932b4ed282SShri Abhyankar     /* Monitor convergence */
12942b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
12952b4ed282SShri Abhyankar     snes->iter = i+1;
1296fe835674SShri Abhyankar     snes->norm = fnorm;
12972b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
12982b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
12997a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
13002b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
13012b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1302fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13032b4ed282SShri Abhyankar     if (snes->reason) break;
13042b4ed282SShri Abhyankar   }
13054c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13062b4ed282SShri Abhyankar   if (i == maxits) {
13072b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13082b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13092b4ed282SShri Abhyankar   }
13102b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13112b4ed282SShri Abhyankar }
13122b4ed282SShri Abhyankar 
13132f63a38cSShri Abhyankar #undef __FUNCT__
1314720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1315cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13162f63a38cSShri Abhyankar {
13172f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13182f63a38cSShri Abhyankar 
13192f63a38cSShri Abhyankar   PetscFunctionBegin;
13202f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13212f63a38cSShri Abhyankar   vi->checkredundancy = func;
1322cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13232f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13242f63a38cSShri Abhyankar }
13252f63a38cSShri Abhyankar 
1326ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1327ff596062SShri Abhyankar #include <engine.h>
1328ff596062SShri Abhyankar #include <mex.h>
1329cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1330ff596062SShri Abhyankar 
1331ff596062SShri Abhyankar #undef __FUNCT__
1332ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1333ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1334ff596062SShri Abhyankar {
1335ff596062SShri Abhyankar   PetscErrorCode      ierr;
1336cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1337cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1338cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1339cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1340fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1341ff596062SShri Abhyankar 
1342ff596062SShri Abhyankar   PetscFunctionBegin;
1343ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1344ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1345ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1346ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1347ff596062SShri Abhyankar 
134809db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
134909db5ad8SShri Abhyankar    bet set by the Matlab function */
1350fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1351cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1352ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1353ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1354cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1355ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1356ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1357cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1358cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1359cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1360ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1361ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1362ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1363ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1364ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1365ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1366ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1367ff596062SShri Abhyankar   PetscFunctionReturn(0);
1368ff596062SShri Abhyankar }
1369ff596062SShri Abhyankar 
1370ff596062SShri Abhyankar #undef __FUNCT__
1371ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1372ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1373ff596062SShri Abhyankar {
1374ff596062SShri Abhyankar   PetscErrorCode      ierr;
1375cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1376ff596062SShri Abhyankar 
1377ff596062SShri Abhyankar   PetscFunctionBegin;
1378ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1379cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1380ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1381ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1382cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1383ff596062SShri Abhyankar   PetscFunctionReturn(0);
1384ff596062SShri Abhyankar }
1385ff596062SShri Abhyankar 
1386ff596062SShri Abhyankar #endif
1387ff596062SShri Abhyankar 
1388ff596062SShri Abhyankar 
13892f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
13902f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1391720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
139256a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
139356a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
13942f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
13952f63a38cSShri Abhyankar */
13962f63a38cSShri Abhyankar #undef __FUNCT__
1397b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1398b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
13992f63a38cSShri Abhyankar {
14002f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
14012f63a38cSShri Abhyankar   PetscErrorCode    ierr;
14022f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
14032f63a38cSShri Abhyankar   PetscBool         lssucceed;
14042f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
14052f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14062f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14072f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14082f63a38cSShri Abhyankar 
14092f63a38cSShri Abhyankar   PetscFunctionBegin;
14102f63a38cSShri Abhyankar   snes->numFailures            = 0;
14112f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14122f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14132f63a38cSShri Abhyankar 
14142f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14152f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14162f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14172f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14182f63a38cSShri Abhyankar   G		= snes->work[1];
14192f63a38cSShri Abhyankar   W		= snes->work[2];
14202f63a38cSShri Abhyankar 
14212f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14222f63a38cSShri Abhyankar   snes->iter = 0;
14232f63a38cSShri Abhyankar   snes->norm = 0.0;
14242f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14252f63a38cSShri Abhyankar 
14262f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14272f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14282f63a38cSShri Abhyankar   if (snes->domainerror) {
14292f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14302f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14312f63a38cSShri Abhyankar   }
14322f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14332f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14342f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
143562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14362f63a38cSShri Abhyankar 
14372f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14382f63a38cSShri Abhyankar   snes->norm = fnorm;
14392f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14402f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
14417a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
14422f63a38cSShri Abhyankar 
14432f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
14442f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
14452f63a38cSShri Abhyankar   /* test convergence */
14462f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
14472f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
14482f63a38cSShri Abhyankar 
14492f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
14502f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1451cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
145256a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
145356a221efSShri Abhyankar     Vec            F_aug,Y_aug;
145456a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
145556a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
145656a221efSShri Abhyankar     PetscInt       k;
145763ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
145856a221efSShri Abhyankar     PetscScalar    *f,*f2;
14592f63a38cSShri Abhyankar     PetscBool      isequal;
146056a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
14612f63a38cSShri Abhyankar 
14622f63a38cSShri Abhyankar     /* Call general purpose update function */
14632f63a38cSShri Abhyankar     if (snes->ops->update) {
14642f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
14652f63a38cSShri Abhyankar     }
14662f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
14672f63a38cSShri Abhyankar 
14682f63a38cSShri Abhyankar     /* Create active and inactive index sets */
14692f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
14702f63a38cSShri Abhyankar 
147156a221efSShri Abhyankar     /* Get local active set size */
14722f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
147356a221efSShri Abhyankar     if (nis_act) {
1474e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1475e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
147656a221efSShri Abhyankar       if(vi->checkredundancy) {
1477cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
147856a221efSShri Abhyankar       }
14792f63a38cSShri Abhyankar 
148056a221efSShri Abhyankar       if(!IS_redact) {
148156a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
148256a221efSShri Abhyankar            there were no redundant active set variables */
148356a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
148456a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
148556a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
148656a221efSShri Abhyankar 	nkept = nis_act;
148756a221efSShri Abhyankar       } else {
148856a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
148956a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
14902f63a38cSShri Abhyankar 
149156a221efSShri Abhyankar 	/* Create reduced active set list */
149256a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
149356a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1494cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
149556a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
149656a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
149756a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
149856a221efSShri Abhyankar 	}
149956a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
150056a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1501cb5fe31bSShri Abhyankar 
1502cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
150356a221efSShri Abhyankar       }
15042f63a38cSShri Abhyankar 
150556a221efSShri Abhyankar       /* Create augmented F and Y */
150656a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
150756a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
150856a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
150956a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15102f63a38cSShri Abhyankar 
151156a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
151256a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
151356a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
151456a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
151556a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
151656a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15172f63a38cSShri Abhyankar 
151856a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
151956a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
152056a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
152156a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15222f63a38cSShri Abhyankar 
152356a221efSShri Abhyankar 
15249521db3cSSatish Balay       { /* local vars */
1525493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
152656a221efSShri Abhyankar       PetscInt          ncols;
152756a221efSShri Abhyankar       const PetscInt    *cols;
152856a221efSShri Abhyankar       const PetscScalar *vals;
15292969f145SShri Abhyankar       PetscScalar        value[2];
15302969f145SShri Abhyankar       PetscInt           row,col[2];
1531493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15322969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1533493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1534493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1535493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1536493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1537493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1538493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1539493a4f3dSShri Abhyankar       }
1540493a4f3dSShri Abhyankar 
1541493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1542493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
15432969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1544493a4f3dSShri Abhyankar       }
1545493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1546493a4f3dSShri Abhyankar 
1547493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
154856a221efSShri Abhyankar 
154956a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
155056a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
155156a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
155256a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
155356a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
155456a221efSShri Abhyankar       }
155556a221efSShri Abhyankar       /* Add the augmented part */
155656a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
15572969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
15582969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
15592969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
15602969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
156156a221efSShri Abhyankar       }
156256a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
156356a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
156456a221efSShri Abhyankar       /* Only considering prejac = jac for now */
156556a221efSShri Abhyankar       Jpre_aug = J_aug;
15669521db3cSSatish Balay       } /* local vars*/
1567e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1568e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
156956a221efSShri Abhyankar     } else {
157056a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
157156a221efSShri Abhyankar     }
15722f63a38cSShri Abhyankar 
15732f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
15742f63a38cSShri Abhyankar     if (!isequal) {
157556a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
15762f63a38cSShri Abhyankar     }
157756a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
15782f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
157956a221efSShri Abhyankar     /*  {
15802f63a38cSShri Abhyankar       PC        pc;
15812f63a38cSShri Abhyankar       PetscBool flg;
15822f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
15832f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15842f63a38cSShri Abhyankar       if (flg) {
15852f63a38cSShri Abhyankar         KSP      *subksps;
15862f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
15872f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
15882f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
15892f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
15902f63a38cSShri Abhyankar         if (flg) {
15912f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
15922f63a38cSShri Abhyankar           const PetscInt *ii;
15932f63a38cSShri Abhyankar 
15942f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
15952f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
15962f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
15972f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
15982f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
15992f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
16002f63a38cSShri Abhyankar           }
16012f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
16022f63a38cSShri Abhyankar 
16032f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
16042f63a38cSShri Abhyankar         }
16052f63a38cSShri Abhyankar       }
16062f63a38cSShri Abhyankar     }
160756a221efSShri Abhyankar     */
160856a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16092f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16102f63a38cSShri Abhyankar     if (kspreason < 0) {
16112f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16122f63a38cSShri 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);
16132f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16142f63a38cSShri Abhyankar         break;
16152f63a38cSShri Abhyankar       }
16162f63a38cSShri Abhyankar     }
16172f63a38cSShri Abhyankar 
161856a221efSShri Abhyankar     if(nis_act) {
161956a221efSShri Abhyankar       PetscScalar *y1,*y2;
162056a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
162156a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
162256a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
162356a221efSShri Abhyankar       j1 = 0;
162456a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
162556a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
162656a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
162756a221efSShri Abhyankar       }
162856a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
162956a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16302f63a38cSShri Abhyankar 
16316bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16326bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16336bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
163456a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
163556a221efSShri Abhyankar     }
163656a221efSShri Abhyankar 
16372f63a38cSShri Abhyankar     if (!isequal) {
16386bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16392f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
16402f63a38cSShri Abhyankar     }
16416bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
164256a221efSShri Abhyankar 
16432f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
16442f63a38cSShri Abhyankar     snes->linear_its += lits;
16452f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
16462f63a38cSShri Abhyankar     /*
16472f63a38cSShri Abhyankar     if (vi->precheckstep) {
16482f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
16492f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
16502f63a38cSShri Abhyankar     }
16512f63a38cSShri Abhyankar 
16522f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
16532f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
16542f63a38cSShri Abhyankar     }
16552f63a38cSShri Abhyankar     */
16562f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
16572f63a38cSShri Abhyankar          Y <- X - lambda*Y
16582f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
16592f63a38cSShri Abhyankar     */
16602f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
16612f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
16622f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
16632f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
16642f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
16652f63a38cSShri Abhyankar     if (snes->domainerror) {
16662f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
16672f63a38cSShri Abhyankar       PetscFunctionReturn(0);
16682f63a38cSShri Abhyankar     }
16692f63a38cSShri Abhyankar     if (!lssucceed) {
16702f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
16712f63a38cSShri Abhyankar 	PetscBool ismin;
16722f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
16732f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
16742f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
16752f63a38cSShri Abhyankar         break;
16762f63a38cSShri Abhyankar       }
16772f63a38cSShri Abhyankar     }
16782f63a38cSShri Abhyankar     /* Update function and solution vectors */
16792f63a38cSShri Abhyankar     fnorm = gnorm;
16802f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
16812f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
16822f63a38cSShri Abhyankar     /* Monitor convergence */
16832f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
16842f63a38cSShri Abhyankar     snes->iter = i+1;
16852f63a38cSShri Abhyankar     snes->norm = fnorm;
16862f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
16872f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
16887a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16892f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
16902f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
16912f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
16922f63a38cSShri Abhyankar     if (snes->reason) break;
16932f63a38cSShri Abhyankar   }
16942f63a38cSShri Abhyankar   if (i == maxits) {
16952f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
16962f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
16972f63a38cSShri Abhyankar   }
16982f63a38cSShri Abhyankar   PetscFunctionReturn(0);
16992f63a38cSShri Abhyankar }
17002f63a38cSShri Abhyankar 
17012b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17022b4ed282SShri Abhyankar /*
17032b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
17042b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
17052b4ed282SShri Abhyankar 
17062b4ed282SShri Abhyankar    Input Parameter:
17072b4ed282SShri Abhyankar .  snes - the SNES context
17082b4ed282SShri Abhyankar .  x - the solution vector
17092b4ed282SShri Abhyankar 
17102b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17112b4ed282SShri Abhyankar 
17122b4ed282SShri Abhyankar    Notes:
17132b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17142b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17152b4ed282SShri Abhyankar    the call to SNESSolve().
17162b4ed282SShri Abhyankar  */
17172b4ed282SShri Abhyankar #undef __FUNCT__
17182b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17192b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17202b4ed282SShri Abhyankar {
17212b4ed282SShri Abhyankar   PetscErrorCode ierr;
17222b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17232b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17242b4ed282SShri Abhyankar 
17252b4ed282SShri Abhyankar   PetscFunctionBegin;
172658c9b817SLisandro Dalcin 
172758c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17282b4ed282SShri Abhyankar 
17292176524cSBarry Smith   if (vi->computevariablebounds) {
17302176524cSBarry Smith     ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
17312176524cSBarry Smith     ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
17322176524cSBarry Smith     ierr = (*vi->computevariablebounds)(snes,&vi->xl,&vi->xu);CHKERRQ(ierr);
17332176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
17342176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
17352b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
173601f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17372b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
173801f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17392b4ed282SShri Abhyankar   } else {
17402b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
17412b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
17422b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
17432b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
17442b4ed282SShri 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]))
17452b4ed282SShri 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.");
17462b4ed282SShri Abhyankar   }
17472f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1748abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1749abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1750abcba341SShri Abhyankar     PetscInt *indices;
1751abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1752abcba341SShri Abhyankar 
1753abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1754abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1755abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1756abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1757abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1758abcba341SShri Abhyankar   }
17592b4ed282SShri Abhyankar 
17602f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1761fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1762fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1763fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1764fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1765fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1766fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1767fe835674SShri Abhyankar   }
17682b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17692b4ed282SShri Abhyankar }
17702b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17712176524cSBarry Smith #undef __FUNCT__
17722176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
17732176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
17742176524cSBarry Smith {
17752176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
17762176524cSBarry Smith   PetscErrorCode ierr;
17772176524cSBarry Smith 
17782176524cSBarry Smith   PetscFunctionBegin;
17792176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
17802176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1781d655a5daSBarry Smith   if (snes->ops->solve != SNESSolveVI_SS) {
1782d655a5daSBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1783d655a5daSBarry Smith   }
17842176524cSBarry Smith   PetscFunctionReturn(0);
17852176524cSBarry Smith }
17862176524cSBarry Smith 
17872b4ed282SShri Abhyankar /*
17882b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
17892b4ed282SShri Abhyankar    with SNESCreate_VI().
17902b4ed282SShri Abhyankar 
17912b4ed282SShri Abhyankar    Input Parameter:
17922b4ed282SShri Abhyankar .  snes - the SNES context
17932b4ed282SShri Abhyankar 
17942b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
17952b4ed282SShri Abhyankar  */
17962b4ed282SShri Abhyankar #undef __FUNCT__
17972b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
17982b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
17992b4ed282SShri Abhyankar {
18002b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
18012b4ed282SShri Abhyankar   PetscErrorCode ierr;
18022b4ed282SShri Abhyankar 
18032b4ed282SShri Abhyankar   PetscFunctionBegin;
18042b4ed282SShri Abhyankar 
18052f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18062b4ed282SShri Abhyankar     /* clear vectors */
18076bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18086bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18096bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18106bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18116bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18126bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18137fe79bc4SShri Abhyankar   }
18147fe79bc4SShri Abhyankar 
18156bf464f9SBarry Smith   ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
18162b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18172b4ed282SShri Abhyankar 
18182b4ed282SShri Abhyankar   /* clear composed functions */
18192b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1820c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18212b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18222b4ed282SShri Abhyankar }
18237fe79bc4SShri Abhyankar 
18242b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18252b4ed282SShri Abhyankar #undef __FUNCT__
18262b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18272b4ed282SShri Abhyankar 
18282b4ed282SShri Abhyankar /*
18297fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18307fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18312b4ed282SShri Abhyankar 
18322b4ed282SShri Abhyankar */
1833ace3abfcSBarry 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)
18342b4ed282SShri Abhyankar {
18352b4ed282SShri Abhyankar   PetscErrorCode ierr;
18362b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1837ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18382b4ed282SShri Abhyankar 
18392b4ed282SShri Abhyankar   PetscFunctionBegin;
18402b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18412b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18422b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
18432b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1844c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1845c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1846c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1847c1a5e521SShri Abhyankar   }
1848c1a5e521SShri Abhyankar   if (changed_y) {
1849c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18507fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1851c1a5e521SShri Abhyankar   }
1852c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1853c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1854c1a5e521SShri Abhyankar   if (!snes->domainerror) {
18552f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
18567fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
18577fe79bc4SShri Abhyankar     } else {
1858c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
18597fe79bc4SShri Abhyankar     }
186062cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1861c1a5e521SShri Abhyankar   }
1862c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1863c1a5e521SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1864c1a5e521SShri Abhyankar   }
1865c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1866c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1867c1a5e521SShri Abhyankar }
1868c1a5e521SShri Abhyankar 
1869c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1870c1a5e521SShri Abhyankar #undef __FUNCT__
18712b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
18722b4ed282SShri Abhyankar 
18732b4ed282SShri Abhyankar /*
18742b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
18752b4ed282SShri Abhyankar */
1876ace3abfcSBarry 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)
18772b4ed282SShri Abhyankar {
18782b4ed282SShri Abhyankar   PetscErrorCode ierr;
18792b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1880ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18812b4ed282SShri Abhyankar 
18822b4ed282SShri Abhyankar   PetscFunctionBegin;
18832b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18842b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18852b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
18867fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18872b4ed282SShri Abhyankar   if (vi->postcheckstep) {
18882b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
18892b4ed282SShri Abhyankar   }
18902b4ed282SShri Abhyankar   if (changed_y) {
18912b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18927fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18932b4ed282SShri Abhyankar   }
18942b4ed282SShri Abhyankar 
18952b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
18962b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
18972b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18982b4ed282SShri Abhyankar   }
18992b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19002b4ed282SShri Abhyankar   PetscFunctionReturn(0);
19012b4ed282SShri Abhyankar }
19027fe79bc4SShri Abhyankar 
19032b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
19042b4ed282SShri Abhyankar #undef __FUNCT__
19052b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19062b4ed282SShri Abhyankar /*
19077fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19082b4ed282SShri Abhyankar */
1909ace3abfcSBarry 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)
19102b4ed282SShri Abhyankar {
1911fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1912fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1913fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1914fe835674SShri Abhyankar   PetscScalar    cinitslope;
1915fe835674SShri Abhyankar #endif
1916fe835674SShri Abhyankar   PetscErrorCode ierr;
1917fe835674SShri Abhyankar   PetscInt       count;
1918fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1919fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1920fe835674SShri Abhyankar   MPI_Comm       comm;
1921fe835674SShri Abhyankar 
1922fe835674SShri Abhyankar   PetscFunctionBegin;
1923fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1924fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1925fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1926fe835674SShri Abhyankar 
1927fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1928fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1929fe835674SShri Abhyankar     if (vi->lsmonitor) {
1930fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1931fe835674SShri Abhyankar     }
1932fe835674SShri Abhyankar     *gnorm = fnorm;
1933fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1934fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1935fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1936fe835674SShri Abhyankar     goto theend1;
1937fe835674SShri Abhyankar   }
1938fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1939fe835674SShri Abhyankar     if (vi->lsmonitor) {
1940fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1941fe835674SShri Abhyankar     }
1942fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1943fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1944fe835674SShri Abhyankar   }
1945fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1946fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1947fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1948fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1949fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1950fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1951fe835674SShri Abhyankar #else
1952fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1953fe835674SShri Abhyankar #endif
1954fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1955fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1956fe835674SShri Abhyankar 
1957fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
1958fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1959fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1960fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
1961fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1962fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1963fe835674SShri Abhyankar     goto theend1;
1964fe835674SShri Abhyankar   }
1965fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19662f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1967fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19687fe79bc4SShri Abhyankar   } else {
19697fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19707fe79bc4SShri Abhyankar   }
1971fe835674SShri Abhyankar   if (snes->domainerror) {
1972fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1973fe835674SShri Abhyankar     PetscFunctionReturn(0);
1974fe835674SShri Abhyankar   }
197562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1976fe835674SShri Abhyankar   ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1977fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
1978fe835674SShri Abhyankar     if (vi->lsmonitor) {
1979fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1980fe835674SShri Abhyankar     }
1981fe835674SShri Abhyankar     goto theend1;
1982fe835674SShri Abhyankar   }
1983fe835674SShri Abhyankar 
1984fe835674SShri Abhyankar   /* Fit points with quadratic */
1985fe835674SShri Abhyankar   lambda     = 1.0;
1986fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
1987fe835674SShri Abhyankar   lambdaprev = lambda;
1988fe835674SShri Abhyankar   gnormprev  = *gnorm;
1989fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1990fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
1991fe835674SShri Abhyankar   else                         lambda = lambdatemp;
1992fe835674SShri Abhyankar 
1993fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1994fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1995fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1996fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
1997fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1998fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1999fe835674SShri Abhyankar     goto theend1;
2000fe835674SShri Abhyankar   }
2001fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20022f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2003fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20047fe79bc4SShri Abhyankar   } else {
20057fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20067fe79bc4SShri Abhyankar   }
2007fe835674SShri Abhyankar   if (snes->domainerror) {
2008fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2009fe835674SShri Abhyankar     PetscFunctionReturn(0);
2010fe835674SShri Abhyankar   }
201162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2012fe835674SShri Abhyankar   if (vi->lsmonitor) {
2013fe835674SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
2014fe835674SShri Abhyankar   }
2015fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2016fe835674SShri Abhyankar     if (vi->lsmonitor) {
2017fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
2018fe835674SShri Abhyankar     }
2019fe835674SShri Abhyankar     goto theend1;
2020fe835674SShri Abhyankar   }
2021fe835674SShri Abhyankar 
2022fe835674SShri Abhyankar   /* Fit points with cubic */
2023fe835674SShri Abhyankar   count = 1;
2024fe835674SShri Abhyankar   while (PETSC_TRUE) {
2025fe835674SShri Abhyankar     if (lambda <= minlambda) {
2026fe835674SShri Abhyankar       if (vi->lsmonitor) {
2027fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
2028fe835674SShri 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);
2029fe835674SShri Abhyankar       }
2030fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2031fe835674SShri Abhyankar       break;
2032fe835674SShri Abhyankar     }
2033fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2034fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2035fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2036fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2037fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2038fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2039fe835674SShri Abhyankar     if (a == 0.0) {
2040fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2041fe835674SShri Abhyankar     } else {
2042fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2043fe835674SShri Abhyankar     }
2044fe835674SShri Abhyankar     lambdaprev = lambda;
2045fe835674SShri Abhyankar     gnormprev  = *gnorm;
2046fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2047fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2048fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2049fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2050fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2051fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2052fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2053fe835674SShri 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);
2054fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2055fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2056fe835674SShri Abhyankar       break;
2057fe835674SShri Abhyankar     }
2058fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20592f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2060fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20617fe79bc4SShri Abhyankar     } else {
20627fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20637fe79bc4SShri Abhyankar     }
2064fe835674SShri Abhyankar     if (snes->domainerror) {
2065fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2066fe835674SShri Abhyankar       PetscFunctionReturn(0);
2067fe835674SShri Abhyankar     }
206862cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2069fe835674SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */
2070fe835674SShri Abhyankar       if (vi->lsmonitor) {
2071fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2072fe835674SShri Abhyankar       }
2073fe835674SShri Abhyankar       break;
2074fe835674SShri Abhyankar     } else {
2075fe835674SShri Abhyankar       if (vi->lsmonitor) {
2076fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2077fe835674SShri Abhyankar       }
2078fe835674SShri Abhyankar     }
2079fe835674SShri Abhyankar     count++;
2080fe835674SShri Abhyankar   }
2081fe835674SShri Abhyankar   theend1:
2082fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2083fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2084fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2085fe835674SShri Abhyankar     if (changed_y) {
2086fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2087fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2088fe835674SShri Abhyankar     }
2089fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2090fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20912f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2092fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20937fe79bc4SShri Abhyankar       } else {
20947fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20957fe79bc4SShri Abhyankar       }
2096fe835674SShri Abhyankar       if (snes->domainerror) {
2097fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2098fe835674SShri Abhyankar         PetscFunctionReturn(0);
2099fe835674SShri Abhyankar       }
210062cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2101fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2102fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2103fe835674SShri Abhyankar     }
2104fe835674SShri Abhyankar   }
2105fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2106fe835674SShri Abhyankar   PetscFunctionReturn(0);
2107fe835674SShri Abhyankar }
2108fe835674SShri Abhyankar 
21092b4ed282SShri Abhyankar #undef __FUNCT__
21102b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21112b4ed282SShri Abhyankar /*
21127fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21132b4ed282SShri Abhyankar */
2114ace3abfcSBarry 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)
21152b4ed282SShri Abhyankar {
21162b4ed282SShri Abhyankar   /*
21172b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21182b4ed282SShri Abhyankar      minimization problem:
21192b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21202b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
21212b4ed282SShri Abhyankar    */
21222b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
21232b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21242b4ed282SShri Abhyankar   PetscScalar    cinitslope;
21252b4ed282SShri Abhyankar #endif
21262b4ed282SShri Abhyankar   PetscErrorCode ierr;
21272b4ed282SShri Abhyankar   PetscInt       count;
21282b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2129ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
21302b4ed282SShri Abhyankar 
21312b4ed282SShri Abhyankar   PetscFunctionBegin;
21322b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21332b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
21342b4ed282SShri Abhyankar 
21352b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
21362b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2137c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2138c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
21392b4ed282SShri Abhyankar     }
21402b4ed282SShri Abhyankar     *gnorm = fnorm;
21412b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
21422b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
21432b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
21442b4ed282SShri Abhyankar     goto theend2;
21452b4ed282SShri Abhyankar   }
21462b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
21472b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
21482b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
21492b4ed282SShri Abhyankar   }
21502b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
21512b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
21527fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
21532b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21547fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
21552b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
21562b4ed282SShri Abhyankar #else
21577fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
21582b4ed282SShri Abhyankar #endif
21592b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
21602b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
21612b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
21622b4ed282SShri Abhyankar 
21632b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21647fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21652b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
21662b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
21672b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
21682b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21692b4ed282SShri Abhyankar     goto theend2;
21702b4ed282SShri Abhyankar   }
21712b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21722f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
21737fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21747fe79bc4SShri Abhyankar   } else {
21757fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21767fe79bc4SShri Abhyankar   }
21772b4ed282SShri Abhyankar   if (snes->domainerror) {
21782b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21792b4ed282SShri Abhyankar     PetscFunctionReturn(0);
21802b4ed282SShri Abhyankar   }
218162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21822b4ed282SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
2183c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2184c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
21852b4ed282SShri Abhyankar     }
21862b4ed282SShri Abhyankar     goto theend2;
21872b4ed282SShri Abhyankar   }
21882b4ed282SShri Abhyankar 
21892b4ed282SShri Abhyankar   /* Fit points with quadratic */
21902b4ed282SShri Abhyankar   lambda = 1.0;
21912b4ed282SShri Abhyankar   count = 1;
21922b4ed282SShri Abhyankar   while (PETSC_TRUE) {
21932b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2194c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2195c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2196c92abb8aSShri 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);
21972b4ed282SShri Abhyankar       }
21982b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
21992b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22002b4ed282SShri Abhyankar       break;
22012b4ed282SShri Abhyankar     }
22022b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
22032b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
22042b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
22052b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22062b4ed282SShri Abhyankar 
22072b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22087fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22092b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22102b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
22112b4ed282SShri 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);
22122b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22132b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22142b4ed282SShri Abhyankar       break;
22152b4ed282SShri Abhyankar     }
22162b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22172b4ed282SShri Abhyankar     if (snes->domainerror) {
22182b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22192b4ed282SShri Abhyankar       PetscFunctionReturn(0);
22202b4ed282SShri Abhyankar     }
22212f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
22227fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22237fe79bc4SShri Abhyankar     } else {
22242b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22257fe79bc4SShri Abhyankar     }
222662cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22272b4ed282SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2228c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2229c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
22302b4ed282SShri Abhyankar       }
22312b4ed282SShri Abhyankar       break;
22322b4ed282SShri Abhyankar     }
22332b4ed282SShri Abhyankar     count++;
22342b4ed282SShri Abhyankar   }
22352b4ed282SShri Abhyankar   theend2:
22362b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
22372b4ed282SShri Abhyankar   if (vi->postcheckstep) {
22382b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
22392b4ed282SShri Abhyankar     if (changed_y) {
22402b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22417fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22422b4ed282SShri Abhyankar     }
22432b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
22442b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
22452b4ed282SShri Abhyankar       if (snes->domainerror) {
22462b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22472b4ed282SShri Abhyankar         PetscFunctionReturn(0);
22482b4ed282SShri Abhyankar       }
22492f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
22507fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22517fe79bc4SShri Abhyankar       } else {
22527fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22537fe79bc4SShri Abhyankar       }
22547fe79bc4SShri Abhyankar 
22552b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
22562b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
225762cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
22582b4ed282SShri Abhyankar     }
22592b4ed282SShri Abhyankar   }
22602b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22612b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22622b4ed282SShri Abhyankar }
22632b4ed282SShri Abhyankar 
2264ace3abfcSBarry 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*/
22652b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22662b4ed282SShri Abhyankar EXTERN_C_BEGIN
22672b4ed282SShri Abhyankar #undef __FUNCT__
22682b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
22697087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
22702b4ed282SShri Abhyankar {
22712b4ed282SShri Abhyankar   PetscFunctionBegin;
22722b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
22732b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
22742b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22752b4ed282SShri Abhyankar }
22762b4ed282SShri Abhyankar EXTERN_C_END
22772b4ed282SShri Abhyankar 
22782b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22792b4ed282SShri Abhyankar EXTERN_C_BEGIN
22802b4ed282SShri Abhyankar #undef __FUNCT__
22812b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
22827087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
22832b4ed282SShri Abhyankar {
22842b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
22852b4ed282SShri Abhyankar   PetscErrorCode ierr;
22862b4ed282SShri Abhyankar 
22872b4ed282SShri Abhyankar   PetscFunctionBegin;
2288c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2289c92abb8aSShri Abhyankar     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr);
2290c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
22916bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
22922b4ed282SShri Abhyankar   }
22932b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22942b4ed282SShri Abhyankar }
22952b4ed282SShri Abhyankar EXTERN_C_END
22962b4ed282SShri Abhyankar 
22972b4ed282SShri Abhyankar /*
22982b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
22992b4ed282SShri Abhyankar 
23002b4ed282SShri Abhyankar    Input Parameters:
23012b4ed282SShri Abhyankar .  SNES - the SNES context
23022b4ed282SShri Abhyankar .  viewer - visualization context
23032b4ed282SShri Abhyankar 
23042b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
23052b4ed282SShri Abhyankar */
23062b4ed282SShri Abhyankar #undef __FUNCT__
23072b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23082b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23092b4ed282SShri Abhyankar {
23102b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
231178c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23122b4ed282SShri Abhyankar   PetscErrorCode ierr;
2313ace3abfcSBarry Smith   PetscBool     iascii;
23142b4ed282SShri Abhyankar 
23152b4ed282SShri Abhyankar   PetscFunctionBegin;
23162b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23172b4ed282SShri Abhyankar   if (iascii) {
23182b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
23192b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
23202b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
23212b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
232278c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
23230a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2324b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
232578c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
232678c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
23272b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
23282b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
23292b4ed282SShri Abhyankar   } else {
23302b4ed282SShri Abhyankar     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name);
23312b4ed282SShri Abhyankar   }
23322b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23332b4ed282SShri Abhyankar }
23342b4ed282SShri Abhyankar 
23355559b345SBarry Smith #undef __FUNCT__
23365559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
23375559b345SBarry Smith /*@
23382b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
23392b4ed282SShri Abhyankar 
23402b4ed282SShri Abhyankar    Input Parameters:
23412b4ed282SShri Abhyankar .  snes - the SNES context.
23422b4ed282SShri Abhyankar .  xl   - lower bound.
23432b4ed282SShri Abhyankar .  xu   - upper bound.
23442b4ed282SShri Abhyankar 
23452b4ed282SShri Abhyankar    Notes:
23462b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
234701f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
234884c105d7SBarry Smith 
23495559b345SBarry Smith @*/
235069c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
23512b4ed282SShri Abhyankar {
2352d923200aSJungho Lee   SNES_VI        *vi;
2353d923200aSJungho Lee   PetscErrorCode ierr;
23542b4ed282SShri Abhyankar 
23552b4ed282SShri Abhyankar   PetscFunctionBegin;
23562b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
23572b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
23582b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
23592b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
23602b4ed282SShri 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);
23612b4ed282SShri 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);
2362d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2363d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
23642176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
23652176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
23662176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
23672176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
23682b4ed282SShri Abhyankar   vi->xl = xl;
23692b4ed282SShri Abhyankar   vi->xu = xu;
23702b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23712b4ed282SShri Abhyankar }
2372693ddf92SShri Abhyankar 
23732b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23742b4ed282SShri Abhyankar /*
23752b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
23762b4ed282SShri Abhyankar 
23772b4ed282SShri Abhyankar    Input Parameter:
23782b4ed282SShri Abhyankar .  snes - the SNES context
23792b4ed282SShri Abhyankar 
23802b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
23812b4ed282SShri Abhyankar */
23822b4ed282SShri Abhyankar #undef __FUNCT__
23832b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
23842b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
23852b4ed282SShri Abhyankar {
23862b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
23877fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2388b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
23892b4ed282SShri Abhyankar   PetscErrorCode ierr;
23902b4ed282SShri Abhyankar   PetscInt       indx;
239169c03620SShri Abhyankar   PetscBool      flg,set,flg2;
23922b4ed282SShri Abhyankar 
23932b4ed282SShri Abhyankar   PetscFunctionBegin;
23942b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
23959308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
23969308c137SBarry Smith   if (flg) {
23979308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
23989308c137SBarry Smith   }
2399be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2400be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2401be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
24022b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2403be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
24042b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
24052f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
240669c03620SShri Abhyankar   if (flg2) {
240769c03620SShri Abhyankar     switch (indx) {
240869c03620SShri Abhyankar     case 0:
240969c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
241069c03620SShri Abhyankar       break;
241169c03620SShri Abhyankar     case 1:
2412d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2413d950fb63SShri Abhyankar       break;
24142f63a38cSShri Abhyankar     case 2:
2415b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
241669c03620SShri Abhyankar     }
241769c03620SShri Abhyankar   }
2418be6adb11SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr);
24192b4ed282SShri Abhyankar   if (flg) {
24202b4ed282SShri Abhyankar     switch (indx) {
24212b4ed282SShri Abhyankar     case 0:
24222b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
24232b4ed282SShri Abhyankar       break;
24242b4ed282SShri Abhyankar     case 1:
24252b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
24262b4ed282SShri Abhyankar       break;
24272b4ed282SShri Abhyankar     case 2:
24282b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
24292b4ed282SShri Abhyankar       break;
24302b4ed282SShri Abhyankar     case 3:
24312b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
24322b4ed282SShri Abhyankar       break;
24332b4ed282SShri Abhyankar     }
2434fe835674SShri Abhyankar   }
24352b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
24362b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24372b4ed282SShri Abhyankar }
24382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24392b4ed282SShri Abhyankar /*MC
24408b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
24412b4ed282SShri Abhyankar 
24422b4ed282SShri Abhyankar    Options Database:
24438b4c83edSBarry 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
24448b4c83edSBarry Smith                                 additional variables that enforce the constraints
24458b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
24462b4ed282SShri Abhyankar 
24472b4ed282SShri Abhyankar 
24482b4ed282SShri Abhyankar    Level: beginner
24492b4ed282SShri Abhyankar 
24502b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
24512b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
24522b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
24532b4ed282SShri Abhyankar 
24542b4ed282SShri Abhyankar M*/
24552b4ed282SShri Abhyankar EXTERN_C_BEGIN
24562b4ed282SShri Abhyankar #undef __FUNCT__
24572b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
24587087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
24592b4ed282SShri Abhyankar {
24602b4ed282SShri Abhyankar   PetscErrorCode ierr;
24612b4ed282SShri Abhyankar   SNES_VI        *vi;
24622b4ed282SShri Abhyankar 
24632b4ed282SShri Abhyankar   PetscFunctionBegin;
24642176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
24652b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2466edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
24672b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
24682b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
24692b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
24702b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
24712b4ed282SShri Abhyankar 
24722b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
24732b4ed282SShri Abhyankar   snes->data            = (void*)vi;
24742b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
24752b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
24762b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
24777fe79bc4SShri Abhyankar   vi->LineSearch        = SNESLineSearchNo_VI;
24782b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
24792b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
24802b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
24812b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
24822b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
24832b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
24842f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
24852b4ed282SShri Abhyankar 
24862b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
24872b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
24882b4ed282SShri Abhyankar 
24892b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24902b4ed282SShri Abhyankar }
24912b4ed282SShri Abhyankar EXTERN_C_END
2492