xref: /petsc/src/snes/impls/vi/vi.c (revision 2bd2b0e6efd31c4ff81d5cb633a913ae833c5993)
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 
16*2bd2b0e6SSatish Balay    Level: advanced
172176524cSBarry Smith 
18aab9d709SJed Brown @*/
1977cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec))
202176524cSBarry Smith {
212176524cSBarry Smith   PetscErrorCode   ierr;
222176524cSBarry Smith   SNES_VI          *vi;
232176524cSBarry Smith 
242176524cSBarry Smith   PetscFunctionBegin;
252176524cSBarry Smith   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
262176524cSBarry Smith   vi = (SNES_VI*)snes->data;
272176524cSBarry Smith   vi->computevariablebounds = compute;
282176524cSBarry Smith   PetscFunctionReturn(0);
292176524cSBarry Smith }
302176524cSBarry Smith 
312176524cSBarry Smith 
322176524cSBarry Smith #undef __FUNCT__
33ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS"
34d0af7cd3SBarry Smith /*
35ed70e96aSJungho Lee    SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables
36d0af7cd3SBarry Smith 
37d0af7cd3SBarry Smith    Input parameter
38d0af7cd3SBarry Smith .  snes - the SNES context
39d0af7cd3SBarry Smith .  X    - the snes solution vector
40d0af7cd3SBarry Smith 
41d0af7cd3SBarry Smith    Output parameter
42d0af7cd3SBarry Smith .  ISact - active set index set
43d0af7cd3SBarry Smith 
44d0af7cd3SBarry Smith  */
45ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
46d0af7cd3SBarry Smith {
47d0af7cd3SBarry Smith   PetscErrorCode   ierr;
48d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
49d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
50d0af7cd3SBarry Smith 
51d0af7cd3SBarry Smith   PetscFunctionBegin;
52d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
53d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
54d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
55d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
56d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
57d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
58d0af7cd3SBarry Smith   /* Compute inactive set size */
59d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
60d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
61d0af7cd3SBarry Smith   }
62d0af7cd3SBarry Smith 
63d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
64d0af7cd3SBarry Smith 
65d0af7cd3SBarry Smith   /* Set inactive set indices */
66d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
67d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
68d0af7cd3SBarry Smith   }
69d0af7cd3SBarry Smith 
70d0af7cd3SBarry Smith    /* Create inactive set IS */
71d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
72d0af7cd3SBarry Smith 
73d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
74d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
75d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
76d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
77d0af7cd3SBarry Smith   PetscFunctionReturn(0);
78d0af7cd3SBarry Smith }
79d0af7cd3SBarry Smith 
803c0c59f3SBarry Smith /*
813c0c59f3SBarry Smith     Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors
823c0c59f3SBarry Smith   defined by the reduced space method.
833c0c59f3SBarry Smith 
843c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
853c0c59f3SBarry Smith 
86ed70e96aSJungho Lee <*/
873c0c59f3SBarry Smith typedef struct {
883c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
893c0c59f3SBarry Smith   IS             inactive;
903c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
913c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
923c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
934c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
943c0c59f3SBarry Smith } DM_SNESVI;
953c0c59f3SBarry Smith 
96d0af7cd3SBarry Smith #undef __FUNCT__
974dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
984dcab191SBarry Smith /*
994dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
1004dcab191SBarry Smith 
1014dcab191SBarry Smith */
1024dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
1034dcab191SBarry Smith {
1044dcab191SBarry Smith   PetscErrorCode          ierr;
1054dcab191SBarry Smith   PetscContainer          isnes;
1063c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
1074dcab191SBarry Smith 
1084dcab191SBarry Smith   PetscFunctionBegin;
1094dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1104dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
1114dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
1124dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
1134dcab191SBarry Smith   PetscFunctionReturn(0);
1144dcab191SBarry Smith }
1154dcab191SBarry Smith 
1164dcab191SBarry Smith #undef __FUNCT__
117d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
118d0af7cd3SBarry Smith /*
119d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
120d0af7cd3SBarry Smith 
121d0af7cd3SBarry Smith */
122d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
123d0af7cd3SBarry Smith {
124d0af7cd3SBarry Smith   PetscErrorCode          ierr;
125d0af7cd3SBarry Smith   PetscContainer          isnes;
1263c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
127d0af7cd3SBarry Smith   Mat                     interp;
128d0af7cd3SBarry Smith 
129d0af7cd3SBarry Smith   PetscFunctionBegin;
130d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1314c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
132d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
133d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1344c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
135d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
136d0af7cd3SBarry Smith 
137d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1384dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
139d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
14000ac8be1SBarry Smith   *vec = 0;
141d0af7cd3SBarry Smith   PetscFunctionReturn(0);
142d0af7cd3SBarry Smith }
143d0af7cd3SBarry Smith 
1449ce20c35SJungho Lee extern PetscErrorCode  DMSetVI(DM,IS);
145d0af7cd3SBarry Smith 
146d0af7cd3SBarry Smith #undef __FUNCT__
147d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
148d0af7cd3SBarry Smith /*
149d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
150d0af7cd3SBarry Smith 
151d0af7cd3SBarry Smith */
152d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
153d0af7cd3SBarry Smith {
154d0af7cd3SBarry Smith   PetscErrorCode          ierr;
155d0af7cd3SBarry Smith   PetscContainer          isnes;
1563c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
1579ce20c35SJungho Lee   Vec                     finemarked,coarsemarked;
158d0af7cd3SBarry Smith   IS                      inactive;
159d0af7cd3SBarry Smith   VecScatter              inject;
1609ce20c35SJungho Lee   const PetscInt          *index;
1619ce20c35SJungho Lee   PetscInt                n,k,cnt = 0,rstart,*coarseindex;
1629ce20c35SJungho Lee   PetscScalar             *marked;
163d0af7cd3SBarry Smith 
164d0af7cd3SBarry Smith   PetscFunctionBegin;
165d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1664c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
167d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
168d0af7cd3SBarry Smith 
169298cc208SBarry Smith   /* get the original coarsen */
170d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
171298cc208SBarry Smith 
1723c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1733c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1743c0c59f3SBarry Smith 
175298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
176298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
177298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
1789ce20c35SJungho Lee   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
1799ce20c35SJungho Lee   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
1809ce20c35SJungho Lee 
1819ce20c35SJungho Lee   /*
1829ce20c35SJungho Lee      fill finemarked with locations of inactive points
1839ce20c35SJungho Lee   */
1849ce20c35SJungho Lee   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
1859ce20c35SJungho Lee   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
1869ce20c35SJungho Lee   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
1879ce20c35SJungho Lee   for (k=0;k<n;k++){
1889ce20c35SJungho Lee       ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
1899ce20c35SJungho Lee   }
1909ce20c35SJungho Lee   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
1919ce20c35SJungho Lee   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
1929ce20c35SJungho Lee 
193d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
1949ce20c35SJungho Lee   ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1959ce20c35SJungho Lee   ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
196d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
1979ce20c35SJungho Lee 
1989ce20c35SJungho Lee   /*
1999ce20c35SJungho Lee      create index set list of coarse inactive points from coarsemarked
2009ce20c35SJungho Lee   */
2019ce20c35SJungho Lee   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
2029ce20c35SJungho Lee   ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr);
2039ce20c35SJungho Lee   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
2049ce20c35SJungho Lee   for (k=0; k<n; k++) {
205ff207688SJed Brown     if (marked[k] != 0.0) cnt++;
2069ce20c35SJungho Lee   }
2079ce20c35SJungho Lee   ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr);
2089ce20c35SJungho Lee   cnt  = 0;
2099ce20c35SJungho Lee   for (k=0; k<n; k++) {
210ff207688SJed Brown     if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart;
2119ce20c35SJungho Lee   }
2129ce20c35SJungho Lee   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
2139ce20c35SJungho Lee   ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
2149ce20c35SJungho Lee 
215298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
216298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
2179ce20c35SJungho Lee   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
2189ce20c35SJungho Lee 
2199ce20c35SJungho Lee   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
2209ce20c35SJungho Lee   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
2213c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
222d0af7cd3SBarry Smith   PetscFunctionReturn(0);
223d0af7cd3SBarry Smith }
224d0af7cd3SBarry Smith 
225d0af7cd3SBarry Smith #undef __FUNCT__
2263c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2273c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
228d0af7cd3SBarry Smith {
229d0af7cd3SBarry Smith   PetscErrorCode ierr;
230d0af7cd3SBarry Smith 
231d0af7cd3SBarry Smith   PetscFunctionBegin;
2324c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2334c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2344c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2354c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
23600ac8be1SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
23700ac8be1SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
23800ac8be1SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
2394c661befSBarry Smith 
240d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
241d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
242d0af7cd3SBarry Smith   PetscFunctionReturn(0);
243d0af7cd3SBarry Smith }
244d0af7cd3SBarry Smith 
245d0af7cd3SBarry Smith #undef __FUNCT__
246d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
247d0af7cd3SBarry Smith /*
248d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
249d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
250d0af7cd3SBarry Smith 
251d0af7cd3SBarry Smith */
2529ce20c35SJungho Lee PetscErrorCode  DMSetVI(DM dm,IS inactive)
253d0af7cd3SBarry Smith {
254d0af7cd3SBarry Smith   PetscErrorCode          ierr;
255d0af7cd3SBarry Smith   PetscContainer          isnes;
2563c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
257d0af7cd3SBarry Smith 
258d0af7cd3SBarry Smith   PetscFunctionBegin;
2594dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
2601c0a9e84SBarry Smith 
261d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
262d0af7cd3SBarry Smith 
263d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
264d0af7cd3SBarry Smith   if (!isnes) {
265d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2663c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2673c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
268d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
269d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2703c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
271d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
272d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
273d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
274d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
275298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2764dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
277d0af7cd3SBarry Smith   } else {
278d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
279d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
280d0af7cd3SBarry Smith   }
2814dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2824dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
283d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2841a223a97SBarry Smith   dmsnesvi->dm       = dm;
285d0af7cd3SBarry Smith   PetscFunctionReturn(0);
286d0af7cd3SBarry Smith }
287d0af7cd3SBarry Smith 
2884c661befSBarry Smith #undef __FUNCT__
2894c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2904c661befSBarry Smith /*
2914c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2924c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2934c661befSBarry Smith */
2944c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2954c661befSBarry Smith {
2964c661befSBarry Smith   PetscErrorCode          ierr;
2974c661befSBarry Smith 
2984c661befSBarry Smith   PetscFunctionBegin;
2994c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
3004c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
3014c661befSBarry Smith   PetscFunctionReturn(0);
3024c661befSBarry Smith }
3034c661befSBarry Smith 
3043c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
3052b4ed282SShri Abhyankar 
3069308c137SBarry Smith #undef __FUNCT__
3079308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3087087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3099308c137SBarry Smith {
3109308c137SBarry Smith   PetscErrorCode    ierr;
3119308c137SBarry Smith   SNES_VI            *vi = (SNES_VI*)snes->data;
312649052a6SBarry Smith   PetscViewer        viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);
3139308c137SBarry Smith   const PetscScalar  *x,*xl,*xu,*f;
3146fd67740SBarry Smith   PetscInt           i,n,act[2] = {0,0},fact[2],N;
3156a9e2d46SJungho Lee   /* remove later */
3166a9e2d46SJungho Lee   /* Number of components that actually hit the bounds (c.f. active variables) */
3176a9e2d46SJungho Lee   PetscInt           act_bound[2] = {0,0},fact_bound[2];
3189308c137SBarry Smith   PetscReal          rnorm,fnorm;
3199308c137SBarry Smith 
3209308c137SBarry Smith   PetscFunctionBegin;
3219308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3226fd67740SBarry Smith   ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr);
3239308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3249308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3259308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3263f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3279308c137SBarry Smith 
3289308c137SBarry Smith   rnorm = 0.0;
3299308c137SBarry Smith   for (i=0; i<n; i++) {
33010f5ae6bSBarry 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]);
331e400df7aSBarry Smith     else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++;
332e400df7aSBarry Smith     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++;
333e400df7aSBarry Smith     else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here");
3349308c137SBarry Smith   }
3356a9e2d46SJungho Lee 
3366a9e2d46SJungho Lee   /* Remove later, number of components that actually hit the bounds */
3376a9e2d46SJungho Lee   for (i=0; i<n; i++) {
3386a9e2d46SJungho Lee     if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++;
3396a9e2d46SJungho Lee     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++;
3406a9e2d46SJungho Lee   }
3413f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3429308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3439308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3449308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
345d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
34621a4c9b1SBarry Smith   ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3476a9e2d46SJungho Lee   /* remove later */
3486a9e2d46SJungho Lee   ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
349f137e44dSBarry Smith   fnorm = PetscSqrtReal(fnorm);
3506fd67740SBarry Smith 
351649052a6SBarry Smith   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
352f137e44dSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"%3D SNES VI Function norm %14.12e Active lower constraints %D upper constraints %D Percent of total %g Percent of bounded %g\n",its,(double)fnorm,fact[0],fact[1],((double)(fact[0]+fact[1]))/((double)N),((double)(fact[0]+fact[1]))/((double)vi->ntruebounds));CHKERRQ(ierr);
353f137e44dSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"                               lower constraints satisfied %D upper constraints satisfied %D\n",its,fact_bound[0],fact_bound[1]);CHKERRQ(ierr);
3546a9e2d46SJungho Lee 
355649052a6SBarry Smith   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
3569308c137SBarry Smith   PetscFunctionReturn(0);
3579308c137SBarry Smith }
3589308c137SBarry Smith 
3592b4ed282SShri Abhyankar /*
3602b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3612b4ed282SShri 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
3622b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3632b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3642b4ed282SShri Abhyankar */
3652b4ed282SShri Abhyankar #undef __FUNCT__
3662b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
367ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3682b4ed282SShri Abhyankar {
3692b4ed282SShri Abhyankar   PetscReal      a1;
3702b4ed282SShri Abhyankar   PetscErrorCode ierr;
371ace3abfcSBarry Smith   PetscBool     hastranspose;
3722b4ed282SShri Abhyankar 
3732b4ed282SShri Abhyankar   PetscFunctionBegin;
3742b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3752b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3762b4ed282SShri Abhyankar   if (hastranspose) {
3772b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3782b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3792b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3802b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3812b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3822b4ed282SShri Abhyankar   } else {
3832b4ed282SShri Abhyankar     Vec         work;
3842b4ed282SShri Abhyankar     PetscScalar result;
3852b4ed282SShri Abhyankar     PetscReal   wnorm;
3862b4ed282SShri Abhyankar 
3872b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3882b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3892b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3902b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3912b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3926bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3932b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3942b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3952b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3962b4ed282SShri Abhyankar   }
3972b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3982b4ed282SShri Abhyankar }
3992b4ed282SShri Abhyankar 
4002b4ed282SShri Abhyankar /*
4012b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
4022b4ed282SShri Abhyankar */
4032b4ed282SShri Abhyankar #undef __FUNCT__
4042b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
4052b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
4062b4ed282SShri Abhyankar {
4072b4ed282SShri Abhyankar   PetscReal      a1,a2;
4082b4ed282SShri Abhyankar   PetscErrorCode ierr;
409ace3abfcSBarry Smith   PetscBool     hastranspose;
4102b4ed282SShri Abhyankar 
4112b4ed282SShri Abhyankar   PetscFunctionBegin;
4122b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
4132b4ed282SShri Abhyankar   if (hastranspose) {
4142b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
4152b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
4162b4ed282SShri Abhyankar 
4172b4ed282SShri Abhyankar     /* Compute || J^T W|| */
4182b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
4192b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
4202b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
4212b4ed282SShri Abhyankar     if (a1 != 0.0) {
4222b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
4232b4ed282SShri Abhyankar     }
4242b4ed282SShri Abhyankar   }
4252b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4262b4ed282SShri Abhyankar }
4272b4ed282SShri Abhyankar 
4282b4ed282SShri Abhyankar /*
4292b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4302b4ed282SShri Abhyankar 
4312b4ed282SShri Abhyankar   Notes:
4322b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4332b4ed282SShri Abhyankar   merit < abstol
4342b4ed282SShri Abhyankar   merit < rtol*merit_initial
4352b4ed282SShri Abhyankar */
4362b4ed282SShri Abhyankar #undef __FUNCT__
4372b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4387fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4392b4ed282SShri Abhyankar {
4402b4ed282SShri Abhyankar   PetscErrorCode ierr;
4412b4ed282SShri Abhyankar 
4422b4ed282SShri Abhyankar   PetscFunctionBegin;
4432b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4442b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4452b4ed282SShri Abhyankar 
4462b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4472b4ed282SShri Abhyankar 
4482b4ed282SShri Abhyankar   if (!it) {
4492b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4507fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4512b4ed282SShri Abhyankar   }
4527fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4532b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4542b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4557fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4567fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4572b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4582b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4592b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4602b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4612b4ed282SShri Abhyankar   }
4622b4ed282SShri Abhyankar 
4632b4ed282SShri Abhyankar   if (it && !*reason) {
4647fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4657fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4662b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4672b4ed282SShri Abhyankar     }
4682b4ed282SShri Abhyankar   }
4692b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4702b4ed282SShri Abhyankar }
4712b4ed282SShri Abhyankar 
4722b4ed282SShri Abhyankar /*
4732b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4742b4ed282SShri Abhyankar 
4752b4ed282SShri Abhyankar   Input Parameter:
4762b4ed282SShri Abhyankar . phi - the semismooth function
4772b4ed282SShri Abhyankar 
4782b4ed282SShri Abhyankar   Output Parameter:
4792b4ed282SShri Abhyankar . merit - the merit function
4802b4ed282SShri Abhyankar . phinorm - ||phi||
4812b4ed282SShri Abhyankar 
4822b4ed282SShri Abhyankar   Notes:
4832b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4842b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4852b4ed282SShri Abhyankar */
4862b4ed282SShri Abhyankar #undef __FUNCT__
4872b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4882b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4892b4ed282SShri Abhyankar {
4902b4ed282SShri Abhyankar   PetscErrorCode ierr;
4912b4ed282SShri Abhyankar 
4922b4ed282SShri Abhyankar   PetscFunctionBegin;
4935f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4945f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4952b4ed282SShri Abhyankar 
4962b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4972b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4982b4ed282SShri Abhyankar }
4992b4ed282SShri Abhyankar 
5007f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
5014c21c6cdSBarry Smith {
502bec29f96SSatish Balay   return a + b - PetscSqrtScalar(a*a + b*b);
5034c21c6cdSBarry Smith }
5044c21c6cdSBarry Smith 
5057f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
5064c21c6cdSBarry Smith {
507bec29f96SSatish Balay   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ PetscSqrtScalar(a*a + b*b);
5085559b345SBarry Smith   else return .5;
5094c21c6cdSBarry Smith }
5104c21c6cdSBarry Smith 
5112b4ed282SShri Abhyankar /*
5121f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
5132b4ed282SShri Abhyankar 
5142b4ed282SShri Abhyankar    Input Parameters:
5152b4ed282SShri Abhyankar .  snes - the SNES context
5162b4ed282SShri Abhyankar .  x - current iterate
5172b4ed282SShri Abhyankar .  functx - user defined function context
5182b4ed282SShri Abhyankar 
5192b4ed282SShri Abhyankar    Output Parameters:
5202b4ed282SShri Abhyankar .  phi - Semismooth function
5212b4ed282SShri Abhyankar 
5222b4ed282SShri Abhyankar */
5232b4ed282SShri Abhyankar #undef __FUNCT__
5241f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5251f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5262b4ed282SShri Abhyankar {
5272b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5282b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5292b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5304c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5312b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5322b4ed282SShri Abhyankar 
5332b4ed282SShri Abhyankar   PetscFunctionBegin;
5342b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5352b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5362b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5372b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5382b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5392b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5402b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5412b4ed282SShri Abhyankar 
5422b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
54310f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5444c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
54510f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5464c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
54710f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5484c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5495559b345SBarry Smith     } else if (l[i] == u[i]) {
5502b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5515559b345SBarry Smith     } else {                                                /* both bounds on variable */
5524c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5532b4ed282SShri Abhyankar     }
5542b4ed282SShri Abhyankar   }
5552b4ed282SShri Abhyankar 
5562b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5572b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5582b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5592b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5602b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5612b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5622b4ed282SShri Abhyankar }
5632b4ed282SShri Abhyankar 
5642b4ed282SShri Abhyankar /*
565a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
566a79edbefSShri Abhyankar                                           the semismooth jacobian.
5672b4ed282SShri Abhyankar */
5682b4ed282SShri Abhyankar #undef __FUNCT__
569a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
570a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5712b4ed282SShri Abhyankar {
5722b4ed282SShri Abhyankar   PetscErrorCode ierr;
5732b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5744c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5752b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5762b4ed282SShri Abhyankar 
5772b4ed282SShri Abhyankar   PetscFunctionBegin;
5782b4ed282SShri Abhyankar 
5792b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5802b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5812b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5822b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
583a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
584a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5852b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5864c21c6cdSBarry Smith 
5872b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
58810f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5894c21c6cdSBarry Smith       da[i] = 0;
5902b4ed282SShri Abhyankar       db[i] = 1;
59110f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5924c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5934c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
59410f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5955559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5965559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5975559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5984c21c6cdSBarry Smith       da[i] = 1;
5992b4ed282SShri Abhyankar       db[i] = 0;
6005559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
6014c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
6024c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
6034c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
6044c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
6054c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
6064c21c6cdSBarry Smith       db[i] = db1*db2;
6072b4ed282SShri Abhyankar     }
6082b4ed282SShri Abhyankar   }
6095559b345SBarry Smith 
6102b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
6112b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
6122b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
6132b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
614a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
615a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
616a79edbefSShri Abhyankar   PetscFunctionReturn(0);
617a79edbefSShri Abhyankar }
618a79edbefSShri Abhyankar 
619a79edbefSShri Abhyankar /*
620a79edbefSShri 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.
621a79edbefSShri Abhyankar 
622a79edbefSShri Abhyankar    Input Parameters:
623a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
624a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
625a79edbefSShri Abhyankar 
626a79edbefSShri Abhyankar    Output Parameters:
627a79edbefSShri Abhyankar .  jac      - semismooth jacobian
628a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
629a79edbefSShri Abhyankar 
630a79edbefSShri Abhyankar    Notes:
631a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
632a79edbefSShri Abhyankar    jac = Da + Db*jacfun
633a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
634a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
635a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
636a79edbefSShri Abhyankar */
637a79edbefSShri Abhyankar #undef __FUNCT__
638a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
639a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
640a79edbefSShri Abhyankar {
641a79edbefSShri Abhyankar   PetscErrorCode ierr;
642a79edbefSShri Abhyankar 
6432b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
644a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
645a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
646a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
647a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
648a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6492b4ed282SShri Abhyankar   }
6502b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6512b4ed282SShri Abhyankar }
6522b4ed282SShri Abhyankar 
6532b4ed282SShri Abhyankar /*
654ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
655ee657d29SShri Abhyankar 
656ee657d29SShri Abhyankar    Input Parameters:
657ee657d29SShri Abhyankar    phi - semismooth function.
658ee657d29SShri Abhyankar    H   - semismooth jacobian
659ee657d29SShri Abhyankar 
660ee657d29SShri Abhyankar    Output Parameters:
661ee657d29SShri Abhyankar    dpsi - merit function gradient
662ee657d29SShri Abhyankar 
663ee657d29SShri Abhyankar    Notes:
664ee657d29SShri Abhyankar   The merit function gradient is computed as follows
665ee657d29SShri Abhyankar         dpsi = H^T*phi
666ee657d29SShri Abhyankar */
667ee657d29SShri Abhyankar #undef __FUNCT__
668ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
669ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
670ee657d29SShri Abhyankar {
671ee657d29SShri Abhyankar   PetscErrorCode ierr;
672ee657d29SShri Abhyankar 
673ee657d29SShri Abhyankar   PetscFunctionBegin;
6745f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
675ee657d29SShri Abhyankar   PetscFunctionReturn(0);
676ee657d29SShri Abhyankar }
677ee657d29SShri Abhyankar 
678c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
679c1a5e521SShri Abhyankar /*
680c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
681c1a5e521SShri Abhyankar 
682c1a5e521SShri Abhyankar    Input Parameters:
683c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
684c1a5e521SShri Abhyankar 
685c1a5e521SShri Abhyankar    Output Parameters:
686c1a5e521SShri Abhyankar .  X - Bound projected X
687c1a5e521SShri Abhyankar 
688c1a5e521SShri Abhyankar */
689c1a5e521SShri Abhyankar 
690c1a5e521SShri Abhyankar #undef __FUNCT__
691c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
692c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
693c1a5e521SShri Abhyankar {
694c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
695c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
696c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
697c1a5e521SShri Abhyankar   PetscScalar       *x;
698c1a5e521SShri Abhyankar   PetscInt          i,n;
699c1a5e521SShri Abhyankar 
700c1a5e521SShri Abhyankar   PetscFunctionBegin;
701c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
702c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
703c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
704c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
705c1a5e521SShri Abhyankar 
706c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
70710f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
70810f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
709c1a5e521SShri Abhyankar   }
710c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
711c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
712c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
713c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
714c1a5e521SShri Abhyankar }
715c1a5e521SShri Abhyankar 
7162b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
7172b4ed282SShri Abhyankar 
7182b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
7192b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
7202b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
7212b4ed282SShri Abhyankar      respectively.
7222b4ed282SShri Abhyankar 
7232b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7242b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7252b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7262b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7272b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7282b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7292b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7302b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7312b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7322b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7332b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7342b4ed282SShri Abhyankar      for all nonlinear solvers.
7352b4ed282SShri Abhyankar 
7362b4ed282SShri Abhyankar      Another key routine is:
7372b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7382b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7392b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7402b4ed282SShri Abhyankar      SNESSolve() if necessary.
7412b4ed282SShri Abhyankar 
7422b4ed282SShri Abhyankar      Additional basic routines are:
7432b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7442b4ed282SShri Abhyankar                                       have actually been used.
7452b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7462b4ed282SShri Abhyankar      SNESView().
7472b4ed282SShri Abhyankar 
7482b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7492b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7502b4ed282SShri Abhyankar      above description applies to these categories also.
7512b4ed282SShri Abhyankar 
7522b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7532b4ed282SShri Abhyankar /*
75469c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7552b4ed282SShri Abhyankar    method using a line search.
7562b4ed282SShri Abhyankar 
7572b4ed282SShri Abhyankar    Input Parameters:
7582b4ed282SShri Abhyankar .  snes - the SNES context
7592b4ed282SShri Abhyankar 
7602b4ed282SShri Abhyankar    Output Parameter:
7612b4ed282SShri Abhyankar .  outits - number of iterations until termination
7622b4ed282SShri Abhyankar 
7632b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7642b4ed282SShri Abhyankar 
7652b4ed282SShri Abhyankar    Notes:
7662b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
76751defd01SShri Abhyankar    line search. The default line search does not do any line seach
76851defd01SShri Abhyankar    but rather takes a full newton step.
7692b4ed282SShri Abhyankar */
7702b4ed282SShri Abhyankar #undef __FUNCT__
77169c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
77269c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7732b4ed282SShri Abhyankar {
7742b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7752b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7762b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7773b336b49SShri Abhyankar   PetscBool          lssucceed;
7782b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7792b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7802b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7812b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7822b4ed282SShri Abhyankar 
7832b4ed282SShri Abhyankar   PetscFunctionBegin;
7849ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7859ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7869ce7406fSBarry Smith 
7872b4ed282SShri Abhyankar   snes->numFailures            = 0;
7882b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7892b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7902b4ed282SShri Abhyankar 
7912b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7922b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7932b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7942b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7952b4ed282SShri Abhyankar   G		= snes->work[1];
7962b4ed282SShri Abhyankar   W		= snes->work[2];
7972b4ed282SShri Abhyankar 
7982b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7992b4ed282SShri Abhyankar   snes->iter = 0;
8002b4ed282SShri Abhyankar   snes->norm = 0.0;
8012b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8022b4ed282SShri Abhyankar 
8037fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
8042b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
8052b4ed282SShri Abhyankar   if (snes->domainerror) {
8062b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8079ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8082b4ed282SShri Abhyankar     PetscFunctionReturn(0);
8092b4ed282SShri Abhyankar   }
8102b4ed282SShri Abhyankar    /* Compute Merit function */
8112b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
8122b4ed282SShri Abhyankar 
8132b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
8142b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
81562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
8162b4ed282SShri Abhyankar 
8172b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8182b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
8192b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8202b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
8217a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8222b4ed282SShri Abhyankar 
8232b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8242b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8252b4ed282SShri Abhyankar   /* test convergence */
8262b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8279ce7406fSBarry Smith   if (snes->reason) {
8289ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8299ce7406fSBarry Smith     PetscFunctionReturn(0);
8309ce7406fSBarry Smith   }
8312b4ed282SShri Abhyankar 
8322b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8332b4ed282SShri Abhyankar 
8342b4ed282SShri Abhyankar     /* Call general purpose update function */
8352b4ed282SShri Abhyankar     if (snes->ops->update) {
8362b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8372b4ed282SShri Abhyankar     }
8382b4ed282SShri Abhyankar 
8392b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
840a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8412b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
842a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
843a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
844a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
845a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
846ee657d29SShri Abhyankar     /* Compute the merit function gradient */
847ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8482b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8492b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8502b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8513b336b49SShri Abhyankar 
8523b336b49SShri Abhyankar     if (kspreason < 0) {
8532b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8542b4ed282SShri 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);
8552b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8562b4ed282SShri Abhyankar         break;
8572b4ed282SShri Abhyankar       }
8582b4ed282SShri Abhyankar     }
8592b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8602b4ed282SShri Abhyankar     snes->linear_its += lits;
8612b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8622b4ed282SShri Abhyankar     /*
8632b4ed282SShri Abhyankar     if (vi->precheckstep) {
864ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8652b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8662b4ed282SShri Abhyankar     }
8672b4ed282SShri Abhyankar 
8682b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8692b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8702b4ed282SShri Abhyankar     }
8712b4ed282SShri Abhyankar     */
8722b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8732b4ed282SShri Abhyankar          Y <- X - lambda*Y
8742b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8752b4ed282SShri Abhyankar     */
8762b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8772b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8782b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8792b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8802b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8812b4ed282SShri Abhyankar     if (snes->domainerror) {
8822b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8839ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8842b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8852b4ed282SShri Abhyankar     }
8862b4ed282SShri Abhyankar     if (!lssucceed) {
8872b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
888ace3abfcSBarry Smith 	PetscBool ismin;
8892b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8902b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8912b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8922b4ed282SShri Abhyankar         break;
8932b4ed282SShri Abhyankar       }
8942b4ed282SShri Abhyankar     }
8952b4ed282SShri Abhyankar     /* Update function and solution vectors */
8962b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8972b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8982b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8992b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
9002b4ed282SShri Abhyankar     /* Monitor convergence */
9012b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
9022b4ed282SShri Abhyankar     snes->iter = i+1;
9032b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
9042b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
9052b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
9067a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
9072b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
9082b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
9092b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
9102b4ed282SShri Abhyankar     if (snes->reason) break;
9112b4ed282SShri Abhyankar   }
9122b4ed282SShri Abhyankar   if (i == maxits) {
9132b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
9142b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
9152b4ed282SShri Abhyankar   }
9169ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
9172b4ed282SShri Abhyankar   PetscFunctionReturn(0);
9182b4ed282SShri Abhyankar }
91969c03620SShri Abhyankar 
92069c03620SShri Abhyankar #undef __FUNCT__
921693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
922693ddf92SShri Abhyankar /*
923693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
924693ddf92SShri Abhyankar 
925693ddf92SShri Abhyankar    Input parameter
926693ddf92SShri Abhyankar .  snes - the SNES context
927693ddf92SShri Abhyankar .  X    - the snes solution vector
928693ddf92SShri Abhyankar .  F    - the nonlinear function vector
929693ddf92SShri Abhyankar 
930693ddf92SShri Abhyankar    Output parameter
931693ddf92SShri Abhyankar .  ISact - active set index set
932693ddf92SShri Abhyankar  */
933693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
934d950fb63SShri Abhyankar {
935d950fb63SShri Abhyankar   PetscErrorCode   ierr;
936693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
937693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
938693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
939693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
940d950fb63SShri Abhyankar 
941d950fb63SShri Abhyankar   PetscFunctionBegin;
942d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
943d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
944fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
945fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
946fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
947fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
948693ddf92SShri Abhyankar   /* Compute active set size */
949d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
950e6337399SBarry Smith     if (!vi->ignorefunctionsign) {
95110f5ae6bSBarry 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++;
952e6337399SBarry Smith     } else {
953e6337399SBarry Smith       if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8  && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) nloc_isact++;
954e6337399SBarry Smith     }
955d950fb63SShri Abhyankar   }
956693ddf92SShri Abhyankar 
957d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
958d950fb63SShri Abhyankar 
959693ddf92SShri Abhyankar   /* Set active set indices */
960d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
961e6337399SBarry Smith     if (!vi->ignorefunctionsign) {
96210f5ae6bSBarry 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;
963e6337399SBarry Smith     } else {
964e6337399SBarry Smith       if (!(PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8  && PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) idx_act[i1++] = ilow+i;
965e6337399SBarry Smith     }
966d950fb63SShri Abhyankar   }
967d950fb63SShri Abhyankar 
968693ddf92SShri Abhyankar    /* Create active set IS */
96962298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
970d950fb63SShri Abhyankar 
971fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
972fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
973fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
974fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
975d950fb63SShri Abhyankar   PetscFunctionReturn(0);
976d950fb63SShri Abhyankar }
977d950fb63SShri Abhyankar 
978693ddf92SShri Abhyankar #undef __FUNCT__
979693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
980693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
981693ddf92SShri Abhyankar {
982693ddf92SShri Abhyankar   PetscErrorCode     ierr;
983693ddf92SShri Abhyankar 
984693ddf92SShri Abhyankar   PetscFunctionBegin;
985693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
986693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
987693ddf92SShri Abhyankar   PetscFunctionReturn(0);
988693ddf92SShri Abhyankar }
989693ddf92SShri Abhyankar 
990dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
991dbd914b8SShri Abhyankar #undef __FUNCT__
992fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
993fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
994dbd914b8SShri Abhyankar {
995dbd914b8SShri Abhyankar   PetscErrorCode ierr;
996dbd914b8SShri Abhyankar   Vec            v;
997dbd914b8SShri Abhyankar 
998dbd914b8SShri Abhyankar   PetscFunctionBegin;
999dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
1000dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
1001dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
1002dbd914b8SShri Abhyankar   *newv = v;
1003dbd914b8SShri Abhyankar 
1004dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
1005dbd914b8SShri Abhyankar }
1006dbd914b8SShri Abhyankar 
1007732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
1008732bb160SShri Abhyankar #undef __FUNCT__
1009732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
1010732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
1011732bb160SShri Abhyankar {
1012732bb160SShri Abhyankar   PetscErrorCode         ierr;
1013d0af7cd3SBarry Smith   KSP                    snesksp;
1014dbd914b8SShri Abhyankar 
1015732bb160SShri Abhyankar   PetscFunctionBegin;
1016732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
1017d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
1018c2efdce3SBarry Smith 
1019c2efdce3SBarry Smith   /*
1020d0af7cd3SBarry Smith   KSP                    kspnew;
1021d0af7cd3SBarry Smith   PC                     pcnew;
1022d0af7cd3SBarry Smith   const MatSolverPackage stype;
1023d0af7cd3SBarry Smith 
1024c2efdce3SBarry Smith 
1025732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
1026732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
1027732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
1028732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
1029732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1030732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1031732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1032732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1033732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1034732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1035732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10366bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1037732bb160SShri Abhyankar   snes->ksp = kspnew;
1038732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1039d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1040732bb160SShri Abhyankar   PetscFunctionReturn(0);
1041732bb160SShri Abhyankar }
104269c03620SShri Abhyankar 
104369c03620SShri Abhyankar 
1044fe835674SShri Abhyankar #undef __FUNCT__
1045fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
104610f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1047fe835674SShri Abhyankar {
1048fe835674SShri Abhyankar   PetscErrorCode    ierr;
1049fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1050fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1051fe835674SShri Abhyankar   PetscInt          i,n;
1052fe835674SShri Abhyankar   PetscReal         rnorm;
1053fe835674SShri Abhyankar 
1054fe835674SShri Abhyankar   PetscFunctionBegin;
1055fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1056fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1057fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1058fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1059fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1060fe835674SShri Abhyankar   rnorm = 0.0;
1061e007de34SBarry Smith   if (!vi->ignorefunctionsign) {
1062fe835674SShri Abhyankar     for (i=0; i<n; i++) {
106310f5ae6bSBarry 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]);
1064fe835674SShri Abhyankar     }
1065e007de34SBarry Smith   } else {
1066e007de34SBarry Smith     for (i=0; i<n; i++) {
1067e007de34SBarry Smith       if ((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8) && (PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8)) rnorm += PetscRealPart(PetscConj(f[i])*f[i]);
1068e007de34SBarry Smith     }
1069e007de34SBarry Smith   }
1070fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1071fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1072fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1073fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1074d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1075fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1076fe835674SShri Abhyankar   PetscFunctionReturn(0);
1077fe835674SShri Abhyankar }
1078fe835674SShri Abhyankar 
1079fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1080c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1081c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1082d950fb63SShri Abhyankar #undef __FUNCT__
1083d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1084d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1085d950fb63SShri Abhyankar {
1086d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1087d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1088abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1089d950fb63SShri Abhyankar   PetscBool         lssucceed;
1090d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1091fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1092d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1093d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1094d950fb63SShri Abhyankar 
1095d950fb63SShri Abhyankar   PetscFunctionBegin;
1096d950fb63SShri Abhyankar   snes->numFailures            = 0;
1097d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1098d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1099d950fb63SShri Abhyankar 
1100d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1101d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1102d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1103d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1104d950fb63SShri Abhyankar   G		= snes->work[1];
1105d950fb63SShri Abhyankar   W		= snes->work[2];
1106d950fb63SShri Abhyankar 
1107d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1108d950fb63SShri Abhyankar   snes->iter = 0;
1109d950fb63SShri Abhyankar   snes->norm = 0.0;
1110d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1111d950fb63SShri Abhyankar 
11127fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1113fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1114d950fb63SShri Abhyankar   if (snes->domainerror) {
1115d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1116d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1117d950fb63SShri Abhyankar   }
1118fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1119d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1120d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
112162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1122d950fb63SShri Abhyankar 
1123d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1124fe835674SShri Abhyankar   snes->norm = fnorm;
1125d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1126fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
11277a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1128d950fb63SShri Abhyankar 
1129d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1130fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1131d950fb63SShri Abhyankar   /* test convergence */
1132fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1133d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1134d950fb63SShri Abhyankar 
11359ce20c35SJungho Lee 
1136d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1137d950fb63SShri Abhyankar 
1138d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1139a6b72b01SJungho Lee     IS         IS_redact; /* redundant active set */
1140d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1141abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1142fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1143d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
114462298a1eSBarry Smith     IS         keptrows;
1145abcba341SShri Abhyankar     PetscBool  isequal;
1146d950fb63SShri Abhyankar 
1147d950fb63SShri Abhyankar     /* Call general purpose update function */
1148d950fb63SShri Abhyankar     if (snes->ops->update) {
1149d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1150d950fb63SShri Abhyankar     }
1151d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
115262298a1eSBarry Smith 
11539ce20c35SJungho Lee 
1154d950fb63SShri Abhyankar         /* Create active and inactive index sets */
1155a6b72b01SJungho Lee 
1156a6b72b01SJungho Lee     /*original
1157693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1158a6b72b01SJungho Lee      */
1159a6b72b01SJungho Lee     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
1160a6b72b01SJungho Lee 
1161a6b72b01SJungho Lee     if (vi->checkredundancy) {
1162a6b72b01SJungho Lee       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
1163ed70e96aSJungho Lee       if (IS_redact){
1164ed70e96aSJungho Lee         ierr = ISSort(IS_redact);CHKERRQ(ierr);
1165a6b72b01SJungho Lee         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1166a6b72b01SJungho Lee         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
1167ed70e96aSJungho Lee       }
1168ed70e96aSJungho Lee       else {
1169ed70e96aSJungho Lee         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1170ed70e96aSJungho Lee       }
1171a6b72b01SJungho Lee     } else {
1172a6b72b01SJungho Lee       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1173a6b72b01SJungho Lee     }
1174d950fb63SShri Abhyankar 
11754dcab191SBarry Smith 
1176abcba341SShri Abhyankar     /* Create inactive set submatrix */
117762298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1178a6b72b01SJungho Lee 
1179b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
11809ce20c35SJungho Lee     if (0 && keptrows) {
11819ce20c35SJungho Lee     // if (keptrows) {
118262298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
118362298a1eSBarry Smith       const PetscInt *krows,*inact;
118427d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
118562298a1eSBarry Smith 
11866bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11876bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
118862298a1eSBarry Smith 
118962298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
119062298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
119162298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
119262298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
119362298a1eSBarry Smith       for (k=0; k<cnt; k++) {
119427d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
119562298a1eSBarry Smith       }
119662298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
119762298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11986bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11996bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
120062298a1eSBarry Smith 
120127d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
120227d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
120362298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
120462298a1eSBarry Smith     }
12059ce20c35SJungho Lee     ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr);
12069ce20c35SJungho Lee     /* remove later */
12079ce20c35SJungho Lee 
12089ce20c35SJungho Lee     /*
12099ce20c35SJungho Lee   ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12109ce20c35SJungho Lee   ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12119ce20c35SJungho Lee   ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12129ce20c35SJungho Lee   ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12139ce20c35SJungho Lee   ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
12149ce20c35SJungho Lee      */
121562298a1eSBarry Smith 
1216d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1217d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1218d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1219d950fb63SShri Abhyankar 
1220d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1221fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1222fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1223fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1224d950fb63SShri Abhyankar 
1225d950fb63SShri Abhyankar     /* Create scatter contexts */
1226d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1227d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1228d950fb63SShri Abhyankar 
1229d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1230fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1231fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1232d950fb63SShri Abhyankar 
1233d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1234d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1235d950fb63SShri Abhyankar 
1236d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1237d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1238d950fb63SShri Abhyankar 
1239d950fb63SShri Abhyankar     /* Active set direction = 0 */
1240d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1241d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1242d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1243d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1244d950fb63SShri Abhyankar 
1245abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1246abcba341SShri Abhyankar     if (!isequal) {
1247732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1248c58c0d17SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
1249d950fb63SShri Abhyankar     }
1250d950fb63SShri Abhyankar 
125113e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
125213e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
125313e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
125413e0d083SBarry Smith 
1255f15307b4SJungho Lee 
12569ce20c35SJungho Lee 
1257d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
125813e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
125913e0d083SBarry Smith     {
126013e0d083SBarry Smith       PC        pc;
126113e0d083SBarry Smith       PetscBool flg;
126213e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
126313e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
126413e0d083SBarry Smith       if (flg) {
126513e0d083SBarry Smith         KSP      *subksps;
126613e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
126713e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
126813e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
126913e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
127013e0d083SBarry Smith         if (flg) {
127113e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
127213e0d083SBarry Smith           const PetscInt *ii;
127313e0d083SBarry Smith 
127413e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
127513e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
127613e0d083SBarry Smith           for (j=0; j<n; j++) {
127713e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
127813e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
127913e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
128013e0d083SBarry Smith           }
128113e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
128213e0d083SBarry Smith 
128313e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
128413e0d083SBarry Smith         }
128513e0d083SBarry Smith       }
128613e0d083SBarry Smith     }
128713e0d083SBarry Smith 
1288fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1289d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1290d950fb63SShri Abhyankar     if (kspreason < 0) {
1291d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1292d950fb63SShri 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);
1293d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1294d950fb63SShri Abhyankar         break;
1295d950fb63SShri Abhyankar       }
1296d950fb63SShri Abhyankar      }
1297d950fb63SShri Abhyankar 
1298d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1299d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1300d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1301d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1302d950fb63SShri Abhyankar 
13036bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
13046bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
13056bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
13066bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
13076bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
13086bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1309abcba341SShri Abhyankar     if (!isequal) {
13106bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1311abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1312abcba341SShri Abhyankar     }
13136bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
13146bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1315d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
13166bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1317d950fb63SShri Abhyankar     }
1318d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1319d950fb63SShri Abhyankar     snes->linear_its += lits;
1320d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1321d950fb63SShri Abhyankar     /*
1322d950fb63SShri Abhyankar     if (vi->precheckstep) {
1323d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1324d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1325d950fb63SShri Abhyankar     }
1326d950fb63SShri Abhyankar 
1327d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1328d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1329d950fb63SShri Abhyankar     }
1330d950fb63SShri Abhyankar     */
1331d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1332d950fb63SShri Abhyankar          Y <- X - lambda*Y
1333d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1334d950fb63SShri Abhyankar     */
1335d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1336fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1337fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1338fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
13392b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
13402b4ed282SShri Abhyankar     if (snes->domainerror) {
13412b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13424c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13432b4ed282SShri Abhyankar       PetscFunctionReturn(0);
13442b4ed282SShri Abhyankar     }
13452b4ed282SShri Abhyankar     if (!lssucceed) {
13462b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
13472b4ed282SShri Abhyankar 	PetscBool ismin;
13482b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
13492b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
13502b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
13512b4ed282SShri Abhyankar         break;
13522b4ed282SShri Abhyankar       }
13532b4ed282SShri Abhyankar     }
13542b4ed282SShri Abhyankar     /* Update function and solution vectors */
1355fe835674SShri Abhyankar     fnorm = gnorm;
1356fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
13572b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
13582b4ed282SShri Abhyankar     /* Monitor convergence */
13592b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13602b4ed282SShri Abhyankar     snes->iter = i+1;
1361fe835674SShri Abhyankar     snes->norm = fnorm;
13622b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13632b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
13647a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
13652b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
13662b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1367fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13682b4ed282SShri Abhyankar     if (snes->reason) break;
13692b4ed282SShri Abhyankar   }
13704c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13712b4ed282SShri Abhyankar   if (i == maxits) {
13722b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13732b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13742b4ed282SShri Abhyankar   }
13752b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13762b4ed282SShri Abhyankar }
13772b4ed282SShri Abhyankar 
13782f63a38cSShri Abhyankar #undef __FUNCT__
1379720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1380cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13812f63a38cSShri Abhyankar {
13822f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13832f63a38cSShri Abhyankar 
13842f63a38cSShri Abhyankar   PetscFunctionBegin;
13852f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13862f63a38cSShri Abhyankar   vi->checkredundancy = func;
1387cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13882f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13892f63a38cSShri Abhyankar }
13902f63a38cSShri Abhyankar 
1391ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1392ff596062SShri Abhyankar #include <engine.h>
1393ff596062SShri Abhyankar #include <mex.h>
1394cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1395ff596062SShri Abhyankar 
1396ff596062SShri Abhyankar #undef __FUNCT__
1397ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1398ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1399ff596062SShri Abhyankar {
1400ff596062SShri Abhyankar   PetscErrorCode      ierr;
1401cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1402cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1403cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1404cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1405fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1406ff596062SShri Abhyankar 
1407ff596062SShri Abhyankar   PetscFunctionBegin;
1408ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1409ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1410ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1411ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1412ff596062SShri Abhyankar 
141309db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
141409db5ad8SShri Abhyankar    bet set by the Matlab function */
1415fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1416cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1417ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1418ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1419cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1420ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1421ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1422cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1423cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1424cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1425ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1426ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1427ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1428ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1429ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1430ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1431ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1432ff596062SShri Abhyankar   PetscFunctionReturn(0);
1433ff596062SShri Abhyankar }
1434ff596062SShri Abhyankar 
1435ff596062SShri Abhyankar #undef __FUNCT__
1436ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1437ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1438ff596062SShri Abhyankar {
1439ff596062SShri Abhyankar   PetscErrorCode      ierr;
1440cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1441ff596062SShri Abhyankar 
1442ff596062SShri Abhyankar   PetscFunctionBegin;
1443ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1444cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1445ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1446ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1447cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1448ff596062SShri Abhyankar   PetscFunctionReturn(0);
1449ff596062SShri Abhyankar }
1450ff596062SShri Abhyankar 
1451ff596062SShri Abhyankar #endif
1452ff596062SShri Abhyankar 
1453ff596062SShri Abhyankar 
14542f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
14552f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1456720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
145756a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
145856a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
14592f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
14602f63a38cSShri Abhyankar */
14612f63a38cSShri Abhyankar #undef __FUNCT__
1462b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1463b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
14642f63a38cSShri Abhyankar {
14652f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
14662f63a38cSShri Abhyankar   PetscErrorCode    ierr;
14672f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
14682f63a38cSShri Abhyankar   PetscBool         lssucceed;
14692f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
14702f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14712f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14722f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14732f63a38cSShri Abhyankar 
14742f63a38cSShri Abhyankar   PetscFunctionBegin;
14752f63a38cSShri Abhyankar   snes->numFailures            = 0;
14762f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14772f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14782f63a38cSShri Abhyankar 
14792f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14802f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14812f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14822f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14832f63a38cSShri Abhyankar   G		= snes->work[1];
14842f63a38cSShri Abhyankar   W		= snes->work[2];
14852f63a38cSShri Abhyankar 
14862f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14872f63a38cSShri Abhyankar   snes->iter = 0;
14882f63a38cSShri Abhyankar   snes->norm = 0.0;
14892f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14902f63a38cSShri Abhyankar 
14912f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14922f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14932f63a38cSShri Abhyankar   if (snes->domainerror) {
14942f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14952f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14962f63a38cSShri Abhyankar   }
14972f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14982f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14992f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
150062cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
15012f63a38cSShri Abhyankar 
15022f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
15032f63a38cSShri Abhyankar   snes->norm = fnorm;
15042f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
15052f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
15067a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
15072f63a38cSShri Abhyankar 
15082f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
15092f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
15102f63a38cSShri Abhyankar   /* test convergence */
15112f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
15122f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
15132f63a38cSShri Abhyankar 
15142f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
15152f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1516cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
151756a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
151856a221efSShri Abhyankar     Vec            F_aug,Y_aug;
151956a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
152056a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
152156a221efSShri Abhyankar     PetscInt       k;
152263ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
152356a221efSShri Abhyankar     PetscScalar    *f,*f2;
15242f63a38cSShri Abhyankar     PetscBool      isequal;
152556a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
15262f63a38cSShri Abhyankar 
15272f63a38cSShri Abhyankar     /* Call general purpose update function */
15282f63a38cSShri Abhyankar     if (snes->ops->update) {
15292f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
15302f63a38cSShri Abhyankar     }
15312f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
15322f63a38cSShri Abhyankar 
15332f63a38cSShri Abhyankar     /* Create active and inactive index sets */
15342f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
15352f63a38cSShri Abhyankar 
153656a221efSShri Abhyankar     /* Get local active set size */
15372f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
153856a221efSShri Abhyankar     if (nis_act) {
1539e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1540e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
154156a221efSShri Abhyankar       if(vi->checkredundancy) {
1542cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
154356a221efSShri Abhyankar       }
15442f63a38cSShri Abhyankar 
154556a221efSShri Abhyankar       if(!IS_redact) {
154656a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
154756a221efSShri Abhyankar            there were no redundant active set variables */
154856a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
154956a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
155056a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
155156a221efSShri Abhyankar 	nkept = nis_act;
155256a221efSShri Abhyankar       } else {
155356a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
155456a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
15552f63a38cSShri Abhyankar 
155656a221efSShri Abhyankar 	/* Create reduced active set list */
155756a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
155856a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1559cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
156056a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
156156a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
156256a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
156356a221efSShri Abhyankar 	}
156456a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
156556a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1566cb5fe31bSShri Abhyankar 
1567cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
156856a221efSShri Abhyankar       }
15692f63a38cSShri Abhyankar 
157056a221efSShri Abhyankar       /* Create augmented F and Y */
157156a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
157256a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
157356a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
157456a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15752f63a38cSShri Abhyankar 
157656a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
157756a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
157856a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
157956a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
158056a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
158156a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15822f63a38cSShri Abhyankar 
158356a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
158456a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
158556a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
158656a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15872f63a38cSShri Abhyankar 
158856a221efSShri Abhyankar 
15899521db3cSSatish Balay       { /* local vars */
1590493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
159156a221efSShri Abhyankar       PetscInt          ncols;
159256a221efSShri Abhyankar       const PetscInt    *cols;
159356a221efSShri Abhyankar       const PetscScalar *vals;
15942969f145SShri Abhyankar       PetscScalar        value[2];
15952969f145SShri Abhyankar       PetscInt           row,col[2];
1596493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15972969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1598493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1599493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1600493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1601493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1602493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1603493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1604493a4f3dSShri Abhyankar       }
1605493a4f3dSShri Abhyankar 
1606493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1607493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
16082969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1609493a4f3dSShri Abhyankar       }
1610493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1611493a4f3dSShri Abhyankar 
1612493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
161356a221efSShri Abhyankar 
161456a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
161556a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
161656a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
161756a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
161856a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
161956a221efSShri Abhyankar       }
162056a221efSShri Abhyankar       /* Add the augmented part */
162156a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
16222969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
16232969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
16242969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
16252969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
162656a221efSShri Abhyankar       }
162756a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
162856a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
162956a221efSShri Abhyankar       /* Only considering prejac = jac for now */
163056a221efSShri Abhyankar       Jpre_aug = J_aug;
16319521db3cSSatish Balay       } /* local vars*/
1632e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1633e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
163456a221efSShri Abhyankar     } else {
163556a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
163656a221efSShri Abhyankar     }
16372f63a38cSShri Abhyankar 
16382f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
16392f63a38cSShri Abhyankar     if (!isequal) {
164056a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
16412f63a38cSShri Abhyankar     }
164256a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
16432f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
164456a221efSShri Abhyankar     /*  {
16452f63a38cSShri Abhyankar       PC        pc;
16462f63a38cSShri Abhyankar       PetscBool flg;
16472f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
16482f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
16492f63a38cSShri Abhyankar       if (flg) {
16502f63a38cSShri Abhyankar         KSP      *subksps;
16512f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
16522f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
16532f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
16542f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
16552f63a38cSShri Abhyankar         if (flg) {
16562f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
16572f63a38cSShri Abhyankar           const PetscInt *ii;
16582f63a38cSShri Abhyankar 
16592f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
16602f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
16612f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
16622f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
16632f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
16642f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
16652f63a38cSShri Abhyankar           }
16662f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
16672f63a38cSShri Abhyankar 
16682f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
16692f63a38cSShri Abhyankar         }
16702f63a38cSShri Abhyankar       }
16712f63a38cSShri Abhyankar     }
167256a221efSShri Abhyankar     */
167356a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16742f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16752f63a38cSShri Abhyankar     if (kspreason < 0) {
16762f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16772f63a38cSShri 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);
16782f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16792f63a38cSShri Abhyankar         break;
16802f63a38cSShri Abhyankar       }
16812f63a38cSShri Abhyankar     }
16822f63a38cSShri Abhyankar 
168356a221efSShri Abhyankar     if(nis_act) {
168456a221efSShri Abhyankar       PetscScalar *y1,*y2;
168556a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
168656a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
168756a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
168856a221efSShri Abhyankar       j1 = 0;
168956a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
169056a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
169156a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
169256a221efSShri Abhyankar       }
169356a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
169456a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16952f63a38cSShri Abhyankar 
16966bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16976bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16986bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
169956a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
170056a221efSShri Abhyankar     }
170156a221efSShri Abhyankar 
17022f63a38cSShri Abhyankar     if (!isequal) {
17036bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
17042f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
17052f63a38cSShri Abhyankar     }
17066bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
170756a221efSShri Abhyankar 
17082f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
17092f63a38cSShri Abhyankar     snes->linear_its += lits;
17102f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
17112f63a38cSShri Abhyankar     /*
17122f63a38cSShri Abhyankar     if (vi->precheckstep) {
17132f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
17142f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
17152f63a38cSShri Abhyankar     }
17162f63a38cSShri Abhyankar 
17172f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
17182f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
17192f63a38cSShri Abhyankar     }
17202f63a38cSShri Abhyankar     */
17212f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
17222f63a38cSShri Abhyankar          Y <- X - lambda*Y
17232f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
17242f63a38cSShri Abhyankar     */
17252f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
17262f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
17272f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
17282f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
17292f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
17302f63a38cSShri Abhyankar     if (snes->domainerror) {
17312f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
17322f63a38cSShri Abhyankar       PetscFunctionReturn(0);
17332f63a38cSShri Abhyankar     }
17342f63a38cSShri Abhyankar     if (!lssucceed) {
17352f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
17362f63a38cSShri Abhyankar 	PetscBool ismin;
17372f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
17382f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
17392f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
17402f63a38cSShri Abhyankar         break;
17412f63a38cSShri Abhyankar       }
17422f63a38cSShri Abhyankar     }
17432f63a38cSShri Abhyankar     /* Update function and solution vectors */
17442f63a38cSShri Abhyankar     fnorm = gnorm;
17452f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
17462f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
17472f63a38cSShri Abhyankar     /* Monitor convergence */
17482f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
17492f63a38cSShri Abhyankar     snes->iter = i+1;
17502f63a38cSShri Abhyankar     snes->norm = fnorm;
17512f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
17522f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
17537a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
17542f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
17552f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
17562f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
17572f63a38cSShri Abhyankar     if (snes->reason) break;
17582f63a38cSShri Abhyankar   }
17592f63a38cSShri Abhyankar   if (i == maxits) {
17602f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
17612f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
17622f63a38cSShri Abhyankar   }
17632f63a38cSShri Abhyankar   PetscFunctionReturn(0);
17642f63a38cSShri Abhyankar }
17652f63a38cSShri Abhyankar 
17662b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17672b4ed282SShri Abhyankar /*
17682b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
17692b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
17702b4ed282SShri Abhyankar 
17712b4ed282SShri Abhyankar    Input Parameter:
17722b4ed282SShri Abhyankar .  snes - the SNES context
17732b4ed282SShri Abhyankar .  x - the solution vector
17742b4ed282SShri Abhyankar 
17752b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17762b4ed282SShri Abhyankar 
17772b4ed282SShri Abhyankar    Notes:
17782b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17792b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17802b4ed282SShri Abhyankar    the call to SNESSolve().
17812b4ed282SShri Abhyankar  */
17822b4ed282SShri Abhyankar #undef __FUNCT__
17832b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17842b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17852b4ed282SShri Abhyankar {
17862b4ed282SShri Abhyankar   PetscErrorCode ierr;
17872b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17882b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17892b4ed282SShri Abhyankar 
17902b4ed282SShri Abhyankar   PetscFunctionBegin;
179158c9b817SLisandro Dalcin 
179258c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17932b4ed282SShri Abhyankar 
17942176524cSBarry Smith   if (vi->computevariablebounds) {
179577cdaf69SJed Brown     if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);}
179677cdaf69SJed Brown     if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);}
179777cdaf69SJed Brown     ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr);
17982176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
17992176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
18002b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
180101f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
18022b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
180301f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
18042b4ed282SShri Abhyankar   } else {
18052b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
18062b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
18072b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
18082b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
18092b4ed282SShri 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]))
18102b4ed282SShri 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.");
18112b4ed282SShri Abhyankar   }
18122f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1813abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1814abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1815abcba341SShri Abhyankar     PetscInt *indices;
1816abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1817abcba341SShri Abhyankar 
1818abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1819abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1820abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1821abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1822abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1823abcba341SShri Abhyankar   }
18242b4ed282SShri Abhyankar 
18252f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1826fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1827fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1828fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1829fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1830fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1831fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1832fe835674SShri Abhyankar   }
18332b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18342b4ed282SShri Abhyankar }
18352b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18362176524cSBarry Smith #undef __FUNCT__
18372176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
18382176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
18392176524cSBarry Smith {
18402176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
18412176524cSBarry Smith   PetscErrorCode ierr;
18422176524cSBarry Smith 
18432176524cSBarry Smith   PetscFunctionBegin;
18442176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
18452176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1846d655a5daSBarry Smith   if (snes->ops->solve != SNESSolveVI_SS) {
1847d655a5daSBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1848d655a5daSBarry Smith   }
18492176524cSBarry Smith   PetscFunctionReturn(0);
18502176524cSBarry Smith }
18512176524cSBarry Smith 
18522b4ed282SShri Abhyankar /*
18532b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
18542b4ed282SShri Abhyankar    with SNESCreate_VI().
18552b4ed282SShri Abhyankar 
18562b4ed282SShri Abhyankar    Input Parameter:
18572b4ed282SShri Abhyankar .  snes - the SNES context
18582b4ed282SShri Abhyankar 
18592b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
18602b4ed282SShri Abhyankar  */
18612b4ed282SShri Abhyankar #undef __FUNCT__
18622b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
18632b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
18642b4ed282SShri Abhyankar {
18652b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
18662b4ed282SShri Abhyankar   PetscErrorCode ierr;
18672b4ed282SShri Abhyankar 
18682b4ed282SShri Abhyankar   PetscFunctionBegin;
18692b4ed282SShri Abhyankar 
18702f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18712b4ed282SShri Abhyankar     /* clear vectors */
18726bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18736bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18746bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18756bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18766bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18776bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18787fe79bc4SShri Abhyankar   }
18797fe79bc4SShri Abhyankar 
1880649052a6SBarry Smith   ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
18812b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18822b4ed282SShri Abhyankar 
18832b4ed282SShri Abhyankar   /* clear composed functions */
18842b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1885c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18862b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18872b4ed282SShri Abhyankar }
18887fe79bc4SShri Abhyankar 
18892b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18902b4ed282SShri Abhyankar #undef __FUNCT__
18912b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18922b4ed282SShri Abhyankar 
18932b4ed282SShri Abhyankar /*
18947fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18957fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18962b4ed282SShri Abhyankar 
18972b4ed282SShri Abhyankar */
1898ace3abfcSBarry 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)
18992b4ed282SShri Abhyankar {
19002b4ed282SShri Abhyankar   PetscErrorCode ierr;
19012b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1902ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
19032b4ed282SShri Abhyankar 
19042b4ed282SShri Abhyankar   PetscFunctionBegin;
19052b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
19062b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19072b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
19082b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1909c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1910c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1911c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1912c1a5e521SShri Abhyankar   }
1913c1a5e521SShri Abhyankar   if (changed_y) {
1914c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19157fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1916c1a5e521SShri Abhyankar   }
1917c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1918c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1919c1a5e521SShri Abhyankar   if (!snes->domainerror) {
19202f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
19217fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19227fe79bc4SShri Abhyankar     } else {
1923c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
19247fe79bc4SShri Abhyankar     }
192562cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1926c1a5e521SShri Abhyankar   }
1927c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1928649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1929e6337399SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr);
1930649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1931c1a5e521SShri Abhyankar   }
1932c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1933c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1934c1a5e521SShri Abhyankar }
1935c1a5e521SShri Abhyankar 
1936c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1937c1a5e521SShri Abhyankar #undef __FUNCT__
19382b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
19392b4ed282SShri Abhyankar 
19402b4ed282SShri Abhyankar /*
19412b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
19422b4ed282SShri Abhyankar */
1943ace3abfcSBarry 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)
19442b4ed282SShri Abhyankar {
19452b4ed282SShri Abhyankar   PetscErrorCode ierr;
19462b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1947ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
19482b4ed282SShri Abhyankar 
19492b4ed282SShri Abhyankar   PetscFunctionBegin;
19502b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
19512b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19522b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
19537fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19542b4ed282SShri Abhyankar   if (vi->postcheckstep) {
19552b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
19562b4ed282SShri Abhyankar   }
19572b4ed282SShri Abhyankar   if (changed_y) {
19582b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19597fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19602b4ed282SShri Abhyankar   }
19612b4ed282SShri Abhyankar 
19622b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
19632b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
19642b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19652b4ed282SShri Abhyankar   }
19662b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19672b4ed282SShri Abhyankar   PetscFunctionReturn(0);
19682b4ed282SShri Abhyankar }
19697fe79bc4SShri Abhyankar 
19702b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
19712b4ed282SShri Abhyankar #undef __FUNCT__
19722b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19732b4ed282SShri Abhyankar /*
19747fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19752b4ed282SShri Abhyankar */
1976ace3abfcSBarry 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)
19772b4ed282SShri Abhyankar {
1978fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1979fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1980fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1981fe835674SShri Abhyankar   PetscScalar    cinitslope;
1982fe835674SShri Abhyankar #endif
1983fe835674SShri Abhyankar   PetscErrorCode ierr;
1984fe835674SShri Abhyankar   PetscInt       count;
1985fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1986fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1987fe835674SShri Abhyankar   MPI_Comm       comm;
1988fe835674SShri Abhyankar 
1989fe835674SShri Abhyankar   PetscFunctionBegin;
1990fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1991fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1992fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1993fe835674SShri Abhyankar 
1994fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1995fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1996fe835674SShri Abhyankar     if (vi->lsmonitor) {
1997649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1998649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1999649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2000fe835674SShri Abhyankar     }
2001fe835674SShri Abhyankar     *gnorm = fnorm;
2002fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
2003fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
2004fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
2005fe835674SShri Abhyankar     goto theend1;
2006fe835674SShri Abhyankar   }
2007fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
2008fe835674SShri Abhyankar     if (vi->lsmonitor) {
2009649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2010e6337399SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Scaling step by %g old ynorm %g\n",(double)vi->maxstep/(*ynorm),(double)*ynorm);CHKERRQ(ierr);
2011649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2012fe835674SShri Abhyankar     }
2013fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
2014fe835674SShri Abhyankar     *ynorm = vi->maxstep;
2015fe835674SShri Abhyankar   }
2016fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
2017fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
2018fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
2019fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
2020fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
2021fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
2022fe835674SShri Abhyankar #else
2023fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
2024fe835674SShri Abhyankar #endif
2025fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
2026fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
2027fe835674SShri Abhyankar 
2028fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2029fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2030fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2031fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
2032fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2033fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2034fe835674SShri Abhyankar     goto theend1;
2035fe835674SShri Abhyankar   }
2036fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20372f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2038fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20397fe79bc4SShri Abhyankar   } else {
20407fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20417fe79bc4SShri Abhyankar   }
2042fe835674SShri Abhyankar   if (snes->domainerror) {
2043fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2044fe835674SShri Abhyankar     PetscFunctionReturn(0);
2045fe835674SShri Abhyankar   }
204662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2047e6337399SBarry Smith   ierr = PetscInfo4(snes,"Initial fnorm %g gnorm %g alpha %g initslope %g\n",(double)fnorm,(double)*gnorm,(double)vi->alpha,(double)initslope);CHKERRQ(ierr);
2048f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm ) { /* Sufficient reduction */
2049fe835674SShri Abhyankar     if (vi->lsmonitor) {
2050649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2051e6337399SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %g gnorm %g\n",(double)fnorm,(double)*gnorm);CHKERRQ(ierr);
2052649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2053fe835674SShri Abhyankar     }
2054fe835674SShri Abhyankar     goto theend1;
2055fe835674SShri Abhyankar   }
2056fe835674SShri Abhyankar 
2057fe835674SShri Abhyankar   /* Fit points with quadratic */
2058fe835674SShri Abhyankar   lambda     = 1.0;
2059fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
2060fe835674SShri Abhyankar   lambdaprev = lambda;
2061fe835674SShri Abhyankar   gnormprev  = *gnorm;
2062fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2063fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
2064fe835674SShri Abhyankar   else                         lambda = lambdatemp;
2065fe835674SShri Abhyankar 
2066fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2067fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2068fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2069fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
2070fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2071fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2072fe835674SShri Abhyankar     goto theend1;
2073fe835674SShri Abhyankar   }
2074fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20752f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2076fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20777fe79bc4SShri Abhyankar   } else {
20787fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20797fe79bc4SShri Abhyankar   }
2080fe835674SShri Abhyankar   if (snes->domainerror) {
2081fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2082fe835674SShri Abhyankar     PetscFunctionReturn(0);
2083fe835674SShri Abhyankar   }
208462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2085fe835674SShri Abhyankar   if (vi->lsmonitor) {
2086649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2087e6337399SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %g\n",(double)*gnorm);CHKERRQ(ierr);
2088649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2089fe835674SShri Abhyankar   }
2090f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm ) { /* sufficient reduction */
2091fe835674SShri Abhyankar     if (vi->lsmonitor) {
2092649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2093649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
2094649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2095fe835674SShri Abhyankar     }
2096fe835674SShri Abhyankar     goto theend1;
2097fe835674SShri Abhyankar   }
2098fe835674SShri Abhyankar 
2099fe835674SShri Abhyankar   /* Fit points with cubic */
2100fe835674SShri Abhyankar   count = 1;
2101fe835674SShri Abhyankar   while (PETSC_TRUE) {
2102fe835674SShri Abhyankar     if (lambda <= minlambda) {
2103fe835674SShri Abhyankar       if (vi->lsmonitor) {
2104649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2105649052a6SBarry Smith  	ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
2106649052a6SBarry 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);
2107649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2108fe835674SShri Abhyankar       }
2109fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2110fe835674SShri Abhyankar       break;
2111fe835674SShri Abhyankar     }
2112fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2113fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2114fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2115fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2116fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2117fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2118fe835674SShri Abhyankar     if (a == 0.0) {
2119fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2120fe835674SShri Abhyankar     } else {
2121fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2122fe835674SShri Abhyankar     }
2123fe835674SShri Abhyankar     lambdaprev = lambda;
2124fe835674SShri Abhyankar     gnormprev  = *gnorm;
2125fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2126fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2127fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2128fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2129fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2130fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2131fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2132fe835674SShri 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);
2133fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2134fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2135fe835674SShri Abhyankar       break;
2136fe835674SShri Abhyankar     }
2137fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21382f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2139fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21407fe79bc4SShri Abhyankar     } else {
21417fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21427fe79bc4SShri Abhyankar     }
2143fe835674SShri Abhyankar     if (snes->domainerror) {
2144fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2145fe835674SShri Abhyankar       PetscFunctionReturn(0);
2146fe835674SShri Abhyankar     }
214762cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2148f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* is reduction enough? */
2149fe835674SShri Abhyankar       if (vi->lsmonitor) {
2150e6337399SBarry Smith 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %g lambda=%18.16e\n",(double)*gnorm,(double)lambda);CHKERRQ(ierr);
2151fe835674SShri Abhyankar       }
2152fe835674SShri Abhyankar       break;
2153fe835674SShri Abhyankar     } else {
2154fe835674SShri Abhyankar       if (vi->lsmonitor) {
2155e6337399SBarry Smith         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %g lambda=%18.16e\n",(double)*gnorm,(double)lambda);CHKERRQ(ierr);
2156fe835674SShri Abhyankar       }
2157fe835674SShri Abhyankar     }
2158fe835674SShri Abhyankar     count++;
2159fe835674SShri Abhyankar   }
2160fe835674SShri Abhyankar   theend1:
2161fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2162fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2163fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2164fe835674SShri Abhyankar     if (changed_y) {
2165fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2166fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2167fe835674SShri Abhyankar     }
2168fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2169fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21702f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2171fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21727fe79bc4SShri Abhyankar       } else {
21737fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21747fe79bc4SShri Abhyankar       }
2175fe835674SShri Abhyankar       if (snes->domainerror) {
2176fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2177fe835674SShri Abhyankar         PetscFunctionReturn(0);
2178fe835674SShri Abhyankar       }
217962cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2180fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2181fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2182fe835674SShri Abhyankar     }
2183fe835674SShri Abhyankar   }
2184fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2185fe835674SShri Abhyankar   PetscFunctionReturn(0);
2186fe835674SShri Abhyankar }
2187fe835674SShri Abhyankar 
21882b4ed282SShri Abhyankar #undef __FUNCT__
21892b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21902b4ed282SShri Abhyankar /*
21917fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21922b4ed282SShri Abhyankar */
2193ace3abfcSBarry 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)
21942b4ed282SShri Abhyankar {
21952b4ed282SShri Abhyankar   /*
21962b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21972b4ed282SShri Abhyankar      minimization problem:
21982b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21992b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
22002b4ed282SShri Abhyankar    */
22012b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
22022b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
22032b4ed282SShri Abhyankar   PetscScalar    cinitslope;
22042b4ed282SShri Abhyankar #endif
22052b4ed282SShri Abhyankar   PetscErrorCode ierr;
22062b4ed282SShri Abhyankar   PetscInt       count;
22072b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2208ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
22092b4ed282SShri Abhyankar 
22102b4ed282SShri Abhyankar   PetscFunctionBegin;
22112b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22122b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
22132b4ed282SShri Abhyankar 
22142b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
22152b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2216c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2217649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2218649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
2219649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22202b4ed282SShri Abhyankar     }
22212b4ed282SShri Abhyankar     *gnorm = fnorm;
22222b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
22232b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
22242b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
22252b4ed282SShri Abhyankar     goto theend2;
22262b4ed282SShri Abhyankar   }
22272b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
22282b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
22292b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
22302b4ed282SShri Abhyankar   }
22312b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
22322b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
22337fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
22342b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
22357fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
22362b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
22372b4ed282SShri Abhyankar #else
22387fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
22392b4ed282SShri Abhyankar #endif
22402b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
22412b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
22422b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
22432b4ed282SShri Abhyankar 
22442b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22457fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22462b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
22472b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
22482b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
22492b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22502b4ed282SShri Abhyankar     goto theend2;
22512b4ed282SShri Abhyankar   }
22522b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22532f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
22547fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22557fe79bc4SShri Abhyankar   } else {
22567fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22577fe79bc4SShri Abhyankar   }
22582b4ed282SShri Abhyankar   if (snes->domainerror) {
22592b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22602b4ed282SShri Abhyankar     PetscFunctionReturn(0);
22612b4ed282SShri Abhyankar   }
226262cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2263f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm) { /* Sufficient reduction */
2264c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2265649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2266649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
2267649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22682b4ed282SShri Abhyankar     }
22692b4ed282SShri Abhyankar     goto theend2;
22702b4ed282SShri Abhyankar   }
22712b4ed282SShri Abhyankar 
22722b4ed282SShri Abhyankar   /* Fit points with quadratic */
22732b4ed282SShri Abhyankar   lambda = 1.0;
22742b4ed282SShri Abhyankar   count = 1;
22752b4ed282SShri Abhyankar   while (PETSC_TRUE) {
22762b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2277c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2278649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2279649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2280649052a6SBarry 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);
2281649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22822b4ed282SShri Abhyankar       }
22832b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
22842b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22852b4ed282SShri Abhyankar       break;
22862b4ed282SShri Abhyankar     }
22872b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
22882b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
22892b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
22902b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22912b4ed282SShri Abhyankar 
22922b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22937fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22942b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22952b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
22962b4ed282SShri 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);
22972b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22982b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22992b4ed282SShri Abhyankar       break;
23002b4ed282SShri Abhyankar     }
23012b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
23022b4ed282SShri Abhyankar     if (snes->domainerror) {
23032b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23042b4ed282SShri Abhyankar       PetscFunctionReturn(0);
23052b4ed282SShri Abhyankar     }
23062f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
23077fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
23087fe79bc4SShri Abhyankar     } else {
23092b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
23107fe79bc4SShri Abhyankar     }
231162cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2312f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* sufficient reduction */
2313c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2314649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2315649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
2316649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
23172b4ed282SShri Abhyankar       }
23182b4ed282SShri Abhyankar       break;
23192b4ed282SShri Abhyankar     }
23202b4ed282SShri Abhyankar     count++;
23212b4ed282SShri Abhyankar   }
23222b4ed282SShri Abhyankar   theend2:
23232b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
23242b4ed282SShri Abhyankar   if (vi->postcheckstep) {
23252b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
23262b4ed282SShri Abhyankar     if (changed_y) {
23272b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
23287fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
23292b4ed282SShri Abhyankar     }
23302b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
23312b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
23322b4ed282SShri Abhyankar       if (snes->domainerror) {
23332b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23342b4ed282SShri Abhyankar         PetscFunctionReturn(0);
23352b4ed282SShri Abhyankar       }
23362f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
23377fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
23387fe79bc4SShri Abhyankar       } else {
23397fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
23407fe79bc4SShri Abhyankar       }
23417fe79bc4SShri Abhyankar 
23422b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
23432b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
234462cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
23452b4ed282SShri Abhyankar     }
23462b4ed282SShri Abhyankar   }
23472b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23482b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23492b4ed282SShri Abhyankar }
23502b4ed282SShri Abhyankar 
2351ace3abfcSBarry 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*/
23522b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23532b4ed282SShri Abhyankar EXTERN_C_BEGIN
23542b4ed282SShri Abhyankar #undef __FUNCT__
23552b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
23567087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
23572b4ed282SShri Abhyankar {
23582b4ed282SShri Abhyankar   PetscFunctionBegin;
23592b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
23602b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
23612b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23622b4ed282SShri Abhyankar }
23632b4ed282SShri Abhyankar EXTERN_C_END
23642b4ed282SShri Abhyankar 
23652b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23662b4ed282SShri Abhyankar EXTERN_C_BEGIN
23672b4ed282SShri Abhyankar #undef __FUNCT__
23682b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
23697087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
23702b4ed282SShri Abhyankar {
23712b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
23722b4ed282SShri Abhyankar   PetscErrorCode ierr;
23732b4ed282SShri Abhyankar 
23742b4ed282SShri Abhyankar   PetscFunctionBegin;
2375c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2376649052a6SBarry Smith     ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr);
2377c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
2378649052a6SBarry Smith     ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
23792b4ed282SShri Abhyankar   }
23802b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23812b4ed282SShri Abhyankar }
23822b4ed282SShri Abhyankar EXTERN_C_END
23832b4ed282SShri Abhyankar 
23842b4ed282SShri Abhyankar /*
23852b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
23862b4ed282SShri Abhyankar 
23872b4ed282SShri Abhyankar    Input Parameters:
23882b4ed282SShri Abhyankar .  SNES - the SNES context
23892b4ed282SShri Abhyankar .  viewer - visualization context
23902b4ed282SShri Abhyankar 
23912b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
23922b4ed282SShri Abhyankar */
23932b4ed282SShri Abhyankar #undef __FUNCT__
23942b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23952b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23962b4ed282SShri Abhyankar {
23972b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
239878c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23992b4ed282SShri Abhyankar   PetscErrorCode ierr;
2400ace3abfcSBarry Smith   PetscBool     iascii;
24012b4ed282SShri Abhyankar 
24022b4ed282SShri Abhyankar   PetscFunctionBegin;
24032b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
24042b4ed282SShri Abhyankar   if (iascii) {
24052b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
24062b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
24072b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
24082b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
240978c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
24100a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2411b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
241278c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
241378c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
24142b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
24152b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
24162b4ed282SShri Abhyankar   }
24172b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24182b4ed282SShri Abhyankar }
24192b4ed282SShri Abhyankar 
24205559b345SBarry Smith #undef __FUNCT__
24215559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
24225559b345SBarry Smith /*@
24232b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
24242b4ed282SShri Abhyankar 
24252b4ed282SShri Abhyankar    Input Parameters:
24262b4ed282SShri Abhyankar .  snes - the SNES context.
24272b4ed282SShri Abhyankar .  xl   - lower bound.
24282b4ed282SShri Abhyankar .  xu   - upper bound.
24292b4ed282SShri Abhyankar 
24302b4ed282SShri Abhyankar    Notes:
24312b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
243201f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
243384c105d7SBarry Smith 
2434*2bd2b0e6SSatish Balay    Level: advanced
2435*2bd2b0e6SSatish Balay 
24365559b345SBarry Smith @*/
243769c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
24382b4ed282SShri Abhyankar {
2439d923200aSJungho Lee   SNES_VI           *vi;
2440d923200aSJungho Lee   PetscErrorCode    ierr;
24416fd67740SBarry Smith   const PetscScalar *xxl,*xxu;
24426fd67740SBarry Smith   PetscInt          i,n, cnt = 0;
24432b4ed282SShri Abhyankar 
24442b4ed282SShri Abhyankar   PetscFunctionBegin;
24452b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
24462b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
24472b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
24482b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
24492b4ed282SShri 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);
24502b4ed282SShri 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);
2451d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2452d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
24532176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
24542176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
24552176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
24562176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
24572b4ed282SShri Abhyankar   vi->xl = xl;
24582b4ed282SShri Abhyankar   vi->xu = xu;
24596fd67740SBarry Smith   ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr);
24606fd67740SBarry Smith   ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr);
24616fd67740SBarry Smith   ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr);
24626fd67740SBarry Smith   for (i=0; i<n; i++) {
24636fd67740SBarry Smith     cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF));
24646fd67740SBarry Smith   }
24656fd67740SBarry Smith   ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
24666fd67740SBarry Smith   ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr);
24676fd67740SBarry Smith   ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr);
24682b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24692b4ed282SShri Abhyankar }
2470693ddf92SShri Abhyankar 
24712b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24722b4ed282SShri Abhyankar /*
24732b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
24742b4ed282SShri Abhyankar 
24752b4ed282SShri Abhyankar    Input Parameter:
24762b4ed282SShri Abhyankar .  snes - the SNES context
24772b4ed282SShri Abhyankar 
24782b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
24792b4ed282SShri Abhyankar */
24802b4ed282SShri Abhyankar #undef __FUNCT__
24812b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
24822b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
24832b4ed282SShri Abhyankar {
24842b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
24857fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2486b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
24872b4ed282SShri Abhyankar   PetscErrorCode ierr;
24882b4ed282SShri Abhyankar   PetscInt       indx;
248969c03620SShri Abhyankar   PetscBool      flg,set,flg2;
24902b4ed282SShri Abhyankar 
24912b4ed282SShri Abhyankar   PetscFunctionBegin;
24922b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
24939308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
24949308c137SBarry Smith   if (flg) {
24959308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
24969308c137SBarry Smith   }
2497be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2498be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2499be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
25002b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2501be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
25022b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
25035b071b1aSBarry Smith   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"rs",&indx,&flg2);CHKERRQ(ierr);
250469c03620SShri Abhyankar   if (flg2) {
250569c03620SShri Abhyankar     switch (indx) {
250669c03620SShri Abhyankar     case 0:
250769c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
250869c03620SShri Abhyankar       break;
250969c03620SShri Abhyankar     case 1:
2510d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2511d950fb63SShri Abhyankar       break;
25122f63a38cSShri Abhyankar     case 2:
2513b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
251469c03620SShri Abhyankar     }
251569c03620SShri Abhyankar   }
2516f2b03b96SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"cubic",&indx,&flg);CHKERRQ(ierr);
25172b4ed282SShri Abhyankar   if (flg) {
25182b4ed282SShri Abhyankar     switch (indx) {
25192b4ed282SShri Abhyankar     case 0:
25202b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
25212b4ed282SShri Abhyankar       break;
25222b4ed282SShri Abhyankar     case 1:
25232b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
25242b4ed282SShri Abhyankar       break;
25252b4ed282SShri Abhyankar     case 2:
25262b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
25272b4ed282SShri Abhyankar       break;
25282b4ed282SShri Abhyankar     case 3:
25292b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
25302b4ed282SShri Abhyankar       break;
25312b4ed282SShri Abhyankar     }
2532fe835674SShri Abhyankar   }
2533e6337399SBarry Smith   ierr = PetscOptionsBool("-snes_vi_ignore_function_sign","Ignore the sign of function for active constraints","None",vi->ignorefunctionsign,&vi->ignorefunctionsign,PETSC_NULL);CHKERRQ(ierr);
25342b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
25352b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25362b4ed282SShri Abhyankar }
25372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
25382b4ed282SShri Abhyankar /*MC
25398b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
25402b4ed282SShri Abhyankar 
25412b4ed282SShri Abhyankar    Options Database:
25428b4c83edSBarry 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
25438b4c83edSBarry Smith                                 additional variables that enforce the constraints
25448b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
25452b4ed282SShri Abhyankar 
25462b4ed282SShri Abhyankar 
25472b4ed282SShri Abhyankar    Level: beginner
25482b4ed282SShri Abhyankar 
25492b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
25502b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
25512b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
25522b4ed282SShri Abhyankar 
25532b4ed282SShri Abhyankar M*/
25542b4ed282SShri Abhyankar EXTERN_C_BEGIN
25552b4ed282SShri Abhyankar #undef __FUNCT__
25562b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
25577087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
25582b4ed282SShri Abhyankar {
25592b4ed282SShri Abhyankar   PetscErrorCode ierr;
25602b4ed282SShri Abhyankar   SNES_VI        *vi;
25612b4ed282SShri Abhyankar 
25622b4ed282SShri Abhyankar   PetscFunctionBegin;
25632176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
25642b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2565edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
25662b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
25672b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
25682b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
25692b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
25702b4ed282SShri Abhyankar 
25712b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
25722b4ed282SShri Abhyankar   snes->data            = (void*)vi;
25732b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
25742b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
25752b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
2576f2b03b96SBarry Smith   vi->LineSearch        = SNESLineSearchCubic_VI;
25772b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
25782b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
25792b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
25802b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
25812b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
25822b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
25832f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
25842b4ed282SShri Abhyankar 
25852b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
25862b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
25872b4ed282SShri Abhyankar 
25882b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25892b4ed282SShri Abhyankar }
25902b4ed282SShri Abhyankar EXTERN_C_END
2591ed70e96aSJungho Lee 
2592ed70e96aSJungho Lee #undef __FUNCT__
2593ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet"
2594ed70e96aSJungho Lee /*
2595ed70e96aSJungho Lee    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
2596ed70e96aSJungho Lee      system is solved on)
2597ed70e96aSJungho Lee 
2598ed70e96aSJungho Lee    Input parameter
2599ed70e96aSJungho Lee .  snes - the SNES context
2600ed70e96aSJungho Lee 
2601ed70e96aSJungho Lee    Output parameter
2602ed70e96aSJungho Lee .  ISact - active set index set
2603ed70e96aSJungho Lee 
2604ed70e96aSJungho Lee  */
2605ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact)
2606ed70e96aSJungho Lee {
2607ed70e96aSJungho Lee   SNES_VI          *vi = (SNES_VI*)snes->data;
2608ed70e96aSJungho Lee   PetscFunctionBegin;
2609ed70e96aSJungho Lee   *inact = vi->IS_inact_prev;
2610ed70e96aSJungho Lee   PetscFunctionReturn(0);
2611ed70e96aSJungho Lee }
2612