xref: /petsc/src/snes/impls/vi/rs/virs.c (revision a71f0d7d9375a154061b6b52b45db4a1fedb0dea)
1c2fc9fa9SBarry Smith 
2c2fc9fa9SBarry Smith #include <../src/snes/impls/vi/rs/virsimpl.h> /*I "petscsnes.h" I*/
3b45d2f2cSJed Brown #include <../include/petsc-private/kspimpl.h>
4b45d2f2cSJed Brown #include <../include/petsc-private/matimpl.h>
5b45d2f2cSJed Brown #include <../include/petsc-private/dmimpl.h>
6c2fc9fa9SBarry Smith 
7c2fc9fa9SBarry Smith #undef __FUNCT__
8c2fc9fa9SBarry Smith #define __FUNCT__ "SNESVIGetInactiveSet"
9c2fc9fa9SBarry Smith /*
10c2fc9fa9SBarry Smith    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
11c2fc9fa9SBarry Smith      system is solved on)
12c2fc9fa9SBarry Smith 
13c2fc9fa9SBarry Smith    Input parameter
14c2fc9fa9SBarry Smith .  snes - the SNES context
15c2fc9fa9SBarry Smith 
16c2fc9fa9SBarry Smith    Output parameter
17c2fc9fa9SBarry Smith .  ISact - active set index set
18c2fc9fa9SBarry Smith 
19c2fc9fa9SBarry Smith  */
20c2fc9fa9SBarry Smith PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS *inact)
21c2fc9fa9SBarry Smith {
22f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*)snes->data;
236e111a19SKarl Rupp 
24c2fc9fa9SBarry Smith   PetscFunctionBegin;
25c2fc9fa9SBarry Smith   *inact = vi->IS_inact_prev;
26c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
27c2fc9fa9SBarry Smith }
28c2fc9fa9SBarry Smith 
29c2fc9fa9SBarry Smith /*
30c2fc9fa9SBarry Smith     Provides a wrapper to a DM to allow it to be used to generated the interpolation/restriction from the DM for the smaller matrices and vectors
31c2fc9fa9SBarry Smith   defined by the reduced space method.
32c2fc9fa9SBarry Smith 
33c2fc9fa9SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
34c2fc9fa9SBarry Smith 
35c2fc9fa9SBarry Smith <*/
36c2fc9fa9SBarry Smith typedef struct {
37c2fc9fa9SBarry Smith   PetscInt n;                                              /* size of vectors in the reduced DM space */
38c2fc9fa9SBarry Smith   IS       inactive;
39f5af7f23SKarl Rupp 
4025296bd5SBarry Smith   PetscErrorCode (*createinterpolation)(DM,DM,Mat*,Vec*);  /* DM's original routines */
41c2fc9fa9SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
42c2fc9fa9SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
43f5af7f23SKarl Rupp 
44c2fc9fa9SBarry Smith   DM dm;                                                  /* when destroying this object we need to reset the above function into the base DM */
45c2fc9fa9SBarry Smith } DM_SNESVI;
46c2fc9fa9SBarry Smith 
47c2fc9fa9SBarry Smith #undef __FUNCT__
48c2fc9fa9SBarry Smith #define __FUNCT__ "DMCreateGlobalVector_SNESVI"
49c2fc9fa9SBarry Smith /*
50c2fc9fa9SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
51c2fc9fa9SBarry Smith 
52c2fc9fa9SBarry Smith */
53c2fc9fa9SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
54c2fc9fa9SBarry Smith {
55c2fc9fa9SBarry Smith   PetscErrorCode ierr;
56c2fc9fa9SBarry Smith   PetscContainer isnes;
57c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi;
58c2fc9fa9SBarry Smith 
59c2fc9fa9SBarry Smith   PetscFunctionBegin;
60c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
61c2fc9fa9SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm)->comm,PETSC_ERR_PLIB,"Composed SNES is missing");
62c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
63c2fc9fa9SBarry Smith   ierr = VecCreateMPI(((PetscObject)dm)->comm,dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
64c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
65c2fc9fa9SBarry Smith }
66c2fc9fa9SBarry Smith 
67c2fc9fa9SBarry Smith #undef __FUNCT__
68e727c939SJed Brown #define __FUNCT__ "DMCreateInterpolation_SNESVI"
69c2fc9fa9SBarry Smith /*
70e727c939SJed Brown      DMCreateInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
71c2fc9fa9SBarry Smith 
72c2fc9fa9SBarry Smith */
73e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
74c2fc9fa9SBarry Smith {
75c2fc9fa9SBarry Smith   PetscErrorCode ierr;
76c2fc9fa9SBarry Smith   PetscContainer isnes;
77c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi1,*dmsnesvi2;
78c2fc9fa9SBarry Smith   Mat            interp;
79c2fc9fa9SBarry Smith 
80c2fc9fa9SBarry Smith   PetscFunctionBegin;
81c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
82c2fc9fa9SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
83c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
84c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
85c2fc9fa9SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm2)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
86c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
87c2fc9fa9SBarry Smith 
880298fd71SBarry Smith   ierr = (*dmsnesvi1->createinterpolation)(dm1,dm2,&interp,NULL);CHKERRQ(ierr);
89c2fc9fa9SBarry Smith   ierr = MatGetSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
90c2fc9fa9SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
91c2fc9fa9SBarry Smith   *vec = 0;
92c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
93c2fc9fa9SBarry Smith }
94c2fc9fa9SBarry Smith 
95c2fc9fa9SBarry Smith extern PetscErrorCode  DMSetVI(DM,IS);
96c2fc9fa9SBarry Smith 
97c2fc9fa9SBarry Smith #undef __FUNCT__
98c2fc9fa9SBarry Smith #define __FUNCT__ "DMCoarsen_SNESVI"
99c2fc9fa9SBarry Smith /*
100c2fc9fa9SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
101c2fc9fa9SBarry Smith 
102c2fc9fa9SBarry Smith */
103c2fc9fa9SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
104c2fc9fa9SBarry Smith {
105c2fc9fa9SBarry Smith   PetscErrorCode ierr;
106c2fc9fa9SBarry Smith   PetscContainer isnes;
107c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi1;
108c2fc9fa9SBarry Smith   Vec            finemarked,coarsemarked;
109c2fc9fa9SBarry Smith   IS             inactive;
110c2fc9fa9SBarry Smith   VecScatter     inject;
111c2fc9fa9SBarry Smith   const PetscInt *index;
112c2fc9fa9SBarry Smith   PetscInt       n,k,cnt = 0,rstart,*coarseindex;
113c2fc9fa9SBarry Smith   PetscScalar    *marked;
114c2fc9fa9SBarry Smith 
115c2fc9fa9SBarry Smith   PetscFunctionBegin;
116c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
117c2fc9fa9SBarry Smith   if (!isnes) SETERRQ(((PetscObject)dm1)->comm,PETSC_ERR_PLIB,"Composed VI data structure is missing");
118c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
119c2fc9fa9SBarry Smith 
120c2fc9fa9SBarry Smith   /* get the original coarsen */
121c2fc9fa9SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
122c2fc9fa9SBarry Smith 
123c2fc9fa9SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
124c2fc9fa9SBarry Smith   ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);
125c2fc9fa9SBarry Smith 
126c2fc9fa9SBarry Smith   /* need to set back global vectors in order to use the original injection */
127c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
1281aa26658SKarl Rupp 
129c2fc9fa9SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
1301aa26658SKarl Rupp 
131c2fc9fa9SBarry Smith   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
132c2fc9fa9SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
133c2fc9fa9SBarry Smith 
134c2fc9fa9SBarry Smith   /*
135c2fc9fa9SBarry Smith      fill finemarked with locations of inactive points
136c2fc9fa9SBarry Smith   */
137c2fc9fa9SBarry Smith   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
138c2fc9fa9SBarry Smith   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
139c2fc9fa9SBarry Smith   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
140c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
141c2fc9fa9SBarry Smith     ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
142c2fc9fa9SBarry Smith   }
143c2fc9fa9SBarry Smith   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
144c2fc9fa9SBarry Smith   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
145c2fc9fa9SBarry Smith 
146e727c939SJed Brown   ierr = DMCreateInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
147c2fc9fa9SBarry Smith   ierr = VecScatterBegin(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
148c2fc9fa9SBarry Smith   ierr = VecScatterEnd(inject,finemarked,coarsemarked,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
149c2fc9fa9SBarry Smith   ierr = VecScatterDestroy(&inject);CHKERRQ(ierr);
150c2fc9fa9SBarry Smith 
151c2fc9fa9SBarry Smith   /*
152c2fc9fa9SBarry Smith      create index set list of coarse inactive points from coarsemarked
153c2fc9fa9SBarry Smith   */
154c2fc9fa9SBarry Smith   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
1550298fd71SBarry Smith   ierr = VecGetOwnershipRange(coarsemarked,&rstart,NULL);CHKERRQ(ierr);
156c2fc9fa9SBarry Smith   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
157c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
158c2fc9fa9SBarry Smith     if (marked[k] != 0.0) cnt++;
159c2fc9fa9SBarry Smith   }
160c2fc9fa9SBarry Smith   ierr = PetscMalloc(cnt*sizeof(PetscInt),&coarseindex);CHKERRQ(ierr);
161c2fc9fa9SBarry Smith   cnt  = 0;
162c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
163c2fc9fa9SBarry Smith     if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart;
164c2fc9fa9SBarry Smith   }
165c2fc9fa9SBarry Smith   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
1665f042095SDmitry Karpeev   ierr = ISCreateGeneral(((PetscObject)coarsemarked)->comm,cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
167c2fc9fa9SBarry Smith 
168c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
1691aa26658SKarl Rupp 
170c2fc9fa9SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
1711aa26658SKarl Rupp 
172c2fc9fa9SBarry Smith   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
173c2fc9fa9SBarry Smith 
174c2fc9fa9SBarry Smith   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
175c2fc9fa9SBarry Smith   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
176c2fc9fa9SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
177c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
178c2fc9fa9SBarry Smith }
179c2fc9fa9SBarry Smith 
180c2fc9fa9SBarry Smith #undef __FUNCT__
181c2fc9fa9SBarry Smith #define __FUNCT__ "DMDestroy_SNESVI"
182c2fc9fa9SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
183c2fc9fa9SBarry Smith {
184c2fc9fa9SBarry Smith   PetscErrorCode ierr;
185c2fc9fa9SBarry Smith 
186c2fc9fa9SBarry Smith   PetscFunctionBegin;
187c2fc9fa9SBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
18825296bd5SBarry Smith   dmsnesvi->dm->ops->createinterpolation = dmsnesvi->createinterpolation;
189c2fc9fa9SBarry Smith   dmsnesvi->dm->ops->coarsen             = dmsnesvi->coarsen;
190c2fc9fa9SBarry Smith   dmsnesvi->dm->ops->createglobalvector  = dmsnesvi->createglobalvector;
191c2fc9fa9SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
192c2fc9fa9SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
193c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
194c2fc9fa9SBarry Smith 
195c2fc9fa9SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
196c2fc9fa9SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
197c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
198c2fc9fa9SBarry Smith }
199c2fc9fa9SBarry Smith 
200c2fc9fa9SBarry Smith #undef __FUNCT__
201c2fc9fa9SBarry Smith #define __FUNCT__ "DMSetVI"
202c2fc9fa9SBarry Smith /*
203c2fc9fa9SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
204c2fc9fa9SBarry Smith                be restricted to only those variables NOT associated with active constraints.
205c2fc9fa9SBarry Smith 
206c2fc9fa9SBarry Smith */
207c2fc9fa9SBarry Smith PetscErrorCode  DMSetVI(DM dm,IS inactive)
208c2fc9fa9SBarry Smith {
209c2fc9fa9SBarry Smith   PetscErrorCode ierr;
210c2fc9fa9SBarry Smith   PetscContainer isnes;
211c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi;
212c2fc9fa9SBarry Smith 
213c2fc9fa9SBarry Smith   PetscFunctionBegin;
214c2fc9fa9SBarry Smith   if (!dm) PetscFunctionReturn(0);
215c2fc9fa9SBarry Smith 
216c2fc9fa9SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
217c2fc9fa9SBarry Smith 
218c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
219c2fc9fa9SBarry Smith   if (!isnes) {
220c2fc9fa9SBarry Smith     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&isnes);CHKERRQ(ierr);
221c2fc9fa9SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
222c2fc9fa9SBarry Smith     ierr = PetscNew(DM_SNESVI,&dmsnesvi);CHKERRQ(ierr);
223c2fc9fa9SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
224c2fc9fa9SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
225c2fc9fa9SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
2261aa26658SKarl Rupp 
22725296bd5SBarry Smith     dmsnesvi->createinterpolation = dm->ops->createinterpolation;
22825296bd5SBarry Smith     dm->ops->createinterpolation  = DMCreateInterpolation_SNESVI;
229c2fc9fa9SBarry Smith     dmsnesvi->coarsen             = dm->ops->coarsen;
230c2fc9fa9SBarry Smith     dm->ops->coarsen              = DMCoarsen_SNESVI;
231c2fc9fa9SBarry Smith     dmsnesvi->createglobalvector  = dm->ops->createglobalvector;
232c2fc9fa9SBarry Smith     dm->ops->createglobalvector   = DMCreateGlobalVector_SNESVI;
233c2fc9fa9SBarry Smith   } else {
234c2fc9fa9SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
235c2fc9fa9SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
236c2fc9fa9SBarry Smith   }
237c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
238c2fc9fa9SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
2391aa26658SKarl Rupp 
240c2fc9fa9SBarry Smith   dmsnesvi->inactive = inactive;
241c2fc9fa9SBarry Smith   dmsnesvi->dm       = dm;
242c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
243c2fc9fa9SBarry Smith }
244c2fc9fa9SBarry Smith 
245c2fc9fa9SBarry Smith #undef __FUNCT__
246c2fc9fa9SBarry Smith #define __FUNCT__ "DMDestroyVI"
247c2fc9fa9SBarry Smith /*
248c2fc9fa9SBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
24925296bd5SBarry Smith          - also resets the function pointers in the DM for createinterpolation() etc to use the original DM
250c2fc9fa9SBarry Smith */
251c2fc9fa9SBarry Smith PetscErrorCode  DMDestroyVI(DM dm)
252c2fc9fa9SBarry Smith {
253c2fc9fa9SBarry Smith   PetscErrorCode ierr;
254c2fc9fa9SBarry Smith 
255c2fc9fa9SBarry Smith   PetscFunctionBegin;
256c2fc9fa9SBarry Smith   if (!dm) PetscFunctionReturn(0);
2570298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)NULL);CHKERRQ(ierr);
258c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
259c2fc9fa9SBarry Smith }
260c2fc9fa9SBarry Smith 
261c2fc9fa9SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
262c2fc9fa9SBarry Smith 
263c2fc9fa9SBarry Smith 
264c2fc9fa9SBarry Smith 
265c2fc9fa9SBarry Smith 
266c2fc9fa9SBarry Smith #undef __FUNCT__
267f450aa47SBarry Smith #define __FUNCT__ "SNESCreateIndexSets_VINEWTONRSLS"
268f450aa47SBarry Smith PetscErrorCode SNESCreateIndexSets_VINEWTONRSLS(SNES snes,Vec X,Vec F,IS *ISact,IS *ISinact)
269c2fc9fa9SBarry Smith {
270c2fc9fa9SBarry Smith   PetscErrorCode ierr;
271c2fc9fa9SBarry Smith 
272c2fc9fa9SBarry Smith   PetscFunctionBegin;
273c2fc9fa9SBarry Smith   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
274c2fc9fa9SBarry Smith   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
275c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
276c2fc9fa9SBarry Smith }
277c2fc9fa9SBarry Smith 
278c2fc9fa9SBarry Smith /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
279c2fc9fa9SBarry Smith #undef __FUNCT__
280f450aa47SBarry Smith #define __FUNCT__ "SNESCreateSubVectors_VINEWTONRSLS"
281f450aa47SBarry Smith PetscErrorCode SNESCreateSubVectors_VINEWTONRSLS(SNES snes,PetscInt n,Vec *newv)
282c2fc9fa9SBarry Smith {
283c2fc9fa9SBarry Smith   PetscErrorCode ierr;
284c2fc9fa9SBarry Smith   Vec            v;
285c2fc9fa9SBarry Smith 
286c2fc9fa9SBarry Smith   PetscFunctionBegin;
287c2fc9fa9SBarry Smith   ierr  = VecCreate(((PetscObject)snes)->comm,&v);CHKERRQ(ierr);
288c2fc9fa9SBarry Smith   ierr  = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
289c2fc9fa9SBarry Smith   ierr  = VecSetFromOptions(v);CHKERRQ(ierr);
290c2fc9fa9SBarry Smith   *newv = v;
291c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
292c2fc9fa9SBarry Smith }
293c2fc9fa9SBarry Smith 
294c2fc9fa9SBarry Smith /* Resets the snes PC and KSP when the active set sizes change */
295c2fc9fa9SBarry Smith #undef __FUNCT__
296c2fc9fa9SBarry Smith #define __FUNCT__ "SNESVIResetPCandKSP"
297c2fc9fa9SBarry Smith PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
298c2fc9fa9SBarry Smith {
299c2fc9fa9SBarry Smith   PetscErrorCode ierr;
300c2fc9fa9SBarry Smith   KSP            snesksp;
301c2fc9fa9SBarry Smith 
302c2fc9fa9SBarry Smith   PetscFunctionBegin;
303c2fc9fa9SBarry Smith   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
304c2fc9fa9SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
305c2fc9fa9SBarry Smith 
306c2fc9fa9SBarry Smith   /*
307c2fc9fa9SBarry Smith   KSP                    kspnew;
308c2fc9fa9SBarry Smith   PC                     pcnew;
309c2fc9fa9SBarry Smith   const MatSolverPackage stype;
310c2fc9fa9SBarry Smith 
311c2fc9fa9SBarry Smith 
312c2fc9fa9SBarry Smith   ierr = KSPCreate(((PetscObject)snes)->comm,&kspnew);CHKERRQ(ierr);
313c2fc9fa9SBarry Smith   kspnew->pc_side = snesksp->pc_side;
314c2fc9fa9SBarry Smith   kspnew->rtol    = snesksp->rtol;
315c2fc9fa9SBarry Smith   kspnew->abstol    = snesksp->abstol;
316c2fc9fa9SBarry Smith   kspnew->max_it  = snesksp->max_it;
317c2fc9fa9SBarry Smith   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
318c2fc9fa9SBarry Smith   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
319c2fc9fa9SBarry Smith   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
320c2fc9fa9SBarry Smith   ierr = PCSetOperators(kspnew->pc,Amat,Pmat,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr);
321c2fc9fa9SBarry Smith   ierr = PCFactorGetMatSolverPackage(snesksp->pc,&stype);CHKERRQ(ierr);
322c2fc9fa9SBarry Smith   ierr = PCFactorSetMatSolverPackage(kspnew->pc,stype);CHKERRQ(ierr);
323c2fc9fa9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
324c2fc9fa9SBarry Smith   snes->ksp = kspnew;
325c2fc9fa9SBarry Smith   ierr = PetscLogObjectParent(snes,kspnew);CHKERRQ(ierr);
326c2fc9fa9SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
327c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
328c2fc9fa9SBarry Smith }
329c2fc9fa9SBarry Smith 
330c2fc9fa9SBarry Smith /* Variational Inequality solver using reduce space method. No semismooth algorithm is
331c2fc9fa9SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
332c2fc9fa9SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
333c2fc9fa9SBarry Smith #undef __FUNCT__
334f450aa47SBarry Smith #define __FUNCT__ "SNESSolve_VINEWTONRSLS"
335f450aa47SBarry Smith PetscErrorCode SNESSolve_VINEWTONRSLS(SNES snes)
336c2fc9fa9SBarry Smith {
337f450aa47SBarry Smith   SNES_VINEWTONRSLS  *vi = (SNES_VINEWTONRSLS*)snes->data;
338c2fc9fa9SBarry Smith   PetscErrorCode     ierr;
339c2fc9fa9SBarry Smith   PetscInt           maxits,i,lits;
340c2fc9fa9SBarry Smith   PetscBool          lssucceed;
341c2fc9fa9SBarry Smith   MatStructure       flg = DIFFERENT_NONZERO_PATTERN;
342c2fc9fa9SBarry Smith   PetscReal          fnorm,gnorm,xnorm=0,ynorm;
3439bd66eb0SPeter Brune   Vec                Y,X,F;
344c2fc9fa9SBarry Smith   KSPConvergedReason kspreason;
345c2fc9fa9SBarry Smith 
346c2fc9fa9SBarry Smith   PetscFunctionBegin;
347c2fc9fa9SBarry Smith   snes->numFailures            = 0;
348c2fc9fa9SBarry Smith   snes->numLinearSolveFailures = 0;
349c2fc9fa9SBarry Smith   snes->reason                 = SNES_CONVERGED_ITERATING;
350c2fc9fa9SBarry Smith 
351c2fc9fa9SBarry Smith   maxits = snes->max_its;               /* maximum number of iterations */
352c2fc9fa9SBarry Smith   X      = snes->vec_sol;               /* solution vector */
353c2fc9fa9SBarry Smith   F      = snes->vec_func;              /* residual vector */
354c2fc9fa9SBarry Smith   Y      = snes->work[0];               /* work vectors */
3559bd66eb0SPeter Brune 
356f1c6b773SPeter Brune   ierr = SNESLineSearchSetVIFunctions(snes->linesearch, SNESVIProjectOntoBounds, SNESVIComputeInactiveSetFnorm);CHKERRQ(ierr);
3570298fd71SBarry Smith   ierr = SNESLineSearchSetVecs(snes->linesearch, X, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
358f1c6b773SPeter Brune   ierr = SNESLineSearchSetUp(snes->linesearch);CHKERRQ(ierr);
359c2fc9fa9SBarry Smith 
360c2fc9fa9SBarry Smith   ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
361c2fc9fa9SBarry Smith   snes->iter = 0;
362c2fc9fa9SBarry Smith   snes->norm = 0.0;
363c2fc9fa9SBarry Smith   ierr       = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
364c2fc9fa9SBarry Smith 
365c2fc9fa9SBarry Smith   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
366c2fc9fa9SBarry Smith   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
367c2fc9fa9SBarry Smith   if (snes->domainerror) {
368c2fc9fa9SBarry Smith     snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
369c2fc9fa9SBarry Smith     PetscFunctionReturn(0);
370c2fc9fa9SBarry Smith   }
371c2fc9fa9SBarry Smith   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
372c2fc9fa9SBarry Smith   ierr = VecNormBegin(X,NORM_2,&xnorm);CHKERRQ(ierr);        /* xnorm <- ||x||  */
373c2fc9fa9SBarry Smith   ierr = VecNormEnd(X,NORM_2,&xnorm);CHKERRQ(ierr);
3745f042095SDmitry Karpeev   if (PetscIsInfOrNanReal(fnorm)) SETERRQ(((PetscObject)X)->comm,PETSC_ERR_FP,"User provided compute function generated a Not-a-Number");
375c2fc9fa9SBarry Smith 
376c2fc9fa9SBarry Smith   ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
377c2fc9fa9SBarry Smith   snes->norm = fnorm;
378c2fc9fa9SBarry Smith   ierr       = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
379*a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
380c2fc9fa9SBarry Smith   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
381c2fc9fa9SBarry Smith 
382c2fc9fa9SBarry Smith   /* set parameter for default relative tolerance convergence test */
383c2fc9fa9SBarry Smith   snes->ttol = fnorm*snes->rtol;
384c2fc9fa9SBarry Smith   /* test convergence */
385c2fc9fa9SBarry Smith   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
386c2fc9fa9SBarry Smith   if (snes->reason) PetscFunctionReturn(0);
387c2fc9fa9SBarry Smith 
388c2fc9fa9SBarry Smith 
389c2fc9fa9SBarry Smith   for (i=0; i<maxits; i++) {
390c2fc9fa9SBarry Smith 
391c2fc9fa9SBarry Smith     IS         IS_act,IS_inact; /* _act -> active set _inact -> inactive set */
392c2fc9fa9SBarry Smith     IS         IS_redact; /* redundant active set */
393c2fc9fa9SBarry Smith     VecScatter scat_act,scat_inact;
394c2fc9fa9SBarry Smith     PetscInt   nis_act,nis_inact;
395c2fc9fa9SBarry Smith     Vec        Y_act,Y_inact,F_inact;
396c2fc9fa9SBarry Smith     Mat        jac_inact_inact,prejac_inact_inact;
397c2fc9fa9SBarry Smith     PetscBool  isequal;
398c2fc9fa9SBarry Smith 
399c2fc9fa9SBarry Smith     /* Call general purpose update function */
400c2fc9fa9SBarry Smith     if (snes->ops->update) {
401c2fc9fa9SBarry Smith       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
402c2fc9fa9SBarry Smith     }
403c2fc9fa9SBarry Smith     ierr = SNESComputeJacobian(snes,X,&snes->jacobian,&snes->jacobian_pre,&flg);CHKERRQ(ierr);
404c2fc9fa9SBarry Smith 
405c2fc9fa9SBarry Smith 
406c2fc9fa9SBarry Smith     /* Create active and inactive index sets */
407c2fc9fa9SBarry Smith 
408c2fc9fa9SBarry Smith     /*original
409c2fc9fa9SBarry Smith     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&IS_inact);CHKERRQ(ierr);
410c2fc9fa9SBarry Smith      */
411c2fc9fa9SBarry Smith     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
412c2fc9fa9SBarry Smith 
413c2fc9fa9SBarry Smith     if (vi->checkredundancy) {
414c2fc9fa9SBarry Smith       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
415c2fc9fa9SBarry Smith       if (IS_redact) {
416c2fc9fa9SBarry Smith         ierr = ISSort(IS_redact);CHKERRQ(ierr);
417c2fc9fa9SBarry Smith         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
418c2fc9fa9SBarry Smith         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
4191aa26658SKarl Rupp       } else {
420c2fc9fa9SBarry Smith         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
421c2fc9fa9SBarry Smith       }
422c2fc9fa9SBarry Smith     } else {
423c2fc9fa9SBarry Smith       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&IS_inact);CHKERRQ(ierr);
424c2fc9fa9SBarry Smith     }
425c2fc9fa9SBarry Smith 
426c2fc9fa9SBarry Smith 
427c2fc9fa9SBarry Smith     /* Create inactive set submatrix */
428c2fc9fa9SBarry Smith     ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
429c2fc9fa9SBarry Smith 
43066bfb381SJed Brown     if (0) {                    /* Dead code (temporary developer hack) */
43166bfb381SJed Brown       IS keptrows;
432c2fc9fa9SBarry Smith       ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
43366bfb381SJed Brown       if (keptrows) {
434c2fc9fa9SBarry Smith         PetscInt       cnt,*nrows,k;
435c2fc9fa9SBarry Smith         const PetscInt *krows,*inact;
436c2fc9fa9SBarry Smith         PetscInt       rstart=jac_inact_inact->rmap->rstart;
437c2fc9fa9SBarry Smith 
438c2fc9fa9SBarry Smith         ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
439c2fc9fa9SBarry Smith         ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
440c2fc9fa9SBarry Smith 
441c2fc9fa9SBarry Smith         ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
442c2fc9fa9SBarry Smith         ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
443c2fc9fa9SBarry Smith         ierr = ISGetIndices(IS_inact,&inact);CHKERRQ(ierr);
444c2fc9fa9SBarry Smith         ierr = PetscMalloc(cnt*sizeof(PetscInt),&nrows);CHKERRQ(ierr);
4451aa26658SKarl Rupp         for (k=0; k<cnt; k++) nrows[k] = inact[krows[k]-rstart];
446c2fc9fa9SBarry Smith         ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
447c2fc9fa9SBarry Smith         ierr = ISRestoreIndices(IS_inact,&inact);CHKERRQ(ierr);
448c2fc9fa9SBarry Smith         ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
449c2fc9fa9SBarry Smith         ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
450c2fc9fa9SBarry Smith 
4515f042095SDmitry Karpeev         ierr = ISCreateGeneral(((PetscObject)snes)->comm,cnt,nrows,PETSC_OWN_POINTER,&IS_inact);CHKERRQ(ierr);
452c2fc9fa9SBarry Smith         ierr = ISComplement(IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
453c2fc9fa9SBarry Smith         ierr = MatGetSubMatrix(snes->jacobian,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
454c2fc9fa9SBarry Smith       }
45566bfb381SJed Brown     }
456c2fc9fa9SBarry Smith     ierr = DMSetVI(snes->dm,IS_inact);CHKERRQ(ierr);
457c2fc9fa9SBarry Smith     /* remove later */
458c2fc9fa9SBarry Smith 
459c2fc9fa9SBarry Smith     /*
4605f042095SDmitry Karpeev     ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xu))->comm));CHKERRQ(ierr);
4615f042095SDmitry Karpeev     ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xl))->comm));CHKERRQ(ierr);
4625f042095SDmitry Karpeev     ierr = VecView(X,PETSC_VIEWER_BINARY_(((PetscObject)X)->comm));CHKERRQ(ierr);
4635f042095SDmitry Karpeev     ierr = VecView(F,PETSC_VIEWER_BINARY_(((PetscObject)F)->comm));CHKERRQ(ierr);
4645f042095SDmitry Karpeev     ierr = ISView(IS_inact,PETSC_VIEWER_BINARY_(((PetscObject)IS_inact)->comm));CHKERRQ(ierr);
465c2fc9fa9SBarry Smith      */
466c2fc9fa9SBarry Smith 
467c2fc9fa9SBarry Smith     /* Get sizes of active and inactive sets */
468c2fc9fa9SBarry Smith     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
469c2fc9fa9SBarry Smith     ierr = ISGetLocalSize(IS_inact,&nis_inact);CHKERRQ(ierr);
470c2fc9fa9SBarry Smith 
471c2fc9fa9SBarry Smith     /* Create active and inactive set vectors */
472f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&F_inact);CHKERRQ(ierr);
473f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_act,&Y_act);CHKERRQ(ierr);
474f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
475c2fc9fa9SBarry Smith 
476c2fc9fa9SBarry Smith     /* Create scatter contexts */
4770298fd71SBarry Smith     ierr = VecScatterCreate(Y,IS_act,Y_act,NULL,&scat_act);CHKERRQ(ierr);
4780298fd71SBarry Smith     ierr = VecScatterCreate(Y,IS_inact,Y_inact,NULL,&scat_inact);CHKERRQ(ierr);
479c2fc9fa9SBarry Smith 
480c2fc9fa9SBarry Smith     /* Do a vec scatter to active and inactive set vectors */
481c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
482c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
483c2fc9fa9SBarry Smith 
484c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
485c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
486c2fc9fa9SBarry Smith 
487c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
488c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
489c2fc9fa9SBarry Smith 
490c2fc9fa9SBarry Smith     /* Active set direction = 0 */
491c2fc9fa9SBarry Smith     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
492c2fc9fa9SBarry Smith     if (snes->jacobian != snes->jacobian_pre) {
493c2fc9fa9SBarry Smith       ierr = MatGetSubMatrix(snes->jacobian_pre,IS_inact,IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
494c2fc9fa9SBarry Smith     } else prejac_inact_inact = jac_inact_inact;
495c2fc9fa9SBarry Smith 
496c2fc9fa9SBarry Smith     ierr = ISEqual(vi->IS_inact_prev,IS_inact,&isequal);CHKERRQ(ierr);
497c2fc9fa9SBarry Smith     if (!isequal) {
498c2fc9fa9SBarry Smith       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
499c2fc9fa9SBarry Smith       flg  = DIFFERENT_NONZERO_PATTERN;
500c2fc9fa9SBarry Smith     }
501c2fc9fa9SBarry Smith 
502c2fc9fa9SBarry Smith     /*      ierr = ISView(IS_inact,0);CHKERRQ(ierr); */
503c2fc9fa9SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
504c2fc9fa9SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
505c2fc9fa9SBarry Smith 
506c2fc9fa9SBarry Smith 
507c2fc9fa9SBarry Smith 
508c2fc9fa9SBarry Smith     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact,flg);CHKERRQ(ierr);
509c2fc9fa9SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
510c2fc9fa9SBarry Smith     {
511c2fc9fa9SBarry Smith       PC        pc;
512c2fc9fa9SBarry Smith       PetscBool flg;
513c2fc9fa9SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
514251f4c67SDmitry Karpeev       ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
515c2fc9fa9SBarry Smith       if (flg) {
516c2fc9fa9SBarry Smith         KSP *subksps;
5170298fd71SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,NULL,&subksps);CHKERRQ(ierr);
518c2fc9fa9SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
519c2fc9fa9SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
520251f4c67SDmitry Karpeev         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
521c2fc9fa9SBarry Smith         if (flg) {
522c2fc9fa9SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
523c2fc9fa9SBarry Smith           const PetscInt *ii;
524c2fc9fa9SBarry Smith 
525c2fc9fa9SBarry Smith           ierr = ISGetSize(IS_inact,&n);CHKERRQ(ierr);
526c2fc9fa9SBarry Smith           ierr = ISGetIndices(IS_inact,&ii);CHKERRQ(ierr);
527c2fc9fa9SBarry Smith           for (j=0; j<n; j++) {
528c2fc9fa9SBarry Smith             if (ii[j] < N) cnts[0]++;
529c2fc9fa9SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
530c2fc9fa9SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
531c2fc9fa9SBarry Smith           }
532c2fc9fa9SBarry Smith           ierr = ISRestoreIndices(IS_inact,&ii);CHKERRQ(ierr);
533c2fc9fa9SBarry Smith 
534c2fc9fa9SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
535c2fc9fa9SBarry Smith         }
536c2fc9fa9SBarry Smith       }
537c2fc9fa9SBarry Smith     }
538c2fc9fa9SBarry Smith 
539c2fc9fa9SBarry Smith     ierr = SNES_KSPSolve(snes,snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
540c2fc9fa9SBarry Smith     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
541c2fc9fa9SBarry Smith     if (kspreason < 0) {
542c2fc9fa9SBarry Smith       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
543c2fc9fa9SBarry Smith         ierr         = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
544c2fc9fa9SBarry Smith         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
545c2fc9fa9SBarry Smith         break;
546c2fc9fa9SBarry Smith       }
547c2fc9fa9SBarry Smith      }
548c2fc9fa9SBarry Smith 
549c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
550c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
551c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
552c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
553c2fc9fa9SBarry Smith 
554c2fc9fa9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
555c2fc9fa9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
556c2fc9fa9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
557c2fc9fa9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
558c2fc9fa9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
559c2fc9fa9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
560c2fc9fa9SBarry Smith     if (!isequal) {
561c2fc9fa9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
562c2fc9fa9SBarry Smith       ierr = ISDuplicate(IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
563c2fc9fa9SBarry Smith     }
564c2fc9fa9SBarry Smith     ierr = ISDestroy(&IS_inact);CHKERRQ(ierr);
565c2fc9fa9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
566c2fc9fa9SBarry Smith     if (snes->jacobian != snes->jacobian_pre) {
567c2fc9fa9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
568c2fc9fa9SBarry Smith     }
569c2fc9fa9SBarry Smith     ierr              = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
570c2fc9fa9SBarry Smith     snes->linear_its += lits;
571c2fc9fa9SBarry Smith     ierr              = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
572c2fc9fa9SBarry Smith     /*
5736b2b7091SBarry Smith     if (snes->ops->precheck) {
574c2fc9fa9SBarry Smith       PetscBool changed_y = PETSC_FALSE;
5756b2b7091SBarry Smith       ierr = (*snes->ops->precheck)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr);
576c2fc9fa9SBarry Smith     }
577c2fc9fa9SBarry Smith 
578c2fc9fa9SBarry Smith     if (PetscLogPrintInfo) {
579c2fc9fa9SBarry Smith       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
580c2fc9fa9SBarry Smith     }
581c2fc9fa9SBarry Smith     */
582c2fc9fa9SBarry Smith     /* Compute a (scaled) negative update in the line search routine:
583c2fc9fa9SBarry Smith          Y <- X - lambda*Y
584c2fc9fa9SBarry Smith        and evaluate G = function(Y) (depends on the line search).
585c2fc9fa9SBarry Smith     */
586c2fc9fa9SBarry Smith     ierr  = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
587c2fc9fa9SBarry Smith     ynorm = 1; gnorm = fnorm;
588f1c6b773SPeter Brune     ierr  = SNESLineSearchApply(snes->linesearch, X, F, &gnorm, Y);CHKERRQ(ierr);
589f1c6b773SPeter Brune     ierr  = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr);
590c2fc9fa9SBarry Smith     ierr  = PetscInfo4(snes,"fnorm=%18.16e, gnorm=%18.16e, ynorm=%18.16e, lssucceed=%d\n",(double)fnorm,(double)gnorm,(double)ynorm,(int)lssucceed);CHKERRQ(ierr);
591c2fc9fa9SBarry Smith     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
592c2fc9fa9SBarry Smith     if (snes->domainerror) {
593c2fc9fa9SBarry Smith       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
594c2fc9fa9SBarry Smith       ierr         = DMDestroyVI(snes->dm);CHKERRQ(ierr);
595c2fc9fa9SBarry Smith       PetscFunctionReturn(0);
596c2fc9fa9SBarry Smith     }
597f1c6b773SPeter Brune     ierr = SNESLineSearchGetSuccess(snes->linesearch, &lssucceed);CHKERRQ(ierr);
5989bd66eb0SPeter Brune 
599c2fc9fa9SBarry Smith     if (!lssucceed) {
600c2fc9fa9SBarry Smith       if (++snes->numFailures >= snes->maxFailures) {
601c2fc9fa9SBarry Smith         PetscBool ismin;
602c2fc9fa9SBarry Smith         snes->reason = SNES_DIVERGED_LINE_SEARCH;
6039bd66eb0SPeter Brune         ierr         = SNESVICheckLocalMin_Private(snes,snes->jacobian,F,X,gnorm,&ismin);CHKERRQ(ierr);
604c2fc9fa9SBarry Smith         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
605c2fc9fa9SBarry Smith         break;
606c2fc9fa9SBarry Smith       }
607c2fc9fa9SBarry Smith     }
608c2fc9fa9SBarry Smith     /* Update function and solution vectors */
609c2fc9fa9SBarry Smith     fnorm = gnorm;
610c2fc9fa9SBarry Smith     /* Monitor convergence */
611c2fc9fa9SBarry Smith     ierr       = PetscObjectTakeAccess(snes);CHKERRQ(ierr);
612c2fc9fa9SBarry Smith     snes->iter = i+1;
613c2fc9fa9SBarry Smith     snes->norm = fnorm;
614c2fc9fa9SBarry Smith     ierr       = PetscObjectGrantAccess(snes);CHKERRQ(ierr);
615*a71f0d7dSBarry Smith     ierr       = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr);
616c2fc9fa9SBarry Smith     ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
617c2fc9fa9SBarry Smith     /* Test for convergence, xnorm = || X || */
618c2fc9fa9SBarry Smith     if (snes->ops->converged != SNESSkipConverged) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
619c2fc9fa9SBarry Smith     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
620c2fc9fa9SBarry Smith     if (snes->reason) break;
621c2fc9fa9SBarry Smith   }
622c2fc9fa9SBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
623c2fc9fa9SBarry Smith   if (i == maxits) {
624c2fc9fa9SBarry Smith     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
625c2fc9fa9SBarry Smith     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
626c2fc9fa9SBarry Smith   }
627c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
628c2fc9fa9SBarry Smith }
629c2fc9fa9SBarry Smith 
630c2fc9fa9SBarry Smith #undef __FUNCT__
631c2fc9fa9SBarry Smith #define __FUNCT__ "SNESVISetRedundancyCheck"
632c2fc9fa9SBarry Smith PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
633c2fc9fa9SBarry Smith {
634f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*)snes->data;
635c2fc9fa9SBarry Smith 
636c2fc9fa9SBarry Smith   PetscFunctionBegin;
637c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
638c2fc9fa9SBarry Smith   vi->checkredundancy = func;
639c2fc9fa9SBarry Smith   vi->ctxP            = ctx;
640c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
641c2fc9fa9SBarry Smith }
642c2fc9fa9SBarry Smith 
643c2fc9fa9SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
644c2fc9fa9SBarry Smith #include <engine.h>
645c2fc9fa9SBarry Smith #include <mex.h>
646c2fc9fa9SBarry Smith typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
647c2fc9fa9SBarry Smith 
648c2fc9fa9SBarry Smith #undef __FUNCT__
649c2fc9fa9SBarry Smith #define __FUNCT__ "SNESVIRedundancyCheck_Matlab"
650c2fc9fa9SBarry Smith PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS *is_redact,void *ctx)
651c2fc9fa9SBarry Smith {
652c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
653c2fc9fa9SBarry Smith   SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
654c2fc9fa9SBarry Smith   int               nlhs  = 1, nrhs = 5;
655c2fc9fa9SBarry Smith   mxArray           *plhs[1], *prhs[5];
656c2fc9fa9SBarry Smith   long long int     l1      = 0, l2 = 0, ls = 0;
6570298fd71SBarry Smith   PetscInt          *indices=NULL;
658c2fc9fa9SBarry Smith 
659c2fc9fa9SBarry Smith   PetscFunctionBegin;
660c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
661c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
662c2fc9fa9SBarry Smith   PetscValidPointer(is_redact,3);
663c2fc9fa9SBarry Smith   PetscCheckSameComm(snes,1,is_act,2);
664c2fc9fa9SBarry Smith 
665c2fc9fa9SBarry Smith   /* Create IS for reduced active set of size 0, its size and indices will
666c2fc9fa9SBarry Smith    bet set by the Matlab function */
667c2fc9fa9SBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
668c2fc9fa9SBarry Smith   /* call Matlab function in ctx */
669c2fc9fa9SBarry Smith   ierr    = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr);
670c2fc9fa9SBarry Smith   ierr    = PetscMemcpy(&l1,&is_act,sizeof(is_act));CHKERRQ(ierr);
671c2fc9fa9SBarry Smith   ierr    = PetscMemcpy(&l2,is_redact,sizeof(is_act));CHKERRQ(ierr);
672c2fc9fa9SBarry Smith   prhs[0] = mxCreateDoubleScalar((double)ls);
673c2fc9fa9SBarry Smith   prhs[1] = mxCreateDoubleScalar((double)l1);
674c2fc9fa9SBarry Smith   prhs[2] = mxCreateDoubleScalar((double)l2);
675c2fc9fa9SBarry Smith   prhs[3] = mxCreateString(sctx->funcname);
676c2fc9fa9SBarry Smith   prhs[4] = sctx->ctx;
677c2fc9fa9SBarry Smith   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
678c2fc9fa9SBarry Smith   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
679c2fc9fa9SBarry Smith   mxDestroyArray(prhs[0]);
680c2fc9fa9SBarry Smith   mxDestroyArray(prhs[1]);
681c2fc9fa9SBarry Smith   mxDestroyArray(prhs[2]);
682c2fc9fa9SBarry Smith   mxDestroyArray(prhs[3]);
683c2fc9fa9SBarry Smith   mxDestroyArray(plhs[0]);
684c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
685c2fc9fa9SBarry Smith }
686c2fc9fa9SBarry Smith 
687c2fc9fa9SBarry Smith #undef __FUNCT__
688c2fc9fa9SBarry Smith #define __FUNCT__ "SNESVISetRedundancyCheckMatlab"
689c2fc9fa9SBarry Smith PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char *func,mxArray *ctx)
690c2fc9fa9SBarry Smith {
691c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
692c2fc9fa9SBarry Smith   SNESMatlabContext *sctx;
693c2fc9fa9SBarry Smith 
694c2fc9fa9SBarry Smith   PetscFunctionBegin;
695c2fc9fa9SBarry Smith   /* currently sctx is memory bleed */
696c2fc9fa9SBarry Smith   ierr      = PetscMalloc(sizeof(SNESMatlabContext),&sctx);CHKERRQ(ierr);
697c2fc9fa9SBarry Smith   ierr      = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
698c2fc9fa9SBarry Smith   sctx->ctx = mxDuplicateArray(ctx);
699c2fc9fa9SBarry Smith   ierr      = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
700c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
701c2fc9fa9SBarry Smith }
702c2fc9fa9SBarry Smith 
703c2fc9fa9SBarry Smith #endif
704c2fc9fa9SBarry Smith 
705c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
706c2fc9fa9SBarry Smith /*
707f450aa47SBarry Smith    SNESSetUp_VINEWTONRSLS - Sets up the internal data structures for the later use
708c2fc9fa9SBarry Smith    of the SNESVI nonlinear solver.
709c2fc9fa9SBarry Smith 
710c2fc9fa9SBarry Smith    Input Parameter:
711c2fc9fa9SBarry Smith .  snes - the SNES context
712c2fc9fa9SBarry Smith .  x - the solution vector
713c2fc9fa9SBarry Smith 
714c2fc9fa9SBarry Smith    Application Interface Routine: SNESSetUp()
715c2fc9fa9SBarry Smith 
716c2fc9fa9SBarry Smith    Notes:
717c2fc9fa9SBarry Smith    For basic use of the SNES solvers, the user need not explicitly call
718c2fc9fa9SBarry Smith    SNESSetUp(), since these actions will automatically occur during
719c2fc9fa9SBarry Smith    the call to SNESSolve().
720c2fc9fa9SBarry Smith  */
721c2fc9fa9SBarry Smith #undef __FUNCT__
722f450aa47SBarry Smith #define __FUNCT__ "SNESSetUp_VINEWTONRSLS"
723f450aa47SBarry Smith PetscErrorCode SNESSetUp_VINEWTONRSLS(SNES snes)
724c2fc9fa9SBarry Smith {
725c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
726f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*) snes->data;
727c2fc9fa9SBarry Smith   PetscInt          *indices;
728c2fc9fa9SBarry Smith   PetscInt          i,n,rstart,rend;
729f1c6b773SPeter Brune   SNESLineSearch    linesearch;
730c2fc9fa9SBarry Smith 
731c2fc9fa9SBarry Smith   PetscFunctionBegin;
732c2fc9fa9SBarry Smith   ierr = SNESSetUp_VI(snes);CHKERRQ(ierr);
733c2fc9fa9SBarry Smith 
734c2fc9fa9SBarry Smith   /* Set up previous active index set for the first snes solve
735c2fc9fa9SBarry Smith    vi->IS_inact_prev = 0,1,2,....N */
736c2fc9fa9SBarry Smith 
737c2fc9fa9SBarry Smith   ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
738c2fc9fa9SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
739c2fc9fa9SBarry Smith   ierr = PetscMalloc(n*sizeof(PetscInt),&indices);CHKERRQ(ierr);
740c2fc9fa9SBarry Smith   for (i=0; i < n; i++) indices[i] = rstart + i;
74122d28d08SBarry Smith   ierr = ISCreateGeneral(((PetscObject)snes)->comm,n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);CHKERRQ(ierr);
7429bd66eb0SPeter Brune 
7439bd66eb0SPeter Brune   /* set the line search functions */
7449bd66eb0SPeter Brune   if (!snes->linesearch) {
745f1c6b773SPeter Brune     ierr = SNESGetSNESLineSearch(snes, &linesearch);CHKERRQ(ierr);
7461a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
7479bd66eb0SPeter Brune   }
748c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
749c2fc9fa9SBarry Smith }
750c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
751c2fc9fa9SBarry Smith #undef __FUNCT__
752f450aa47SBarry Smith #define __FUNCT__ "SNESReset_VINEWTONRSLS"
753f450aa47SBarry Smith PetscErrorCode SNESReset_VINEWTONRSLS(SNES snes)
754c2fc9fa9SBarry Smith {
755f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*) snes->data;
756c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
757c2fc9fa9SBarry Smith 
758c2fc9fa9SBarry Smith   PetscFunctionBegin;
759c2fc9fa9SBarry Smith   ierr = SNESReset_VI(snes);CHKERRQ(ierr);
760c2fc9fa9SBarry Smith   ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
761c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
762c2fc9fa9SBarry Smith }
763c2fc9fa9SBarry Smith 
764c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
765c2fc9fa9SBarry Smith /*MC
766f450aa47SBarry Smith       SNESVINEWTONRSLS - Reduced space active set solvers for variational inequalities based on Newton's method
767c2fc9fa9SBarry Smith 
76861589011SJed Brown    Options Database:
76961589011SJed Brown +   -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 additional variables that enforce the constraints
77061589011SJed Brown -   -snes_vi_monitor - prints the number of active constraints at each iteration.
771c2fc9fa9SBarry Smith 
772c2fc9fa9SBarry Smith    Level: beginner
773c2fc9fa9SBarry Smith 
774b80f3ac1SShri Abhyankar    References:
775b80f3ac1SShri Abhyankar    - T. S. Munson, and S. Benson. Flexible Complementarity Solvers for Large-Scale
776b80f3ac1SShri Abhyankar      Applications, Optimization Methods and Software, 21 (2006).
777b80f3ac1SShri Abhyankar 
77804d7464bSBarry Smith .seealso:  SNESVISetVariableBounds(), SNESVISetComputeVariableBounds(), SNESCreate(), SNES, SNESSetType(), SNESVINEWTONRSLS, SNESVINEWTONSSLS, SNESNEWTONTR, SNESLineSearchSet(),
779c2fc9fa9SBarry Smith            SNESLineSearchSetPostCheck(), SNESLineSearchNo(), SNESLineSearchCubic(), SNESLineSearchQuadratic(),
780c2fc9fa9SBarry Smith            SNESLineSearchSet(), SNESLineSearchNoNorms(), SNESLineSearchSetPreCheck(), SNESLineSearchSetParams(), SNESLineSearchGetParams()
781c2fc9fa9SBarry Smith 
782c2fc9fa9SBarry Smith M*/
783c2fc9fa9SBarry Smith EXTERN_C_BEGIN
784c2fc9fa9SBarry Smith #undef __FUNCT__
785f450aa47SBarry Smith #define __FUNCT__ "SNESCreate_VINEWTONRSLS"
786f450aa47SBarry Smith PetscErrorCode  SNESCreate_VINEWTONRSLS(SNES snes)
787c2fc9fa9SBarry Smith {
788c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
789f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi;
790c2fc9fa9SBarry Smith 
791c2fc9fa9SBarry Smith   PetscFunctionBegin;
792f450aa47SBarry Smith   snes->ops->reset          = SNESReset_VINEWTONRSLS;
793f450aa47SBarry Smith   snes->ops->setup          = SNESSetUp_VINEWTONRSLS;
794f450aa47SBarry Smith   snes->ops->solve          = SNESSolve_VINEWTONRSLS;
795c2fc9fa9SBarry Smith   snes->ops->destroy        = SNESDestroy_VI;
796c2fc9fa9SBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_VI;
7970298fd71SBarry Smith   snes->ops->view           = NULL;
798c2fc9fa9SBarry Smith   snes->ops->converged      = SNESDefaultConverged_VI;
799c2fc9fa9SBarry Smith 
800c2fc9fa9SBarry Smith   snes->usesksp = PETSC_TRUE;
801c2fc9fa9SBarry Smith   snes->usespc  = PETSC_FALSE;
802c2fc9fa9SBarry Smith 
803f450aa47SBarry Smith   ierr                = PetscNewLog(snes,SNES_VINEWTONRSLS,&vi);CHKERRQ(ierr);
804c2fc9fa9SBarry Smith   snes->data          = (void*)vi;
8050298fd71SBarry Smith   vi->checkredundancy = NULL;
806c2fc9fa9SBarry Smith 
80761589011SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESVISetVariableBounds_C","SNESVISetVariableBounds_VI",SNESVISetVariableBounds_VI);CHKERRQ(ierr);
80861589011SJed Brown   ierr = PetscObjectComposeFunctionDynamic((PetscObject)snes,"SNESVISetComputeVariableBounds_C","SNESVISetComputeVariableBounds_VI",SNESVISetComputeVariableBounds_VI);CHKERRQ(ierr);
809c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
810c2fc9fa9SBarry Smith }
811c2fc9fa9SBarry Smith EXTERN_C_END
812c2fc9fa9SBarry Smith 
813