xref: /petsc/src/snes/impls/vi/vi.c (revision 3c0c59f39ee3bd561a1b4dcbd0e58366bfa60aba)
12b4ed282SShri Abhyankar 
2c6db04a5SJed Brown #include <../src/snes/impls/vi/viimpl.h> /*I "petscsnes.h" I*/
3c6db04a5SJed Brown #include <../include/private/kspimpl.h>
4c6db04a5SJed Brown #include <../include/private/matimpl.h>
5d0af7cd3SBarry Smith #include <../include/private/dmimpl.h>
6d0af7cd3SBarry Smith 
7d0af7cd3SBarry Smith #undef __FUNCT__
8d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS"
9d0af7cd3SBarry Smith /*
10d0af7cd3SBarry Smith    SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables
11d0af7cd3SBarry Smith 
12d0af7cd3SBarry Smith    Input parameter
13d0af7cd3SBarry Smith .  snes - the SNES context
14d0af7cd3SBarry Smith .  X    - the snes solution vector
15d0af7cd3SBarry Smith 
16d0af7cd3SBarry Smith    Output parameter
17d0af7cd3SBarry Smith .  ISact - active set index set
18d0af7cd3SBarry Smith 
19d0af7cd3SBarry Smith  */
20d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
21d0af7cd3SBarry Smith {
22d0af7cd3SBarry Smith   PetscErrorCode   ierr;
23d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
24d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
25d0af7cd3SBarry Smith 
26d0af7cd3SBarry Smith   PetscFunctionBegin;
27d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
28d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
29d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
30d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
31d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
32d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
33d0af7cd3SBarry Smith   /* Compute inactive set size */
34d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
35d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) nloc_isact++;
36d0af7cd3SBarry Smith   }
37d0af7cd3SBarry Smith 
38d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
39d0af7cd3SBarry Smith 
40d0af7cd3SBarry Smith   /* Set inactive set indices */
41d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
42d0af7cd3SBarry Smith     if (((PetscRealPart(x[i]) > PetscRealPart(xl[i]) + 1.e-8 || (PetscRealPart(f[i]) < 0.0)) && ((PetscRealPart(x[i]) < PetscRealPart(xu[i]) - 1.e-8) || PetscRealPart(f[i]) > 0.0))) idx_act[i1++] = ilow+i;
43d0af7cd3SBarry Smith   }
44d0af7cd3SBarry Smith 
45d0af7cd3SBarry Smith    /* Create inactive set IS */
46d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
47d0af7cd3SBarry Smith 
48d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
49d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
50d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
51d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
52d0af7cd3SBarry Smith   PetscFunctionReturn(0);
53d0af7cd3SBarry Smith }
54d0af7cd3SBarry Smith 
55*3c0c59f3SBarry Smith /*
56*3c0c59f3SBarry 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
57*3c0c59f3SBarry Smith   defined by the reduced space method.
58*3c0c59f3SBarry Smith 
59*3c0c59f3SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
60*3c0c59f3SBarry Smith 
61*3c0c59f3SBarry Smith */
62*3c0c59f3SBarry Smith typedef struct {
63*3c0c59f3SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
64*3c0c59f3SBarry Smith   IS             inactive;
65*3c0c59f3SBarry Smith   Vec            upper,lower,values,F;                    /* upper and lower bounds of all variables on this level, the values and the function values */
66*3c0c59f3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
67*3c0c59f3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
68*3c0c59f3SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
69*3c0c59f3SBarry Smith } DM_SNESVI;
70*3c0c59f3SBarry Smith 
71d0af7cd3SBarry Smith #undef __FUNCT__
724dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
734dcab191SBarry Smith /*
744dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
754dcab191SBarry Smith 
764dcab191SBarry Smith */
774dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
784dcab191SBarry Smith {
794dcab191SBarry Smith   PetscErrorCode          ierr;
804dcab191SBarry Smith   PetscContainer          isnes;
81*3c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
824dcab191SBarry Smith 
834dcab191SBarry Smith   PetscFunctionBegin;
844dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
854dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
864dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
874dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
884dcab191SBarry Smith   PetscFunctionReturn(0);
894dcab191SBarry Smith }
904dcab191SBarry Smith 
914dcab191SBarry Smith #undef __FUNCT__
92d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
93d0af7cd3SBarry Smith /*
94d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
95d0af7cd3SBarry Smith 
96d0af7cd3SBarry Smith */
97d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
98d0af7cd3SBarry Smith {
99d0af7cd3SBarry Smith   PetscErrorCode          ierr;
100d0af7cd3SBarry Smith   PetscContainer          isnes;
101*3c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1,*dmsnesvi2;
102d0af7cd3SBarry Smith   Mat                     interp;
103d0af7cd3SBarry Smith 
104d0af7cd3SBarry Smith   PetscFunctionBegin;
105d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1064dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
107d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
108d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1094dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
110d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
111d0af7cd3SBarry Smith 
112d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1134dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
114d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
115d0af7cd3SBarry Smith   PetscFunctionReturn(0);
116d0af7cd3SBarry Smith }
117d0af7cd3SBarry Smith 
118d0af7cd3SBarry Smith extern PetscErrorCode  DMSetVI(DM,Vec,Vec,Vec,Vec,IS);
119d0af7cd3SBarry Smith 
120d0af7cd3SBarry Smith #undef __FUNCT__
121d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
122d0af7cd3SBarry Smith /*
123d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
124d0af7cd3SBarry Smith 
125d0af7cd3SBarry Smith */
126d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
127d0af7cd3SBarry Smith {
128d0af7cd3SBarry Smith   PetscErrorCode          ierr;
129d0af7cd3SBarry Smith   PetscContainer          isnes;
130*3c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi1;
131d0af7cd3SBarry Smith   Vec                     upper,lower,values,F;
132d0af7cd3SBarry Smith   IS                      inactive;
133d0af7cd3SBarry Smith   VecScatter              inject;
134d0af7cd3SBarry Smith 
135d0af7cd3SBarry Smith   PetscFunctionBegin;
136d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1374dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
138d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
139d0af7cd3SBarry Smith 
140298cc208SBarry Smith   /* get the original coarsen */
141d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
142298cc208SBarry Smith 
143*3c0c59f3SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
144*3c0c59f3SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
145*3c0c59f3SBarry Smith 
146298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
147298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
148298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
149d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
150d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr);
151d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
152d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
153d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr);
154d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
155d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
156d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr);
157d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
158d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
159d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr);
160d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
161d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
162d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
163298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
164298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
165d0af7cd3SBarry Smith   ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr);
166d0af7cd3SBarry Smith   ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr);
167*3c0c59f3SBarry Smith   ierr = VecDestroy(&upper);CHKERRQ(ierr);
168*3c0c59f3SBarry Smith   ierr = VecDestroy(&lower);CHKERRQ(ierr);
169*3c0c59f3SBarry Smith   ierr = VecDestroy(&values);CHKERRQ(ierr);
170*3c0c59f3SBarry Smith   ierr = VecDestroy(&F);CHKERRQ(ierr);
171*3c0c59f3SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
172d0af7cd3SBarry Smith   PetscFunctionReturn(0);
173d0af7cd3SBarry Smith }
174d0af7cd3SBarry Smith 
175d0af7cd3SBarry Smith #undef __FUNCT__
176*3c0c59f3SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
177*3c0c59f3SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
178d0af7cd3SBarry Smith {
179d0af7cd3SBarry Smith   PetscErrorCode ierr;
180d0af7cd3SBarry Smith 
181d0af7cd3SBarry Smith   PetscFunctionBegin;
182d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
183d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
184d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
185d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
186d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
187d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
188d0af7cd3SBarry Smith   PetscFunctionReturn(0);
189d0af7cd3SBarry Smith }
190d0af7cd3SBarry Smith 
191d0af7cd3SBarry Smith #undef __FUNCT__
192d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
193d0af7cd3SBarry Smith /*
194d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
195d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
196d0af7cd3SBarry Smith 
197d0af7cd3SBarry Smith */
198d0af7cd3SBarry Smith PetscErrorCode  DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive)
199d0af7cd3SBarry Smith {
200d0af7cd3SBarry Smith   PetscErrorCode          ierr;
201d0af7cd3SBarry Smith   PetscContainer          isnes;
202*3c0c59f3SBarry Smith   DM_SNESVI               *dmsnesvi;
203d0af7cd3SBarry Smith 
204d0af7cd3SBarry Smith   PetscFunctionBegin;
2054dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
206d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr);
207d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr);
208d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr);
209d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
210d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
211d0af7cd3SBarry Smith 
212d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
213d0af7cd3SBarry Smith   if (!isnes) {
214d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
215*3c0c59f3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
216*3c0c59f3SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
217d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
218d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
219*3c0c59f3SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
220d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
221d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
222d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
223d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
224298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2254dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
226d0af7cd3SBarry Smith   } else {
227d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
228d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
229d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
230d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
231d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
232d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
233d0af7cd3SBarry Smith   }
2344dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2354dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
236d0af7cd3SBarry Smith   dmsnesvi->upper    = upper;
237d0af7cd3SBarry Smith   dmsnesvi->lower    = lower;
238d0af7cd3SBarry Smith   dmsnesvi->values   = values;
239d0af7cd3SBarry Smith   dmsnesvi->F        = F;
240d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
241*3c0c59f3SBarry Smith   /* since these vectors may reference the DM, need to remove circle referencing */
242*3c0c59f3SBarry Smith   ierr = PetscObjectCompose((PetscObject)dmsnesvi->upper,"DM",PETSC_NULL);CHKERRQ(ierr);
243*3c0c59f3SBarry Smith   ierr = PetscObjectCompose((PetscObject)dmsnesvi->lower,"DM",PETSC_NULL);CHKERRQ(ierr);
244*3c0c59f3SBarry Smith   ierr = PetscObjectCompose((PetscObject)dmsnesvi->values,"DM",PETSC_NULL);CHKERRQ(ierr);
245*3c0c59f3SBarry Smith   ierr = PetscObjectCompose((PetscObject)dmsnesvi->F,"DM",PETSC_NULL);CHKERRQ(ierr);
246d0af7cd3SBarry Smith   PetscFunctionReturn(0);
247d0af7cd3SBarry Smith }
248d0af7cd3SBarry Smith 
249*3c0c59f3SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
2502b4ed282SShri Abhyankar 
2519308c137SBarry Smith #undef __FUNCT__
2529308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
2537087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
2549308c137SBarry Smith {
2559308c137SBarry Smith   PetscErrorCode          ierr;
2569308c137SBarry Smith   SNES_VI                 *vi = (SNES_VI*)snes->data;
2579308c137SBarry Smith   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
2589308c137SBarry Smith   const PetscScalar       *x,*xl,*xu,*f;
25909573ac7SBarry Smith   PetscInt                i,n,act = 0;
2609308c137SBarry Smith   PetscReal               rnorm,fnorm;
2619308c137SBarry Smith 
2629308c137SBarry Smith   PetscFunctionBegin;
2639308c137SBarry Smith   if (!dummy) {
2649308c137SBarry Smith     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
2659308c137SBarry Smith   }
2669308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
2679308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
2689308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
2699308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
2703f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
2719308c137SBarry Smith 
2729308c137SBarry Smith   rnorm = 0.0;
2739308c137SBarry Smith   for (i=0; i<n; i++) {
27410f5ae6bSBarry 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]);
27509573ac7SBarry Smith     else act++;
2769308c137SBarry Smith   }
2773f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
2789308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
2799308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
2809308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
281d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
2829308c137SBarry Smith   fnorm = sqrt(fnorm);
28309573ac7SBarry Smith   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
2849308c137SBarry Smith   if (!dummy) {
2856bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr);
2869308c137SBarry Smith   }
2879308c137SBarry Smith   PetscFunctionReturn(0);
2889308c137SBarry Smith }
2899308c137SBarry Smith 
2902b4ed282SShri Abhyankar /*
2912b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
2922b4ed282SShri 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
2932b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
2942b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
2952b4ed282SShri Abhyankar */
2962b4ed282SShri Abhyankar #undef __FUNCT__
2972b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
298ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
2992b4ed282SShri Abhyankar {
3002b4ed282SShri Abhyankar   PetscReal      a1;
3012b4ed282SShri Abhyankar   PetscErrorCode ierr;
302ace3abfcSBarry Smith   PetscBool     hastranspose;
3032b4ed282SShri Abhyankar 
3042b4ed282SShri Abhyankar   PetscFunctionBegin;
3052b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
3062b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3072b4ed282SShri Abhyankar   if (hastranspose) {
3082b4ed282SShri Abhyankar     /* Compute || J^T F|| */
3092b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
3102b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
3112b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
3122b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
3132b4ed282SShri Abhyankar   } else {
3142b4ed282SShri Abhyankar     Vec         work;
3152b4ed282SShri Abhyankar     PetscScalar result;
3162b4ed282SShri Abhyankar     PetscReal   wnorm;
3172b4ed282SShri Abhyankar 
3182b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
3192b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3202b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3212b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3222b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3236bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3242b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3252b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3262b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3272b4ed282SShri Abhyankar   }
3282b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3292b4ed282SShri Abhyankar }
3302b4ed282SShri Abhyankar 
3312b4ed282SShri Abhyankar /*
3322b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3332b4ed282SShri Abhyankar */
3342b4ed282SShri Abhyankar #undef __FUNCT__
3352b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3362b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3372b4ed282SShri Abhyankar {
3382b4ed282SShri Abhyankar   PetscReal      a1,a2;
3392b4ed282SShri Abhyankar   PetscErrorCode ierr;
340ace3abfcSBarry Smith   PetscBool     hastranspose;
3412b4ed282SShri Abhyankar 
3422b4ed282SShri Abhyankar   PetscFunctionBegin;
3432b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3442b4ed282SShri Abhyankar   if (hastranspose) {
3452b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3462b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3472b4ed282SShri Abhyankar 
3482b4ed282SShri Abhyankar     /* Compute || J^T W|| */
3492b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
3502b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
3512b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
3522b4ed282SShri Abhyankar     if (a1 != 0.0) {
3532b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
3542b4ed282SShri Abhyankar     }
3552b4ed282SShri Abhyankar   }
3562b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3572b4ed282SShri Abhyankar }
3582b4ed282SShri Abhyankar 
3592b4ed282SShri Abhyankar /*
3602b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
3612b4ed282SShri Abhyankar 
3622b4ed282SShri Abhyankar   Notes:
3632b4ed282SShri Abhyankar   The convergence criterion currently implemented is
3642b4ed282SShri Abhyankar   merit < abstol
3652b4ed282SShri Abhyankar   merit < rtol*merit_initial
3662b4ed282SShri Abhyankar */
3672b4ed282SShri Abhyankar #undef __FUNCT__
3682b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
3697fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
3702b4ed282SShri Abhyankar {
3712b4ed282SShri Abhyankar   PetscErrorCode ierr;
3722b4ed282SShri Abhyankar 
3732b4ed282SShri Abhyankar   PetscFunctionBegin;
3742b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3752b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
3762b4ed282SShri Abhyankar 
3772b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
3782b4ed282SShri Abhyankar 
3792b4ed282SShri Abhyankar   if (!it) {
3802b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
3817fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
3822b4ed282SShri Abhyankar   }
3837fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
3842b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
3852b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
3867fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
3877fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
3882b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
3892b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
3902b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
3912b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
3922b4ed282SShri Abhyankar   }
3932b4ed282SShri Abhyankar 
3942b4ed282SShri Abhyankar   if (it && !*reason) {
3957fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
3967fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
3972b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
3982b4ed282SShri Abhyankar     }
3992b4ed282SShri Abhyankar   }
4002b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4012b4ed282SShri Abhyankar }
4022b4ed282SShri Abhyankar 
4032b4ed282SShri Abhyankar /*
4042b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
4052b4ed282SShri Abhyankar 
4062b4ed282SShri Abhyankar   Input Parameter:
4072b4ed282SShri Abhyankar . phi - the semismooth function
4082b4ed282SShri Abhyankar 
4092b4ed282SShri Abhyankar   Output Parameter:
4102b4ed282SShri Abhyankar . merit - the merit function
4112b4ed282SShri Abhyankar . phinorm - ||phi||
4122b4ed282SShri Abhyankar 
4132b4ed282SShri Abhyankar   Notes:
4142b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
4152b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
4162b4ed282SShri Abhyankar */
4172b4ed282SShri Abhyankar #undef __FUNCT__
4182b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
4192b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4202b4ed282SShri Abhyankar {
4212b4ed282SShri Abhyankar   PetscErrorCode ierr;
4222b4ed282SShri Abhyankar 
4232b4ed282SShri Abhyankar   PetscFunctionBegin;
4245f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4255f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4262b4ed282SShri Abhyankar 
4272b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4282b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4292b4ed282SShri Abhyankar }
4302b4ed282SShri Abhyankar 
4317f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4324c21c6cdSBarry Smith {
4334c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4344c21c6cdSBarry Smith }
4354c21c6cdSBarry Smith 
4367f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4374c21c6cdSBarry Smith {
4385559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4395559b345SBarry Smith   else return .5;
4404c21c6cdSBarry Smith }
4414c21c6cdSBarry Smith 
4422b4ed282SShri Abhyankar /*
4431f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4442b4ed282SShri Abhyankar 
4452b4ed282SShri Abhyankar    Input Parameters:
4462b4ed282SShri Abhyankar .  snes - the SNES context
4472b4ed282SShri Abhyankar .  x - current iterate
4482b4ed282SShri Abhyankar .  functx - user defined function context
4492b4ed282SShri Abhyankar 
4502b4ed282SShri Abhyankar    Output Parameters:
4512b4ed282SShri Abhyankar .  phi - Semismooth function
4522b4ed282SShri Abhyankar 
4532b4ed282SShri Abhyankar */
4542b4ed282SShri Abhyankar #undef __FUNCT__
4551f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
4561f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
4572b4ed282SShri Abhyankar {
4582b4ed282SShri Abhyankar   PetscErrorCode  ierr;
4592b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
4602b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
4614c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
4622b4ed282SShri Abhyankar   PetscInt        i,nlocal;
4632b4ed282SShri Abhyankar 
4642b4ed282SShri Abhyankar   PetscFunctionBegin;
4652b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
4662b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
4672b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
4682b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
4692b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
4702b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
4712b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
4722b4ed282SShri Abhyankar 
4732b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
47410f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
4754c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
47610f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
4774c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
47810f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
4794c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
4805559b345SBarry Smith     } else if (l[i] == u[i]) {
4812b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
4825559b345SBarry Smith     } else {                                                /* both bounds on variable */
4834c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
4842b4ed282SShri Abhyankar     }
4852b4ed282SShri Abhyankar   }
4862b4ed282SShri Abhyankar 
4872b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
4882b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
4892b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
4902b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
4912b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
4922b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4932b4ed282SShri Abhyankar }
4942b4ed282SShri Abhyankar 
4952b4ed282SShri Abhyankar /*
496a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
497a79edbefSShri Abhyankar                                           the semismooth jacobian.
4982b4ed282SShri Abhyankar */
4992b4ed282SShri Abhyankar #undef __FUNCT__
500a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
501a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
5022b4ed282SShri Abhyankar {
5032b4ed282SShri Abhyankar   PetscErrorCode ierr;
5042b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
5054c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
5062b4ed282SShri Abhyankar   PetscInt       i,nlocal;
5072b4ed282SShri Abhyankar 
5082b4ed282SShri Abhyankar   PetscFunctionBegin;
5092b4ed282SShri Abhyankar 
5102b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
5112b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
5122b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
5132b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
514a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
515a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
5162b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
5174c21c6cdSBarry Smith 
5182b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
51910f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5204c21c6cdSBarry Smith       da[i] = 0;
5212b4ed282SShri Abhyankar       db[i] = 1;
52210f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5234c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5244c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
52510f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5265559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5275559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5285559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5294c21c6cdSBarry Smith       da[i] = 1;
5302b4ed282SShri Abhyankar       db[i] = 0;
5315559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5324c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5334c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5344c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5354c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5364c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5374c21c6cdSBarry Smith       db[i] = db1*db2;
5382b4ed282SShri Abhyankar     }
5392b4ed282SShri Abhyankar   }
5405559b345SBarry Smith 
5412b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5422b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5432b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5442b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
545a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
546a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
547a79edbefSShri Abhyankar   PetscFunctionReturn(0);
548a79edbefSShri Abhyankar }
549a79edbefSShri Abhyankar 
550a79edbefSShri Abhyankar /*
551a79edbefSShri 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.
552a79edbefSShri Abhyankar 
553a79edbefSShri Abhyankar    Input Parameters:
554a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
555a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
556a79edbefSShri Abhyankar 
557a79edbefSShri Abhyankar    Output Parameters:
558a79edbefSShri Abhyankar .  jac      - semismooth jacobian
559a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
560a79edbefSShri Abhyankar 
561a79edbefSShri Abhyankar    Notes:
562a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
563a79edbefSShri Abhyankar    jac = Da + Db*jacfun
564a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
565a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
566a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
567a79edbefSShri Abhyankar */
568a79edbefSShri Abhyankar #undef __FUNCT__
569a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
570a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
571a79edbefSShri Abhyankar {
572a79edbefSShri Abhyankar   PetscErrorCode ierr;
573a79edbefSShri Abhyankar 
5742b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
575a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
576a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
577a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
578a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
579a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
5802b4ed282SShri Abhyankar   }
5812b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5822b4ed282SShri Abhyankar }
5832b4ed282SShri Abhyankar 
5842b4ed282SShri Abhyankar /*
585ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
586ee657d29SShri Abhyankar 
587ee657d29SShri Abhyankar    Input Parameters:
588ee657d29SShri Abhyankar    phi - semismooth function.
589ee657d29SShri Abhyankar    H   - semismooth jacobian
590ee657d29SShri Abhyankar 
591ee657d29SShri Abhyankar    Output Parameters:
592ee657d29SShri Abhyankar    dpsi - merit function gradient
593ee657d29SShri Abhyankar 
594ee657d29SShri Abhyankar    Notes:
595ee657d29SShri Abhyankar   The merit function gradient is computed as follows
596ee657d29SShri Abhyankar         dpsi = H^T*phi
597ee657d29SShri Abhyankar */
598ee657d29SShri Abhyankar #undef __FUNCT__
599ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
600ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
601ee657d29SShri Abhyankar {
602ee657d29SShri Abhyankar   PetscErrorCode ierr;
603ee657d29SShri Abhyankar 
604ee657d29SShri Abhyankar   PetscFunctionBegin;
6055f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
606ee657d29SShri Abhyankar   PetscFunctionReturn(0);
607ee657d29SShri Abhyankar }
608ee657d29SShri Abhyankar 
609c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
610c1a5e521SShri Abhyankar /*
611c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
612c1a5e521SShri Abhyankar 
613c1a5e521SShri Abhyankar    Input Parameters:
614c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
615c1a5e521SShri Abhyankar 
616c1a5e521SShri Abhyankar    Output Parameters:
617c1a5e521SShri Abhyankar .  X - Bound projected X
618c1a5e521SShri Abhyankar 
619c1a5e521SShri Abhyankar */
620c1a5e521SShri Abhyankar 
621c1a5e521SShri Abhyankar #undef __FUNCT__
622c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
623c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
624c1a5e521SShri Abhyankar {
625c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
626c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
627c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
628c1a5e521SShri Abhyankar   PetscScalar       *x;
629c1a5e521SShri Abhyankar   PetscInt          i,n;
630c1a5e521SShri Abhyankar 
631c1a5e521SShri Abhyankar   PetscFunctionBegin;
632c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
633c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
634c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
635c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
636c1a5e521SShri Abhyankar 
637c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
63810f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
63910f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
640c1a5e521SShri Abhyankar   }
641c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
642c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
643c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
644c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
645c1a5e521SShri Abhyankar }
646c1a5e521SShri Abhyankar 
6472b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
6482b4ed282SShri Abhyankar 
6492b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
6502b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
6512b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
6522b4ed282SShri Abhyankar      respectively.
6532b4ed282SShri Abhyankar 
6542b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
6552b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
6562b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
6572b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
6582b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
6592b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
6602b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
6612b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
6622b4ed282SShri Abhyankar      These routines are actually called via the common user interface
6632b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
6642b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
6652b4ed282SShri Abhyankar      for all nonlinear solvers.
6662b4ed282SShri Abhyankar 
6672b4ed282SShri Abhyankar      Another key routine is:
6682b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
6692b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
6702b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
6712b4ed282SShri Abhyankar      SNESSolve() if necessary.
6722b4ed282SShri Abhyankar 
6732b4ed282SShri Abhyankar      Additional basic routines are:
6742b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
6752b4ed282SShri Abhyankar                                       have actually been used.
6762b4ed282SShri Abhyankar      These are called by application codes via the interface routines
6772b4ed282SShri Abhyankar      SNESView().
6782b4ed282SShri Abhyankar 
6792b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
6802b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
6812b4ed282SShri Abhyankar      above description applies to these categories also.
6822b4ed282SShri Abhyankar 
6832b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
6842b4ed282SShri Abhyankar /*
68569c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
6862b4ed282SShri Abhyankar    method using a line search.
6872b4ed282SShri Abhyankar 
6882b4ed282SShri Abhyankar    Input Parameters:
6892b4ed282SShri Abhyankar .  snes - the SNES context
6902b4ed282SShri Abhyankar 
6912b4ed282SShri Abhyankar    Output Parameter:
6922b4ed282SShri Abhyankar .  outits - number of iterations until termination
6932b4ed282SShri Abhyankar 
6942b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
6952b4ed282SShri Abhyankar 
6962b4ed282SShri Abhyankar    Notes:
6972b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
69851defd01SShri Abhyankar    line search. The default line search does not do any line seach
69951defd01SShri Abhyankar    but rather takes a full newton step.
7002b4ed282SShri Abhyankar */
7012b4ed282SShri Abhyankar #undef __FUNCT__
70269c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
70369c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
7042b4ed282SShri Abhyankar {
7052b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
7062b4ed282SShri Abhyankar   PetscErrorCode     ierr;
7072b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
7083b336b49SShri Abhyankar   PetscBool          lssucceed;
7092b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
7102b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
7112b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
7122b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
7132b4ed282SShri Abhyankar 
7142b4ed282SShri Abhyankar   PetscFunctionBegin;
7159ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
7169ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
7179ce7406fSBarry Smith 
7182b4ed282SShri Abhyankar   snes->numFailures            = 0;
7192b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7202b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7212b4ed282SShri Abhyankar 
7222b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7232b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7242b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7252b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7262b4ed282SShri Abhyankar   G		= snes->work[1];
7272b4ed282SShri Abhyankar   W		= snes->work[2];
7282b4ed282SShri Abhyankar 
7292b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7302b4ed282SShri Abhyankar   snes->iter = 0;
7312b4ed282SShri Abhyankar   snes->norm = 0.0;
7322b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7332b4ed282SShri Abhyankar 
7347fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7352b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7362b4ed282SShri Abhyankar   if (snes->domainerror) {
7372b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7389ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7392b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7402b4ed282SShri Abhyankar   }
7412b4ed282SShri Abhyankar    /* Compute Merit function */
7422b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7432b4ed282SShri Abhyankar 
7442b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7452b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
74662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7472b4ed282SShri Abhyankar 
7482b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7492b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
7502b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7512b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
7527a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
7532b4ed282SShri Abhyankar 
7542b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
7552b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
7562b4ed282SShri Abhyankar   /* test convergence */
7572b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
7589ce7406fSBarry Smith   if (snes->reason) {
7599ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7609ce7406fSBarry Smith     PetscFunctionReturn(0);
7619ce7406fSBarry Smith   }
7622b4ed282SShri Abhyankar 
7632b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
7642b4ed282SShri Abhyankar 
7652b4ed282SShri Abhyankar     /* Call general purpose update function */
7662b4ed282SShri Abhyankar     if (snes->ops->update) {
7672b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
7682b4ed282SShri Abhyankar     }
7692b4ed282SShri Abhyankar 
7702b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
771a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
7722b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
773a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
774a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
775a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
776a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
777ee657d29SShri Abhyankar     /* Compute the merit function gradient */
778ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
7792b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
7802b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
7812b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
7823b336b49SShri Abhyankar 
7833b336b49SShri Abhyankar     if (kspreason < 0) {
7842b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
7852b4ed282SShri 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);
7862b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
7872b4ed282SShri Abhyankar         break;
7882b4ed282SShri Abhyankar       }
7892b4ed282SShri Abhyankar     }
7902b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
7912b4ed282SShri Abhyankar     snes->linear_its += lits;
7922b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
7932b4ed282SShri Abhyankar     /*
7942b4ed282SShri Abhyankar     if (vi->precheckstep) {
795ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
7962b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
7972b4ed282SShri Abhyankar     }
7982b4ed282SShri Abhyankar 
7992b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
8002b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
8012b4ed282SShri Abhyankar     }
8022b4ed282SShri Abhyankar     */
8032b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
8042b4ed282SShri Abhyankar          Y <- X - lambda*Y
8052b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
8062b4ed282SShri Abhyankar     */
8072b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
8082b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
8092b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
8102b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
8112b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
8122b4ed282SShri Abhyankar     if (snes->domainerror) {
8132b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
8149ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
8152b4ed282SShri Abhyankar       PetscFunctionReturn(0);
8162b4ed282SShri Abhyankar     }
8172b4ed282SShri Abhyankar     if (!lssucceed) {
8182b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
819ace3abfcSBarry Smith 	PetscBool ismin;
8202b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8212b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8222b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8232b4ed282SShri Abhyankar         break;
8242b4ed282SShri Abhyankar       }
8252b4ed282SShri Abhyankar     }
8262b4ed282SShri Abhyankar     /* Update function and solution vectors */
8272b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8282b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8292b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8302b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8312b4ed282SShri Abhyankar     /* Monitor convergence */
8322b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8332b4ed282SShri Abhyankar     snes->iter = i+1;
8342b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8352b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8362b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8377a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8382b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8392b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8402b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8412b4ed282SShri Abhyankar     if (snes->reason) break;
8422b4ed282SShri Abhyankar   }
8432b4ed282SShri Abhyankar   if (i == maxits) {
8442b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8452b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8462b4ed282SShri Abhyankar   }
8479ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
8482b4ed282SShri Abhyankar   PetscFunctionReturn(0);
8492b4ed282SShri Abhyankar }
85069c03620SShri Abhyankar 
85169c03620SShri Abhyankar #undef __FUNCT__
852693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
853693ddf92SShri Abhyankar /*
854693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
855693ddf92SShri Abhyankar 
856693ddf92SShri Abhyankar    Input parameter
857693ddf92SShri Abhyankar .  snes - the SNES context
858693ddf92SShri Abhyankar .  X    - the snes solution vector
859693ddf92SShri Abhyankar .  F    - the nonlinear function vector
860693ddf92SShri Abhyankar 
861693ddf92SShri Abhyankar    Output parameter
862693ddf92SShri Abhyankar .  ISact - active set index set
863693ddf92SShri Abhyankar  */
864693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
865d950fb63SShri Abhyankar {
866d950fb63SShri Abhyankar   PetscErrorCode   ierr;
867693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
868693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
869693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
870693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
871d950fb63SShri Abhyankar 
872d950fb63SShri Abhyankar   PetscFunctionBegin;
873d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
874d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
875fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
876fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
877fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
878fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
879693ddf92SShri Abhyankar   /* Compute active set size */
880d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
88110f5ae6bSBarry 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++;
882d950fb63SShri Abhyankar   }
883693ddf92SShri Abhyankar 
884d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
885d950fb63SShri Abhyankar 
886693ddf92SShri Abhyankar   /* Set active set indices */
887d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
88810f5ae6bSBarry 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;
889d950fb63SShri Abhyankar   }
890d950fb63SShri Abhyankar 
891693ddf92SShri Abhyankar    /* Create active set IS */
89262298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
893d950fb63SShri Abhyankar 
894fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
895fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
896fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
897fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
898d950fb63SShri Abhyankar   PetscFunctionReturn(0);
899d950fb63SShri Abhyankar }
900d950fb63SShri Abhyankar 
901693ddf92SShri Abhyankar #undef __FUNCT__
902693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
903693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
904693ddf92SShri Abhyankar {
905693ddf92SShri Abhyankar   PetscErrorCode     ierr;
906693ddf92SShri Abhyankar 
907693ddf92SShri Abhyankar   PetscFunctionBegin;
908693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
909693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
910693ddf92SShri Abhyankar   PetscFunctionReturn(0);
911693ddf92SShri Abhyankar }
912693ddf92SShri Abhyankar 
913dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
914dbd914b8SShri Abhyankar #undef __FUNCT__
915fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
916fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
917dbd914b8SShri Abhyankar {
918dbd914b8SShri Abhyankar   PetscErrorCode ierr;
919dbd914b8SShri Abhyankar   Vec            v;
920dbd914b8SShri Abhyankar 
921dbd914b8SShri Abhyankar   PetscFunctionBegin;
922dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
923dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
924dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
925dbd914b8SShri Abhyankar   *newv = v;
926dbd914b8SShri Abhyankar 
927dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
928dbd914b8SShri Abhyankar }
929dbd914b8SShri Abhyankar 
930732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
931732bb160SShri Abhyankar #undef __FUNCT__
932732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
933732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
934732bb160SShri Abhyankar {
935732bb160SShri Abhyankar   PetscErrorCode         ierr;
936d0af7cd3SBarry Smith   KSP                    snesksp;
937dbd914b8SShri Abhyankar 
938732bb160SShri Abhyankar   PetscFunctionBegin;
939732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
940d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
941c2efdce3SBarry Smith 
942c2efdce3SBarry Smith   /*
943d0af7cd3SBarry Smith   KSP                    kspnew;
944d0af7cd3SBarry Smith   PC                     pcnew;
945d0af7cd3SBarry Smith   const MatSolverPackage stype;
946d0af7cd3SBarry Smith 
947c2efdce3SBarry Smith 
948732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
949732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
950732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
951732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
952732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
953732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
954732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
955732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
956732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
957732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
958732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
9596bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
960732bb160SShri Abhyankar   snes->ksp = kspnew;
961732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
962d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
963732bb160SShri Abhyankar   PetscFunctionReturn(0);
964732bb160SShri Abhyankar }
96569c03620SShri Abhyankar 
96669c03620SShri Abhyankar 
967fe835674SShri Abhyankar #undef __FUNCT__
968fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
96910f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
970fe835674SShri Abhyankar {
971fe835674SShri Abhyankar   PetscErrorCode    ierr;
972fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
973fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
974fe835674SShri Abhyankar   PetscInt          i,n;
975fe835674SShri Abhyankar   PetscReal         rnorm;
976fe835674SShri Abhyankar 
977fe835674SShri Abhyankar   PetscFunctionBegin;
978fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
979fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
980fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
981fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
982fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
983fe835674SShri Abhyankar   rnorm = 0.0;
984fe835674SShri Abhyankar   for (i=0; i<n; i++) {
98510f5ae6bSBarry 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]);
986fe835674SShri Abhyankar   }
987fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
988fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
989fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
990fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
991d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
992fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
993fe835674SShri Abhyankar   PetscFunctionReturn(0);
994fe835674SShri Abhyankar }
995fe835674SShri Abhyankar 
996fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
997c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
998c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
999d950fb63SShri Abhyankar #undef __FUNCT__
1000d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
1001d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
1002d950fb63SShri Abhyankar {
1003d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
1004d950fb63SShri Abhyankar   PetscErrorCode    ierr;
1005abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
1006d950fb63SShri Abhyankar   PetscBool         lssucceed;
1007d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
1008fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
1009d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
1010d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
1011d950fb63SShri Abhyankar 
1012d950fb63SShri Abhyankar   PetscFunctionBegin;
1013d950fb63SShri Abhyankar   snes->numFailures            = 0;
1014d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
1015d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
1016d950fb63SShri Abhyankar 
1017d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
1018d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
1019d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1020d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1021d950fb63SShri Abhyankar   G		= snes->work[1];
1022d950fb63SShri Abhyankar   W		= snes->work[2];
1023d950fb63SShri Abhyankar 
1024d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1025d950fb63SShri Abhyankar   snes->iter = 0;
1026d950fb63SShri Abhyankar   snes->norm = 0.0;
1027d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1028d950fb63SShri Abhyankar 
10297fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1030fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1031d950fb63SShri Abhyankar   if (snes->domainerror) {
1032d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1033d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1034d950fb63SShri Abhyankar   }
1035fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1036d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1037d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
103862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1039d950fb63SShri Abhyankar 
1040d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1041fe835674SShri Abhyankar   snes->norm = fnorm;
1042d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1043fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10447a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1045d950fb63SShri Abhyankar 
1046d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1047fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1048d950fb63SShri Abhyankar   /* test convergence */
1049fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1050d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1051d950fb63SShri Abhyankar 
1052d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1053d950fb63SShri Abhyankar 
1054d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1055d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1056abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1057fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1058d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
105962298a1eSBarry Smith     IS         keptrows;
1060abcba341SShri Abhyankar     PetscBool  isequal;
1061d950fb63SShri Abhyankar 
1062d950fb63SShri Abhyankar     /* Call general purpose update function */
1063d950fb63SShri Abhyankar     if (snes->ops->update) {
1064d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1065d950fb63SShri Abhyankar     }
1066d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
106762298a1eSBarry Smith 
1068d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1069693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1070d950fb63SShri Abhyankar 
10714dcab191SBarry Smith     ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr);
10724dcab191SBarry Smith 
10734dcab191SBarry Smith 
1074abcba341SShri Abhyankar     /* Create inactive set submatrix */
107562298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1076b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
107762298a1eSBarry Smith     if (keptrows) {
107862298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
107962298a1eSBarry Smith       const PetscInt *krows,*inact;
108027d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
108162298a1eSBarry Smith 
10826bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
10836bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
108462298a1eSBarry Smith 
108562298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
108662298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
108762298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
108862298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
108962298a1eSBarry Smith       for (k=0; k<cnt; k++) {
109027d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
109162298a1eSBarry Smith       }
109262298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
109362298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
10946bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
10956bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
109662298a1eSBarry Smith 
109727d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
109827d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
109962298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
110062298a1eSBarry Smith     }
110162298a1eSBarry Smith 
1102d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1103d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1104d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1105d950fb63SShri Abhyankar 
1106d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1107fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1108fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1109fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1110d950fb63SShri Abhyankar 
1111d950fb63SShri Abhyankar     /* Create scatter contexts */
1112d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1113d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1114d950fb63SShri Abhyankar 
1115d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1116fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1117fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1118d950fb63SShri Abhyankar 
1119d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1120d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1121d950fb63SShri Abhyankar 
1122d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1123d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1124d950fb63SShri Abhyankar 
1125d950fb63SShri Abhyankar     /* Active set direction = 0 */
1126d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1127d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1128d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1129d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1130d950fb63SShri Abhyankar 
1131abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1132abcba341SShri Abhyankar     if (!isequal) {
1133732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1134d950fb63SShri Abhyankar     }
1135d950fb63SShri Abhyankar 
113613e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
113713e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
113813e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
113913e0d083SBarry Smith 
1140d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
114113e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
114213e0d083SBarry Smith     {
114313e0d083SBarry Smith       PC        pc;
114413e0d083SBarry Smith       PetscBool flg;
114513e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
114613e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
114713e0d083SBarry Smith       if (flg) {
114813e0d083SBarry Smith         KSP      *subksps;
114913e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
115013e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
115113e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
115213e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
115313e0d083SBarry Smith         if (flg) {
115413e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
115513e0d083SBarry Smith           const PetscInt *ii;
115613e0d083SBarry Smith 
115713e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
115813e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
115913e0d083SBarry Smith           for (j=0; j<n; j++) {
116013e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
116113e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
116213e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
116313e0d083SBarry Smith           }
116413e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
116513e0d083SBarry Smith 
116613e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
116713e0d083SBarry Smith         }
116813e0d083SBarry Smith       }
116913e0d083SBarry Smith     }
117013e0d083SBarry Smith 
1171fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1172d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1173d950fb63SShri Abhyankar     if (kspreason < 0) {
1174d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1175d950fb63SShri 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);
1176d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1177d950fb63SShri Abhyankar         break;
1178d950fb63SShri Abhyankar       }
1179d950fb63SShri Abhyankar      }
1180d950fb63SShri Abhyankar 
1181d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1182d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1183d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1184d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1185d950fb63SShri Abhyankar 
11866bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
11876bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
11886bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
11896bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
11906bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
11916bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1192abcba341SShri Abhyankar     if (!isequal) {
11936bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1194abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1195abcba341SShri Abhyankar     }
11966bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
11976bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1198d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
11996bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1200d950fb63SShri Abhyankar     }
1201d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1202d950fb63SShri Abhyankar     snes->linear_its += lits;
1203d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1204d950fb63SShri Abhyankar     /*
1205d950fb63SShri Abhyankar     if (vi->precheckstep) {
1206d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1207d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1208d950fb63SShri Abhyankar     }
1209d950fb63SShri Abhyankar 
1210d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1211d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1212d950fb63SShri Abhyankar     }
1213d950fb63SShri Abhyankar     */
1214d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1215d950fb63SShri Abhyankar          Y <- X - lambda*Y
1216d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1217d950fb63SShri Abhyankar     */
1218d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1219fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1220fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1221fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
12222b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
12232b4ed282SShri Abhyankar     if (snes->domainerror) {
12242b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
12252b4ed282SShri Abhyankar       PetscFunctionReturn(0);
12262b4ed282SShri Abhyankar     }
12272b4ed282SShri Abhyankar     if (!lssucceed) {
12282b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
12292b4ed282SShri Abhyankar 	PetscBool ismin;
12302b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
12312b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
12322b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
12332b4ed282SShri Abhyankar         break;
12342b4ed282SShri Abhyankar       }
12352b4ed282SShri Abhyankar     }
12362b4ed282SShri Abhyankar     /* Update function and solution vectors */
1237fe835674SShri Abhyankar     fnorm = gnorm;
1238fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
12392b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
12402b4ed282SShri Abhyankar     /* Monitor convergence */
12412b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
12422b4ed282SShri Abhyankar     snes->iter = i+1;
1243fe835674SShri Abhyankar     snes->norm = fnorm;
12442b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
12452b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
12467a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
12472b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
12482b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1249fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
12502b4ed282SShri Abhyankar     if (snes->reason) break;
12512b4ed282SShri Abhyankar   }
12522b4ed282SShri Abhyankar   if (i == maxits) {
12532b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
12542b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
12552b4ed282SShri Abhyankar   }
12562b4ed282SShri Abhyankar   PetscFunctionReturn(0);
12572b4ed282SShri Abhyankar }
12582b4ed282SShri Abhyankar 
12592f63a38cSShri Abhyankar #undef __FUNCT__
1260720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1261cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
12622f63a38cSShri Abhyankar {
12632f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
12642f63a38cSShri Abhyankar 
12652f63a38cSShri Abhyankar   PetscFunctionBegin;
12662f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
12672f63a38cSShri Abhyankar   vi->checkredundancy = func;
1268cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
12692f63a38cSShri Abhyankar   PetscFunctionReturn(0);
12702f63a38cSShri Abhyankar }
12712f63a38cSShri Abhyankar 
1272ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1273ff596062SShri Abhyankar #include <engine.h>
1274ff596062SShri Abhyankar #include <mex.h>
1275cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1276ff596062SShri Abhyankar 
1277ff596062SShri Abhyankar #undef __FUNCT__
1278ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1279ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1280ff596062SShri Abhyankar {
1281ff596062SShri Abhyankar   PetscErrorCode      ierr;
1282cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1283cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1284cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1285cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1286fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1287ff596062SShri Abhyankar 
1288ff596062SShri Abhyankar   PetscFunctionBegin;
1289ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1290ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1291ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1292ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1293ff596062SShri Abhyankar 
129409db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
129509db5ad8SShri Abhyankar    bet set by the Matlab function */
1296fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1297cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1298ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1299ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1300cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1301ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1302ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1303cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1304cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1305cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1306ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1307ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1308ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1309ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1310ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1311ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1312ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1313ff596062SShri Abhyankar   PetscFunctionReturn(0);
1314ff596062SShri Abhyankar }
1315ff596062SShri Abhyankar 
1316ff596062SShri Abhyankar #undef __FUNCT__
1317ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1318ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1319ff596062SShri Abhyankar {
1320ff596062SShri Abhyankar   PetscErrorCode      ierr;
1321cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1322ff596062SShri Abhyankar 
1323ff596062SShri Abhyankar   PetscFunctionBegin;
1324ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1325cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1326ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1327ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1328cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1329ff596062SShri Abhyankar   PetscFunctionReturn(0);
1330ff596062SShri Abhyankar }
1331ff596062SShri Abhyankar 
1332ff596062SShri Abhyankar #endif
1333ff596062SShri Abhyankar 
1334ff596062SShri Abhyankar 
13352f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
13362f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1337720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
133856a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
133956a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
13402f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
13412f63a38cSShri Abhyankar */
13422f63a38cSShri Abhyankar #undef __FUNCT__
1343b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1344b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
13452f63a38cSShri Abhyankar {
13462f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
13472f63a38cSShri Abhyankar   PetscErrorCode    ierr;
13482f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
13492f63a38cSShri Abhyankar   PetscBool         lssucceed;
13502f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
13512f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
13522f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
13532f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
13542f63a38cSShri Abhyankar 
13552f63a38cSShri Abhyankar   PetscFunctionBegin;
13562f63a38cSShri Abhyankar   snes->numFailures            = 0;
13572f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
13582f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
13592f63a38cSShri Abhyankar 
13602f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
13612f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
13622f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
13632f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
13642f63a38cSShri Abhyankar   G		= snes->work[1];
13652f63a38cSShri Abhyankar   W		= snes->work[2];
13662f63a38cSShri Abhyankar 
13672f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13682f63a38cSShri Abhyankar   snes->iter = 0;
13692f63a38cSShri Abhyankar   snes->norm = 0.0;
13702f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13712f63a38cSShri Abhyankar 
13722f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
13732f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
13742f63a38cSShri Abhyankar   if (snes->domainerror) {
13752f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13762f63a38cSShri Abhyankar     PetscFunctionReturn(0);
13772f63a38cSShri Abhyankar   }
13782f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
13792f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
13802f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
138162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
13822f63a38cSShri Abhyankar 
13832f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13842f63a38cSShri Abhyankar   snes->norm = fnorm;
13852f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13862f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
13877a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
13882f63a38cSShri Abhyankar 
13892f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
13902f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
13912f63a38cSShri Abhyankar   /* test convergence */
13922f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13932f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
13942f63a38cSShri Abhyankar 
13952f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
13962f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1397cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
139856a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
139956a221efSShri Abhyankar     Vec            F_aug,Y_aug;
140056a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
140156a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
140256a221efSShri Abhyankar     PetscInt       k;
140363ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
140456a221efSShri Abhyankar     PetscScalar    *f,*f2;
14052f63a38cSShri Abhyankar     PetscBool      isequal;
140656a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
14072f63a38cSShri Abhyankar 
14082f63a38cSShri Abhyankar     /* Call general purpose update function */
14092f63a38cSShri Abhyankar     if (snes->ops->update) {
14102f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
14112f63a38cSShri Abhyankar     }
14122f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
14132f63a38cSShri Abhyankar 
14142f63a38cSShri Abhyankar     /* Create active and inactive index sets */
14152f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
14162f63a38cSShri Abhyankar 
141756a221efSShri Abhyankar     /* Get local active set size */
14182f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
141956a221efSShri Abhyankar     if (nis_act) {
1420e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1421e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
142256a221efSShri Abhyankar       if(vi->checkredundancy) {
1423cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
142456a221efSShri Abhyankar       }
14252f63a38cSShri Abhyankar 
142656a221efSShri Abhyankar       if(!IS_redact) {
142756a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
142856a221efSShri Abhyankar            there were no redundant active set variables */
142956a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
143056a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
143156a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
143256a221efSShri Abhyankar 	nkept = nis_act;
143356a221efSShri Abhyankar       } else {
143456a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
143556a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
14362f63a38cSShri Abhyankar 
143756a221efSShri Abhyankar 	/* Create reduced active set list */
143856a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
143956a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1440cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
144156a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
144256a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
144356a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
144456a221efSShri Abhyankar 	}
144556a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
144656a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1447cb5fe31bSShri Abhyankar 
1448cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
144956a221efSShri Abhyankar       }
14502f63a38cSShri Abhyankar 
145156a221efSShri Abhyankar       /* Create augmented F and Y */
145256a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
145356a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
145456a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
145556a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
14562f63a38cSShri Abhyankar 
145756a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
145856a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
145956a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
146056a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
146156a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
146256a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
14632f63a38cSShri Abhyankar 
146456a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
146556a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
146656a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
146756a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
14682f63a38cSShri Abhyankar 
146956a221efSShri Abhyankar 
14709521db3cSSatish Balay       { /* local vars */
1471493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
147256a221efSShri Abhyankar       PetscInt          ncols;
147356a221efSShri Abhyankar       const PetscInt    *cols;
147456a221efSShri Abhyankar       const PetscScalar *vals;
14752969f145SShri Abhyankar       PetscScalar        value[2];
14762969f145SShri Abhyankar       PetscInt           row,col[2];
1477493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
14782969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1479493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1480493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1481493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1482493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1483493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1484493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1485493a4f3dSShri Abhyankar       }
1486493a4f3dSShri Abhyankar 
1487493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1488493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
14892969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1490493a4f3dSShri Abhyankar       }
1491493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1492493a4f3dSShri Abhyankar 
1493493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
149456a221efSShri Abhyankar 
149556a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
149656a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
149756a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
149856a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
149956a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
150056a221efSShri Abhyankar       }
150156a221efSShri Abhyankar       /* Add the augmented part */
150256a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
15032969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
15042969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
15052969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
15062969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
150756a221efSShri Abhyankar       }
150856a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
150956a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
151056a221efSShri Abhyankar       /* Only considering prejac = jac for now */
151156a221efSShri Abhyankar       Jpre_aug = J_aug;
15129521db3cSSatish Balay       } /* local vars*/
1513e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1514e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
151556a221efSShri Abhyankar     } else {
151656a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
151756a221efSShri Abhyankar     }
15182f63a38cSShri Abhyankar 
15192f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
15202f63a38cSShri Abhyankar     if (!isequal) {
152156a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
15222f63a38cSShri Abhyankar     }
152356a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
15242f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
152556a221efSShri Abhyankar     /*  {
15262f63a38cSShri Abhyankar       PC        pc;
15272f63a38cSShri Abhyankar       PetscBool flg;
15282f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
15292f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15302f63a38cSShri Abhyankar       if (flg) {
15312f63a38cSShri Abhyankar         KSP      *subksps;
15322f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
15332f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
15342f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
15352f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
15362f63a38cSShri Abhyankar         if (flg) {
15372f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
15382f63a38cSShri Abhyankar           const PetscInt *ii;
15392f63a38cSShri Abhyankar 
15402f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
15412f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
15422f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
15432f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
15442f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
15452f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
15462f63a38cSShri Abhyankar           }
15472f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
15482f63a38cSShri Abhyankar 
15492f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
15502f63a38cSShri Abhyankar         }
15512f63a38cSShri Abhyankar       }
15522f63a38cSShri Abhyankar     }
155356a221efSShri Abhyankar     */
155456a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
15552f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
15562f63a38cSShri Abhyankar     if (kspreason < 0) {
15572f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
15582f63a38cSShri 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);
15592f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
15602f63a38cSShri Abhyankar         break;
15612f63a38cSShri Abhyankar       }
15622f63a38cSShri Abhyankar     }
15632f63a38cSShri Abhyankar 
156456a221efSShri Abhyankar     if(nis_act) {
156556a221efSShri Abhyankar       PetscScalar *y1,*y2;
156656a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
156756a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
156856a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
156956a221efSShri Abhyankar       j1 = 0;
157056a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
157156a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
157256a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
157356a221efSShri Abhyankar       }
157456a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
157556a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
15762f63a38cSShri Abhyankar 
15776bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
15786bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
15796bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
158056a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
158156a221efSShri Abhyankar     }
158256a221efSShri Abhyankar 
15832f63a38cSShri Abhyankar     if (!isequal) {
15846bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
15852f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
15862f63a38cSShri Abhyankar     }
15876bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
158856a221efSShri Abhyankar 
15892f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
15902f63a38cSShri Abhyankar     snes->linear_its += lits;
15912f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
15922f63a38cSShri Abhyankar     /*
15932f63a38cSShri Abhyankar     if (vi->precheckstep) {
15942f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
15952f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
15962f63a38cSShri Abhyankar     }
15972f63a38cSShri Abhyankar 
15982f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
15992f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
16002f63a38cSShri Abhyankar     }
16012f63a38cSShri Abhyankar     */
16022f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
16032f63a38cSShri Abhyankar          Y <- X - lambda*Y
16042f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
16052f63a38cSShri Abhyankar     */
16062f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
16072f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
16082f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
16092f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
16102f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
16112f63a38cSShri Abhyankar     if (snes->domainerror) {
16122f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
16132f63a38cSShri Abhyankar       PetscFunctionReturn(0);
16142f63a38cSShri Abhyankar     }
16152f63a38cSShri Abhyankar     if (!lssucceed) {
16162f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
16172f63a38cSShri Abhyankar 	PetscBool ismin;
16182f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
16192f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
16202f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
16212f63a38cSShri Abhyankar         break;
16222f63a38cSShri Abhyankar       }
16232f63a38cSShri Abhyankar     }
16242f63a38cSShri Abhyankar     /* Update function and solution vectors */
16252f63a38cSShri Abhyankar     fnorm = gnorm;
16262f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
16272f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
16282f63a38cSShri Abhyankar     /* Monitor convergence */
16292f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
16302f63a38cSShri Abhyankar     snes->iter = i+1;
16312f63a38cSShri Abhyankar     snes->norm = fnorm;
16322f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
16332f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
16347a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16352f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
16362f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
16372f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
16382f63a38cSShri Abhyankar     if (snes->reason) break;
16392f63a38cSShri Abhyankar   }
16402f63a38cSShri Abhyankar   if (i == maxits) {
16412f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
16422f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
16432f63a38cSShri Abhyankar   }
16442f63a38cSShri Abhyankar   PetscFunctionReturn(0);
16452f63a38cSShri Abhyankar }
16462f63a38cSShri Abhyankar 
16472b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
16482b4ed282SShri Abhyankar /*
16492b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
16502b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
16512b4ed282SShri Abhyankar 
16522b4ed282SShri Abhyankar    Input Parameter:
16532b4ed282SShri Abhyankar .  snes - the SNES context
16542b4ed282SShri Abhyankar .  x - the solution vector
16552b4ed282SShri Abhyankar 
16562b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
16572b4ed282SShri Abhyankar 
16582b4ed282SShri Abhyankar    Notes:
16592b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
16602b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
16612b4ed282SShri Abhyankar    the call to SNESSolve().
16622b4ed282SShri Abhyankar  */
16632b4ed282SShri Abhyankar #undef __FUNCT__
16642b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
16652b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
16662b4ed282SShri Abhyankar {
16672b4ed282SShri Abhyankar   PetscErrorCode ierr;
16682b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
16692b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
16702b4ed282SShri Abhyankar 
16712b4ed282SShri Abhyankar   PetscFunctionBegin;
167258c9b817SLisandro Dalcin 
167358c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
16742b4ed282SShri Abhyankar 
16752b4ed282SShri Abhyankar   /* If the lower and upper bound on variables are not set, set it to
16762b4ed282SShri Abhyankar      -Inf and Inf */
16772b4ed282SShri Abhyankar   if (!vi->xl && !vi->xu) {
16782b4ed282SShri Abhyankar     vi->usersetxbounds = PETSC_FALSE;
16792b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr);
168001f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
16812b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr);
168201f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
16832b4ed282SShri Abhyankar   } else {
16842b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
16852b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
16862b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
16872b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
16882b4ed282SShri 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]))
16892b4ed282SShri 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.");
16902b4ed282SShri Abhyankar   }
16912f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1692abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1693abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1694abcba341SShri Abhyankar     PetscInt *indices;
1695abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1696abcba341SShri Abhyankar 
1697abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1698abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1699abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1700abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1701abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1702abcba341SShri Abhyankar   }
17032b4ed282SShri Abhyankar 
17042f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1705fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1706fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr);
1707fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr);
1708fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr);
1709fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1710fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr);
1711fe835674SShri Abhyankar   }
17122b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17132b4ed282SShri Abhyankar }
17142b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17152b4ed282SShri Abhyankar /*
17162b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
17172b4ed282SShri Abhyankar    with SNESCreate_VI().
17182b4ed282SShri Abhyankar 
17192b4ed282SShri Abhyankar    Input Parameter:
17202b4ed282SShri Abhyankar .  snes - the SNES context
17212b4ed282SShri Abhyankar 
17222b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
17232b4ed282SShri Abhyankar  */
17242b4ed282SShri Abhyankar #undef __FUNCT__
17252b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
17262b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
17272b4ed282SShri Abhyankar {
17282b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17292b4ed282SShri Abhyankar   PetscErrorCode ierr;
17302b4ed282SShri Abhyankar 
17312b4ed282SShri Abhyankar   PetscFunctionBegin;
17322f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
17336bf464f9SBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);
1734abcba341SShri Abhyankar   }
17352b4ed282SShri Abhyankar 
17362f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
17372b4ed282SShri Abhyankar     /* clear vectors */
17386bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
17396bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi); CHKERRQ(ierr);
17406bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da); CHKERRQ(ierr);
17416bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db); CHKERRQ(ierr);
17426bf464f9SBarry Smith     ierr = VecDestroy(&vi->z); CHKERRQ(ierr);
17436bf464f9SBarry Smith     ierr = VecDestroy(&vi->t); CHKERRQ(ierr);
17447fe79bc4SShri Abhyankar   }
17457fe79bc4SShri Abhyankar 
17462b4ed282SShri Abhyankar   if (!vi->usersetxbounds) {
17476bf464f9SBarry Smith     ierr = VecDestroy(&vi->xl); CHKERRQ(ierr);
17486bf464f9SBarry Smith     ierr = VecDestroy(&vi->xu); CHKERRQ(ierr);
17492b4ed282SShri Abhyankar   }
17507fe79bc4SShri Abhyankar 
17516bf464f9SBarry Smith   ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
17522b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
17532b4ed282SShri Abhyankar 
17542b4ed282SShri Abhyankar   /* clear composed functions */
17552b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1756c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
17572b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17582b4ed282SShri Abhyankar }
17597fe79bc4SShri Abhyankar 
17602b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17612b4ed282SShri Abhyankar #undef __FUNCT__
17622b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
17632b4ed282SShri Abhyankar 
17642b4ed282SShri Abhyankar /*
17657fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
17667fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
17672b4ed282SShri Abhyankar 
17682b4ed282SShri Abhyankar */
1769ace3abfcSBarry 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)
17702b4ed282SShri Abhyankar {
17712b4ed282SShri Abhyankar   PetscErrorCode ierr;
17722b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1773ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
17742b4ed282SShri Abhyankar 
17752b4ed282SShri Abhyankar   PetscFunctionBegin;
17762b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
17772b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
17782b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
17792b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1780c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1781c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1782c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1783c1a5e521SShri Abhyankar   }
1784c1a5e521SShri Abhyankar   if (changed_y) {
1785c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
17867fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1787c1a5e521SShri Abhyankar   }
1788c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1789c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1790c1a5e521SShri Abhyankar   if (!snes->domainerror) {
17912f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
17927fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
17937fe79bc4SShri Abhyankar     } else {
1794c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
17957fe79bc4SShri Abhyankar     }
179662cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1797c1a5e521SShri Abhyankar   }
1798c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1799c1a5e521SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1800c1a5e521SShri Abhyankar   }
1801c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1802c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1803c1a5e521SShri Abhyankar }
1804c1a5e521SShri Abhyankar 
1805c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1806c1a5e521SShri Abhyankar #undef __FUNCT__
18072b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
18082b4ed282SShri Abhyankar 
18092b4ed282SShri Abhyankar /*
18102b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
18112b4ed282SShri Abhyankar */
1812ace3abfcSBarry 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)
18132b4ed282SShri Abhyankar {
18142b4ed282SShri Abhyankar   PetscErrorCode ierr;
18152b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1816ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
18172b4ed282SShri Abhyankar 
18182b4ed282SShri Abhyankar   PetscFunctionBegin;
18192b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18202b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18212b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
18227fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18232b4ed282SShri Abhyankar   if (vi->postcheckstep) {
18242b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
18252b4ed282SShri Abhyankar   }
18262b4ed282SShri Abhyankar   if (changed_y) {
18272b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18287fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18292b4ed282SShri Abhyankar   }
18302b4ed282SShri Abhyankar 
18312b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
18322b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
18332b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18342b4ed282SShri Abhyankar   }
18352b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18362b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18372b4ed282SShri Abhyankar }
18387fe79bc4SShri Abhyankar 
18392b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18402b4ed282SShri Abhyankar #undef __FUNCT__
18412b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
18422b4ed282SShri Abhyankar /*
18437fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
18442b4ed282SShri Abhyankar */
1845ace3abfcSBarry 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)
18462b4ed282SShri Abhyankar {
1847fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1848fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1849fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1850fe835674SShri Abhyankar   PetscScalar    cinitslope;
1851fe835674SShri Abhyankar #endif
1852fe835674SShri Abhyankar   PetscErrorCode ierr;
1853fe835674SShri Abhyankar   PetscInt       count;
1854fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1855fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1856fe835674SShri Abhyankar   MPI_Comm       comm;
1857fe835674SShri Abhyankar 
1858fe835674SShri Abhyankar   PetscFunctionBegin;
1859fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1860fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1861fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1862fe835674SShri Abhyankar 
1863fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1864fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1865fe835674SShri Abhyankar     if (vi->lsmonitor) {
1866fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1867fe835674SShri Abhyankar     }
1868fe835674SShri Abhyankar     *gnorm = fnorm;
1869fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1870fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1871fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1872fe835674SShri Abhyankar     goto theend1;
1873fe835674SShri Abhyankar   }
1874fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1875fe835674SShri Abhyankar     if (vi->lsmonitor) {
1876fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1877fe835674SShri Abhyankar     }
1878fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1879fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1880fe835674SShri Abhyankar   }
1881fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1882fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1883fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1884fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1885fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1886fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1887fe835674SShri Abhyankar #else
1888fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1889fe835674SShri Abhyankar #endif
1890fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1891fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1892fe835674SShri Abhyankar 
1893fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
1894fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1895fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1896fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
1897fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1898fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1899fe835674SShri Abhyankar     goto theend1;
1900fe835674SShri Abhyankar   }
1901fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19022f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1903fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19047fe79bc4SShri Abhyankar   } else {
19057fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19067fe79bc4SShri Abhyankar   }
1907fe835674SShri Abhyankar   if (snes->domainerror) {
1908fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1909fe835674SShri Abhyankar     PetscFunctionReturn(0);
1910fe835674SShri Abhyankar   }
191162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1912fe835674SShri Abhyankar   ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1913fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
1914fe835674SShri Abhyankar     if (vi->lsmonitor) {
1915fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1916fe835674SShri Abhyankar     }
1917fe835674SShri Abhyankar     goto theend1;
1918fe835674SShri Abhyankar   }
1919fe835674SShri Abhyankar 
1920fe835674SShri Abhyankar   /* Fit points with quadratic */
1921fe835674SShri Abhyankar   lambda     = 1.0;
1922fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
1923fe835674SShri Abhyankar   lambdaprev = lambda;
1924fe835674SShri Abhyankar   gnormprev  = *gnorm;
1925fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1926fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
1927fe835674SShri Abhyankar   else                         lambda = lambdatemp;
1928fe835674SShri Abhyankar 
1929fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1930fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1931fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1932fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
1933fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1934fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1935fe835674SShri Abhyankar     goto theend1;
1936fe835674SShri Abhyankar   }
1937fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19382f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1939fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19407fe79bc4SShri Abhyankar   } else {
19417fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19427fe79bc4SShri Abhyankar   }
1943fe835674SShri Abhyankar   if (snes->domainerror) {
1944fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1945fe835674SShri Abhyankar     PetscFunctionReturn(0);
1946fe835674SShri Abhyankar   }
194762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1948fe835674SShri Abhyankar   if (vi->lsmonitor) {
1949fe835674SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
1950fe835674SShri Abhyankar   }
1951fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
1952fe835674SShri Abhyankar     if (vi->lsmonitor) {
1953fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
1954fe835674SShri Abhyankar     }
1955fe835674SShri Abhyankar     goto theend1;
1956fe835674SShri Abhyankar   }
1957fe835674SShri Abhyankar 
1958fe835674SShri Abhyankar   /* Fit points with cubic */
1959fe835674SShri Abhyankar   count = 1;
1960fe835674SShri Abhyankar   while (PETSC_TRUE) {
1961fe835674SShri Abhyankar     if (lambda <= minlambda) {
1962fe835674SShri Abhyankar       if (vi->lsmonitor) {
1963fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
1964fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, minlambda=%18.16e, lambda=%18.16e, initial slope=%18.16e\n",fnorm,*gnorm,*ynorm,minlambda,lambda,initslope);CHKERRQ(ierr);
1965fe835674SShri Abhyankar       }
1966fe835674SShri Abhyankar       *flag = PETSC_FALSE;
1967fe835674SShri Abhyankar       break;
1968fe835674SShri Abhyankar     }
1969fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
1970fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
1971fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1972fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1973fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
1974fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
1975fe835674SShri Abhyankar     if (a == 0.0) {
1976fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
1977fe835674SShri Abhyankar     } else {
1978fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
1979fe835674SShri Abhyankar     }
1980fe835674SShri Abhyankar     lambdaprev = lambda;
1981fe835674SShri Abhyankar     gnormprev  = *gnorm;
1982fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1983fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
1984fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
1985fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1986fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1987fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
1988fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
1989fe835674SShri 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);
1990fe835674SShri Abhyankar       *flag = PETSC_FALSE;
1991fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1992fe835674SShri Abhyankar       break;
1993fe835674SShri Abhyankar     }
1994fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19952f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
1996fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19977fe79bc4SShri Abhyankar     } else {
19987fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19997fe79bc4SShri Abhyankar     }
2000fe835674SShri Abhyankar     if (snes->domainerror) {
2001fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2002fe835674SShri Abhyankar       PetscFunctionReturn(0);
2003fe835674SShri Abhyankar     }
200462cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2005fe835674SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */
2006fe835674SShri Abhyankar       if (vi->lsmonitor) {
2007fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2008fe835674SShri Abhyankar       }
2009fe835674SShri Abhyankar       break;
2010fe835674SShri Abhyankar     } else {
2011fe835674SShri Abhyankar       if (vi->lsmonitor) {
2012fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
2013fe835674SShri Abhyankar       }
2014fe835674SShri Abhyankar     }
2015fe835674SShri Abhyankar     count++;
2016fe835674SShri Abhyankar   }
2017fe835674SShri Abhyankar   theend1:
2018fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
2019fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2020fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2021fe835674SShri Abhyankar     if (changed_y) {
2022fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2023fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2024fe835674SShri Abhyankar     }
2025fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2026fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20272f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2028fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20297fe79bc4SShri Abhyankar       } else {
20307fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20317fe79bc4SShri Abhyankar       }
2032fe835674SShri Abhyankar       if (snes->domainerror) {
2033fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2034fe835674SShri Abhyankar         PetscFunctionReturn(0);
2035fe835674SShri Abhyankar       }
203662cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2037fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2038fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2039fe835674SShri Abhyankar     }
2040fe835674SShri Abhyankar   }
2041fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2042fe835674SShri Abhyankar   PetscFunctionReturn(0);
2043fe835674SShri Abhyankar }
2044fe835674SShri Abhyankar 
20452b4ed282SShri Abhyankar #undef __FUNCT__
20462b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
20472b4ed282SShri Abhyankar /*
20487fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
20492b4ed282SShri Abhyankar */
2050ace3abfcSBarry 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)
20512b4ed282SShri Abhyankar {
20522b4ed282SShri Abhyankar   /*
20532b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
20542b4ed282SShri Abhyankar      minimization problem:
20552b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
20562b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
20572b4ed282SShri Abhyankar    */
20582b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
20592b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
20602b4ed282SShri Abhyankar   PetscScalar    cinitslope;
20612b4ed282SShri Abhyankar #endif
20622b4ed282SShri Abhyankar   PetscErrorCode ierr;
20632b4ed282SShri Abhyankar   PetscInt       count;
20642b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2065ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
20662b4ed282SShri Abhyankar 
20672b4ed282SShri Abhyankar   PetscFunctionBegin;
20682b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
20692b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
20702b4ed282SShri Abhyankar 
20712b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
20722b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2073c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2074c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
20752b4ed282SShri Abhyankar     }
20762b4ed282SShri Abhyankar     *gnorm = fnorm;
20772b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
20782b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
20792b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
20802b4ed282SShri Abhyankar     goto theend2;
20812b4ed282SShri Abhyankar   }
20822b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
20832b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
20842b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
20852b4ed282SShri Abhyankar   }
20862b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
20872b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
20887fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
20892b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
20907fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
20912b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
20922b4ed282SShri Abhyankar #else
20937fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
20942b4ed282SShri Abhyankar #endif
20952b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
20962b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
20972b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
20982b4ed282SShri Abhyankar 
20992b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21007fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21012b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
21022b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
21032b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
21042b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21052b4ed282SShri Abhyankar     goto theend2;
21062b4ed282SShri Abhyankar   }
21072b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21082f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
21097fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21107fe79bc4SShri Abhyankar   } else {
21117fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21127fe79bc4SShri Abhyankar   }
21132b4ed282SShri Abhyankar   if (snes->domainerror) {
21142b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21152b4ed282SShri Abhyankar     PetscFunctionReturn(0);
21162b4ed282SShri Abhyankar   }
211762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21182b4ed282SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
2119c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2120c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
21212b4ed282SShri Abhyankar     }
21222b4ed282SShri Abhyankar     goto theend2;
21232b4ed282SShri Abhyankar   }
21242b4ed282SShri Abhyankar 
21252b4ed282SShri Abhyankar   /* Fit points with quadratic */
21262b4ed282SShri Abhyankar   lambda = 1.0;
21272b4ed282SShri Abhyankar   count = 1;
21282b4ed282SShri Abhyankar   while (PETSC_TRUE) {
21292b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2130c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2131c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2132c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: fnorm=%G, gnorm=%G, ynorm=%G, lambda=%G, initial slope=%G\n",fnorm,*gnorm,*ynorm,lambda,initslope);CHKERRQ(ierr);
21332b4ed282SShri Abhyankar       }
21342b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
21352b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21362b4ed282SShri Abhyankar       break;
21372b4ed282SShri Abhyankar     }
21382b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
21392b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
21402b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
21412b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
21422b4ed282SShri Abhyankar 
21432b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
21447fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21452b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
21462b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
21472b4ed282SShri 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);
21482b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21492b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21502b4ed282SShri Abhyankar       break;
21512b4ed282SShri Abhyankar     }
21522b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21532b4ed282SShri Abhyankar     if (snes->domainerror) {
21542b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21552b4ed282SShri Abhyankar       PetscFunctionReturn(0);
21562b4ed282SShri Abhyankar     }
21572f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
21587fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21597fe79bc4SShri Abhyankar     } else {
21602b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21617fe79bc4SShri Abhyankar     }
216262cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21632b4ed282SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2164c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2165c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
21662b4ed282SShri Abhyankar       }
21672b4ed282SShri Abhyankar       break;
21682b4ed282SShri Abhyankar     }
21692b4ed282SShri Abhyankar     count++;
21702b4ed282SShri Abhyankar   }
21712b4ed282SShri Abhyankar   theend2:
21722b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
21732b4ed282SShri Abhyankar   if (vi->postcheckstep) {
21742b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
21752b4ed282SShri Abhyankar     if (changed_y) {
21762b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21777fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21782b4ed282SShri Abhyankar     }
21792b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
21802b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
21812b4ed282SShri Abhyankar       if (snes->domainerror) {
21822b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21832b4ed282SShri Abhyankar         PetscFunctionReturn(0);
21842b4ed282SShri Abhyankar       }
21852f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
21867fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21877fe79bc4SShri Abhyankar       } else {
21887fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21897fe79bc4SShri Abhyankar       }
21907fe79bc4SShri Abhyankar 
21912b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
21922b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
219362cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21942b4ed282SShri Abhyankar     }
21952b4ed282SShri Abhyankar   }
21962b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21972b4ed282SShri Abhyankar   PetscFunctionReturn(0);
21982b4ed282SShri Abhyankar }
21992b4ed282SShri Abhyankar 
2200ace3abfcSBarry 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*/
22012b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22022b4ed282SShri Abhyankar EXTERN_C_BEGIN
22032b4ed282SShri Abhyankar #undef __FUNCT__
22042b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
22057087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
22062b4ed282SShri Abhyankar {
22072b4ed282SShri Abhyankar   PetscFunctionBegin;
22082b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
22092b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
22102b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22112b4ed282SShri Abhyankar }
22122b4ed282SShri Abhyankar EXTERN_C_END
22132b4ed282SShri Abhyankar 
22142b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22152b4ed282SShri Abhyankar EXTERN_C_BEGIN
22162b4ed282SShri Abhyankar #undef __FUNCT__
22172b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
22187087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
22192b4ed282SShri Abhyankar {
22202b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
22212b4ed282SShri Abhyankar   PetscErrorCode ierr;
22222b4ed282SShri Abhyankar 
22232b4ed282SShri Abhyankar   PetscFunctionBegin;
2224c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2225c92abb8aSShri Abhyankar     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr);
2226c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
22276bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
22282b4ed282SShri Abhyankar   }
22292b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22302b4ed282SShri Abhyankar }
22312b4ed282SShri Abhyankar EXTERN_C_END
22322b4ed282SShri Abhyankar 
22332b4ed282SShri Abhyankar /*
22342b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
22352b4ed282SShri Abhyankar 
22362b4ed282SShri Abhyankar    Input Parameters:
22372b4ed282SShri Abhyankar .  SNES - the SNES context
22382b4ed282SShri Abhyankar .  viewer - visualization context
22392b4ed282SShri Abhyankar 
22402b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
22412b4ed282SShri Abhyankar */
22422b4ed282SShri Abhyankar #undef __FUNCT__
22432b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
22442b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
22452b4ed282SShri Abhyankar {
22462b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
224778c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
22482b4ed282SShri Abhyankar   PetscErrorCode ierr;
2249ace3abfcSBarry Smith   PetscBool     iascii;
22502b4ed282SShri Abhyankar 
22512b4ed282SShri Abhyankar   PetscFunctionBegin;
22522b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
22532b4ed282SShri Abhyankar   if (iascii) {
22542b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
22552b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
22562b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
22572b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
225878c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
22590a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2260b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
226178c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
226278c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
22632b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
22642b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
22652b4ed282SShri Abhyankar   } else {
22662b4ed282SShri Abhyankar     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name);
22672b4ed282SShri Abhyankar   }
22682b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22692b4ed282SShri Abhyankar }
22702b4ed282SShri Abhyankar 
22715559b345SBarry Smith #undef __FUNCT__
22725559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
22735559b345SBarry Smith /*@
22742b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
22752b4ed282SShri Abhyankar 
22762b4ed282SShri Abhyankar    Input Parameters:
22772b4ed282SShri Abhyankar .  snes - the SNES context.
22782b4ed282SShri Abhyankar .  xl   - lower bound.
22792b4ed282SShri Abhyankar .  xu   - upper bound.
22802b4ed282SShri Abhyankar 
22812b4ed282SShri Abhyankar    Notes:
22822b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
228301f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
228484c105d7SBarry Smith 
22855559b345SBarry Smith @*/
228669c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
22872b4ed282SShri Abhyankar {
2288d923200aSJungho Lee   SNES_VI        *vi;
2289d923200aSJungho Lee   PetscErrorCode ierr;
22902b4ed282SShri Abhyankar 
22912b4ed282SShri Abhyankar   PetscFunctionBegin;
22922b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
22932b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
22942b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
22952b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
22962b4ed282SShri 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);
22972b4ed282SShri 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);
2298d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2299d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
23002b4ed282SShri Abhyankar   vi->usersetxbounds = PETSC_TRUE;
23012b4ed282SShri Abhyankar   vi->xl = xl;
23022b4ed282SShri Abhyankar   vi->xu = xu;
23032b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23042b4ed282SShri Abhyankar }
2305693ddf92SShri Abhyankar 
23062b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23072b4ed282SShri Abhyankar /*
23082b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
23092b4ed282SShri Abhyankar 
23102b4ed282SShri Abhyankar    Input Parameter:
23112b4ed282SShri Abhyankar .  snes - the SNES context
23122b4ed282SShri Abhyankar 
23132b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
23142b4ed282SShri Abhyankar */
23152b4ed282SShri Abhyankar #undef __FUNCT__
23162b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
23172b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
23182b4ed282SShri Abhyankar {
23192b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
23207fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2321b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
23222b4ed282SShri Abhyankar   PetscErrorCode ierr;
23232b4ed282SShri Abhyankar   PetscInt       indx;
232469c03620SShri Abhyankar   PetscBool      flg,set,flg2;
23252b4ed282SShri Abhyankar 
23262b4ed282SShri Abhyankar   PetscFunctionBegin;
23272b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
23289308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
23299308c137SBarry Smith   if (flg) {
23309308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
23319308c137SBarry Smith   }
2332be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2333be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2334be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
23352b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2336be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
23372b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
23382f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
233969c03620SShri Abhyankar   if (flg2) {
234069c03620SShri Abhyankar     switch (indx) {
234169c03620SShri Abhyankar     case 0:
234269c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
234369c03620SShri Abhyankar       break;
234469c03620SShri Abhyankar     case 1:
2345d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2346d950fb63SShri Abhyankar       break;
23472f63a38cSShri Abhyankar     case 2:
2348b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
234969c03620SShri Abhyankar     }
235069c03620SShri Abhyankar   }
2351be6adb11SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr);
23522b4ed282SShri Abhyankar   if (flg) {
23532b4ed282SShri Abhyankar     switch (indx) {
23542b4ed282SShri Abhyankar     case 0:
23552b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
23562b4ed282SShri Abhyankar       break;
23572b4ed282SShri Abhyankar     case 1:
23582b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
23592b4ed282SShri Abhyankar       break;
23602b4ed282SShri Abhyankar     case 2:
23612b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
23622b4ed282SShri Abhyankar       break;
23632b4ed282SShri Abhyankar     case 3:
23642b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
23652b4ed282SShri Abhyankar       break;
23662b4ed282SShri Abhyankar     }
2367fe835674SShri Abhyankar   }
23682b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
23692b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23702b4ed282SShri Abhyankar }
23712b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23722b4ed282SShri Abhyankar /*MC
23738b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
23742b4ed282SShri Abhyankar 
23752b4ed282SShri Abhyankar    Options Database:
23768b4c83edSBarry 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
23778b4c83edSBarry Smith                                 additional variables that enforce the constraints
23788b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
23792b4ed282SShri Abhyankar 
23802b4ed282SShri Abhyankar 
23812b4ed282SShri Abhyankar    Level: beginner
23822b4ed282SShri Abhyankar 
23832b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
23842b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
23852b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
23862b4ed282SShri Abhyankar 
23872b4ed282SShri Abhyankar M*/
23882b4ed282SShri Abhyankar EXTERN_C_BEGIN
23892b4ed282SShri Abhyankar #undef __FUNCT__
23902b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
23917087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
23922b4ed282SShri Abhyankar {
23932b4ed282SShri Abhyankar   PetscErrorCode ierr;
23942b4ed282SShri Abhyankar   SNES_VI      *vi;
23952b4ed282SShri Abhyankar 
23962b4ed282SShri Abhyankar   PetscFunctionBegin;
23972b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2398edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
23992b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
24002b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
24012b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
240237596af1SLisandro Dalcin   snes->ops->reset           = 0; /* XXX Implement!!! */
24032b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
24042b4ed282SShri Abhyankar 
24052b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
24062b4ed282SShri Abhyankar   snes->data            = (void*)vi;
24072b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
24082b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
24092b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
24107fe79bc4SShri Abhyankar   vi->LineSearch        = SNESLineSearchNo_VI;
24112b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
24122b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
24132b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
24142b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
24152b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
24162b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
24172f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
24182b4ed282SShri Abhyankar 
24192b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
24202b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
24212b4ed282SShri Abhyankar 
24222b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24232b4ed282SShri Abhyankar }
24242b4ed282SShri Abhyankar EXTERN_C_END
2425