xref: /petsc/src/snes/impls/vi/vi.c (revision 298cc2083debba3835f8dd411d8115b662ff203b)
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 typedef struct {
84dcab191SBarry Smith   PetscInt       n;                                        /* size of vectors in the reduced DM space */
9d0af7cd3SBarry Smith   IS             inactive;
10d0af7cd3SBarry Smith   Vec            upper,lower,values,F;                    /* upper and lower bounds of all variables on this level, the values and the function values */
11d0af7cd3SBarry Smith   PetscErrorCode (*getinterpolation)(DM,DM,Mat*,Vec*);    /* DM's original routines */
12d0af7cd3SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
13*298cc208SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
14d0af7cd3SBarry Smith } DMSNESVI;
15d0af7cd3SBarry Smith 
16d0af7cd3SBarry Smith #undef __FUNCT__
17d0af7cd3SBarry Smith #define __FUNCT__ "SNESVIGetInActiveSetIS"
18d0af7cd3SBarry Smith /*
19d0af7cd3SBarry Smith    SNESVIGetInActiveSetIS - Gets the global indices for the bogus inactive set variables
20d0af7cd3SBarry Smith 
21d0af7cd3SBarry Smith    Input parameter
22d0af7cd3SBarry Smith .  snes - the SNES context
23d0af7cd3SBarry Smith .  X    - the snes solution vector
24d0af7cd3SBarry Smith 
25d0af7cd3SBarry Smith    Output parameter
26d0af7cd3SBarry Smith .  ISact - active set index set
27d0af7cd3SBarry Smith 
28d0af7cd3SBarry Smith  */
29d0af7cd3SBarry Smith PetscErrorCode SNESVIGetInActiveSetIS(Vec upper,Vec lower,Vec X,Vec F,IS* inact)
30d0af7cd3SBarry Smith {
31d0af7cd3SBarry Smith   PetscErrorCode   ierr;
32d0af7cd3SBarry Smith   const PetscScalar *x,*xl,*xu,*f;
33d0af7cd3SBarry Smith   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
34d0af7cd3SBarry Smith 
35d0af7cd3SBarry Smith   PetscFunctionBegin;
36d0af7cd3SBarry Smith   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
37d0af7cd3SBarry Smith   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
38d0af7cd3SBarry Smith   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
39d0af7cd3SBarry Smith   ierr = VecGetArrayRead(lower,&xl);CHKERRQ(ierr);
40d0af7cd3SBarry Smith   ierr = VecGetArrayRead(upper,&xu);CHKERRQ(ierr);
41d0af7cd3SBarry Smith   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
42d0af7cd3SBarry Smith   /* Compute inactive set size */
43d0af7cd3SBarry Smith   for (i=0; i < nlocal;i++) {
44d0af7cd3SBarry 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++;
45d0af7cd3SBarry Smith   }
46d0af7cd3SBarry Smith 
47d0af7cd3SBarry Smith   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
48d0af7cd3SBarry Smith 
49d0af7cd3SBarry Smith   /* Set inactive set indices */
50d0af7cd3SBarry Smith   for(i=0; i < nlocal; i++) {
51d0af7cd3SBarry 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;
52d0af7cd3SBarry Smith   }
53d0af7cd3SBarry Smith 
54d0af7cd3SBarry Smith    /* Create inactive set IS */
55d0af7cd3SBarry Smith   ierr = ISCreateGeneral(((PetscObject)upper)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,inact);CHKERRQ(ierr);
56d0af7cd3SBarry Smith 
57d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
58d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(lower,&xl);CHKERRQ(ierr);
59d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(upper,&xu);CHKERRQ(ierr);
60d0af7cd3SBarry Smith   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
61d0af7cd3SBarry Smith   PetscFunctionReturn(0);
62d0af7cd3SBarry Smith }
63d0af7cd3SBarry Smith 
64d0af7cd3SBarry Smith #undef __FUNCT__
654dcab191SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
664dcab191SBarry Smith /*
674dcab191SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
684dcab191SBarry Smith 
694dcab191SBarry Smith */
704dcab191SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
714dcab191SBarry Smith {
724dcab191SBarry Smith   PetscErrorCode          ierr;
734dcab191SBarry Smith   PetscContainer          isnes;
744dcab191SBarry Smith   DMSNESVI                *dmsnesvi;
754dcab191SBarry Smith 
764dcab191SBarry Smith   PetscFunctionBegin;
774dcab191SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
784dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
794dcab191SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
804dcab191SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
814dcab191SBarry Smith   PetscFunctionReturn(0);
824dcab191SBarry Smith }
834dcab191SBarry Smith 
844dcab191SBarry Smith #undef __FUNCT__
85d0af7cd3SBarry Smith #define __FUNCT__ "DMGetInterpolation_SNESVI"
86d0af7cd3SBarry Smith /*
87d0af7cd3SBarry Smith      DMGetInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
88d0af7cd3SBarry Smith 
89d0af7cd3SBarry Smith */
90d0af7cd3SBarry Smith PetscErrorCode  DMGetInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
91d0af7cd3SBarry Smith {
92d0af7cd3SBarry Smith   PetscErrorCode          ierr;
93d0af7cd3SBarry Smith   PetscContainer          isnes;
94d0af7cd3SBarry Smith   DMSNESVI                *dmsnesvi1,*dmsnesvi2;
95d0af7cd3SBarry Smith   Mat                     interp;
96d0af7cd3SBarry Smith 
97d0af7cd3SBarry Smith   PetscFunctionBegin;
98d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
994dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
100d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
101d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1024dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
103d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
104d0af7cd3SBarry Smith 
105d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->getinterpolation)(dm1,dm2,&interp,PETSC_NULL);CHKERRQ(ierr);
1064dcab191SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
107d0af7cd3SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
108d0af7cd3SBarry Smith   PetscFunctionReturn(0);
109d0af7cd3SBarry Smith }
110d0af7cd3SBarry Smith 
111d0af7cd3SBarry Smith extern PetscErrorCode  DMSetVI(DM,Vec,Vec,Vec,Vec,IS);
112d0af7cd3SBarry Smith 
113d0af7cd3SBarry Smith #undef __FUNCT__
114d0af7cd3SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
115d0af7cd3SBarry Smith /*
116d0af7cd3SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
117d0af7cd3SBarry Smith 
118d0af7cd3SBarry Smith */
119d0af7cd3SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
120d0af7cd3SBarry Smith {
121d0af7cd3SBarry Smith   PetscErrorCode          ierr;
122d0af7cd3SBarry Smith   PetscContainer          isnes;
123d0af7cd3SBarry Smith   DMSNESVI                *dmsnesvi1;
124d0af7cd3SBarry Smith   Vec                     upper,lower,values,F;
125d0af7cd3SBarry Smith   IS                      inactive;
126d0af7cd3SBarry Smith   VecScatter              inject;
127d0af7cd3SBarry Smith 
128d0af7cd3SBarry Smith   PetscFunctionBegin;
129d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
1304dcab191SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
131d0af7cd3SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
132d0af7cd3SBarry Smith 
133*298cc208SBarry Smith   /* get the original coarsen */
134d0af7cd3SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
135*298cc208SBarry Smith 
136*298cc208SBarry Smith   /* need to set back global vectors in order to use the original injection */
137*298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
138*298cc208SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
139d0af7cd3SBarry Smith   ierr = DMGetInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
140d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&upper);CHKERRQ(ierr);
141d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
142d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->upper,upper,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
143d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&lower);CHKERRQ(ierr);
144d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
145d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->lower,lower,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
146d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&values);CHKERRQ(ierr);
147d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
148d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->values,values,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
149d0af7cd3SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&F);CHKERRQ(ierr);
150d0af7cd3SBarry Smith   ierr = VecScatterBegin(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
151d0af7cd3SBarry Smith   ierr = VecScatterEnd(inject,dmsnesvi1->F,F,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
152d0af7cd3SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
153*298cc208SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
154*298cc208SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
155d0af7cd3SBarry Smith   ierr = SNESVIGetInActiveSetIS(upper,lower,values,F,&inactive);CHKERRQ(ierr);
156d0af7cd3SBarry Smith   ierr = DMSetVI(*dm2,upper,lower,values,F,inactive);CHKERRQ(ierr);
157d0af7cd3SBarry Smith   PetscFunctionReturn(0);
158d0af7cd3SBarry Smith }
159d0af7cd3SBarry Smith 
160d0af7cd3SBarry Smith #undef __FUNCT__
161d0af7cd3SBarry Smith #define __FUNCT__ "DMSNESVIDestroy"
162d0af7cd3SBarry Smith PetscErrorCode DMSNESVIDestroy(DMSNESVI *dmsnesvi)
163d0af7cd3SBarry Smith {
164d0af7cd3SBarry Smith   PetscErrorCode ierr;
165d0af7cd3SBarry Smith 
166d0af7cd3SBarry Smith   PetscFunctionBegin;
167d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
168d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
169d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
170d0af7cd3SBarry Smith   ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
171d0af7cd3SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
172d0af7cd3SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
173d0af7cd3SBarry Smith   PetscFunctionReturn(0);
174d0af7cd3SBarry Smith }
175d0af7cd3SBarry Smith 
176d0af7cd3SBarry Smith #undef __FUNCT__
177d0af7cd3SBarry Smith #define __FUNCT__ "DMSetVI"
178d0af7cd3SBarry Smith /*
179d0af7cd3SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
180d0af7cd3SBarry Smith                be restricted to only those variables NOT associated with active constraints.
181d0af7cd3SBarry Smith 
182d0af7cd3SBarry Smith */
183d0af7cd3SBarry Smith PetscErrorCode  DMSetVI(DM dm,Vec upper,Vec lower,Vec values,Vec F,IS inactive)
184d0af7cd3SBarry Smith {
185d0af7cd3SBarry Smith   PetscErrorCode          ierr;
186d0af7cd3SBarry Smith   PetscContainer          isnes;
187d0af7cd3SBarry Smith   DMSNESVI                *dmsnesvi;
188d0af7cd3SBarry Smith 
189d0af7cd3SBarry Smith   PetscFunctionBegin;
1904dcab191SBarry Smith   if (!dm) PetscFunctionReturn(0);
191d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)upper);CHKERRQ(ierr);
192d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)lower);CHKERRQ(ierr);
193d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)values);CHKERRQ(ierr);
194d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)F);CHKERRQ(ierr);
195d0af7cd3SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
196d0af7cd3SBarry Smith 
197d0af7cd3SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject *)&isnes);CHKERRQ(ierr);
198d0af7cd3SBarry Smith   if (!isnes) {
199d0af7cd3SBarry Smith     /* cannot just compose snes into dm because that will cause circular reference */
200d0af7cd3SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
201d0af7cd3SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMSNESVIDestroy);CHKERRQ(ierr);
202d0af7cd3SBarry Smith     ierr = PetscNew(DMSNESVI,&dmsnesvi);CHKERRQ(ierr);
203d0af7cd3SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
204d0af7cd3SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
205d0af7cd3SBarry Smith     dmsnesvi->getinterpolation   = dm->ops->getinterpolation;
206d0af7cd3SBarry Smith     dm->ops->getinterpolation    = DMGetInterpolation_SNESVI;
207d0af7cd3SBarry Smith     dmsnesvi->coarsen            = dm->ops->coarsen;
208d0af7cd3SBarry Smith     dm->ops->coarsen             = DMCoarsen_SNESVI;
209*298cc208SBarry Smith     dmsnesvi->createglobalvector = dm->ops->createglobalvector;
2104dcab191SBarry Smith     dm->ops->createglobalvector  = DMCreateGlobalVector_SNESVI;
211d0af7cd3SBarry Smith   } else {
212d0af7cd3SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
213d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->upper);CHKERRQ(ierr);
214d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->lower);CHKERRQ(ierr);
215d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->values);CHKERRQ(ierr);
216d0af7cd3SBarry Smith     ierr = VecDestroy(&dmsnesvi->F);CHKERRQ(ierr);
217d0af7cd3SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
218d0af7cd3SBarry Smith   }
2194dcab191SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
2204dcab191SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
221d0af7cd3SBarry Smith   dmsnesvi->upper    = upper;
222d0af7cd3SBarry Smith   dmsnesvi->lower    = lower;
223d0af7cd3SBarry Smith   dmsnesvi->values   = values;
224d0af7cd3SBarry Smith   dmsnesvi->F        = F;
225d0af7cd3SBarry Smith   dmsnesvi->inactive = inactive;
226d0af7cd3SBarry Smith   PetscFunctionReturn(0);
227d0af7cd3SBarry Smith }
228d0af7cd3SBarry Smith 
229d0af7cd3SBarry Smith 
2302b4ed282SShri Abhyankar 
2319308c137SBarry Smith #undef __FUNCT__
2329308c137SBarry Smith #define __FUNCT__ "SNESMonitorVI"
2337087cfbeSBarry Smith PetscErrorCode  SNESMonitorVI(SNES snes,PetscInt its,PetscReal fgnorm,void *dummy)
2349308c137SBarry Smith {
2359308c137SBarry Smith   PetscErrorCode          ierr;
2369308c137SBarry Smith   SNES_VI                 *vi = (SNES_VI*)snes->data;
2379308c137SBarry Smith   PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor) dummy;
2389308c137SBarry Smith   const PetscScalar       *x,*xl,*xu,*f;
23909573ac7SBarry Smith   PetscInt                i,n,act = 0;
2409308c137SBarry Smith   PetscReal               rnorm,fnorm;
2419308c137SBarry Smith 
2429308c137SBarry Smith   PetscFunctionBegin;
2439308c137SBarry Smith   if (!dummy) {
2449308c137SBarry Smith     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",0,&viewer);CHKERRQ(ierr);
2459308c137SBarry Smith   }
2469308c137SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
2479308c137SBarry Smith   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
2489308c137SBarry Smith   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
2499308c137SBarry Smith   ierr = VecGetArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
2503f731af5SBarry Smith   ierr = VecGetArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
2519308c137SBarry Smith 
2529308c137SBarry Smith   rnorm = 0.0;
2539308c137SBarry Smith   for (i=0; i<n; i++) {
25410f5ae6bSBarry 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]);
25509573ac7SBarry Smith     else act++;
2569308c137SBarry Smith   }
2573f731af5SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_func,&f);CHKERRQ(ierr);
2589308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
2599308c137SBarry Smith   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
2609308c137SBarry Smith   ierr = VecRestoreArrayRead(snes->vec_sol,&x);CHKERRQ(ierr);
261d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,&fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
2629308c137SBarry Smith   fnorm = sqrt(fnorm);
26309573ac7SBarry Smith   ierr = PetscViewerASCIIMonitorPrintf(viewer,"%3D SNES VI Function norm %14.12e Active constraints %D\n",its,fnorm,act);CHKERRQ(ierr);
2649308c137SBarry Smith   if (!dummy) {
2656bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&viewer);CHKERRQ(ierr);
2669308c137SBarry Smith   }
2679308c137SBarry Smith   PetscFunctionReturn(0);
2689308c137SBarry Smith }
2699308c137SBarry Smith 
2702b4ed282SShri Abhyankar /*
2712b4ed282SShri Abhyankar      Checks if J^T F = 0 which implies we've found a local minimum of the norm of the function,
2722b4ed282SShri 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
2732b4ed282SShri Abhyankar     0 = (J^T F)^T W = F^T J W iff W not in the null space of J. Thanks for Jorge More
2742b4ed282SShri Abhyankar     for this trick. One assumes that the probability that W is in the null space of J is very, very small.
2752b4ed282SShri Abhyankar */
2762b4ed282SShri Abhyankar #undef __FUNCT__
2772b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckLocalMin_Private"
278ace3abfcSBarry Smith PetscErrorCode SNESVICheckLocalMin_Private(SNES snes,Mat A,Vec F,Vec W,PetscReal fnorm,PetscBool *ismin)
2792b4ed282SShri Abhyankar {
2802b4ed282SShri Abhyankar   PetscReal      a1;
2812b4ed282SShri Abhyankar   PetscErrorCode ierr;
282ace3abfcSBarry Smith   PetscBool     hastranspose;
2832b4ed282SShri Abhyankar 
2842b4ed282SShri Abhyankar   PetscFunctionBegin;
2852b4ed282SShri Abhyankar   *ismin = PETSC_FALSE;
2862b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
2872b4ed282SShri Abhyankar   if (hastranspose) {
2882b4ed282SShri Abhyankar     /* Compute || J^T F|| */
2892b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,F,W);CHKERRQ(ierr);
2902b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&a1);CHKERRQ(ierr);
2912b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"|| J^T F|| %G near zero implies found a local minimum\n",a1/fnorm);CHKERRQ(ierr);
2922b4ed282SShri Abhyankar     if (a1/fnorm < 1.e-4) *ismin = PETSC_TRUE;
2932b4ed282SShri Abhyankar   } else {
2942b4ed282SShri Abhyankar     Vec         work;
2952b4ed282SShri Abhyankar     PetscScalar result;
2962b4ed282SShri Abhyankar     PetscReal   wnorm;
2972b4ed282SShri Abhyankar 
2982b4ed282SShri Abhyankar     ierr = VecSetRandom(W,PETSC_NULL);CHKERRQ(ierr);
2992b4ed282SShri Abhyankar     ierr = VecNorm(W,NORM_2,&wnorm);CHKERRQ(ierr);
3002b4ed282SShri Abhyankar     ierr = VecDuplicate(W,&work);CHKERRQ(ierr);
3012b4ed282SShri Abhyankar     ierr = MatMult(A,W,work);CHKERRQ(ierr);
3022b4ed282SShri Abhyankar     ierr = VecDot(F,work,&result);CHKERRQ(ierr);
3036bf464f9SBarry Smith     ierr = VecDestroy(&work);CHKERRQ(ierr);
3042b4ed282SShri Abhyankar     a1   = PetscAbsScalar(result)/(fnorm*wnorm);
3052b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"(F^T J random)/(|| F ||*||random|| %G near zero implies found a local minimum\n",a1);CHKERRQ(ierr);
3062b4ed282SShri Abhyankar     if (a1 < 1.e-4) *ismin = PETSC_TRUE;
3072b4ed282SShri Abhyankar   }
3082b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3092b4ed282SShri Abhyankar }
3102b4ed282SShri Abhyankar 
3112b4ed282SShri Abhyankar /*
3122b4ed282SShri Abhyankar      Checks if J^T(F - J*X) = 0
3132b4ed282SShri Abhyankar */
3142b4ed282SShri Abhyankar #undef __FUNCT__
3152b4ed282SShri Abhyankar #define __FUNCT__ "SNESVICheckResidual_Private"
3162b4ed282SShri Abhyankar PetscErrorCode SNESVICheckResidual_Private(SNES snes,Mat A,Vec F,Vec X,Vec W1,Vec W2)
3172b4ed282SShri Abhyankar {
3182b4ed282SShri Abhyankar   PetscReal      a1,a2;
3192b4ed282SShri Abhyankar   PetscErrorCode ierr;
320ace3abfcSBarry Smith   PetscBool     hastranspose;
3212b4ed282SShri Abhyankar 
3222b4ed282SShri Abhyankar   PetscFunctionBegin;
3232b4ed282SShri Abhyankar   ierr = MatHasOperation(A,MATOP_MULT_TRANSPOSE,&hastranspose);CHKERRQ(ierr);
3242b4ed282SShri Abhyankar   if (hastranspose) {
3252b4ed282SShri Abhyankar     ierr = MatMult(A,X,W1);CHKERRQ(ierr);
3262b4ed282SShri Abhyankar     ierr = VecAXPY(W1,-1.0,F);CHKERRQ(ierr);
3272b4ed282SShri Abhyankar 
3282b4ed282SShri Abhyankar     /* Compute || J^T W|| */
3292b4ed282SShri Abhyankar     ierr = MatMultTranspose(A,W1,W2);CHKERRQ(ierr);
3302b4ed282SShri Abhyankar     ierr = VecNorm(W1,NORM_2,&a1);CHKERRQ(ierr);
3312b4ed282SShri Abhyankar     ierr = VecNorm(W2,NORM_2,&a2);CHKERRQ(ierr);
3322b4ed282SShri Abhyankar     if (a1 != 0.0) {
3332b4ed282SShri Abhyankar       ierr = PetscInfo1(snes,"||J^T(F-Ax)||/||F-AX|| %G near zero implies inconsistent rhs\n",a2/a1);CHKERRQ(ierr);
3342b4ed282SShri Abhyankar     }
3352b4ed282SShri Abhyankar   }
3362b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3372b4ed282SShri Abhyankar }
3382b4ed282SShri Abhyankar 
3392b4ed282SShri Abhyankar /*
3402b4ed282SShri Abhyankar   SNESDefaultConverged_VI - Checks the convergence of the semismooth newton algorithm.
3412b4ed282SShri Abhyankar 
3422b4ed282SShri Abhyankar   Notes:
3432b4ed282SShri Abhyankar   The convergence criterion currently implemented is
3442b4ed282SShri Abhyankar   merit < abstol
3452b4ed282SShri Abhyankar   merit < rtol*merit_initial
3462b4ed282SShri Abhyankar */
3472b4ed282SShri Abhyankar #undef __FUNCT__
3482b4ed282SShri Abhyankar #define __FUNCT__ "SNESDefaultConverged_VI"
3497fe79bc4SShri Abhyankar PetscErrorCode SNESDefaultConverged_VI(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gradnorm,PetscReal fnorm,SNESConvergedReason *reason,void *dummy)
3502b4ed282SShri Abhyankar {
3512b4ed282SShri Abhyankar   PetscErrorCode ierr;
3522b4ed282SShri Abhyankar 
3532b4ed282SShri Abhyankar   PetscFunctionBegin;
3542b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
3552b4ed282SShri Abhyankar   PetscValidPointer(reason,6);
3562b4ed282SShri Abhyankar 
3572b4ed282SShri Abhyankar   *reason = SNES_CONVERGED_ITERATING;
3582b4ed282SShri Abhyankar 
3592b4ed282SShri Abhyankar   if (!it) {
3602b4ed282SShri Abhyankar     /* set parameter for default relative tolerance convergence test */
3617fe79bc4SShri Abhyankar     snes->ttol = fnorm*snes->rtol;
3622b4ed282SShri Abhyankar   }
3637fe79bc4SShri Abhyankar   if (fnorm != fnorm) {
3642b4ed282SShri Abhyankar     ierr = PetscInfo(snes,"Failed to converged, function norm is NaN\n");CHKERRQ(ierr);
3652b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FNORM_NAN;
3667fe79bc4SShri Abhyankar   } else if (fnorm < snes->abstol) {
3677fe79bc4SShri Abhyankar     ierr = PetscInfo2(snes,"Converged due to function norm %G < %G\n",fnorm,snes->abstol);CHKERRQ(ierr);
3682b4ed282SShri Abhyankar     *reason = SNES_CONVERGED_FNORM_ABS;
3692b4ed282SShri Abhyankar   } else if (snes->nfuncs >= snes->max_funcs) {
3702b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"Exceeded maximum number of function evaluations: %D > %D\n",snes->nfuncs,snes->max_funcs);CHKERRQ(ierr);
3712b4ed282SShri Abhyankar     *reason = SNES_DIVERGED_FUNCTION_COUNT;
3722b4ed282SShri Abhyankar   }
3732b4ed282SShri Abhyankar 
3742b4ed282SShri Abhyankar   if (it && !*reason) {
3757fe79bc4SShri Abhyankar     if (fnorm < snes->ttol) {
3767fe79bc4SShri Abhyankar       ierr = PetscInfo2(snes,"Converged due to function norm %G < %G (relative tolerance)\n",fnorm,snes->ttol);CHKERRQ(ierr);
3772b4ed282SShri Abhyankar       *reason = SNES_CONVERGED_FNORM_RELATIVE;
3782b4ed282SShri Abhyankar     }
3792b4ed282SShri Abhyankar   }
3802b4ed282SShri Abhyankar   PetscFunctionReturn(0);
3812b4ed282SShri Abhyankar }
3822b4ed282SShri Abhyankar 
3832b4ed282SShri Abhyankar /*
3842b4ed282SShri Abhyankar   SNESVIComputeMeritFunction - Evaluates the merit function for the mixed complementarity problem.
3852b4ed282SShri Abhyankar 
3862b4ed282SShri Abhyankar   Input Parameter:
3872b4ed282SShri Abhyankar . phi - the semismooth function
3882b4ed282SShri Abhyankar 
3892b4ed282SShri Abhyankar   Output Parameter:
3902b4ed282SShri Abhyankar . merit - the merit function
3912b4ed282SShri Abhyankar . phinorm - ||phi||
3922b4ed282SShri Abhyankar 
3932b4ed282SShri Abhyankar   Notes:
3942b4ed282SShri Abhyankar   The merit function for the mixed complementarity problem is defined as
3952b4ed282SShri Abhyankar      merit = 0.5*phi^T*phi
3962b4ed282SShri Abhyankar */
3972b4ed282SShri Abhyankar #undef __FUNCT__
3982b4ed282SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunction"
3992b4ed282SShri Abhyankar static PetscErrorCode SNESVIComputeMeritFunction(Vec phi, PetscReal* merit,PetscReal* phinorm)
4002b4ed282SShri Abhyankar {
4012b4ed282SShri Abhyankar   PetscErrorCode ierr;
4022b4ed282SShri Abhyankar 
4032b4ed282SShri Abhyankar   PetscFunctionBegin;
4045f48b12bSBarry Smith   ierr = VecNormBegin(phi,NORM_2,phinorm);CHKERRQ(ierr);
4055f48b12bSBarry Smith   ierr = VecNormEnd(phi,NORM_2,phinorm);CHKERRQ(ierr);
4062b4ed282SShri Abhyankar 
4072b4ed282SShri Abhyankar   *merit = 0.5*(*phinorm)*(*phinorm);
4082b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4092b4ed282SShri Abhyankar }
4102b4ed282SShri Abhyankar 
4117f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar Phi(PetscScalar a,PetscScalar b)
4124c21c6cdSBarry Smith {
4134c21c6cdSBarry Smith   return a + b - sqrt(a*a + b*b);
4144c21c6cdSBarry Smith }
4154c21c6cdSBarry Smith 
4167f6f51e9SSatish Balay PETSC_STATIC_INLINE PetscScalar DPhi(PetscScalar a,PetscScalar b)
4174c21c6cdSBarry Smith {
4185559b345SBarry Smith   if ((PetscAbsScalar(a) >= 1.e-6) || (PetscAbsScalar(b) >= 1.e-6)) return  1.0 - a/ sqrt(a*a + b*b);
4195559b345SBarry Smith   else return .5;
4204c21c6cdSBarry Smith }
4214c21c6cdSBarry Smith 
4222b4ed282SShri Abhyankar /*
4231f79c099SShri Abhyankar    SNESVIComputeFunction - Reformulates a system of nonlinear equations in mixed complementarity form to a system of nonlinear equations in semismooth form.
4242b4ed282SShri Abhyankar 
4252b4ed282SShri Abhyankar    Input Parameters:
4262b4ed282SShri Abhyankar .  snes - the SNES context
4272b4ed282SShri Abhyankar .  x - current iterate
4282b4ed282SShri Abhyankar .  functx - user defined function context
4292b4ed282SShri Abhyankar 
4302b4ed282SShri Abhyankar    Output Parameters:
4312b4ed282SShri Abhyankar .  phi - Semismooth function
4322b4ed282SShri Abhyankar 
4332b4ed282SShri Abhyankar */
4342b4ed282SShri Abhyankar #undef __FUNCT__
4351f79c099SShri Abhyankar #define __FUNCT__ "SNESVIComputeFunction"
4361f79c099SShri Abhyankar static PetscErrorCode SNESVIComputeFunction(SNES snes,Vec X,Vec phi,void* functx)
4372b4ed282SShri Abhyankar {
4382b4ed282SShri Abhyankar   PetscErrorCode  ierr;
4392b4ed282SShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
4402b4ed282SShri Abhyankar   Vec             Xl = vi->xl,Xu = vi->xu,F = snes->vec_func;
4414c21c6cdSBarry Smith   PetscScalar     *phi_arr,*x_arr,*f_arr,*l,*u;
4422b4ed282SShri Abhyankar   PetscInt        i,nlocal;
4432b4ed282SShri Abhyankar 
4442b4ed282SShri Abhyankar   PetscFunctionBegin;
4452b4ed282SShri Abhyankar   ierr = (*vi->computeuserfunction)(snes,X,F,functx);CHKERRQ(ierr);
4462b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
4472b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x_arr);CHKERRQ(ierr);
4482b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f_arr);CHKERRQ(ierr);
4492b4ed282SShri Abhyankar   ierr = VecGetArray(Xl,&l);CHKERRQ(ierr);
4502b4ed282SShri Abhyankar   ierr = VecGetArray(Xu,&u);CHKERRQ(ierr);
4512b4ed282SShri Abhyankar   ierr = VecGetArray(phi,&phi_arr);CHKERRQ(ierr);
4522b4ed282SShri Abhyankar 
4532b4ed282SShri Abhyankar   for (i=0;i < nlocal;i++) {
45410f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) { /* no constraints on variable */
4554c21c6cdSBarry Smith       phi_arr[i] = f_arr[i];
45610f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                      /* upper bound on variable only */
4574c21c6cdSBarry Smith       phi_arr[i] = -Phi(u[i] - x_arr[i],-f_arr[i]);
45810f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                       /* lower bound on variable only */
4594c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],f_arr[i]);
4605559b345SBarry Smith     } else if (l[i] == u[i]) {
4612b4ed282SShri Abhyankar       phi_arr[i] = l[i] - x_arr[i];
4625559b345SBarry Smith     } else {                                                /* both bounds on variable */
4634c21c6cdSBarry Smith       phi_arr[i] = Phi(x_arr[i] - l[i],-Phi(u[i] - x_arr[i],-f_arr[i]));
4642b4ed282SShri Abhyankar     }
4652b4ed282SShri Abhyankar   }
4662b4ed282SShri Abhyankar 
4672b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x_arr);CHKERRQ(ierr);
4682b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f_arr);CHKERRQ(ierr);
4692b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xl,&l);CHKERRQ(ierr);
4702b4ed282SShri Abhyankar   ierr = VecRestoreArray(Xu,&u);CHKERRQ(ierr);
4712b4ed282SShri Abhyankar   ierr = VecRestoreArray(phi,&phi_arr);CHKERRQ(ierr);
4722b4ed282SShri Abhyankar   PetscFunctionReturn(0);
4732b4ed282SShri Abhyankar }
4742b4ed282SShri Abhyankar 
4752b4ed282SShri Abhyankar /*
476a79edbefSShri Abhyankar    SNESVIComputeBsubdifferentialVectors - Computes the diagonal shift (Da) and row scaling (Db) vectors needed for the
477a79edbefSShri Abhyankar                                           the semismooth jacobian.
4782b4ed282SShri Abhyankar */
4792b4ed282SShri Abhyankar #undef __FUNCT__
480a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeBsubdifferentialVectors"
481a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeBsubdifferentialVectors(SNES snes,Vec X,Vec F,Mat jac,Vec Da,Vec Db)
4822b4ed282SShri Abhyankar {
4832b4ed282SShri Abhyankar   PetscErrorCode ierr;
4842b4ed282SShri Abhyankar   SNES_VI      *vi = (SNES_VI*)snes->data;
4854c21c6cdSBarry Smith   PetscScalar    *l,*u,*x,*f,*da,*db,da1,da2,db1,db2;
4862b4ed282SShri Abhyankar   PetscInt       i,nlocal;
4872b4ed282SShri Abhyankar 
4882b4ed282SShri Abhyankar   PetscFunctionBegin;
4892b4ed282SShri Abhyankar 
4902b4ed282SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
4912b4ed282SShri Abhyankar   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
4922b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xl,&l);CHKERRQ(ierr);
4932b4ed282SShri Abhyankar   ierr = VecGetArray(vi->xu,&u);CHKERRQ(ierr);
494a79edbefSShri Abhyankar   ierr = VecGetArray(Da,&da);CHKERRQ(ierr);
495a79edbefSShri Abhyankar   ierr = VecGetArray(Db,&db);CHKERRQ(ierr);
4962b4ed282SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
4974c21c6cdSBarry Smith 
4982b4ed282SShri Abhyankar   for (i=0;i< nlocal;i++) {
49910f5ae6bSBarry Smith     if ((PetscRealPart(l[i]) <= SNES_VI_NINF) && (PetscRealPart(u[i]) >= SNES_VI_INF)) {/* no constraints on variable */
5004c21c6cdSBarry Smith       da[i] = 0;
5012b4ed282SShri Abhyankar       db[i] = 1;
50210f5ae6bSBarry Smith     } else if (PetscRealPart(l[i]) <= SNES_VI_NINF) {                     /* upper bound on variable only */
5034c21c6cdSBarry Smith       da[i] = DPhi(u[i] - x[i], -f[i]);
5044c21c6cdSBarry Smith       db[i] = DPhi(-f[i],u[i] - x[i]);
50510f5ae6bSBarry Smith     } else if (PetscRealPart(u[i]) >= SNES_VI_INF) {                      /* lower bound on variable only */
5065559b345SBarry Smith       da[i] = DPhi(x[i] - l[i], f[i]);
5075559b345SBarry Smith       db[i] = DPhi(f[i],x[i] - l[i]);
5085559b345SBarry Smith     } else if (l[i] == u[i]) {                              /* fixed variable */
5094c21c6cdSBarry Smith       da[i] = 1;
5102b4ed282SShri Abhyankar       db[i] = 0;
5115559b345SBarry Smith     } else {                                                /* upper and lower bounds on variable */
5124c21c6cdSBarry Smith       da1 = DPhi(x[i] - l[i], -Phi(u[i] - x[i], -f[i]));
5134c21c6cdSBarry Smith       db1 = DPhi(-Phi(u[i] - x[i], -f[i]),x[i] - l[i]);
5144c21c6cdSBarry Smith       da2 = DPhi(u[i] - x[i], -f[i]);
5154c21c6cdSBarry Smith       db2 = DPhi(-f[i],u[i] - x[i]);
5164c21c6cdSBarry Smith       da[i] = da1 + db1*da2;
5174c21c6cdSBarry Smith       db[i] = db1*db2;
5182b4ed282SShri Abhyankar     }
5192b4ed282SShri Abhyankar   }
5205559b345SBarry Smith 
5212b4ed282SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
5222b4ed282SShri Abhyankar   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
5232b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xl,&l);CHKERRQ(ierr);
5242b4ed282SShri Abhyankar   ierr = VecRestoreArray(vi->xu,&u);CHKERRQ(ierr);
525a79edbefSShri Abhyankar   ierr = VecRestoreArray(Da,&da);CHKERRQ(ierr);
526a79edbefSShri Abhyankar   ierr = VecRestoreArray(Db,&db);CHKERRQ(ierr);
527a79edbefSShri Abhyankar   PetscFunctionReturn(0);
528a79edbefSShri Abhyankar }
529a79edbefSShri Abhyankar 
530a79edbefSShri Abhyankar /*
531a79edbefSShri 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.
532a79edbefSShri Abhyankar 
533a79edbefSShri Abhyankar    Input Parameters:
534a79edbefSShri Abhyankar .  Da       - Diagonal shift vector for the semismooth jacobian.
535a79edbefSShri Abhyankar .  Db       - Row scaling vector for the semismooth jacobian.
536a79edbefSShri Abhyankar 
537a79edbefSShri Abhyankar    Output Parameters:
538a79edbefSShri Abhyankar .  jac      - semismooth jacobian
539a79edbefSShri Abhyankar .  jac_pre  - optional preconditioning matrix
540a79edbefSShri Abhyankar 
541a79edbefSShri Abhyankar    Notes:
542a79edbefSShri Abhyankar    The semismooth jacobian matrix is given by
543a79edbefSShri Abhyankar    jac = Da + Db*jacfun
544a79edbefSShri Abhyankar    where Db is the row scaling matrix stored as a vector,
545a79edbefSShri Abhyankar          Da is the diagonal perturbation matrix stored as a vector
546a79edbefSShri Abhyankar    and   jacfun is the jacobian of the original nonlinear function.
547a79edbefSShri Abhyankar */
548a79edbefSShri Abhyankar #undef __FUNCT__
549a79edbefSShri Abhyankar #define __FUNCT__ "SNESVIComputeJacobian"
550a79edbefSShri Abhyankar PetscErrorCode SNESVIComputeJacobian(Mat jac, Mat jac_pre,Vec Da, Vec Db)
551a79edbefSShri Abhyankar {
552a79edbefSShri Abhyankar   PetscErrorCode ierr;
553a79edbefSShri Abhyankar 
5542b4ed282SShri Abhyankar   /* Do row scaling  and add diagonal perturbation */
555a79edbefSShri Abhyankar   ierr = MatDiagonalScale(jac,Db,PETSC_NULL);CHKERRQ(ierr);
556a79edbefSShri Abhyankar   ierr = MatDiagonalSet(jac,Da,ADD_VALUES);CHKERRQ(ierr);
557a79edbefSShri Abhyankar   if (jac != jac_pre) { /* If jac and jac_pre are different */
558a79edbefSShri Abhyankar     ierr = MatDiagonalScale(jac_pre,Db,PETSC_NULL);
559a79edbefSShri Abhyankar     ierr = MatDiagonalSet(jac_pre,Da,ADD_VALUES);CHKERRQ(ierr);
5602b4ed282SShri Abhyankar   }
5612b4ed282SShri Abhyankar   PetscFunctionReturn(0);
5622b4ed282SShri Abhyankar }
5632b4ed282SShri Abhyankar 
5642b4ed282SShri Abhyankar /*
565ee657d29SShri Abhyankar    SNESVIComputeMeritFunctionGradient - Computes the gradient of the merit function psi.
566ee657d29SShri Abhyankar 
567ee657d29SShri Abhyankar    Input Parameters:
568ee657d29SShri Abhyankar    phi - semismooth function.
569ee657d29SShri Abhyankar    H   - semismooth jacobian
570ee657d29SShri Abhyankar 
571ee657d29SShri Abhyankar    Output Parameters:
572ee657d29SShri Abhyankar    dpsi - merit function gradient
573ee657d29SShri Abhyankar 
574ee657d29SShri Abhyankar    Notes:
575ee657d29SShri Abhyankar   The merit function gradient is computed as follows
576ee657d29SShri Abhyankar         dpsi = H^T*phi
577ee657d29SShri Abhyankar */
578ee657d29SShri Abhyankar #undef __FUNCT__
579ee657d29SShri Abhyankar #define __FUNCT__ "SNESVIComputeMeritFunctionGradient"
580ee657d29SShri Abhyankar PetscErrorCode SNESVIComputeMeritFunctionGradient(Mat H, Vec phi, Vec dpsi)
581ee657d29SShri Abhyankar {
582ee657d29SShri Abhyankar   PetscErrorCode ierr;
583ee657d29SShri Abhyankar 
584ee657d29SShri Abhyankar   PetscFunctionBegin;
5855f48b12bSBarry Smith   ierr = MatMultTranspose(H,phi,dpsi);CHKERRQ(ierr);
586ee657d29SShri Abhyankar   PetscFunctionReturn(0);
587ee657d29SShri Abhyankar }
588ee657d29SShri Abhyankar 
589c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
590c1a5e521SShri Abhyankar /*
591c1a5e521SShri Abhyankar    SNESVIProjectOntoBounds - Projects X onto the feasible region so that Xl[i] <= X[i] <= Xu[i] for i = 1...n.
592c1a5e521SShri Abhyankar 
593c1a5e521SShri Abhyankar    Input Parameters:
594c1a5e521SShri Abhyankar .  SNES - nonlinear solver context
595c1a5e521SShri Abhyankar 
596c1a5e521SShri Abhyankar    Output Parameters:
597c1a5e521SShri Abhyankar .  X - Bound projected X
598c1a5e521SShri Abhyankar 
599c1a5e521SShri Abhyankar */
600c1a5e521SShri Abhyankar 
601c1a5e521SShri Abhyankar #undef __FUNCT__
602c1a5e521SShri Abhyankar #define __FUNCT__ "SNESVIProjectOntoBounds"
603c1a5e521SShri Abhyankar PetscErrorCode SNESVIProjectOntoBounds(SNES snes,Vec X)
604c1a5e521SShri Abhyankar {
605c1a5e521SShri Abhyankar   PetscErrorCode    ierr;
606c1a5e521SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
607c1a5e521SShri Abhyankar   const PetscScalar *xl,*xu;
608c1a5e521SShri Abhyankar   PetscScalar       *x;
609c1a5e521SShri Abhyankar   PetscInt          i,n;
610c1a5e521SShri Abhyankar 
611c1a5e521SShri Abhyankar   PetscFunctionBegin;
612c1a5e521SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
613c1a5e521SShri Abhyankar   ierr = VecGetArray(X,&x);CHKERRQ(ierr);
614c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
615c1a5e521SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
616c1a5e521SShri Abhyankar 
617c1a5e521SShri Abhyankar   for(i = 0;i<n;i++) {
61810f5ae6bSBarry Smith     if (PetscRealPart(x[i]) < PetscRealPart(xl[i])) x[i] = xl[i];
61910f5ae6bSBarry Smith     else if (PetscRealPart(x[i]) > PetscRealPart(xu[i])) x[i] = xu[i];
620c1a5e521SShri Abhyankar   }
621c1a5e521SShri Abhyankar   ierr = VecRestoreArray(X,&x);CHKERRQ(ierr);
622c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
623c1a5e521SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
624c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
625c1a5e521SShri Abhyankar }
626c1a5e521SShri Abhyankar 
6272b4ed282SShri Abhyankar /*  --------------------------------------------------------------------
6282b4ed282SShri Abhyankar 
6292b4ed282SShri Abhyankar      This file implements a semismooth truncated Newton method with a line search,
6302b4ed282SShri Abhyankar      for solving a system of nonlinear equations in complementarity form, using the KSP, Vec,
6312b4ed282SShri Abhyankar      and Mat interfaces for linear solvers, vectors, and matrices,
6322b4ed282SShri Abhyankar      respectively.
6332b4ed282SShri Abhyankar 
6342b4ed282SShri Abhyankar      The following basic routines are required for each nonlinear solver:
6352b4ed282SShri Abhyankar           SNESCreate_XXX()          - Creates a nonlinear solver context
6362b4ed282SShri Abhyankar           SNESSetFromOptions_XXX()  - Sets runtime options
6372b4ed282SShri Abhyankar           SNESSolve_XXX()           - Solves the nonlinear system
6382b4ed282SShri Abhyankar           SNESDestroy_XXX()         - Destroys the nonlinear solver context
6392b4ed282SShri Abhyankar      The suffix "_XXX" denotes a particular implementation, in this case
6402b4ed282SShri Abhyankar      we use _VI (e.g., SNESCreate_VI, SNESSolve_VI) for solving
6412b4ed282SShri Abhyankar      systems of nonlinear equations with a line search (LS) method.
6422b4ed282SShri Abhyankar      These routines are actually called via the common user interface
6432b4ed282SShri Abhyankar      routines SNESCreate(), SNESSetFromOptions(), SNESSolve(), and
6442b4ed282SShri Abhyankar      SNESDestroy(), so the application code interface remains identical
6452b4ed282SShri Abhyankar      for all nonlinear solvers.
6462b4ed282SShri Abhyankar 
6472b4ed282SShri Abhyankar      Another key routine is:
6482b4ed282SShri Abhyankar           SNESSetUp_XXX()           - Prepares for the use of a nonlinear solver
6492b4ed282SShri Abhyankar      by setting data structures and options.   The interface routine SNESSetUp()
6502b4ed282SShri Abhyankar      is not usually called directly by the user, but instead is called by
6512b4ed282SShri Abhyankar      SNESSolve() if necessary.
6522b4ed282SShri Abhyankar 
6532b4ed282SShri Abhyankar      Additional basic routines are:
6542b4ed282SShri Abhyankar           SNESView_XXX()            - Prints details of runtime options that
6552b4ed282SShri Abhyankar                                       have actually been used.
6562b4ed282SShri Abhyankar      These are called by application codes via the interface routines
6572b4ed282SShri Abhyankar      SNESView().
6582b4ed282SShri Abhyankar 
6592b4ed282SShri Abhyankar      The various types of solvers (preconditioners, Krylov subspace methods,
6602b4ed282SShri Abhyankar      nonlinear solvers, timesteppers) are all organized similarly, so the
6612b4ed282SShri Abhyankar      above description applies to these categories also.
6622b4ed282SShri Abhyankar 
6632b4ed282SShri Abhyankar     -------------------------------------------------------------------- */
6642b4ed282SShri Abhyankar /*
66569c03620SShri Abhyankar    SNESSolveVI_SS - Solves the complementarity problem with a semismooth Newton
6662b4ed282SShri Abhyankar    method using a line search.
6672b4ed282SShri Abhyankar 
6682b4ed282SShri Abhyankar    Input Parameters:
6692b4ed282SShri Abhyankar .  snes - the SNES context
6702b4ed282SShri Abhyankar 
6712b4ed282SShri Abhyankar    Output Parameter:
6722b4ed282SShri Abhyankar .  outits - number of iterations until termination
6732b4ed282SShri Abhyankar 
6742b4ed282SShri Abhyankar    Application Interface Routine: SNESSolve()
6752b4ed282SShri Abhyankar 
6762b4ed282SShri Abhyankar    Notes:
6772b4ed282SShri Abhyankar    This implements essentially a semismooth Newton method with a
67851defd01SShri Abhyankar    line search. The default line search does not do any line seach
67951defd01SShri Abhyankar    but rather takes a full newton step.
6802b4ed282SShri Abhyankar */
6812b4ed282SShri Abhyankar #undef __FUNCT__
68269c03620SShri Abhyankar #define __FUNCT__ "SNESSolveVI_SS"
68369c03620SShri Abhyankar PetscErrorCode SNESSolveVI_SS(SNES snes)
6842b4ed282SShri Abhyankar {
6852b4ed282SShri Abhyankar   SNES_VI            *vi = (SNES_VI*)snes->data;
6862b4ed282SShri Abhyankar   PetscErrorCode     ierr;
6872b4ed282SShri Abhyankar   PetscInt           maxits,i,lits;
6883b336b49SShri Abhyankar   PetscBool          lssucceed;
6892b4ed282SShri Abhyankar   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
6902b4ed282SShri Abhyankar   PetscReal          gnorm,xnorm=0,ynorm;
6912b4ed282SShri Abhyankar   Vec                Y,X,F,G,W;
6922b4ed282SShri Abhyankar   KSPConvergedReason kspreason;
6932b4ed282SShri Abhyankar 
6942b4ed282SShri Abhyankar   PetscFunctionBegin;
6959ce7406fSBarry Smith   vi->computeuserfunction    = snes->ops->computefunction;
6969ce7406fSBarry Smith   snes->ops->computefunction = SNESVIComputeFunction;
6979ce7406fSBarry Smith 
6982b4ed282SShri Abhyankar   snes->numFailures            = 0;
6992b4ed282SShri Abhyankar   snes->numLinearSolveFailures = 0;
7002b4ed282SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
7012b4ed282SShri Abhyankar 
7022b4ed282SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
7032b4ed282SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
7042b4ed282SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
7052b4ed282SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
7062b4ed282SShri Abhyankar   G		= snes->work[1];
7072b4ed282SShri Abhyankar   W		= snes->work[2];
7082b4ed282SShri Abhyankar 
7092b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7102b4ed282SShri Abhyankar   snes->iter = 0;
7112b4ed282SShri Abhyankar   snes->norm = 0.0;
7122b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7132b4ed282SShri Abhyankar 
7147fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
7152b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,X,vi->phi);CHKERRQ(ierr);
7162b4ed282SShri Abhyankar   if (snes->domainerror) {
7172b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7189ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7192b4ed282SShri Abhyankar     PetscFunctionReturn(0);
7202b4ed282SShri Abhyankar   }
7212b4ed282SShri Abhyankar    /* Compute Merit function */
7222b4ed282SShri Abhyankar   ierr = SNESVIComputeMeritFunction(vi->phi,&vi->merit,&vi->phinorm);CHKERRQ(ierr);
7232b4ed282SShri Abhyankar 
7242b4ed282SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
7252b4ed282SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
72662cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(vi->merit)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
7272b4ed282SShri Abhyankar 
7282b4ed282SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
7292b4ed282SShri Abhyankar   snes->norm = vi->phinorm;
7302b4ed282SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
7312b4ed282SShri Abhyankar   SNESLogConvHistory(snes,vi->phinorm,0);
7327a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,vi->phinorm);CHKERRQ(ierr);
7332b4ed282SShri Abhyankar 
7342b4ed282SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
7352b4ed282SShri Abhyankar   snes->ttol = vi->phinorm*snes->rtol;
7362b4ed282SShri Abhyankar   /* test convergence */
7372b4ed282SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
7389ce7406fSBarry Smith   if (snes->reason) {
7399ce7406fSBarry Smith     snes->ops->computefunction = vi->computeuserfunction;
7409ce7406fSBarry Smith     PetscFunctionReturn(0);
7419ce7406fSBarry Smith   }
7422b4ed282SShri Abhyankar 
7432b4ed282SShri Abhyankar   for (i=0; i<maxits; i++) {
7442b4ed282SShri Abhyankar 
7452b4ed282SShri Abhyankar     /* Call general purpose update function */
7462b4ed282SShri Abhyankar     if (snes->ops->update) {
7472b4ed282SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
7482b4ed282SShri Abhyankar     }
7492b4ed282SShri Abhyankar 
7502b4ed282SShri Abhyankar     /* Solve J Y = Phi, where J is the semismooth jacobian */
751a79edbefSShri Abhyankar     /* Get the nonlinear function jacobian */
7522b4ed282SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
753a79edbefSShri Abhyankar     /* Get the diagonal shift and row scaling vectors */
754a79edbefSShri Abhyankar     ierr = SNESVIComputeBsubdifferentialVectors(snes,X,F,snes->jacobian,vi->Da,vi->Db);CHKERRQ(ierr);
755a79edbefSShri Abhyankar     /* Compute the semismooth jacobian */
756a79edbefSShri Abhyankar     ierr = SNESVIComputeJacobian(snes->jacobian,snes->jacobian_pre,vi->Da,vi->Db);CHKERRQ(ierr);
757ee657d29SShri Abhyankar     /* Compute the merit function gradient */
758ee657d29SShri Abhyankar     ierr = SNESVIComputeMeritFunctionGradient(snes->jacobian,vi->phi,vi->dpsi);CHKERRQ(ierr);
7592b4ed282SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre,flg);CHKERRQ(ierr);
7602b4ed282SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,vi->phi,Y);CHKERRQ(ierr);
7612b4ed282SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
7623b336b49SShri Abhyankar 
7633b336b49SShri Abhyankar     if (kspreason < 0) {
7642b4ed282SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
7652b4ed282SShri 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);
7662b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
7672b4ed282SShri Abhyankar         break;
7682b4ed282SShri Abhyankar       }
7692b4ed282SShri Abhyankar     }
7702b4ed282SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
7712b4ed282SShri Abhyankar     snes->linear_its += lits;
7722b4ed282SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
7732b4ed282SShri Abhyankar     /*
7742b4ed282SShri Abhyankar     if (vi->precheckstep) {
775ace3abfcSBarry Smith       PetscBool changed_y = PETSC_FALSE;
7762b4ed282SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
7772b4ed282SShri Abhyankar     }
7782b4ed282SShri Abhyankar 
7792b4ed282SShri Abhyankar     if (PetscLogPrintInfo){
7802b4ed282SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
7812b4ed282SShri Abhyankar     }
7822b4ed282SShri Abhyankar     */
7832b4ed282SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
7842b4ed282SShri Abhyankar          Y <- X - lambda*Y
7852b4ed282SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
7862b4ed282SShri Abhyankar     */
7872b4ed282SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
7882b4ed282SShri Abhyankar     ynorm = 1; gnorm = vi->phinorm;
7892b4ed282SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,vi->phi,G,Y,W,vi->phinorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
7902b4ed282SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",vi->phinorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
7912b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
7922b4ed282SShri Abhyankar     if (snes->domainerror) {
7932b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
7949ce7406fSBarry Smith       snes->ops->computefunction = vi->computeuserfunction;
7952b4ed282SShri Abhyankar       PetscFunctionReturn(0);
7962b4ed282SShri Abhyankar     }
7972b4ed282SShri Abhyankar     if (!lssucceed) {
7982b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
799ace3abfcSBarry Smith 	PetscBool ismin;
8002b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
8012b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
8022b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
8032b4ed282SShri Abhyankar         break;
8042b4ed282SShri Abhyankar       }
8052b4ed282SShri Abhyankar     }
8062b4ed282SShri Abhyankar     /* Update function and solution vectors */
8072b4ed282SShri Abhyankar     vi->phinorm = gnorm;
8082b4ed282SShri Abhyankar     vi->merit = 0.5*vi->phinorm*vi->phinorm;
8092b4ed282SShri Abhyankar     ierr = VecCopy(G,vi->phi);CHKERRQ(ierr);
8102b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
8112b4ed282SShri Abhyankar     /* Monitor convergence */
8122b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
8132b4ed282SShri Abhyankar     snes->iter = i+1;
8142b4ed282SShri Abhyankar     snes->norm = vi->phinorm;
8152b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
8162b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
8177a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
8182b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
8192b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
8202b4ed282SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,vi->phinorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
8212b4ed282SShri Abhyankar     if (snes->reason) break;
8222b4ed282SShri Abhyankar   }
8232b4ed282SShri Abhyankar   if (i == maxits) {
8242b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
8252b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
8262b4ed282SShri Abhyankar   }
8279ce7406fSBarry Smith   snes->ops->computefunction = vi->computeuserfunction;
8282b4ed282SShri Abhyankar   PetscFunctionReturn(0);
8292b4ed282SShri Abhyankar }
83069c03620SShri Abhyankar 
83169c03620SShri Abhyankar #undef __FUNCT__
832693ddf92SShri Abhyankar #define __FUNCT__ "SNESVIGetActiveSetIS"
833693ddf92SShri Abhyankar /*
834693ddf92SShri Abhyankar    SNESVIGetActiveSetIndices - Gets the global indices for the active set variables
835693ddf92SShri Abhyankar 
836693ddf92SShri Abhyankar    Input parameter
837693ddf92SShri Abhyankar .  snes - the SNES context
838693ddf92SShri Abhyankar .  X    - the snes solution vector
839693ddf92SShri Abhyankar .  F    - the nonlinear function vector
840693ddf92SShri Abhyankar 
841693ddf92SShri Abhyankar    Output parameter
842693ddf92SShri Abhyankar .  ISact - active set index set
843693ddf92SShri Abhyankar  */
844693ddf92SShri Abhyankar PetscErrorCode SNESVIGetActiveSetIS(SNES snes,Vec X,Vec F,IS* ISact)
845d950fb63SShri Abhyankar {
846d950fb63SShri Abhyankar   PetscErrorCode   ierr;
847693ddf92SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
848693ddf92SShri Abhyankar   Vec               Xl=vi->xl,Xu=vi->xu;
849693ddf92SShri Abhyankar   const PetscScalar *x,*f,*xl,*xu;
850693ddf92SShri Abhyankar   PetscInt          *idx_act,i,nlocal,nloc_isact=0,ilow,ihigh,i1=0;
851d950fb63SShri Abhyankar 
852d950fb63SShri Abhyankar   PetscFunctionBegin;
853d950fb63SShri Abhyankar   ierr = VecGetLocalSize(X,&nlocal);CHKERRQ(ierr);
854d950fb63SShri Abhyankar   ierr = VecGetOwnershipRange(X,&ilow,&ihigh);CHKERRQ(ierr);
855fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
856fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xl,&xl);CHKERRQ(ierr);
857fe835674SShri Abhyankar   ierr = VecGetArrayRead(Xu,&xu);CHKERRQ(ierr);
858fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
859693ddf92SShri Abhyankar   /* Compute active set size */
860d950fb63SShri Abhyankar   for (i=0; i < nlocal;i++) {
86110f5ae6bSBarry 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++;
862d950fb63SShri Abhyankar   }
863693ddf92SShri Abhyankar 
864d950fb63SShri Abhyankar   ierr = PetscMalloc(nloc_isact*sizeof(PetscInt),&idx_act);CHKERRQ(ierr);
865d950fb63SShri Abhyankar 
866693ddf92SShri Abhyankar   /* Set active set indices */
867d950fb63SShri Abhyankar   for(i=0; i < nlocal; i++) {
86810f5ae6bSBarry 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;
869d950fb63SShri Abhyankar   }
870d950fb63SShri Abhyankar 
871693ddf92SShri Abhyankar    /* Create active set IS */
87262298a1eSBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,nloc_isact,idx_act,PETSC_OWN_POINTER,ISact);CHKERRQ(ierr);
873d950fb63SShri Abhyankar 
874fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
875fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xl,&xl);CHKERRQ(ierr);
876fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(Xu,&xu);CHKERRQ(ierr);
877fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
878d950fb63SShri Abhyankar   PetscFunctionReturn(0);
879d950fb63SShri Abhyankar }
880d950fb63SShri Abhyankar 
881693ddf92SShri Abhyankar #undef __FUNCT__
882693ddf92SShri Abhyankar #define __FUNCT__ "SNESVICreateIndexSets_RS"
883693ddf92SShri Abhyankar PetscErrorCode SNESVICreateIndexSets_RS(SNES snes,Vec X,Vec F,IS* ISact,IS* ISinact)
884693ddf92SShri Abhyankar {
885693ddf92SShri Abhyankar   PetscErrorCode     ierr;
886693ddf92SShri Abhyankar 
887693ddf92SShri Abhyankar   PetscFunctionBegin;
888693ddf92SShri Abhyankar   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
889693ddf92SShri Abhyankar   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
890693ddf92SShri Abhyankar   PetscFunctionReturn(0);
891693ddf92SShri Abhyankar }
892693ddf92SShri Abhyankar 
893dbd914b8SShri Abhyankar /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
894dbd914b8SShri Abhyankar #undef __FUNCT__
895fe835674SShri Abhyankar #define __FUNCT__ "SNESVICreateSubVectors"
896fe835674SShri Abhyankar PetscErrorCode SNESVICreateSubVectors(SNES snes,PetscInt n,Vec* newv)
897dbd914b8SShri Abhyankar {
898dbd914b8SShri Abhyankar   PetscErrorCode ierr;
899dbd914b8SShri Abhyankar   Vec            v;
900dbd914b8SShri Abhyankar 
901dbd914b8SShri Abhyankar   PetscFunctionBegin;
902dbd914b8SShri Abhyankar   ierr = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
903dbd914b8SShri Abhyankar   ierr = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
904dbd914b8SShri Abhyankar   ierr = VecSetFromOptions(v);CHKERRQ(ierr);
905dbd914b8SShri Abhyankar   *newv = v;
906dbd914b8SShri Abhyankar 
907dbd914b8SShri Abhyankar   PetscFunctionReturn(0);
908dbd914b8SShri Abhyankar }
909dbd914b8SShri Abhyankar 
910732bb160SShri Abhyankar /* Resets the snes PC and KSP when the active set sizes change */
911732bb160SShri Abhyankar #undef __FUNCT__
912732bb160SShri Abhyankar #define __FUNCT__ "SNESVIResetPCandKSP"
913732bb160SShri Abhyankar PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
914732bb160SShri Abhyankar {
915732bb160SShri Abhyankar   PetscErrorCode         ierr;
916d0af7cd3SBarry Smith   KSP                    snesksp;
917dbd914b8SShri Abhyankar 
918732bb160SShri Abhyankar   PetscFunctionBegin;
919732bb160SShri Abhyankar   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
920d0af7cd3SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
921c2efdce3SBarry Smith 
922c2efdce3SBarry Smith   /*
923d0af7cd3SBarry Smith   KSP                    kspnew;
924d0af7cd3SBarry Smith   PC                     pcnew;
925d0af7cd3SBarry Smith   const MatSolverPackage stype;
926d0af7cd3SBarry Smith 
927c2efdce3SBarry Smith 
928732bb160SShri Abhyankar   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
929732bb160SShri Abhyankar   kspnew->pc_side = snesksp->pc_side;
930732bb160SShri Abhyankar   kspnew->rtol    = snesksp->rtol;
931732bb160SShri Abhyankar   kspnew->abstol    = snesksp->abstol;
932732bb160SShri Abhyankar   kspnew->max_it  = snesksp->max_it;
933732bb160SShri Abhyankar   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
934732bb160SShri Abhyankar   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
935732bb160SShri Abhyankar   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
936732bb160SShri Abhyankar   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
937732bb160SShri Abhyankar   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
938732bb160SShri Abhyankar   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
9396bf464f9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
940732bb160SShri Abhyankar   snes->ksp = kspnew;
941732bb160SShri Abhyankar   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
942d0af7cd3SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
943732bb160SShri Abhyankar   PetscFunctionReturn(0);
944732bb160SShri Abhyankar }
94569c03620SShri Abhyankar 
94669c03620SShri Abhyankar 
947fe835674SShri Abhyankar #undef __FUNCT__
948fe835674SShri Abhyankar #define __FUNCT__ "SNESVIComputeInactiveSetFnorm"
94910f5ae6bSBarry Smith PetscErrorCode SNESVIComputeInactiveSetFnorm(SNES snes,Vec F,Vec X,PetscReal *fnorm)
950fe835674SShri Abhyankar {
951fe835674SShri Abhyankar   PetscErrorCode    ierr;
952fe835674SShri Abhyankar   SNES_VI           *vi = (SNES_VI*)snes->data;
953fe835674SShri Abhyankar   const PetscScalar *x,*xl,*xu,*f;
954fe835674SShri Abhyankar   PetscInt          i,n;
955fe835674SShri Abhyankar   PetscReal         rnorm;
956fe835674SShri Abhyankar 
957fe835674SShri Abhyankar   PetscFunctionBegin;
958fe835674SShri Abhyankar   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
959fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xl,&xl);CHKERRQ(ierr);
960fe835674SShri Abhyankar   ierr = VecGetArrayRead(vi->xu,&xu);CHKERRQ(ierr);
961fe835674SShri Abhyankar   ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
962fe835674SShri Abhyankar   ierr = VecGetArrayRead(F,&f);CHKERRQ(ierr);
963fe835674SShri Abhyankar   rnorm = 0.0;
964fe835674SShri Abhyankar   for (i=0; i<n; i++) {
96510f5ae6bSBarry 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]);
966fe835674SShri Abhyankar   }
967fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(F,&f);CHKERRQ(ierr);
968fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xl,&xl);CHKERRQ(ierr);
969fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(vi->xu,&xu);CHKERRQ(ierr);
970fe835674SShri Abhyankar   ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
971d9822059SBarry Smith   ierr = MPI_Allreduce(&rnorm,fnorm,1,MPIU_REAL,MPIU_SUM,((PetscObject)snes)->comm);CHKERRQ(ierr);
972fe835674SShri Abhyankar   *fnorm = sqrt(*fnorm);
973fe835674SShri Abhyankar   PetscFunctionReturn(0);
974fe835674SShri Abhyankar }
975fe835674SShri Abhyankar 
976fe835674SShri Abhyankar /* Variational Inequality solver using reduce space method. No semismooth algorithm is
977c2efdce3SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
978c2efdce3SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
979d950fb63SShri Abhyankar #undef __FUNCT__
980d950fb63SShri Abhyankar #define __FUNCT__ "SNESSolveVI_RS"
981d950fb63SShri Abhyankar PetscErrorCode SNESSolveVI_RS(SNES snes)
982d950fb63SShri Abhyankar {
983d950fb63SShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
984d950fb63SShri Abhyankar   PetscErrorCode    ierr;
985abcba341SShri Abhyankar   PetscInt          maxits,i,lits;
986d950fb63SShri Abhyankar   PetscBool         lssucceed;
987d950fb63SShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
988fe835674SShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
989d950fb63SShri Abhyankar   Vec                Y,X,F,G,W;
990d950fb63SShri Abhyankar   KSPConvergedReason kspreason;
991d950fb63SShri Abhyankar 
992d950fb63SShri Abhyankar   PetscFunctionBegin;
993d950fb63SShri Abhyankar   snes->numFailures            = 0;
994d950fb63SShri Abhyankar   snes->numLinearSolveFailures = 0;
995d950fb63SShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
996d950fb63SShri Abhyankar 
997d950fb63SShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
998d950fb63SShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
999d950fb63SShri Abhyankar   F		= snes->vec_func;	/* residual vector */
1000d950fb63SShri Abhyankar   Y		= snes->work[0];	/* work vectors */
1001d950fb63SShri Abhyankar   G		= snes->work[1];
1002d950fb63SShri Abhyankar   W		= snes->work[2];
1003d950fb63SShri Abhyankar 
1004d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1005d950fb63SShri Abhyankar   snes->iter = 0;
1006d950fb63SShri Abhyankar   snes->norm = 0.0;
1007d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1008d950fb63SShri Abhyankar 
10097fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
1010fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
1011d950fb63SShri Abhyankar   if (snes->domainerror) {
1012d950fb63SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
1013d950fb63SShri Abhyankar     PetscFunctionReturn(0);
1014d950fb63SShri Abhyankar   }
1015fe835674SShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
1016d950fb63SShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
1017d950fb63SShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
101862cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1019d950fb63SShri Abhyankar 
1020d950fb63SShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
1021fe835674SShri Abhyankar   snes->norm = fnorm;
1022d950fb63SShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
1023fe835674SShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
10247a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
1025d950fb63SShri Abhyankar 
1026d950fb63SShri Abhyankar   /* set parameter for default relative tolerance convergence test */
1027fe835674SShri Abhyankar   snes->ttol = fnorm*snes->rtol;
1028d950fb63SShri Abhyankar   /* test convergence */
1029fe835674SShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
1030d950fb63SShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
1031d950fb63SShri Abhyankar 
1032d950fb63SShri Abhyankar   for (i=0; i<maxits; i++) {
1033d950fb63SShri Abhyankar 
1034d950fb63SShri Abhyankar     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1035d950fb63SShri Abhyankar     VecScatter scat_act,scat_inact;
1036abcba341SShri Abhyankar     PetscInt   nis_act,nis_inact;
1037fe835674SShri Abhyankar     Vec        Y_act,Y_inact,F_inact;
1038d950fb63SShri Abhyankar     Mat        jac_inact_inact,prejac_inact_inact;
103962298a1eSBarry Smith     IS         keptrows;
1040abcba341SShri Abhyankar     PetscBool  isequal;
1041d950fb63SShri Abhyankar 
1042d950fb63SShri Abhyankar     /* Call general purpose update function */
1043d950fb63SShri Abhyankar     if (snes->ops->update) {
1044d950fb63SShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
1045d950fb63SShri Abhyankar     }
1046d950fb63SShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
104762298a1eSBarry Smith 
1048d950fb63SShri Abhyankar     /* Create active and inactive index sets */
1049693ddf92SShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
1050d950fb63SShri Abhyankar 
10514dcab191SBarry Smith     ierr = DMSetVI(snes->dm,vi->xu,vi->xl,X,F,IS_inact);CHKERRQ(ierr);
10524dcab191SBarry Smith 
10534dcab191SBarry Smith 
1054abcba341SShri Abhyankar     /* Create inactive set submatrix */
105562298a1eSBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
1056b3a44c85SBarry Smith     ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
105762298a1eSBarry Smith     if (keptrows) {
105862298a1eSBarry Smith       PetscInt       cnt,*nrows,k;
105962298a1eSBarry Smith       const PetscInt *krows,*inact;
106027d4218bSShri Abhyankar       PetscInt       rstart=jac_inact_inact->rmap->rstart;
106162298a1eSBarry Smith 
10626bf464f9SBarry Smith       ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
10636bf464f9SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
106462298a1eSBarry Smith 
106562298a1eSBarry Smith       ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
106662298a1eSBarry Smith       ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
106762298a1eSBarry Smith       ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
106862298a1eSBarry Smith       ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
106962298a1eSBarry Smith       for (k=0; k<cnt; k++) {
107027d4218bSShri Abhyankar         nrows[k] = inact[krows[k]-rstart];
107162298a1eSBarry Smith       }
107262298a1eSBarry Smith       ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
107362298a1eSBarry Smith       ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
10746bf464f9SBarry Smith       ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
10756bf464f9SBarry Smith       ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
107662298a1eSBarry Smith 
107727d4218bSShri Abhyankar       ierr = ISCreateGeneral(PETSC_COMM_WORLD,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
107827d4218bSShri Abhyankar       ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
107962298a1eSBarry Smith       ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
108062298a1eSBarry Smith     }
108162298a1eSBarry Smith 
1082d950fb63SShri Abhyankar     /* Get sizes of active and inactive sets */
1083d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
1084d950fb63SShri Abhyankar     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
1085d950fb63SShri Abhyankar 
1086d950fb63SShri Abhyankar     /* Create active and inactive set vectors */
1087fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&F_inact);CHKERRQ(ierr);
1088fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_act,&Y_act);CHKERRQ(ierr);
1089fe835674SShri Abhyankar     ierr = SNESVICreateSubVectors(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
1090d950fb63SShri Abhyankar 
1091d950fb63SShri Abhyankar     /* Create scatter contexts */
1092d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_act,Y_act,PETSC_NULL,&scat_act);CHKERRQ(ierr);
1093d950fb63SShri Abhyankar     ierr = VecScatterCreate(Y,IS_inact,Y_inact,PETSC_NULL,&scat_inact);CHKERRQ(ierr);
1094d950fb63SShri Abhyankar 
1095d950fb63SShri Abhyankar     /* Do a vec scatter to active and inactive set vectors */
1096fe835674SShri Abhyankar     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1097fe835674SShri Abhyankar     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1098d950fb63SShri Abhyankar 
1099d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1100d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1101d950fb63SShri Abhyankar 
1102d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1103d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1104d950fb63SShri Abhyankar 
1105d950fb63SShri Abhyankar     /* Active set direction = 0 */
1106d950fb63SShri Abhyankar     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
1107d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
1108d950fb63SShri Abhyankar       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
1109d950fb63SShri Abhyankar     } else prejac_inact_inact = jac_inact_inact;
1110d950fb63SShri Abhyankar 
1111abcba341SShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
1112abcba341SShri Abhyankar     if (!isequal) {
1113732bb160SShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
1114d950fb63SShri Abhyankar     }
1115d950fb63SShri Abhyankar 
111613e0d083SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
111713e0d083SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
111813e0d083SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
111913e0d083SBarry Smith 
1120d950fb63SShri Abhyankar     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
112113e0d083SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
112213e0d083SBarry Smith     {
112313e0d083SBarry Smith       PC        pc;
112413e0d083SBarry Smith       PetscBool flg;
112513e0d083SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
112613e0d083SBarry Smith       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
112713e0d083SBarry Smith       if (flg) {
112813e0d083SBarry Smith         KSP      *subksps;
112913e0d083SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
113013e0d083SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
113113e0d083SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
113213e0d083SBarry Smith         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
113313e0d083SBarry Smith         if (flg) {
113413e0d083SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
113513e0d083SBarry Smith           const PetscInt *ii;
113613e0d083SBarry Smith 
113713e0d083SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
113813e0d083SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
113913e0d083SBarry Smith           for (j=0; j<n; j++) {
114013e0d083SBarry Smith             if (ii[j] < N) cnts[0]++;
114113e0d083SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
114213e0d083SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
114313e0d083SBarry Smith           }
114413e0d083SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
114513e0d083SBarry Smith 
114613e0d083SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
114713e0d083SBarry Smith         }
114813e0d083SBarry Smith       }
114913e0d083SBarry Smith     }
115013e0d083SBarry Smith 
1151fe835674SShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
1152d950fb63SShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
1153d950fb63SShri Abhyankar     if (kspreason < 0) {
1154d950fb63SShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
1155d950fb63SShri 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);
1156d950fb63SShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
1157d950fb63SShri Abhyankar         break;
1158d950fb63SShri Abhyankar       }
1159d950fb63SShri Abhyankar      }
1160d950fb63SShri Abhyankar 
1161d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1162d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1163d950fb63SShri Abhyankar     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1164d950fb63SShri Abhyankar     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1165d950fb63SShri Abhyankar 
11666bf464f9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
11676bf464f9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
11686bf464f9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
11696bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
11706bf464f9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
11716bf464f9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
1172abcba341SShri Abhyankar     if (!isequal) {
11736bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
1174abcba341SShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
1175abcba341SShri Abhyankar     }
11766bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
11776bf464f9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
1178d950fb63SShri Abhyankar     if (snes->jacobian != snes->jacobian_pre) {
11796bf464f9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
1180d950fb63SShri Abhyankar     }
1181d950fb63SShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
1182d950fb63SShri Abhyankar     snes->linear_its += lits;
1183d950fb63SShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
1184d950fb63SShri Abhyankar     /*
1185d950fb63SShri Abhyankar     if (vi->precheckstep) {
1186d950fb63SShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
1187d950fb63SShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
1188d950fb63SShri Abhyankar     }
1189d950fb63SShri Abhyankar 
1190d950fb63SShri Abhyankar     if (PetscLogPrintInfo){
1191d950fb63SShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
1192d950fb63SShri Abhyankar     }
1193d950fb63SShri Abhyankar     */
1194d950fb63SShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
1195d950fb63SShri Abhyankar          Y <- X - lambda*Y
1196d950fb63SShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
1197d950fb63SShri Abhyankar     */
1198d950fb63SShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
1199fe835674SShri Abhyankar     ynorm = 1; gnorm = fnorm;
1200fe835674SShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
1201fe835674SShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
12022b4ed282SShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
12032b4ed282SShri Abhyankar     if (snes->domainerror) {
12042b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
12052b4ed282SShri Abhyankar       PetscFunctionReturn(0);
12062b4ed282SShri Abhyankar     }
12072b4ed282SShri Abhyankar     if (!lssucceed) {
12082b4ed282SShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
12092b4ed282SShri Abhyankar 	PetscBool ismin;
12102b4ed282SShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
12112b4ed282SShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
12122b4ed282SShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
12132b4ed282SShri Abhyankar         break;
12142b4ed282SShri Abhyankar       }
12152b4ed282SShri Abhyankar     }
12162b4ed282SShri Abhyankar     /* Update function and solution vectors */
1217fe835674SShri Abhyankar     fnorm = gnorm;
1218fe835674SShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
12192b4ed282SShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
12202b4ed282SShri Abhyankar     /* Monitor convergence */
12212b4ed282SShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
12222b4ed282SShri Abhyankar     snes->iter = i+1;
1223fe835674SShri Abhyankar     snes->norm = fnorm;
12242b4ed282SShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
12252b4ed282SShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
12267a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
12272b4ed282SShri Abhyankar     /* Test for convergence, xnorm = || X || */
12282b4ed282SShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
1229fe835674SShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
12302b4ed282SShri Abhyankar     if (snes->reason) break;
12312b4ed282SShri Abhyankar   }
12322b4ed282SShri Abhyankar   if (i == maxits) {
12332b4ed282SShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
12342b4ed282SShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
12352b4ed282SShri Abhyankar   }
12362b4ed282SShri Abhyankar   PetscFunctionReturn(0);
12372b4ed282SShri Abhyankar }
12382b4ed282SShri Abhyankar 
12392f63a38cSShri Abhyankar #undef __FUNCT__
1240720c9a41SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheck"
1241cb5fe31bSShri Abhyankar PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
12422f63a38cSShri Abhyankar {
12432f63a38cSShri Abhyankar   SNES_VI         *vi = (SNES_VI*)snes->data;
12442f63a38cSShri Abhyankar 
12452f63a38cSShri Abhyankar   PetscFunctionBegin;
12462f63a38cSShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
12472f63a38cSShri Abhyankar   vi->checkredundancy = func;
1248cb5fe31bSShri Abhyankar   vi->ctxP            = ctx;
12492f63a38cSShri Abhyankar   PetscFunctionReturn(0);
12502f63a38cSShri Abhyankar }
12512f63a38cSShri Abhyankar 
1252ff596062SShri Abhyankar #if defined(PETSC_HAVE_MATLAB_ENGINE)
1253ff596062SShri Abhyankar #include <engine.h>
1254ff596062SShri Abhyankar #include <mex.h>
1255cb5fe31bSShri Abhyankar typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
1256ff596062SShri Abhyankar 
1257ff596062SShri Abhyankar #undef __FUNCT__
1258ff596062SShri Abhyankar #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
1259ff596062SShri Abhyankar PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS* is_redact,void* ctx)
1260ff596062SShri Abhyankar {
1261ff596062SShri Abhyankar   PetscErrorCode      ierr;
1262cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx = (SNESMatlabContext*)ctx;
1263cb5fe31bSShri Abhyankar   int                 nlhs = 1, nrhs = 5;
1264cb5fe31bSShri Abhyankar   mxArray             *plhs[1], *prhs[5];
1265cb5fe31bSShri Abhyankar   long long int       l1 = 0, l2 = 0, ls = 0;
1266fcb1c9afSShri Abhyankar   PetscInt            *indices=PETSC_NULL;
1267ff596062SShri Abhyankar 
1268ff596062SShri Abhyankar   PetscFunctionBegin;
1269ff596062SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
1270ff596062SShri Abhyankar   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
1271ff596062SShri Abhyankar   PetscValidPointer(is_redact,3);
1272ff596062SShri Abhyankar   PetscCheckSameComm(snes,1,is_act,2);
1273ff596062SShri Abhyankar 
127409db5ad8SShri Abhyankar   /* Create IS for reduced active set of size 0, its size and indices will
127509db5ad8SShri Abhyankar    bet set by the Matlab function */
1276fcb1c9afSShri Abhyankar   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
1277cb5fe31bSShri Abhyankar   /* call Matlab function in ctx */
1278ff596062SShri Abhyankar   ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
1279ff596062SShri Abhyankar   ierr = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
1280cb5fe31bSShri Abhyankar   ierr = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
1281ff596062SShri Abhyankar   prhs[0] = mxCreateDoubleScalar((double)ls);
1282ff596062SShri Abhyankar   prhs[1] = mxCreateDoubleScalar((double)l1);
1283cb5fe31bSShri Abhyankar   prhs[2] = mxCreateDoubleScalar((double)l2);
1284cb5fe31bSShri Abhyankar   prhs[3] = mxCreateString(sctx->funcname);
1285cb5fe31bSShri Abhyankar   prhs[4] = sctx->ctx;
1286ff596062SShri Abhyankar   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
1287ff596062SShri Abhyankar   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
1288ff596062SShri Abhyankar   mxDestroyArray(prhs[0]);
1289ff596062SShri Abhyankar   mxDestroyArray(prhs[1]);
1290ff596062SShri Abhyankar   mxDestroyArray(prhs[2]);
1291ff596062SShri Abhyankar   mxDestroyArray(prhs[3]);
1292ff596062SShri Abhyankar   mxDestroyArray(plhs[0]);
1293ff596062SShri Abhyankar   PetscFunctionReturn(0);
1294ff596062SShri Abhyankar }
1295ff596062SShri Abhyankar 
1296ff596062SShri Abhyankar #undef __FUNCT__
1297ff596062SShri Abhyankar #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
1298ff596062SShri Abhyankar PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char* func,mxArray* ctx)
1299ff596062SShri Abhyankar {
1300ff596062SShri Abhyankar   PetscErrorCode      ierr;
1301cb5fe31bSShri Abhyankar   SNESMatlabContext   *sctx;
1302ff596062SShri Abhyankar 
1303ff596062SShri Abhyankar   PetscFunctionBegin;
1304ff596062SShri Abhyankar   /* currently sctx is memory bleed */
1305cb5fe31bSShri Abhyankar   ierr = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
1306ff596062SShri Abhyankar   ierr = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
1307ff596062SShri Abhyankar   sctx->ctx = mxDuplicateArray(ctx);
1308cb5fe31bSShri Abhyankar   ierr = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
1309ff596062SShri Abhyankar   PetscFunctionReturn(0);
1310ff596062SShri Abhyankar }
1311ff596062SShri Abhyankar 
1312ff596062SShri Abhyankar #endif
1313ff596062SShri Abhyankar 
1314ff596062SShri Abhyankar 
13152f63a38cSShri Abhyankar /* Variational Inequality solver using augmented space method. It does the opposite of the
13162f63a38cSShri Abhyankar    reduced space method i.e. it identifies the active set variables and instead of discarding
1317720c9a41SShri Abhyankar    them it augments the original system by introducing additional equality
131856a221efSShri Abhyankar    constraint equations for active set variables. The user can optionally provide an IS for
131956a221efSShri Abhyankar    a subset of 'redundant' active set variables which will treated as free variables.
13202f63a38cSShri Abhyankar    Specific implementation for Allen-Cahn problem
13212f63a38cSShri Abhyankar */
13222f63a38cSShri Abhyankar #undef __FUNCT__
1323b350b9c9SBarry Smith #define __FUNCT__ "SNESSolveVI_RSAUG"
1324b350b9c9SBarry Smith PetscErrorCode SNESSolveVI_RSAUG(SNES snes)
13252f63a38cSShri Abhyankar {
13262f63a38cSShri Abhyankar   SNES_VI          *vi = (SNES_VI*)snes->data;
13272f63a38cSShri Abhyankar   PetscErrorCode    ierr;
13282f63a38cSShri Abhyankar   PetscInt          maxits,i,lits;
13292f63a38cSShri Abhyankar   PetscBool         lssucceed;
13302f63a38cSShri Abhyankar   MatStructure      flg = DIFFERENT_NONZERO_PATTERN;
13312f63a38cSShri Abhyankar   PetscReal         fnorm,gnorm,xnorm=0,ynorm;
13322f63a38cSShri Abhyankar   Vec                Y,X,F,G,W;
13332f63a38cSShri Abhyankar   KSPConvergedReason kspreason;
13342f63a38cSShri Abhyankar 
13352f63a38cSShri Abhyankar   PetscFunctionBegin;
13362f63a38cSShri Abhyankar   snes->numFailures            = 0;
13372f63a38cSShri Abhyankar   snes->numLinearSolveFailures = 0;
13382f63a38cSShri Abhyankar   snes->reason                 = SNES_CONVERGED_ITERATING;
13392f63a38cSShri Abhyankar 
13402f63a38cSShri Abhyankar   maxits	= snes->max_its;	/* maximum number of iterations */
13412f63a38cSShri Abhyankar   X		= snes->vec_sol;	/* solution vector */
13422f63a38cSShri Abhyankar   F		= snes->vec_func;	/* residual vector */
13432f63a38cSShri Abhyankar   Y		= snes->work[0];	/* work vectors */
13442f63a38cSShri Abhyankar   G		= snes->work[1];
13452f63a38cSShri Abhyankar   W		= snes->work[2];
13462f63a38cSShri Abhyankar 
13472f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13482f63a38cSShri Abhyankar   snes->iter = 0;
13492f63a38cSShri Abhyankar   snes->norm = 0.0;
13502f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13512f63a38cSShri Abhyankar 
13522f63a38cSShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
13532f63a38cSShri Abhyankar   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
13542f63a38cSShri Abhyankar   if (snes->domainerror) {
13552f63a38cSShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
13562f63a38cSShri Abhyankar     PetscFunctionReturn(0);
13572f63a38cSShri Abhyankar   }
13582f63a38cSShri Abhyankar   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
13592f63a38cSShri Abhyankar   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);	/* xnorm <- ||x||  */
13602f63a38cSShri Abhyankar   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
136162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
13622f63a38cSShri Abhyankar 
13632f63a38cSShri Abhyankar   ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
13642f63a38cSShri Abhyankar   snes->norm = fnorm;
13652f63a38cSShri Abhyankar   ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
13662f63a38cSShri Abhyankar   SNESLogConvHistory(snes,fnorm,0);
13677a03ce2fSLisandro Dalcin   ierr = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
13682f63a38cSShri Abhyankar 
13692f63a38cSShri Abhyankar   /* set parameter for default relative tolerance convergence test */
13702f63a38cSShri Abhyankar   snes->ttol = fnorm*snes->rtol;
13712f63a38cSShri Abhyankar   /* test convergence */
13722f63a38cSShri Abhyankar   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
13732f63a38cSShri Abhyankar   if (snes->reason) PetscFunctionReturn(0);
13742f63a38cSShri Abhyankar 
13752f63a38cSShri Abhyankar   for (i=0; i<maxits; i++) {
13762f63a38cSShri Abhyankar     IS             IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
1377cb5fe31bSShri Abhyankar     IS             IS_redact; /* redundant active set */
137856a221efSShri Abhyankar     Mat            J_aug,Jpre_aug;
137956a221efSShri Abhyankar     Vec            F_aug,Y_aug;
138056a221efSShri Abhyankar     PetscInt       nis_redact,nis_act;
138156a221efSShri Abhyankar     const PetscInt *idx_redact,*idx_act;
138256a221efSShri Abhyankar     PetscInt       k;
138363ee972cSSatish Balay     PetscInt       *idx_actkept=PETSC_NULL,nkept=0; /* list of kept active set */
138456a221efSShri Abhyankar     PetscScalar    *f,*f2;
13852f63a38cSShri Abhyankar     PetscBool      isequal;
138656a221efSShri Abhyankar     PetscInt       i1=0,j1=0;
13872f63a38cSShri Abhyankar 
13882f63a38cSShri Abhyankar     /* Call general purpose update function */
13892f63a38cSShri Abhyankar     if (snes->ops->update) {
13902f63a38cSShri Abhyankar       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
13912f63a38cSShri Abhyankar     }
13922f63a38cSShri Abhyankar     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
13932f63a38cSShri Abhyankar 
13942f63a38cSShri Abhyankar     /* Create active and inactive index sets */
13952f63a38cSShri Abhyankar     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
13962f63a38cSShri Abhyankar 
139756a221efSShri Abhyankar     /* Get local active set size */
13982f63a38cSShri Abhyankar     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
139956a221efSShri Abhyankar     if (nis_act) {
1400e63076c7SBarry Smith       ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
1401e63076c7SBarry Smith       IS_redact  = PETSC_NULL;
140256a221efSShri Abhyankar       if(vi->checkredundancy) {
1403cb5fe31bSShri Abhyankar 	(*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);
140456a221efSShri Abhyankar       }
14052f63a38cSShri Abhyankar 
140656a221efSShri Abhyankar       if(!IS_redact) {
140756a221efSShri Abhyankar 	/* User called checkredundancy function but didn't create IS_redact because
140856a221efSShri Abhyankar            there were no redundant active set variables */
140956a221efSShri Abhyankar 	/* Copy over all active set indices to the list */
141056a221efSShri Abhyankar 	ierr = PetscMalloc(nis_act*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
141156a221efSShri Abhyankar 	for(k=0;k < nis_act;k++) idx_actkept[k] = idx_act[k];
141256a221efSShri Abhyankar 	nkept = nis_act;
141356a221efSShri Abhyankar       } else {
141456a221efSShri Abhyankar 	ierr = ISGetLocalSize(IS_redact,&nis_redact);CHKERRQ(ierr);
141556a221efSShri Abhyankar 	ierr = PetscMalloc((nis_act-nis_redact)*sizeof(PetscInt),&idx_actkept);CHKERRQ(ierr);
14162f63a38cSShri Abhyankar 
141756a221efSShri Abhyankar 	/* Create reduced active set list */
141856a221efSShri Abhyankar 	ierr = ISGetIndices(IS_act,&idx_act);CHKERRQ(ierr);
141956a221efSShri Abhyankar 	ierr = ISGetIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1420cb5fe31bSShri Abhyankar 	j1 = 0;nkept = 0;
142156a221efSShri Abhyankar 	for(k=0;k<nis_act;k++) {
142256a221efSShri Abhyankar 	  if(j1 < nis_redact && idx_act[k] == idx_redact[j1]) j1++;
142356a221efSShri Abhyankar 	  else idx_actkept[nkept++] = idx_act[k];
142456a221efSShri Abhyankar 	}
142556a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
142656a221efSShri Abhyankar 	ierr = ISRestoreIndices(IS_redact,&idx_redact);CHKERRQ(ierr);
1427cb5fe31bSShri Abhyankar 
1428cb5fe31bSShri Abhyankar         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
142956a221efSShri Abhyankar       }
14302f63a38cSShri Abhyankar 
143156a221efSShri Abhyankar       /* Create augmented F and Y */
143256a221efSShri Abhyankar       ierr = VecCreate(((PetscObject)snes)->comm,&F_aug);CHKERRQ(ierr);
143356a221efSShri Abhyankar       ierr = VecSetSizes(F_aug,F->map->n+nkept,PETSC_DECIDE);CHKERRQ(ierr);
143456a221efSShri Abhyankar       ierr = VecSetFromOptions(F_aug);CHKERRQ(ierr);
143556a221efSShri Abhyankar       ierr = VecDuplicate(F_aug,&Y_aug);CHKERRQ(ierr);
14362f63a38cSShri Abhyankar 
143756a221efSShri Abhyankar       /* Copy over F to F_aug in the first n locations */
143856a221efSShri Abhyankar       ierr = VecGetArray(F,&f);CHKERRQ(ierr);
143956a221efSShri Abhyankar       ierr = VecGetArray(F_aug,&f2);CHKERRQ(ierr);
144056a221efSShri Abhyankar       ierr = PetscMemcpy(f2,f,F->map->n*sizeof(PetscScalar));CHKERRQ(ierr);
144156a221efSShri Abhyankar       ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
144256a221efSShri Abhyankar       ierr = VecRestoreArray(F_aug,&f2);CHKERRQ(ierr);
14432f63a38cSShri Abhyankar 
144456a221efSShri Abhyankar       /* Create the augmented jacobian matrix */
144556a221efSShri Abhyankar       ierr = MatCreate(((PetscObject)snes)->comm,&J_aug);CHKERRQ(ierr);
144656a221efSShri Abhyankar       ierr = MatSetSizes(J_aug,X->map->n+nkept,X->map->n+nkept,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
144756a221efSShri Abhyankar       ierr = MatSetFromOptions(J_aug);CHKERRQ(ierr);
14482f63a38cSShri Abhyankar 
144956a221efSShri Abhyankar 
14509521db3cSSatish Balay       { /* local vars */
1451493a4f3dSShri Abhyankar       /* Preallocate augmented matrix and set values in it...Doing only sequential case first*/
145256a221efSShri Abhyankar       PetscInt          ncols;
145356a221efSShri Abhyankar       const PetscInt    *cols;
145456a221efSShri Abhyankar       const PetscScalar *vals;
14552969f145SShri Abhyankar       PetscScalar        value[2];
14562969f145SShri Abhyankar       PetscInt           row,col[2];
1457493a4f3dSShri Abhyankar       PetscInt           *d_nnz;
14582969f145SShri Abhyankar       value[0] = 1.0; value[1] = 0.0;
1459493a4f3dSShri Abhyankar       ierr = PetscMalloc((X->map->n+nkept)*sizeof(PetscInt),&d_nnz);CHKERRQ(ierr);
1460493a4f3dSShri Abhyankar       ierr = PetscMemzero(d_nnz,(X->map->n+nkept)*sizeof(PetscInt));CHKERRQ(ierr);
1461493a4f3dSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
1462493a4f3dSShri Abhyankar         ierr = MatGetRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1463493a4f3dSShri Abhyankar         d_nnz[row] += ncols;
1464493a4f3dSShri Abhyankar         ierr = MatRestoreRow(snes->jacobian,row,&ncols,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr);
1465493a4f3dSShri Abhyankar       }
1466493a4f3dSShri Abhyankar 
1467493a4f3dSShri Abhyankar       for(k=0;k<nkept;k++) {
1468493a4f3dSShri Abhyankar         d_nnz[idx_actkept[k]] += 1;
14692969f145SShri Abhyankar         d_nnz[snes->jacobian->rmap->n+k] += 2;
1470493a4f3dSShri Abhyankar       }
1471493a4f3dSShri Abhyankar       ierr = MatSeqAIJSetPreallocation(J_aug,PETSC_NULL,d_nnz);CHKERRQ(ierr);
1472493a4f3dSShri Abhyankar 
1473493a4f3dSShri Abhyankar       ierr = PetscFree(d_nnz);CHKERRQ(ierr);
147456a221efSShri Abhyankar 
147556a221efSShri Abhyankar       /* Set the original jacobian matrix in J_aug */
147656a221efSShri Abhyankar       for(row=0;row<snes->jacobian->rmap->n;row++) {
147756a221efSShri Abhyankar 	ierr = MatGetRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
147856a221efSShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,ncols,cols,vals,INSERT_VALUES);CHKERRQ(ierr);
147956a221efSShri Abhyankar 	ierr = MatRestoreRow(snes->jacobian,row,&ncols,&cols,&vals);CHKERRQ(ierr);
148056a221efSShri Abhyankar       }
148156a221efSShri Abhyankar       /* Add the augmented part */
148256a221efSShri Abhyankar       for(k=0;k<nkept;k++) {
14832969f145SShri Abhyankar 	row = snes->jacobian->rmap->n+k;
14842969f145SShri Abhyankar 	col[0] = idx_actkept[k]; col[1] = snes->jacobian->rmap->n+k;
14852969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&row,1,col,value,INSERT_VALUES);CHKERRQ(ierr);
14862969f145SShri Abhyankar 	ierr = MatSetValues(J_aug,1,&col[0],1,&row,&value[0],INSERT_VALUES);CHKERRQ(ierr);
148756a221efSShri Abhyankar       }
148856a221efSShri Abhyankar       ierr = MatAssemblyBegin(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
148956a221efSShri Abhyankar       ierr = MatAssemblyEnd(J_aug,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
149056a221efSShri Abhyankar       /* Only considering prejac = jac for now */
149156a221efSShri Abhyankar       Jpre_aug = J_aug;
14929521db3cSSatish Balay       } /* local vars*/
1493e63076c7SBarry Smith       ierr = ISRestoreIndices(IS_act,&idx_act);CHKERRQ(ierr);
1494e63076c7SBarry Smith       ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
149556a221efSShri Abhyankar     } else {
149656a221efSShri Abhyankar       F_aug = F; J_aug = snes->jacobian; Y_aug = Y; Jpre_aug = snes->jacobian_pre;
149756a221efSShri Abhyankar     }
14982f63a38cSShri Abhyankar 
14992f63a38cSShri Abhyankar     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
15002f63a38cSShri Abhyankar     if (!isequal) {
150156a221efSShri Abhyankar       ierr = SNESVIResetPCandKSP(snes,J_aug,Jpre_aug);CHKERRQ(ierr);
15022f63a38cSShri Abhyankar     }
150356a221efSShri Abhyankar     ierr = KSPSetOperators(snes->ksp,J_aug,Jpre_aug,flg);CHKERRQ(ierr);
15042f63a38cSShri Abhyankar     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
150556a221efSShri Abhyankar     /*  {
15062f63a38cSShri Abhyankar       PC        pc;
15072f63a38cSShri Abhyankar       PetscBool flg;
15082f63a38cSShri Abhyankar       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
15092f63a38cSShri Abhyankar       ierr = PetscTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
15102f63a38cSShri Abhyankar       if (flg) {
15112f63a38cSShri Abhyankar         KSP      *subksps;
15122f63a38cSShri Abhyankar         ierr = PCFieldSplitGetSubKSP(pc,PETSC_NULL,&subksps);CHKERRQ(ierr);
15132f63a38cSShri Abhyankar         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
15142f63a38cSShri Abhyankar         ierr = PetscFree(subksps);CHKERRQ(ierr);
15152f63a38cSShri Abhyankar         ierr = PetscTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
15162f63a38cSShri Abhyankar         if (flg) {
15172f63a38cSShri Abhyankar           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
15182f63a38cSShri Abhyankar           const PetscInt *ii;
15192f63a38cSShri Abhyankar 
15202f63a38cSShri Abhyankar           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
15212f63a38cSShri Abhyankar           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
15222f63a38cSShri Abhyankar           for (j=0; j<n; j++) {
15232f63a38cSShri Abhyankar             if (ii[j] < N) cnts[0]++;
15242f63a38cSShri Abhyankar             else if (ii[j] < 2*N) cnts[1]++;
15252f63a38cSShri Abhyankar             else if (ii[j] < 3*N) cnts[2]++;
15262f63a38cSShri Abhyankar           }
15272f63a38cSShri Abhyankar           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
15282f63a38cSShri Abhyankar 
15292f63a38cSShri Abhyankar           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
15302f63a38cSShri Abhyankar         }
15312f63a38cSShri Abhyankar       }
15322f63a38cSShri Abhyankar     }
153356a221efSShri Abhyankar     */
153456a221efSShri Abhyankar     ierr = SNES_KSPSolve(snes,snes->ksp,F_aug,Y_aug);CHKERRQ(ierr);
15352f63a38cSShri Abhyankar     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
15362f63a38cSShri Abhyankar     if (kspreason < 0) {
15372f63a38cSShri Abhyankar       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
15382f63a38cSShri 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);
15392f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
15402f63a38cSShri Abhyankar         break;
15412f63a38cSShri Abhyankar       }
15422f63a38cSShri Abhyankar     }
15432f63a38cSShri Abhyankar 
154456a221efSShri Abhyankar     if(nis_act) {
154556a221efSShri Abhyankar       PetscScalar *y1,*y2;
154656a221efSShri Abhyankar       ierr = VecGetArray(Y,&y1);CHKERRQ(ierr);
154756a221efSShri Abhyankar       ierr = VecGetArray(Y_aug,&y2);CHKERRQ(ierr);
154856a221efSShri Abhyankar       /* Copy over inactive Y_aug to Y */
154956a221efSShri Abhyankar       j1 = 0;
155056a221efSShri Abhyankar       for(i1=Y->map->rstart;i1 < Y->map->rend;i1++) {
155156a221efSShri Abhyankar 	if(j1 < nkept && idx_actkept[j1] == i1) j1++;
155256a221efSShri Abhyankar 	else y1[i1-Y->map->rstart] = y2[i1-Y->map->rstart];
155356a221efSShri Abhyankar       }
155456a221efSShri Abhyankar       ierr = VecRestoreArray(Y,&y1);CHKERRQ(ierr);
155556a221efSShri Abhyankar       ierr = VecRestoreArray(Y_aug,&y2);CHKERRQ(ierr);
15562f63a38cSShri Abhyankar 
15576bf464f9SBarry Smith       ierr = VecDestroy(&F_aug);CHKERRQ(ierr);
15586bf464f9SBarry Smith       ierr = VecDestroy(&Y_aug);CHKERRQ(ierr);
15596bf464f9SBarry Smith       ierr = MatDestroy(&J_aug);CHKERRQ(ierr);
156056a221efSShri Abhyankar       ierr = PetscFree(idx_actkept);CHKERRQ(ierr);
156156a221efSShri Abhyankar     }
156256a221efSShri Abhyankar 
15632f63a38cSShri Abhyankar     if (!isequal) {
15646bf464f9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
15652f63a38cSShri Abhyankar       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
15662f63a38cSShri Abhyankar     }
15676bf464f9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
156856a221efSShri Abhyankar 
15692f63a38cSShri Abhyankar     ierr = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
15702f63a38cSShri Abhyankar     snes->linear_its += lits;
15712f63a38cSShri Abhyankar     ierr = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
15722f63a38cSShri Abhyankar     /*
15732f63a38cSShri Abhyankar     if (vi->precheckstep) {
15742f63a38cSShri Abhyankar       PetscBool changed_y = PETSC_FALSE;
15752f63a38cSShri Abhyankar       ierr = (*vi->precheckstep)(snes,X,Y,vi->precheck,&changed_y);CHKERRQ(ierr);
15762f63a38cSShri Abhyankar     }
15772f63a38cSShri Abhyankar 
15782f63a38cSShri Abhyankar     if (PetscLogPrintInfo){
15792f63a38cSShri Abhyankar       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
15802f63a38cSShri Abhyankar     }
15812f63a38cSShri Abhyankar     */
15822f63a38cSShri Abhyankar     /* Compute a (scaled) negative update in the line search routine:
15832f63a38cSShri Abhyankar          Y <- X - lambda*Y
15842f63a38cSShri Abhyankar        and evaluate G = function(Y) (depends on the line search).
15852f63a38cSShri Abhyankar     */
15862f63a38cSShri Abhyankar     ierr = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
15872f63a38cSShri Abhyankar     ynorm = 1; gnorm = fnorm;
15882f63a38cSShri Abhyankar     ierr = (*vi->LineSearch)(snes,vi->lsP,X,F,G,Y,W,fnorm,xnorm,&ynorm,&gnorm,&lssucceed);CHKERRQ(ierr);
15892f63a38cSShri Abhyankar     ierr = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",fnorm,gnorm,ynorm,(int)lssucceed);CHKERRQ(ierr);
15902f63a38cSShri Abhyankar     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
15912f63a38cSShri Abhyankar     if (snes->domainerror) {
15922f63a38cSShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
15932f63a38cSShri Abhyankar       PetscFunctionReturn(0);
15942f63a38cSShri Abhyankar     }
15952f63a38cSShri Abhyankar     if (!lssucceed) {
15962f63a38cSShri Abhyankar       if (++snes->numFailures >= snes->maxFailures) {
15972f63a38cSShri Abhyankar 	PetscBool ismin;
15982f63a38cSShri Abhyankar         snes->reason = SNES_DIVERGED_LINE_SEARCH;
15992f63a38cSShri Abhyankar         ierr = SNESVICheckLocalMin_Private(snes,snes->jacobian,G,W,gnorm,&ismin);CHKERRQ(ierr);
16002f63a38cSShri Abhyankar         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
16012f63a38cSShri Abhyankar         break;
16022f63a38cSShri Abhyankar       }
16032f63a38cSShri Abhyankar     }
16042f63a38cSShri Abhyankar     /* Update function and solution vectors */
16052f63a38cSShri Abhyankar     fnorm = gnorm;
16062f63a38cSShri Abhyankar     ierr = VecCopy(G,F);CHKERRQ(ierr);
16072f63a38cSShri Abhyankar     ierr = VecCopy(W,X);CHKERRQ(ierr);
16082f63a38cSShri Abhyankar     /* Monitor convergence */
16092f63a38cSShri Abhyankar     ierr = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
16102f63a38cSShri Abhyankar     snes->iter = i+1;
16112f63a38cSShri Abhyankar     snes->norm = fnorm;
16122f63a38cSShri Abhyankar     ierr = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
16132f63a38cSShri Abhyankar     SNESLogConvHistory(snes,snes->norm,lits);
16147a03ce2fSLisandro Dalcin     ierr = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
16152f63a38cSShri Abhyankar     /* Test for convergence, xnorm = || X || */
16162f63a38cSShri Abhyankar     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
16172f63a38cSShri Abhyankar     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
16182f63a38cSShri Abhyankar     if (snes->reason) break;
16192f63a38cSShri Abhyankar   }
16202f63a38cSShri Abhyankar   if (i == maxits) {
16212f63a38cSShri Abhyankar     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
16222f63a38cSShri Abhyankar     if(!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
16232f63a38cSShri Abhyankar   }
16242f63a38cSShri Abhyankar   PetscFunctionReturn(0);
16252f63a38cSShri Abhyankar }
16262f63a38cSShri Abhyankar 
16272b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
16282b4ed282SShri Abhyankar /*
16292b4ed282SShri Abhyankar    SNESSetUp_VI - Sets up the internal data structures for the later use
16302b4ed282SShri Abhyankar    of the SNESVI nonlinear solver.
16312b4ed282SShri Abhyankar 
16322b4ed282SShri Abhyankar    Input Parameter:
16332b4ed282SShri Abhyankar .  snes - the SNES context
16342b4ed282SShri Abhyankar .  x - the solution vector
16352b4ed282SShri Abhyankar 
16362b4ed282SShri Abhyankar    Application Interface Routine: SNESSetUp()
16372b4ed282SShri Abhyankar 
16382b4ed282SShri Abhyankar    Notes:
16392b4ed282SShri Abhyankar    For basic use of the SNES solvers, the user need not explicitly call
16402b4ed282SShri Abhyankar    SNESSetUp(), since these actions will automatically occur during
16412b4ed282SShri Abhyankar    the call to SNESSolve().
16422b4ed282SShri Abhyankar  */
16432b4ed282SShri Abhyankar #undef __FUNCT__
16442b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetUp_VI"
16452b4ed282SShri Abhyankar PetscErrorCode SNESSetUp_VI(SNES snes)
16462b4ed282SShri Abhyankar {
16472b4ed282SShri Abhyankar   PetscErrorCode ierr;
16482b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
16492b4ed282SShri Abhyankar   PetscInt       i_start[3],i_end[3];
16502b4ed282SShri Abhyankar 
16512b4ed282SShri Abhyankar   PetscFunctionBegin;
165258c9b817SLisandro Dalcin 
165358c9b817SLisandro Dalcin   ierr = SNESDefaultGetWork(snes,3);CHKERRQ(ierr);
16542b4ed282SShri Abhyankar 
16552b4ed282SShri Abhyankar   /* If the lower and upper bound on variables are not set, set it to
16562b4ed282SShri Abhyankar      -Inf and Inf */
16572b4ed282SShri Abhyankar   if (!vi->xl && !vi->xu) {
16582b4ed282SShri Abhyankar     vi->usersetxbounds = PETSC_FALSE;
16592b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xl); CHKERRQ(ierr);
166001f0b76bSBarry Smith     ierr = VecSet(vi->xl,SNES_VI_NINF);CHKERRQ(ierr);
16612b4ed282SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->xu); CHKERRQ(ierr);
166201f0b76bSBarry Smith     ierr = VecSet(vi->xu,SNES_VI_INF);CHKERRQ(ierr);
16632b4ed282SShri Abhyankar   } else {
16642b4ed282SShri Abhyankar     /* Check if lower bound, upper bound and solution vector distribution across the processors is identical */
16652b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,i_start,i_end);CHKERRQ(ierr);
16662b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xl,i_start+1,i_end+1);CHKERRQ(ierr);
16672b4ed282SShri Abhyankar     ierr = VecGetOwnershipRange(vi->xu,i_start+2,i_end+2);CHKERRQ(ierr);
16682b4ed282SShri 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]))
16692b4ed282SShri 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.");
16702b4ed282SShri Abhyankar   }
16712f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1672abcba341SShri Abhyankar     /* Set up previous active index set for the first snes solve
1673abcba341SShri Abhyankar        vi->IS_inact_prev = 0,1,2,....N */
1674abcba341SShri Abhyankar     PetscInt *indices;
1675abcba341SShri Abhyankar     PetscInt  i,n,rstart,rend;
1676abcba341SShri Abhyankar 
1677abcba341SShri Abhyankar     ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
1678abcba341SShri Abhyankar     ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
1679abcba341SShri Abhyankar     ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
1680abcba341SShri Abhyankar     for(i=0;i < n; i++) indices[i] = rstart + i;
1681abcba341SShri Abhyankar     ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);
1682abcba341SShri Abhyankar   }
16832b4ed282SShri Abhyankar 
16842f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
1685fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->dpsi);CHKERRQ(ierr);
1686fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->phi); CHKERRQ(ierr);
1687fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Da); CHKERRQ(ierr);
1688fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->Db); CHKERRQ(ierr);
1689fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->z);CHKERRQ(ierr);
1690fe835674SShri Abhyankar     ierr = VecDuplicate(snes->vec_sol, &vi->t); CHKERRQ(ierr);
1691fe835674SShri Abhyankar   }
16922b4ed282SShri Abhyankar   PetscFunctionReturn(0);
16932b4ed282SShri Abhyankar }
16942b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
16952b4ed282SShri Abhyankar /*
16962b4ed282SShri Abhyankar    SNESDestroy_VI - Destroys the private SNES_VI context that was created
16972b4ed282SShri Abhyankar    with SNESCreate_VI().
16982b4ed282SShri Abhyankar 
16992b4ed282SShri Abhyankar    Input Parameter:
17002b4ed282SShri Abhyankar .  snes - the SNES context
17012b4ed282SShri Abhyankar 
17022b4ed282SShri Abhyankar    Application Interface Routine: SNESDestroy()
17032b4ed282SShri Abhyankar  */
17042b4ed282SShri Abhyankar #undef __FUNCT__
17052b4ed282SShri Abhyankar #define __FUNCT__ "SNESDestroy_VI"
17062b4ed282SShri Abhyankar PetscErrorCode SNESDestroy_VI(SNES snes)
17072b4ed282SShri Abhyankar {
17082b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*) snes->data;
17092b4ed282SShri Abhyankar   PetscErrorCode ierr;
17102b4ed282SShri Abhyankar 
17112b4ed282SShri Abhyankar   PetscFunctionBegin;
17122f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
17136bf464f9SBarry Smith     ierr = ISDestroy(&vi->IS_inact_prev);
1714abcba341SShri Abhyankar   }
17152b4ed282SShri Abhyankar 
17162f63a38cSShri Abhyankar   if (snes->ops->solve == SNESSolveVI_SS) {
17172b4ed282SShri Abhyankar     /* clear vectors */
17186bf464f9SBarry Smith     ierr = VecDestroy(&vi->dpsi);CHKERRQ(ierr);
17196bf464f9SBarry Smith     ierr = VecDestroy(&vi->phi); CHKERRQ(ierr);
17206bf464f9SBarry Smith     ierr = VecDestroy(&vi->Da); CHKERRQ(ierr);
17216bf464f9SBarry Smith     ierr = VecDestroy(&vi->Db); CHKERRQ(ierr);
17226bf464f9SBarry Smith     ierr = VecDestroy(&vi->z); CHKERRQ(ierr);
17236bf464f9SBarry Smith     ierr = VecDestroy(&vi->t); CHKERRQ(ierr);
17247fe79bc4SShri Abhyankar   }
17257fe79bc4SShri Abhyankar 
17262b4ed282SShri Abhyankar   if (!vi->usersetxbounds) {
17276bf464f9SBarry Smith     ierr = VecDestroy(&vi->xl); CHKERRQ(ierr);
17286bf464f9SBarry Smith     ierr = VecDestroy(&vi->xu); CHKERRQ(ierr);
17292b4ed282SShri Abhyankar   }
17307fe79bc4SShri Abhyankar 
17316bf464f9SBarry Smith   ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
17322b4ed282SShri Abhyankar   ierr = PetscFree(snes->data);CHKERRQ(ierr);
17332b4ed282SShri Abhyankar 
17342b4ed282SShri Abhyankar   /* clear composed functions */
17352b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","",PETSC_NULL);CHKERRQ(ierr);
1736c92abb8aSShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","",PETSC_NULL);CHKERRQ(ierr);
17372b4ed282SShri Abhyankar   PetscFunctionReturn(0);
17382b4ed282SShri Abhyankar }
17397fe79bc4SShri Abhyankar 
17402b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
17412b4ed282SShri Abhyankar #undef __FUNCT__
17422b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNo_VI"
17432b4ed282SShri Abhyankar 
17442b4ed282SShri Abhyankar /*
17457fe79bc4SShri Abhyankar   This routine does not actually do a line search but it takes a full newton
17467fe79bc4SShri Abhyankar   step while ensuring that the new iterates remain within the constraints.
17472b4ed282SShri Abhyankar 
17482b4ed282SShri Abhyankar */
1749ace3abfcSBarry 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)
17502b4ed282SShri Abhyankar {
17512b4ed282SShri Abhyankar   PetscErrorCode ierr;
17522b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1753ace3abfcSBarry Smith   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
17542b4ed282SShri Abhyankar 
17552b4ed282SShri Abhyankar   PetscFunctionBegin;
17562b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
17572b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
17582b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);         /* ynorm = || y || */
17592b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
1760c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1761c1a5e521SShri Abhyankar   if (vi->postcheckstep) {
1762c1a5e521SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
1763c1a5e521SShri Abhyankar   }
1764c1a5e521SShri Abhyankar   if (changed_y) {
1765c1a5e521SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
17667fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1767c1a5e521SShri Abhyankar   }
1768c1a5e521SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1769c1a5e521SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
1770c1a5e521SShri Abhyankar   if (!snes->domainerror) {
17712f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
17727fe79bc4SShri Abhyankar        ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
17737fe79bc4SShri Abhyankar     } else {
1774c1a5e521SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);  /* gnorm = || g || */
17757fe79bc4SShri Abhyankar     }
177662cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1777c1a5e521SShri Abhyankar   }
1778c1a5e521SShri Abhyankar   if (vi->lsmonitor) {
1779c1a5e521SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1780c1a5e521SShri Abhyankar   }
1781c1a5e521SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1782c1a5e521SShri Abhyankar   PetscFunctionReturn(0);
1783c1a5e521SShri Abhyankar }
1784c1a5e521SShri Abhyankar 
1785c1a5e521SShri Abhyankar /* -------------------------------------------------------------------------- */
1786c1a5e521SShri Abhyankar #undef __FUNCT__
17872b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchNoNorms_VI"
17882b4ed282SShri Abhyankar 
17892b4ed282SShri Abhyankar /*
17902b4ed282SShri Abhyankar   This routine is a copy of SNESLineSearchNoNorms in snes/impls/ls/ls.c
17912b4ed282SShri Abhyankar */
1792ace3abfcSBarry 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)
17932b4ed282SShri Abhyankar {
17942b4ed282SShri Abhyankar   PetscErrorCode ierr;
17952b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1796ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
17972b4ed282SShri Abhyankar 
17982b4ed282SShri Abhyankar   PetscFunctionBegin;
17992b4ed282SShri Abhyankar   *flag = PETSC_TRUE;
18002b4ed282SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18012b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y      */
18027fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18032b4ed282SShri Abhyankar   if (vi->postcheckstep) {
18042b4ed282SShri Abhyankar    ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
18052b4ed282SShri Abhyankar   }
18062b4ed282SShri Abhyankar   if (changed_y) {
18072b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);            /* w <- x - y   */
18087fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
18092b4ed282SShri Abhyankar   }
18102b4ed282SShri Abhyankar 
18112b4ed282SShri Abhyankar   /* don't evaluate function the last time through */
18122b4ed282SShri Abhyankar   if (snes->iter < snes->max_its-1) {
18132b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18142b4ed282SShri Abhyankar   }
18152b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
18162b4ed282SShri Abhyankar   PetscFunctionReturn(0);
18172b4ed282SShri Abhyankar }
18187fe79bc4SShri Abhyankar 
18192b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
18202b4ed282SShri Abhyankar #undef __FUNCT__
18212b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchCubic_VI"
18222b4ed282SShri Abhyankar /*
18237fe79bc4SShri Abhyankar   This routine implements a cubic line search while doing a projection on the variable bounds
18242b4ed282SShri Abhyankar */
1825ace3abfcSBarry 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)
18262b4ed282SShri Abhyankar {
1827fe835674SShri Abhyankar   PetscReal      initslope,lambdaprev,gnormprev,a,b,d,t1,t2,rellength;
1828fe835674SShri Abhyankar   PetscReal      minlambda,lambda,lambdatemp;
1829fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1830fe835674SShri Abhyankar   PetscScalar    cinitslope;
1831fe835674SShri Abhyankar #endif
1832fe835674SShri Abhyankar   PetscErrorCode ierr;
1833fe835674SShri Abhyankar   PetscInt       count;
1834fe835674SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
1835fe835674SShri Abhyankar   PetscBool      changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
1836fe835674SShri Abhyankar   MPI_Comm       comm;
1837fe835674SShri Abhyankar 
1838fe835674SShri Abhyankar   PetscFunctionBegin;
1839fe835674SShri Abhyankar   ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr);
1840fe835674SShri Abhyankar   ierr = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1841fe835674SShri Abhyankar   *flag   = PETSC_TRUE;
1842fe835674SShri Abhyankar 
1843fe835674SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
1844fe835674SShri Abhyankar   if (*ynorm == 0.0) {
1845fe835674SShri Abhyankar     if (vi->lsmonitor) {
1846fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Initial direction and size is 0\n");CHKERRQ(ierr);
1847fe835674SShri Abhyankar     }
1848fe835674SShri Abhyankar     *gnorm = fnorm;
1849fe835674SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
1850fe835674SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
1851fe835674SShri Abhyankar     *flag  = PETSC_FALSE;
1852fe835674SShri Abhyankar     goto theend1;
1853fe835674SShri Abhyankar   }
1854fe835674SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
1855fe835674SShri Abhyankar     if (vi->lsmonitor) {
1856fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Scaling step by %G old ynorm %G\n",vi->maxstep/(*ynorm),*ynorm);CHKERRQ(ierr);
1857fe835674SShri Abhyankar     }
1858fe835674SShri Abhyankar     ierr = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
1859fe835674SShri Abhyankar     *ynorm = vi->maxstep;
1860fe835674SShri Abhyankar   }
1861fe835674SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
1862fe835674SShri Abhyankar   minlambda = vi->minlambda/rellength;
1863fe835674SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
1864fe835674SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
1865fe835674SShri Abhyankar   ierr = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
1866fe835674SShri Abhyankar   initslope = PetscRealPart(cinitslope);
1867fe835674SShri Abhyankar #else
1868fe835674SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
1869fe835674SShri Abhyankar #endif
1870fe835674SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
1871fe835674SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
1872fe835674SShri Abhyankar 
1873fe835674SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
1874fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1875fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1876fe835674SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
1877fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1878fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1879fe835674SShri Abhyankar     goto theend1;
1880fe835674SShri Abhyankar   }
1881fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
18822f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1883fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
18847fe79bc4SShri Abhyankar   } else {
18857fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
18867fe79bc4SShri Abhyankar   }
1887fe835674SShri Abhyankar   if (snes->domainerror) {
1888fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1889fe835674SShri Abhyankar     PetscFunctionReturn(0);
1890fe835674SShri Abhyankar   }
189162cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1892fe835674SShri Abhyankar   ierr = PetscInfo2(snes,"Initial fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1893fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
1894fe835674SShri Abhyankar     if (vi->lsmonitor) {
1895fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
1896fe835674SShri Abhyankar     }
1897fe835674SShri Abhyankar     goto theend1;
1898fe835674SShri Abhyankar   }
1899fe835674SShri Abhyankar 
1900fe835674SShri Abhyankar   /* Fit points with quadratic */
1901fe835674SShri Abhyankar   lambda     = 1.0;
1902fe835674SShri Abhyankar   lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
1903fe835674SShri Abhyankar   lambdaprev = lambda;
1904fe835674SShri Abhyankar   gnormprev  = *gnorm;
1905fe835674SShri Abhyankar   if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1906fe835674SShri Abhyankar   if (lambdatemp <= .1*lambda) lambda = .1*lambda;
1907fe835674SShri Abhyankar   else                         lambda = lambdatemp;
1908fe835674SShri Abhyankar 
1909fe835674SShri Abhyankar   ierr  = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1910fe835674SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1911fe835674SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
1912fe835674SShri Abhyankar     ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while attempting quadratic backtracking! %D \n",snes->nfuncs);CHKERRQ(ierr);
1913fe835674SShri Abhyankar     *flag = PETSC_FALSE;
1914fe835674SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1915fe835674SShri Abhyankar     goto theend1;
1916fe835674SShri Abhyankar   }
1917fe835674SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19182f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
1919fe835674SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19207fe79bc4SShri Abhyankar   } else {
19217fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19227fe79bc4SShri Abhyankar   }
1923fe835674SShri Abhyankar   if (snes->domainerror) {
1924fe835674SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1925fe835674SShri Abhyankar     PetscFunctionReturn(0);
1926fe835674SShri Abhyankar   }
192762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1928fe835674SShri Abhyankar   if (vi->lsmonitor) {
1929fe835674SShri Abhyankar     ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: gnorm after quadratic fit %G\n",*gnorm);CHKERRQ(ierr);
1930fe835674SShri Abhyankar   }
1931fe835674SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
1932fe835674SShri Abhyankar     if (vi->lsmonitor) {
1933fe835674SShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Quadratically determined step, lambda=%18.16e\n",lambda);CHKERRQ(ierr);
1934fe835674SShri Abhyankar     }
1935fe835674SShri Abhyankar     goto theend1;
1936fe835674SShri Abhyankar   }
1937fe835674SShri Abhyankar 
1938fe835674SShri Abhyankar   /* Fit points with cubic */
1939fe835674SShri Abhyankar   count = 1;
1940fe835674SShri Abhyankar   while (PETSC_TRUE) {
1941fe835674SShri Abhyankar     if (lambda <= minlambda) {
1942fe835674SShri Abhyankar       if (vi->lsmonitor) {
1943fe835674SShri Abhyankar 	ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: unable to find good step length! After %D tries \n",count);CHKERRQ(ierr);
1944fe835674SShri 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);
1945fe835674SShri Abhyankar       }
1946fe835674SShri Abhyankar       *flag = PETSC_FALSE;
1947fe835674SShri Abhyankar       break;
1948fe835674SShri Abhyankar     }
1949fe835674SShri Abhyankar     t1 = .5*((*gnorm)*(*gnorm) - fnorm*fnorm) - lambda*initslope;
1950fe835674SShri Abhyankar     t2 = .5*(gnormprev*gnormprev  - fnorm*fnorm) - lambdaprev*initslope;
1951fe835674SShri Abhyankar     a  = (t1/(lambda*lambda) - t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1952fe835674SShri Abhyankar     b  = (-lambdaprev*t1/(lambda*lambda) + lambda*t2/(lambdaprev*lambdaprev))/(lambda-lambdaprev);
1953fe835674SShri Abhyankar     d  = b*b - 3*a*initslope;
1954fe835674SShri Abhyankar     if (d < 0.0) d = 0.0;
1955fe835674SShri Abhyankar     if (a == 0.0) {
1956fe835674SShri Abhyankar       lambdatemp = -initslope/(2.0*b);
1957fe835674SShri Abhyankar     } else {
1958fe835674SShri Abhyankar       lambdatemp = (-b + sqrt(d))/(3.0*a);
1959fe835674SShri Abhyankar     }
1960fe835674SShri Abhyankar     lambdaprev = lambda;
1961fe835674SShri Abhyankar     gnormprev  = *gnorm;
1962fe835674SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
1963fe835674SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
1964fe835674SShri Abhyankar     else                         lambda     = lambdatemp;
1965fe835674SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
1966fe835674SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
1967fe835674SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
1968fe835674SShri Abhyankar       ierr = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
1969fe835674SShri 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);
1970fe835674SShri Abhyankar       *flag = PETSC_FALSE;
1971fe835674SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
1972fe835674SShri Abhyankar       break;
1973fe835674SShri Abhyankar     }
1974fe835674SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
19752f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
1976fe835674SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
19777fe79bc4SShri Abhyankar     } else {
19787fe79bc4SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
19797fe79bc4SShri Abhyankar     }
1980fe835674SShri Abhyankar     if (snes->domainerror) {
1981fe835674SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
1982fe835674SShri Abhyankar       PetscFunctionReturn(0);
1983fe835674SShri Abhyankar     }
198462cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
1985fe835674SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* is reduction enough? */
1986fe835674SShri Abhyankar       if (vi->lsmonitor) {
1987fe835674SShri Abhyankar 	ierr = PetscPrintf(comm,"    Line search: Cubically determined step, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
1988fe835674SShri Abhyankar       }
1989fe835674SShri Abhyankar       break;
1990fe835674SShri Abhyankar     } else {
1991fe835674SShri Abhyankar       if (vi->lsmonitor) {
1992fe835674SShri Abhyankar         ierr = PetscPrintf(comm,"    Line search: Cubic step no good, shrinking lambda, current gnorm %G lambda=%18.16e\n",*gnorm,lambda);CHKERRQ(ierr);
1993fe835674SShri Abhyankar       }
1994fe835674SShri Abhyankar     }
1995fe835674SShri Abhyankar     count++;
1996fe835674SShri Abhyankar   }
1997fe835674SShri Abhyankar   theend1:
1998fe835674SShri Abhyankar   /* Optional user-defined check for line search step validity */
1999fe835674SShri Abhyankar   if (vi->postcheckstep && *flag) {
2000fe835674SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
2001fe835674SShri Abhyankar     if (changed_y) {
2002fe835674SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
2003fe835674SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
2004fe835674SShri Abhyankar     }
2005fe835674SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
2006fe835674SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20072f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
2008fe835674SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20097fe79bc4SShri Abhyankar       } else {
20107fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20117fe79bc4SShri Abhyankar       }
2012fe835674SShri Abhyankar       if (snes->domainerror) {
2013fe835674SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2014fe835674SShri Abhyankar         PetscFunctionReturn(0);
2015fe835674SShri Abhyankar       }
201662cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
2017fe835674SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
2018fe835674SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
2019fe835674SShri Abhyankar     }
2020fe835674SShri Abhyankar   }
2021fe835674SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
2022fe835674SShri Abhyankar   PetscFunctionReturn(0);
2023fe835674SShri Abhyankar }
2024fe835674SShri Abhyankar 
20252b4ed282SShri Abhyankar #undef __FUNCT__
20262b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchQuadratic_VI"
20272b4ed282SShri Abhyankar /*
20287fe79bc4SShri Abhyankar   This routine does a quadratic line search while keeping the iterates within the variable bounds
20292b4ed282SShri Abhyankar */
2030ace3abfcSBarry 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)
20312b4ed282SShri Abhyankar {
20322b4ed282SShri Abhyankar   /*
20332b4ed282SShri Abhyankar      Note that for line search purposes we work with with the related
20342b4ed282SShri Abhyankar      minimization problem:
20352b4ed282SShri Abhyankar         min  z(x):  R^n -> R,
20362b4ed282SShri Abhyankar      where z(x) = .5 * fnorm*fnorm,and fnorm = || f ||_2.
20372b4ed282SShri Abhyankar    */
20382b4ed282SShri Abhyankar   PetscReal      initslope,minlambda,lambda,lambdatemp,rellength;
20392b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
20402b4ed282SShri Abhyankar   PetscScalar    cinitslope;
20412b4ed282SShri Abhyankar #endif
20422b4ed282SShri Abhyankar   PetscErrorCode ierr;
20432b4ed282SShri Abhyankar   PetscInt       count;
20442b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
2045ace3abfcSBarry Smith   PetscBool     changed_w = PETSC_FALSE,changed_y = PETSC_FALSE;
20462b4ed282SShri Abhyankar 
20472b4ed282SShri Abhyankar   PetscFunctionBegin;
20482b4ed282SShri Abhyankar   ierr    = PetscLogEventBegin(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
20492b4ed282SShri Abhyankar   *flag   = PETSC_TRUE;
20502b4ed282SShri Abhyankar 
20512b4ed282SShri Abhyankar   ierr = VecNorm(y,NORM_2,ynorm);CHKERRQ(ierr);
20522b4ed282SShri Abhyankar   if (*ynorm == 0.0) {
2053c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2054c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Direction and size is 0\n");CHKERRQ(ierr);
20552b4ed282SShri Abhyankar     }
20562b4ed282SShri Abhyankar     *gnorm = fnorm;
20572b4ed282SShri Abhyankar     ierr   = VecCopy(x,w);CHKERRQ(ierr);
20582b4ed282SShri Abhyankar     ierr   = VecCopy(f,g);CHKERRQ(ierr);
20592b4ed282SShri Abhyankar     *flag  = PETSC_FALSE;
20602b4ed282SShri Abhyankar     goto theend2;
20612b4ed282SShri Abhyankar   }
20622b4ed282SShri Abhyankar   if (*ynorm > vi->maxstep) {	/* Step too big, so scale back */
20632b4ed282SShri Abhyankar     ierr   = VecScale(y,vi->maxstep/(*ynorm));CHKERRQ(ierr);
20642b4ed282SShri Abhyankar     *ynorm = vi->maxstep;
20652b4ed282SShri Abhyankar   }
20662b4ed282SShri Abhyankar   ierr      = VecMaxPointwiseDivide(y,x,&rellength);CHKERRQ(ierr);
20672b4ed282SShri Abhyankar   minlambda = vi->minlambda/rellength;
20687fe79bc4SShri Abhyankar   ierr = MatMult(snes->jacobian,y,w);CHKERRQ(ierr);
20692b4ed282SShri Abhyankar #if defined(PETSC_USE_COMPLEX)
20707fe79bc4SShri Abhyankar   ierr      = VecDot(f,w,&cinitslope);CHKERRQ(ierr);
20712b4ed282SShri Abhyankar   initslope = PetscRealPart(cinitslope);
20722b4ed282SShri Abhyankar #else
20737fe79bc4SShri Abhyankar   ierr = VecDot(f,w,&initslope);CHKERRQ(ierr);
20742b4ed282SShri Abhyankar #endif
20752b4ed282SShri Abhyankar   if (initslope > 0.0)  initslope = -initslope;
20762b4ed282SShri Abhyankar   if (initslope == 0.0) initslope = -1.0;
20772b4ed282SShri Abhyankar   ierr = PetscInfo1(snes,"Initslope %G \n",initslope);CHKERRQ(ierr);
20782b4ed282SShri Abhyankar 
20792b4ed282SShri Abhyankar   ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
20807fe79bc4SShri Abhyankar   ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
20812b4ed282SShri Abhyankar   if (snes->nfuncs >= snes->max_funcs) {
20822b4ed282SShri Abhyankar     ierr  = PetscInfo(snes,"Exceeded maximum function evaluations, while checking full step length!\n");CHKERRQ(ierr);
20832b4ed282SShri Abhyankar     *flag = PETSC_FALSE;
20842b4ed282SShri Abhyankar     snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
20852b4ed282SShri Abhyankar     goto theend2;
20862b4ed282SShri Abhyankar   }
20872b4ed282SShri Abhyankar   ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
20882f63a38cSShri Abhyankar   if (snes->ops->solve != SNESSolveVI_SS) {
20897fe79bc4SShri Abhyankar     ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
20907fe79bc4SShri Abhyankar   } else {
20917fe79bc4SShri Abhyankar     ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
20927fe79bc4SShri Abhyankar   }
20932b4ed282SShri Abhyankar   if (snes->domainerror) {
20942b4ed282SShri Abhyankar     ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
20952b4ed282SShri Abhyankar     PetscFunctionReturn(0);
20962b4ed282SShri Abhyankar   }
209762cbcd01SMatthew G Knepley   if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
20982b4ed282SShri Abhyankar   if (.5*(*gnorm)*(*gnorm) <= .5*fnorm*fnorm + vi->alpha*initslope) { /* Sufficient reduction */
2099c92abb8aSShri Abhyankar     if (vi->lsmonitor) {
2100c92abb8aSShri Abhyankar       ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line search: Using full step: fnorm %G gnorm %G\n",fnorm,*gnorm);CHKERRQ(ierr);
21012b4ed282SShri Abhyankar     }
21022b4ed282SShri Abhyankar     goto theend2;
21032b4ed282SShri Abhyankar   }
21042b4ed282SShri Abhyankar 
21052b4ed282SShri Abhyankar   /* Fit points with quadratic */
21062b4ed282SShri Abhyankar   lambda = 1.0;
21072b4ed282SShri Abhyankar   count = 1;
21082b4ed282SShri Abhyankar   while (PETSC_TRUE) {
21092b4ed282SShri Abhyankar     if (lambda <= minlambda) { /* bad luck; use full step */
2110c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2111c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"Line search: Unable to find good step length! %D \n",count);CHKERRQ(ierr);
2112c92abb8aSShri 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);
21132b4ed282SShri Abhyankar       }
21142b4ed282SShri Abhyankar       ierr = VecCopy(x,w);CHKERRQ(ierr);
21152b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21162b4ed282SShri Abhyankar       break;
21172b4ed282SShri Abhyankar     }
21182b4ed282SShri Abhyankar     lambdatemp = -initslope/((*gnorm)*(*gnorm) - fnorm*fnorm - 2.0*initslope);
21192b4ed282SShri Abhyankar     if (lambdatemp > .5*lambda)  lambdatemp = .5*lambda;
21202b4ed282SShri Abhyankar     if (lambdatemp <= .1*lambda) lambda     = .1*lambda;
21212b4ed282SShri Abhyankar     else                         lambda     = lambdatemp;
21222b4ed282SShri Abhyankar 
21232b4ed282SShri Abhyankar     ierr = VecWAXPY(w,-lambda,y,x);CHKERRQ(ierr);
21247fe79bc4SShri Abhyankar     ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21252b4ed282SShri Abhyankar     if (snes->nfuncs >= snes->max_funcs) {
21262b4ed282SShri Abhyankar       ierr  = PetscInfo1(snes,"Exceeded maximum function evaluations, while looking for good step length! %D \n",count);CHKERRQ(ierr);
21272b4ed282SShri 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);
21282b4ed282SShri Abhyankar       *flag = PETSC_FALSE;
21292b4ed282SShri Abhyankar       snes->reason = SNES_DIVERGED_FUNCTION_COUNT;
21302b4ed282SShri Abhyankar       break;
21312b4ed282SShri Abhyankar     }
21322b4ed282SShri Abhyankar     ierr = SNESComputeFunction(snes,w,g);CHKERRQ(ierr);
21332b4ed282SShri Abhyankar     if (snes->domainerror) {
21342b4ed282SShri Abhyankar       ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21352b4ed282SShri Abhyankar       PetscFunctionReturn(0);
21362b4ed282SShri Abhyankar     }
21372f63a38cSShri Abhyankar     if (snes->ops->solve != SNESSolveVI_SS) {
21387fe79bc4SShri Abhyankar       ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21397fe79bc4SShri Abhyankar     } else {
21402b4ed282SShri Abhyankar       ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21417fe79bc4SShri Abhyankar     }
214262cbcd01SMatthew G Knepley     if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21432b4ed282SShri Abhyankar     if (.5*(*gnorm)*(*gnorm) < .5*fnorm*fnorm + lambda*vi->alpha*initslope) { /* sufficient reduction */
2144c92abb8aSShri Abhyankar       if (vi->lsmonitor) {
2145c92abb8aSShri Abhyankar         ierr = PetscViewerASCIIMonitorPrintf(vi->lsmonitor,"    Line Search: Quadratically determined step, lambda=%G\n",lambda);CHKERRQ(ierr);
21462b4ed282SShri Abhyankar       }
21472b4ed282SShri Abhyankar       break;
21482b4ed282SShri Abhyankar     }
21492b4ed282SShri Abhyankar     count++;
21502b4ed282SShri Abhyankar   }
21512b4ed282SShri Abhyankar   theend2:
21522b4ed282SShri Abhyankar   /* Optional user-defined check for line search step validity */
21532b4ed282SShri Abhyankar   if (vi->postcheckstep) {
21542b4ed282SShri Abhyankar     ierr = (*vi->postcheckstep)(snes,x,y,w,vi->postcheck,&changed_y,&changed_w);CHKERRQ(ierr);
21552b4ed282SShri Abhyankar     if (changed_y) {
21562b4ed282SShri Abhyankar       ierr = VecWAXPY(w,-1.0,y,x);CHKERRQ(ierr);
21577fe79bc4SShri Abhyankar       ierr = SNESVIProjectOntoBounds(snes,w);CHKERRQ(ierr);
21582b4ed282SShri Abhyankar     }
21592b4ed282SShri Abhyankar     if (changed_y || changed_w) { /* recompute the function if the step has changed */
21602b4ed282SShri Abhyankar       ierr = SNESComputeFunction(snes,w,g);
21612b4ed282SShri Abhyankar       if (snes->domainerror) {
21622b4ed282SShri Abhyankar         ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21632b4ed282SShri Abhyankar         PetscFunctionReturn(0);
21642b4ed282SShri Abhyankar       }
21652f63a38cSShri Abhyankar       if (snes->ops->solve != SNESSolveVI_SS) {
21667fe79bc4SShri Abhyankar         ierr = SNESVIComputeInactiveSetFnorm(snes,g,w,gnorm);CHKERRQ(ierr);
21677fe79bc4SShri Abhyankar       } else {
21687fe79bc4SShri Abhyankar         ierr = VecNorm(g,NORM_2,gnorm);CHKERRQ(ierr);
21697fe79bc4SShri Abhyankar       }
21707fe79bc4SShri Abhyankar 
21712b4ed282SShri Abhyankar       ierr = VecNormBegin(y,NORM_2,ynorm);CHKERRQ(ierr);
21722b4ed282SShri Abhyankar       ierr = VecNormEnd(y,NORM_2,ynorm);CHKERRQ(ierr);
217362cbcd01SMatthew G Knepley       if (PetscIsInfOrNanReal(*gnorm)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
21742b4ed282SShri Abhyankar     }
21752b4ed282SShri Abhyankar   }
21762b4ed282SShri Abhyankar   ierr = PetscLogEventEnd(SNES_LineSearch,snes,x,f,g);CHKERRQ(ierr);
21772b4ed282SShri Abhyankar   PetscFunctionReturn(0);
21782b4ed282SShri Abhyankar }
21792b4ed282SShri Abhyankar 
2180ace3abfcSBarry 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*/
21812b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
21822b4ed282SShri Abhyankar EXTERN_C_BEGIN
21832b4ed282SShri Abhyankar #undef __FUNCT__
21842b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSet_VI"
21857087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSet_VI(SNES snes,FCN2 func,void *lsctx)
21862b4ed282SShri Abhyankar {
21872b4ed282SShri Abhyankar   PetscFunctionBegin;
21882b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->LineSearch = func;
21892b4ed282SShri Abhyankar   ((SNES_VI *)(snes->data))->lsP        = lsctx;
21902b4ed282SShri Abhyankar   PetscFunctionReturn(0);
21912b4ed282SShri Abhyankar }
21922b4ed282SShri Abhyankar EXTERN_C_END
21932b4ed282SShri Abhyankar 
21942b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
21952b4ed282SShri Abhyankar EXTERN_C_BEGIN
21962b4ed282SShri Abhyankar #undef __FUNCT__
21972b4ed282SShri Abhyankar #define __FUNCT__ "SNESLineSearchSetMonitor_VI"
21987087cfbeSBarry Smith PetscErrorCode  SNESLineSearchSetMonitor_VI(SNES snes,PetscBool flg)
21992b4ed282SShri Abhyankar {
22002b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI*)snes->data;
22012b4ed282SShri Abhyankar   PetscErrorCode ierr;
22022b4ed282SShri Abhyankar 
22032b4ed282SShri Abhyankar   PetscFunctionBegin;
2204c92abb8aSShri Abhyankar   if (flg && !vi->lsmonitor) {
2205c92abb8aSShri Abhyankar     ierr = PetscViewerASCIIMonitorCreate(((PetscObject)snes)->comm,"stdout",((PetscObject)snes)->tablevel,&vi->lsmonitor);CHKERRQ(ierr);
2206c92abb8aSShri Abhyankar   } else if (!flg && vi->lsmonitor) {
22076bf464f9SBarry Smith     ierr = PetscViewerASCIIMonitorDestroy(&vi->lsmonitor);CHKERRQ(ierr);
22082b4ed282SShri Abhyankar   }
22092b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22102b4ed282SShri Abhyankar }
22112b4ed282SShri Abhyankar EXTERN_C_END
22122b4ed282SShri Abhyankar 
22132b4ed282SShri Abhyankar /*
22142b4ed282SShri Abhyankar    SNESView_VI - Prints info from the SNESVI data structure.
22152b4ed282SShri Abhyankar 
22162b4ed282SShri Abhyankar    Input Parameters:
22172b4ed282SShri Abhyankar .  SNES - the SNES context
22182b4ed282SShri Abhyankar .  viewer - visualization context
22192b4ed282SShri Abhyankar 
22202b4ed282SShri Abhyankar    Application Interface Routine: SNESView()
22212b4ed282SShri Abhyankar */
22222b4ed282SShri Abhyankar #undef __FUNCT__
22232b4ed282SShri Abhyankar #define __FUNCT__ "SNESView_VI"
22242b4ed282SShri Abhyankar static PetscErrorCode SNESView_VI(SNES snes,PetscViewer viewer)
22252b4ed282SShri Abhyankar {
22262b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
222778c4b9d3SShri Abhyankar   const char     *cstr,*tstr;
22282b4ed282SShri Abhyankar   PetscErrorCode ierr;
2229ace3abfcSBarry Smith   PetscBool     iascii;
22302b4ed282SShri Abhyankar 
22312b4ed282SShri Abhyankar   PetscFunctionBegin;
22322b4ed282SShri Abhyankar   ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
22332b4ed282SShri Abhyankar   if (iascii) {
22342b4ed282SShri Abhyankar     if (vi->LineSearch == SNESLineSearchNo_VI)             cstr = "SNESLineSearchNo";
22352b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchQuadratic_VI) cstr = "SNESLineSearchQuadratic";
22362b4ed282SShri Abhyankar     else if (vi->LineSearch == SNESLineSearchCubic_VI)     cstr = "SNESLineSearchCubic";
22372b4ed282SShri Abhyankar     else                                                   cstr = "unknown";
223878c4b9d3SShri Abhyankar     if (snes->ops->solve == SNESSolveVI_SS)         tstr = "Semismooth";
22390a7c7af0SShri Abhyankar     else if (snes->ops->solve == SNESSolveVI_RS)    tstr = "Reduced Space";
2240b350b9c9SBarry Smith     else if (snes->ops->solve == SNESSolveVI_RSAUG) tstr = "Reduced space with augmented variables";
224178c4b9d3SShri Abhyankar     else                                         tstr = "unknown";
224278c4b9d3SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  VI algorithm: %s\n",tstr);CHKERRQ(ierr);
22432b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  line search variant: %s\n",cstr);CHKERRQ(ierr);
22442b4ed282SShri Abhyankar     ierr = PetscViewerASCIIPrintf(viewer,"  alpha=%G, maxstep=%G, minlambda=%G\n",vi->alpha,vi->maxstep,vi->minlambda);CHKERRQ(ierr);
22452b4ed282SShri Abhyankar   } else {
22462b4ed282SShri Abhyankar     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported for SNES EQ VI",((PetscObject)viewer)->type_name);
22472b4ed282SShri Abhyankar   }
22482b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22492b4ed282SShri Abhyankar }
22502b4ed282SShri Abhyankar 
22515559b345SBarry Smith #undef __FUNCT__
22525559b345SBarry Smith #define __FUNCT__ "SNESVISetVariableBounds"
22535559b345SBarry Smith /*@
22542b4ed282SShri Abhyankar    SNESVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu.
22552b4ed282SShri Abhyankar 
22562b4ed282SShri Abhyankar    Input Parameters:
22572b4ed282SShri Abhyankar .  snes - the SNES context.
22582b4ed282SShri Abhyankar .  xl   - lower bound.
22592b4ed282SShri Abhyankar .  xu   - upper bound.
22602b4ed282SShri Abhyankar 
22612b4ed282SShri Abhyankar    Notes:
22622b4ed282SShri Abhyankar    If this routine is not called then the lower and upper bounds are set to
226301f0b76bSBarry Smith    SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
226484c105d7SBarry Smith 
22655559b345SBarry Smith @*/
226669c03620SShri Abhyankar PetscErrorCode SNESVISetVariableBounds(SNES snes, Vec xl, Vec xu)
22672b4ed282SShri Abhyankar {
2268d923200aSJungho Lee   SNES_VI        *vi;
2269d923200aSJungho Lee   PetscErrorCode ierr;
22702b4ed282SShri Abhyankar 
22712b4ed282SShri Abhyankar   PetscFunctionBegin;
22722b4ed282SShri Abhyankar   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
22732b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xl,VEC_CLASSID,2);
22742b4ed282SShri Abhyankar   PetscValidHeaderSpecific(xu,VEC_CLASSID,3);
22752b4ed282SShri Abhyankar   if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call SNESSetFunction() first");
22762b4ed282SShri 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);
22772b4ed282SShri 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);
2278d923200aSJungho Lee   ierr = SNESSetType(snes,SNESVI);CHKERRQ(ierr);
2279d923200aSJungho Lee   vi = (SNES_VI*)snes->data;
22802b4ed282SShri Abhyankar   vi->usersetxbounds = PETSC_TRUE;
22812b4ed282SShri Abhyankar   vi->xl = xl;
22822b4ed282SShri Abhyankar   vi->xu = xu;
22832b4ed282SShri Abhyankar   PetscFunctionReturn(0);
22842b4ed282SShri Abhyankar }
2285693ddf92SShri Abhyankar 
22862b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
22872b4ed282SShri Abhyankar /*
22882b4ed282SShri Abhyankar    SNESSetFromOptions_VI - Sets various parameters for the SNESVI method.
22892b4ed282SShri Abhyankar 
22902b4ed282SShri Abhyankar    Input Parameter:
22912b4ed282SShri Abhyankar .  snes - the SNES context
22922b4ed282SShri Abhyankar 
22932b4ed282SShri Abhyankar    Application Interface Routine: SNESSetFromOptions()
22942b4ed282SShri Abhyankar */
22952b4ed282SShri Abhyankar #undef __FUNCT__
22962b4ed282SShri Abhyankar #define __FUNCT__ "SNESSetFromOptions_VI"
22972b4ed282SShri Abhyankar static PetscErrorCode SNESSetFromOptions_VI(SNES snes)
22982b4ed282SShri Abhyankar {
22992b4ed282SShri Abhyankar   SNES_VI        *vi = (SNES_VI *)snes->data;
23007fe79bc4SShri Abhyankar   const char     *lses[] = {"basic","basicnonorms","quadratic","cubic"};
2301b350b9c9SBarry Smith   const char     *vies[] = {"ss","rs","rsaug"};
23022b4ed282SShri Abhyankar   PetscErrorCode ierr;
23032b4ed282SShri Abhyankar   PetscInt       indx;
230469c03620SShri Abhyankar   PetscBool      flg,set,flg2;
23052b4ed282SShri Abhyankar 
23062b4ed282SShri Abhyankar   PetscFunctionBegin;
23072b4ed282SShri Abhyankar   ierr = PetscOptionsHead("SNES semismooth method options");CHKERRQ(ierr);
23089308c137SBarry Smith   ierr = PetscOptionsBool("-snes_vi_monitor","Monitor all non-active variables","None",PETSC_FALSE,&flg,0);CHKERRQ(ierr);
23099308c137SBarry Smith   if (flg) {
23109308c137SBarry Smith     ierr = SNESMonitorSet(snes,SNESMonitorVI,0,0);CHKERRQ(ierr);
23119308c137SBarry Smith   }
2312be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_alpha","Function norm must decrease by","None",vi->alpha,&vi->alpha,0);CHKERRQ(ierr);
2313be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_maxstep","Step must be less than","None",vi->maxstep,&vi->maxstep,0);CHKERRQ(ierr);
2314be6adb11SBarry Smith   ierr = PetscOptionsReal("-snes_ls_minlambda","Minimum lambda allowed","None",vi->minlambda,&vi->minlambda,0);CHKERRQ(ierr);
23152b4ed282SShri Abhyankar   ierr = PetscOptionsReal("-snes_vi_const_tol","constraint tolerance","None",vi->const_tol,&vi->const_tol,0);CHKERRQ(ierr);
2316be6adb11SBarry Smith   ierr = PetscOptionsBool("-snes_ls_monitor","Print progress of line searches","SNESLineSearchSetMonitor",vi->lsmonitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
23172b4ed282SShri Abhyankar   if (set) {ierr = SNESLineSearchSetMonitor(snes,flg);CHKERRQ(ierr);}
23182f63a38cSShri Abhyankar   ierr = PetscOptionsEList("-snes_vi_type","Semismooth algorithm used","",vies,3,"ss",&indx,&flg2);CHKERRQ(ierr);
231969c03620SShri Abhyankar   if (flg2) {
232069c03620SShri Abhyankar     switch (indx) {
232169c03620SShri Abhyankar     case 0:
232269c03620SShri Abhyankar       snes->ops->solve = SNESSolveVI_SS;
232369c03620SShri Abhyankar       break;
232469c03620SShri Abhyankar     case 1:
2325d950fb63SShri Abhyankar       snes->ops->solve = SNESSolveVI_RS;
2326d950fb63SShri Abhyankar       break;
23272f63a38cSShri Abhyankar     case 2:
2328b350b9c9SBarry Smith       snes->ops->solve = SNESSolveVI_RSAUG;
232969c03620SShri Abhyankar     }
233069c03620SShri Abhyankar   }
2331be6adb11SBarry Smith   ierr = PetscOptionsEList("-snes_ls","Line search used","SNESLineSearchSet",lses,4,"basic",&indx,&flg);CHKERRQ(ierr);
23322b4ed282SShri Abhyankar   if (flg) {
23332b4ed282SShri Abhyankar     switch (indx) {
23342b4ed282SShri Abhyankar     case 0:
23352b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNo_VI,PETSC_NULL);CHKERRQ(ierr);
23362b4ed282SShri Abhyankar       break;
23372b4ed282SShri Abhyankar     case 1:
23382b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchNoNorms_VI,PETSC_NULL);CHKERRQ(ierr);
23392b4ed282SShri Abhyankar       break;
23402b4ed282SShri Abhyankar     case 2:
23412b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchQuadratic_VI,PETSC_NULL);CHKERRQ(ierr);
23422b4ed282SShri Abhyankar       break;
23432b4ed282SShri Abhyankar     case 3:
23442b4ed282SShri Abhyankar       ierr = SNESLineSearchSet(snes,SNESLineSearchCubic_VI,PETSC_NULL);CHKERRQ(ierr);
23452b4ed282SShri Abhyankar       break;
23462b4ed282SShri Abhyankar     }
2347fe835674SShri Abhyankar   }
23482b4ed282SShri Abhyankar   ierr = PetscOptionsTail();CHKERRQ(ierr);
23492b4ed282SShri Abhyankar   PetscFunctionReturn(0);
23502b4ed282SShri Abhyankar }
23512b4ed282SShri Abhyankar /* -------------------------------------------------------------------------- */
23522b4ed282SShri Abhyankar /*MC
23538b4c83edSBarry Smith       SNESVI - Various solvers for variational inequalities based on Newton's method
23542b4ed282SShri Abhyankar 
23552b4ed282SShri Abhyankar    Options Database:
23568b4c83edSBarry 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
23578b4c83edSBarry Smith                                 additional variables that enforce the constraints
23588b4c83edSBarry Smith -   -snes_vi_monitor - prints the number of active constraints at each iteration.
23592b4ed282SShri Abhyankar 
23602b4ed282SShri Abhyankar 
23612b4ed282SShri Abhyankar    Level: beginner
23622b4ed282SShri Abhyankar 
23632b4ed282SShri Abhyankar .seealso:  SNESCreate(), SNES, SNESSetType(), SNESTR, SNESLineSearchSet(),
23642b4ed282SShri Abhyankar            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
23652b4ed282SShri Abhyankar            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
23662b4ed282SShri Abhyankar 
23672b4ed282SShri Abhyankar M*/
23682b4ed282SShri Abhyankar EXTERN_C_BEGIN
23692b4ed282SShri Abhyankar #undef __FUNCT__
23702b4ed282SShri Abhyankar #define __FUNCT__ "SNESCreate_VI"
23717087cfbeSBarry Smith PetscErrorCode  SNESCreate_VI(SNES snes)
23722b4ed282SShri Abhyankar {
23732b4ed282SShri Abhyankar   PetscErrorCode ierr;
23742b4ed282SShri Abhyankar   SNES_VI      *vi;
23752b4ed282SShri Abhyankar 
23762b4ed282SShri Abhyankar   PetscFunctionBegin;
23772b4ed282SShri Abhyankar   snes->ops->setup           = SNESSetUp_VI;
2378edafb9efSBarry Smith   snes->ops->solve           = SNESSolveVI_RS;
23792b4ed282SShri Abhyankar   snes->ops->destroy         = SNESDestroy_VI;
23802b4ed282SShri Abhyankar   snes->ops->setfromoptions  = SNESSetFromOptions_VI;
23812b4ed282SShri Abhyankar   snes->ops->view            = SNESView_VI;
238237596af1SLisandro Dalcin   snes->ops->reset           = 0; /* XXX Implement!!! */
23832b4ed282SShri Abhyankar   snes->ops->converged       = SNESDefaultConverged_VI;
23842b4ed282SShri Abhyankar 
23852b4ed282SShri Abhyankar   ierr                  = PetscNewLog(snes,SNES_VI,&vi);CHKERRQ(ierr);
23862b4ed282SShri Abhyankar   snes->data            = (void*)vi;
23872b4ed282SShri Abhyankar   vi->alpha             = 1.e-4;
23882b4ed282SShri Abhyankar   vi->maxstep           = 1.e8;
23892b4ed282SShri Abhyankar   vi->minlambda         = 1.e-12;
23907fe79bc4SShri Abhyankar   vi->LineSearch        = SNESLineSearchNo_VI;
23912b4ed282SShri Abhyankar   vi->lsP               = PETSC_NULL;
23922b4ed282SShri Abhyankar   vi->postcheckstep     = PETSC_NULL;
23932b4ed282SShri Abhyankar   vi->postcheck         = PETSC_NULL;
23942b4ed282SShri Abhyankar   vi->precheckstep      = PETSC_NULL;
23952b4ed282SShri Abhyankar   vi->precheck          = PETSC_NULL;
23962b4ed282SShri Abhyankar   vi->const_tol         =  2.2204460492503131e-16;
23972f63a38cSShri Abhyankar   vi->checkredundancy   = PETSC_NULL;
23982b4ed282SShri Abhyankar 
23992b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSetMonitor_C","SNESLineSearchSetMonitor_VI",SNESLineSearchSetMonitor_VI);CHKERRQ(ierr);
24002b4ed282SShri Abhyankar   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESLineSearchSet_C","SNESLineSearchSet_VI",SNESLineSearchSet_VI);CHKERRQ(ierr);
24012b4ed282SShri Abhyankar 
24022b4ed282SShri Abhyankar   PetscFunctionReturn(0);
24032b4ed282SShri Abhyankar }
24042b4ed282SShri Abhyankar EXTERN_C_END
2405