xref: /petsc/src/tao/bound/utils/isutil.c (revision 7e9273c40cc204dfb9a7cb6a2a34b31efa468fb3)
1ba92ff59SBarry Smith #include <petsctao.h> /*I "petsctao.h" I*/
2c4b75bccSAlp Dener #include <petsc/private/vecimpl.h>
3af0996ceSBarry Smith #include <petsc/private/taoimpl.h>
4aaa7dc30SBarry Smith #include <../src/tao/matrix/submatfree.h>
5a7e14dcfSSatish Balay 
6b98f30f2SJason Sarich /*@C
7b98f30f2SJason Sarich   TaoVecGetSubVec - Gets a subvector using the IS
8a7e14dcfSSatish Balay 
9a7e14dcfSSatish Balay   Input Parameters:
10a7e14dcfSSatish Balay + vfull - the full matrix
11a7e14dcfSSatish Balay . is - the index set for the subvector
12a7e14dcfSSatish Balay . reduced_type - the method TAO is using for subsetting (TAO_SUBSET_SUBVEC, TAO_SUBSET_MASK,  TAO_SUBSET_MATRIXFREE)
13a7e14dcfSSatish Balay - maskvalue - the value to set the unused vector elements to (for TAO_SUBSET_MASK or TAO_SUBSET_MATRIXFREE)
14a7e14dcfSSatish Balay 
15a7e14dcfSSatish Balay   Output Parameters:
16a7e14dcfSSatish Balay . vreduced - the subvector
17a7e14dcfSSatish Balay 
181eb8069cSJason Sarich   Notes:
19a7e14dcfSSatish Balay   maskvalue should usually be 0.0, unless a pointwise divide will be used.
201eb8069cSJason Sarich 
21a7e14dcfSSatish Balay @*/
223a831ad5SBarry Smith PetscErrorCode TaoVecGetSubVec(Vec vfull, IS is, TaoSubsetType reduced_type, PetscReal maskvalue, Vec *vreduced)
23a7e14dcfSSatish Balay {
24a7e14dcfSSatish Balay   PetscErrorCode ierr;
25a7e14dcfSSatish Balay   PetscInt       nfull,nreduced,nreduced_local,rlow,rhigh,flow,fhigh;
26a7e14dcfSSatish Balay   PetscInt       i,nlocal;
27a7e14dcfSSatish Balay   PetscReal      *fv,*rv;
28a7e14dcfSSatish Balay   const PetscInt *s;
29a7e14dcfSSatish Balay   IS             ident;
30a7e14dcfSSatish Balay   VecType        vtype;
31a7e14dcfSSatish Balay   VecScatter     scatter;
32a7e14dcfSSatish Balay   MPI_Comm       comm;
33a7e14dcfSSatish Balay 
34a7e14dcfSSatish Balay   PetscFunctionBegin;
35a7e14dcfSSatish Balay   PetscValidHeaderSpecific(vfull,VEC_CLASSID,1);
36a7e14dcfSSatish Balay   PetscValidHeaderSpecific(is,IS_CLASSID,2);
37a7e14dcfSSatish Balay 
38a7e14dcfSSatish Balay   ierr = VecGetSize(vfull, &nfull);CHKERRQ(ierr);
39a7e14dcfSSatish Balay   ierr = ISGetSize(is, &nreduced);CHKERRQ(ierr);
40a7e14dcfSSatish Balay 
41a7e14dcfSSatish Balay   if (nreduced == nfull) {
42a7e14dcfSSatish Balay     ierr = VecDestroy(vreduced);CHKERRQ(ierr);
43a7e14dcfSSatish Balay     ierr = VecDuplicate(vfull,vreduced);CHKERRQ(ierr);
44a7e14dcfSSatish Balay     ierr = VecCopy(vfull,*vreduced);CHKERRQ(ierr);
45a7e14dcfSSatish Balay   } else {
46a7e14dcfSSatish Balay     switch (reduced_type) {
47a7e14dcfSSatish Balay     case TAO_SUBSET_SUBVEC:
48a7e14dcfSSatish Balay       ierr = VecGetType(vfull,&vtype);CHKERRQ(ierr);
49a7e14dcfSSatish Balay       ierr = VecGetOwnershipRange(vfull,&flow,&fhigh);CHKERRQ(ierr);
50a7e14dcfSSatish Balay       ierr = ISGetLocalSize(is,&nreduced_local);CHKERRQ(ierr);
51a7e14dcfSSatish Balay       ierr = PetscObjectGetComm((PetscObject)vfull,&comm);CHKERRQ(ierr);
52a7e14dcfSSatish Balay       if (*vreduced) {
53a7e14dcfSSatish Balay         ierr = VecDestroy(vreduced);CHKERRQ(ierr);
54a7e14dcfSSatish Balay       }
55a7e14dcfSSatish Balay       ierr = VecCreate(comm,vreduced);CHKERRQ(ierr);
56a7e14dcfSSatish Balay       ierr = VecSetType(*vreduced,vtype);CHKERRQ(ierr);
57a7e14dcfSSatish Balay 
58a7e14dcfSSatish Balay       ierr = VecSetSizes(*vreduced,nreduced_local,nreduced);CHKERRQ(ierr);
59a7e14dcfSSatish Balay       ierr = VecGetOwnershipRange(*vreduced,&rlow,&rhigh);CHKERRQ(ierr);
60a7e14dcfSSatish Balay       ierr = ISCreateStride(comm,nreduced_local,rlow,1,&ident);CHKERRQ(ierr);
61a7e14dcfSSatish Balay       ierr = VecScatterCreate(vfull,is,*vreduced,ident,&scatter);CHKERRQ(ierr);
62a7e14dcfSSatish Balay       ierr = VecScatterBegin(scatter,vfull,*vreduced,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
63a7e14dcfSSatish Balay       ierr = VecScatterEnd(scatter,vfull,*vreduced,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
64a7e14dcfSSatish Balay       ierr = VecScatterDestroy(&scatter);CHKERRQ(ierr);
65a7e14dcfSSatish Balay       ierr = ISDestroy(&ident);CHKERRQ(ierr);
66a7e14dcfSSatish Balay       break;
67a7e14dcfSSatish Balay 
68a7e14dcfSSatish Balay     case TAO_SUBSET_MASK:
69a7e14dcfSSatish Balay     case TAO_SUBSET_MATRIXFREE:
70a7e14dcfSSatish Balay       /* vr[i] = vf[i]   if i in is
71a7e14dcfSSatish Balay        vr[i] = 0       otherwise */
726c4ed002SBarry Smith       if (!*vreduced) {
73a7e14dcfSSatish Balay         ierr = VecDuplicate(vfull,vreduced);CHKERRQ(ierr);
74a7e14dcfSSatish Balay       }
75a7e14dcfSSatish Balay 
76a7e14dcfSSatish Balay       ierr = VecSet(*vreduced,maskvalue);CHKERRQ(ierr);
77a7e14dcfSSatish Balay       ierr = ISGetLocalSize(is,&nlocal);CHKERRQ(ierr);
78a7e14dcfSSatish Balay       ierr = VecGetOwnershipRange(vfull,&flow,&fhigh);CHKERRQ(ierr);
79a7e14dcfSSatish Balay       ierr = VecGetArray(vfull,&fv);CHKERRQ(ierr);
80a7e14dcfSSatish Balay       ierr = VecGetArray(*vreduced,&rv);CHKERRQ(ierr);
81a7e14dcfSSatish Balay       ierr = ISGetIndices(is,&s);CHKERRQ(ierr);
8253506e15SBarry Smith       if (nlocal > (fhigh-flow)) SETERRQ2(PETSC_COMM_WORLD,1,"IS local size %d > Vec local size %d",nlocal,fhigh-flow);
83c4b75bccSAlp Dener       for (i=0;i<nlocal;++i) {
84a7e14dcfSSatish Balay         rv[s[i]-flow] = fv[s[i]-flow];
85a7e14dcfSSatish Balay       }
86a7e14dcfSSatish Balay       ierr = ISRestoreIndices(is,&s);CHKERRQ(ierr);
87a7e14dcfSSatish Balay       ierr = VecRestoreArray(vfull,&fv);CHKERRQ(ierr);
88a7e14dcfSSatish Balay       ierr = VecRestoreArray(*vreduced,&rv);CHKERRQ(ierr);
89a7e14dcfSSatish Balay       break;
90a7e14dcfSSatish Balay     }
91a7e14dcfSSatish Balay   }
92a7e14dcfSSatish Balay   PetscFunctionReturn(0);
93a7e14dcfSSatish Balay }
94a7e14dcfSSatish Balay 
95b98f30f2SJason Sarich /*@C
96b98f30f2SJason Sarich   TaoMatGetSubMat - Gets a submatrix using the IS
97a7e14dcfSSatish Balay 
98a7e14dcfSSatish Balay   Input Parameters:
99a7e14dcfSSatish Balay + M - the full matrix (n x n)
100a7e14dcfSSatish Balay . is - the index set for the submatrix (both row and column index sets need to be the same)
101a7e14dcfSSatish Balay . v1 - work vector of dimension n, needed for TAO_SUBSET_MASK option
102a7e14dcfSSatish Balay - subset_type - the method TAO is using for subsetting (TAO_SUBSET_SUBVEC, TAO_SUBSET_MASK,
103a7e14dcfSSatish Balay   TAO_SUBSET_MATRIXFREE)
104a7e14dcfSSatish Balay 
105a7e14dcfSSatish Balay   Output Parameters:
106a7e14dcfSSatish Balay . Msub - the submatrix
107a7e14dcfSSatish Balay @*/
108b98f30f2SJason Sarich PetscErrorCode TaoMatGetSubMat(Mat M, IS is, Vec v1, TaoSubsetType subset_type, Mat *Msub)
109a7e14dcfSSatish Balay {
110a7e14dcfSSatish Balay   PetscErrorCode ierr;
111a7e14dcfSSatish Balay   IS             iscomp;
11262675beeSAlp Dener   PetscBool      flg = PETSC_TRUE;
11353506e15SBarry Smith 
114a7e14dcfSSatish Balay   PetscFunctionBegin;
115a7e14dcfSSatish Balay   PetscValidHeaderSpecific(M,MAT_CLASSID,1);
116a7e14dcfSSatish Balay   PetscValidHeaderSpecific(is,IS_CLASSID,2);
117a7e14dcfSSatish Balay   ierr = MatDestroy(Msub);CHKERRQ(ierr);
118a7e14dcfSSatish Balay   switch (subset_type) {
119a7e14dcfSSatish Balay   case TAO_SUBSET_SUBVEC:
1207dae84e0SHong Zhang     ierr = MatCreateSubMatrix(M, is, is, MAT_INITIAL_MATRIX, Msub);CHKERRQ(ierr);
121a7e14dcfSSatish Balay     break;
122a7e14dcfSSatish Balay 
123a7e14dcfSSatish Balay   case TAO_SUBSET_MASK:
124a7e14dcfSSatish Balay     /* Get Reduced Hessian
125a7e14dcfSSatish Balay      Msub[i,j] = M[i,j] if i,j in Free_Local or i==j
126a7e14dcfSSatish Balay      Msub[i,j] = 0      if i!=j and i or j not in Free_Local
127a7e14dcfSSatish Balay      */
1281a1499c8SBarry Smith     ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)M),NULL,NULL,NULL);CHKERRQ(ierr);
12962675beeSAlp Dener     ierr = PetscOptionsBool("-overwrite_hessian","modify the existing hessian matrix when computing submatrices","TaoSubsetType",flg,&flg,NULL);CHKERRQ(ierr);
130302440fdSBarry Smith     ierr = PetscOptionsEnd();CHKERRQ(ierr);
1318afaa268SBarry Smith     if (flg) {
132a7e14dcfSSatish Balay       ierr = MatDuplicate(M, MAT_COPY_VALUES, Msub);CHKERRQ(ierr);
133a7e14dcfSSatish Balay     } else {
134a7e14dcfSSatish Balay       /* Act on hessian directly (default) */
135a7e14dcfSSatish Balay       ierr = PetscObjectReference((PetscObject)M);CHKERRQ(ierr);
136a7e14dcfSSatish Balay       *Msub = M;
137a7e14dcfSSatish Balay     }
138a7e14dcfSSatish Balay     /* Save the diagonal to temporary vector */
139a7e14dcfSSatish Balay     ierr = MatGetDiagonal(*Msub,v1);CHKERRQ(ierr);
140a7e14dcfSSatish Balay 
141a7e14dcfSSatish Balay     /* Zero out rows and columns */
1424473680cSBarry Smith     ierr = ISComplementVec(is,v1,&iscomp);CHKERRQ(ierr);
143a7e14dcfSSatish Balay 
144a7e14dcfSSatish Balay     /* Use v1 instead of 0 here because of PETSc bug */
145a7e14dcfSSatish Balay     ierr = MatZeroRowsColumnsIS(*Msub,iscomp,1.0,v1,v1);CHKERRQ(ierr);
146a7e14dcfSSatish Balay 
147a7e14dcfSSatish Balay     ierr = ISDestroy(&iscomp);CHKERRQ(ierr);
148a7e14dcfSSatish Balay     break;
149a7e14dcfSSatish Balay   case TAO_SUBSET_MATRIXFREE:
1504473680cSBarry Smith     ierr = ISComplementVec(is,v1,&iscomp);CHKERRQ(ierr);
151a7e14dcfSSatish Balay     ierr = MatCreateSubMatrixFree(M,iscomp,iscomp,Msub);CHKERRQ(ierr);
152a7e14dcfSSatish Balay     ierr = ISDestroy(&iscomp);CHKERRQ(ierr);
153a7e14dcfSSatish Balay     break;
154a7e14dcfSSatish Balay   }
155a7e14dcfSSatish Balay   PetscFunctionReturn(0);
156a7e14dcfSSatish Balay }
1572f75a4aaSAlp Dener 
1582f75a4aaSAlp Dener /*@C
1592f75a4aaSAlp Dener   TaoEstimateActiveBounds - Generates index sets for variables at the lower and upper
1602f75a4aaSAlp Dener   bounds, as well as fixed variables where lower and upper bounds equal each other.
1612f75a4aaSAlp Dener 
1622f75a4aaSAlp Dener   Input Parameters:
1632f75a4aaSAlp Dener + X - solution vector
1642f75a4aaSAlp Dener . XL - lower bound vector
1652f75a4aaSAlp Dener . XU - upper bound vector
1662f75a4aaSAlp Dener . G - unprojected gradient
1670a4511e9SAlp Dener . S - step direction with which the active bounds will be estimated
1680a4511e9SAlp Dener - steplen - the step length at which the active bounds will be estimated (needs to be conservative)
1692f75a4aaSAlp Dener 
1702f75a4aaSAlp Dener   Output Parameters:
1712f75a4aaSAlp Dener . bound_tol - tolerance for for the bound estimation
1722f75a4aaSAlp Dener . active_lower - index set for active variables at the lower bound
1732f75a4aaSAlp Dener . active_upper - index set for active variables at the upper bound
1742f75a4aaSAlp Dener . active_fixed - index set for fixed variables
1752f75a4aaSAlp Dener . active - index set for all active variables
1762f75a4aaSAlp Dener . inactive - complementary index set for inactive variables
1770a4511e9SAlp Dener 
1780a4511e9SAlp Dener   Notes:
1790a4511e9SAlp Dener   This estimation is based on Bertsekas' method, with a built in diagonal scaling value of 1.0e-3.
1800a4511e9SAlp Dener 
1812f75a4aaSAlp Dener @*/
182c4b75bccSAlp Dener PetscErrorCode TaoEstimateActiveBounds(Vec X, Vec XL, Vec XU, Vec G, Vec S, Vec W, PetscReal steplen, PetscReal *bound_tol,
1832f75a4aaSAlp Dener                                        IS *active_lower, IS *active_upper, IS *active_fixed, IS *active, IS *inactive)
1842f75a4aaSAlp Dener {
1852f75a4aaSAlp Dener   PetscErrorCode               ierr;
1862f75a4aaSAlp Dener 
1872f75a4aaSAlp Dener   PetscReal                    wnorm;
18889da521bSAlp Dener   PetscReal                    zero = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
189c4b75bccSAlp Dener   PetscInt                     i, n_isl=0, n_isu=0, n_isf=0, n_isa=0, n_isi=0;
190c4b75bccSAlp Dener   PetscInt                     N_isl, N_isu, N_isf, N_isa, N_isi;
191c4b75bccSAlp Dener   PetscInt                     n, low, high, nDiff;
192c4b75bccSAlp Dener   PetscInt                     *isl=NULL, *isu=NULL, *isf=NULL, *isa=NULL, *isi=NULL;
1932f75a4aaSAlp Dener   const PetscScalar            *xl, *xu, *x, *g;
1942f75a4aaSAlp Dener 
1952f75a4aaSAlp Dener   PetscFunctionBegin;
196c4b75bccSAlp Dener   PetscValidHeaderSpecific(X,VEC_CLASSID,1);
197c4b75bccSAlp Dener   PetscValidHeaderSpecific(XL,VEC_CLASSID,2);
198c4b75bccSAlp Dener   PetscValidHeaderSpecific(XU,VEC_CLASSID,3);
199c4b75bccSAlp Dener   PetscValidHeaderSpecific(G,VEC_CLASSID,4);
200c4b75bccSAlp Dener   PetscValidHeaderSpecific(S,VEC_CLASSID,5);
201c4b75bccSAlp Dener   PetscValidHeaderSpecific(W,VEC_CLASSID,6);
202c4b75bccSAlp Dener 
203c4b75bccSAlp Dener   PetscValidType(X,1);
204c4b75bccSAlp Dener   PetscValidType(XL,2);
205c4b75bccSAlp Dener   PetscValidType(XU,3);
206c4b75bccSAlp Dener   PetscValidType(G,4);
207c4b75bccSAlp Dener   PetscValidType(S,5);
208c4b75bccSAlp Dener   PetscValidType(W,6);
209c4b75bccSAlp Dener   PetscCheckSameType(X,1,XL,2);
210c4b75bccSAlp Dener   PetscCheckSameType(X,1,XU,3);
211c4b75bccSAlp Dener   PetscCheckSameType(X,1,G,4);
212c4b75bccSAlp Dener   PetscCheckSameType(X,1,S,5);
213c4b75bccSAlp Dener   PetscCheckSameType(X,1,W,6);
214c4b75bccSAlp Dener   PetscCheckSameComm(X,1,XL,2);
215c4b75bccSAlp Dener   PetscCheckSameComm(X,1,XU,3);
216c4b75bccSAlp Dener   PetscCheckSameComm(X,1,G,4);
217c4b75bccSAlp Dener   PetscCheckSameComm(X,1,S,5);
218c4b75bccSAlp Dener   PetscCheckSameComm(X,1,W,6);
219c4b75bccSAlp Dener   VecCheckSameSize(X,1,XL,2);
220c4b75bccSAlp Dener   VecCheckSameSize(X,1,XU,3);
221c4b75bccSAlp Dener   VecCheckSameSize(X,1,G,4);
222c4b75bccSAlp Dener   VecCheckSameSize(X,1,S,5);
223c4b75bccSAlp Dener   VecCheckSameSize(X,1,W,6);
224c4b75bccSAlp Dener 
2252f75a4aaSAlp Dener   /* Update the tolerance for bound detection (this is based on Bertsekas' method) */
226c4b75bccSAlp Dener   ierr = VecCopy(X, W);CHKERRQ(ierr);
227c4b75bccSAlp Dener   ierr = VecAXPBY(W, steplen, 1.0, S);CHKERRQ(ierr);
22889da521bSAlp Dener   ierr = TaoBoundSolution(XL, XU, W, 0.0, &nDiff);CHKERRQ(ierr);
2292f75a4aaSAlp Dener   ierr = VecAXPBY(W, 1.0, -1.0, X);CHKERRQ(ierr);
2302f75a4aaSAlp Dener   ierr = VecNorm(W, NORM_2, &wnorm);CHKERRQ(ierr);
2312f75a4aaSAlp Dener   *bound_tol = PetscMin(*bound_tol, wnorm);
2322f75a4aaSAlp Dener 
2332f75a4aaSAlp Dener   ierr = VecGetOwnershipRange(X, &low, &high);CHKERRQ(ierr);
2342f75a4aaSAlp Dener   ierr = VecGetLocalSize(X, &n);CHKERRQ(ierr);
2352f75a4aaSAlp Dener   if (n>0){
2362f75a4aaSAlp Dener     ierr = VecGetArrayRead(X, &x);CHKERRQ(ierr);
2372f75a4aaSAlp Dener     ierr = VecGetArrayRead(XL, &xl);CHKERRQ(ierr);
2382f75a4aaSAlp Dener     ierr = VecGetArrayRead(XU, &xu);CHKERRQ(ierr);
2392f75a4aaSAlp Dener     ierr = VecGetArrayRead(G, &g);CHKERRQ(ierr);
2402f75a4aaSAlp Dener 
2412f75a4aaSAlp Dener     /* Loop over variables and categorize the indexes */
2422f75a4aaSAlp Dener     ierr = PetscMalloc1(n, &isl);CHKERRQ(ierr);
2432f75a4aaSAlp Dener     ierr = PetscMalloc1(n, &isu);CHKERRQ(ierr);
2442f75a4aaSAlp Dener     ierr = PetscMalloc1(n, &isf);CHKERRQ(ierr);
245c4b75bccSAlp Dener     ierr = PetscMalloc1(n, &isa);CHKERRQ(ierr);
246c4b75bccSAlp Dener     ierr = PetscMalloc1(n, &isi);CHKERRQ(ierr);
247c4b75bccSAlp Dener     for (i=0; i<n; ++i) {
24866b4d56fSTodd Munson       if (xl[i] == xu[i]) {
249c4b75bccSAlp Dener         /* Fixed variables */
2502f75a4aaSAlp Dener         isf[n_isf]=low+i; ++n_isf;
251c4b75bccSAlp Dener         isa[n_isa]=low+i; ++n_isa;
25289da521bSAlp Dener       } else if ((xl[i] > PETSC_NINFINITY) && (x[i] <= xl[i] + *bound_tol) && (g[i] > zero)) {
253c4b75bccSAlp Dener         /* Lower bounded variables */
2542f75a4aaSAlp Dener         isl[n_isl]=low+i; ++n_isl;
255c4b75bccSAlp Dener         isa[n_isa]=low+i; ++n_isa;
25689da521bSAlp Dener       } else if ((xu[i] < PETSC_INFINITY) && (x[i] >= xu[i] - *bound_tol) && (g[i] < zero)) {
257c4b75bccSAlp Dener         /* Upper bounded variables */
2582f75a4aaSAlp Dener         isu[n_isu]=low+i; ++n_isu;
259c4b75bccSAlp Dener         isa[n_isa]=low+i; ++n_isa;
260c4b75bccSAlp Dener       } else {
261c4b75bccSAlp Dener         /* Inactive variables */
262c4b75bccSAlp Dener         isi[n_isi]=low+i; ++n_isi;
2632f75a4aaSAlp Dener       }
2642f75a4aaSAlp Dener     }
2652f75a4aaSAlp Dener 
2662f75a4aaSAlp Dener     ierr = VecRestoreArrayRead(X, &x);CHKERRQ(ierr);
2672f75a4aaSAlp Dener     ierr = VecRestoreArrayRead(XL, &xl);CHKERRQ(ierr);
2682f75a4aaSAlp Dener     ierr = VecRestoreArrayRead(XU, &xu);CHKERRQ(ierr);
2692f75a4aaSAlp Dener     ierr = VecRestoreArrayRead(G, &g);CHKERRQ(ierr);
2702f75a4aaSAlp Dener   }
2712f75a4aaSAlp Dener 
272c4b75bccSAlp Dener   /* Clear all index sets */
2732f75a4aaSAlp Dener   ierr = ISDestroy(active_lower);CHKERRQ(ierr);
2742f75a4aaSAlp Dener   ierr = ISDestroy(active_upper);CHKERRQ(ierr);
2752f75a4aaSAlp Dener   ierr = ISDestroy(active_fixed);CHKERRQ(ierr);
2762f75a4aaSAlp Dener   ierr = ISDestroy(active);CHKERRQ(ierr);
2772f75a4aaSAlp Dener   ierr = ISDestroy(inactive);CHKERRQ(ierr);
278c4b75bccSAlp Dener 
279c4b75bccSAlp Dener   /* Collect global sizes */
280c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&n_isl, &N_isl, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
281c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&n_isu, &N_isu, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
282c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&n_isf, &N_isf, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
283c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&n_isa, &N_isa, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
284c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&n_isi, &N_isi, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
285c4b75bccSAlp Dener 
286c4b75bccSAlp Dener   /* Create index set for lower bounded variables */
287c4b75bccSAlp Dener   if (N_isl > 0) {
288c4b75bccSAlp Dener     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)X), n_isl, isl, PETSC_OWN_POINTER, active_lower);CHKERRQ(ierr);
289*7e9273c4SAlp Dener   } else {
290*7e9273c4SAlp Dener     ierr = PetscFree(isl);CHKERRQ(ierr);
291c4b75bccSAlp Dener   }
292c4b75bccSAlp Dener   /* Create index set for upper bounded variables */
293c4b75bccSAlp Dener   if (N_isu > 0) {
294c4b75bccSAlp Dener     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)X), n_isu, isu, PETSC_OWN_POINTER, active_upper);CHKERRQ(ierr);
295*7e9273c4SAlp Dener   } else {
296*7e9273c4SAlp Dener     ierr = PetscFree(isu);CHKERRQ(ierr);
297c4b75bccSAlp Dener   }
298c4b75bccSAlp Dener   /* Create index set for fixed variables */
299c4b75bccSAlp Dener   if (N_isf > 0) {
300c4b75bccSAlp Dener     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)X), n_isf, isf, PETSC_OWN_POINTER, active_fixed);CHKERRQ(ierr);
301*7e9273c4SAlp Dener   } else {
302*7e9273c4SAlp Dener     ierr = PetscFree(isf);CHKERRQ(ierr);
303c4b75bccSAlp Dener   }
304c4b75bccSAlp Dener   /* Create index set for all actively bounded variables */
305c4b75bccSAlp Dener   if (N_isa > 0) {
306c4b75bccSAlp Dener     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)X), n_isa, isa, PETSC_OWN_POINTER, active);CHKERRQ(ierr);
307*7e9273c4SAlp Dener   } else {
308*7e9273c4SAlp Dener     ierr = PetscFree(isa);CHKERRQ(ierr);
309c4b75bccSAlp Dener   }
310c4b75bccSAlp Dener   /* Create index set for all inactive variables */
311c4b75bccSAlp Dener   if (N_isi > 0) {
312c4b75bccSAlp Dener     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)X), n_isi, isi, PETSC_OWN_POINTER, inactive);CHKERRQ(ierr);
313*7e9273c4SAlp Dener   } else {
314*7e9273c4SAlp Dener     ierr = PetscFree(isi);CHKERRQ(ierr);
315c4b75bccSAlp Dener   }
3162f75a4aaSAlp Dener 
3172f75a4aaSAlp Dener   /* Clean up and exit */
3182f75a4aaSAlp Dener   PetscFunctionReturn(0);
3192f75a4aaSAlp Dener }
3202f75a4aaSAlp Dener 
3212f75a4aaSAlp Dener /*@C
3222f75a4aaSAlp Dener   TaoBoundStep - Ensures the correct zero or adjusted step direction
3232f75a4aaSAlp Dener   values for active variables.
3242f75a4aaSAlp Dener 
3252f75a4aaSAlp Dener   Input Parameters:
3262f75a4aaSAlp Dener + X - solution vector
3272f75a4aaSAlp Dener . XL - lower bound vector
3282f75a4aaSAlp Dener . XU - upper bound vector
3292f75a4aaSAlp Dener . active_lower - index set for lower bounded active variables
3302f75a4aaSAlp Dener . active_upper - index set for lower bounded active variables
3312f75a4aaSAlp Dener - active_fixed - index set for fixed active variables
3322f75a4aaSAlp Dener 
3332f75a4aaSAlp Dener   Output Parameters:
3342f75a4aaSAlp Dener . S - step direction to be modified
3352f75a4aaSAlp Dener @*/
336c4b75bccSAlp Dener PetscErrorCode TaoBoundStep(Vec X, Vec XL, Vec XU, IS active_lower, IS active_upper, IS active_fixed, PetscReal scale, Vec S)
3372f75a4aaSAlp Dener {
3382f75a4aaSAlp Dener   PetscErrorCode               ierr;
3392f75a4aaSAlp Dener 
3402f75a4aaSAlp Dener   Vec                          step_lower, step_upper, step_fixed;
3412f75a4aaSAlp Dener   Vec                          x_lower, x_upper;
3422f75a4aaSAlp Dener   Vec                          bound_lower, bound_upper;
3432f75a4aaSAlp Dener 
3442f75a4aaSAlp Dener   PetscFunctionBegin;
3452f75a4aaSAlp Dener   /* Adjust step for variables at the estimated lower bound */
3462f75a4aaSAlp Dener   if (active_lower) {
3472f75a4aaSAlp Dener     ierr = VecGetSubVector(S, active_lower, &step_lower);CHKERRQ(ierr);
3482f75a4aaSAlp Dener     ierr = VecGetSubVector(X, active_lower, &x_lower);CHKERRQ(ierr);
3492f75a4aaSAlp Dener     ierr = VecGetSubVector(XL, active_lower, &bound_lower);CHKERRQ(ierr);
3502f75a4aaSAlp Dener     ierr = VecCopy(bound_lower, step_lower);CHKERRQ(ierr);
3512f75a4aaSAlp Dener     ierr = VecAXPY(step_lower, -1.0, x_lower);CHKERRQ(ierr);
352c4b75bccSAlp Dener     ierr = VecScale(step_lower, scale);CHKERRQ(ierr);
3532f75a4aaSAlp Dener     ierr = VecRestoreSubVector(S, active_lower, &step_lower);CHKERRQ(ierr);
3542f75a4aaSAlp Dener     ierr = VecRestoreSubVector(X, active_lower, &x_lower);CHKERRQ(ierr);
3552f75a4aaSAlp Dener     ierr = VecRestoreSubVector(XL, active_lower, &bound_lower);CHKERRQ(ierr);
3562f75a4aaSAlp Dener   }
3572f75a4aaSAlp Dener 
3582f75a4aaSAlp Dener   /* Adjust step for the variables at the estimated upper bound */
3592f75a4aaSAlp Dener   if (active_upper) {
3602f75a4aaSAlp Dener     ierr = VecGetSubVector(S, active_upper, &step_upper);CHKERRQ(ierr);
3612f75a4aaSAlp Dener     ierr = VecGetSubVector(X, active_upper, &x_upper);CHKERRQ(ierr);
3622f75a4aaSAlp Dener     ierr = VecGetSubVector(XU, active_upper, &bound_upper);CHKERRQ(ierr);
3632f75a4aaSAlp Dener     ierr = VecCopy(bound_upper, step_upper);CHKERRQ(ierr);
3642f75a4aaSAlp Dener     ierr = VecAXPY(step_upper, -1.0, x_upper);CHKERRQ(ierr);
365c4b75bccSAlp Dener     ierr = VecScale(step_upper, scale);CHKERRQ(ierr);
3662f75a4aaSAlp Dener     ierr = VecRestoreSubVector(S, active_upper, &step_upper);CHKERRQ(ierr);
3672f75a4aaSAlp Dener     ierr = VecRestoreSubVector(X, active_upper, &x_upper);CHKERRQ(ierr);
3682f75a4aaSAlp Dener     ierr = VecRestoreSubVector(XU, active_upper, &bound_upper);CHKERRQ(ierr);
3692f75a4aaSAlp Dener   }
3702f75a4aaSAlp Dener 
3712f75a4aaSAlp Dener   /* Zero out step for fixed variables */
3722f75a4aaSAlp Dener   if (active_fixed) {
3732f75a4aaSAlp Dener     ierr = VecGetSubVector(S, active_fixed, &step_fixed);CHKERRQ(ierr);
3742f75a4aaSAlp Dener     ierr = VecSet(step_fixed, 0.0);CHKERRQ(ierr);
3752f75a4aaSAlp Dener     ierr = VecRestoreSubVector(S, active_fixed, &step_fixed);CHKERRQ(ierr);
3762f75a4aaSAlp Dener   }
3772f75a4aaSAlp Dener   PetscFunctionReturn(0);
3782f75a4aaSAlp Dener }
379c4b75bccSAlp Dener 
380c4b75bccSAlp Dener /*@C
381c4b75bccSAlp Dener   TaoBoundSolution - Ensures that the solution vector is snapped into the bounds.
382c4b75bccSAlp Dener 
383c4b75bccSAlp Dener   Input Parameters:
384c4b75bccSAlp Dener + XL - lower bound vector
385c4b75bccSAlp Dener . XU - upper bound vector
386c4b75bccSAlp Dener - X - solution vector
387c4b75bccSAlp Dener 
388c4b75bccSAlp Dener   Output Parameters:
389c4b75bccSAlp Dener . X - modified solution vector
390c4b75bccSAlp Dener @*/
39189da521bSAlp Dener PetscErrorCode TaoBoundSolution(Vec XL, Vec XU, Vec X, PetscReal bound_tol, PetscInt *nDiff)
392c4b75bccSAlp Dener {
393c4b75bccSAlp Dener   PetscErrorCode    ierr;
394c4b75bccSAlp Dener   PetscInt          i,n,low,high,nDiff_loc=0;
395c4b75bccSAlp Dener   PetscScalar       *x;
396c4b75bccSAlp Dener   const PetscScalar *xl,*xu;
397c4b75bccSAlp Dener 
398c4b75bccSAlp Dener   PetscFunctionBegin;
399c4b75bccSAlp Dener   PetscValidHeaderSpecific(X,VEC_CLASSID,1);
400c4b75bccSAlp Dener   PetscValidHeaderSpecific(XL,VEC_CLASSID,2);
401c4b75bccSAlp Dener   PetscValidHeaderSpecific(XU,VEC_CLASSID,3);
402c4b75bccSAlp Dener 
403c4b75bccSAlp Dener   PetscValidType(X,1);
404c4b75bccSAlp Dener   PetscValidType(XL,2);
405c4b75bccSAlp Dener   PetscValidType(XU,3);
406c4b75bccSAlp Dener   PetscCheckSameType(X,1,XL,2);
407c4b75bccSAlp Dener   PetscCheckSameType(X,1,XU,3);
408c4b75bccSAlp Dener   PetscCheckSameComm(X,1,XL,2);
409c4b75bccSAlp Dener   PetscCheckSameComm(X,1,XU,3);
410c4b75bccSAlp Dener   VecCheckSameSize(X,1,XL,2);
411c4b75bccSAlp Dener   VecCheckSameSize(X,1,XU,3);
412c4b75bccSAlp Dener 
413c4b75bccSAlp Dener   ierr = VecGetOwnershipRange(X,&low,&high);CHKERRQ(ierr);
414c4b75bccSAlp Dener   ierr = VecGetLocalSize(X,&n);CHKERRQ(ierr);
415c4b75bccSAlp Dener   if (n>0){
416c4b75bccSAlp Dener     ierr = VecGetArray(X, &x);
417c4b75bccSAlp Dener     ierr = VecGetArrayRead(XL, &xl);
418c4b75bccSAlp Dener     ierr = VecGetArrayRead(XU, &xu);
419c4b75bccSAlp Dener 
420c4b75bccSAlp Dener     for (i=0;i<n;++i){
42189da521bSAlp Dener       if ((xl[i] > PETSC_NINFINITY) && (x[i] <= xl[i] + bound_tol)) {
422c4b75bccSAlp Dener         x[i] = xl[i]; ++nDiff_loc;
42389da521bSAlp Dener       } else if ((xu[i] < PETSC_INFINITY) && (x[i] >= xu[i] - bound_tol)) {
424c4b75bccSAlp Dener         x[i] = xu[i]; ++nDiff_loc;
425c4b75bccSAlp Dener       }
426c4b75bccSAlp Dener     }
427c4b75bccSAlp Dener 
428c4b75bccSAlp Dener     ierr = VecRestoreArray(X, &x);
429c4b75bccSAlp Dener     ierr = VecRestoreArrayRead(XL, &xl);
430c4b75bccSAlp Dener     ierr = VecRestoreArrayRead(XU, &xu);
431c4b75bccSAlp Dener   }
432c4b75bccSAlp Dener   ierr = MPIU_Allreduce(&nDiff_loc, nDiff, 1, MPI_INT, MPI_SUM, PetscObjectComm((PetscObject)X));CHKERRQ(ierr);
433c4b75bccSAlp Dener   PetscFunctionReturn(0);
434c4b75bccSAlp Dener }
435