xref: /petsc/src/snes/impls/vi/rs/virs.c (revision 7a7aea1f13832695eadc2fd5afef8ec0a48c5f75)
1c2fc9fa9SBarry Smith 
2c2fc9fa9SBarry Smith #include <../src/snes/impls/vi/rs/virsimpl.h> /*I "petscsnes.h" I*/
3af0996ceSBarry Smith #include <petsc/private/dmimpl.h>
4af0996ceSBarry Smith #include <petsc/private/vecimpl.h>
5c2fc9fa9SBarry Smith 
6c2fc9fa9SBarry Smith /*
7c2fc9fa9SBarry Smith    SNESVIGetInactiveSet - Gets the global indices for the inactive set variables (these correspond to the degrees of freedom the linear
8c2fc9fa9SBarry Smith      system is solved on)
9c2fc9fa9SBarry Smith 
10*7a7aea1fSJed Brown    Input parameter:
11c2fc9fa9SBarry Smith .  snes - the SNES context
12c2fc9fa9SBarry Smith 
13*7a7aea1fSJed Brown    Output parameter:
14d5f1b7e6SEd Bueler .  inact - inactive set index set
15c2fc9fa9SBarry Smith 
16c2fc9fa9SBarry Smith  */
17c2fc9fa9SBarry Smith PetscErrorCode SNESVIGetInactiveSet(SNES snes,IS *inact)
18c2fc9fa9SBarry Smith {
19f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*)snes->data;
206e111a19SKarl Rupp 
21c2fc9fa9SBarry Smith   PetscFunctionBegin;
22f009fc93SPatrick Farrell   *inact = vi->IS_inact;
23c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
24c2fc9fa9SBarry Smith }
25c2fc9fa9SBarry Smith 
26c2fc9fa9SBarry Smith /*
27c2fc9fa9SBarry 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
28c2fc9fa9SBarry Smith   defined by the reduced space method.
29c2fc9fa9SBarry Smith 
30c2fc9fa9SBarry Smith     Simple calls the regular DM interpolation and restricts it to operation on the variables not associated with active constraints.
31c2fc9fa9SBarry Smith 
32c2fc9fa9SBarry Smith <*/
33c2fc9fa9SBarry Smith typedef struct {
34c2fc9fa9SBarry Smith   PetscInt n;                                              /* size of vectors in the reduced DM space */
35c2fc9fa9SBarry Smith   IS       inactive;
36f5af7f23SKarl Rupp 
3725296bd5SBarry Smith   PetscErrorCode (*createinterpolation)(DM,DM,Mat*,Vec*);  /* DM's original routines */
38c2fc9fa9SBarry Smith   PetscErrorCode (*coarsen)(DM, MPI_Comm, DM*);
39c2fc9fa9SBarry Smith   PetscErrorCode (*createglobalvector)(DM,Vec*);
405a84ad33SLisandro Dalcin   PetscErrorCode (*createinjection)(DM,DM,Mat*);
414a7a4c06SLawrence Mitchell   PetscErrorCode (*hascreateinjection)(DM,PetscBool*);
42f5af7f23SKarl Rupp 
43c2fc9fa9SBarry Smith   DM dm;                                                  /* when destroying this object we need to reset the above function into the base DM */
44c2fc9fa9SBarry Smith } DM_SNESVI;
45c2fc9fa9SBarry Smith 
46c2fc9fa9SBarry Smith /*
47c2fc9fa9SBarry Smith      DMCreateGlobalVector_SNESVI - Creates global vector of the size of the reduced space
48c2fc9fa9SBarry Smith 
49c2fc9fa9SBarry Smith */
50c2fc9fa9SBarry Smith PetscErrorCode  DMCreateGlobalVector_SNESVI(DM dm,Vec *vec)
51c2fc9fa9SBarry Smith {
52c2fc9fa9SBarry Smith   PetscErrorCode ierr;
53c2fc9fa9SBarry Smith   PetscContainer isnes;
54c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi;
55c2fc9fa9SBarry Smith 
56c2fc9fa9SBarry Smith   PetscFunctionBegin;
57c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
58ce94432eSBarry Smith   if (!isnes) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_PLIB,"Composed SNES is missing");
59c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
60ce94432eSBarry Smith   ierr = VecCreateMPI(PetscObjectComm((PetscObject)dm),dmsnesvi->n,PETSC_DETERMINE,vec);CHKERRQ(ierr);
61c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
62c2fc9fa9SBarry Smith }
63c2fc9fa9SBarry Smith 
64c2fc9fa9SBarry Smith /*
65e727c939SJed Brown      DMCreateInterpolation_SNESVI - Modifieds the interpolation obtained from the DM by removing all rows and columns associated with active constraints.
66c2fc9fa9SBarry Smith 
67c2fc9fa9SBarry Smith */
68e727c939SJed Brown PetscErrorCode  DMCreateInterpolation_SNESVI(DM dm1,DM dm2,Mat *mat,Vec *vec)
69c2fc9fa9SBarry Smith {
70c2fc9fa9SBarry Smith   PetscErrorCode ierr;
71c2fc9fa9SBarry Smith   PetscContainer isnes;
72c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi1,*dmsnesvi2;
73c2fc9fa9SBarry Smith   Mat            interp;
74c2fc9fa9SBarry Smith 
75c2fc9fa9SBarry Smith   PetscFunctionBegin;
76c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
773b4367a7SBarry Smith   if (!isnes) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_PLIB,"Composed VI data structure is missing");
78c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
79c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm2,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
803b4367a7SBarry Smith   if (!isnes) SETERRQ(PetscObjectComm((PetscObject)dm2),PETSC_ERR_PLIB,"Composed VI data structure is missing");
81c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi2);CHKERRQ(ierr);
82c2fc9fa9SBarry Smith 
830298fd71SBarry Smith   ierr = (*dmsnesvi1->createinterpolation)(dm1,dm2,&interp,NULL);CHKERRQ(ierr);
847dae84e0SHong Zhang   ierr = MatCreateSubMatrix(interp,dmsnesvi2->inactive,dmsnesvi1->inactive,MAT_INITIAL_MATRIX,mat);CHKERRQ(ierr);
85c2fc9fa9SBarry Smith   ierr = MatDestroy(&interp);CHKERRQ(ierr);
86c2fc9fa9SBarry Smith   *vec = 0;
87c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
88c2fc9fa9SBarry Smith }
89c2fc9fa9SBarry Smith 
9025acbd8eSLisandro Dalcin static PetscErrorCode DMSetVI(DM,IS);
9125acbd8eSLisandro Dalcin static PetscErrorCode DMDestroyVI(DM);
92c2fc9fa9SBarry Smith 
93c2fc9fa9SBarry Smith /*
94c2fc9fa9SBarry Smith      DMCoarsen_SNESVI - Computes the regular coarsened DM then computes additional information about its inactive set
95c2fc9fa9SBarry Smith 
96c2fc9fa9SBarry Smith */
97c2fc9fa9SBarry Smith PetscErrorCode  DMCoarsen_SNESVI(DM dm1,MPI_Comm comm,DM *dm2)
98c2fc9fa9SBarry Smith {
99c2fc9fa9SBarry Smith   PetscErrorCode ierr;
100c2fc9fa9SBarry Smith   PetscContainer isnes;
101c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi1;
102c2fc9fa9SBarry Smith   Vec            finemarked,coarsemarked;
103c2fc9fa9SBarry Smith   IS             inactive;
1046dbf9973SLawrence Mitchell   Mat            inject;
105c2fc9fa9SBarry Smith   const PetscInt *index;
106c2fc9fa9SBarry Smith   PetscInt       n,k,cnt = 0,rstart,*coarseindex;
107c2fc9fa9SBarry Smith   PetscScalar    *marked;
108c2fc9fa9SBarry Smith 
109c2fc9fa9SBarry Smith   PetscFunctionBegin;
110c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm1,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
1113b4367a7SBarry Smith   if (!isnes) SETERRQ(PetscObjectComm((PetscObject)dm1),PETSC_ERR_PLIB,"Composed VI data structure is missing");
112c2fc9fa9SBarry Smith   ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi1);CHKERRQ(ierr);
113c2fc9fa9SBarry Smith 
114c2fc9fa9SBarry Smith   /* get the original coarsen */
115c2fc9fa9SBarry Smith   ierr = (*dmsnesvi1->coarsen)(dm1,comm,dm2);CHKERRQ(ierr);
116c2fc9fa9SBarry Smith 
117c2fc9fa9SBarry Smith   /* not sure why this extra reference is needed, but without the dm2 disappears too early */
11894c98981SBarry Smith   /* Updating the KSPCreateVecs() to avoid using DMGetGlobalVector() when matrix is available removes the need for this reference? */
11994c98981SBarry Smith   /*  ierr = PetscObjectReference((PetscObject)*dm2);CHKERRQ(ierr);*/
120c2fc9fa9SBarry Smith 
121c2fc9fa9SBarry Smith   /* need to set back global vectors in order to use the original injection */
122c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
1231aa26658SKarl Rupp 
124c2fc9fa9SBarry Smith   dm1->ops->createglobalvector = dmsnesvi1->createglobalvector;
1251aa26658SKarl Rupp 
126c2fc9fa9SBarry Smith   ierr = DMCreateGlobalVector(dm1,&finemarked);CHKERRQ(ierr);
127c2fc9fa9SBarry Smith   ierr = DMCreateGlobalVector(*dm2,&coarsemarked);CHKERRQ(ierr);
128c2fc9fa9SBarry Smith 
129c2fc9fa9SBarry Smith   /*
130c2fc9fa9SBarry Smith      fill finemarked with locations of inactive points
131c2fc9fa9SBarry Smith   */
132c2fc9fa9SBarry Smith   ierr = ISGetIndices(dmsnesvi1->inactive,&index);CHKERRQ(ierr);
133c2fc9fa9SBarry Smith   ierr = ISGetLocalSize(dmsnesvi1->inactive,&n);CHKERRQ(ierr);
134c2fc9fa9SBarry Smith   ierr = VecSet(finemarked,0.0);CHKERRQ(ierr);
135c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
136c2fc9fa9SBarry Smith     ierr = VecSetValue(finemarked,index[k],1.0,INSERT_VALUES);CHKERRQ(ierr);
137c2fc9fa9SBarry Smith   }
138c2fc9fa9SBarry Smith   ierr = VecAssemblyBegin(finemarked);CHKERRQ(ierr);
139c2fc9fa9SBarry Smith   ierr = VecAssemblyEnd(finemarked);CHKERRQ(ierr);
140c2fc9fa9SBarry Smith 
141e727c939SJed Brown   ierr = DMCreateInjection(*dm2,dm1,&inject);CHKERRQ(ierr);
1422adcf181SLawrence Mitchell   ierr = MatRestrict(inject,finemarked,coarsemarked);CHKERRQ(ierr);
1436dbf9973SLawrence Mitchell   ierr = MatDestroy(&inject);CHKERRQ(ierr);
144c2fc9fa9SBarry Smith 
145c2fc9fa9SBarry Smith   /*
146c2fc9fa9SBarry Smith      create index set list of coarse inactive points from coarsemarked
147c2fc9fa9SBarry Smith   */
148c2fc9fa9SBarry Smith   ierr = VecGetLocalSize(coarsemarked,&n);CHKERRQ(ierr);
1490298fd71SBarry Smith   ierr = VecGetOwnershipRange(coarsemarked,&rstart,NULL);CHKERRQ(ierr);
150c2fc9fa9SBarry Smith   ierr = VecGetArray(coarsemarked,&marked);CHKERRQ(ierr);
151c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
152c2fc9fa9SBarry Smith     if (marked[k] != 0.0) cnt++;
153c2fc9fa9SBarry Smith   }
154785e854fSJed Brown   ierr = PetscMalloc1(cnt,&coarseindex);CHKERRQ(ierr);
155c2fc9fa9SBarry Smith   cnt  = 0;
156c2fc9fa9SBarry Smith   for (k=0; k<n; k++) {
157c2fc9fa9SBarry Smith     if (marked[k] != 0.0) coarseindex[cnt++] = k + rstart;
158c2fc9fa9SBarry Smith   }
159c2fc9fa9SBarry Smith   ierr = VecRestoreArray(coarsemarked,&marked);CHKERRQ(ierr);
160ce94432eSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)coarsemarked),cnt,coarseindex,PETSC_OWN_POINTER,&inactive);CHKERRQ(ierr);
161c2fc9fa9SBarry Smith 
162c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm1);CHKERRQ(ierr);
1631aa26658SKarl Rupp 
164c2fc9fa9SBarry Smith   dm1->ops->createglobalvector = DMCreateGlobalVector_SNESVI;
1651aa26658SKarl Rupp 
166c2fc9fa9SBarry Smith   ierr = DMSetVI(*dm2,inactive);CHKERRQ(ierr);
167c2fc9fa9SBarry Smith 
168c2fc9fa9SBarry Smith   ierr = VecDestroy(&finemarked);CHKERRQ(ierr);
169c2fc9fa9SBarry Smith   ierr = VecDestroy(&coarsemarked);CHKERRQ(ierr);
170c2fc9fa9SBarry Smith   ierr = ISDestroy(&inactive);CHKERRQ(ierr);
171c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
172c2fc9fa9SBarry Smith }
173c2fc9fa9SBarry Smith 
174c2fc9fa9SBarry Smith PetscErrorCode DMDestroy_SNESVI(DM_SNESVI *dmsnesvi)
175c2fc9fa9SBarry Smith {
176c2fc9fa9SBarry Smith   PetscErrorCode ierr;
177c2fc9fa9SBarry Smith 
178c2fc9fa9SBarry Smith   PetscFunctionBegin;
179c2fc9fa9SBarry Smith   /* reset the base methods in the DM object that were changed when the DM_SNESVI was reset */
18025296bd5SBarry Smith   dmsnesvi->dm->ops->createinterpolation = dmsnesvi->createinterpolation;
181c2fc9fa9SBarry Smith   dmsnesvi->dm->ops->coarsen             = dmsnesvi->coarsen;
182c2fc9fa9SBarry Smith   dmsnesvi->dm->ops->createglobalvector  = dmsnesvi->createglobalvector;
1835a84ad33SLisandro Dalcin   dmsnesvi->dm->ops->createinjection     = dmsnesvi->createinjection;
1844a7a4c06SLawrence Mitchell   dmsnesvi->dm->ops->hascreateinjection  = dmsnesvi->hascreateinjection;
185c2fc9fa9SBarry Smith   /* need to clear out this vectors because some of them may not have a reference to the DM
186c2fc9fa9SBarry Smith     but they are counted as having references to the DM in DMDestroy() */
187c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dmsnesvi->dm);CHKERRQ(ierr);
188c2fc9fa9SBarry Smith 
189c2fc9fa9SBarry Smith   ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
190c2fc9fa9SBarry Smith   ierr = PetscFree(dmsnesvi);CHKERRQ(ierr);
191c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
192c2fc9fa9SBarry Smith }
193c2fc9fa9SBarry Smith 
194c2fc9fa9SBarry Smith /*
195c2fc9fa9SBarry Smith      DMSetVI - Marks a DM as associated with a VI problem. This causes the interpolation/restriction operators to
196c2fc9fa9SBarry Smith                be restricted to only those variables NOT associated with active constraints.
197c2fc9fa9SBarry Smith 
198c2fc9fa9SBarry Smith */
19925acbd8eSLisandro Dalcin static PetscErrorCode DMSetVI(DM dm,IS inactive)
200c2fc9fa9SBarry Smith {
201c2fc9fa9SBarry Smith   PetscErrorCode ierr;
202c2fc9fa9SBarry Smith   PetscContainer isnes;
203c2fc9fa9SBarry Smith   DM_SNESVI      *dmsnesvi;
204c2fc9fa9SBarry Smith 
205c2fc9fa9SBarry Smith   PetscFunctionBegin;
206c2fc9fa9SBarry Smith   if (!dm) PetscFunctionReturn(0);
207c2fc9fa9SBarry Smith 
208c2fc9fa9SBarry Smith   ierr = PetscObjectReference((PetscObject)inactive);CHKERRQ(ierr);
209c2fc9fa9SBarry Smith 
210c2fc9fa9SBarry Smith   ierr = PetscObjectQuery((PetscObject)dm,"VI",(PetscObject*)&isnes);CHKERRQ(ierr);
211c2fc9fa9SBarry Smith   if (!isnes) {
212ce94432eSBarry Smith     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)dm),&isnes);CHKERRQ(ierr);
213c2fc9fa9SBarry Smith     ierr = PetscContainerSetUserDestroy(isnes,(PetscErrorCode (*)(void*))DMDestroy_SNESVI);CHKERRQ(ierr);
214b00a9115SJed Brown     ierr = PetscNew(&dmsnesvi);CHKERRQ(ierr);
215c2fc9fa9SBarry Smith     ierr = PetscContainerSetPointer(isnes,(void*)dmsnesvi);CHKERRQ(ierr);
216c2fc9fa9SBarry Smith     ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)isnes);CHKERRQ(ierr);
217c2fc9fa9SBarry Smith     ierr = PetscContainerDestroy(&isnes);CHKERRQ(ierr);
2181aa26658SKarl Rupp 
21925296bd5SBarry Smith     dmsnesvi->createinterpolation = dm->ops->createinterpolation;
22025296bd5SBarry Smith     dm->ops->createinterpolation  = DMCreateInterpolation_SNESVI;
221c2fc9fa9SBarry Smith     dmsnesvi->coarsen             = dm->ops->coarsen;
222c2fc9fa9SBarry Smith     dm->ops->coarsen              = DMCoarsen_SNESVI;
223c2fc9fa9SBarry Smith     dmsnesvi->createglobalvector  = dm->ops->createglobalvector;
224c2fc9fa9SBarry Smith     dm->ops->createglobalvector   = DMCreateGlobalVector_SNESVI;
2255a84ad33SLisandro Dalcin     dmsnesvi->createinjection     = dm->ops->createinjection;
2265a84ad33SLisandro Dalcin     dm->ops->createinjection      = NULL;
2274a7a4c06SLawrence Mitchell     dmsnesvi->hascreateinjection  = dm->ops->hascreateinjection;
2285a84ad33SLisandro Dalcin     dm->ops->hascreateinjection   = NULL;
229c2fc9fa9SBarry Smith   } else {
230c2fc9fa9SBarry Smith     ierr = PetscContainerGetPointer(isnes,(void**)&dmsnesvi);CHKERRQ(ierr);
231c2fc9fa9SBarry Smith     ierr = ISDestroy(&dmsnesvi->inactive);CHKERRQ(ierr);
232c2fc9fa9SBarry Smith   }
233c2fc9fa9SBarry Smith   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
234c2fc9fa9SBarry Smith   ierr = ISGetLocalSize(inactive,&dmsnesvi->n);CHKERRQ(ierr);
2351aa26658SKarl Rupp 
236c2fc9fa9SBarry Smith   dmsnesvi->inactive = inactive;
237c2fc9fa9SBarry Smith   dmsnesvi->dm       = dm;
238c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
239c2fc9fa9SBarry Smith }
240c2fc9fa9SBarry Smith 
241c2fc9fa9SBarry Smith /*
242c2fc9fa9SBarry Smith      DMDestroyVI - Frees the DM_SNESVI object contained in the DM
24325296bd5SBarry Smith          - also resets the function pointers in the DM for createinterpolation() etc to use the original DM
244c2fc9fa9SBarry Smith */
24525acbd8eSLisandro Dalcin static PetscErrorCode DMDestroyVI(DM dm)
246c2fc9fa9SBarry Smith {
247c2fc9fa9SBarry Smith   PetscErrorCode ierr;
248c2fc9fa9SBarry Smith 
249c2fc9fa9SBarry Smith   PetscFunctionBegin;
250c2fc9fa9SBarry Smith   if (!dm) PetscFunctionReturn(0);
2510298fd71SBarry Smith   ierr = PetscObjectCompose((PetscObject)dm,"VI",(PetscObject)NULL);CHKERRQ(ierr);
252c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
253c2fc9fa9SBarry Smith }
254c2fc9fa9SBarry Smith 
255c2fc9fa9SBarry Smith /* --------------------------------------------------------------------------------------------------------*/
256c2fc9fa9SBarry Smith 
257c2fc9fa9SBarry Smith 
258f450aa47SBarry Smith PetscErrorCode SNESCreateIndexSets_VINEWTONRSLS(SNES snes,Vec X,Vec F,IS *ISact,IS *ISinact)
259c2fc9fa9SBarry Smith {
260c2fc9fa9SBarry Smith   PetscErrorCode ierr;
261c2fc9fa9SBarry Smith 
262c2fc9fa9SBarry Smith   PetscFunctionBegin;
263c2fc9fa9SBarry Smith   ierr = SNESVIGetActiveSetIS(snes,X,F,ISact);CHKERRQ(ierr);
264c2fc9fa9SBarry Smith   ierr = ISComplement(*ISact,X->map->rstart,X->map->rend,ISinact);CHKERRQ(ierr);
265c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
266c2fc9fa9SBarry Smith }
267c2fc9fa9SBarry Smith 
268c2fc9fa9SBarry Smith /* Create active and inactive set vectors. The local size of this vector is set and petsc computes the global size */
269f450aa47SBarry Smith PetscErrorCode SNESCreateSubVectors_VINEWTONRSLS(SNES snes,PetscInt n,Vec *newv)
270c2fc9fa9SBarry Smith {
271c2fc9fa9SBarry Smith   PetscErrorCode ierr;
272c2fc9fa9SBarry Smith   Vec            v;
273c2fc9fa9SBarry Smith 
274c2fc9fa9SBarry Smith   PetscFunctionBegin;
275ce94432eSBarry Smith   ierr  = VecCreate(PetscObjectComm((PetscObject)snes),&v);CHKERRQ(ierr);
276c2fc9fa9SBarry Smith   ierr  = VecSetSizes(v,n,PETSC_DECIDE);CHKERRQ(ierr);
277c0dedaeaSBarry Smith   ierr  = VecSetType(v,VECSTANDARD);CHKERRQ(ierr);
278c2fc9fa9SBarry Smith   *newv = v;
279c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
280c2fc9fa9SBarry Smith }
281c2fc9fa9SBarry Smith 
282c2fc9fa9SBarry Smith /* Resets the snes PC and KSP when the active set sizes change */
283c2fc9fa9SBarry Smith PetscErrorCode SNESVIResetPCandKSP(SNES snes,Mat Amat,Mat Pmat)
284c2fc9fa9SBarry Smith {
285c2fc9fa9SBarry Smith   PetscErrorCode ierr;
286c2fc9fa9SBarry Smith   KSP            snesksp;
287c2fc9fa9SBarry Smith 
288c2fc9fa9SBarry Smith   PetscFunctionBegin;
289c2fc9fa9SBarry Smith   ierr = SNESGetKSP(snes,&snesksp);CHKERRQ(ierr);
290c2fc9fa9SBarry Smith   ierr = KSPReset(snesksp);CHKERRQ(ierr);
29184343125SMatthew G. Knepley   ierr = KSPResetFromOptions(snesksp);CHKERRQ(ierr);
292c2fc9fa9SBarry Smith 
293c2fc9fa9SBarry Smith   /*
294c2fc9fa9SBarry Smith   KSP                    kspnew;
295c2fc9fa9SBarry Smith   PC                     pcnew;
296ea799195SBarry Smith   MatSolverType          stype;
297c2fc9fa9SBarry Smith 
298c2fc9fa9SBarry Smith 
299ce94432eSBarry Smith   ierr = KSPCreate(PetscObjectComm((PetscObject)snes),&kspnew);CHKERRQ(ierr);
300c2fc9fa9SBarry Smith   kspnew->pc_side = snesksp->pc_side;
301c2fc9fa9SBarry Smith   kspnew->rtol    = snesksp->rtol;
302c2fc9fa9SBarry Smith   kspnew->abstol    = snesksp->abstol;
303c2fc9fa9SBarry Smith   kspnew->max_it  = snesksp->max_it;
304c2fc9fa9SBarry Smith   ierr = KSPSetType(kspnew,((PetscObject)snesksp)->type_name);CHKERRQ(ierr);
305c2fc9fa9SBarry Smith   ierr = KSPGetPC(kspnew,&pcnew);CHKERRQ(ierr);
306c2fc9fa9SBarry Smith   ierr = PCSetType(kspnew->pc,((PetscObject)snesksp->pc)->type_name);CHKERRQ(ierr);
30723ee1639SBarry Smith   ierr = PCSetOperators(kspnew->pc,Amat,Pmat);CHKERRQ(ierr);
3083ca39a21SBarry Smith   ierr = PCFactorGetMatSolverType(snesksp->pc,&stype);CHKERRQ(ierr);
3093ca39a21SBarry Smith   ierr = PCFactorSetMatSolverType(kspnew->pc,stype);CHKERRQ(ierr);
310c2fc9fa9SBarry Smith   ierr = KSPDestroy(&snesksp);CHKERRQ(ierr);
311c2fc9fa9SBarry Smith   snes->ksp = kspnew;
3123bb1ff40SBarry Smith   ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)kspnew);CHKERRQ(ierr);
313c2fc9fa9SBarry Smith    ierr = KSPSetFromOptions(kspnew);CHKERRQ(ierr);*/
314c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
315c2fc9fa9SBarry Smith }
316c2fc9fa9SBarry Smith 
317c2fc9fa9SBarry Smith /* Variational Inequality solver using reduce space method. No semismooth algorithm is
318c2fc9fa9SBarry Smith    implemented in this algorithm. It basically identifies the active constraints and does
319c2fc9fa9SBarry Smith    a linear solve on the other variables (those not associated with the active constraints). */
320f450aa47SBarry Smith PetscErrorCode SNESSolve_VINEWTONRSLS(SNES snes)
321c2fc9fa9SBarry Smith {
322f450aa47SBarry Smith   SNES_VINEWTONRSLS    *vi = (SNES_VINEWTONRSLS*)snes->data;
323c2fc9fa9SBarry Smith   PetscErrorCode       ierr;
324c2fc9fa9SBarry Smith   PetscInt             maxits,i,lits;
325422a814eSBarry Smith   SNESLineSearchReason lssucceed;
326c2fc9fa9SBarry Smith   PetscReal            fnorm,gnorm,xnorm=0,ynorm;
3279bd66eb0SPeter Brune   Vec                  Y,X,F;
328c2fc9fa9SBarry Smith   KSPConvergedReason   kspreason;
32992e89061SBarry Smith   KSP                  ksp;
33092e89061SBarry Smith   PC                   pc;
331c2fc9fa9SBarry Smith 
332c2fc9fa9SBarry Smith   PetscFunctionBegin;
33392e89061SBarry Smith   /* Multigrid must use Galerkin for coarse grids with active set/reduced space methods; cannot rediscretize on coarser grids*/
33492e89061SBarry Smith   ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr);
33592e89061SBarry Smith   ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
3362134b1e4SBarry Smith   ierr = PCMGSetGalerkin(pc,PC_MG_GALERKIN_BOTH);CHKERRQ(ierr);
33792e89061SBarry Smith 
338c2fc9fa9SBarry Smith   snes->numFailures            = 0;
339c2fc9fa9SBarry Smith   snes->numLinearSolveFailures = 0;
340c2fc9fa9SBarry Smith   snes->reason                 = SNES_CONVERGED_ITERATING;
341c2fc9fa9SBarry Smith 
342c2fc9fa9SBarry Smith   maxits = snes->max_its;               /* maximum number of iterations */
343c2fc9fa9SBarry Smith   X      = snes->vec_sol;               /* solution vector */
344c2fc9fa9SBarry Smith   F      = snes->vec_func;              /* residual vector */
345c2fc9fa9SBarry Smith   Y      = snes->work[0];               /* work vectors */
3469bd66eb0SPeter Brune 
347f1c6b773SPeter Brune   ierr = SNESLineSearchSetVIFunctions(snes->linesearch, SNESVIProjectOntoBounds, SNESVIComputeInactiveSetFnorm);CHKERRQ(ierr);
3480298fd71SBarry Smith   ierr = SNESLineSearchSetVecs(snes->linesearch, X, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
349f1c6b773SPeter Brune   ierr = SNESLineSearchSetUp(snes->linesearch);CHKERRQ(ierr);
350c2fc9fa9SBarry Smith 
351e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
352c2fc9fa9SBarry Smith   snes->iter = 0;
353c2fc9fa9SBarry Smith   snes->norm = 0.0;
354e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
355c2fc9fa9SBarry Smith 
356c2fc9fa9SBarry Smith   ierr = SNESVIProjectOntoBounds(snes,X);CHKERRQ(ierr);
357c2fc9fa9SBarry Smith   ierr = SNESComputeFunction(snes,X,F);CHKERRQ(ierr);
358c2fc9fa9SBarry Smith   ierr = SNESVIComputeInactiveSetFnorm(snes,F,X,&fnorm);CHKERRQ(ierr);
3592fbecc10SBarry Smith   ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr);        /* xnorm <- ||x||  */
360422a814eSBarry Smith   SNESCheckFunctionNorm(snes,fnorm);
361e04113cfSBarry Smith   ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
362c2fc9fa9SBarry Smith   snes->norm = fnorm;
363e04113cfSBarry Smith   ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
364a71f0d7dSBarry Smith   ierr       = SNESLogConvergenceHistory(snes,fnorm,0);CHKERRQ(ierr);
365c2fc9fa9SBarry Smith   ierr       = SNESMonitor(snes,0,fnorm);CHKERRQ(ierr);
366c2fc9fa9SBarry Smith 
367c2fc9fa9SBarry Smith   /* test convergence */
368c2fc9fa9SBarry Smith   ierr = (*snes->ops->converged)(snes,0,0.0,0.0,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
369c2fc9fa9SBarry Smith   if (snes->reason) PetscFunctionReturn(0);
370c2fc9fa9SBarry Smith 
371c2fc9fa9SBarry Smith 
372c2fc9fa9SBarry Smith   for (i=0; i<maxits; i++) {
373c2fc9fa9SBarry Smith 
374f009fc93SPatrick Farrell     IS         IS_act; /* _act -> active set _inact -> inactive set */
375c2fc9fa9SBarry Smith     IS         IS_redact; /* redundant active set */
376c2fc9fa9SBarry Smith     VecScatter scat_act,scat_inact;
377c2fc9fa9SBarry Smith     PetscInt   nis_act,nis_inact;
378c2fc9fa9SBarry Smith     Vec        Y_act,Y_inact,F_inact;
379c2fc9fa9SBarry Smith     Mat        jac_inact_inact,prejac_inact_inact;
380c2fc9fa9SBarry Smith     PetscBool  isequal;
381c2fc9fa9SBarry Smith 
382c2fc9fa9SBarry Smith     /* Call general purpose update function */
383c2fc9fa9SBarry Smith     if (snes->ops->update) {
384c2fc9fa9SBarry Smith       ierr = (*snes->ops->update)(snes, snes->iter);CHKERRQ(ierr);
385c2fc9fa9SBarry Smith     }
386d1e9a80fSBarry Smith     ierr = SNESComputeJacobian(snes,X,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr);
38707b62357SFande Kong     SNESCheckJacobianDomainerror(snes);
388c2fc9fa9SBarry Smith 
389c2fc9fa9SBarry Smith     /* Create active and inactive index sets */
390c2fc9fa9SBarry Smith 
391c2fc9fa9SBarry Smith     /*original
392f009fc93SPatrick Farrell     ierr = SNESVICreateIndexSets_RS(snes,X,F,&IS_act,&vi->IS_inact);CHKERRQ(ierr);
393c2fc9fa9SBarry Smith      */
394c2fc9fa9SBarry Smith     ierr = SNESVIGetActiveSetIS(snes,X,F,&IS_act);CHKERRQ(ierr);
395c2fc9fa9SBarry Smith 
396c2fc9fa9SBarry Smith     if (vi->checkredundancy) {
397c2fc9fa9SBarry Smith       (*vi->checkredundancy)(snes,IS_act,&IS_redact,vi->ctxP);CHKERRQ(ierr);
398c2fc9fa9SBarry Smith       if (IS_redact) {
399c2fc9fa9SBarry Smith         ierr = ISSort(IS_redact);CHKERRQ(ierr);
400f009fc93SPatrick Farrell         ierr = ISComplement(IS_redact,X->map->rstart,X->map->rend,&vi->IS_inact);CHKERRQ(ierr);
401c2fc9fa9SBarry Smith         ierr = ISDestroy(&IS_redact);CHKERRQ(ierr);
4021aa26658SKarl Rupp       } else {
403f009fc93SPatrick Farrell         ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&vi->IS_inact);CHKERRQ(ierr);
404c2fc9fa9SBarry Smith       }
405c2fc9fa9SBarry Smith     } else {
406f009fc93SPatrick Farrell       ierr = ISComplement(IS_act,X->map->rstart,X->map->rend,&vi->IS_inact);CHKERRQ(ierr);
407c2fc9fa9SBarry Smith     }
408c2fc9fa9SBarry Smith 
409c2fc9fa9SBarry Smith 
410c2fc9fa9SBarry Smith     /* Create inactive set submatrix */
4117dae84e0SHong Zhang     ierr = MatCreateSubMatrix(snes->jacobian,vi->IS_inact,vi->IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
412c2fc9fa9SBarry Smith 
41366bfb381SJed Brown     if (0) {                    /* Dead code (temporary developer hack) */
41466bfb381SJed Brown       IS keptrows;
415c2fc9fa9SBarry Smith       ierr = MatFindNonzeroRows(jac_inact_inact,&keptrows);CHKERRQ(ierr);
41666bfb381SJed Brown       if (keptrows) {
417c2fc9fa9SBarry Smith         PetscInt       cnt,*nrows,k;
418c2fc9fa9SBarry Smith         const PetscInt *krows,*inact;
419367daffbSBarry Smith         PetscInt       rstart;
420c2fc9fa9SBarry Smith 
421367daffbSBarry Smith         ierr = MatGetOwnershipRange(jac_inact_inact,&rstart,NULL);CHKERRQ(ierr);
422c2fc9fa9SBarry Smith         ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
423c2fc9fa9SBarry Smith         ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
424c2fc9fa9SBarry Smith 
425c2fc9fa9SBarry Smith         ierr = ISGetLocalSize(keptrows,&cnt);CHKERRQ(ierr);
426c2fc9fa9SBarry Smith         ierr = ISGetIndices(keptrows,&krows);CHKERRQ(ierr);
427f009fc93SPatrick Farrell         ierr = ISGetIndices(vi->IS_inact,&inact);CHKERRQ(ierr);
428785e854fSJed Brown         ierr = PetscMalloc1(cnt,&nrows);CHKERRQ(ierr);
4291aa26658SKarl Rupp         for (k=0; k<cnt; k++) nrows[k] = inact[krows[k]-rstart];
430c2fc9fa9SBarry Smith         ierr = ISRestoreIndices(keptrows,&krows);CHKERRQ(ierr);
431f009fc93SPatrick Farrell         ierr = ISRestoreIndices(vi->IS_inact,&inact);CHKERRQ(ierr);
432c2fc9fa9SBarry Smith         ierr = ISDestroy(&keptrows);CHKERRQ(ierr);
433f009fc93SPatrick Farrell         ierr = ISDestroy(&vi->IS_inact);CHKERRQ(ierr);
434c2fc9fa9SBarry Smith 
435f009fc93SPatrick Farrell         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),cnt,nrows,PETSC_OWN_POINTER,&vi->IS_inact);CHKERRQ(ierr);
436f009fc93SPatrick Farrell         ierr = ISComplement(vi->IS_inact,F->map->rstart,F->map->rend,&IS_act);CHKERRQ(ierr);
4377dae84e0SHong Zhang         ierr = MatCreateSubMatrix(snes->jacobian,vi->IS_inact,vi->IS_inact,MAT_INITIAL_MATRIX,&jac_inact_inact);CHKERRQ(ierr);
438c2fc9fa9SBarry Smith       }
43966bfb381SJed Brown     }
440f009fc93SPatrick Farrell     ierr = DMSetVI(snes->dm,vi->IS_inact);CHKERRQ(ierr);
441c2fc9fa9SBarry Smith     /* remove later */
442c2fc9fa9SBarry Smith 
443c2fc9fa9SBarry Smith     /*
4445f042095SDmitry Karpeev     ierr = VecView(vi->xu,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xu))->comm));CHKERRQ(ierr);
4455f042095SDmitry Karpeev     ierr = VecView(vi->xl,PETSC_VIEWER_BINARY_(((PetscObject)(vi->xl))->comm));CHKERRQ(ierr);
446ce94432eSBarry Smith     ierr = VecView(X,PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)X)));CHKERRQ(ierr);
447ce94432eSBarry Smith     ierr = VecView(F,PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)F)));CHKERRQ(ierr);
448f009fc93SPatrick Farrell     ierr = ISView(vi->IS_inact,PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)vi->IS_inact)));CHKERRQ(ierr);
449c2fc9fa9SBarry Smith      */
450c2fc9fa9SBarry Smith 
451c2fc9fa9SBarry Smith     /* Get sizes of active and inactive sets */
452c2fc9fa9SBarry Smith     ierr = ISGetLocalSize(IS_act,&nis_act);CHKERRQ(ierr);
453f009fc93SPatrick Farrell     ierr = ISGetLocalSize(vi->IS_inact,&nis_inact);CHKERRQ(ierr);
454c2fc9fa9SBarry Smith 
455c2fc9fa9SBarry Smith     /* Create active and inactive set vectors */
456f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&F_inact);CHKERRQ(ierr);
457f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_act,&Y_act);CHKERRQ(ierr);
458f450aa47SBarry Smith     ierr = SNESCreateSubVectors_VINEWTONRSLS(snes,nis_inact,&Y_inact);CHKERRQ(ierr);
459c2fc9fa9SBarry Smith 
460c2fc9fa9SBarry Smith     /* Create scatter contexts */
4619448b7f1SJunchao Zhang     ierr = VecScatterCreate(Y,IS_act,Y_act,NULL,&scat_act);CHKERRQ(ierr);
4629448b7f1SJunchao Zhang     ierr = VecScatterCreate(Y,vi->IS_inact,Y_inact,NULL,&scat_inact);CHKERRQ(ierr);
463c2fc9fa9SBarry Smith 
464c2fc9fa9SBarry Smith     /* Do a vec scatter to active and inactive set vectors */
465c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
466c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,F,F_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
467c2fc9fa9SBarry Smith 
468c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
469c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_act,Y,Y_act,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
470c2fc9fa9SBarry Smith 
471c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
472c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,Y,Y_inact,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
473c2fc9fa9SBarry Smith 
474c2fc9fa9SBarry Smith     /* Active set direction = 0 */
475c2fc9fa9SBarry Smith     ierr = VecSet(Y_act,0);CHKERRQ(ierr);
476c2fc9fa9SBarry Smith     if (snes->jacobian != snes->jacobian_pre) {
4777dae84e0SHong Zhang       ierr = MatCreateSubMatrix(snes->jacobian_pre,vi->IS_inact,vi->IS_inact,MAT_INITIAL_MATRIX,&prejac_inact_inact);CHKERRQ(ierr);
478c2fc9fa9SBarry Smith     } else prejac_inact_inact = jac_inact_inact;
479c2fc9fa9SBarry Smith 
480f009fc93SPatrick Farrell     ierr = ISEqual(vi->IS_inact_prev,vi->IS_inact,&isequal);CHKERRQ(ierr);
481c2fc9fa9SBarry Smith     if (!isequal) {
482c2fc9fa9SBarry Smith       ierr = SNESVIResetPCandKSP(snes,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
4836dbb499eSCian Wilson       ierr = PCFieldSplitRestrictIS(pc,vi->IS_inact);CHKERRQ(ierr);
484c2fc9fa9SBarry Smith     }
485c2fc9fa9SBarry Smith 
486f009fc93SPatrick Farrell     /*      ierr = ISView(vi->IS_inact,0);CHKERRQ(ierr); */
487c2fc9fa9SBarry Smith     /*      ierr = ISView(IS_act,0);CHKERRQ(ierr);*/
488c2fc9fa9SBarry Smith     /*      ierr = MatView(snes->jacobian_pre,0); */
489c2fc9fa9SBarry Smith 
490c2fc9fa9SBarry Smith 
491c2fc9fa9SBarry Smith 
49223ee1639SBarry Smith     ierr = KSPSetOperators(snes->ksp,jac_inact_inact,prejac_inact_inact);CHKERRQ(ierr);
493c2fc9fa9SBarry Smith     ierr = KSPSetUp(snes->ksp);CHKERRQ(ierr);
494c2fc9fa9SBarry Smith     {
495c2fc9fa9SBarry Smith       PC        pc;
496c2fc9fa9SBarry Smith       PetscBool flg;
497c2fc9fa9SBarry Smith       ierr = KSPGetPC(snes->ksp,&pc);CHKERRQ(ierr);
498251f4c67SDmitry Karpeev       ierr = PetscObjectTypeCompare((PetscObject)pc,PCFIELDSPLIT,&flg);CHKERRQ(ierr);
499c2fc9fa9SBarry Smith       if (flg) {
500c2fc9fa9SBarry Smith         KSP *subksps;
5010298fd71SBarry Smith         ierr = PCFieldSplitGetSubKSP(pc,NULL,&subksps);CHKERRQ(ierr);
502c2fc9fa9SBarry Smith         ierr = KSPGetPC(subksps[0],&pc);CHKERRQ(ierr);
503c2fc9fa9SBarry Smith         ierr = PetscFree(subksps);CHKERRQ(ierr);
504251f4c67SDmitry Karpeev         ierr = PetscObjectTypeCompare((PetscObject)pc,PCBJACOBI,&flg);CHKERRQ(ierr);
505c2fc9fa9SBarry Smith         if (flg) {
506c2fc9fa9SBarry Smith           PetscInt       n,N = 101*101,j,cnts[3] = {0,0,0};
507c2fc9fa9SBarry Smith           const PetscInt *ii;
508c2fc9fa9SBarry Smith 
509f009fc93SPatrick Farrell           ierr = ISGetSize(vi->IS_inact,&n);CHKERRQ(ierr);
510f009fc93SPatrick Farrell           ierr = ISGetIndices(vi->IS_inact,&ii);CHKERRQ(ierr);
511c2fc9fa9SBarry Smith           for (j=0; j<n; j++) {
512c2fc9fa9SBarry Smith             if (ii[j] < N) cnts[0]++;
513c2fc9fa9SBarry Smith             else if (ii[j] < 2*N) cnts[1]++;
514c2fc9fa9SBarry Smith             else if (ii[j] < 3*N) cnts[2]++;
515c2fc9fa9SBarry Smith           }
516f009fc93SPatrick Farrell           ierr = ISRestoreIndices(vi->IS_inact,&ii);CHKERRQ(ierr);
517c2fc9fa9SBarry Smith 
518c2fc9fa9SBarry Smith           ierr = PCBJacobiSetTotalBlocks(pc,3,cnts);CHKERRQ(ierr);
519c2fc9fa9SBarry Smith         }
520c2fc9fa9SBarry Smith       }
521c2fc9fa9SBarry Smith     }
522c2fc9fa9SBarry Smith 
523d4211eb9SBarry Smith     ierr = KSPSolve(snes->ksp,F_inact,Y_inact);CHKERRQ(ierr);
524c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
525c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_act,Y_act,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
526c2fc9fa9SBarry Smith     ierr = VecScatterBegin(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
527c2fc9fa9SBarry Smith     ierr = VecScatterEnd(scat_inact,Y_inact,Y,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
528c2fc9fa9SBarry Smith 
529c2fc9fa9SBarry Smith     ierr = VecDestroy(&F_inact);CHKERRQ(ierr);
530c2fc9fa9SBarry Smith     ierr = VecDestroy(&Y_act);CHKERRQ(ierr);
531c2fc9fa9SBarry Smith     ierr = VecDestroy(&Y_inact);CHKERRQ(ierr);
532c2fc9fa9SBarry Smith     ierr = VecScatterDestroy(&scat_act);CHKERRQ(ierr);
533c2fc9fa9SBarry Smith     ierr = VecScatterDestroy(&scat_inact);CHKERRQ(ierr);
534c2fc9fa9SBarry Smith     ierr = ISDestroy(&IS_act);CHKERRQ(ierr);
535c2fc9fa9SBarry Smith     if (!isequal) {
536c2fc9fa9SBarry Smith       ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
537f009fc93SPatrick Farrell       ierr = ISDuplicate(vi->IS_inact,&vi->IS_inact_prev);CHKERRQ(ierr);
538c2fc9fa9SBarry Smith     }
539f009fc93SPatrick Farrell     ierr = ISDestroy(&vi->IS_inact);CHKERRQ(ierr);
540c2fc9fa9SBarry Smith     ierr = MatDestroy(&jac_inact_inact);CHKERRQ(ierr);
541c2fc9fa9SBarry Smith     if (snes->jacobian != snes->jacobian_pre) {
542c2fc9fa9SBarry Smith       ierr = MatDestroy(&prejac_inact_inact);CHKERRQ(ierr);
543c2fc9fa9SBarry Smith     }
544fa6eefd1SCian Wilson 
545fa6eefd1SCian Wilson     ierr = KSPGetConvergedReason(snes->ksp,&kspreason);CHKERRQ(ierr);
546fa6eefd1SCian Wilson     if (kspreason < 0) {
547fa6eefd1SCian Wilson       if (++snes->numLinearSolveFailures >= snes->maxLinearSolveFailures) {
548fa6eefd1SCian Wilson         ierr         = PetscInfo2(snes,"iter=%D, number linear solve failures %D greater than current SNES allowed, stopping solve\n",snes->iter,snes->numLinearSolveFailures);CHKERRQ(ierr);
549fa6eefd1SCian Wilson         snes->reason = SNES_DIVERGED_LINEAR_SOLVE;
550fa6eefd1SCian Wilson         break;
551fa6eefd1SCian Wilson       }
552fa6eefd1SCian Wilson     }
553fa6eefd1SCian Wilson 
554c2fc9fa9SBarry Smith     ierr              = KSPGetIterationNumber(snes->ksp,&lits);CHKERRQ(ierr);
555c2fc9fa9SBarry Smith     snes->linear_its += lits;
556c2fc9fa9SBarry Smith     ierr              = PetscInfo2(snes,"iter=%D, linear solve iterations=%D\n",snes->iter,lits);CHKERRQ(ierr);
557c2fc9fa9SBarry Smith     /*
5586b2b7091SBarry Smith     if (snes->ops->precheck) {
559c2fc9fa9SBarry Smith       PetscBool changed_y = PETSC_FALSE;
5606b2b7091SBarry Smith       ierr = (*snes->ops->precheck)(snes,X,Y,snes->precheck,&changed_y);CHKERRQ(ierr);
561c2fc9fa9SBarry Smith     }
562c2fc9fa9SBarry Smith 
563c2fc9fa9SBarry Smith     if (PetscLogPrintInfo) {
564c2fc9fa9SBarry Smith       ierr = SNESVICheckResidual_Private(snes,snes->jacobian,F,Y,G,W);CHKERRQ(ierr);
565c2fc9fa9SBarry Smith     }
566c2fc9fa9SBarry Smith     */
567c2fc9fa9SBarry Smith     /* Compute a (scaled) negative update in the line search routine:
568c2fc9fa9SBarry Smith          Y <- X - lambda*Y
569c2fc9fa9SBarry Smith        and evaluate G = function(Y) (depends on the line search).
570c2fc9fa9SBarry Smith     */
571c2fc9fa9SBarry Smith     ierr  = VecCopy(Y,snes->vec_sol_update);CHKERRQ(ierr);
572c2fc9fa9SBarry Smith     ynorm = 1; gnorm = fnorm;
573f1c6b773SPeter Brune     ierr  = SNESLineSearchApply(snes->linesearch, X, F, &gnorm, Y);CHKERRQ(ierr);
574422a814eSBarry Smith     ierr  = SNESLineSearchGetReason(snes->linesearch, &lssucceed);CHKERRQ(ierr);
575f1c6b773SPeter Brune     ierr  = SNESLineSearchGetNorms(snes->linesearch, &xnorm, &gnorm, &ynorm);CHKERRQ(ierr);
576c2fc9fa9SBarry 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);
577c2fc9fa9SBarry Smith     if (snes->reason == SNES_DIVERGED_FUNCTION_COUNT) break;
578c2fc9fa9SBarry Smith     if (snes->domainerror) {
579c2fc9fa9SBarry Smith       snes->reason = SNES_DIVERGED_FUNCTION_DOMAIN;
580c2fc9fa9SBarry Smith       ierr         = DMDestroyVI(snes->dm);CHKERRQ(ierr);
581c2fc9fa9SBarry Smith       PetscFunctionReturn(0);
582c2fc9fa9SBarry Smith     }
583422a814eSBarry Smith     if (lssucceed) {
584c2fc9fa9SBarry Smith       if (++snes->numFailures >= snes->maxFailures) {
585c2fc9fa9SBarry Smith         PetscBool ismin;
586c2fc9fa9SBarry Smith         snes->reason = SNES_DIVERGED_LINE_SEARCH;
5879bd66eb0SPeter Brune         ierr         = SNESVICheckLocalMin_Private(snes,snes->jacobian,F,X,gnorm,&ismin);CHKERRQ(ierr);
588c2fc9fa9SBarry Smith         if (ismin) snes->reason = SNES_DIVERGED_LOCAL_MIN;
589c2fc9fa9SBarry Smith         break;
590c2fc9fa9SBarry Smith       }
591c2fc9fa9SBarry Smith    }
59287e98922SBarry Smith    ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
593c2fc9fa9SBarry Smith     /* Update function and solution vectors */
594c2fc9fa9SBarry Smith     fnorm = gnorm;
595c2fc9fa9SBarry Smith     /* Monitor convergence */
596e04113cfSBarry Smith     ierr       = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr);
597c2fc9fa9SBarry Smith     snes->iter = i+1;
598c2fc9fa9SBarry Smith     snes->norm = fnorm;
599c1e67a49SFande Kong     snes->xnorm = xnorm;
600c1e67a49SFande Kong     snes->ynorm = ynorm;
601e04113cfSBarry Smith     ierr       = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr);
602a71f0d7dSBarry Smith     ierr       = SNESLogConvergenceHistory(snes,snes->norm,lits);CHKERRQ(ierr);
603c2fc9fa9SBarry Smith     ierr       = SNESMonitor(snes,snes->iter,snes->norm);CHKERRQ(ierr);
604c2fc9fa9SBarry Smith     /* Test for convergence, xnorm = || X || */
605e2a6519dSDmitry Karpeev     if (snes->ops->converged != SNESConvergedSkip) { ierr = VecNorm(X,NORM_2,&xnorm);CHKERRQ(ierr); }
606c2fc9fa9SBarry Smith     ierr = (*snes->ops->converged)(snes,snes->iter,xnorm,ynorm,fnorm,&snes->reason,snes->cnvP);CHKERRQ(ierr);
607c2fc9fa9SBarry Smith     if (snes->reason) break;
608c2fc9fa9SBarry Smith   }
60991a42fcfSBarry Smith   /* make sure that the VI information attached to the DM is removed if the for loop above was broken early due to some exceptional conditional */
61091a42fcfSBarry Smith   ierr = DMDestroyVI(snes->dm);CHKERRQ(ierr);
611c2fc9fa9SBarry Smith   if (i == maxits) {
612c2fc9fa9SBarry Smith     ierr = PetscInfo1(snes,"Maximum number of iterations has been reached: %D\n",maxits);CHKERRQ(ierr);
613c2fc9fa9SBarry Smith     if (!snes->reason) snes->reason = SNES_DIVERGED_MAX_IT;
614c2fc9fa9SBarry Smith   }
615c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
616c2fc9fa9SBarry Smith }
617c2fc9fa9SBarry Smith 
618c2fc9fa9SBarry Smith PetscErrorCode SNESVISetRedundancyCheck(SNES snes,PetscErrorCode (*func)(SNES,IS,IS*,void*),void *ctx)
619c2fc9fa9SBarry Smith {
620f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*)snes->data;
621c2fc9fa9SBarry Smith 
622c2fc9fa9SBarry Smith   PetscFunctionBegin;
623c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
624c2fc9fa9SBarry Smith   vi->checkredundancy = func;
625c2fc9fa9SBarry Smith   vi->ctxP            = ctx;
626c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
627c2fc9fa9SBarry Smith }
628c2fc9fa9SBarry Smith 
629c2fc9fa9SBarry Smith #if defined(PETSC_HAVE_MATLAB_ENGINE)
630c2fc9fa9SBarry Smith #include <engine.h>
631c2fc9fa9SBarry Smith #include <mex.h>
632c2fc9fa9SBarry Smith typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext;
633c2fc9fa9SBarry Smith 
634c2fc9fa9SBarry Smith PetscErrorCode SNESVIRedundancyCheck_Matlab(SNES snes,IS is_act,IS *is_redact,void *ctx)
635c2fc9fa9SBarry Smith {
636c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
637c2fc9fa9SBarry Smith   SNESMatlabContext *sctx = (SNESMatlabContext*)ctx;
638c2fc9fa9SBarry Smith   int               nlhs  = 1, nrhs = 5;
639c2fc9fa9SBarry Smith   mxArray           *plhs[1], *prhs[5];
640c2fc9fa9SBarry Smith   long long int     l1      = 0, l2 = 0, ls = 0;
6410298fd71SBarry Smith   PetscInt          *indices=NULL;
642c2fc9fa9SBarry Smith 
643c2fc9fa9SBarry Smith   PetscFunctionBegin;
644c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(snes,SNES_CLASSID,1);
645c2fc9fa9SBarry Smith   PetscValidHeaderSpecific(is_act,IS_CLASSID,2);
646c2fc9fa9SBarry Smith   PetscValidPointer(is_redact,3);
647c2fc9fa9SBarry Smith   PetscCheckSameComm(snes,1,is_act,2);
648c2fc9fa9SBarry Smith 
649c2fc9fa9SBarry Smith   /* Create IS for reduced active set of size 0, its size and indices will
650c2fc9fa9SBarry Smith    bet set by the Matlab function */
651ce94432eSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),0,indices,PETSC_OWN_POINTER,is_redact);CHKERRQ(ierr);
652c2fc9fa9SBarry Smith   /* call Matlab function in ctx */
653580bdb30SBarry Smith   ierr    = PetscArraycpy(&ls,&snes,1);CHKERRQ(ierr);
654580bdb30SBarry Smith   ierr    = PetscArraycpy(&l1,&is_act,1);CHKERRQ(ierr);
655580bdb30SBarry Smith   ierr    = PetscArraycpy(&l2,is_redact,1);CHKERRQ(ierr);
656c2fc9fa9SBarry Smith   prhs[0] = mxCreateDoubleScalar((double)ls);
657c2fc9fa9SBarry Smith   prhs[1] = mxCreateDoubleScalar((double)l1);
658c2fc9fa9SBarry Smith   prhs[2] = mxCreateDoubleScalar((double)l2);
659c2fc9fa9SBarry Smith   prhs[3] = mxCreateString(sctx->funcname);
660c2fc9fa9SBarry Smith   prhs[4] = sctx->ctx;
661c2fc9fa9SBarry Smith   ierr    = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESVIRedundancyCheckInternal");CHKERRQ(ierr);
662c2fc9fa9SBarry Smith   ierr    = mxGetScalar(plhs[0]);CHKERRQ(ierr);
663c2fc9fa9SBarry Smith   mxDestroyArray(prhs[0]);
664c2fc9fa9SBarry Smith   mxDestroyArray(prhs[1]);
665c2fc9fa9SBarry Smith   mxDestroyArray(prhs[2]);
666c2fc9fa9SBarry Smith   mxDestroyArray(prhs[3]);
667c2fc9fa9SBarry Smith   mxDestroyArray(plhs[0]);
668c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
669c2fc9fa9SBarry Smith }
670c2fc9fa9SBarry Smith 
671c2fc9fa9SBarry Smith PetscErrorCode SNESVISetRedundancyCheckMatlab(SNES snes,const char *func,mxArray *ctx)
672c2fc9fa9SBarry Smith {
673c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
674c2fc9fa9SBarry Smith   SNESMatlabContext *sctx;
675c2fc9fa9SBarry Smith 
676c2fc9fa9SBarry Smith   PetscFunctionBegin;
677c2fc9fa9SBarry Smith   /* currently sctx is memory bleed */
678854ce69bSBarry Smith   ierr      = PetscNew(&sctx);CHKERRQ(ierr);
679c2fc9fa9SBarry Smith   ierr      = PetscStrallocpy(func,&sctx->funcname);CHKERRQ(ierr);
680c2fc9fa9SBarry Smith   sctx->ctx = mxDuplicateArray(ctx);
681c2fc9fa9SBarry Smith   ierr      = SNESVISetRedundancyCheck(snes,SNESVIRedundancyCheck_Matlab,sctx);CHKERRQ(ierr);
682c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
683c2fc9fa9SBarry Smith }
684c2fc9fa9SBarry Smith 
685c2fc9fa9SBarry Smith #endif
686c2fc9fa9SBarry Smith 
687c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
688c2fc9fa9SBarry Smith /*
689f450aa47SBarry Smith    SNESSetUp_VINEWTONRSLS - Sets up the internal data structures for the later use
690c2fc9fa9SBarry Smith    of the SNESVI nonlinear solver.
691c2fc9fa9SBarry Smith 
692c2fc9fa9SBarry Smith    Input Parameter:
693c2fc9fa9SBarry Smith .  snes - the SNES context
694c2fc9fa9SBarry Smith 
695c2fc9fa9SBarry Smith    Application Interface Routine: SNESSetUp()
696c2fc9fa9SBarry Smith 
697c2fc9fa9SBarry Smith    Notes:
698c2fc9fa9SBarry Smith    For basic use of the SNES solvers, the user need not explicitly call
699c2fc9fa9SBarry Smith    SNESSetUp(), since these actions will automatically occur during
700c2fc9fa9SBarry Smith    the call to SNESSolve().
701c2fc9fa9SBarry Smith  */
702f450aa47SBarry Smith PetscErrorCode SNESSetUp_VINEWTONRSLS(SNES snes)
703c2fc9fa9SBarry Smith {
704c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
705f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*) snes->data;
706c2fc9fa9SBarry Smith   PetscInt          *indices;
707c2fc9fa9SBarry Smith   PetscInt          i,n,rstart,rend;
708f1c6b773SPeter Brune   SNESLineSearch    linesearch;
709c2fc9fa9SBarry Smith 
710c2fc9fa9SBarry Smith   PetscFunctionBegin;
711c2fc9fa9SBarry Smith   ierr = SNESSetUp_VI(snes);CHKERRQ(ierr);
712c2fc9fa9SBarry Smith 
713c2fc9fa9SBarry Smith   /* Set up previous active index set for the first snes solve
714c2fc9fa9SBarry Smith    vi->IS_inact_prev = 0,1,2,....N */
715c2fc9fa9SBarry Smith 
716c2fc9fa9SBarry Smith   ierr = VecGetOwnershipRange(snes->vec_sol,&rstart,&rend);CHKERRQ(ierr);
717c2fc9fa9SBarry Smith   ierr = VecGetLocalSize(snes->vec_sol,&n);CHKERRQ(ierr);
718785e854fSJed Brown   ierr = PetscMalloc1(n,&indices);CHKERRQ(ierr);
719c2fc9fa9SBarry Smith   for (i=0; i < n; i++) indices[i] = rstart + i;
720ce94432eSBarry Smith   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)snes),n,indices,PETSC_OWN_POINTER,&vi->IS_inact_prev);CHKERRQ(ierr);
7219bd66eb0SPeter Brune 
7229bd66eb0SPeter Brune   /* set the line search functions */
7239bd66eb0SPeter Brune   if (!snes->linesearch) {
7247601faf0SJed Brown     ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
7251a4f838cSPeter Brune     ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
7269bd66eb0SPeter Brune   }
727c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
728c2fc9fa9SBarry Smith }
729c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
730f450aa47SBarry Smith PetscErrorCode SNESReset_VINEWTONRSLS(SNES snes)
731c2fc9fa9SBarry Smith {
732f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi = (SNES_VINEWTONRSLS*) snes->data;
733c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
734c2fc9fa9SBarry Smith 
735c2fc9fa9SBarry Smith   PetscFunctionBegin;
736c2fc9fa9SBarry Smith   ierr = SNESReset_VI(snes);CHKERRQ(ierr);
737c2fc9fa9SBarry Smith   ierr = ISDestroy(&vi->IS_inact_prev);CHKERRQ(ierr);
738c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
739c2fc9fa9SBarry Smith }
740c2fc9fa9SBarry Smith 
741c2fc9fa9SBarry Smith /* -------------------------------------------------------------------------- */
742c2fc9fa9SBarry Smith /*MC
743f450aa47SBarry Smith       SNESVINEWTONRSLS - Reduced space active set solvers for variational inequalities based on Newton's method
744c2fc9fa9SBarry Smith 
74561589011SJed Brown    Options Database:
746b621fa8fSRichard Tran Mills +   -snes_type <vinewtonssls,vinewtonrsls> - a semi-smooth solver, a reduced space active set method
74761589011SJed Brown -   -snes_vi_monitor - prints the number of active constraints at each iteration.
748c2fc9fa9SBarry Smith 
749c2fc9fa9SBarry Smith    Level: beginner
750c2fc9fa9SBarry Smith 
751b80f3ac1SShri Abhyankar    References:
75296a0c994SBarry Smith .  1. - T. S. Munson, and S. Benson. Flexible Complementarity Solvers for Large Scale
753b80f3ac1SShri Abhyankar      Applications, Optimization Methods and Software, 21 (2006).
754b80f3ac1SShri Abhyankar 
755f4091ad2SBarry Smith .seealso:  SNESVISetVariableBounds(), SNESVISetComputeVariableBounds(), SNESCreate(), SNES, SNESSetType(), SNESVINEWTONSSLS, SNESNEWTONTR, SNESLineSearchSetType(),SNESLineSearchSetPostCheck(), SNESLineSearchSetPreCheck()
756c2fc9fa9SBarry Smith 
757c2fc9fa9SBarry Smith M*/
7588cc058d9SJed Brown PETSC_EXTERN PetscErrorCode SNESCreate_VINEWTONRSLS(SNES snes)
759c2fc9fa9SBarry Smith {
760c2fc9fa9SBarry Smith   PetscErrorCode    ierr;
761f450aa47SBarry Smith   SNES_VINEWTONRSLS *vi;
762d8d34be6SBarry Smith   SNESLineSearch    linesearch;
763c2fc9fa9SBarry Smith 
764c2fc9fa9SBarry Smith   PetscFunctionBegin;
765f450aa47SBarry Smith   snes->ops->reset          = SNESReset_VINEWTONRSLS;
766f450aa47SBarry Smith   snes->ops->setup          = SNESSetUp_VINEWTONRSLS;
767f450aa47SBarry Smith   snes->ops->solve          = SNESSolve_VINEWTONRSLS;
768c2fc9fa9SBarry Smith   snes->ops->destroy        = SNESDestroy_VI;
769c2fc9fa9SBarry Smith   snes->ops->setfromoptions = SNESSetFromOptions_VI;
7700298fd71SBarry Smith   snes->ops->view           = NULL;
7718d359177SBarry Smith   snes->ops->converged      = SNESConvergedDefault_VI;
772c2fc9fa9SBarry Smith 
773c2fc9fa9SBarry Smith   snes->usesksp = PETSC_TRUE;
774efd4aadfSBarry Smith   snes->usesnpc = PETSC_FALSE;
775c2fc9fa9SBarry Smith 
776d8d34be6SBarry Smith   ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr);
777d8d34be6SBarry Smith   ierr = SNESLineSearchSetType(linesearch, SNESLINESEARCHBT);CHKERRQ(ierr);
778d8d34be6SBarry Smith   ierr = SNESLineSearchBTSetAlpha(linesearch, 0.0);CHKERRQ(ierr);
779d8d34be6SBarry Smith 
7804fc747eaSLawrence Mitchell   snes->alwayscomputesfinalresidual = PETSC_TRUE;
7814fc747eaSLawrence Mitchell 
782b00a9115SJed Brown   ierr                = PetscNewLog(snes,&vi);CHKERRQ(ierr);
783c2fc9fa9SBarry Smith   snes->data          = (void*)vi;
7840298fd71SBarry Smith   vi->checkredundancy = NULL;
785c2fc9fa9SBarry Smith 
786bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESVISetVariableBounds_C",SNESVISetVariableBounds_VI);CHKERRQ(ierr);
787bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)snes,"SNESVISetComputeVariableBounds_C",SNESVISetComputeVariableBounds_VI);CHKERRQ(ierr);
788c2fc9fa9SBarry Smith   PetscFunctionReturn(0);
789c2fc9fa9SBarry Smith }
790c2fc9fa9SBarry Smith 
791