xref: /petsc/src/snes/impls/vi/vi.c (revision 9ce20c35ba6d5c5a7f5ce079ef995208a8d797ba)
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 @*/
1877cdaf69SJed Brown 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__
32ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS"
33d0af7cd3SBarry Smith /*
34ed70e96aSJungho Lee    SNESVIComputeInactiveSetIS - 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  */
44ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(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 
85ed70e96aSJungho Lee <*/
863c0c59f3SBarry Smith typedef struct {
873c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
883c0c59f3SBarry Smith   IS             inactive;
893c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
903c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
913c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
924c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
933c0c59f3SBarry Smith } DM_SNESVI;
943c0c59f3SBarry Smith 
95d0af7cd3SBarry Smith #undef __FUNCT__
964dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
974dcab191SBarry Smith /*
984dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
994dcab191SBarry Smith 
1004dcab191SBarry Smith */
1014dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
1024dcab191SBarry Smith {
1034dcab191SBarry Smith   PetscErrorCode          ierr;
1044dcab191SBarry Smith   PetscContainer          isnes;
1053c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
1064dcab191SBarry Smith 
1074dcab191SBarry Smith   PetscFunctionBegin;
1084dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1094dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
1104dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
1114dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
1124dcab191SBarry Smith   PetscFunctionReturn(0);
1134dcab191SBarry Smith }
1144dcab191SBarry Smith 
1154dcab191SBarry Smith #undef __FUNCT__
116d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
117d0af7cd3SBarry Smith /*
118d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
119d0af7cd3SBarry Smith 
120d0af7cd3SBarry Smith */
121d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
122d0af7cd3SBarry Smith {
123d0af7cd3SBarry Smith   PetscErrorCode          ierr;
124d0af7cd3SBarry Smith   PetscContainer          isnes;
1253c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
126d0af7cd3SBarry Smith   Mat                     interp;
127d0af7cd3SBarry Smith 
128d0af7cd3SBarry Smith   PetscFunctionBegin;
129d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1304c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
131d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
132d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1334c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
134d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
135d0af7cd3SBarry Smith 
136d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1374dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
138d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
13900ac8be1SBarry Smith   *vec = 0;
140d0af7cd3SBarry Smith   PetscFunctionReturn(0);
141d0af7cd3SBarry Smith }
142d0af7cd3SBarry Smith 
143*9ce20c35SJungho Lee extern PetscErrorCode  DMSetVI(DM,IS);
144d0af7cd3SBarry Smith 
145d0af7cd3SBarry Smith #undef __FUNCT__
146d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
147d0af7cd3SBarry Smith /*
148d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
149d0af7cd3SBarry Smith 
150d0af7cd3SBarry Smith */
151d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
152d0af7cd3SBarry Smith {
153d0af7cd3SBarry Smith   PetscErrorCode          ierr;
154d0af7cd3SBarry Smith   PetscContainer          isnes;
1553c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
156*9ce20c35SJungho Lee   Vec                     finemarked,coarsemarked;
157d0af7cd3SBarry Smith   IS                      inactive;
158d0af7cd3SBarry Smith   VecScatter              inject;
159*9ce20c35SJungho Lee   const PetscInt          *index;
160*9ce20c35SJungho Lee   PetscInt                n,k,cnt = 0,rstart,*coarseindex;
161*9ce20c35SJungho Lee   PetscScalar             *marked;
162d0af7cd3SBarry Smith 
163d0af7cd3SBarry Smith   PetscFunctionBegin;
164d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1654c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
166d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
167d0af7cd3SBarry Smith 
168298cc208SBarry Smith   /* get the original coarsen */
169d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
170298cc208SBarry Smith 
1713c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1723c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1733c0c59f3SBarry Smith 
174298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
175298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
176298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
177*9ce20c35SJungho Lee   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
178*9ce20c35SJungho Lee   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
179*9ce20c35SJungho Lee 
180*9ce20c35SJungho Lee   /*
181*9ce20c35SJungho Lee      fill finemarked with locations of inactive points
182*9ce20c35SJungho Lee   */
183*9ce20c35SJungho Lee   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
184*9ce20c35SJungho Lee   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
185*9ce20c35SJungho Lee   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
186*9ce20c35SJungho Lee   for (k=0;k<n;k++){
187*9ce20c35SJungho Lee       ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
188*9ce20c35SJungho Lee   }
189*9ce20c35SJungho Lee   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
190*9ce20c35SJungho Lee   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
191*9ce20c35SJungho Lee 
192d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
193*9ce20c35SJungho Lee   ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
194*9ce20c35SJungho Lee   ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
196*9ce20c35SJungho Lee 
197*9ce20c35SJungho Lee   /*
198*9ce20c35SJungho Lee      create index set list of coarse inactive points from coarsemarked
199*9ce20c35SJungho Lee   */
200*9ce20c35SJungho Lee   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
201*9ce20c35SJungho Lee   ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr);
202*9ce20c35SJungho Lee   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
203*9ce20c35SJungho Lee   for (k=0; k<n; k++) {
204*9ce20c35SJungho Lee     if (marked[k]) cnt++;
205*9ce20c35SJungho Lee   }
206*9ce20c35SJungho Lee   ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr);
207*9ce20c35SJungho Lee   cnt  = 0;
208*9ce20c35SJungho Lee   for (k=0; k<n; k++) {
209*9ce20c35SJungho Lee     if (marked[k]) coarseindex[cnt++] = k + rstart;
210*9ce20c35SJungho Lee   }
211*9ce20c35SJungho Lee   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
212*9ce20c35SJungho Lee   ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
213*9ce20c35SJungho Lee 
214298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
215298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
216*9ce20c35SJungho Lee   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
217*9ce20c35SJungho Lee 
218*9ce20c35SJungho Lee   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
219*9ce20c35SJungho Lee   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
2203c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
221d0af7cd3SBarry Smith   PetscFunctionReturn(0);
222d0af7cd3SBarry Smith }
223d0af7cd3SBarry Smith 
224d0af7cd3SBarry Smith #undef __FUNCT__
2253c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2263c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
227d0af7cd3SBarry Smith {
228d0af7cd3SBarry Smith   PetscErrorCode ierr;
229d0af7cd3SBarry Smith 
230d0af7cd3SBarry Smith   PetscFunctionBegin;
2314c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2324c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2334c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2344c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
23500ac8be1SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
23600ac8be1SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
23700ac8be1SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
2384c661befSBarry Smith 
239d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
240d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
241d0af7cd3SBarry Smith   PetscFunctionReturn(0);
242d0af7cd3SBarry Smith }
243d0af7cd3SBarry Smith 
244d0af7cd3SBarry Smith #undef __FUNCT__
245d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
246d0af7cd3SBarry Smith /*
247d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
248d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
249d0af7cd3SBarry Smith 
250d0af7cd3SBarry Smith */
251*9ce20c35SJungho Lee PetscErrorCode  DMSetVI(DM dm,IS inactive)
252d0af7cd3SBarry Smith {
253d0af7cd3SBarry Smith   PetscErrorCode          ierr;
254d0af7cd3SBarry Smith   PetscContainer          isnes;
2553c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
256d0af7cd3SBarry Smith 
257d0af7cd3SBarry Smith   PetscFunctionBegin;
2584dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
2591c0a9e84SBarry Smith 
260d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
261d0af7cd3SBarry Smith 
262d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
263d0af7cd3SBarry Smith   if (!isnes) {
264d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2653c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2663c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
267d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
268d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2693c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
270d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
271d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
272d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
273d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
274298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2754dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
276d0af7cd3SBarry Smith   } else {
277d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
278d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
279d0af7cd3SBarry Smith   }
2804dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2814dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
282d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2831a223a97SBarry Smith   dmsnesvi->dm       = dm;
284d0af7cd3SBarry Smith   PetscFunctionReturn(0);
285d0af7cd3SBarry Smith }
286d0af7cd3SBarry Smith 
2874c661befSBarry Smith #undef __FUNCT__
2884c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2894c661befSBarry Smith /*
2904c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2914c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2924c661befSBarry Smith */
2934c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2944c661befSBarry Smith {
2954c661befSBarry Smith   PetscErrorCode          ierr;
2964c661befSBarry Smith 
2974c661befSBarry Smith   PetscFunctionBegin;
2984c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
2994c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
3004c661befSBarry Smith   PetscFunctionReturn(0);
3014c661befSBarry Smith }
3024c661befSBarry Smith 
3033c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
3042b4ed282SShri Abhyankar 
3059308c137SBarry Smith #undef __FUNCT__
3069308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3077087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3089308c137SBarry Smith {
3099308c137SBarry Smith   PetscErrorCode    ierr;
3109308c137SBarry Smith   SNES_VI            *vi = (SNES_VI*)snes->data;
311649052a6SBarry Smith   PetscViewer        viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);
3129308c137SBarry Smith   const PetscScalar  *x,*xl,*xu,*f;
31309573ac7SBarry Smith   PetscInt           i,n,act = 0;
3149308c137SBarry Smith   PetscReal          rnorm,fnorm;
3159308c137SBarry Smith 
3169308c137SBarry Smith   PetscFunctionBegin;
3179308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3189308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3199308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3209308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3213f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3229308c137SBarry Smith 
3239308c137SBarry Smith   rnorm = 0.0;
3249308c137SBarry Smith   for (i=0; i<n; i++) {
32510f5ae6bSBarry 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]);
32609573ac7SBarry Smith     else act++;
3279308c137SBarry Smith   }
3283f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3299308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3309308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3319308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
332d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3339308c137SBarry Smith   fnorm = sqrt(fnorm);
334649052a6SBarry Smith   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
335649052a6SBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
336649052a6SBarry Smith   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
3379308c137SBarry Smith   PetscFunctionReturn(0);
3389308c137SBarry Smith }
3399308c137SBarry Smith 
3402b4ed282SShri Abhyankar /*
3412b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3422b4ed282SShri 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
3432b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3442b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3452b4ed282SShri Abhyankar */
3462b4ed282SShri Abhyankar #undef __FUNCT__
3472b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
348ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3492b4ed282SShri Abhyankar {
3502b4ed282SShri Abhyankar   PetscReal      a1;
3512b4ed282SShri Abhyankar   PetscErrorCode ierr;
352ace3abfcSBarry Smith   PetscBool     hastranspose;
3532b4ed282SShri Abhyankar 
3542b4ed282SShri Abhyankar   PetscFunctionBegin;
3552b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3562b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3572b4ed282SShri Abhyankar   if (hastranspose) {
3582b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3592b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3602b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3612b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3622b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3632b4ed282SShri Abhyankar   } else {
3642b4ed282SShri Abhyankar     Vec         work;
3652b4ed282SShri Abhyankar     PetscScalar result;
3662b4ed282SShri Abhyankar     PetscReal   wnorm;
3672b4ed282SShri Abhyankar 
3682b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3692b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3702b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3712b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3722b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3736bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3742b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3752b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3762b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3772b4ed282SShri Abhyankar   }
3782b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3792b4ed282SShri Abhyankar }
3802b4ed282SShri Abhyankar 
3812b4ed282SShri Abhyankar /*
3822b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3832b4ed282SShri Abhyankar */
3842b4ed282SShri Abhyankar #undef __FUNCT__
3852b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3862b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3872b4ed282SShri Abhyankar {
3882b4ed282SShri Abhyankar   PetscReal      a1,a2;
3892b4ed282SShri Abhyankar   PetscErrorCode ierr;
390ace3abfcSBarry Smith   PetscBool     hastranspose;
3912b4ed282SShri Abhyankar 
3922b4ed282SShri Abhyankar   PetscFunctionBegin;
3932b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3942b4ed282SShri Abhyankar   if (hastranspose) {
3952b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3962b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3972b4ed282SShri Abhyankar 
3982b4ed282SShri Abhyankar     /* Compute || J^T W|| */
3992b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
4002b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
4012b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
4022b4ed282SShri Abhyankar     if (a1 != 0.0) {
4032b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
4042b4ed282SShri Abhyankar     }
4052b4ed282SShri Abhyankar   }
4062b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4072b4ed282SShri Abhyankar }
4082b4ed282SShri Abhyankar 
4092b4ed282SShri Abhyankar /*
4102b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4112b4ed282SShri Abhyankar 
4122b4ed282SShri Abhyankar   Notes:
4132b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4142b4ed282SShri Abhyankar   merit < abstol
4152b4ed282SShri Abhyankar   merit < rtol*merit_initial
4162b4ed282SShri Abhyankar */
4172b4ed282SShri Abhyankar #undef __FUNCT__
4182b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4197fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4202b4ed282SShri Abhyankar {
4212b4ed282SShri Abhyankar   PetscErrorCode ierr;
4222b4ed282SShri Abhyankar 
4232b4ed282SShri Abhyankar   PetscFunctionBegin;
4242b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4252b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4262b4ed282SShri Abhyankar 
4272b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4282b4ed282SShri Abhyankar 
4292b4ed282SShri Abhyankar   if (!it) {
4302b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4317fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4322b4ed282SShri Abhyankar   }
4337fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4342b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4352b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4367fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4377fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4382b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4392b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4402b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4412b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4422b4ed282SShri Abhyankar   }
4432b4ed282SShri Abhyankar 
4442b4ed282SShri Abhyankar   if (it && !*reason) {
4457fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4467fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4472b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4482b4ed282SShri Abhyankar     }
4492b4ed282SShri Abhyankar   }
4502b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4512b4ed282SShri Abhyankar }
4522b4ed282SShri Abhyankar 
4532b4ed282SShri Abhyankar /*
4542b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4552b4ed282SShri Abhyankar 
4562b4ed282SShri Abhyankar   Input Parameter:
4572b4ed282SShri Abhyankar . phi - the semismooth function
4582b4ed282SShri Abhyankar 
4592b4ed282SShri Abhyankar   Output Parameter:
4602b4ed282SShri Abhyankar . merit - the merit function
4612b4ed282SShri Abhyankar . phinorm - ||phi||
4622b4ed282SShri Abhyankar 
4632b4ed282SShri Abhyankar   Notes:
4642b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4652b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4662b4ed282SShri Abhyankar */
4672b4ed282SShri Abhyankar #undef __FUNCT__
4682b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4692b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4702b4ed282SShri Abhyankar {
4712b4ed282SShri Abhyankar   PetscErrorCode ierr;
4722b4ed282SShri Abhyankar 
4732b4ed282SShri Abhyankar   PetscFunctionBegin;
4745f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4755f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4762b4ed282SShri Abhyankar 
4772b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4782b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4792b4ed282SShri Abhyankar }
4802b4ed282SShri Abhyankar 
4817f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4824c21c6cdSBarry Smith {
4834c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4844c21c6cdSBarry Smith }
4854c21c6cdSBarry Smith 
4867f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4874c21c6cdSBarry Smith {
4885559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4895559b345SBarry Smith   else return .5;
4904c21c6cdSBarry Smith }
4914c21c6cdSBarry Smith 
4922b4ed282SShri Abhyankar /*
4931f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4942b4ed282SShri Abhyankar 
4952b4ed282SShri Abhyankar    Input Parameters:
4962b4ed282SShri Abhyankar .  snes - the SNES context
4972b4ed282SShri Abhyankar .  x - current iterate
4982b4ed282SShri Abhyankar .  functx - user defined function context
4992b4ed282SShri Abhyankar 
5002b4ed282SShri Abhyankar    Output Parameters:
5012b4ed282SShri Abhyankar .  phi - Semismooth function
5022b4ed282SShri Abhyankar 
5032b4ed282SShri Abhyankar */
5042b4ed282SShri Abhyankar #undef __FUNCT__
5051f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5061f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5072b4ed282SShri Abhyankar {
5082b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5092b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5102b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5114c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5122b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5132b4ed282SShri Abhyankar 
5142b4ed282SShri Abhyankar   PetscFunctionBegin;
5152b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5162b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5172b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5182b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5192b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5202b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5212b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5222b4ed282SShri Abhyankar 
5232b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
52410f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5254c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
52610f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5274c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
52810f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5294c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5305559b345SBarry Smith     } else if (l[i] == u[i]) {
5312b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5325559b345SBarry Smith     } else {                                                /* both bounds on variable */
5334c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5342b4ed282SShri Abhyankar     }
5352b4ed282SShri Abhyankar   }
5362b4ed282SShri Abhyankar 
5372b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5382b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5392b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5402b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5412b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5422b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5432b4ed282SShri Abhyankar }
5442b4ed282SShri Abhyankar 
5452b4ed282SShri Abhyankar /*
546a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
547a79edbefSShri Abhyankar                                           the semismooth jacobian.
5482b4ed282SShri Abhyankar */
5492b4ed282SShri Abhyankar #undef __FUNCT__
550a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
551a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5522b4ed282SShri Abhyankar {
5532b4ed282SShri Abhyankar   PetscErrorCode ierr;
5542b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5554c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5562b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5572b4ed282SShri Abhyankar 
5582b4ed282SShri Abhyankar   PetscFunctionBegin;
5592b4ed282SShri Abhyankar 
5602b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5612b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5622b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5632b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
564a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
565a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5662b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5674c21c6cdSBarry Smith 
5682b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
56910f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5704c21c6cdSBarry Smith       da[i] = 0;
5712b4ed282SShri Abhyankar       db[i] = 1;
57210f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5734c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5744c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
57510f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5765559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5775559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5785559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5794c21c6cdSBarry Smith       da[i] = 1;
5802b4ed282SShri Abhyankar       db[i] = 0;
5815559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5824c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5834c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5844c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5854c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5864c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5874c21c6cdSBarry Smith       db[i] = db1*db2;
5882b4ed282SShri Abhyankar     }
5892b4ed282SShri Abhyankar   }
5905559b345SBarry Smith 
5912b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5922b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5932b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5942b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
595a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
596a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
597a79edbefSShri Abhyankar   PetscFunctionReturn(0);
598a79edbefSShri Abhyankar }
599a79edbefSShri Abhyankar 
600a79edbefSShri Abhyankar /*
601a79edbefSShri 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.
602a79edbefSShri Abhyankar 
603a79edbefSShri Abhyankar    Input Parameters:
604a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
605a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
606a79edbefSShri Abhyankar 
607a79edbefSShri Abhyankar    Output Parameters:
608a79edbefSShri Abhyankar .  jac      - semismooth jacobian
609a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
610a79edbefSShri Abhyankar 
611a79edbefSShri Abhyankar    Notes:
612a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
613a79edbefSShri Abhyankar    jac = Da + Db*jacfun
614a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
615a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
616a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
617a79edbefSShri Abhyankar */
618a79edbefSShri Abhyankar #undef __FUNCT__
619a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
620a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
621a79edbefSShri Abhyankar {
622a79edbefSShri Abhyankar   PetscErrorCode ierr;
623a79edbefSShri Abhyankar 
6242b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
625a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
626a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
627a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
628a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
629a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6302b4ed282SShri Abhyankar   }
6312b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6322b4ed282SShri Abhyankar }
6332b4ed282SShri Abhyankar 
6342b4ed282SShri Abhyankar /*
635ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
636ee657d29SShri Abhyankar 
637ee657d29SShri Abhyankar    Input Parameters:
638ee657d29SShri Abhyankar    phi - semismooth function.
639ee657d29SShri Abhyankar    H   - semismooth jacobian
640ee657d29SShri Abhyankar 
641ee657d29SShri Abhyankar    Output Parameters:
642ee657d29SShri Abhyankar    dpsi - merit function gradient
643ee657d29SShri Abhyankar 
644ee657d29SShri Abhyankar    Notes:
645ee657d29SShri Abhyankar   The merit function gradient is computed as follows
646ee657d29SShri Abhyankar         dpsi = H^T*phi
647ee657d29SShri Abhyankar */
648ee657d29SShri Abhyankar #undef __FUNCT__
649ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
650ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
651ee657d29SShri Abhyankar {
652ee657d29SShri Abhyankar   PetscErrorCode ierr;
653ee657d29SShri Abhyankar 
654ee657d29SShri Abhyankar   PetscFunctionBegin;
6555f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
656ee657d29SShri Abhyankar   PetscFunctionReturn(0);
657ee657d29SShri Abhyankar }
658ee657d29SShri Abhyankar 
659c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
660c1a5e521SShri Abhyankar /*
661c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
662c1a5e521SShri Abhyankar 
663c1a5e521SShri Abhyankar    Input Parameters:
664c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
665c1a5e521SShri Abhyankar 
666c1a5e521SShri Abhyankar    Output Parameters:
667c1a5e521SShri Abhyankar .  X - Bound projected X
668c1a5e521SShri Abhyankar 
669c1a5e521SShri Abhyankar */
670c1a5e521SShri Abhyankar 
671c1a5e521SShri Abhyankar #undef __FUNCT__
672c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
673c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
674c1a5e521SShri Abhyankar {
675c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
676c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
677c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
678c1a5e521SShri Abhyankar   PetscScalar       *x;
679c1a5e521SShri Abhyankar   PetscInt          i,n;
680c1a5e521SShri Abhyankar 
681c1a5e521SShri Abhyankar   PetscFunctionBegin;
682c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
683c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
684c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
685c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
686c1a5e521SShri Abhyankar 
687c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
68810f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
68910f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
690c1a5e521SShri Abhyankar   }
691c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
692c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
693c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
694c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
695c1a5e521SShri Abhyankar }
696c1a5e521SShri Abhyankar 
6972b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
6982b4ed282SShri Abhyankar 
6992b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
7002b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
7012b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
7022b4ed282SShri Abhyankar      respectively.
7032b4ed282SShri Abhyankar 
7042b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7052b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7062b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7072b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7082b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7092b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7102b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7112b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7122b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7132b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7142b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7152b4ed282SShri Abhyankar      for all nonlinear solvers.
7162b4ed282SShri Abhyankar 
7172b4ed282SShri Abhyankar      Another key routine is:
7182b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7192b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7202b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7212b4ed282SShri Abhyankar      SNESSolve() if necessary.
7222b4ed282SShri Abhyankar 
7232b4ed282SShri Abhyankar      Additional basic routines are:
7242b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7252b4ed282SShri Abhyankar                                       have actually been used.
7262b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7272b4ed282SShri Abhyankar      SNESView().
7282b4ed282SShri Abhyankar 
7292b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7302b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7312b4ed282SShri Abhyankar      above description applies to these categories also.
7322b4ed282SShri Abhyankar 
7332b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7342b4ed282SShri Abhyankar /*
73569c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7362b4ed282SShri Abhyankar    method using a line search.
7372b4ed282SShri Abhyankar 
7382b4ed282SShri Abhyankar    Input Parameters:
7392b4ed282SShri Abhyankar .  snes - the SNES context
7402b4ed282SShri Abhyankar 
7412b4ed282SShri Abhyankar    Output Parameter:
7422b4ed282SShri Abhyankar .  outits - number of iterations until termination
7432b4ed282SShri Abhyankar 
7442b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7452b4ed282SShri Abhyankar 
7462b4ed282SShri Abhyankar    Notes:
7472b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
74851defd01SShri Abhyankar    line search. The default line search does not do any line seach
74951defd01SShri Abhyankar    but rather takes a full newton step.
7502b4ed282SShri Abhyankar */
7512b4ed282SShri Abhyankar #undef __FUNCT__
75269c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
75369c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7542b4ed282SShri Abhyankar {
7552b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7562b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7572b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7583b336b49SShri Abhyankar   PetscBool          lssucceed;
7592b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7602b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7612b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7622b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7632b4ed282SShri Abhyankar 
7642b4ed282SShri Abhyankar   PetscFunctionBegin;
7659ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7669ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7679ce7406fSBarry Smith 
7682b4ed282SShri Abhyankar   snes->numFailures            = 0;
7692b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7702b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7712b4ed282SShri Abhyankar 
7722b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7732b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7742b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7752b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7762b4ed282SShri Abhyankar   G		= snes->work[1];
7772b4ed282SShri Abhyankar   W		= snes->work[2];
7782b4ed282SShri Abhyankar 
7792b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7802b4ed282SShri Abhyankar   snes->iter = 0;
7812b4ed282SShri Abhyankar   snes->norm = 0.0;
7822b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7832b4ed282SShri Abhyankar 
7847fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7852b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7862b4ed282SShri Abhyankar   if (snes->domainerror) {
7872b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7889ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7892b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7902b4ed282SShri Abhyankar   }
7912b4ed282SShri Abhyankar    /* Compute Merit function */
7922b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7932b4ed282SShri Abhyankar 
7942b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7952b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
79662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7972b4ed282SShri Abhyankar 
7982b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7992b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
8002b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
8027a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8032b4ed282SShri Abhyankar 
8042b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8052b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8062b4ed282SShri Abhyankar   /* test convergence */
8072b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8089ce7406fSBarry Smith   if (snes->reason) {
8099ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8109ce7406fSBarry Smith     PetscFunctionReturn(0);
8119ce7406fSBarry Smith   }
8122b4ed282SShri Abhyankar 
8132b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8142b4ed282SShri Abhyankar 
8152b4ed282SShri Abhyankar     /* Call general purpose update function */
8162b4ed282SShri Abhyankar     if (snes->ops->update) {
8172b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8182b4ed282SShri Abhyankar     }
8192b4ed282SShri Abhyankar 
8202b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
821a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8222b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
823a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
824a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
825a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
826a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
827ee657d29SShri Abhyankar     /* Compute the merit function gradient */
828ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8292b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8302b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8312b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8323b336b49SShri Abhyankar 
8333b336b49SShri Abhyankar     if (kspreason < 0) {
8342b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8352b4ed282SShri 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);
8362b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8372b4ed282SShri Abhyankar         break;
8382b4ed282SShri Abhyankar       }
8392b4ed282SShri Abhyankar     }
8402b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8412b4ed282SShri Abhyankar     snes->linear_its += lits;
8422b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8432b4ed282SShri Abhyankar     /*
8442b4ed282SShri Abhyankar     if (vi->precheckstep) {
845ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8462b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8472b4ed282SShri Abhyankar     }
8482b4ed282SShri Abhyankar 
8492b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8502b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8512b4ed282SShri Abhyankar     }
8522b4ed282SShri Abhyankar     */
8532b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8542b4ed282SShri Abhyankar          Y <- X - lambda*Y
8552b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8562b4ed282SShri Abhyankar     */
8572b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8582b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8592b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8602b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8612b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8622b4ed282SShri Abhyankar     if (snes->domainerror) {
8632b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8649ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8652b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8662b4ed282SShri Abhyankar     }
8672b4ed282SShri Abhyankar     if (!lssucceed) {
8682b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
869ace3abfcSBarry Smith 	PetscBool ismin;
8702b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8712b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8722b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8732b4ed282SShri Abhyankar         break;
8742b4ed282SShri Abhyankar       }
8752b4ed282SShri Abhyankar     }
8762b4ed282SShri Abhyankar     /* Update function and solution vectors */
8772b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8782b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8792b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8802b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8812b4ed282SShri Abhyankar     /* Monitor convergence */
8822b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8832b4ed282SShri Abhyankar     snes->iter = i+1;
8842b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8852b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8862b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8877a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8882b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8892b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8902b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8912b4ed282SShri Abhyankar     if (snes->reason) break;
8922b4ed282SShri Abhyankar   }
8932b4ed282SShri Abhyankar   if (i == maxits) {
8942b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8952b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8962b4ed282SShri Abhyankar   }
8979ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
8982b4ed282SShri Abhyankar   PetscFunctionReturn(0);
8992b4ed282SShri Abhyankar }
90069c03620SShri Abhyankar 
90169c03620SShri Abhyankar #undef __FUNCT__
902693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
903693ddf92SShri Abhyankar /*
904693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
905693ddf92SShri Abhyankar 
906693ddf92SShri Abhyankar    Input parameter
907693ddf92SShri Abhyankar .  snes - the SNES context
908693ddf92SShri Abhyankar .  X    - the snes solution vector
909693ddf92SShri Abhyankar .  F    - the nonlinear function vector
910693ddf92SShri Abhyankar 
911693ddf92SShri Abhyankar    Output parameter
912693ddf92SShri Abhyankar .  ISact - active set index set
913693ddf92SShri Abhyankar  */
914693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
915d950fb63SShri Abhyankar {
916d950fb63SShri Abhyankar   PetscErrorCode   ierr;
917693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
918693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
919693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
920693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
921d950fb63SShri Abhyankar 
922d950fb63SShri Abhyankar   PetscFunctionBegin;
923d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
924d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
925fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
926fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
927fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
928fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
929693ddf92SShri Abhyankar   /* Compute active set size */
930d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
93110f5ae6bSBarry 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++;
932d950fb63SShri Abhyankar   }
933693ddf92SShri Abhyankar 
934d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
935d950fb63SShri Abhyankar 
936693ddf92SShri Abhyankar   /* Set active set indices */
937d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
93810f5ae6bSBarry 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;
939d950fb63SShri Abhyankar   }
940d950fb63SShri Abhyankar 
941693ddf92SShri Abhyankar    /* Create active set IS */
94262298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
943d950fb63SShri Abhyankar 
944fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
945fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
946fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
947fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
948d950fb63SShri Abhyankar   PetscFunctionReturn(0);
949d950fb63SShri Abhyankar }
950d950fb63SShri Abhyankar 
951693ddf92SShri Abhyankar #undef __FUNCT__
952693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
953693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
954693ddf92SShri Abhyankar {
955693ddf92SShri Abhyankar   PetscErrorCode     ierr;
956693ddf92SShri Abhyankar 
957693ddf92SShri Abhyankar   PetscFunctionBegin;
958693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
959693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
960693ddf92SShri Abhyankar   PetscFunctionReturn(0);
961693ddf92SShri Abhyankar }
962693ddf92SShri Abhyankar 
963dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
964dbd914b8SShri Abhyankar #undef __FUNCT__
965fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
966fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
967dbd914b8SShri Abhyankar {
968dbd914b8SShri Abhyankar   PetscErrorCode ierr;
969dbd914b8SShri Abhyankar   Vec            v;
970dbd914b8SShri Abhyankar 
971dbd914b8SShri Abhyankar   PetscFunctionBegin;
972dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
973dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
974dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
975dbd914b8SShri Abhyankar   *newv = v;
976dbd914b8SShri Abhyankar 
977dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
978dbd914b8SShri Abhyankar }
979dbd914b8SShri Abhyankar 
980732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
981732bb160SShri Abhyankar #undef __FUNCT__
982732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
983732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
984732bb160SShri Abhyankar {
985732bb160SShri Abhyankar   PetscErrorCode         ierr;
986d0af7cd3SBarry Smith   KSP                    snesksp;
987dbd914b8SShri Abhyankar 
988732bb160SShri Abhyankar   PetscFunctionBegin;
989732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
990d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
991c2efdce3SBarry Smith 
992c2efdce3SBarry Smith   /*
993d0af7cd3SBarry Smith   KSP                    kspnew;
994d0af7cd3SBarry Smith   PC                     pcnew;
995d0af7cd3SBarry Smith   const MatSolverPackage stype;
996d0af7cd3SBarry Smith 
997c2efdce3SBarry Smith 
998732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
999732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
1000732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
1001732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
1002732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1003732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1004732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1005732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1006732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1007732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1008732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10096bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1010732bb160SShri Abhyankar   snes->ksp = kspnew;
1011732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1012d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1013732bb160SShri Abhyankar   PetscFunctionReturn(0);
1014732bb160SShri Abhyankar }
101569c03620SShri Abhyankar 
101669c03620SShri Abhyankar 
1017fe835674SShri Abhyankar #undef __FUNCT__
1018fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
101910f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1020fe835674SShri Abhyankar {
1021fe835674SShri Abhyankar   PetscErrorCode    ierr;
1022fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1023fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1024fe835674SShri Abhyankar   PetscInt          i,n;
1025fe835674SShri Abhyankar   PetscReal         rnorm;
1026fe835674SShri Abhyankar 
1027fe835674SShri Abhyankar   PetscFunctionBegin;
1028fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1029fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1030fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1031fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1032fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1033fe835674SShri Abhyankar   rnorm = 0.0;
1034fe835674SShri Abhyankar   for (i=0; i<n; i++) {
103510f5ae6bSBarry 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]);
1036fe835674SShri Abhyankar   }
1037fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1038fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1039fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1040fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1041d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1042fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1043fe835674SShri Abhyankar   PetscFunctionReturn(0);
1044fe835674SShri Abhyankar }
1045fe835674SShri Abhyankar 
1046fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1047c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1048c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1049d950fb63SShri Abhyankar #undef __FUNCT__
1050d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1051d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1052d950fb63SShri Abhyankar {
1053d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1054d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1055abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1056d950fb63SShri Abhyankar   PetscBool         lssucceed;
1057d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1058fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1059d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1060d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1061d950fb63SShri Abhyankar 
1062d950fb63SShri Abhyankar   PetscFunctionBegin;
1063d950fb63SShri Abhyankar   snes->numFailures            = 0;
1064d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1065d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1066d950fb63SShri Abhyankar 
1067d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1068d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1069d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1070d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1071d950fb63SShri Abhyankar   G		= snes->work[1];
1072d950fb63SShri Abhyankar   W		= snes->work[2];
1073d950fb63SShri Abhyankar 
1074d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1075d950fb63SShri Abhyankar   snes->iter = 0;
1076d950fb63SShri Abhyankar   snes->norm = 0.0;
1077d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1078d950fb63SShri Abhyankar 
10797fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1080fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1081d950fb63SShri Abhyankar   if (snes->domainerror) {
1082d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1083d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1084d950fb63SShri Abhyankar   }
1085fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1086d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1087d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
108862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1089d950fb63SShri Abhyankar 
1090d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1091fe835674SShri Abhyankar   snes->norm = fnorm;
1092d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1093fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10947a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1095d950fb63SShri Abhyankar 
1096d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1097fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1098d950fb63SShri Abhyankar   /* test convergence */
1099fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1100d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1101d950fb63SShri Abhyankar 
1102*9ce20c35SJungho Lee 
1103d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1104d950fb63SShri Abhyankar 
1105d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1106a6b72b01SJungho Lee     IS         IS_redact; /* redundant active 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 
1120*9ce20c35SJungho Lee 
1121*9ce20c35SJungho Lee     /* remove later */
1122*9ce20c35SJungho Lee     ierr = MatView(snes->jacobian,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1123*9ce20c35SJungho Lee 
1124d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1125a6b72b01SJungho Lee 
1126a6b72b01SJungho Lee     /*original
1127693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1128a6b72b01SJungho Lee      */
1129a6b72b01SJungho Lee     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
1130a6b72b01SJungho Lee 
1131a6b72b01SJungho Lee     if (vi->checkredundancy) {
1132a6b72b01SJungho Lee       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
1133ed70e96aSJungho Lee       if (IS_redact){
1134ed70e96aSJungho Lee         ierr = ISSort(IS_redact);CHKERRQ(ierr);
1135a6b72b01SJungho Lee         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1136a6b72b01SJungho Lee         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
1137ed70e96aSJungho Lee       }
1138ed70e96aSJungho Lee       else {
1139ed70e96aSJungho Lee         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1140ed70e96aSJungho Lee       }
1141a6b72b01SJungho Lee     } else {
1142a6b72b01SJungho Lee       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1143a6b72b01SJungho Lee     }
1144d950fb63SShri Abhyankar 
11454dcab191SBarry Smith 
1146abcba341SShri Abhyankar     /* Create inactive set submatrix */
114762298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1148a6b72b01SJungho Lee 
1149b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
1150*9ce20c35SJungho Lee     if (0 && keptrows) {
1151*9ce20c35SJungho Lee     // if (keptrows) {
115262298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
115362298a1eSBarry Smith       const PetscInt *krows,*inact;
115427d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
115562298a1eSBarry Smith 
11566bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11576bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
115862298a1eSBarry Smith 
115962298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
116062298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
116162298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
116262298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
116362298a1eSBarry Smith       for (k=0; k<cnt; k++) {
116427d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
116562298a1eSBarry Smith       }
116662298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
116762298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11686bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11696bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
117062298a1eSBarry Smith 
117127d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
117227d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
117362298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
117462298a1eSBarry Smith     }
1175*9ce20c35SJungho Lee     ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr);
1176*9ce20c35SJungho Lee     /* remove later */
1177*9ce20c35SJungho Lee 
1178*9ce20c35SJungho Lee     /*
1179*9ce20c35SJungho Lee   ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1180*9ce20c35SJungho Lee   ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1181*9ce20c35SJungho Lee   ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1182*9ce20c35SJungho Lee   ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1183*9ce20c35SJungho Lee   ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1184*9ce20c35SJungho Lee      */
118562298a1eSBarry Smith 
1186d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1187d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1188d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1189d950fb63SShri Abhyankar 
1190d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1191fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1192fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1193fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1194d950fb63SShri Abhyankar 
1195d950fb63SShri Abhyankar     /* Create scatter contexts */
1196d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1197d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1198d950fb63SShri Abhyankar 
1199d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1200fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1201fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1202d950fb63SShri Abhyankar 
1203d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1204d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1205d950fb63SShri Abhyankar 
1206d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1207d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1208d950fb63SShri Abhyankar 
1209d950fb63SShri Abhyankar     /* Active set direction = 0 */
1210d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1211d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1212d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1213d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1214d950fb63SShri Abhyankar 
1215abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1216abcba341SShri Abhyankar     if (!isequal) {
1217732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1218c58c0d17SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
1219d950fb63SShri Abhyankar     }
1220d950fb63SShri Abhyankar 
122113e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
122213e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
122313e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
122413e0d083SBarry Smith 
1225*9ce20c35SJungho Lee     /* remove later */
1226*9ce20c35SJungho Lee     ierr = MatView(jac_inact_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1227*9ce20c35SJungho Lee     ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
1228*9ce20c35SJungho Lee 
1229d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
123013e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
123113e0d083SBarry Smith     {
123213e0d083SBarry Smith       PC        pc;
123313e0d083SBarry Smith       PetscBool flg;
123413e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
123513e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
123613e0d083SBarry Smith       if (flg) {
123713e0d083SBarry Smith         KSP      *subksps;
123813e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
123913e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
124013e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
124113e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
124213e0d083SBarry Smith         if (flg) {
124313e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
124413e0d083SBarry Smith           const PetscInt *ii;
124513e0d083SBarry Smith 
124613e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
124713e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
124813e0d083SBarry Smith           for (j=0; j<n; j++) {
124913e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
125013e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
125113e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
125213e0d083SBarry Smith           }
125313e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
125413e0d083SBarry Smith 
125513e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
125613e0d083SBarry Smith         }
125713e0d083SBarry Smith       }
125813e0d083SBarry Smith     }
125913e0d083SBarry Smith 
1260fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1261d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1262d950fb63SShri Abhyankar     if (kspreason < 0) {
1263d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1264d950fb63SShri 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);
1265d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1266d950fb63SShri Abhyankar         break;
1267d950fb63SShri Abhyankar       }
1268d950fb63SShri Abhyankar      }
1269d950fb63SShri Abhyankar 
1270d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1271d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1272d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1273d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1274d950fb63SShri Abhyankar 
12756bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12766bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
12776bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
12786bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
12796bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
12806bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1281abcba341SShri Abhyankar     if (!isequal) {
12826bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1283abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1284abcba341SShri Abhyankar     }
12856bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
12866bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1287d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
12886bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1289d950fb63SShri Abhyankar     }
1290d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1291d950fb63SShri Abhyankar     snes->linear_its += lits;
1292d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1293d950fb63SShri Abhyankar     /*
1294d950fb63SShri Abhyankar     if (vi->precheckstep) {
1295d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1296d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1297d950fb63SShri Abhyankar     }
1298d950fb63SShri Abhyankar 
1299d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1300d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1301d950fb63SShri Abhyankar     }
1302d950fb63SShri Abhyankar     */
1303d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1304d950fb63SShri Abhyankar          Y <- X - lambda*Y
1305d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1306d950fb63SShri Abhyankar     */
1307d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1308fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1309fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1310fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
13112b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
13122b4ed282SShri Abhyankar     if (snes->domainerror) {
13132b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13144c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13152b4ed282SShri Abhyankar       PetscFunctionReturn(0);
13162b4ed282SShri Abhyankar     }
13172b4ed282SShri Abhyankar     if (!lssucceed) {
13182b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
13192b4ed282SShri Abhyankar 	PetscBool ismin;
13202b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
13212b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
13222b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
13232b4ed282SShri Abhyankar         break;
13242b4ed282SShri Abhyankar       }
13252b4ed282SShri Abhyankar     }
13262b4ed282SShri Abhyankar     /* Update function and solution vectors */
1327fe835674SShri Abhyankar     fnorm = gnorm;
1328fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
13292b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
13302b4ed282SShri Abhyankar     /* Monitor convergence */
13312b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13322b4ed282SShri Abhyankar     snes->iter = i+1;
1333fe835674SShri Abhyankar     snes->norm = fnorm;
13342b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13352b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
13367a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
13372b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
13382b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1339fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13402b4ed282SShri Abhyankar     if (snes->reason) break;
13412b4ed282SShri Abhyankar   }
13424c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13432b4ed282SShri Abhyankar   if (i == maxits) {
13442b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13452b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13462b4ed282SShri Abhyankar   }
13472b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13482b4ed282SShri Abhyankar }
13492b4ed282SShri Abhyankar 
13502f63a38cSShri Abhyankar #undef __FUNCT__
1351720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1352cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13532f63a38cSShri Abhyankar {
13542f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13552f63a38cSShri Abhyankar 
13562f63a38cSShri Abhyankar   PetscFunctionBegin;
13572f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13582f63a38cSShri Abhyankar   vi->checkredundancy = func;
1359cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13602f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13612f63a38cSShri Abhyankar }
13622f63a38cSShri Abhyankar 
1363ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1364ff596062SShri Abhyankar #include <engine.h>
1365ff596062SShri Abhyankar #include <mex.h>
1366cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1367ff596062SShri Abhyankar 
1368ff596062SShri Abhyankar #undef __FUNCT__
1369ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1370ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1371ff596062SShri Abhyankar {
1372ff596062SShri Abhyankar   PetscErrorCode      ierr;
1373cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1374cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1375cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1376cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1377fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1378ff596062SShri Abhyankar 
1379ff596062SShri Abhyankar   PetscFunctionBegin;
1380ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1381ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1382ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1383ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1384ff596062SShri Abhyankar 
138509db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
138609db5ad8SShri Abhyankar    bet set by the Matlab function */
1387fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1388cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1389ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1390ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1391cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1392ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1393ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1394cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1395cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1396cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1397ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1398ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1399ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1400ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1401ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1402ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1403ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1404ff596062SShri Abhyankar   PetscFunctionReturn(0);
1405ff596062SShri Abhyankar }
1406ff596062SShri Abhyankar 
1407ff596062SShri Abhyankar #undef __FUNCT__
1408ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1409ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1410ff596062SShri Abhyankar {
1411ff596062SShri Abhyankar   PetscErrorCode      ierr;
1412cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1413ff596062SShri Abhyankar 
1414ff596062SShri Abhyankar   PetscFunctionBegin;
1415ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1416cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1417ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1418ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1419cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1420ff596062SShri Abhyankar   PetscFunctionReturn(0);
1421ff596062SShri Abhyankar }
1422ff596062SShri Abhyankar 
1423ff596062SShri Abhyankar #endif
1424ff596062SShri Abhyankar 
1425ff596062SShri Abhyankar 
14262f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
14272f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1428720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
142956a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
143056a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
14312f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
14322f63a38cSShri Abhyankar */
14332f63a38cSShri Abhyankar #undef __FUNCT__
1434b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1435b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
14362f63a38cSShri Abhyankar {
14372f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
14382f63a38cSShri Abhyankar   PetscErrorCode    ierr;
14392f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
14402f63a38cSShri Abhyankar   PetscBool         lssucceed;
14412f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
14422f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14432f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14442f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14452f63a38cSShri Abhyankar 
14462f63a38cSShri Abhyankar   PetscFunctionBegin;
14472f63a38cSShri Abhyankar   snes->numFailures            = 0;
14482f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14492f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14502f63a38cSShri Abhyankar 
14512f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14522f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14532f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14542f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14552f63a38cSShri Abhyankar   G		= snes->work[1];
14562f63a38cSShri Abhyankar   W		= snes->work[2];
14572f63a38cSShri Abhyankar 
14582f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14592f63a38cSShri Abhyankar   snes->iter = 0;
14602f63a38cSShri Abhyankar   snes->norm = 0.0;
14612f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14622f63a38cSShri Abhyankar 
14632f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14642f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14652f63a38cSShri Abhyankar   if (snes->domainerror) {
14662f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14672f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14682f63a38cSShri Abhyankar   }
14692f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14702f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14712f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
147262cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14732f63a38cSShri Abhyankar 
14742f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14752f63a38cSShri Abhyankar   snes->norm = fnorm;
14762f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14772f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
14787a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
14792f63a38cSShri Abhyankar 
14802f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
14812f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
14822f63a38cSShri Abhyankar   /* test convergence */
14832f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
14842f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
14852f63a38cSShri Abhyankar 
14862f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
14872f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1488cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
148956a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
149056a221efSShri Abhyankar     Vec            F_aug,Y_aug;
149156a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
149256a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
149356a221efSShri Abhyankar     PetscInt       k;
149463ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
149556a221efSShri Abhyankar     PetscScalar    *f,*f2;
14962f63a38cSShri Abhyankar     PetscBool      isequal;
149756a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
14982f63a38cSShri Abhyankar 
14992f63a38cSShri Abhyankar     /* Call general purpose update function */
15002f63a38cSShri Abhyankar     if (snes->ops->update) {
15012f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
15022f63a38cSShri Abhyankar     }
15032f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
15042f63a38cSShri Abhyankar 
15052f63a38cSShri Abhyankar     /* Create active and inactive index sets */
15062f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
15072f63a38cSShri Abhyankar 
150856a221efSShri Abhyankar     /* Get local active set size */
15092f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
151056a221efSShri Abhyankar     if (nis_act) {
1511e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1512e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
151356a221efSShri Abhyankar       if(vi->checkredundancy) {
1514cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
151556a221efSShri Abhyankar       }
15162f63a38cSShri Abhyankar 
151756a221efSShri Abhyankar       if(!IS_redact) {
151856a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
151956a221efSShri Abhyankar            there were no redundant active set variables */
152056a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
152156a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
152256a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
152356a221efSShri Abhyankar 	nkept = nis_act;
152456a221efSShri Abhyankar       } else {
152556a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
152656a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
15272f63a38cSShri Abhyankar 
152856a221efSShri Abhyankar 	/* Create reduced active set list */
152956a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
153056a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1531cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
153256a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
153356a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
153456a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
153556a221efSShri Abhyankar 	}
153656a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
153756a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1538cb5fe31bSShri Abhyankar 
1539cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
154056a221efSShri Abhyankar       }
15412f63a38cSShri Abhyankar 
154256a221efSShri Abhyankar       /* Create augmented F and Y */
154356a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
154456a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
154556a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
154656a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15472f63a38cSShri Abhyankar 
154856a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
154956a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
155056a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
155156a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
155256a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
155356a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15542f63a38cSShri Abhyankar 
155556a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
155656a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
155756a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
155856a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15592f63a38cSShri Abhyankar 
156056a221efSShri Abhyankar 
15619521db3cSSatish Balay       { /* local vars */
1562493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
156356a221efSShri Abhyankar       PetscInt          ncols;
156456a221efSShri Abhyankar       const PetscInt    *cols;
156556a221efSShri Abhyankar       const PetscScalar *vals;
15662969f145SShri Abhyankar       PetscScalar        value[2];
15672969f145SShri Abhyankar       PetscInt           row,col[2];
1568493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15692969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1570493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1571493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1572493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1573493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1574493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1575493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1576493a4f3dSShri Abhyankar       }
1577493a4f3dSShri Abhyankar 
1578493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1579493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
15802969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1581493a4f3dSShri Abhyankar       }
1582493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1583493a4f3dSShri Abhyankar 
1584493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
158556a221efSShri Abhyankar 
158656a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
158756a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
158856a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
158956a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
159056a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
159156a221efSShri Abhyankar       }
159256a221efSShri Abhyankar       /* Add the augmented part */
159356a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
15942969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
15952969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
15962969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
15972969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
159856a221efSShri Abhyankar       }
159956a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160056a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
160156a221efSShri Abhyankar       /* Only considering prejac = jac for now */
160256a221efSShri Abhyankar       Jpre_aug = J_aug;
16039521db3cSSatish Balay       } /* local vars*/
1604e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1605e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
160656a221efSShri Abhyankar     } else {
160756a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
160856a221efSShri Abhyankar     }
16092f63a38cSShri Abhyankar 
16102f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
16112f63a38cSShri Abhyankar     if (!isequal) {
161256a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
16132f63a38cSShri Abhyankar     }
161456a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
16152f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
161656a221efSShri Abhyankar     /*  {
16172f63a38cSShri Abhyankar       PC        pc;
16182f63a38cSShri Abhyankar       PetscBool flg;
16192f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
16202f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
16212f63a38cSShri Abhyankar       if (flg) {
16222f63a38cSShri Abhyankar         KSP      *subksps;
16232f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
16242f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
16252f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
16262f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
16272f63a38cSShri Abhyankar         if (flg) {
16282f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
16292f63a38cSShri Abhyankar           const PetscInt *ii;
16302f63a38cSShri Abhyankar 
16312f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
16322f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
16332f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
16342f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
16352f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
16362f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
16372f63a38cSShri Abhyankar           }
16382f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
16392f63a38cSShri Abhyankar 
16402f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
16412f63a38cSShri Abhyankar         }
16422f63a38cSShri Abhyankar       }
16432f63a38cSShri Abhyankar     }
164456a221efSShri Abhyankar     */
164556a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16462f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16472f63a38cSShri Abhyankar     if (kspreason < 0) {
16482f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16492f63a38cSShri 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);
16502f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16512f63a38cSShri Abhyankar         break;
16522f63a38cSShri Abhyankar       }
16532f63a38cSShri Abhyankar     }
16542f63a38cSShri Abhyankar 
165556a221efSShri Abhyankar     if(nis_act) {
165656a221efSShri Abhyankar       PetscScalar *y1,*y2;
165756a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
165856a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
165956a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
166056a221efSShri Abhyankar       j1 = 0;
166156a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
166256a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
166356a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
166456a221efSShri Abhyankar       }
166556a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
166656a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16672f63a38cSShri Abhyankar 
16686bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16696bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16706bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
167156a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
167256a221efSShri Abhyankar     }
167356a221efSShri Abhyankar 
16742f63a38cSShri Abhyankar     if (!isequal) {
16756bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16762f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
16772f63a38cSShri Abhyankar     }
16786bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
167956a221efSShri Abhyankar 
16802f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
16812f63a38cSShri Abhyankar     snes->linear_its += lits;
16822f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
16832f63a38cSShri Abhyankar     /*
16842f63a38cSShri Abhyankar     if (vi->precheckstep) {
16852f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
16862f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
16872f63a38cSShri Abhyankar     }
16882f63a38cSShri Abhyankar 
16892f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
16902f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
16912f63a38cSShri Abhyankar     }
16922f63a38cSShri Abhyankar     */
16932f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
16942f63a38cSShri Abhyankar          Y <- X - lambda*Y
16952f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
16962f63a38cSShri Abhyankar     */
16972f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
16982f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
16992f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
17002f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
17012f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
17022f63a38cSShri Abhyankar     if (snes->domainerror) {
17032f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
17042f63a38cSShri Abhyankar       PetscFunctionReturn(0);
17052f63a38cSShri Abhyankar     }
17062f63a38cSShri Abhyankar     if (!lssucceed) {
17072f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
17082f63a38cSShri Abhyankar 	PetscBool ismin;
17092f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
17102f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
17112f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
17122f63a38cSShri Abhyankar         break;
17132f63a38cSShri Abhyankar       }
17142f63a38cSShri Abhyankar     }
17152f63a38cSShri Abhyankar     /* Update function and solution vectors */
17162f63a38cSShri Abhyankar     fnorm = gnorm;
17172f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
17182f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
17192f63a38cSShri Abhyankar     /* Monitor convergence */
17202f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
17212f63a38cSShri Abhyankar     snes->iter = i+1;
17222f63a38cSShri Abhyankar     snes->norm = fnorm;
17232f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
17242f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
17257a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
17262f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
17272f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
17282f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
17292f63a38cSShri Abhyankar     if (snes->reason) break;
17302f63a38cSShri Abhyankar   }
17312f63a38cSShri Abhyankar   if (i == maxits) {
17322f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
17332f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
17342f63a38cSShri Abhyankar   }
17352f63a38cSShri Abhyankar   PetscFunctionReturn(0);
17362f63a38cSShri Abhyankar }
17372f63a38cSShri Abhyankar 
17382b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17392b4ed282SShri Abhyankar /*
17402b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
17412b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
17422b4ed282SShri Abhyankar 
17432b4ed282SShri Abhyankar    Input Parameter:
17442b4ed282SShri Abhyankar .  snes - the SNES context
17452b4ed282SShri Abhyankar .  x - the solution vector
17462b4ed282SShri Abhyankar 
17472b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17482b4ed282SShri Abhyankar 
17492b4ed282SShri Abhyankar    Notes:
17502b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17512b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17522b4ed282SShri Abhyankar    the call to SNESSolve().
17532b4ed282SShri Abhyankar  */
17542b4ed282SShri Abhyankar #undef __FUNCT__
17552b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17562b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17572b4ed282SShri Abhyankar {
17582b4ed282SShri Abhyankar   PetscErrorCode ierr;
17592b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17602b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17612b4ed282SShri Abhyankar 
17622b4ed282SShri Abhyankar   PetscFunctionBegin;
176358c9b817SLisandro Dalcin 
176458c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17652b4ed282SShri Abhyankar 
17662176524cSBarry Smith   if (vi->computevariablebounds) {
176777cdaf69SJed Brown     if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);}
176877cdaf69SJed Brown     if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);}
176977cdaf69SJed Brown     ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr);
17702176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
17712176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
17722b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
177301f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17742b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
177501f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17762b4ed282SShri Abhyankar   } else {
17772b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
17782b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
17792b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
17802b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
17812b4ed282SShri 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]))
17822b4ed282SShri 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.");
17832b4ed282SShri Abhyankar   }
17842f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1785abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1786abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1787abcba341SShri Abhyankar     PetscInt *indices;
1788abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1789abcba341SShri Abhyankar 
1790abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1791abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1792abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1793abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1794abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1795abcba341SShri Abhyankar   }
17962b4ed282SShri Abhyankar 
17972f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1798fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1799fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1800fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1801fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1802fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1803fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1804fe835674SShri Abhyankar   }
18052b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18062b4ed282SShri Abhyankar }
18072b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18082176524cSBarry Smith #undef __FUNCT__
18092176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
18102176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
18112176524cSBarry Smith {
18122176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
18132176524cSBarry Smith   PetscErrorCode ierr;
18142176524cSBarry Smith 
18152176524cSBarry Smith   PetscFunctionBegin;
18162176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
18172176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1818d655a5daSBarry Smith   if (snes->ops->solve != SNESSolveVI_SS) {
1819d655a5daSBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1820d655a5daSBarry Smith   }
18212176524cSBarry Smith   PetscFunctionReturn(0);
18222176524cSBarry Smith }
18232176524cSBarry Smith 
18242b4ed282SShri Abhyankar /*
18252b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
18262b4ed282SShri Abhyankar    with SNESCreate_VI().
18272b4ed282SShri Abhyankar 
18282b4ed282SShri Abhyankar    Input Parameter:
18292b4ed282SShri Abhyankar .  snes - the SNES context
18302b4ed282SShri Abhyankar 
18312b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
18322b4ed282SShri Abhyankar  */
18332b4ed282SShri Abhyankar #undef __FUNCT__
18342b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
18352b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
18362b4ed282SShri Abhyankar {
18372b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
18382b4ed282SShri Abhyankar   PetscErrorCode ierr;
18392b4ed282SShri Abhyankar 
18402b4ed282SShri Abhyankar   PetscFunctionBegin;
18412b4ed282SShri Abhyankar 
18422f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18432b4ed282SShri Abhyankar     /* clear vectors */
18446bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18456bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18466bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18476bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18486bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18496bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18507fe79bc4SShri Abhyankar   }
18517fe79bc4SShri Abhyankar 
1852649052a6SBarry Smith   ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
18532b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18542b4ed282SShri Abhyankar 
18552b4ed282SShri Abhyankar   /* clear composed functions */
18562b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1857c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18582b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18592b4ed282SShri Abhyankar }
18607fe79bc4SShri Abhyankar 
18612b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18622b4ed282SShri Abhyankar #undef __FUNCT__
18632b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18642b4ed282SShri Abhyankar 
18652b4ed282SShri Abhyankar /*
18667fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18677fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18682b4ed282SShri Abhyankar 
18692b4ed282SShri Abhyankar */
1870ace3abfcSBarry 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)
18712b4ed282SShri Abhyankar {
18722b4ed282SShri Abhyankar   PetscErrorCode ierr;
18732b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1874ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18752b4ed282SShri Abhyankar 
18762b4ed282SShri Abhyankar   PetscFunctionBegin;
18772b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18782b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18792b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
18802b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1881c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1882c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1883c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1884c1a5e521SShri Abhyankar   }
1885c1a5e521SShri Abhyankar   if (changed_y) {
1886c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18877fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1888c1a5e521SShri Abhyankar   }
1889c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1890c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1891c1a5e521SShri Abhyankar   if (!snes->domainerror) {
18922f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
18937fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
18947fe79bc4SShri Abhyankar     } else {
1895c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
18967fe79bc4SShri Abhyankar     }
189762cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1898c1a5e521SShri Abhyankar   }
1899c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1900649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1901649052a6SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1902649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1903c1a5e521SShri Abhyankar   }
1904c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1905c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1906c1a5e521SShri Abhyankar }
1907c1a5e521SShri Abhyankar 
1908c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1909c1a5e521SShri Abhyankar #undef __FUNCT__
19102b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
19112b4ed282SShri Abhyankar 
19122b4ed282SShri Abhyankar /*
19132b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
19142b4ed282SShri Abhyankar */
1915ace3abfcSBarry 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)
19162b4ed282SShri Abhyankar {
19172b4ed282SShri Abhyankar   PetscErrorCode ierr;
19182b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1919ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
19202b4ed282SShri Abhyankar 
19212b4ed282SShri Abhyankar   PetscFunctionBegin;
19222b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
19232b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19242b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
19257fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19262b4ed282SShri Abhyankar   if (vi->postcheckstep) {
19272b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
19282b4ed282SShri Abhyankar   }
19292b4ed282SShri Abhyankar   if (changed_y) {
19302b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19317fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19322b4ed282SShri Abhyankar   }
19332b4ed282SShri Abhyankar 
19342b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
19352b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
19362b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19372b4ed282SShri Abhyankar   }
19382b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19392b4ed282SShri Abhyankar   PetscFunctionReturn(0);
19402b4ed282SShri Abhyankar }
19417fe79bc4SShri Abhyankar 
19422b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
19432b4ed282SShri Abhyankar #undef __FUNCT__
19442b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19452b4ed282SShri Abhyankar /*
19467fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19472b4ed282SShri Abhyankar */
1948ace3abfcSBarry 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)
19492b4ed282SShri Abhyankar {
1950fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1951fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1952fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1953fe835674SShri Abhyankar   PetscScalar    cinitslope;
1954fe835674SShri Abhyankar #endif
1955fe835674SShri Abhyankar   PetscErrorCode ierr;
1956fe835674SShri Abhyankar   PetscInt       count;
1957fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1958fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1959fe835674SShri Abhyankar   MPI_Comm       comm;
1960fe835674SShri Abhyankar 
1961fe835674SShri Abhyankar   PetscFunctionBegin;
1962fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1963fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1964fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1965fe835674SShri Abhyankar 
1966fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1967fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1968fe835674SShri Abhyankar     if (vi->lsmonitor) {
1969649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1970649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1971649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1972fe835674SShri Abhyankar     }
1973fe835674SShri Abhyankar     *gnorm = fnorm;
1974fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1975fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1976fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1977fe835674SShri Abhyankar     goto theend1;
1978fe835674SShri Abhyankar   }
1979fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1980fe835674SShri Abhyankar     if (vi->lsmonitor) {
1981649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1982649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1983649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1984fe835674SShri Abhyankar     }
1985fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1986fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1987fe835674SShri Abhyankar   }
1988fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1989fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1990fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1991fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1992fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1993fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1994fe835674SShri Abhyankar #else
1995fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1996fe835674SShri Abhyankar #endif
1997fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1998fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1999fe835674SShri Abhyankar 
2000fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2001fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2002fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2003fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
2004fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2005fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2006fe835674SShri Abhyankar     goto theend1;
2007fe835674SShri Abhyankar   }
2008fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20092f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2010fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20117fe79bc4SShri Abhyankar   } else {
20127fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20137fe79bc4SShri Abhyankar   }
2014fe835674SShri Abhyankar   if (snes->domainerror) {
2015fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2016fe835674SShri Abhyankar     PetscFunctionReturn(0);
2017fe835674SShri Abhyankar   }
201862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2019ed70e96aSJungho Lee   ierr = PetscInfo4(snes,"Initial fnorm %G gnorm %G alpha %G initslope %G\n",fnorm,*gnorm,vi->alpha,initslope);CHKERRQ(ierr);
2020f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm ) { /* Sufficient reduction */
2021fe835674SShri Abhyankar     if (vi->lsmonitor) {
2022649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2023649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
2024649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2025fe835674SShri Abhyankar     }
2026fe835674SShri Abhyankar     goto theend1;
2027fe835674SShri Abhyankar   }
2028fe835674SShri Abhyankar 
2029fe835674SShri Abhyankar   /* Fit points with quadratic */
2030fe835674SShri Abhyankar   lambda     = 1.0;
2031fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
2032fe835674SShri Abhyankar   lambdaprev = lambda;
2033fe835674SShri Abhyankar   gnormprev  = *gnorm;
2034fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2035fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
2036fe835674SShri Abhyankar   else                         lambda = lambdatemp;
2037fe835674SShri Abhyankar 
2038fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2039fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2040fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2041fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
2042fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2043fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2044fe835674SShri Abhyankar     goto theend1;
2045fe835674SShri Abhyankar   }
2046fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20472f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2048fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20497fe79bc4SShri Abhyankar   } else {
20507fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20517fe79bc4SShri Abhyankar   }
2052fe835674SShri Abhyankar   if (snes->domainerror) {
2053fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2054fe835674SShri Abhyankar     PetscFunctionReturn(0);
2055fe835674SShri Abhyankar   }
205662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2057fe835674SShri Abhyankar   if (vi->lsmonitor) {
2058649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2059649052a6SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
2060649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2061fe835674SShri Abhyankar   }
2062f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm ) { /* sufficient reduction */
2063fe835674SShri Abhyankar     if (vi->lsmonitor) {
2064649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2065649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
2066649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2067fe835674SShri Abhyankar     }
2068fe835674SShri Abhyankar     goto theend1;
2069fe835674SShri Abhyankar   }
2070fe835674SShri Abhyankar 
2071fe835674SShri Abhyankar   /* Fit points with cubic */
2072fe835674SShri Abhyankar   count = 1;
2073fe835674SShri Abhyankar   while (PETSC_TRUE) {
2074fe835674SShri Abhyankar     if (lambda <= minlambda) {
2075fe835674SShri Abhyankar       if (vi->lsmonitor) {
2076649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2077649052a6SBarry Smith  	ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
2078649052a6SBarry Smith 	ierr = PetscViewerASCIIPrintf(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);
2079649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2080fe835674SShri Abhyankar       }
2081fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2082fe835674SShri Abhyankar       break;
2083fe835674SShri Abhyankar     }
2084fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2085fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2086fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2087fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2088fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2089fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2090fe835674SShri Abhyankar     if (a == 0.0) {
2091fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2092fe835674SShri Abhyankar     } else {
2093fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2094fe835674SShri Abhyankar     }
2095fe835674SShri Abhyankar     lambdaprev = lambda;
2096fe835674SShri Abhyankar     gnormprev  = *gnorm;
2097fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2098fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2099fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2100fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2101fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2102fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2103fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2104fe835674SShri 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);
2105fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2106fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2107fe835674SShri Abhyankar       break;
2108fe835674SShri Abhyankar     }
2109fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21102f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2111fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21127fe79bc4SShri Abhyankar     } else {
21137fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21147fe79bc4SShri Abhyankar     }
2115fe835674SShri Abhyankar     if (snes->domainerror) {
2116fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2117fe835674SShri Abhyankar       PetscFunctionReturn(0);
2118fe835674SShri Abhyankar     }
211962cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2120f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* is reduction enough? */
2121fe835674SShri Abhyankar       if (vi->lsmonitor) {
2122fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2123fe835674SShri Abhyankar       }
2124fe835674SShri Abhyankar       break;
2125fe835674SShri Abhyankar     } else {
2126fe835674SShri Abhyankar       if (vi->lsmonitor) {
2127fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2128fe835674SShri Abhyankar       }
2129fe835674SShri Abhyankar     }
2130fe835674SShri Abhyankar     count++;
2131fe835674SShri Abhyankar   }
2132fe835674SShri Abhyankar   theend1:
2133fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2134fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2135fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2136fe835674SShri Abhyankar     if (changed_y) {
2137fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2138fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2139fe835674SShri Abhyankar     }
2140fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2141fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21422f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2143fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21447fe79bc4SShri Abhyankar       } else {
21457fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21467fe79bc4SShri Abhyankar       }
2147fe835674SShri Abhyankar       if (snes->domainerror) {
2148fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2149fe835674SShri Abhyankar         PetscFunctionReturn(0);
2150fe835674SShri Abhyankar       }
215162cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2152fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2153fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2154fe835674SShri Abhyankar     }
2155fe835674SShri Abhyankar   }
2156fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2157fe835674SShri Abhyankar   PetscFunctionReturn(0);
2158fe835674SShri Abhyankar }
2159fe835674SShri Abhyankar 
21602b4ed282SShri Abhyankar #undef __FUNCT__
21612b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21622b4ed282SShri Abhyankar /*
21637fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21642b4ed282SShri Abhyankar */
2165ace3abfcSBarry 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)
21662b4ed282SShri Abhyankar {
21672b4ed282SShri Abhyankar   /*
21682b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21692b4ed282SShri Abhyankar      minimization problem:
21702b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21712b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
21722b4ed282SShri Abhyankar    */
21732b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
21742b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21752b4ed282SShri Abhyankar   PetscScalar    cinitslope;
21762b4ed282SShri Abhyankar #endif
21772b4ed282SShri Abhyankar   PetscErrorCode ierr;
21782b4ed282SShri Abhyankar   PetscInt       count;
21792b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2180ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
21812b4ed282SShri Abhyankar 
21822b4ed282SShri Abhyankar   PetscFunctionBegin;
21832b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21842b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
21852b4ed282SShri Abhyankar 
21862b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
21872b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2188c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2189649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2190649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
2191649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
21922b4ed282SShri Abhyankar     }
21932b4ed282SShri Abhyankar     *gnorm = fnorm;
21942b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
21952b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
21962b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
21972b4ed282SShri Abhyankar     goto theend2;
21982b4ed282SShri Abhyankar   }
21992b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
22002b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
22012b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
22022b4ed282SShri Abhyankar   }
22032b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
22042b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
22057fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
22062b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
22077fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
22082b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
22092b4ed282SShri Abhyankar #else
22107fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
22112b4ed282SShri Abhyankar #endif
22122b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
22132b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
22142b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
22152b4ed282SShri Abhyankar 
22162b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22177fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22182b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
22192b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
22202b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
22212b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22222b4ed282SShri Abhyankar     goto theend2;
22232b4ed282SShri Abhyankar   }
22242b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22252f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
22267fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22277fe79bc4SShri Abhyankar   } else {
22287fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22297fe79bc4SShri Abhyankar   }
22302b4ed282SShri Abhyankar   if (snes->domainerror) {
22312b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22322b4ed282SShri Abhyankar     PetscFunctionReturn(0);
22332b4ed282SShri Abhyankar   }
223462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2235f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm) { /* Sufficient reduction */
2236c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2237649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2238649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
2239649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22402b4ed282SShri Abhyankar     }
22412b4ed282SShri Abhyankar     goto theend2;
22422b4ed282SShri Abhyankar   }
22432b4ed282SShri Abhyankar 
22442b4ed282SShri Abhyankar   /* Fit points with quadratic */
22452b4ed282SShri Abhyankar   lambda = 1.0;
22462b4ed282SShri Abhyankar   count = 1;
22472b4ed282SShri Abhyankar   while (PETSC_TRUE) {
22482b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2249c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2250649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2251649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2252649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr);
2253649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22542b4ed282SShri Abhyankar       }
22552b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
22562b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22572b4ed282SShri Abhyankar       break;
22582b4ed282SShri Abhyankar     }
22592b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
22602b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
22612b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
22622b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22632b4ed282SShri Abhyankar 
22642b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22657fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22662b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22672b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
22682b4ed282SShri 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);
22692b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22702b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22712b4ed282SShri Abhyankar       break;
22722b4ed282SShri Abhyankar     }
22732b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22742b4ed282SShri Abhyankar     if (snes->domainerror) {
22752b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22762b4ed282SShri Abhyankar       PetscFunctionReturn(0);
22772b4ed282SShri Abhyankar     }
22782f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
22797fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22807fe79bc4SShri Abhyankar     } else {
22812b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22827fe79bc4SShri Abhyankar     }
228362cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2284f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* sufficient reduction */
2285c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2286649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2287649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
2288649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22892b4ed282SShri Abhyankar       }
22902b4ed282SShri Abhyankar       break;
22912b4ed282SShri Abhyankar     }
22922b4ed282SShri Abhyankar     count++;
22932b4ed282SShri Abhyankar   }
22942b4ed282SShri Abhyankar   theend2:
22952b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
22962b4ed282SShri Abhyankar   if (vi->postcheckstep) {
22972b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
22982b4ed282SShri Abhyankar     if (changed_y) {
22992b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
23007fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
23012b4ed282SShri Abhyankar     }
23022b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
23032b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
23042b4ed282SShri Abhyankar       if (snes->domainerror) {
23052b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23062b4ed282SShri Abhyankar         PetscFunctionReturn(0);
23072b4ed282SShri Abhyankar       }
23082f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
23097fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
23107fe79bc4SShri Abhyankar       } else {
23117fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
23127fe79bc4SShri Abhyankar       }
23137fe79bc4SShri Abhyankar 
23142b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
23152b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
231662cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
23172b4ed282SShri Abhyankar     }
23182b4ed282SShri Abhyankar   }
23192b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23202b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23212b4ed282SShri Abhyankar }
23222b4ed282SShri Abhyankar 
2323ace3abfcSBarry 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*/
23242b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23252b4ed282SShri Abhyankar EXTERN_C_BEGIN
23262b4ed282SShri Abhyankar #undef __FUNCT__
23272b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
23287087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
23292b4ed282SShri Abhyankar {
23302b4ed282SShri Abhyankar   PetscFunctionBegin;
23312b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
23322b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
23332b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23342b4ed282SShri Abhyankar }
23352b4ed282SShri Abhyankar EXTERN_C_END
23362b4ed282SShri Abhyankar 
23372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23382b4ed282SShri Abhyankar EXTERN_C_BEGIN
23392b4ed282SShri Abhyankar #undef __FUNCT__
23402b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
23417087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
23422b4ed282SShri Abhyankar {
23432b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
23442b4ed282SShri Abhyankar   PetscErrorCode ierr;
23452b4ed282SShri Abhyankar 
23462b4ed282SShri Abhyankar   PetscFunctionBegin;
2347c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2348649052a6SBarry Smith     ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr);
2349c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
2350649052a6SBarry Smith     ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
23512b4ed282SShri Abhyankar   }
23522b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23532b4ed282SShri Abhyankar }
23542b4ed282SShri Abhyankar EXTERN_C_END
23552b4ed282SShri Abhyankar 
23562b4ed282SShri Abhyankar /*
23572b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
23582b4ed282SShri Abhyankar 
23592b4ed282SShri Abhyankar    Input Parameters:
23602b4ed282SShri Abhyankar .  SNES - the SNES context
23612b4ed282SShri Abhyankar .  viewer - visualization context
23622b4ed282SShri Abhyankar 
23632b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
23642b4ed282SShri Abhyankar */
23652b4ed282SShri Abhyankar #undef __FUNCT__
23662b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23672b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23682b4ed282SShri Abhyankar {
23692b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
237078c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23712b4ed282SShri Abhyankar   PetscErrorCode ierr;
2372ace3abfcSBarry Smith   PetscBool     iascii;
23732b4ed282SShri Abhyankar 
23742b4ed282SShri Abhyankar   PetscFunctionBegin;
23752b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23762b4ed282SShri Abhyankar   if (iascii) {
23772b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
23782b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
23792b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
23802b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
238178c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
23820a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2383b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
238478c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
238578c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
23862b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
23872b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
23882b4ed282SShri Abhyankar   }
23892b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23902b4ed282SShri Abhyankar }
23912b4ed282SShri Abhyankar 
23925559b345SBarry Smith #undef __FUNCT__
23935559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
23945559b345SBarry Smith /*@
23952b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
23962b4ed282SShri Abhyankar 
23972b4ed282SShri Abhyankar    Input Parameters:
23982b4ed282SShri Abhyankar .  snes - the SNES context.
23992b4ed282SShri Abhyankar .  xl   - lower bound.
24002b4ed282SShri Abhyankar .  xu   - upper bound.
24012b4ed282SShri Abhyankar 
24022b4ed282SShri Abhyankar    Notes:
24032b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
240401f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
240584c105d7SBarry Smith 
24065559b345SBarry Smith @*/
240769c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
24082b4ed282SShri Abhyankar {
2409d923200aSJungho Lee   SNES_VI        *vi;
2410d923200aSJungho Lee   PetscErrorCode ierr;
24112b4ed282SShri Abhyankar 
24122b4ed282SShri Abhyankar   PetscFunctionBegin;
24132b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
24142b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
24152b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
24162b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
24172b4ed282SShri 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);
24182b4ed282SShri 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);
2419d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2420d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
24212176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
24222176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
24232176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
24242176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
24252b4ed282SShri Abhyankar   vi->xl = xl;
24262b4ed282SShri Abhyankar   vi->xu = xu;
24272b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24282b4ed282SShri Abhyankar }
2429693ddf92SShri Abhyankar 
24302b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24312b4ed282SShri Abhyankar /*
24322b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
24332b4ed282SShri Abhyankar 
24342b4ed282SShri Abhyankar    Input Parameter:
24352b4ed282SShri Abhyankar .  snes - the SNES context
24362b4ed282SShri Abhyankar 
24372b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
24382b4ed282SShri Abhyankar */
24392b4ed282SShri Abhyankar #undef __FUNCT__
24402b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
24412b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
24422b4ed282SShri Abhyankar {
24432b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
24447fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2445b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
24462b4ed282SShri Abhyankar   PetscErrorCode ierr;
24472b4ed282SShri Abhyankar   PetscInt       indx;
244869c03620SShri Abhyankar   PetscBool      flg,set,flg2;
24492b4ed282SShri Abhyankar 
24502b4ed282SShri Abhyankar   PetscFunctionBegin;
24512b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
24529308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
24539308c137SBarry Smith   if (flg) {
24549308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
24559308c137SBarry Smith   }
2456be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2457be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2458be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
24592b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2460be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
24612b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
24622f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
246369c03620SShri Abhyankar   if (flg2) {
246469c03620SShri Abhyankar     switch (indx) {
246569c03620SShri Abhyankar     case 0:
246669c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
246769c03620SShri Abhyankar       break;
246869c03620SShri Abhyankar     case 1:
2469d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2470d950fb63SShri Abhyankar       break;
24712f63a38cSShri Abhyankar     case 2:
2472b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
247369c03620SShri Abhyankar     }
247469c03620SShri Abhyankar   }
2475f2b03b96SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"cubic",&indx,&flg);CHKERRQ(ierr);
24762b4ed282SShri Abhyankar   if (flg) {
24772b4ed282SShri Abhyankar     switch (indx) {
24782b4ed282SShri Abhyankar     case 0:
24792b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
24802b4ed282SShri Abhyankar       break;
24812b4ed282SShri Abhyankar     case 1:
24822b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
24832b4ed282SShri Abhyankar       break;
24842b4ed282SShri Abhyankar     case 2:
24852b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
24862b4ed282SShri Abhyankar       break;
24872b4ed282SShri Abhyankar     case 3:
24882b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
24892b4ed282SShri Abhyankar       break;
24902b4ed282SShri Abhyankar     }
2491fe835674SShri Abhyankar   }
24922b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
24932b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24942b4ed282SShri Abhyankar }
24952b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24962b4ed282SShri Abhyankar /*MC
24978b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
24982b4ed282SShri Abhyankar 
24992b4ed282SShri Abhyankar    Options Database:
25008b4c83edSBarry 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
25018b4c83edSBarry Smith                                 additional variables that enforce the constraints
25028b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
25032b4ed282SShri Abhyankar 
25042b4ed282SShri Abhyankar 
25052b4ed282SShri Abhyankar    Level: beginner
25062b4ed282SShri Abhyankar 
25072b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
25082b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
25092b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
25102b4ed282SShri Abhyankar 
25112b4ed282SShri Abhyankar M*/
25122b4ed282SShri Abhyankar EXTERN_C_BEGIN
25132b4ed282SShri Abhyankar #undef __FUNCT__
25142b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
25157087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
25162b4ed282SShri Abhyankar {
25172b4ed282SShri Abhyankar   PetscErrorCode ierr;
25182b4ed282SShri Abhyankar   SNES_VI        *vi;
25192b4ed282SShri Abhyankar 
25202b4ed282SShri Abhyankar   PetscFunctionBegin;
25212176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
25222b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2523edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
25242b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
25252b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
25262b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
25272b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
25282b4ed282SShri Abhyankar 
25292b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
25302b4ed282SShri Abhyankar   snes->data            = (void*)vi;
25312b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
25322b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
25332b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
2534f2b03b96SBarry Smith   vi->LineSearch        = SNESLineSearchCubic_VI;
25352b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
25362b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
25372b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
25382b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
25392b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
25402b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
25412f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
25422b4ed282SShri Abhyankar 
25432b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
25442b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
25452b4ed282SShri Abhyankar 
25462b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25472b4ed282SShri Abhyankar }
25482b4ed282SShri Abhyankar EXTERN_C_END
2549ed70e96aSJungho Lee 
2550ed70e96aSJungho Lee #undef __FUNCT__
2551ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet"
2552ed70e96aSJungho Lee /*
2553ed70e96aSJungho Lee    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
2554ed70e96aSJungho Lee      system is solved on)
2555ed70e96aSJungho Lee 
2556ed70e96aSJungho Lee    Input parameter
2557ed70e96aSJungho Lee .  snes - the SNES context
2558ed70e96aSJungho Lee 
2559ed70e96aSJungho Lee    Output parameter
2560ed70e96aSJungho Lee .  ISact - active set index set
2561ed70e96aSJungho Lee 
2562ed70e96aSJungho Lee  */
2563ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact)
2564ed70e96aSJungho Lee {
2565ed70e96aSJungho Lee   SNES_VI          *vi = (SNES_VI*)snes->data;
2566ed70e96aSJungho Lee   PetscFunctionBegin;
2567ed70e96aSJungho Lee   *inact = vi->IS_inact_prev;
2568ed70e96aSJungho Lee   PetscFunctionReturn(0);
2569ed70e96aSJungho Lee }
2570