xref: /petsc/src/snes/impls/vi/vi.c (revision f137e44d2ae6b3c349ef7d0932e365d58e3b7e62)
12b4ed282SShri Abhyankar 
2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/
3c6db04a5SJed Brown #include <../include/private/kspimpl.h>
4c6db04a5SJed Brown #include <../include/private/matimpl.h>
5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h>
6d0af7cd3SBarry Smith 
7d0af7cd3SBarry Smith #undef __FUNCT__
82176524cSBarry Smith #define __FUNCT__ "SNESVISetComputeVariableBounds"
92176524cSBarry Smith /*@C
102176524cSBarry Smith    SNESVISetComputeVariableBounds - Sets a function  that is called to compute the variable bounds
112176524cSBarry Smith 
122176524cSBarry Smith    Input parameter
132176524cSBarry Smith +  snes - the SNES context
142176524cSBarry Smith -  compute - computes the bounds
152176524cSBarry Smith 
162176524cSBarry Smith 
17aab9d709SJed Brown @*/
1877cdaf69SJed Brown PetscErrorCode SNESVISetComputeVariableBounds(SNES snes, PetscErrorCode (*compute)(SNES,Vec,Vec))
192176524cSBarry Smith {
202176524cSBarry Smith   PetscErrorCode   ierr;
212176524cSBarry Smith   SNES_VI          *vi;
222176524cSBarry Smith 
232176524cSBarry Smith   PetscFunctionBegin;
242176524cSBarry Smith   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
252176524cSBarry Smith   vi = (SNES_VI*)snes->data;
262176524cSBarry Smith   vi->computevariablebounds = compute;
272176524cSBarry Smith   PetscFunctionReturn(0);
282176524cSBarry Smith }
292176524cSBarry Smith 
302176524cSBarry Smith 
312176524cSBarry Smith #undef __FUNCT__
32ed70e96aSJungho Lee #define __FUNCT__ "SNESVIComputeInactiveSetIS"
33d0af7cd3SBarry Smith /*
34ed70e96aSJungho Lee    SNESVIComputeInactiveSetIS - Gets the global indices for the bogus inactive set variables
35d0af7cd3SBarry Smith 
36d0af7cd3SBarry Smith    Input parameter
37d0af7cd3SBarry Smith .  snes - the SNES context
38d0af7cd3SBarry Smith .  X    - the snes solution vector
39d0af7cd3SBarry Smith 
40d0af7cd3SBarry Smith    Output parameter
41d0af7cd3SBarry Smith .  ISact - active set index set
42d0af7cd3SBarry Smith 
43d0af7cd3SBarry Smith  */
44ed70e96aSJungho Lee PetscErrorCode SNESVIComputeInactiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
45d0af7cd3SBarry Smith {
46d0af7cd3SBarry Smith   PetscErrorCode   ierr;
47d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
48d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
49d0af7cd3SBarry Smith 
50d0af7cd3SBarry Smith   PetscFunctionBegin;
51d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
52d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
53d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
54d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
55d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
56d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
57d0af7cd3SBarry Smith   /* Compute inactive set size */
58d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
59d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
60d0af7cd3SBarry Smith   }
61d0af7cd3SBarry Smith 
62d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
63d0af7cd3SBarry Smith 
64d0af7cd3SBarry Smith   /* Set inactive set indices */
65d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
66d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
67d0af7cd3SBarry Smith   }
68d0af7cd3SBarry Smith 
69d0af7cd3SBarry Smith    /* Create inactive set IS */
70d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
71d0af7cd3SBarry Smith 
72d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
73d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
74d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
75d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
76d0af7cd3SBarry Smith   PetscFunctionReturn(0);
77d0af7cd3SBarry Smith }
78d0af7cd3SBarry Smith 
793c0c59f3SBarry Smith /*
803c0c59f3SBarry Smith     Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors
813c0c59f3SBarry Smith   defined by the reduced space method.
823c0c59f3SBarry Smith 
833c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
843c0c59f3SBarry Smith 
85ed70e96aSJungho Lee <*/
863c0c59f3SBarry Smith typedef struct {
873c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
883c0c59f3SBarry Smith   IS             inactive;
893c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
903c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
913c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
924c661befSBarry Smith   DM             dm;                                      /* when destroying this object we need to reset the above function into the base DM */
933c0c59f3SBarry Smith } DM_SNESVI;
943c0c59f3SBarry Smith 
95d0af7cd3SBarry Smith #undef __FUNCT__
964dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
974dcab191SBarry Smith /*
984dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
994dcab191SBarry Smith 
1004dcab191SBarry Smith */
1014dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
1024dcab191SBarry Smith {
1034dcab191SBarry Smith   PetscErrorCode          ierr;
1044dcab191SBarry Smith   PetscContainer          isnes;
1053c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
1064dcab191SBarry Smith 
1074dcab191SBarry Smith   PetscFunctionBegin;
1084dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1094dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
1104dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
1114dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
1124dcab191SBarry Smith   PetscFunctionReturn(0);
1134dcab191SBarry Smith }
1144dcab191SBarry Smith 
1154dcab191SBarry Smith #undef __FUNCT__
116d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
117d0af7cd3SBarry Smith /*
118d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
119d0af7cd3SBarry Smith 
120d0af7cd3SBarry Smith */
121d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
122d0af7cd3SBarry Smith {
123d0af7cd3SBarry Smith   PetscErrorCode          ierr;
124d0af7cd3SBarry Smith   PetscContainer          isnes;
1253c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
126d0af7cd3SBarry Smith   Mat                     interp;
127d0af7cd3SBarry Smith 
128d0af7cd3SBarry Smith   PetscFunctionBegin;
129d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1304c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
131d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
132d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1334c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
134d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
135d0af7cd3SBarry Smith 
136d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1374dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
138d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
13900ac8be1SBarry Smith   *vec = 0;
140d0af7cd3SBarry Smith   PetscFunctionReturn(0);
141d0af7cd3SBarry Smith }
142d0af7cd3SBarry Smith 
1439ce20c35SJungho Lee extern PetscErrorCode  DMSetVI(DM,IS);
144d0af7cd3SBarry Smith 
145d0af7cd3SBarry Smith #undef __FUNCT__
146d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
147d0af7cd3SBarry Smith /*
148d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
149d0af7cd3SBarry Smith 
150d0af7cd3SBarry Smith */
151d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
152d0af7cd3SBarry Smith {
153d0af7cd3SBarry Smith   PetscErrorCode          ierr;
154d0af7cd3SBarry Smith   PetscContainer          isnes;
1553c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
1569ce20c35SJungho Lee   Vec                     finemarked,coarsemarked;
157d0af7cd3SBarry Smith   IS                      inactive;
158d0af7cd3SBarry Smith   VecScatter              inject;
1599ce20c35SJungho Lee   const PetscInt          *index;
1609ce20c35SJungho Lee   PetscInt                n,k,cnt = 0,rstart,*coarseindex;
1619ce20c35SJungho Lee   PetscScalar             *marked;
162d0af7cd3SBarry Smith 
163d0af7cd3SBarry Smith   PetscFunctionBegin;
164d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1654c661befSBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
166d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
167d0af7cd3SBarry Smith 
168298cc208SBarry Smith   /* get the original coarsen */
169d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
170298cc208SBarry Smith 
1713c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
1723c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
1733c0c59f3SBarry Smith 
174298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
175298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
176298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
1779ce20c35SJungho Lee   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
1789ce20c35SJungho Lee   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
1799ce20c35SJungho Lee 
1809ce20c35SJungho Lee   /*
1819ce20c35SJungho Lee      fill finemarked with locations of inactive points
1829ce20c35SJungho Lee   */
1839ce20c35SJungho Lee   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
1849ce20c35SJungho Lee   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
1859ce20c35SJungho Lee   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
1869ce20c35SJungho Lee   for (k=0;k<n;k++){
1879ce20c35SJungho Lee       ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
1889ce20c35SJungho Lee   }
1899ce20c35SJungho Lee   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
1909ce20c35SJungho Lee   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
1919ce20c35SJungho Lee 
192d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
1939ce20c35SJungho Lee   ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1949ce20c35SJungho Lee   ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
195d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
1969ce20c35SJungho Lee 
1979ce20c35SJungho Lee   /*
1989ce20c35SJungho Lee      create index set list of coarse inactive points from coarsemarked
1999ce20c35SJungho Lee   */
2009ce20c35SJungho Lee   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
2019ce20c35SJungho Lee   ierr = VecGetOwnershipRange(coarsemarked,&rstart,PETSC_NULL);CHKERRQ(ierr);
2029ce20c35SJungho Lee   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
2039ce20c35SJungho Lee   for (k=0; k<n; k++) {
204ff207688SJed Brown     if (marked[k] != 0.0) cnt++;
2059ce20c35SJungho Lee   }
2069ce20c35SJungho Lee   ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr);
2079ce20c35SJungho Lee   cnt  = 0;
2089ce20c35SJungho Lee   for (k=0; k<n; k++) {
209ff207688SJed Brown     if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart;
2109ce20c35SJungho Lee   }
2119ce20c35SJungho Lee   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
2129ce20c35SJungho Lee   ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
2139ce20c35SJungho Lee 
214298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
215298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
2169ce20c35SJungho Lee   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
2179ce20c35SJungho Lee 
2189ce20c35SJungho Lee   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
2199ce20c35SJungho Lee   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
2203c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
221d0af7cd3SBarry Smith   PetscFunctionReturn(0);
222d0af7cd3SBarry Smith }
223d0af7cd3SBarry Smith 
224d0af7cd3SBarry Smith #undef __FUNCT__
2253c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
2263c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
227d0af7cd3SBarry Smith {
228d0af7cd3SBarry Smith   PetscErrorCode ierr;
229d0af7cd3SBarry Smith 
230d0af7cd3SBarry Smith   PetscFunctionBegin;
2314c661befSBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
2324c661befSBarry Smith   dmsnesvi->dm->ops->getinterpolation   = dmsnesvi->getinterpolation;
2334c661befSBarry Smith   dmsnesvi->dm->ops->coarsen            = dmsnesvi->coarsen;
2344c661befSBarry Smith   dmsnesvi->dm->ops->createglobalvector = dmsnesvi->createglobalvector;
23500ac8be1SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
23600ac8be1SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
23700ac8be1SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
2384c661befSBarry Smith 
239d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
240d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
241d0af7cd3SBarry Smith   PetscFunctionReturn(0);
242d0af7cd3SBarry Smith }
243d0af7cd3SBarry Smith 
244d0af7cd3SBarry Smith #undef __FUNCT__
245d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
246d0af7cd3SBarry Smith /*
247d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
248d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
249d0af7cd3SBarry Smith 
250d0af7cd3SBarry Smith */
2519ce20c35SJungho Lee PetscErrorCode  DMSetVI(DM dm,IS inactive)
252d0af7cd3SBarry Smith {
253d0af7cd3SBarry Smith   PetscErrorCode          ierr;
254d0af7cd3SBarry Smith   PetscContainer          isnes;
2553c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
256d0af7cd3SBarry Smith 
257d0af7cd3SBarry Smith   PetscFunctionBegin;
2584dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
2591c0a9e84SBarry Smith 
260d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
261d0af7cd3SBarry Smith 
262d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
263d0af7cd3SBarry Smith   if (!isnes) {
264d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
2653c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
2663c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
267d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
268d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
2693c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
270d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
271d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
272d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
273d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
274298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2754dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
276d0af7cd3SBarry Smith   } else {
277d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
278d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
279d0af7cd3SBarry Smith   }
2804dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2814dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
282d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
2831a223a97SBarry Smith   dmsnesvi->dm       = dm;
284d0af7cd3SBarry Smith   PetscFunctionReturn(0);
285d0af7cd3SBarry Smith }
286d0af7cd3SBarry Smith 
2874c661befSBarry Smith #undef __FUNCT__
2884c661befSBarry Smith #define __FUNCT__ "DMDestroyVI"
2894c661befSBarry Smith /*
2904c661befSBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
2914c661befSBarry Smith          - also resets the function pointers in the DM for getinterpolation() etc to use the original DM
2924c661befSBarry Smith */
2934c661befSBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
2944c661befSBarry Smith {
2954c661befSBarry Smith   PetscErrorCode          ierr;
2964c661befSBarry Smith 
2974c661befSBarry Smith   PetscFunctionBegin;
2984c661befSBarry Smith   if (!dm) PetscFunctionReturn(0);
2994c661befSBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)PETSC_NULL);CHKERRQ(ierr);
3004c661befSBarry Smith   PetscFunctionReturn(0);
3014c661befSBarry Smith }
3024c661befSBarry Smith 
3033c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
3042b4ed282SShri Abhyankar 
3059308c137SBarry Smith #undef __FUNCT__
3069308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
3077087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
3089308c137SBarry Smith {
3099308c137SBarry Smith   PetscErrorCode    ierr;
3109308c137SBarry Smith   SNES_VI            *vi = (SNES_VI*)snes->data;
311649052a6SBarry Smith   PetscViewer        viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)snes)->comm);
3129308c137SBarry Smith   const PetscScalar  *x,*xl,*xu,*f;
3136fd67740SBarry Smith   PetscInt           i,n,act[2] = {0,0},fact[2],N;
3146a9e2d46SJungho Lee   /* remove later */
3156a9e2d46SJungho Lee   /* Number of components that actually hit the bounds (c.f. active variables) */
3166a9e2d46SJungho Lee   PetscInt           act_bound[2] = {0,0},fact_bound[2];
3179308c137SBarry Smith   PetscReal          rnorm,fnorm;
3189308c137SBarry Smith 
3199308c137SBarry Smith   PetscFunctionBegin;
3209308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
3216fd67740SBarry Smith   ierr = VecGetSize(snes->vec_sol,&N);CHKERRQ(ierr);
3229308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3239308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3249308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
3253f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3269308c137SBarry Smith 
3279308c137SBarry Smith   rnorm = 0.0;
3289308c137SBarry Smith   for (i=0; i<n; i++) {
32910f5ae6bSBarry 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]);
330e400df7aSBarry Smith     else if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8 && PetscRealPart(f[i]) >= 0.0) act[0]++;
331e400df7aSBarry Smith     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8 && PetscRealPart(f[i]) <= 0.0) act[1]++;
332e400df7aSBarry Smith     else SETERRQ(((PetscObject)snes)->comm,PETSC_ERR_PLIB,"Can never get here");
3339308c137SBarry Smith   }
3346a9e2d46SJungho Lee 
3356a9e2d46SJungho Lee   /* Remove later, number of components that actually hit the bounds */
3366a9e2d46SJungho Lee   for (i=0; i<n; i++) {
3376a9e2d46SJungho Lee     if (PetscRealPart(x[i]) <= PetscRealPart(xl[i]) + 1.e-8) act_bound[0]++;
3386a9e2d46SJungho Lee     else if (PetscRealPart(x[i]) >= PetscRealPart(xu[i]) - 1.e-8) act_bound[1]++;
3396a9e2d46SJungho Lee   }
3403f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
3419308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
3429308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
3439308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
344d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
34521a4c9b1SBarry Smith   ierr = MPI_Allreduce(act,fact,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
3466a9e2d46SJungho Lee   /* remove later */
3476a9e2d46SJungho Lee   ierr = MPI_Allreduce(act_bound,fact_bound,2,MPIU_INT,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
348*f137e44dSBarry Smith   fnorm = PetscSqrtReal(fnorm);
3496fd67740SBarry Smith 
350649052a6SBarry Smith   ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
351*f137e44dSBarry 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);
352*f137e44dSBarry Smith   ierr = PetscViewerASCIIPrintf(viewer,"                               lower constraints satisfied %D upper constraints satisfied %D\n",its,fact_bound[0],fact_bound[1]);CHKERRQ(ierr);
3536a9e2d46SJungho Lee 
354649052a6SBarry Smith   ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
3559308c137SBarry Smith   PetscFunctionReturn(0);
3569308c137SBarry Smith }
3579308c137SBarry Smith 
3582b4ed282SShri Abhyankar /*
3592b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
3602b4ed282SShri 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
3612b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
3622b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
3632b4ed282SShri Abhyankar */
3642b4ed282SShri Abhyankar #undef __FUNCT__
3652b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
366ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
3672b4ed282SShri Abhyankar {
3682b4ed282SShri Abhyankar   PetscReal      a1;
3692b4ed282SShri Abhyankar   PetscErrorCode ierr;
370ace3abfcSBarry Smith   PetscBool     hastranspose;
3712b4ed282SShri Abhyankar 
3722b4ed282SShri Abhyankar   PetscFunctionBegin;
3732b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3742b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3752b4ed282SShri Abhyankar   if (hastranspose) {
3762b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3772b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3782b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3792b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3802b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3812b4ed282SShri Abhyankar   } else {
3822b4ed282SShri Abhyankar     Vec         work;
3832b4ed282SShri Abhyankar     PetscScalar result;
3842b4ed282SShri Abhyankar     PetscReal   wnorm;
3852b4ed282SShri Abhyankar 
3862b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3872b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3882b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3892b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3902b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3916bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3922b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3932b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3942b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3952b4ed282SShri Abhyankar   }
3962b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3972b4ed282SShri Abhyankar }
3982b4ed282SShri Abhyankar 
3992b4ed282SShri Abhyankar /*
4002b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
4012b4ed282SShri Abhyankar */
4022b4ed282SShri Abhyankar #undef __FUNCT__
4032b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
4042b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
4052b4ed282SShri Abhyankar {
4062b4ed282SShri Abhyankar   PetscReal      a1,a2;
4072b4ed282SShri Abhyankar   PetscErrorCode ierr;
408ace3abfcSBarry Smith   PetscBool     hastranspose;
4092b4ed282SShri Abhyankar 
4102b4ed282SShri Abhyankar   PetscFunctionBegin;
4112b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
4122b4ed282SShri Abhyankar   if (hastranspose) {
4132b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
4142b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
4152b4ed282SShri Abhyankar 
4162b4ed282SShri Abhyankar     /* Compute || J^T W|| */
4172b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
4182b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
4192b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
4202b4ed282SShri Abhyankar     if (a1 != 0.0) {
4212b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
4222b4ed282SShri Abhyankar     }
4232b4ed282SShri Abhyankar   }
4242b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4252b4ed282SShri Abhyankar }
4262b4ed282SShri Abhyankar 
4272b4ed282SShri Abhyankar /*
4282b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
4292b4ed282SShri Abhyankar 
4302b4ed282SShri Abhyankar   Notes:
4312b4ed282SShri Abhyankar   The convergence criterion currently implemented is
4322b4ed282SShri Abhyankar   merit < abstol
4332b4ed282SShri Abhyankar   merit < rtol*merit_initial
4342b4ed282SShri Abhyankar */
4352b4ed282SShri Abhyankar #undef __FUNCT__
4362b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
4377fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
4382b4ed282SShri Abhyankar {
4392b4ed282SShri Abhyankar   PetscErrorCode ierr;
4402b4ed282SShri Abhyankar 
4412b4ed282SShri Abhyankar   PetscFunctionBegin;
4422b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
4432b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
4442b4ed282SShri Abhyankar 
4452b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
4462b4ed282SShri Abhyankar 
4472b4ed282SShri Abhyankar   if (!it) {
4482b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
4497fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
4502b4ed282SShri Abhyankar   }
4517fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
4522b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
4532b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
4547fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
4557fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
4562b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
4572b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
4582b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
4592b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
4602b4ed282SShri Abhyankar   }
4612b4ed282SShri Abhyankar 
4622b4ed282SShri Abhyankar   if (it && !*reason) {
4637fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
4647fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
4652b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
4662b4ed282SShri Abhyankar     }
4672b4ed282SShri Abhyankar   }
4682b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4692b4ed282SShri Abhyankar }
4702b4ed282SShri Abhyankar 
4712b4ed282SShri Abhyankar /*
4722b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4732b4ed282SShri Abhyankar 
4742b4ed282SShri Abhyankar   Input Parameter:
4752b4ed282SShri Abhyankar . phi - the semismooth function
4762b4ed282SShri Abhyankar 
4772b4ed282SShri Abhyankar   Output Parameter:
4782b4ed282SShri Abhyankar . merit - the merit function
4792b4ed282SShri Abhyankar . phinorm - ||phi||
4802b4ed282SShri Abhyankar 
4812b4ed282SShri Abhyankar   Notes:
4822b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4832b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4842b4ed282SShri Abhyankar */
4852b4ed282SShri Abhyankar #undef __FUNCT__
4862b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4872b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4882b4ed282SShri Abhyankar {
4892b4ed282SShri Abhyankar   PetscErrorCode ierr;
4902b4ed282SShri Abhyankar 
4912b4ed282SShri Abhyankar   PetscFunctionBegin;
4925f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4935f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4942b4ed282SShri Abhyankar 
4952b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4962b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4972b4ed282SShri Abhyankar }
4982b4ed282SShri Abhyankar 
4997f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
5004c21c6cdSBarry Smith {
5014c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
5024c21c6cdSBarry Smith }
5034c21c6cdSBarry Smith 
5047f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
5054c21c6cdSBarry Smith {
5065559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
5075559b345SBarry Smith   else return .5;
5084c21c6cdSBarry Smith }
5094c21c6cdSBarry Smith 
5102b4ed282SShri Abhyankar /*
5111f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
5122b4ed282SShri Abhyankar 
5132b4ed282SShri Abhyankar    Input Parameters:
5142b4ed282SShri Abhyankar .  snes - the SNES context
5152b4ed282SShri Abhyankar .  x - current iterate
5162b4ed282SShri Abhyankar .  functx - user defined function context
5172b4ed282SShri Abhyankar 
5182b4ed282SShri Abhyankar    Output Parameters:
5192b4ed282SShri Abhyankar .  phi - Semismooth function
5202b4ed282SShri Abhyankar 
5212b4ed282SShri Abhyankar */
5222b4ed282SShri Abhyankar #undef __FUNCT__
5231f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
5241f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
5252b4ed282SShri Abhyankar {
5262b4ed282SShri Abhyankar   PetscErrorCode  ierr;
5272b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
5282b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
5294c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
5302b4ed282SShri Abhyankar   PetscInt        i,nlocal;
5312b4ed282SShri Abhyankar 
5322b4ed282SShri Abhyankar   PetscFunctionBegin;
5332b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
5342b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5352b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
5362b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
5372b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
5382b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
5392b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
5402b4ed282SShri Abhyankar 
5412b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
54210f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
5434c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
54410f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
5454c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
54610f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
5474c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
5485559b345SBarry Smith     } else if (l[i] == u[i]) {
5492b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
5505559b345SBarry Smith     } else {                                                /* both bounds on variable */
5514c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
5522b4ed282SShri Abhyankar     }
5532b4ed282SShri Abhyankar   }
5542b4ed282SShri Abhyankar 
5552b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
5562b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
5572b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
5582b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
5592b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
5602b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5612b4ed282SShri Abhyankar }
5622b4ed282SShri Abhyankar 
5632b4ed282SShri Abhyankar /*
564a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
565a79edbefSShri Abhyankar                                           the semismooth jacobian.
5662b4ed282SShri Abhyankar */
5672b4ed282SShri Abhyankar #undef __FUNCT__
568a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
569a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5702b4ed282SShri Abhyankar {
5712b4ed282SShri Abhyankar   PetscErrorCode ierr;
5722b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5734c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5742b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5752b4ed282SShri Abhyankar 
5762b4ed282SShri Abhyankar   PetscFunctionBegin;
5772b4ed282SShri Abhyankar 
5782b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5792b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5802b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5812b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
582a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
583a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5842b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5854c21c6cdSBarry Smith 
5862b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
58710f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5884c21c6cdSBarry Smith       da[i] = 0;
5892b4ed282SShri Abhyankar       db[i] = 1;
59010f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5914c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5924c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
59310f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5945559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5955559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5965559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5974c21c6cdSBarry Smith       da[i] = 1;
5982b4ed282SShri Abhyankar       db[i] = 0;
5995559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
6004c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
6014c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
6024c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
6034c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
6044c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
6054c21c6cdSBarry Smith       db[i] = db1*db2;
6062b4ed282SShri Abhyankar     }
6072b4ed282SShri Abhyankar   }
6085559b345SBarry Smith 
6092b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
6102b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
6112b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
6122b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
613a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
614a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
615a79edbefSShri Abhyankar   PetscFunctionReturn(0);
616a79edbefSShri Abhyankar }
617a79edbefSShri Abhyankar 
618a79edbefSShri Abhyankar /*
619a79edbefSShri 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.
620a79edbefSShri Abhyankar 
621a79edbefSShri Abhyankar    Input Parameters:
622a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
623a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
624a79edbefSShri Abhyankar 
625a79edbefSShri Abhyankar    Output Parameters:
626a79edbefSShri Abhyankar .  jac      - semismooth jacobian
627a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
628a79edbefSShri Abhyankar 
629a79edbefSShri Abhyankar    Notes:
630a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
631a79edbefSShri Abhyankar    jac = Da + Db*jacfun
632a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
633a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
634a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
635a79edbefSShri Abhyankar */
636a79edbefSShri Abhyankar #undef __FUNCT__
637a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
638a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
639a79edbefSShri Abhyankar {
640a79edbefSShri Abhyankar   PetscErrorCode ierr;
641a79edbefSShri Abhyankar 
6422b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
643a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
644a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
645a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
646a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
647a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
6482b4ed282SShri Abhyankar   }
6492b4ed282SShri Abhyankar   PetscFunctionReturn(0);
6502b4ed282SShri Abhyankar }
6512b4ed282SShri Abhyankar 
6522b4ed282SShri Abhyankar /*
653ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
654ee657d29SShri Abhyankar 
655ee657d29SShri Abhyankar    Input Parameters:
656ee657d29SShri Abhyankar    phi - semismooth function.
657ee657d29SShri Abhyankar    H   - semismooth jacobian
658ee657d29SShri Abhyankar 
659ee657d29SShri Abhyankar    Output Parameters:
660ee657d29SShri Abhyankar    dpsi - merit function gradient
661ee657d29SShri Abhyankar 
662ee657d29SShri Abhyankar    Notes:
663ee657d29SShri Abhyankar   The merit function gradient is computed as follows
664ee657d29SShri Abhyankar         dpsi = H^T*phi
665ee657d29SShri Abhyankar */
666ee657d29SShri Abhyankar #undef __FUNCT__
667ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
668ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
669ee657d29SShri Abhyankar {
670ee657d29SShri Abhyankar   PetscErrorCode ierr;
671ee657d29SShri Abhyankar 
672ee657d29SShri Abhyankar   PetscFunctionBegin;
6735f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
674ee657d29SShri Abhyankar   PetscFunctionReturn(0);
675ee657d29SShri Abhyankar }
676ee657d29SShri Abhyankar 
677c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
678c1a5e521SShri Abhyankar /*
679c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
680c1a5e521SShri Abhyankar 
681c1a5e521SShri Abhyankar    Input Parameters:
682c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
683c1a5e521SShri Abhyankar 
684c1a5e521SShri Abhyankar    Output Parameters:
685c1a5e521SShri Abhyankar .  X - Bound projected X
686c1a5e521SShri Abhyankar 
687c1a5e521SShri Abhyankar */
688c1a5e521SShri Abhyankar 
689c1a5e521SShri Abhyankar #undef __FUNCT__
690c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
691c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
692c1a5e521SShri Abhyankar {
693c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
694c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
695c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
696c1a5e521SShri Abhyankar   PetscScalar       *x;
697c1a5e521SShri Abhyankar   PetscInt          i,n;
698c1a5e521SShri Abhyankar 
699c1a5e521SShri Abhyankar   PetscFunctionBegin;
700c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
701c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
702c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
703c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
704c1a5e521SShri Abhyankar 
705c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
70610f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
70710f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
708c1a5e521SShri Abhyankar   }
709c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
710c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
711c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
712c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
713c1a5e521SShri Abhyankar }
714c1a5e521SShri Abhyankar 
7152b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
7162b4ed282SShri Abhyankar 
7172b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
7182b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
7192b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
7202b4ed282SShri Abhyankar      respectively.
7212b4ed282SShri Abhyankar 
7222b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
7232b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
7242b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
7252b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
7262b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
7272b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
7282b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
7292b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
7302b4ed282SShri Abhyankar      These routines are actually called via the common user interface
7312b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
7322b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
7332b4ed282SShri Abhyankar      for all nonlinear solvers.
7342b4ed282SShri Abhyankar 
7352b4ed282SShri Abhyankar      Another key routine is:
7362b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
7372b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
7382b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
7392b4ed282SShri Abhyankar      SNESSolve() if necessary.
7402b4ed282SShri Abhyankar 
7412b4ed282SShri Abhyankar      Additional basic routines are:
7422b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
7432b4ed282SShri Abhyankar                                       have actually been used.
7442b4ed282SShri Abhyankar      These are called by application codes via the interface routines
7452b4ed282SShri Abhyankar      SNESView().
7462b4ed282SShri Abhyankar 
7472b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
7482b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
7492b4ed282SShri Abhyankar      above description applies to these categories also.
7502b4ed282SShri Abhyankar 
7512b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
7522b4ed282SShri Abhyankar /*
75369c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
7542b4ed282SShri Abhyankar    method using a line search.
7552b4ed282SShri Abhyankar 
7562b4ed282SShri Abhyankar    Input Parameters:
7572b4ed282SShri Abhyankar .  snes - the SNES context
7582b4ed282SShri Abhyankar 
7592b4ed282SShri Abhyankar    Output Parameter:
7602b4ed282SShri Abhyankar .  outits - number of iterations until termination
7612b4ed282SShri Abhyankar 
7622b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
7632b4ed282SShri Abhyankar 
7642b4ed282SShri Abhyankar    Notes:
7652b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
76651defd01SShri Abhyankar    line search. The default line search does not do any line seach
76751defd01SShri Abhyankar    but rather takes a full newton step.
7682b4ed282SShri Abhyankar */
7692b4ed282SShri Abhyankar #undef __FUNCT__
77069c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
77169c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7722b4ed282SShri Abhyankar {
7732b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7742b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7752b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7763b336b49SShri Abhyankar   PetscBool          lssucceed;
7772b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7782b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7792b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7802b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7812b4ed282SShri Abhyankar 
7822b4ed282SShri Abhyankar   PetscFunctionBegin;
7839ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7849ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7859ce7406fSBarry Smith 
7862b4ed282SShri Abhyankar   snes->numFailures            = 0;
7872b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7882b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7892b4ed282SShri Abhyankar 
7902b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7912b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7922b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7932b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7942b4ed282SShri Abhyankar   G		= snes->work[1];
7952b4ed282SShri Abhyankar   W		= snes->work[2];
7962b4ed282SShri Abhyankar 
7972b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7982b4ed282SShri Abhyankar   snes->iter = 0;
7992b4ed282SShri Abhyankar   snes->norm = 0.0;
8002b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar 
8027fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
8032b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
8042b4ed282SShri Abhyankar   if (snes->domainerror) {
8052b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8069ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8072b4ed282SShri Abhyankar     PetscFunctionReturn(0);
8082b4ed282SShri Abhyankar   }
8092b4ed282SShri Abhyankar    /* Compute Merit function */
8102b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
8112b4ed282SShri Abhyankar 
8122b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
8132b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
81462cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
8152b4ed282SShri Abhyankar 
8162b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8172b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
8182b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8192b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
8207a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
8212b4ed282SShri Abhyankar 
8222b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
8232b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
8242b4ed282SShri Abhyankar   /* test convergence */
8252b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8269ce7406fSBarry Smith   if (snes->reason) {
8279ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
8289ce7406fSBarry Smith     PetscFunctionReturn(0);
8299ce7406fSBarry Smith   }
8302b4ed282SShri Abhyankar 
8312b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
8322b4ed282SShri Abhyankar 
8332b4ed282SShri Abhyankar     /* Call general purpose update function */
8342b4ed282SShri Abhyankar     if (snes->ops->update) {
8352b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
8362b4ed282SShri Abhyankar     }
8372b4ed282SShri Abhyankar 
8382b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
839a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
8402b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
841a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
842a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
843a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
844a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
845ee657d29SShri Abhyankar     /* Compute the merit function gradient */
846ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
8472b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
8482b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
8492b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
8503b336b49SShri Abhyankar 
8513b336b49SShri Abhyankar     if (kspreason < 0) {
8522b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
8532b4ed282SShri 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);
8542b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
8552b4ed282SShri Abhyankar         break;
8562b4ed282SShri Abhyankar       }
8572b4ed282SShri Abhyankar     }
8582b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
8592b4ed282SShri Abhyankar     snes->linear_its += lits;
8602b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
8612b4ed282SShri Abhyankar     /*
8622b4ed282SShri Abhyankar     if (vi->precheckstep) {
863ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
8642b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
8652b4ed282SShri Abhyankar     }
8662b4ed282SShri Abhyankar 
8672b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8682b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8692b4ed282SShri Abhyankar     }
8702b4ed282SShri Abhyankar     */
8712b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8722b4ed282SShri Abhyankar          Y <- X - lambda*Y
8732b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8742b4ed282SShri Abhyankar     */
8752b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8762b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8772b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8782b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8792b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8802b4ed282SShri Abhyankar     if (snes->domainerror) {
8812b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8829ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8832b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8842b4ed282SShri Abhyankar     }
8852b4ed282SShri Abhyankar     if (!lssucceed) {
8862b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
887ace3abfcSBarry Smith 	PetscBool ismin;
8882b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8892b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8902b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8912b4ed282SShri Abhyankar         break;
8922b4ed282SShri Abhyankar       }
8932b4ed282SShri Abhyankar     }
8942b4ed282SShri Abhyankar     /* Update function and solution vectors */
8952b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8962b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8972b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8982b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8992b4ed282SShri Abhyankar     /* Monitor convergence */
9002b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
9012b4ed282SShri Abhyankar     snes->iter = i+1;
9022b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
9032b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
9042b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
9057a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
9062b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
9072b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
9082b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
9092b4ed282SShri Abhyankar     if (snes->reason) break;
9102b4ed282SShri Abhyankar   }
9112b4ed282SShri Abhyankar   if (i == maxits) {
9122b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
9132b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
9142b4ed282SShri Abhyankar   }
9159ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
9162b4ed282SShri Abhyankar   PetscFunctionReturn(0);
9172b4ed282SShri Abhyankar }
91869c03620SShri Abhyankar 
91969c03620SShri Abhyankar #undef __FUNCT__
920693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
921693ddf92SShri Abhyankar /*
922693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
923693ddf92SShri Abhyankar 
924693ddf92SShri Abhyankar    Input parameter
925693ddf92SShri Abhyankar .  snes - the SNES context
926693ddf92SShri Abhyankar .  X    - the snes solution vector
927693ddf92SShri Abhyankar .  F    - the nonlinear function vector
928693ddf92SShri Abhyankar 
929693ddf92SShri Abhyankar    Output parameter
930693ddf92SShri Abhyankar .  ISact - active set index set
931693ddf92SShri Abhyankar  */
932693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
933d950fb63SShri Abhyankar {
934d950fb63SShri Abhyankar   PetscErrorCode   ierr;
935693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
936693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
937693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
938693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
939d950fb63SShri Abhyankar 
940d950fb63SShri Abhyankar   PetscFunctionBegin;
941d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
942d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
943fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
944fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
945fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
946fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
947693ddf92SShri Abhyankar   /* Compute active set size */
948d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
94910f5ae6bSBarry 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++;
950d950fb63SShri Abhyankar   }
951693ddf92SShri Abhyankar 
952d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
953d950fb63SShri Abhyankar 
954693ddf92SShri Abhyankar   /* Set active set indices */
955d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
95610f5ae6bSBarry 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;
957d950fb63SShri Abhyankar   }
958d950fb63SShri Abhyankar 
959693ddf92SShri Abhyankar    /* Create active set IS */
96062298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
961d950fb63SShri Abhyankar 
962fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
963fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
964fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
965fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
966d950fb63SShri Abhyankar   PetscFunctionReturn(0);
967d950fb63SShri Abhyankar }
968d950fb63SShri Abhyankar 
969693ddf92SShri Abhyankar #undef __FUNCT__
970693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
971693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
972693ddf92SShri Abhyankar {
973693ddf92SShri Abhyankar   PetscErrorCode     ierr;
974693ddf92SShri Abhyankar 
975693ddf92SShri Abhyankar   PetscFunctionBegin;
976693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
977693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
978693ddf92SShri Abhyankar   PetscFunctionReturn(0);
979693ddf92SShri Abhyankar }
980693ddf92SShri Abhyankar 
981dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
982dbd914b8SShri Abhyankar #undef __FUNCT__
983fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
984fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
985dbd914b8SShri Abhyankar {
986dbd914b8SShri Abhyankar   PetscErrorCode ierr;
987dbd914b8SShri Abhyankar   Vec            v;
988dbd914b8SShri Abhyankar 
989dbd914b8SShri Abhyankar   PetscFunctionBegin;
990dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
991dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
992dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
993dbd914b8SShri Abhyankar   *newv = v;
994dbd914b8SShri Abhyankar 
995dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
996dbd914b8SShri Abhyankar }
997dbd914b8SShri Abhyankar 
998732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
999732bb160SShri Abhyankar #undef __FUNCT__
1000732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
1001732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
1002732bb160SShri Abhyankar {
1003732bb160SShri Abhyankar   PetscErrorCode         ierr;
1004d0af7cd3SBarry Smith   KSP                    snesksp;
1005dbd914b8SShri Abhyankar 
1006732bb160SShri Abhyankar   PetscFunctionBegin;
1007732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
1008d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
1009c2efdce3SBarry Smith 
1010c2efdce3SBarry Smith   /*
1011d0af7cd3SBarry Smith   KSP                    kspnew;
1012d0af7cd3SBarry Smith   PC                     pcnew;
1013d0af7cd3SBarry Smith   const MatSolverPackage stype;
1014d0af7cd3SBarry Smith 
1015c2efdce3SBarry Smith 
1016732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
1017732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
1018732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
1019732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
1020732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
1021732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
1022732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
1023732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
1024732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
1025732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
1026732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
10276bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
1028732bb160SShri Abhyankar   snes->ksp = kspnew;
1029732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
1030d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
1031732bb160SShri Abhyankar   PetscFunctionReturn(0);
1032732bb160SShri Abhyankar }
103369c03620SShri Abhyankar 
103469c03620SShri Abhyankar 
1035fe835674SShri Abhyankar #undef __FUNCT__
1036fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
103710f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
1038fe835674SShri Abhyankar {
1039fe835674SShri Abhyankar   PetscErrorCode    ierr;
1040fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
1041fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
1042fe835674SShri Abhyankar   PetscInt          i,n;
1043fe835674SShri Abhyankar   PetscReal         rnorm;
1044fe835674SShri Abhyankar 
1045fe835674SShri Abhyankar   PetscFunctionBegin;
1046fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
1047fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1048fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1049fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1050fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
1051fe835674SShri Abhyankar   rnorm = 0.0;
1052fe835674SShri Abhyankar   for (i=0; i<n; i++) {
105310f5ae6bSBarry 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]);
1054fe835674SShri Abhyankar   }
1055fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
1056fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
1057fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
1058fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1059d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
1060fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
1061fe835674SShri Abhyankar   PetscFunctionReturn(0);
1062fe835674SShri Abhyankar }
1063fe835674SShri Abhyankar 
1064fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
1065c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
1066c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
1067d950fb63SShri Abhyankar #undef __FUNCT__
1068d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1069d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1070d950fb63SShri Abhyankar {
1071d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1072d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1073abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1074d950fb63SShri Abhyankar   PetscBool         lssucceed;
1075d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1076fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1077d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1078d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1079d950fb63SShri Abhyankar 
1080d950fb63SShri Abhyankar   PetscFunctionBegin;
1081d950fb63SShri Abhyankar   snes->numFailures            = 0;
1082d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1083d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1084d950fb63SShri Abhyankar 
1085d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1086d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1087d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1088d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1089d950fb63SShri Abhyankar   G		= snes->work[1];
1090d950fb63SShri Abhyankar   W		= snes->work[2];
1091d950fb63SShri Abhyankar 
1092d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1093d950fb63SShri Abhyankar   snes->iter = 0;
1094d950fb63SShri Abhyankar   snes->norm = 0.0;
1095d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1096d950fb63SShri Abhyankar 
10977fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1098fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1099d950fb63SShri Abhyankar   if (snes->domainerror) {
1100d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1101d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1102d950fb63SShri Abhyankar   }
1103fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1104d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1105d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
110662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1107d950fb63SShri Abhyankar 
1108d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1109fe835674SShri Abhyankar   snes->norm = fnorm;
1110d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1111fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
11127a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1113d950fb63SShri Abhyankar 
1114d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1115fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1116d950fb63SShri Abhyankar   /* test convergence */
1117fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1118d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1119d950fb63SShri Abhyankar 
11209ce20c35SJungho Lee 
1121d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1122d950fb63SShri Abhyankar 
1123d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1124a6b72b01SJungho Lee     IS         IS_redact; /* redundant active set */
1125d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1126abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1127fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1128d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
112962298a1eSBarry Smith     IS         keptrows;
1130abcba341SShri Abhyankar     PetscBool  isequal;
1131d950fb63SShri Abhyankar 
1132d950fb63SShri Abhyankar     /* Call general purpose update function */
1133d950fb63SShri Abhyankar     if (snes->ops->update) {
1134d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1135d950fb63SShri Abhyankar     }
1136d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
113762298a1eSBarry Smith 
11389ce20c35SJungho Lee 
1139d950fb63SShri Abhyankar         /* Create active and inactive index sets */
1140a6b72b01SJungho Lee 
1141a6b72b01SJungho Lee     /*original
1142693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1143a6b72b01SJungho Lee      */
1144a6b72b01SJungho Lee     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
1145a6b72b01SJungho Lee 
1146a6b72b01SJungho Lee     if (vi->checkredundancy) {
1147a6b72b01SJungho Lee       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
1148ed70e96aSJungho Lee       if (IS_redact){
1149ed70e96aSJungho Lee         ierr = ISSort(IS_redact);CHKERRQ(ierr);
1150a6b72b01SJungho Lee         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1151a6b72b01SJungho Lee         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
1152ed70e96aSJungho Lee       }
1153ed70e96aSJungho Lee       else {
1154ed70e96aSJungho Lee         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1155ed70e96aSJungho Lee       }
1156a6b72b01SJungho Lee     } else {
1157a6b72b01SJungho Lee       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
1158a6b72b01SJungho Lee     }
1159d950fb63SShri Abhyankar 
11604dcab191SBarry Smith 
1161abcba341SShri Abhyankar     /* Create inactive set submatrix */
116262298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1163a6b72b01SJungho Lee 
1164b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
11659ce20c35SJungho Lee     if (0 && keptrows) {
11669ce20c35SJungho Lee     // if (keptrows) {
116762298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
116862298a1eSBarry Smith       const PetscInt *krows,*inact;
116927d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
117062298a1eSBarry Smith 
11716bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
11726bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
117362298a1eSBarry Smith 
117462298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
117562298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
117662298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
117762298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
117862298a1eSBarry Smith       for (k=0; k<cnt; k++) {
117927d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
118062298a1eSBarry Smith       }
118162298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
118262298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
11836bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
11846bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
118562298a1eSBarry Smith 
118627d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
118727d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
118862298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
118962298a1eSBarry Smith     }
11909ce20c35SJungho Lee     ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr);
11919ce20c35SJungho Lee     /* remove later */
11929ce20c35SJungho Lee 
11939ce20c35SJungho Lee     /*
11949ce20c35SJungho Lee   ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
11959ce20c35SJungho Lee   ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
11969ce20c35SJungho Lee   ierr = VecView(X,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
11979ce20c35SJungho Lee   ierr = VecView(F,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
11989ce20c35SJungho Lee   ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(PETSC_COMM_WORLD));CHKERRQ(ierr);
11999ce20c35SJungho Lee      */
120062298a1eSBarry Smith 
1201d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1202d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1203d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1204d950fb63SShri Abhyankar 
1205d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1206fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1207fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1208fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1209d950fb63SShri Abhyankar 
1210d950fb63SShri Abhyankar     /* Create scatter contexts */
1211d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1212d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1213d950fb63SShri Abhyankar 
1214d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1215fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1216fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1217d950fb63SShri Abhyankar 
1218d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1219d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1220d950fb63SShri Abhyankar 
1221d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1222d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1223d950fb63SShri Abhyankar 
1224d950fb63SShri Abhyankar     /* Active set direction = 0 */
1225d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1226d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1227d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1228d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1229d950fb63SShri Abhyankar 
1230abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1231abcba341SShri Abhyankar     if (!isequal) {
1232732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1233c58c0d17SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
1234d950fb63SShri Abhyankar     }
1235d950fb63SShri Abhyankar 
123613e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
123713e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
123813e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
123913e0d083SBarry Smith 
1240f15307b4SJungho Lee 
12419ce20c35SJungho Lee 
1242d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
124313e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
124413e0d083SBarry Smith     {
124513e0d083SBarry Smith       PC        pc;
124613e0d083SBarry Smith       PetscBool flg;
124713e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
124813e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
124913e0d083SBarry Smith       if (flg) {
125013e0d083SBarry Smith         KSP      *subksps;
125113e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
125213e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
125313e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
125413e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
125513e0d083SBarry Smith         if (flg) {
125613e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
125713e0d083SBarry Smith           const PetscInt *ii;
125813e0d083SBarry Smith 
125913e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
126013e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
126113e0d083SBarry Smith           for (j=0; j<n; j++) {
126213e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
126313e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
126413e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
126513e0d083SBarry Smith           }
126613e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
126713e0d083SBarry Smith 
126813e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
126913e0d083SBarry Smith         }
127013e0d083SBarry Smith       }
127113e0d083SBarry Smith     }
127213e0d083SBarry Smith 
1273fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1274d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1275d950fb63SShri Abhyankar     if (kspreason < 0) {
1276d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1277d950fb63SShri 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);
1278d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1279d950fb63SShri Abhyankar         break;
1280d950fb63SShri Abhyankar       }
1281d950fb63SShri Abhyankar      }
1282d950fb63SShri Abhyankar 
1283d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1284d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1285d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1286d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1287d950fb63SShri Abhyankar 
12886bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
12896bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
12906bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
12916bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
12926bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
12936bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1294abcba341SShri Abhyankar     if (!isequal) {
12956bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1296abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1297abcba341SShri Abhyankar     }
12986bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
12996bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1300d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
13016bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1302d950fb63SShri Abhyankar     }
1303d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1304d950fb63SShri Abhyankar     snes->linear_its += lits;
1305d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1306d950fb63SShri Abhyankar     /*
1307d950fb63SShri Abhyankar     if (vi->precheckstep) {
1308d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1309d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1310d950fb63SShri Abhyankar     }
1311d950fb63SShri Abhyankar 
1312d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1313d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1314d950fb63SShri Abhyankar     }
1315d950fb63SShri Abhyankar     */
1316d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1317d950fb63SShri Abhyankar          Y <- X - lambda*Y
1318d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1319d950fb63SShri Abhyankar     */
1320d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1321fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1322fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1323fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
13242b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
13252b4ed282SShri Abhyankar     if (snes->domainerror) {
13262b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13274c661befSBarry Smith       ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13282b4ed282SShri Abhyankar       PetscFunctionReturn(0);
13292b4ed282SShri Abhyankar     }
13302b4ed282SShri Abhyankar     if (!lssucceed) {
13312b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
13322b4ed282SShri Abhyankar 	PetscBool ismin;
13332b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
13342b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
13352b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
13362b4ed282SShri Abhyankar         break;
13372b4ed282SShri Abhyankar       }
13382b4ed282SShri Abhyankar     }
13392b4ed282SShri Abhyankar     /* Update function and solution vectors */
1340fe835674SShri Abhyankar     fnorm = gnorm;
1341fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
13422b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
13432b4ed282SShri Abhyankar     /* Monitor convergence */
13442b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13452b4ed282SShri Abhyankar     snes->iter = i+1;
1346fe835674SShri Abhyankar     snes->norm = fnorm;
13472b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13482b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
13497a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
13502b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
13512b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1352fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13532b4ed282SShri Abhyankar     if (snes->reason) break;
13542b4ed282SShri Abhyankar   }
13554c661befSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
13562b4ed282SShri Abhyankar   if (i == maxits) {
13572b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
13582b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
13592b4ed282SShri Abhyankar   }
13602b4ed282SShri Abhyankar   PetscFunctionReturn(0);
13612b4ed282SShri Abhyankar }
13622b4ed282SShri Abhyankar 
13632f63a38cSShri Abhyankar #undef __FUNCT__
1364720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1365cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
13662f63a38cSShri Abhyankar {
13672f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
13682f63a38cSShri Abhyankar 
13692f63a38cSShri Abhyankar   PetscFunctionBegin;
13702f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
13712f63a38cSShri Abhyankar   vi->checkredundancy = func;
1372cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
13732f63a38cSShri Abhyankar   PetscFunctionReturn(0);
13742f63a38cSShri Abhyankar }
13752f63a38cSShri Abhyankar 
1376ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1377ff596062SShri Abhyankar #include <engine.h>
1378ff596062SShri Abhyankar #include <mex.h>
1379cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1380ff596062SShri Abhyankar 
1381ff596062SShri Abhyankar #undef __FUNCT__
1382ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1383ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1384ff596062SShri Abhyankar {
1385ff596062SShri Abhyankar   PetscErrorCode      ierr;
1386cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1387cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1388cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1389cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1390fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1391ff596062SShri Abhyankar 
1392ff596062SShri Abhyankar   PetscFunctionBegin;
1393ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1394ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1395ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1396ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1397ff596062SShri Abhyankar 
139809db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
139909db5ad8SShri Abhyankar    bet set by the Matlab function */
1400fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1401cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1402ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1403ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1404cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1405ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1406ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1407cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1408cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1409cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1410ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1411ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1412ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1413ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1414ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1415ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1416ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1417ff596062SShri Abhyankar   PetscFunctionReturn(0);
1418ff596062SShri Abhyankar }
1419ff596062SShri Abhyankar 
1420ff596062SShri Abhyankar #undef __FUNCT__
1421ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1422ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1423ff596062SShri Abhyankar {
1424ff596062SShri Abhyankar   PetscErrorCode      ierr;
1425cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1426ff596062SShri Abhyankar 
1427ff596062SShri Abhyankar   PetscFunctionBegin;
1428ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1429cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1430ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1431ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1432cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1433ff596062SShri Abhyankar   PetscFunctionReturn(0);
1434ff596062SShri Abhyankar }
1435ff596062SShri Abhyankar 
1436ff596062SShri Abhyankar #endif
1437ff596062SShri Abhyankar 
1438ff596062SShri Abhyankar 
14392f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
14402f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1441720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
144256a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
144356a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
14442f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
14452f63a38cSShri Abhyankar */
14462f63a38cSShri Abhyankar #undef __FUNCT__
1447b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1448b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
14492f63a38cSShri Abhyankar {
14502f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
14512f63a38cSShri Abhyankar   PetscErrorCode    ierr;
14522f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
14532f63a38cSShri Abhyankar   PetscBool         lssucceed;
14542f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
14552f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
14562f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
14572f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
14582f63a38cSShri Abhyankar 
14592f63a38cSShri Abhyankar   PetscFunctionBegin;
14602f63a38cSShri Abhyankar   snes->numFailures            = 0;
14612f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
14622f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
14632f63a38cSShri Abhyankar 
14642f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
14652f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
14662f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
14672f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
14682f63a38cSShri Abhyankar   G		= snes->work[1];
14692f63a38cSShri Abhyankar   W		= snes->work[2];
14702f63a38cSShri Abhyankar 
14712f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14722f63a38cSShri Abhyankar   snes->iter = 0;
14732f63a38cSShri Abhyankar   snes->norm = 0.0;
14742f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14752f63a38cSShri Abhyankar 
14762f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
14772f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
14782f63a38cSShri Abhyankar   if (snes->domainerror) {
14792f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
14802f63a38cSShri Abhyankar     PetscFunctionReturn(0);
14812f63a38cSShri Abhyankar   }
14822f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
14832f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
14842f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
148562cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
14862f63a38cSShri Abhyankar 
14872f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
14882f63a38cSShri Abhyankar   snes->norm = fnorm;
14892f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
14902f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
14917a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
14922f63a38cSShri Abhyankar 
14932f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
14942f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
14952f63a38cSShri Abhyankar   /* test convergence */
14962f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
14972f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
14982f63a38cSShri Abhyankar 
14992f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
15002f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1501cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
150256a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
150356a221efSShri Abhyankar     Vec            F_aug,Y_aug;
150456a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
150556a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
150656a221efSShri Abhyankar     PetscInt       k;
150763ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
150856a221efSShri Abhyankar     PetscScalar    *f,*f2;
15092f63a38cSShri Abhyankar     PetscBool      isequal;
151056a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
15112f63a38cSShri Abhyankar 
15122f63a38cSShri Abhyankar     /* Call general purpose update function */
15132f63a38cSShri Abhyankar     if (snes->ops->update) {
15142f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
15152f63a38cSShri Abhyankar     }
15162f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
15172f63a38cSShri Abhyankar 
15182f63a38cSShri Abhyankar     /* Create active and inactive index sets */
15192f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
15202f63a38cSShri Abhyankar 
152156a221efSShri Abhyankar     /* Get local active set size */
15222f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
152356a221efSShri Abhyankar     if (nis_act) {
1524e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1525e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
152656a221efSShri Abhyankar       if(vi->checkredundancy) {
1527cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
152856a221efSShri Abhyankar       }
15292f63a38cSShri Abhyankar 
153056a221efSShri Abhyankar       if(!IS_redact) {
153156a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
153256a221efSShri Abhyankar            there were no redundant active set variables */
153356a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
153456a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
153556a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
153656a221efSShri Abhyankar 	nkept = nis_act;
153756a221efSShri Abhyankar       } else {
153856a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
153956a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
15402f63a38cSShri Abhyankar 
154156a221efSShri Abhyankar 	/* Create reduced active set list */
154256a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
154356a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1544cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
154556a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
154656a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
154756a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
154856a221efSShri Abhyankar 	}
154956a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
155056a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1551cb5fe31bSShri Abhyankar 
1552cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
155356a221efSShri Abhyankar       }
15542f63a38cSShri Abhyankar 
155556a221efSShri Abhyankar       /* Create augmented F and Y */
155656a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
155756a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
155856a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
155956a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
15602f63a38cSShri Abhyankar 
156156a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
156256a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
156356a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
156456a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
156556a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
156656a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
15672f63a38cSShri Abhyankar 
156856a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
156956a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
157056a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
157156a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
15722f63a38cSShri Abhyankar 
157356a221efSShri Abhyankar 
15749521db3cSSatish Balay       { /* local vars */
1575493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
157656a221efSShri Abhyankar       PetscInt          ncols;
157756a221efSShri Abhyankar       const PetscInt    *cols;
157856a221efSShri Abhyankar       const PetscScalar *vals;
15792969f145SShri Abhyankar       PetscScalar        value[2];
15802969f145SShri Abhyankar       PetscInt           row,col[2];
1581493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
15822969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1583493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1584493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1585493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1586493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1587493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1588493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1589493a4f3dSShri Abhyankar       }
1590493a4f3dSShri Abhyankar 
1591493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1592493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
15932969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1594493a4f3dSShri Abhyankar       }
1595493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1596493a4f3dSShri Abhyankar 
1597493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
159856a221efSShri Abhyankar 
159956a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
160056a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
160156a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
160256a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
160356a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
160456a221efSShri Abhyankar       }
160556a221efSShri Abhyankar       /* Add the augmented part */
160656a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
16072969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
16082969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
16092969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
16102969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
161156a221efSShri Abhyankar       }
161256a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
161356a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
161456a221efSShri Abhyankar       /* Only considering prejac = jac for now */
161556a221efSShri Abhyankar       Jpre_aug = J_aug;
16169521db3cSSatish Balay       } /* local vars*/
1617e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1618e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
161956a221efSShri Abhyankar     } else {
162056a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
162156a221efSShri Abhyankar     }
16222f63a38cSShri Abhyankar 
16232f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
16242f63a38cSShri Abhyankar     if (!isequal) {
162556a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
16262f63a38cSShri Abhyankar     }
162756a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
16282f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
162956a221efSShri Abhyankar     /*  {
16302f63a38cSShri Abhyankar       PC        pc;
16312f63a38cSShri Abhyankar       PetscBool flg;
16322f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
16332f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
16342f63a38cSShri Abhyankar       if (flg) {
16352f63a38cSShri Abhyankar         KSP      *subksps;
16362f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
16372f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
16382f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
16392f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
16402f63a38cSShri Abhyankar         if (flg) {
16412f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
16422f63a38cSShri Abhyankar           const PetscInt *ii;
16432f63a38cSShri Abhyankar 
16442f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
16452f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
16462f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
16472f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
16482f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
16492f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
16502f63a38cSShri Abhyankar           }
16512f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
16522f63a38cSShri Abhyankar 
16532f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
16542f63a38cSShri Abhyankar         }
16552f63a38cSShri Abhyankar       }
16562f63a38cSShri Abhyankar     }
165756a221efSShri Abhyankar     */
165856a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
16592f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
16602f63a38cSShri Abhyankar     if (kspreason < 0) {
16612f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
16622f63a38cSShri 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);
16632f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
16642f63a38cSShri Abhyankar         break;
16652f63a38cSShri Abhyankar       }
16662f63a38cSShri Abhyankar     }
16672f63a38cSShri Abhyankar 
166856a221efSShri Abhyankar     if(nis_act) {
166956a221efSShri Abhyankar       PetscScalar *y1,*y2;
167056a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
167156a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
167256a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
167356a221efSShri Abhyankar       j1 = 0;
167456a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
167556a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
167656a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
167756a221efSShri Abhyankar       }
167856a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
167956a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
16802f63a38cSShri Abhyankar 
16816bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
16826bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
16836bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
168456a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
168556a221efSShri Abhyankar     }
168656a221efSShri Abhyankar 
16872f63a38cSShri Abhyankar     if (!isequal) {
16886bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
16892f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
16902f63a38cSShri Abhyankar     }
16916bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
169256a221efSShri Abhyankar 
16932f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
16942f63a38cSShri Abhyankar     snes->linear_its += lits;
16952f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
16962f63a38cSShri Abhyankar     /*
16972f63a38cSShri Abhyankar     if (vi->precheckstep) {
16982f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
16992f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
17002f63a38cSShri Abhyankar     }
17012f63a38cSShri Abhyankar 
17022f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
17032f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
17042f63a38cSShri Abhyankar     }
17052f63a38cSShri Abhyankar     */
17062f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
17072f63a38cSShri Abhyankar          Y <- X - lambda*Y
17082f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
17092f63a38cSShri Abhyankar     */
17102f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
17112f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
17122f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
17132f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
17142f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
17152f63a38cSShri Abhyankar     if (snes->domainerror) {
17162f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
17172f63a38cSShri Abhyankar       PetscFunctionReturn(0);
17182f63a38cSShri Abhyankar     }
17192f63a38cSShri Abhyankar     if (!lssucceed) {
17202f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
17212f63a38cSShri Abhyankar 	PetscBool ismin;
17222f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
17232f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
17242f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
17252f63a38cSShri Abhyankar         break;
17262f63a38cSShri Abhyankar       }
17272f63a38cSShri Abhyankar     }
17282f63a38cSShri Abhyankar     /* Update function and solution vectors */
17292f63a38cSShri Abhyankar     fnorm = gnorm;
17302f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
17312f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
17322f63a38cSShri Abhyankar     /* Monitor convergence */
17332f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
17342f63a38cSShri Abhyankar     snes->iter = i+1;
17352f63a38cSShri Abhyankar     snes->norm = fnorm;
17362f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
17372f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
17387a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
17392f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
17402f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
17412f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
17422f63a38cSShri Abhyankar     if (snes->reason) break;
17432f63a38cSShri Abhyankar   }
17442f63a38cSShri Abhyankar   if (i == maxits) {
17452f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
17462f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
17472f63a38cSShri Abhyankar   }
17482f63a38cSShri Abhyankar   PetscFunctionReturn(0);
17492f63a38cSShri Abhyankar }
17502f63a38cSShri Abhyankar 
17512b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17522b4ed282SShri Abhyankar /*
17532b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
17542b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
17552b4ed282SShri Abhyankar 
17562b4ed282SShri Abhyankar    Input Parameter:
17572b4ed282SShri Abhyankar .  snes - the SNES context
17582b4ed282SShri Abhyankar .  x - the solution vector
17592b4ed282SShri Abhyankar 
17602b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
17612b4ed282SShri Abhyankar 
17622b4ed282SShri Abhyankar    Notes:
17632b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
17642b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
17652b4ed282SShri Abhyankar    the call to SNESSolve().
17662b4ed282SShri Abhyankar  */
17672b4ed282SShri Abhyankar #undef __FUNCT__
17682b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
17692b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
17702b4ed282SShri Abhyankar {
17712b4ed282SShri Abhyankar   PetscErrorCode ierr;
17722b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17732b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
17742b4ed282SShri Abhyankar 
17752b4ed282SShri Abhyankar   PetscFunctionBegin;
177658c9b817SLisandro Dalcin 
177758c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
17782b4ed282SShri Abhyankar 
17792176524cSBarry Smith   if (vi->computevariablebounds) {
178077cdaf69SJed Brown     if (!vi->xl) {ierr = VecDuplicate(snes->vec_sol,&vi->xl);CHKERRQ(ierr);}
178177cdaf69SJed Brown     if (!vi->xu) {ierr = VecDuplicate(snes->vec_sol,&vi->xu);CHKERRQ(ierr);}
178277cdaf69SJed Brown     ierr = (*vi->computevariablebounds)(snes,vi->xl,vi->xu);CHKERRQ(ierr);
17832176524cSBarry Smith   } else if (!vi->xl && !vi->xu) {
17842176524cSBarry Smith     /* If the lower and upper bound on variables are not set, set it to -Inf and Inf */
17852b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl);CHKERRQ(ierr);
178601f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
17872b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu);CHKERRQ(ierr);
178801f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
17892b4ed282SShri Abhyankar   } else {
17902b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
17912b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
17922b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
17932b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
17942b4ed282SShri 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]))
17952b4ed282SShri 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.");
17962b4ed282SShri Abhyankar   }
17972f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1798abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1799abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1800abcba341SShri Abhyankar     PetscInt *indices;
1801abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1802abcba341SShri Abhyankar 
1803abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1804abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1805abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1806abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1807abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1808abcba341SShri Abhyankar   }
18092b4ed282SShri Abhyankar 
18102f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1811fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1812fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi);CHKERRQ(ierr);
1813fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da);CHKERRQ(ierr);
1814fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db);CHKERRQ(ierr);
1815fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1816fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t);CHKERRQ(ierr);
1817fe835674SShri Abhyankar   }
18182b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18192b4ed282SShri Abhyankar }
18202b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18212176524cSBarry Smith #undef __FUNCT__
18222176524cSBarry Smith #define __FUNCT__ "SNESReset_VI"
18232176524cSBarry Smith PetscErrorCode SNESReset_VI(SNES snes)
18242176524cSBarry Smith {
18252176524cSBarry Smith   SNES_VI        *vi = (SNES_VI*) snes->data;
18262176524cSBarry Smith   PetscErrorCode ierr;
18272176524cSBarry Smith 
18282176524cSBarry Smith   PetscFunctionBegin;
18292176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
18302176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
1831d655a5daSBarry Smith   if (snes->ops->solve != SNESSolveVI_SS) {
1832d655a5daSBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1833d655a5daSBarry Smith   }
18342176524cSBarry Smith   PetscFunctionReturn(0);
18352176524cSBarry Smith }
18362176524cSBarry Smith 
18372b4ed282SShri Abhyankar /*
18382b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
18392b4ed282SShri Abhyankar    with SNESCreate_VI().
18402b4ed282SShri Abhyankar 
18412b4ed282SShri Abhyankar    Input Parameter:
18422b4ed282SShri Abhyankar .  snes - the SNES context
18432b4ed282SShri Abhyankar 
18442b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
18452b4ed282SShri Abhyankar  */
18462b4ed282SShri Abhyankar #undef __FUNCT__
18472b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
18482b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
18492b4ed282SShri Abhyankar {
18502b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
18512b4ed282SShri Abhyankar   PetscErrorCode ierr;
18522b4ed282SShri Abhyankar 
18532b4ed282SShri Abhyankar   PetscFunctionBegin;
18542b4ed282SShri Abhyankar 
18552f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
18562b4ed282SShri Abhyankar     /* clear vectors */
18576bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
18586bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi);CHKERRQ(ierr);
18596bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da);CHKERRQ(ierr);
18606bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db);CHKERRQ(ierr);
18616bf464f9SBarry Smith     ierr = VecDestroy(&vi->z);CHKERRQ(ierr);
18626bf464f9SBarry Smith     ierr = VecDestroy(&vi->t);CHKERRQ(ierr);
18637fe79bc4SShri Abhyankar   }
18647fe79bc4SShri Abhyankar 
1865649052a6SBarry Smith   ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
18662b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
18672b4ed282SShri Abhyankar 
18682b4ed282SShri Abhyankar   /* clear composed functions */
18692b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1870c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
18712b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18722b4ed282SShri Abhyankar }
18737fe79bc4SShri Abhyankar 
18742b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18752b4ed282SShri Abhyankar #undef __FUNCT__
18762b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
18772b4ed282SShri Abhyankar 
18782b4ed282SShri Abhyankar /*
18797fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
18807fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
18812b4ed282SShri Abhyankar 
18822b4ed282SShri Abhyankar */
1883ace3abfcSBarry 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)
18842b4ed282SShri Abhyankar {
18852b4ed282SShri Abhyankar   PetscErrorCode ierr;
18862b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1887ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18882b4ed282SShri Abhyankar 
18892b4ed282SShri Abhyankar   PetscFunctionBegin;
18902b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18912b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18922b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
18932b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1894c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1895c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1896c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1897c1a5e521SShri Abhyankar   }
1898c1a5e521SShri Abhyankar   if (changed_y) {
1899c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19007fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1901c1a5e521SShri Abhyankar   }
1902c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1903c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1904c1a5e521SShri Abhyankar   if (!snes->domainerror) {
19052f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
19067fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19077fe79bc4SShri Abhyankar     } else {
1908c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
19097fe79bc4SShri Abhyankar     }
191062cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1911c1a5e521SShri Abhyankar   }
1912c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1913649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1914649052a6SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1915649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1916c1a5e521SShri Abhyankar   }
1917c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1918c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1919c1a5e521SShri Abhyankar }
1920c1a5e521SShri Abhyankar 
1921c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1922c1a5e521SShri Abhyankar #undef __FUNCT__
19232b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
19242b4ed282SShri Abhyankar 
19252b4ed282SShri Abhyankar /*
19262b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
19272b4ed282SShri Abhyankar */
1928ace3abfcSBarry 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)
19292b4ed282SShri Abhyankar {
19302b4ed282SShri Abhyankar   PetscErrorCode ierr;
19312b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1932ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
19332b4ed282SShri Abhyankar 
19342b4ed282SShri Abhyankar   PetscFunctionBegin;
19352b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
19362b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19372b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
19387fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19392b4ed282SShri Abhyankar   if (vi->postcheckstep) {
19402b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
19412b4ed282SShri Abhyankar   }
19422b4ed282SShri Abhyankar   if (changed_y) {
19432b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
19447fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
19452b4ed282SShri Abhyankar   }
19462b4ed282SShri Abhyankar 
19472b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
19482b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
19492b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19502b4ed282SShri Abhyankar   }
19512b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
19522b4ed282SShri Abhyankar   PetscFunctionReturn(0);
19532b4ed282SShri Abhyankar }
19547fe79bc4SShri Abhyankar 
19552b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
19562b4ed282SShri Abhyankar #undef __FUNCT__
19572b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
19582b4ed282SShri Abhyankar /*
19597fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
19602b4ed282SShri Abhyankar */
1961ace3abfcSBarry 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)
19622b4ed282SShri Abhyankar {
1963fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1964fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1965fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1966fe835674SShri Abhyankar   PetscScalar    cinitslope;
1967fe835674SShri Abhyankar #endif
1968fe835674SShri Abhyankar   PetscErrorCode ierr;
1969fe835674SShri Abhyankar   PetscInt       count;
1970fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1971fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1972fe835674SShri Abhyankar   MPI_Comm       comm;
1973fe835674SShri Abhyankar 
1974fe835674SShri Abhyankar   PetscFunctionBegin;
1975fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1976fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1977fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1978fe835674SShri Abhyankar 
1979fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1980fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1981fe835674SShri Abhyankar     if (vi->lsmonitor) {
1982649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1983649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1984649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1985fe835674SShri Abhyankar     }
1986fe835674SShri Abhyankar     *gnorm = fnorm;
1987fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1988fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1989fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1990fe835674SShri Abhyankar     goto theend1;
1991fe835674SShri Abhyankar   }
1992fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1993fe835674SShri Abhyankar     if (vi->lsmonitor) {
1994649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1995649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1996649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
1997fe835674SShri Abhyankar     }
1998fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1999fe835674SShri Abhyankar     *ynorm = vi->maxstep;
2000fe835674SShri Abhyankar   }
2001fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
2002fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
2003fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
2004fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
2005fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
2006fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
2007fe835674SShri Abhyankar #else
2008fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
2009fe835674SShri Abhyankar #endif
2010fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
2011fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
2012fe835674SShri Abhyankar 
2013fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2014fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2015fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2016fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
2017fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2018fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2019fe835674SShri Abhyankar     goto theend1;
2020fe835674SShri Abhyankar   }
2021fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20222f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2023fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20247fe79bc4SShri Abhyankar   } else {
20257fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20267fe79bc4SShri Abhyankar   }
2027fe835674SShri Abhyankar   if (snes->domainerror) {
2028fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2029fe835674SShri Abhyankar     PetscFunctionReturn(0);
2030fe835674SShri Abhyankar   }
203162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2032ed70e96aSJungho Lee   ierr = PetscInfo4(snes,"Initial fnorm %G gnorm %G alpha %G initslope %G\n",fnorm,*gnorm,vi->alpha,initslope);CHKERRQ(ierr);
2033f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm ) { /* Sufficient reduction */
2034fe835674SShri Abhyankar     if (vi->lsmonitor) {
2035649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2036649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
2037649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2038fe835674SShri Abhyankar     }
2039fe835674SShri Abhyankar     goto theend1;
2040fe835674SShri Abhyankar   }
2041fe835674SShri Abhyankar 
2042fe835674SShri Abhyankar   /* Fit points with quadratic */
2043fe835674SShri Abhyankar   lambda     = 1.0;
2044fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
2045fe835674SShri Abhyankar   lambdaprev = lambda;
2046fe835674SShri Abhyankar   gnormprev  = *gnorm;
2047fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2048fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
2049fe835674SShri Abhyankar   else                         lambda = lambdatemp;
2050fe835674SShri Abhyankar 
2051fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2052fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2053fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
2054fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
2055fe835674SShri Abhyankar     *flag = PETSC_FALSE;
2056fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2057fe835674SShri Abhyankar     goto theend1;
2058fe835674SShri Abhyankar   }
2059fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20602f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
2061fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20627fe79bc4SShri Abhyankar   } else {
20637fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20647fe79bc4SShri Abhyankar   }
2065fe835674SShri Abhyankar   if (snes->domainerror) {
2066fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2067fe835674SShri Abhyankar     PetscFunctionReturn(0);
2068fe835674SShri Abhyankar   }
206962cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2070fe835674SShri Abhyankar   if (vi->lsmonitor) {
2071649052a6SBarry Smith     ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2072649052a6SBarry Smith     ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
2073649052a6SBarry Smith     ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2074fe835674SShri Abhyankar   }
2075f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm ) { /* sufficient reduction */
2076fe835674SShri Abhyankar     if (vi->lsmonitor) {
2077649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2078649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
2079649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2080fe835674SShri Abhyankar     }
2081fe835674SShri Abhyankar     goto theend1;
2082fe835674SShri Abhyankar   }
2083fe835674SShri Abhyankar 
2084fe835674SShri Abhyankar   /* Fit points with cubic */
2085fe835674SShri Abhyankar   count = 1;
2086fe835674SShri Abhyankar   while (PETSC_TRUE) {
2087fe835674SShri Abhyankar     if (lambda <= minlambda) {
2088fe835674SShri Abhyankar       if (vi->lsmonitor) {
2089649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2090649052a6SBarry Smith  	ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
2091649052a6SBarry 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);
2092649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2093fe835674SShri Abhyankar       }
2094fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2095fe835674SShri Abhyankar       break;
2096fe835674SShri Abhyankar     }
2097fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
2098fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
2099fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2100fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
2101fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
2102fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
2103fe835674SShri Abhyankar     if (a == 0.0) {
2104fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
2105fe835674SShri Abhyankar     } else {
2106fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
2107fe835674SShri Abhyankar     }
2108fe835674SShri Abhyankar     lambdaprev = lambda;
2109fe835674SShri Abhyankar     gnormprev  = *gnorm;
2110fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
2111fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
2112fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
2113fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
2114fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2115fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
2116fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
2117fe835674SShri 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);
2118fe835674SShri Abhyankar       *flag = PETSC_FALSE;
2119fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
2120fe835674SShri Abhyankar       break;
2121fe835674SShri Abhyankar     }
2122fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21232f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
2124fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21257fe79bc4SShri Abhyankar     } else {
21267fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21277fe79bc4SShri Abhyankar     }
2128fe835674SShri Abhyankar     if (snes->domainerror) {
2129fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2130fe835674SShri Abhyankar       PetscFunctionReturn(0);
2131fe835674SShri Abhyankar     }
213262cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2133f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* is reduction enough? */
2134fe835674SShri Abhyankar       if (vi->lsmonitor) {
2135fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2136fe835674SShri Abhyankar       }
2137fe835674SShri Abhyankar       break;
2138fe835674SShri Abhyankar     } else {
2139fe835674SShri Abhyankar       if (vi->lsmonitor) {
2140fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2141fe835674SShri Abhyankar       }
2142fe835674SShri Abhyankar     }
2143fe835674SShri Abhyankar     count++;
2144fe835674SShri Abhyankar   }
2145fe835674SShri Abhyankar   theend1:
2146fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2147fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2148fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2149fe835674SShri Abhyankar     if (changed_y) {
2150fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2151fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2152fe835674SShri Abhyankar     }
2153fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2154fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21552f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2156fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21577fe79bc4SShri Abhyankar       } else {
21587fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21597fe79bc4SShri Abhyankar       }
2160fe835674SShri Abhyankar       if (snes->domainerror) {
2161fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2162fe835674SShri Abhyankar         PetscFunctionReturn(0);
2163fe835674SShri Abhyankar       }
216462cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2165fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2166fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2167fe835674SShri Abhyankar     }
2168fe835674SShri Abhyankar   }
2169fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2170fe835674SShri Abhyankar   PetscFunctionReturn(0);
2171fe835674SShri Abhyankar }
2172fe835674SShri Abhyankar 
21732b4ed282SShri Abhyankar #undef __FUNCT__
21742b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
21752b4ed282SShri Abhyankar /*
21767fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
21772b4ed282SShri Abhyankar */
2178ace3abfcSBarry 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)
21792b4ed282SShri Abhyankar {
21802b4ed282SShri Abhyankar   /*
21812b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
21822b4ed282SShri Abhyankar      minimization problem:
21832b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
21842b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
21852b4ed282SShri Abhyankar    */
21862b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
21872b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
21882b4ed282SShri Abhyankar   PetscScalar    cinitslope;
21892b4ed282SShri Abhyankar #endif
21902b4ed282SShri Abhyankar   PetscErrorCode ierr;
21912b4ed282SShri Abhyankar   PetscInt       count;
21922b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2193ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
21942b4ed282SShri Abhyankar 
21952b4ed282SShri Abhyankar   PetscFunctionBegin;
21962b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21972b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
21982b4ed282SShri Abhyankar 
21992b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
22002b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2201c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2202649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2203649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
2204649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22052b4ed282SShri Abhyankar     }
22062b4ed282SShri Abhyankar     *gnorm = fnorm;
22072b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
22082b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
22092b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
22102b4ed282SShri Abhyankar     goto theend2;
22112b4ed282SShri Abhyankar   }
22122b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
22132b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
22142b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
22152b4ed282SShri Abhyankar   }
22162b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
22172b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
22187fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
22192b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
22207fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
22212b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
22222b4ed282SShri Abhyankar #else
22237fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
22242b4ed282SShri Abhyankar #endif
22252b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
22262b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
22272b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
22282b4ed282SShri Abhyankar 
22292b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
22307fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22312b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
22322b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
22332b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
22342b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22352b4ed282SShri Abhyankar     goto theend2;
22362b4ed282SShri Abhyankar   }
22372b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22382f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
22397fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22407fe79bc4SShri Abhyankar   } else {
22417fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22427fe79bc4SShri Abhyankar   }
22432b4ed282SShri Abhyankar   if (snes->domainerror) {
22442b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22452b4ed282SShri Abhyankar     PetscFunctionReturn(0);
22462b4ed282SShri Abhyankar   }
224762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2248f2b03b96SBarry Smith   if ((*gnorm)*(*gnorm) <= (1.0 - vi->alpha)*fnorm*fnorm) { /* Sufficient reduction */
2249c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2250649052a6SBarry Smith       ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2251649052a6SBarry Smith       ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
2252649052a6SBarry Smith       ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22532b4ed282SShri Abhyankar     }
22542b4ed282SShri Abhyankar     goto theend2;
22552b4ed282SShri Abhyankar   }
22562b4ed282SShri Abhyankar 
22572b4ed282SShri Abhyankar   /* Fit points with quadratic */
22582b4ed282SShri Abhyankar   lambda = 1.0;
22592b4ed282SShri Abhyankar   count = 1;
22602b4ed282SShri Abhyankar   while (PETSC_TRUE) {
22612b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2262c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2263649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2264649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2265649052a6SBarry 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);
2266649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
22672b4ed282SShri Abhyankar       }
22682b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
22692b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22702b4ed282SShri Abhyankar       break;
22712b4ed282SShri Abhyankar     }
22722b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
22732b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
22742b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
22752b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
22762b4ed282SShri Abhyankar 
22772b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
22787fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
22792b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
22802b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
22812b4ed282SShri 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);
22822b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
22832b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
22842b4ed282SShri Abhyankar       break;
22852b4ed282SShri Abhyankar     }
22862b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
22872b4ed282SShri Abhyankar     if (snes->domainerror) {
22882b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
22892b4ed282SShri Abhyankar       PetscFunctionReturn(0);
22902b4ed282SShri Abhyankar     }
22912f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
22927fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
22937fe79bc4SShri Abhyankar     } else {
22942b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
22957fe79bc4SShri Abhyankar     }
229662cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2297f2b03b96SBarry Smith     if ((*gnorm)*(*gnorm) < (1.0 - vi->alpha)*fnorm*fnorm) { /* sufficient reduction */
2298c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2299649052a6SBarry Smith         ierr = PetscViewerASCIIAddTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
2300649052a6SBarry Smith         ierr = PetscViewerASCIIPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
2301649052a6SBarry Smith         ierr = PetscViewerASCIISubtractTab(vi->lsmonitor,((PetscObject)snes)->tablevel);CHKERRQ(ierr);
23022b4ed282SShri Abhyankar       }
23032b4ed282SShri Abhyankar       break;
23042b4ed282SShri Abhyankar     }
23052b4ed282SShri Abhyankar     count++;
23062b4ed282SShri Abhyankar   }
23072b4ed282SShri Abhyankar   theend2:
23082b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
23092b4ed282SShri Abhyankar   if (vi->postcheckstep) {
23102b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
23112b4ed282SShri Abhyankar     if (changed_y) {
23122b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
23137fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
23142b4ed282SShri Abhyankar     }
23152b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
23162b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
23172b4ed282SShri Abhyankar       if (snes->domainerror) {
23182b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23192b4ed282SShri Abhyankar         PetscFunctionReturn(0);
23202b4ed282SShri Abhyankar       }
23212f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
23227fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
23237fe79bc4SShri Abhyankar       } else {
23247fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
23257fe79bc4SShri Abhyankar       }
23267fe79bc4SShri Abhyankar 
23272b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
23282b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
232962cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
23302b4ed282SShri Abhyankar     }
23312b4ed282SShri Abhyankar   }
23322b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
23332b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23342b4ed282SShri Abhyankar }
23352b4ed282SShri Abhyankar 
2336ace3abfcSBarry 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*/
23372b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23382b4ed282SShri Abhyankar EXTERN_C_BEGIN
23392b4ed282SShri Abhyankar #undef __FUNCT__
23402b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
23417087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
23422b4ed282SShri Abhyankar {
23432b4ed282SShri Abhyankar   PetscFunctionBegin;
23442b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
23452b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
23462b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23472b4ed282SShri Abhyankar }
23482b4ed282SShri Abhyankar EXTERN_C_END
23492b4ed282SShri Abhyankar 
23502b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23512b4ed282SShri Abhyankar EXTERN_C_BEGIN
23522b4ed282SShri Abhyankar #undef __FUNCT__
23532b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
23547087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
23552b4ed282SShri Abhyankar {
23562b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
23572b4ed282SShri Abhyankar   PetscErrorCode ierr;
23582b4ed282SShri Abhyankar 
23592b4ed282SShri Abhyankar   PetscFunctionBegin;
2360c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2361649052a6SBarry Smith     ierr = PetscViewerASCIIOpen(((PetscObject)snes)->comm,"stdout",&vi->lsmonitor);CHKERRQ(ierr);
2362c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
2363649052a6SBarry Smith     ierr = PetscViewerDestroy(&vi->lsmonitor);CHKERRQ(ierr);
23642b4ed282SShri Abhyankar   }
23652b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23662b4ed282SShri Abhyankar }
23672b4ed282SShri Abhyankar EXTERN_C_END
23682b4ed282SShri Abhyankar 
23692b4ed282SShri Abhyankar /*
23702b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
23712b4ed282SShri Abhyankar 
23722b4ed282SShri Abhyankar    Input Parameters:
23732b4ed282SShri Abhyankar .  SNES - the SNES context
23742b4ed282SShri Abhyankar .  viewer - visualization context
23752b4ed282SShri Abhyankar 
23762b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
23772b4ed282SShri Abhyankar */
23782b4ed282SShri Abhyankar #undef __FUNCT__
23792b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
23802b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
23812b4ed282SShri Abhyankar {
23822b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
238378c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
23842b4ed282SShri Abhyankar   PetscErrorCode ierr;
2385ace3abfcSBarry Smith   PetscBool     iascii;
23862b4ed282SShri Abhyankar 
23872b4ed282SShri Abhyankar   PetscFunctionBegin;
23882b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
23892b4ed282SShri Abhyankar   if (iascii) {
23902b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
23912b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
23922b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
23932b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
239478c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
23950a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2396b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
239778c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
239878c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
23992b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
24002b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
24012b4ed282SShri Abhyankar   }
24022b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24032b4ed282SShri Abhyankar }
24042b4ed282SShri Abhyankar 
24055559b345SBarry Smith #undef __FUNCT__
24065559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
24075559b345SBarry Smith /*@
24082b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
24092b4ed282SShri Abhyankar 
24102b4ed282SShri Abhyankar    Input Parameters:
24112b4ed282SShri Abhyankar .  snes - the SNES context.
24122b4ed282SShri Abhyankar .  xl   - lower bound.
24132b4ed282SShri Abhyankar .  xu   - upper bound.
24142b4ed282SShri Abhyankar 
24152b4ed282SShri Abhyankar    Notes:
24162b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
241701f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
241884c105d7SBarry Smith 
24195559b345SBarry Smith @*/
242069c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
24212b4ed282SShri Abhyankar {
2422d923200aSJungho Lee   SNES_VI           *vi;
2423d923200aSJungho Lee   PetscErrorCode    ierr;
24246fd67740SBarry Smith   const PetscScalar *xxl,*xxu;
24256fd67740SBarry Smith   PetscInt          i,n, cnt = 0;
24262b4ed282SShri Abhyankar 
24272b4ed282SShri Abhyankar   PetscFunctionBegin;
24282b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
24292b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
24302b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
24312b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
24322b4ed282SShri 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);
24332b4ed282SShri 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);
2434d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2435d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
24362176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xl);CHKERRQ(ierr);
24372176524cSBarry Smith   ierr = PetscObjectReference((PetscObject)xu);CHKERRQ(ierr);
24382176524cSBarry Smith   ierr = VecDestroy(&vi->xl);CHKERRQ(ierr);
24392176524cSBarry Smith   ierr = VecDestroy(&vi->xu);CHKERRQ(ierr);
24402b4ed282SShri Abhyankar   vi->xl = xl;
24412b4ed282SShri Abhyankar   vi->xu = xu;
24426fd67740SBarry Smith   ierr = VecGetLocalSize(xl,&n);CHKERRQ(ierr);
24436fd67740SBarry Smith   ierr = VecGetArrayRead(xl,&xxl);CHKERRQ(ierr);
24446fd67740SBarry Smith   ierr = VecGetArrayRead(xu,&xxu);CHKERRQ(ierr);
24456fd67740SBarry Smith   for (i=0; i<n; i++) {
24466fd67740SBarry Smith     cnt += ((xxl[i] != SNES_VI_NINF) || (xxu[i] != SNES_VI_INF));
24476fd67740SBarry Smith   }
24486fd67740SBarry Smith   ierr = MPI_Allreduce(&cnt,&vi->ntruebounds,1,MPIU_INT,MPI_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
24496fd67740SBarry Smith   ierr = VecRestoreArrayRead(xl,&xxl);CHKERRQ(ierr);
24506fd67740SBarry Smith   ierr = VecRestoreArrayRead(xu,&xxu);CHKERRQ(ierr);
24512b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24522b4ed282SShri Abhyankar }
2453693ddf92SShri Abhyankar 
24542b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
24552b4ed282SShri Abhyankar /*
24562b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
24572b4ed282SShri Abhyankar 
24582b4ed282SShri Abhyankar    Input Parameter:
24592b4ed282SShri Abhyankar .  snes - the SNES context
24602b4ed282SShri Abhyankar 
24612b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
24622b4ed282SShri Abhyankar */
24632b4ed282SShri Abhyankar #undef __FUNCT__
24642b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
24652b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
24662b4ed282SShri Abhyankar {
24672b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
24687fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2469b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
24702b4ed282SShri Abhyankar   PetscErrorCode ierr;
24712b4ed282SShri Abhyankar   PetscInt       indx;
247269c03620SShri Abhyankar   PetscBool      flg,set,flg2;
24732b4ed282SShri Abhyankar 
24742b4ed282SShri Abhyankar   PetscFunctionBegin;
24752b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
24769308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
24779308c137SBarry Smith   if (flg) {
24789308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
24799308c137SBarry Smith   }
2480be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2481be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2482be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
24832b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2484be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
24852b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
24862f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
248769c03620SShri Abhyankar   if (flg2) {
248869c03620SShri Abhyankar     switch (indx) {
248969c03620SShri Abhyankar     case 0:
249069c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
249169c03620SShri Abhyankar       break;
249269c03620SShri Abhyankar     case 1:
2493d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2494d950fb63SShri Abhyankar       break;
24952f63a38cSShri Abhyankar     case 2:
2496b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
249769c03620SShri Abhyankar     }
249869c03620SShri Abhyankar   }
2499f2b03b96SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"cubic",&indx,&flg);CHKERRQ(ierr);
25002b4ed282SShri Abhyankar   if (flg) {
25012b4ed282SShri Abhyankar     switch (indx) {
25022b4ed282SShri Abhyankar     case 0:
25032b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
25042b4ed282SShri Abhyankar       break;
25052b4ed282SShri Abhyankar     case 1:
25062b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
25072b4ed282SShri Abhyankar       break;
25082b4ed282SShri Abhyankar     case 2:
25092b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
25102b4ed282SShri Abhyankar       break;
25112b4ed282SShri Abhyankar     case 3:
25122b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
25132b4ed282SShri Abhyankar       break;
25142b4ed282SShri Abhyankar     }
2515fe835674SShri Abhyankar   }
25162b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
25172b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25182b4ed282SShri Abhyankar }
25192b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
25202b4ed282SShri Abhyankar /*MC
25218b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
25222b4ed282SShri Abhyankar 
25232b4ed282SShri Abhyankar    Options Database:
25248b4c83edSBarry 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
25258b4c83edSBarry Smith                                 additional variables that enforce the constraints
25268b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
25272b4ed282SShri Abhyankar 
25282b4ed282SShri Abhyankar 
25292b4ed282SShri Abhyankar    Level: beginner
25302b4ed282SShri Abhyankar 
25312b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
25322b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
25332b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
25342b4ed282SShri Abhyankar 
25352b4ed282SShri Abhyankar M*/
25362b4ed282SShri Abhyankar EXTERN_C_BEGIN
25372b4ed282SShri Abhyankar #undef __FUNCT__
25382b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
25397087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
25402b4ed282SShri Abhyankar {
25412b4ed282SShri Abhyankar   PetscErrorCode ierr;
25422b4ed282SShri Abhyankar   SNES_VI        *vi;
25432b4ed282SShri Abhyankar 
25442b4ed282SShri Abhyankar   PetscFunctionBegin;
25452176524cSBarry Smith   snes->ops->reset           = SNESReset_VI;
25462b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2547edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
25482b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
25492b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
25502b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
25512b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
25522b4ed282SShri Abhyankar 
25532b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
25542b4ed282SShri Abhyankar   snes->data            = (void*)vi;
25552b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
25562b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
25572b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
2558f2b03b96SBarry Smith   vi->LineSearch        = SNESLineSearchCubic_VI;
25592b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
25602b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
25612b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
25622b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
25632b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
25642b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
25652f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
25662b4ed282SShri Abhyankar 
25672b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
25682b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
25692b4ed282SShri Abhyankar 
25702b4ed282SShri Abhyankar   PetscFunctionReturn(0);
25712b4ed282SShri Abhyankar }
25722b4ed282SShri Abhyankar EXTERN_C_END
2573ed70e96aSJungho Lee 
2574ed70e96aSJungho Lee #undef __FUNCT__
2575ed70e96aSJungho Lee #define __FUNCT__ "SNESVIGetInactiveSet"
2576ed70e96aSJungho Lee /*
2577ed70e96aSJungho Lee    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
2578ed70e96aSJungho Lee      system is solved on)
2579ed70e96aSJungho Lee 
2580ed70e96aSJungho Lee    Input parameter
2581ed70e96aSJungho Lee .  snes - the SNES context
2582ed70e96aSJungho Lee 
2583ed70e96aSJungho Lee    Output parameter
2584ed70e96aSJungho Lee .  ISact - active set index set
2585ed70e96aSJungho Lee 
2586ed70e96aSJungho Lee  */
2587ed70e96aSJungho Lee PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS* inact)
2588ed70e96aSJungho Lee {
2589ed70e96aSJungho Lee   SNES_VI          *vi = (SNES_VI*)snes->data;
2590ed70e96aSJungho Lee   PetscFunctionBegin;
2591ed70e96aSJungho Lee   *inact = vi->IS_inact_prev;
2592ed70e96aSJungho Lee   PetscFunctionReturn(0);
2593ed70e96aSJungho Lee }
2594