xref: /petsc/src/tao/constrained/impls/ipm/ipm.c (revision 9566063d113dddea24716c546802770db7481bc0)
1ba92ff59SBarry Smith #include <petsctaolinesearch.h>
2aaa7dc30SBarry Smith #include <../src/tao/constrained/impls/ipm/ipm.h> /*I "ipm.h" I*/
31522df2eSJason Sarich 
4a7e14dcfSSatish Balay /*
5a7e14dcfSSatish Balay    x,d in R^n
6a7e14dcfSSatish Balay    f in R
7a7e14dcfSSatish Balay    nb = mi + nlb+nub
8a7e14dcfSSatish Balay    s in R^nb is slack vector CI(x) / x-XL / -x+XU
9a7e14dcfSSatish Balay    bin in R^mi (tao->constraints_inequality)
10a7e14dcfSSatish Balay    beq in R^me (tao->constraints_equality)
11a7e14dcfSSatish Balay    lamdai in R^nb (ipmP->lamdai)
12a7e14dcfSSatish Balay    lamdae in R^me (ipmP->lamdae)
13a7e14dcfSSatish Balay    Jeq in R^(me x n) (tao->jacobian_equality)
14a7e14dcfSSatish Balay    Jin in R^(mi x n) (tao->jacobian_inequality)
15a7e14dcfSSatish Balay    Ai in  R^(nb x n) (ipmP->Ai)
16a7e14dcfSSatish Balay    H in R^(n x n) (tao->hessian)
17a7e14dcfSSatish Balay    min f=(1/2)*x'*H*x + d'*x
18a7e14dcfSSatish Balay    s.t.  CE(x) == 0
19a7e14dcfSSatish Balay          CI(x) >= 0
20a7e14dcfSSatish Balay          x >= tao->XL
21a7e14dcfSSatish Balay          -x >= -tao->XU
22a7e14dcfSSatish Balay */
23a7e14dcfSSatish Balay 
24441846f8SBarry Smith static PetscErrorCode IPMComputeKKT(Tao tao);
25441846f8SBarry Smith static PetscErrorCode IPMPushInitialPoint(Tao tao);
26441846f8SBarry Smith static PetscErrorCode IPMEvaluate(Tao tao);
27441846f8SBarry Smith static PetscErrorCode IPMUpdateK(Tao tao);
28441846f8SBarry Smith static PetscErrorCode IPMUpdateAi(Tao tao);
29441846f8SBarry Smith static PetscErrorCode IPMGatherRHS(Tao tao,Vec,Vec,Vec,Vec,Vec);
30441846f8SBarry Smith static PetscErrorCode IPMScatterStep(Tao tao,Vec,Vec,Vec,Vec,Vec);
31441846f8SBarry Smith static PetscErrorCode IPMInitializeBounds(Tao tao);
32a7e14dcfSSatish Balay 
33441846f8SBarry Smith static PetscErrorCode TaoSolve_IPM(Tao tao)
34a7e14dcfSSatish Balay {
35a7e14dcfSSatish Balay   TAO_IPM            *ipmP = (TAO_IPM*)tao->data;
368931d482SJason Sarich   PetscInt           its,i;
37a7e14dcfSSatish Balay   PetscScalar        stepsize=1.0;
38a7e14dcfSSatish Balay   PetscScalar        step_s,step_l,alpha,tau,sigma,phi_target;
39a7e14dcfSSatish Balay 
4047a47007SBarry Smith   PetscFunctionBegin;
41a7e14dcfSSatish Balay   /* Push initial point away from bounds */
42*9566063dSJacob Faibussowitsch   PetscCall(IPMInitializeBounds(tao));
43*9566063dSJacob Faibussowitsch   PetscCall(IPMPushInitialPoint(tao));
44*9566063dSJacob Faibussowitsch   PetscCall(VecCopy(tao->solution,ipmP->rhs_x));
45*9566063dSJacob Faibussowitsch   PetscCall(IPMEvaluate(tao));
46*9566063dSJacob Faibussowitsch   PetscCall(IPMComputeKKT(tao));
47a7e14dcfSSatish Balay 
48763847b4SAlp Dener   tao->reason = TAO_CONTINUE_ITERATING;
49*9566063dSJacob Faibussowitsch   PetscCall(TaoLogConvergenceHistory(tao,ipmP->kkt_f,ipmP->phi,0.0,tao->ksp_its));
50*9566063dSJacob Faibussowitsch   PetscCall(TaoMonitor(tao,tao->niter,ipmP->kkt_f,ipmP->phi,0.0,1.0));
51*9566063dSJacob Faibussowitsch   PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
52763847b4SAlp Dener 
53763847b4SAlp Dener   while (tao->reason == TAO_CONTINUE_ITERATING) {
54e1e80dc8SAlp Dener     /* Call general purpose update function */
55e1e80dc8SAlp Dener     if (tao->ops->update) {
56*9566063dSJacob Faibussowitsch       PetscCall((*tao->ops->update)(tao, tao->niter, tao->user_update));
57e1e80dc8SAlp Dener     }
58e1e80dc8SAlp Dener 
59b0026674SJason Sarich     tao->ksp_its=0;
60*9566063dSJacob Faibussowitsch     PetscCall(IPMUpdateK(tao));
61a7e14dcfSSatish Balay     /*
62a7e14dcfSSatish Balay        rhs.x    = -rd
63a7e14dcfSSatish Balay        rhs.lame = -rpe
64a7e14dcfSSatish Balay        rhs.lami = -rpi
65a7e14dcfSSatish Balay        rhs.com  = -com
66a7e14dcfSSatish Balay     */
67a7e14dcfSSatish Balay 
68*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(ipmP->rd,ipmP->rhs_x));
69a7e14dcfSSatish Balay     if (ipmP->me > 0) {
70*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->rpe,ipmP->rhs_lamdae));
71a7e14dcfSSatish Balay     }
72a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
73*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->rpi,ipmP->rhs_lamdai));
74*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->complementarity,ipmP->rhs_s));
75a7e14dcfSSatish Balay     }
76*9566063dSJacob Faibussowitsch     PetscCall(IPMGatherRHS(tao,ipmP->bigrhs,ipmP->rhs_x,ipmP->rhs_lamdae,ipmP->rhs_lamdai,ipmP->rhs_s));
77*9566063dSJacob Faibussowitsch     PetscCall(VecScale(ipmP->bigrhs,-1.0));
78a7e14dcfSSatish Balay 
79a7e14dcfSSatish Balay     /* solve K * step = rhs */
80*9566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(tao->ksp,ipmP->K,ipmP->K));
81*9566063dSJacob Faibussowitsch     PetscCall(KSPSolve(tao->ksp,ipmP->bigrhs,ipmP->bigstep));
82a7e14dcfSSatish Balay 
83*9566063dSJacob Faibussowitsch     PetscCall(IPMScatterStep(tao,ipmP->bigstep,tao->stepdirection,ipmP->ds,ipmP->dlamdae,ipmP->dlamdai));
84*9566063dSJacob Faibussowitsch     PetscCall(KSPGetIterationNumber(tao->ksp,&its));
85a7e14dcfSSatish Balay     tao->ksp_its += its;
86b0026674SJason Sarich     tao->ksp_tot_its+=its;
87a7e14dcfSSatish Balay      /* Find distance along step direction to closest bound */
88a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
89*9566063dSJacob Faibussowitsch       PetscCall(VecStepBoundInfo(ipmP->s,ipmP->ds,ipmP->Zero_nb,ipmP->Inf_nb,&step_s,NULL,NULL));
90*9566063dSJacob Faibussowitsch       PetscCall(VecStepBoundInfo(ipmP->lamdai,ipmP->dlamdai,ipmP->Zero_nb,ipmP->Inf_nb,&step_l,NULL,NULL));
91a7e14dcfSSatish Balay       alpha = PetscMin(step_s,step_l);
92a7e14dcfSSatish Balay       alpha = PetscMin(alpha,1.0);
93a7e14dcfSSatish Balay       ipmP->alpha1 = alpha;
94a7e14dcfSSatish Balay     } else {
95a7e14dcfSSatish Balay       ipmP->alpha1 = alpha = 1.0;
96a7e14dcfSSatish Balay     }
97a7e14dcfSSatish Balay 
98a7e14dcfSSatish Balay     /* x_aff = x + alpha*d */
99*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(tao->solution,ipmP->save_x));
100a7e14dcfSSatish Balay     if (ipmP->me > 0) {
101*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->lamdae,ipmP->save_lamdae));
102a7e14dcfSSatish Balay     }
103a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
104*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->lamdai,ipmP->save_lamdai));
105*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->s,ipmP->save_s));
106a7e14dcfSSatish Balay     }
107a7e14dcfSSatish Balay 
108*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(tao->solution,alpha,tao->stepdirection));
109a7e14dcfSSatish Balay     if (ipmP->me > 0) {
110*9566063dSJacob Faibussowitsch       PetscCall(VecAXPY(ipmP->lamdae,alpha,ipmP->dlamdae));
111a7e14dcfSSatish Balay     }
112a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
113*9566063dSJacob Faibussowitsch       PetscCall(VecAXPY(ipmP->lamdai,alpha,ipmP->dlamdai));
114*9566063dSJacob Faibussowitsch       PetscCall(VecAXPY(ipmP->s,alpha,ipmP->ds));
115a7e14dcfSSatish Balay     }
116a7e14dcfSSatish Balay 
117a7e14dcfSSatish Balay     /* Recompute kkt to find centering parameter sigma = (new_mu/old_mu)^3 */
118a7e14dcfSSatish Balay     if (ipmP->mu == 0.0) {
119a7e14dcfSSatish Balay       sigma = 0.0;
120a7e14dcfSSatish Balay     } else {
121a7e14dcfSSatish Balay       sigma = 1.0/ipmP->mu;
122a7e14dcfSSatish Balay     }
123*9566063dSJacob Faibussowitsch     PetscCall(IPMComputeKKT(tao));
124a7e14dcfSSatish Balay     sigma *= ipmP->mu;
125a7e14dcfSSatish Balay     sigma*=sigma*sigma;
126a7e14dcfSSatish Balay 
127a7e14dcfSSatish Balay     /* revert kkt info */
128*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(ipmP->save_x,tao->solution));
129a7e14dcfSSatish Balay     if (ipmP->me > 0) {
130*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->save_lamdae,ipmP->lamdae));
131a7e14dcfSSatish Balay     }
132a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
133*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->save_lamdai,ipmP->lamdai));
134*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->save_s,ipmP->s));
135a7e14dcfSSatish Balay     }
136*9566063dSJacob Faibussowitsch     PetscCall(IPMComputeKKT(tao));
137a7e14dcfSSatish Balay 
138a7e14dcfSSatish Balay     /* update rhs with new complementarity vector */
139a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
140*9566063dSJacob Faibussowitsch       PetscCall(VecCopy(ipmP->complementarity,ipmP->rhs_s));
141*9566063dSJacob Faibussowitsch       PetscCall(VecScale(ipmP->rhs_s,-1.0));
142*9566063dSJacob Faibussowitsch       PetscCall(VecShift(ipmP->rhs_s,sigma*ipmP->mu));
143a7e14dcfSSatish Balay     }
144*9566063dSJacob Faibussowitsch     PetscCall(IPMGatherRHS(tao,ipmP->bigrhs,NULL,NULL,NULL,ipmP->rhs_s));
145a7e14dcfSSatish Balay 
146a7e14dcfSSatish Balay     /* solve K * step = rhs */
147*9566063dSJacob Faibussowitsch     PetscCall(KSPSetOperators(tao->ksp,ipmP->K,ipmP->K));
148*9566063dSJacob Faibussowitsch     PetscCall(KSPSolve(tao->ksp,ipmP->bigrhs,ipmP->bigstep));
149a7e14dcfSSatish Balay 
150*9566063dSJacob Faibussowitsch     PetscCall(IPMScatterStep(tao,ipmP->bigstep,tao->stepdirection,ipmP->ds,ipmP->dlamdae,ipmP->dlamdai));
151*9566063dSJacob Faibussowitsch     PetscCall(KSPGetIterationNumber(tao->ksp,&its));
152a7e14dcfSSatish Balay     tao->ksp_its += its;
153b0026674SJason Sarich     tao->ksp_tot_its+=its;
154a7e14dcfSSatish Balay     if (ipmP->nb > 0) {
155a7e14dcfSSatish Balay       /* Get max step size and apply frac-to-boundary */
156a7e14dcfSSatish Balay       tau = PetscMax(ipmP->taumin,1.0-ipmP->mu);
157a7e14dcfSSatish Balay       tau = PetscMin(tau,1.0);
158a7e14dcfSSatish Balay       if (tau != 1.0) {
159*9566063dSJacob Faibussowitsch         PetscCall(VecScale(ipmP->s,tau));
160*9566063dSJacob Faibussowitsch         PetscCall(VecScale(ipmP->lamdai,tau));
161a7e14dcfSSatish Balay       }
162*9566063dSJacob Faibussowitsch       PetscCall(VecStepBoundInfo(ipmP->s,ipmP->ds,ipmP->Zero_nb,ipmP->Inf_nb,&step_s,NULL,NULL));
163*9566063dSJacob Faibussowitsch       PetscCall(VecStepBoundInfo(ipmP->lamdai,ipmP->dlamdai,ipmP->Zero_nb,ipmP->Inf_nb,&step_l,NULL,NULL));
164a7e14dcfSSatish Balay       if (tau != 1.0) {
165*9566063dSJacob Faibussowitsch         PetscCall(VecCopy(ipmP->save_s,ipmP->s));
166*9566063dSJacob Faibussowitsch         PetscCall(VecCopy(ipmP->save_lamdai,ipmP->lamdai));
167a7e14dcfSSatish Balay       }
168a7e14dcfSSatish Balay       alpha = PetscMin(step_s,step_l);
169a7e14dcfSSatish Balay       alpha = PetscMin(alpha,1.0);
170a7e14dcfSSatish Balay     } else {
171a7e14dcfSSatish Balay       alpha = 1.0;
172a7e14dcfSSatish Balay     }
173a7e14dcfSSatish Balay     ipmP->alpha2 = alpha;
174a7e14dcfSSatish Balay     /* TODO make phi_target meaningful */
175a7e14dcfSSatish Balay     phi_target = ipmP->dec * ipmP->phi;
176a7e14dcfSSatish Balay     for (i=0; i<11;i++) {
177*9566063dSJacob Faibussowitsch       PetscCall(VecAXPY(tao->solution,alpha,tao->stepdirection));
178a7e14dcfSSatish Balay       if (ipmP->nb > 0) {
179*9566063dSJacob Faibussowitsch         PetscCall(VecAXPY(ipmP->s,alpha,ipmP->ds));
180*9566063dSJacob Faibussowitsch         PetscCall(VecAXPY(ipmP->lamdai,alpha,ipmP->dlamdai));
181a7e14dcfSSatish Balay       }
182a7e14dcfSSatish Balay       if (ipmP->me > 0) {
183*9566063dSJacob Faibussowitsch         PetscCall(VecAXPY(ipmP->lamdae,alpha,ipmP->dlamdae));
184a7e14dcfSSatish Balay       }
185a7e14dcfSSatish Balay 
186a7e14dcfSSatish Balay       /* update dual variables */
187a7e14dcfSSatish Balay       if (ipmP->me > 0) {
188*9566063dSJacob Faibussowitsch         PetscCall(VecCopy(ipmP->lamdae,tao->DE));
189a7e14dcfSSatish Balay       }
190a7e14dcfSSatish Balay 
191*9566063dSJacob Faibussowitsch       PetscCall(IPMEvaluate(tao));
192*9566063dSJacob Faibussowitsch       PetscCall(IPMComputeKKT(tao));
193a7e14dcfSSatish Balay       if (ipmP->phi <= phi_target) break;
194a7e14dcfSSatish Balay       alpha /= 2.0;
195a7e14dcfSSatish Balay     }
196a7e14dcfSSatish Balay 
197*9566063dSJacob Faibussowitsch     PetscCall(TaoLogConvergenceHistory(tao,ipmP->kkt_f,ipmP->phi,0.0,tao->ksp_its));
198*9566063dSJacob Faibussowitsch     PetscCall(TaoMonitor(tao,tao->niter,ipmP->kkt_f,ipmP->phi,0.0,stepsize));
199*9566063dSJacob Faibussowitsch     PetscCall((*tao->ops->convergencetest)(tao,tao->cnvP));
2008931d482SJason Sarich     tao->niter++;
201a7e14dcfSSatish Balay   }
202a7e14dcfSSatish Balay   PetscFunctionReturn(0);
203a7e14dcfSSatish Balay }
204a7e14dcfSSatish Balay 
205441846f8SBarry Smith static PetscErrorCode TaoSetup_IPM(Tao tao)
206a7e14dcfSSatish Balay {
207a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM*)tao->data;
208a7e14dcfSSatish Balay 
209a7e14dcfSSatish Balay   PetscFunctionBegin;
210a7e14dcfSSatish Balay   ipmP->nb = ipmP->mi = ipmP->me = 0;
21183c8fe1dSLisandro Dalcin   ipmP->K = NULL;
212*9566063dSJacob Faibussowitsch   PetscCall(VecGetSize(tao->solution,&ipmP->n));
213a7e14dcfSSatish Balay   if (!tao->gradient) {
214*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &tao->gradient));
215*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &tao->stepdirection));
216*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &ipmP->rd));
217*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &ipmP->rhs_x));
218*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &ipmP->work));
219*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->solution, &ipmP->save_x));
220a7e14dcfSSatish Balay   }
221a7e14dcfSSatish Balay   if (tao->constraints_equality) {
222*9566063dSJacob Faibussowitsch     PetscCall(VecGetSize(tao->constraints_equality,&ipmP->me));
223*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&ipmP->lamdae));
224*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&ipmP->dlamdae));
225*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&ipmP->rhs_lamdae));
226*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&ipmP->save_lamdae));
227*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&ipmP->rpe));
228*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_equality,&tao->DE));
229a7e14dcfSSatish Balay   }
230a7e14dcfSSatish Balay   if (tao->constraints_inequality) {
231*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(tao->constraints_inequality,&tao->DI));
232a7e14dcfSSatish Balay   }
233a7e14dcfSSatish Balay   PetscFunctionReturn(0);
234a7e14dcfSSatish Balay }
235a7e14dcfSSatish Balay 
236441846f8SBarry Smith static PetscErrorCode IPMInitializeBounds(Tao tao)
237a7e14dcfSSatish Balay {
238a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM*)tao->data;
239a7e14dcfSSatish Balay   Vec            xtmp;
240a7e14dcfSSatish Balay   PetscInt       xstart,xend;
241a7e14dcfSSatish Balay   PetscInt       ucstart,ucend; /* user ci */
242a7e14dcfSSatish Balay   PetscInt       ucestart,uceend; /* user ce */
243b99af1fdSBarry Smith   PetscInt       sstart = 0 ,send = 0;
244a7e14dcfSSatish Balay   PetscInt       bigsize;
245a7e14dcfSSatish Balay   PetscInt       i,counter,nloc;
246a7e14dcfSSatish Balay   PetscInt       *cind,*xind,*ucind,*uceind,*stepind;
247a7e14dcfSSatish Balay   VecType        vtype;
248a7e14dcfSSatish Balay   const PetscInt *xli,*xui;
249a7e14dcfSSatish Balay   PetscInt       xl_offset,xu_offset;
250a7e14dcfSSatish Balay   IS             bigxl,bigxu,isuc,isc,isx,sis,is1;
251a7e14dcfSSatish Balay   MPI_Comm       comm;
25247a47007SBarry Smith 
253a7e14dcfSSatish Balay   PetscFunctionBegin;
25483c8fe1dSLisandro Dalcin   cind=xind=ucind=uceind=stepind=NULL;
255a7e14dcfSSatish Balay   ipmP->mi=0;
256a7e14dcfSSatish Balay   ipmP->nxlb=0;
257a7e14dcfSSatish Balay   ipmP->nxub=0;
258a7e14dcfSSatish Balay   ipmP->nb=0;
259a7e14dcfSSatish Balay   ipmP->nslack=0;
260a7e14dcfSSatish Balay 
261*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(tao->solution,&xtmp));
262a7e14dcfSSatish Balay   if (!tao->XL && !tao->XU && tao->ops->computebounds) {
263*9566063dSJacob Faibussowitsch     PetscCall(TaoComputeVariableBounds(tao));
264a7e14dcfSSatish Balay   }
265a7e14dcfSSatish Balay   if (tao->XL) {
266*9566063dSJacob Faibussowitsch     PetscCall(VecSet(xtmp,PETSC_NINFINITY));
267*9566063dSJacob Faibussowitsch     PetscCall(VecWhichGreaterThan(tao->XL,xtmp,&ipmP->isxl));
268*9566063dSJacob Faibussowitsch     PetscCall(ISGetSize(ipmP->isxl,&ipmP->nxlb));
269a7e14dcfSSatish Balay   } else {
270a7e14dcfSSatish Balay     ipmP->nxlb=0;
271a7e14dcfSSatish Balay   }
272a7e14dcfSSatish Balay   if (tao->XU) {
273*9566063dSJacob Faibussowitsch     PetscCall(VecSet(xtmp,PETSC_INFINITY));
274*9566063dSJacob Faibussowitsch     PetscCall(VecWhichLessThan(tao->XU,xtmp,&ipmP->isxu));
275*9566063dSJacob Faibussowitsch     PetscCall(ISGetSize(ipmP->isxu,&ipmP->nxub));
276a7e14dcfSSatish Balay   } else {
277a7e14dcfSSatish Balay     ipmP->nxub=0;
278a7e14dcfSSatish Balay   }
279*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&xtmp));
280a7e14dcfSSatish Balay   if (tao->constraints_inequality) {
281*9566063dSJacob Faibussowitsch     PetscCall(VecGetSize(tao->constraints_inequality,&ipmP->mi));
282a7e14dcfSSatish Balay   } else {
283a7e14dcfSSatish Balay     ipmP->mi = 0;
284a7e14dcfSSatish Balay   }
285a7e14dcfSSatish Balay   ipmP->nb = ipmP->nxlb + ipmP->nxub + ipmP->mi;
286a7e14dcfSSatish Balay 
287*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)tao->solution,&comm));
288a7e14dcfSSatish Balay 
289a7e14dcfSSatish Balay   bigsize = ipmP->n+2*ipmP->nb+ipmP->me;
290*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bigsize,&stepind));
291*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ipmP->n,&xind));
292*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ipmP->me,&uceind));
293*9566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(tao->solution,&xstart,&xend));
294a7e14dcfSSatish Balay 
295a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
296*9566063dSJacob Faibussowitsch     PetscCall(VecCreate(comm,&ipmP->s));
297*9566063dSJacob Faibussowitsch     PetscCall(VecSetSizes(ipmP->s,PETSC_DECIDE,ipmP->nb));
298*9566063dSJacob Faibussowitsch     PetscCall(VecSetFromOptions(ipmP->s));
299*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->ds));
300*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->rhs_s));
301*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->complementarity));
302*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->ci));
303a7e14dcfSSatish Balay 
304*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->lamdai));
305*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->dlamdai));
306*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->rhs_lamdai));
307*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->save_lamdai));
308a7e14dcfSSatish Balay 
309*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->save_s));
310*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->rpi));
311*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->Zero_nb));
312*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->Zero_nb,0.0));
313*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->One_nb));
314*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->One_nb,1.0));
315*9566063dSJacob Faibussowitsch     PetscCall(VecDuplicate(ipmP->s,&ipmP->Inf_nb));
316*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->Inf_nb,PETSC_INFINITY));
317a7e14dcfSSatish Balay 
318*9566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ipmP->nb,&cind));
319*9566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(ipmP->mi,&ucind));
320*9566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(ipmP->s,&sstart,&send));
321a7e14dcfSSatish Balay 
322a7e14dcfSSatish Balay     if (ipmP->mi > 0) {
323*9566063dSJacob Faibussowitsch       PetscCall(VecGetOwnershipRange(tao->constraints_inequality,&ucstart,&ucend));
324a7e14dcfSSatish Balay       counter=0;
325a7e14dcfSSatish Balay       for (i=ucstart;i<ucend;i++) {
326a7e14dcfSSatish Balay         cind[counter++] = i;
327a7e14dcfSSatish Balay       }
328*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,counter,cind,PETSC_COPY_VALUES,&isuc));
329*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,counter,cind,PETSC_COPY_VALUES,&isc));
330*9566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(tao->constraints_inequality,isuc,ipmP->ci,isc,&ipmP->ci_scat));
331a7e14dcfSSatish Balay 
332*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isuc));
333*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isc));
334a7e14dcfSSatish Balay     }
335a7e14dcfSSatish Balay     /* need to know how may xbound indices are on each process */
336a7e14dcfSSatish Balay     /* TODO better way */
337a7e14dcfSSatish Balay     if (ipmP->nxlb) {
338*9566063dSJacob Faibussowitsch       PetscCall(ISAllGather(ipmP->isxl,&bigxl));
339*9566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(bigxl,&xli));
340a7e14dcfSSatish Balay       /* find offsets for this processor */
341a7e14dcfSSatish Balay       xl_offset = ipmP->mi;
342a7e14dcfSSatish Balay       for (i=0;i<ipmP->nxlb;i++) {
343a7e14dcfSSatish Balay         if (xli[i] < xstart) {
344a7e14dcfSSatish Balay           xl_offset++;
345a7e14dcfSSatish Balay         } else break;
346a7e14dcfSSatish Balay       }
347*9566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(bigxl,&xli));
348a7e14dcfSSatish Balay 
349*9566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ipmP->isxl,&xli));
350*9566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ipmP->isxl,&nloc));
351a7e14dcfSSatish Balay       for (i=0;i<nloc;i++) {
352a7e14dcfSSatish Balay         xind[i] = xli[i];
353a7e14dcfSSatish Balay         cind[i] = xl_offset+i;
354a7e14dcfSSatish Balay       }
355a7e14dcfSSatish Balay 
356*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,nloc,xind,PETSC_COPY_VALUES,&isx));
357*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,nloc,cind,PETSC_COPY_VALUES,&isc));
358*9566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(tao->XL,isx,ipmP->ci,isc,&ipmP->xl_scat));
359*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isx));
360*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isc));
361*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&bigxl));
362a7e14dcfSSatish Balay     }
363a7e14dcfSSatish Balay 
364a7e14dcfSSatish Balay     if (ipmP->nxub) {
365*9566063dSJacob Faibussowitsch       PetscCall(ISAllGather(ipmP->isxu,&bigxu));
366*9566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(bigxu,&xui));
367a7e14dcfSSatish Balay       /* find offsets for this processor */
368a7e14dcfSSatish Balay       xu_offset = ipmP->mi + ipmP->nxlb;
369a7e14dcfSSatish Balay       for (i=0;i<ipmP->nxub;i++) {
370a7e14dcfSSatish Balay         if (xui[i] < xstart) {
371a7e14dcfSSatish Balay           xu_offset++;
372a7e14dcfSSatish Balay         } else break;
373a7e14dcfSSatish Balay       }
374*9566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(bigxu,&xui));
375a7e14dcfSSatish Balay 
376*9566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(ipmP->isxu,&xui));
377*9566063dSJacob Faibussowitsch       PetscCall(ISGetLocalSize(ipmP->isxu,&nloc));
378a7e14dcfSSatish Balay       for (i=0;i<nloc;i++) {
379a7e14dcfSSatish Balay         xind[i] = xui[i];
380a7e14dcfSSatish Balay         cind[i] = xu_offset+i;
381a7e14dcfSSatish Balay       }
382a7e14dcfSSatish Balay 
383*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,nloc,xind,PETSC_COPY_VALUES,&isx));
384*9566063dSJacob Faibussowitsch       PetscCall(ISCreateGeneral(comm,nloc,cind,PETSC_COPY_VALUES,&isc));
385*9566063dSJacob Faibussowitsch       PetscCall(VecScatterCreate(tao->XU,isx,ipmP->ci,isc,&ipmP->xu_scat));
386*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isx));
387*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&isc));
388*9566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&bigxu));
389a7e14dcfSSatish Balay     }
390a7e14dcfSSatish Balay   }
391*9566063dSJacob Faibussowitsch   PetscCall(VecCreate(comm,&ipmP->bigrhs));
392*9566063dSJacob Faibussowitsch   PetscCall(VecGetType(tao->solution,&vtype));
393*9566063dSJacob Faibussowitsch   PetscCall(VecSetType(ipmP->bigrhs,vtype));
394*9566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(ipmP->bigrhs,PETSC_DECIDE,bigsize));
395*9566063dSJacob Faibussowitsch   PetscCall(VecSetFromOptions(ipmP->bigrhs));
396*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(ipmP->bigrhs,&ipmP->bigstep));
397a7e14dcfSSatish Balay 
398a7e14dcfSSatish Balay   /* create scatters for step->x and x->rhs */
399a7e14dcfSSatish Balay   for (i=xstart;i<xend;i++) {
400a7e14dcfSSatish Balay     stepind[i-xstart] = i;
401a7e14dcfSSatish Balay     xind[i-xstart] = i;
402a7e14dcfSSatish Balay   }
403*9566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm,xend-xstart,stepind,PETSC_COPY_VALUES,&sis));
404*9566063dSJacob Faibussowitsch   PetscCall(ISCreateGeneral(comm,xend-xstart,xind,PETSC_COPY_VALUES,&is1));
405*9566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(ipmP->bigstep,sis,tao->solution,is1,&ipmP->step1));
406*9566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(tao->solution,is1,ipmP->bigrhs,sis,&ipmP->rhs1));
407*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&sis));
408*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&is1));
409a7e14dcfSSatish Balay 
410a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
411a7e14dcfSSatish Balay     for (i=sstart;i<send;i++) {
412a7e14dcfSSatish Balay       stepind[i-sstart] = i+ipmP->n;
413a7e14dcfSSatish Balay       cind[i-sstart] = i;
414a7e14dcfSSatish Balay     }
415*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis));
416*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,send-sstart,cind,PETSC_COPY_VALUES,&is1));
417*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(ipmP->bigstep,sis,ipmP->s,is1,&ipmP->step2));
418*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&sis));
419a7e14dcfSSatish Balay 
420a7e14dcfSSatish Balay     for (i=sstart;i<send;i++) {
421a7e14dcfSSatish Balay       stepind[i-sstart] = i+ipmP->n+ipmP->me;
422a7e14dcfSSatish Balay       cind[i-sstart] = i;
423a7e14dcfSSatish Balay     }
424*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis));
425*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(ipmP->s,is1,ipmP->bigrhs,sis,&ipmP->rhs3));
426*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&sis));
427*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
428a7e14dcfSSatish Balay   }
429a7e14dcfSSatish Balay 
430a7e14dcfSSatish Balay   if (ipmP->me > 0) {
431*9566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(tao->constraints_equality,&ucestart,&uceend));
432a7e14dcfSSatish Balay     for (i=ucestart;i<uceend;i++) {
433a7e14dcfSSatish Balay       stepind[i-ucestart] = i + ipmP->n+ipmP->nb;
434a7e14dcfSSatish Balay       uceind[i-ucestart] = i;
435a7e14dcfSSatish Balay     }
436a7e14dcfSSatish Balay 
437*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,uceend-ucestart,stepind,PETSC_COPY_VALUES,&sis));
438*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,uceend-ucestart,uceind,PETSC_COPY_VALUES,&is1));
439*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(ipmP->bigstep,sis,tao->constraints_equality,is1,&ipmP->step3));
440*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&sis));
441a7e14dcfSSatish Balay 
442a7e14dcfSSatish Balay     for (i=ucestart;i<uceend;i++) {
443a7e14dcfSSatish Balay       stepind[i-ucestart] = i + ipmP->n;
444a7e14dcfSSatish Balay     }
445a7e14dcfSSatish Balay 
446*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,uceend-ucestart,stepind,PETSC_COPY_VALUES,&sis));
447*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(tao->constraints_equality,is1,ipmP->bigrhs,sis,&ipmP->rhs2));
448*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&sis));
449*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
450a7e14dcfSSatish Balay   }
451a7e14dcfSSatish Balay 
452a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
453a7e14dcfSSatish Balay     for (i=sstart;i<send;i++) {
454a7e14dcfSSatish Balay       stepind[i-sstart] = i + ipmP->n + ipmP->nb + ipmP->me;
455a7e14dcfSSatish Balay       cind[i-sstart] = i;
456a7e14dcfSSatish Balay     }
457*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,send-sstart,cind,PETSC_COPY_VALUES,&is1));
458*9566063dSJacob Faibussowitsch     PetscCall(ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis));
459*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(ipmP->bigstep,sis,ipmP->s,is1,&ipmP->step4));
460*9566063dSJacob Faibussowitsch     PetscCall(VecScatterCreate(ipmP->s,is1,ipmP->bigrhs,sis,&ipmP->rhs4));
461*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&sis));
462*9566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&is1));
463a7e14dcfSSatish Balay   }
464a7e14dcfSSatish Balay 
465*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(stepind));
466*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(cind));
467*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(ucind));
468*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(uceind));
469*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(xind));
470a7e14dcfSSatish Balay   PetscFunctionReturn(0);
471a7e14dcfSSatish Balay }
472a7e14dcfSSatish Balay 
473441846f8SBarry Smith static PetscErrorCode TaoDestroy_IPM(Tao tao)
474a7e14dcfSSatish Balay {
475a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM*)tao->data;
47647a47007SBarry Smith 
477a7e14dcfSSatish Balay   PetscFunctionBegin;
478*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rd));
479*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rpe));
480*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rpi));
481*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->work));
482*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->lamdae));
483*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->lamdai));
484*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->s));
485*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->ds));
486*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->ci));
487a7e14dcfSSatish Balay 
488*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rhs_x));
489*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rhs_lamdae));
490*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rhs_lamdai));
491*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->rhs_s));
492a7e14dcfSSatish Balay 
493*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->save_x));
494*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->save_lamdae));
495*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->save_lamdai));
496*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->save_s));
497a7e14dcfSSatish Balay 
498*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->step1));
499*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->step2));
500*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->step3));
501*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->step4));
502a7e14dcfSSatish Balay 
503*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->rhs1));
504*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->rhs2));
505*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->rhs3));
506*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->rhs4));
507a7e14dcfSSatish Balay 
508*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->ci_scat));
509*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->xl_scat));
510*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&ipmP->xu_scat));
511a7e14dcfSSatish Balay 
512*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->dlamdai));
513*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->dlamdae));
514*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->Zero_nb));
515*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->One_nb));
516*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->Inf_nb));
517*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->complementarity));
518a7e14dcfSSatish Balay 
519*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->bigrhs));
520*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&ipmP->bigstep));
521*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ipmP->Ai));
522*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&ipmP->K));
523*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ipmP->isxu));
524*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&ipmP->isxl));
525*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(tao->data));
526a7e14dcfSSatish Balay   PetscFunctionReturn(0);
527a7e14dcfSSatish Balay }
528a7e14dcfSSatish Balay 
5294416b707SBarry Smith static PetscErrorCode TaoSetFromOptions_IPM(PetscOptionItems *PetscOptionsObject,Tao tao)
530a7e14dcfSSatish Balay {
531a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM*)tao->data;
53247a47007SBarry Smith 
533a7e14dcfSSatish Balay   PetscFunctionBegin;
534*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsHead(PetscOptionsObject,"IPM method for constrained optimization"));
535*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsBool("-tao_ipm_monitorkkt","monitor kkt status",NULL,ipmP->monitorkkt,&ipmP->monitorkkt,NULL));
536*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_ipm_pushs","parameter to push initial slack variables away from bounds",NULL,ipmP->pushs,&ipmP->pushs,NULL));
537*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-tao_ipm_pushnu","parameter to push initial (inequality) dual variables away from bounds",NULL,ipmP->pushnu,&ipmP->pushnu,NULL));
538*9566063dSJacob Faibussowitsch   PetscCall(PetscOptionsTail());
539*9566063dSJacob Faibussowitsch   PetscCall(KSPSetFromOptions(tao->ksp));
540a7e14dcfSSatish Balay   PetscFunctionReturn(0);
541a7e14dcfSSatish Balay }
542a7e14dcfSSatish Balay 
543441846f8SBarry Smith static PetscErrorCode TaoView_IPM(Tao tao, PetscViewer viewer)
544a7e14dcfSSatish Balay {
545a7e14dcfSSatish Balay   return 0;
546a7e14dcfSSatish Balay }
547a7e14dcfSSatish Balay 
548a7e14dcfSSatish Balay /* IPMObjectiveAndGradient()
549a7e14dcfSSatish Balay    f = d'x + 0.5 * x' * H * x
550a7e14dcfSSatish Balay    rd = H*x + d + Ae'*lame - Ai'*lami
551a7e14dcfSSatish Balay    rpe = Ae*x - be
552a7e14dcfSSatish Balay    rpi = Ai*x - yi - bi
553a7e14dcfSSatish Balay    mu = yi' * lami/mi;
554a7e14dcfSSatish Balay    com = yi.*lami
555a7e14dcfSSatish Balay 
556a7e14dcfSSatish Balay    phi = ||rd|| + ||rpe|| + ||rpi|| + ||com||
557a7e14dcfSSatish Balay */
558a7e14dcfSSatish Balay /*
559a7e14dcfSSatish Balay static PetscErrorCode IPMObjective(TaoLineSearch ls, Vec X, PetscReal *f, void *tptr)
560a7e14dcfSSatish Balay {
561441846f8SBarry Smith   Tao tao = (Tao)tptr;
562a7e14dcfSSatish Balay   TAO_IPM *ipmP = (TAO_IPM*)tao->data;
563a7e14dcfSSatish Balay   PetscFunctionBegin;
564*9566063dSJacob Faibussowitsch   PetscCall(IPMComputeKKT(tao));
565a7e14dcfSSatish Balay   *f = ipmP->phi;
566a7e14dcfSSatish Balay   PetscFunctionReturn(0);
567a7e14dcfSSatish Balay }
568a7e14dcfSSatish Balay */
569a7e14dcfSSatish Balay 
570a7e14dcfSSatish Balay /*
571a7e14dcfSSatish Balay    f = d'x + 0.5 * x' * H * x
572a7e14dcfSSatish Balay    rd = H*x + d + Ae'*lame - Ai'*lami
573a7e14dcfSSatish Balay        Ai =   jac_ineq
574a7e14dcfSSatish Balay                I (w/lb)
575a7e14dcfSSatish Balay               -I (w/ub)
576a7e14dcfSSatish Balay 
577a7e14dcfSSatish Balay    rpe = ce
578a7e14dcfSSatish Balay    rpi = ci - s;
579a7e14dcfSSatish Balay    com = s.*lami
580a7e14dcfSSatish Balay    mu = yi' * lami/mi;
581a7e14dcfSSatish Balay 
582a7e14dcfSSatish Balay    phi = ||rd|| + ||rpe|| + ||rpi|| + ||com||
583a7e14dcfSSatish Balay */
584441846f8SBarry Smith static PetscErrorCode IPMComputeKKT(Tao tao)
585a7e14dcfSSatish Balay {
586a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM *)tao->data;
587a7e14dcfSSatish Balay   PetscScalar    norm;
58847a47007SBarry Smith 
58947a47007SBarry Smith   PetscFunctionBegin;
590*9566063dSJacob Faibussowitsch   PetscCall(VecCopy(tao->gradient,ipmP->rd));
591a7e14dcfSSatish Balay 
592a7e14dcfSSatish Balay   if (ipmP->me > 0) {
593a7e14dcfSSatish Balay     /* rd = gradient + Ae'*lamdae */
594*9566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(tao->jacobian_equality,ipmP->lamdae,ipmP->work));
595*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(ipmP->rd, 1.0, ipmP->work));
596a7e14dcfSSatish Balay 
597a7e14dcfSSatish Balay     /* rpe = ce(x) */
598*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(tao->constraints_equality,ipmP->rpe));
599a7e14dcfSSatish Balay   }
600a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
601a7e14dcfSSatish Balay     /* rd = rd - Ai'*lamdai */
602*9566063dSJacob Faibussowitsch     PetscCall(MatMultTranspose(ipmP->Ai,ipmP->lamdai,ipmP->work));
603*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(ipmP->rd, -1.0, ipmP->work));
6041522df2eSJason Sarich 
605a7e14dcfSSatish Balay     /* rpi = cin - s */
606*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(ipmP->ci,ipmP->rpi));
607*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(ipmP->rpi, -1.0, ipmP->s));
608a7e14dcfSSatish Balay 
609a7e14dcfSSatish Balay     /* com = s .* lami */
610*9566063dSJacob Faibussowitsch     PetscCall(VecPointwiseMult(ipmP->complementarity, ipmP->s,ipmP->lamdai));
611a7e14dcfSSatish Balay   }
612a7e14dcfSSatish Balay   /* phi = ||rd; rpe; rpi; com|| */
613*9566063dSJacob Faibussowitsch   PetscCall(VecDot(ipmP->rd,ipmP->rd,&norm));
614a7e14dcfSSatish Balay   ipmP->phi = norm;
615a7e14dcfSSatish Balay   if (ipmP->me > 0) {
616*9566063dSJacob Faibussowitsch     PetscCall(VecDot(ipmP->rpe,ipmP->rpe,&norm));
617a7e14dcfSSatish Balay     ipmP->phi += norm;
618a7e14dcfSSatish Balay   }
619a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
620*9566063dSJacob Faibussowitsch     PetscCall(VecDot(ipmP->rpi,ipmP->rpi,&norm));
621a7e14dcfSSatish Balay     ipmP->phi += norm;
622*9566063dSJacob Faibussowitsch     PetscCall(VecDot(ipmP->complementarity,ipmP->complementarity,&norm));
623a7e14dcfSSatish Balay     ipmP->phi += norm;
624a7e14dcfSSatish Balay     /* mu = s'*lami/nb */
625*9566063dSJacob Faibussowitsch     PetscCall(VecDot(ipmP->s,ipmP->lamdai,&ipmP->mu));
626a7e14dcfSSatish Balay     ipmP->mu /= ipmP->nb;
627a7e14dcfSSatish Balay   } else {
628a7e14dcfSSatish Balay     ipmP->mu = 1.0;
629a7e14dcfSSatish Balay   }
630a7e14dcfSSatish Balay 
631a7e14dcfSSatish Balay   ipmP->phi = PetscSqrtScalar(ipmP->phi);
632a7e14dcfSSatish Balay   PetscFunctionReturn(0);
633a7e14dcfSSatish Balay }
634a7e14dcfSSatish Balay 
635a7e14dcfSSatish Balay /* evaluate user info at current point */
636441846f8SBarry Smith PetscErrorCode IPMEvaluate(Tao tao)
637a7e14dcfSSatish Balay {
638a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM *)tao->data;
63947a47007SBarry Smith 
640a7e14dcfSSatish Balay   PetscFunctionBegin;
641*9566063dSJacob Faibussowitsch   PetscCall(TaoComputeObjectiveAndGradient(tao,tao->solution,&ipmP->kkt_f,tao->gradient));
642*9566063dSJacob Faibussowitsch   PetscCall(TaoComputeHessian(tao,tao->solution,tao->hessian,tao->hessian_pre));
643a7e14dcfSSatish Balay   if (ipmP->me > 0) {
644*9566063dSJacob Faibussowitsch     PetscCall(TaoComputeEqualityConstraints(tao,tao->solution,tao->constraints_equality));
645*9566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianEquality(tao,tao->solution,tao->jacobian_equality,tao->jacobian_equality_pre));
646a7e14dcfSSatish Balay   }
647a7e14dcfSSatish Balay   if (ipmP->mi > 0) {
648*9566063dSJacob Faibussowitsch     PetscCall(TaoComputeInequalityConstraints(tao,tao->solution,tao->constraints_inequality));
649*9566063dSJacob Faibussowitsch     PetscCall(TaoComputeJacobianInequality(tao,tao->solution,tao->jacobian_inequality,tao->jacobian_inequality_pre));
650a7e14dcfSSatish Balay   }
651a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
652a7e14dcfSSatish Balay     /* Ai' =   jac_ineq | I (w/lb) | -I (w/ub)  */
653*9566063dSJacob Faibussowitsch     PetscCall(IPMUpdateAi(tao));
654a7e14dcfSSatish Balay   }
655a7e14dcfSSatish Balay   PetscFunctionReturn(0);
656a7e14dcfSSatish Balay }
657a7e14dcfSSatish Balay 
658a7e14dcfSSatish Balay /* Push initial point away from bounds */
659441846f8SBarry Smith PetscErrorCode IPMPushInitialPoint(Tao tao)
660a7e14dcfSSatish Balay {
661a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM *)tao->data;
662a7e14dcfSSatish Balay 
66347a47007SBarry Smith   PetscFunctionBegin;
664*9566063dSJacob Faibussowitsch   PetscCall(TaoComputeVariableBounds(tao));
665a7e14dcfSSatish Balay   if (tao->XL && tao->XU) {
666*9566063dSJacob Faibussowitsch     PetscCall(VecMedian(tao->XL, tao->solution, tao->XU, tao->solution));
667a7e14dcfSSatish Balay   }
668a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
669*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->s,ipmP->pushs));
670*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->lamdai,ipmP->pushnu));
671a7e14dcfSSatish Balay     if (ipmP->mi > 0) {
672*9566063dSJacob Faibussowitsch       PetscCall(VecSet(tao->DI,ipmP->pushnu));
673a7e14dcfSSatish Balay     }
674a7e14dcfSSatish Balay   }
675a7e14dcfSSatish Balay   if (ipmP->me > 0) {
676*9566063dSJacob Faibussowitsch     PetscCall(VecSet(tao->DE,1.0));
677*9566063dSJacob Faibussowitsch     PetscCall(VecSet(ipmP->lamdae,1.0));
678a7e14dcfSSatish Balay   }
679a7e14dcfSSatish Balay   PetscFunctionReturn(0);
680a7e14dcfSSatish Balay }
681a7e14dcfSSatish Balay 
682441846f8SBarry Smith PetscErrorCode IPMUpdateAi(Tao tao)
683a7e14dcfSSatish Balay {
684a7e14dcfSSatish Balay   /* Ai =     Ji
685a7e14dcfSSatish Balay               I (w/lb)
686a7e14dcfSSatish Balay              -I (w/ub) */
687a7e14dcfSSatish Balay 
688a7e14dcfSSatish Balay   /* Ci =    user->ci
689a7e14dcfSSatish Balay              Xi - lb (w/lb)
690a7e14dcfSSatish Balay              -Xi + ub (w/ub)  */
691a7e14dcfSSatish Balay 
692a7e14dcfSSatish Balay   TAO_IPM           *ipmP = (TAO_IPM *)tao->data;
693a7e14dcfSSatish Balay   MPI_Comm          comm;
694a7e14dcfSSatish Balay   PetscInt          i;
695a7e14dcfSSatish Balay   PetscScalar       newval;
696a7e14dcfSSatish Balay   PetscInt          newrow,newcol,ncols;
697a7e14dcfSSatish Balay   const PetscScalar *vals;
698a7e14dcfSSatish Balay   const PetscInt    *cols;
699a7e14dcfSSatish Balay   PetscInt          astart,aend,jstart,jend;
700a7e14dcfSSatish Balay   PetscInt          *nonzeros;
701a7e14dcfSSatish Balay   PetscInt          r2,r3,r4;
70247a47007SBarry Smith   PetscMPIInt       size;
703f86eb7e8SHong Zhang   Vec               solu;
704f86eb7e8SHong Zhang   PetscInt          nloc;
705a7e14dcfSSatish Balay 
706a7e14dcfSSatish Balay   PetscFunctionBegin;
707a7e14dcfSSatish Balay   r2 = ipmP->mi;
708a7e14dcfSSatish Balay   r3 = r2 + ipmP->nxlb;
709a7e14dcfSSatish Balay   r4 = r3 + ipmP->nxub;
710a7e14dcfSSatish Balay 
711050fc7a3SBarry Smith   if (!ipmP->nb) PetscFunctionReturn(0);
712a7e14dcfSSatish Balay 
713a7e14dcfSSatish Balay   /* Create Ai matrix if it doesn't exist yet */
714a7e14dcfSSatish Balay   if (!ipmP->Ai) {
715a7e14dcfSSatish Balay     comm = ((PetscObject)(tao->solution))->comm;
716*9566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Comm_size(comm,&size));
71747a47007SBarry Smith     if (size == 1) {
718*9566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(ipmP->nb,&nonzeros));
719a7e14dcfSSatish Balay       for (i=0;i<ipmP->mi;i++) {
720*9566063dSJacob Faibussowitsch         PetscCall(MatGetRow(tao->jacobian_inequality,i,&ncols,NULL,NULL));
721a7e14dcfSSatish Balay         nonzeros[i] = ncols;
722*9566063dSJacob Faibussowitsch         PetscCall(MatRestoreRow(tao->jacobian_inequality,i,&ncols,NULL,NULL));
723a7e14dcfSSatish Balay       }
724a7e14dcfSSatish Balay       for (i=r2;i<r4;i++) {
725a7e14dcfSSatish Balay         nonzeros[i] = 1;
726a7e14dcfSSatish Balay       }
727a7e14dcfSSatish Balay     }
728*9566063dSJacob Faibussowitsch     PetscCall(MatCreate(comm,&ipmP->Ai));
729*9566063dSJacob Faibussowitsch     PetscCall(MatSetType(ipmP->Ai,MATAIJ));
730f86eb7e8SHong Zhang 
731*9566063dSJacob Faibussowitsch     PetscCall(TaoGetSolution(tao,&solu));
732*9566063dSJacob Faibussowitsch     PetscCall(VecGetLocalSize(solu,&nloc));
733*9566063dSJacob Faibussowitsch     PetscCall(MatSetSizes(ipmP->Ai,PETSC_DECIDE,nloc,ipmP->nb,PETSC_DECIDE));
734*9566063dSJacob Faibussowitsch     PetscCall(MatSetFromOptions(ipmP->Ai));
735*9566063dSJacob Faibussowitsch     PetscCall(MatMPIAIJSetPreallocation(ipmP->Ai,ipmP->nb,NULL,ipmP->nb,NULL));
736*9566063dSJacob Faibussowitsch     PetscCall(MatSeqAIJSetPreallocation(ipmP->Ai,PETSC_DEFAULT,nonzeros));
73747a47007SBarry Smith     if (size ==1) {
738*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(nonzeros));
739a7e14dcfSSatish Balay     }
740a7e14dcfSSatish Balay   }
741a7e14dcfSSatish Balay 
742a7e14dcfSSatish Balay   /* Copy values from user jacobian to Ai */
743*9566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(ipmP->Ai,&astart,&aend));
744a7e14dcfSSatish Balay 
745a7e14dcfSSatish Balay   /* Ai w/lb */
746a7e14dcfSSatish Balay   if (ipmP->mi) {
747*9566063dSJacob Faibussowitsch     PetscCall(MatZeroEntries(ipmP->Ai));
748*9566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(tao->jacobian_inequality,&jstart,&jend));
749a7e14dcfSSatish Balay     for (i=jstart;i<jend;i++) {
750*9566063dSJacob Faibussowitsch       PetscCall(MatGetRow(tao->jacobian_inequality,i,&ncols,&cols,&vals));
751a7e14dcfSSatish Balay       newrow = i;
752*9566063dSJacob Faibussowitsch       PetscCall(MatSetValues(ipmP->Ai,1,&newrow,ncols,cols,vals,INSERT_VALUES));
753*9566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(tao->jacobian_inequality,i,&ncols,&cols,&vals));
754a7e14dcfSSatish Balay     }
755a7e14dcfSSatish Balay   }
756a7e14dcfSSatish Balay 
757a7e14dcfSSatish Balay   /* I w/ xlb */
758a7e14dcfSSatish Balay   if (ipmP->nxlb) {
759a7e14dcfSSatish Balay     for (i=0;i<ipmP->nxlb;i++) {
760a7e14dcfSSatish Balay       if (i>=astart && i<aend) {
761a7e14dcfSSatish Balay         newrow = i+r2;
762a7e14dcfSSatish Balay         newcol = i;
763a7e14dcfSSatish Balay         newval = 1.0;
764*9566063dSJacob Faibussowitsch         PetscCall(MatSetValues(ipmP->Ai,1,&newrow,1,&newcol,&newval,INSERT_VALUES));
765a7e14dcfSSatish Balay       }
766a7e14dcfSSatish Balay     }
767a7e14dcfSSatish Balay   }
768a7e14dcfSSatish Balay   if (ipmP->nxub) {
769a7e14dcfSSatish Balay     /* I w/ xub */
770a7e14dcfSSatish Balay     for (i=0;i<ipmP->nxub;i++) {
771a7e14dcfSSatish Balay       if (i>=astart && i<aend) {
772a7e14dcfSSatish Balay       newrow = i+r3;
773a7e14dcfSSatish Balay       newcol = i;
774a7e14dcfSSatish Balay       newval = -1.0;
775*9566063dSJacob Faibussowitsch       PetscCall(MatSetValues(ipmP->Ai,1,&newrow,1,&newcol,&newval,INSERT_VALUES));
776a7e14dcfSSatish Balay       }
777a7e14dcfSSatish Balay     }
778a7e14dcfSSatish Balay   }
779a7e14dcfSSatish Balay 
780*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(ipmP->Ai,MAT_FINAL_ASSEMBLY));
781*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(ipmP->Ai,MAT_FINAL_ASSEMBLY));
782a7e14dcfSSatish Balay   CHKMEMQ;
783a7e14dcfSSatish Balay 
784*9566063dSJacob Faibussowitsch   PetscCall(VecSet(ipmP->ci,0.0));
785a7e14dcfSSatish Balay 
786a7e14dcfSSatish Balay   /* user ci */
787a7e14dcfSSatish Balay   if (ipmP->mi > 0) {
788*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->ci_scat,tao->constraints_inequality,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
789*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->ci_scat,tao->constraints_inequality,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
790a7e14dcfSSatish Balay   }
791a7e14dcfSSatish Balay   if (!ipmP->work) {
792a7e14dcfSSatish Balay     VecDuplicate(tao->solution,&ipmP->work);
793a7e14dcfSSatish Balay   }
794*9566063dSJacob Faibussowitsch   PetscCall(VecCopy(tao->solution,ipmP->work));
795a7e14dcfSSatish Balay   if (tao->XL) {
796*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(ipmP->work,-1.0,tao->XL));
797a7e14dcfSSatish Balay 
798a7e14dcfSSatish Balay     /* lower bounds on variables */
799a7e14dcfSSatish Balay     if (ipmP->nxlb > 0) {
800*9566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(ipmP->xl_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
801*9566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(ipmP->xl_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
802a7e14dcfSSatish Balay     }
803a7e14dcfSSatish Balay   }
804a7e14dcfSSatish Balay   if (tao->XU) {
805a7e14dcfSSatish Balay     /* upper bounds on variables */
806*9566063dSJacob Faibussowitsch     PetscCall(VecCopy(tao->solution,ipmP->work));
807*9566063dSJacob Faibussowitsch     PetscCall(VecScale(ipmP->work,-1.0));
808*9566063dSJacob Faibussowitsch     PetscCall(VecAXPY(ipmP->work,1.0,tao->XU));
809a7e14dcfSSatish Balay     if (ipmP->nxub > 0) {
810*9566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(ipmP->xu_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
811*9566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(ipmP->xu_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD));
812a7e14dcfSSatish Balay     }
813a7e14dcfSSatish Balay   }
814a7e14dcfSSatish Balay   PetscFunctionReturn(0);
815a7e14dcfSSatish Balay }
816a7e14dcfSSatish Balay 
817a7e14dcfSSatish Balay /* create K = [ Hlag , 0 , Ae', -Ai'];
818a7e14dcfSSatish Balay               [Ae , 0,   0  , 0];
819a7e14dcfSSatish Balay               [Ai ,-I,   0 ,  0];
820a7e14dcfSSatish Balay               [ 0 , S ,  0,   Y ];  */
821441846f8SBarry Smith PetscErrorCode IPMUpdateK(Tao tao)
822a7e14dcfSSatish Balay {
823a7e14dcfSSatish Balay   TAO_IPM         *ipmP = (TAO_IPM *)tao->data;
824a7e14dcfSSatish Balay   MPI_Comm        comm;
82547a47007SBarry Smith   PetscMPIInt     size;
826a7e14dcfSSatish Balay   PetscInt        i,j,row;
827a7e14dcfSSatish Balay   PetscInt        ncols,newcol,newcols[2],newrow;
828a7e14dcfSSatish Balay   const PetscInt  *cols;
829a7e14dcfSSatish Balay   const PetscReal *vals;
8305e081366SBarry Smith   const PetscReal *l,*y;
831a7e14dcfSSatish Balay   PetscReal       *newvals;
832a7e14dcfSSatish Balay   PetscReal       newval;
833a7e14dcfSSatish Balay   PetscInt        subsize;
834a7e14dcfSSatish Balay   const PetscInt  *indices;
835a7e14dcfSSatish Balay   PetscInt        *nonzeros,*d_nonzeros,*o_nonzeros;
836a7e14dcfSSatish Balay   PetscInt        bigsize;
837a7e14dcfSSatish Balay   PetscInt        r1,r2,r3;
838a7e14dcfSSatish Balay   PetscInt        c1,c2,c3;
839a7e14dcfSSatish Balay   PetscInt        klocalsize;
840a7e14dcfSSatish Balay   PetscInt        hstart,hend,kstart,kend;
841a7e14dcfSSatish Balay   PetscInt        aistart,aiend,aestart,aeend;
842a7e14dcfSSatish Balay   PetscInt        sstart,send;
843a7e14dcfSSatish Balay 
84447a47007SBarry Smith   PetscFunctionBegin;
845a7e14dcfSSatish Balay   comm = ((PetscObject)(tao->solution))->comm;
846*9566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm,&size));
847*9566063dSJacob Faibussowitsch   PetscCall(IPMUpdateAi(tao));
8481522df2eSJason Sarich 
849a7e14dcfSSatish Balay   /* allocate workspace */
850a7e14dcfSSatish Balay   subsize = PetscMax(ipmP->n,ipmP->nb);
851a7e14dcfSSatish Balay   subsize = PetscMax(ipmP->me,subsize);
852a7e14dcfSSatish Balay   subsize = PetscMax(2,subsize);
853*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(subsize,(PetscInt**)&indices));
854*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(subsize,&newvals));
855a7e14dcfSSatish Balay 
856a7e14dcfSSatish Balay   r1 = c1 = ipmP->n;
857a7e14dcfSSatish Balay   r2 = r1 + ipmP->me;  c2 = c1 + ipmP->nb;
858a7e14dcfSSatish Balay   r3 = c3 = r2 + ipmP->nb;
859a7e14dcfSSatish Balay 
860a7e14dcfSSatish Balay   bigsize = ipmP->n+2*ipmP->nb+ipmP->me;
861*9566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(ipmP->bigrhs,&kstart,&kend));
862*9566063dSJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(tao->hessian,&hstart,&hend));
863a7e14dcfSSatish Balay   klocalsize = kend-kstart;
864a7e14dcfSSatish Balay   if (!ipmP->K) {
86547a47007SBarry Smith     if (size == 1) {
866*9566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(kend-kstart,&nonzeros));
867a7e14dcfSSatish Balay       for (i=0;i<bigsize;i++) {
868a7e14dcfSSatish Balay         if (i<r1) {
869*9566063dSJacob Faibussowitsch           PetscCall(MatGetRow(tao->hessian,i,&ncols,NULL,NULL));
870a7e14dcfSSatish Balay           nonzeros[i] = ncols;
871*9566063dSJacob Faibussowitsch           PetscCall(MatRestoreRow(tao->hessian,i,&ncols,NULL,NULL));
872a7e14dcfSSatish Balay           nonzeros[i] += ipmP->me+ipmP->nb;
873a7e14dcfSSatish Balay         } else if (i<r2) {
874a7e14dcfSSatish Balay           nonzeros[i-kstart] = ipmP->n;
875a7e14dcfSSatish Balay         } else if (i<r3) {
876a7e14dcfSSatish Balay           nonzeros[i-kstart] = ipmP->n+1;
877a7e14dcfSSatish Balay         } else if (i<bigsize) {
878a7e14dcfSSatish Balay           nonzeros[i-kstart] = 2;
879a7e14dcfSSatish Balay         }
880a7e14dcfSSatish Balay       }
881*9566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&ipmP->K));
882*9566063dSJacob Faibussowitsch       PetscCall(MatSetType(ipmP->K,MATSEQAIJ));
883*9566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(ipmP->K,klocalsize,klocalsize,PETSC_DETERMINE,PETSC_DETERMINE));
884*9566063dSJacob Faibussowitsch       PetscCall(MatSeqAIJSetPreallocation(ipmP->K,0,nonzeros));
885*9566063dSJacob Faibussowitsch       PetscCall(MatSetFromOptions(ipmP->K));
886*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(nonzeros));
887a7e14dcfSSatish Balay     } else {
888*9566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(kend-kstart,&d_nonzeros));
889*9566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(kend-kstart,&o_nonzeros));
890a7e14dcfSSatish Balay       for (i=kstart;i<kend;i++) {
891a7e14dcfSSatish Balay         if (i<r1) {
892a7e14dcfSSatish Balay           /* TODO fix preallocation for mpi mats */
893a7e14dcfSSatish Balay           d_nonzeros[i-kstart] = PetscMin(ipmP->n+ipmP->me+ipmP->nb,kend-kstart);
894a7e14dcfSSatish Balay           o_nonzeros[i-kstart] = PetscMin(ipmP->n+ipmP->me+ipmP->nb,bigsize-(kend-kstart));
895a7e14dcfSSatish Balay         } else if (i<r2) {
896a7e14dcfSSatish Balay           d_nonzeros[i-kstart] = PetscMin(ipmP->n,kend-kstart);
897a7e14dcfSSatish Balay           o_nonzeros[i-kstart] = PetscMin(ipmP->n,bigsize-(kend-kstart));
898a7e14dcfSSatish Balay         } else if (i<r3) {
899a7e14dcfSSatish Balay           d_nonzeros[i-kstart] = PetscMin(ipmP->n+2,kend-kstart);
900a7e14dcfSSatish Balay           o_nonzeros[i-kstart] = PetscMin(ipmP->n+2,bigsize-(kend-kstart));
901a7e14dcfSSatish Balay         } else {
902a7e14dcfSSatish Balay           d_nonzeros[i-kstart] = PetscMin(2,kend-kstart);
903a7e14dcfSSatish Balay           o_nonzeros[i-kstart] = PetscMin(2,bigsize-(kend-kstart));
904a7e14dcfSSatish Balay         }
905a7e14dcfSSatish Balay       }
906*9566063dSJacob Faibussowitsch       PetscCall(MatCreate(comm,&ipmP->K));
907*9566063dSJacob Faibussowitsch       PetscCall(MatSetType(ipmP->K,MATMPIAIJ));
908*9566063dSJacob Faibussowitsch       PetscCall(MatSetSizes(ipmP->K,klocalsize,klocalsize,PETSC_DETERMINE,PETSC_DETERMINE));
909*9566063dSJacob Faibussowitsch       PetscCall(MatMPIAIJSetPreallocation(ipmP->K,0,d_nonzeros,0,o_nonzeros));
910*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(d_nonzeros));
911*9566063dSJacob Faibussowitsch       PetscCall(PetscFree(o_nonzeros));
912*9566063dSJacob Faibussowitsch       PetscCall(MatSetFromOptions(ipmP->K));
913a7e14dcfSSatish Balay     }
914a7e14dcfSSatish Balay   }
915a7e14dcfSSatish Balay 
916*9566063dSJacob Faibussowitsch   PetscCall(MatZeroEntries(ipmP->K));
917a7e14dcfSSatish Balay   /* Copy H */
918a7e14dcfSSatish Balay   for (i=hstart;i<hend;i++) {
919*9566063dSJacob Faibussowitsch     PetscCall(MatGetRow(tao->hessian,i,&ncols,&cols,&vals));
920a7e14dcfSSatish Balay     if (ncols > 0) {
921*9566063dSJacob Faibussowitsch       PetscCall(MatSetValues(ipmP->K,1,&i,ncols,cols,vals,INSERT_VALUES));
922a7e14dcfSSatish Balay     }
923*9566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(tao->hessian,i,&ncols,&cols,&vals));
924a7e14dcfSSatish Balay   }
925a7e14dcfSSatish Balay 
926a7e14dcfSSatish Balay   /* Copy Ae and Ae' */
927a7e14dcfSSatish Balay   if (ipmP->me > 0) {
928*9566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(tao->jacobian_equality,&aestart,&aeend));
929a7e14dcfSSatish Balay     for (i=aestart;i<aeend;i++) {
930*9566063dSJacob Faibussowitsch       PetscCall(MatGetRow(tao->jacobian_equality,i,&ncols,&cols,&vals));
931a7e14dcfSSatish Balay       if (ncols > 0) {
932a7e14dcfSSatish Balay         /*Ae*/
933a7e14dcfSSatish Balay         row = i+r1;
934*9566063dSJacob Faibussowitsch         PetscCall(MatSetValues(ipmP->K,1,&row,ncols,cols,vals,INSERT_VALUES));
935a7e14dcfSSatish Balay         /*Ae'*/
936a7e14dcfSSatish Balay         for (j=0;j<ncols;j++) {
937a7e14dcfSSatish Balay           newcol = i + c2;
938a7e14dcfSSatish Balay           newrow = cols[j];
939a7e14dcfSSatish Balay           newval = vals[j];
940*9566063dSJacob Faibussowitsch           PetscCall(MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES));
941a7e14dcfSSatish Balay         }
942a7e14dcfSSatish Balay       }
943*9566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(tao->jacobian_equality,i,&ncols,&cols,&vals));
944a7e14dcfSSatish Balay     }
945a7e14dcfSSatish Balay   }
946a7e14dcfSSatish Balay 
947a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
948*9566063dSJacob Faibussowitsch     PetscCall(MatGetOwnershipRange(ipmP->Ai,&aistart,&aiend));
949a7e14dcfSSatish Balay     /* Copy Ai,and Ai' */
950a7e14dcfSSatish Balay     for (i=aistart;i<aiend;i++) {
951a7e14dcfSSatish Balay       row = i+r2;
952*9566063dSJacob Faibussowitsch       PetscCall(MatGetRow(ipmP->Ai,i,&ncols,&cols,&vals));
953a7e14dcfSSatish Balay       if (ncols > 0) {
954a7e14dcfSSatish Balay         /*Ai*/
955*9566063dSJacob Faibussowitsch         PetscCall(MatSetValues(ipmP->K,1,&row,ncols,cols,vals,INSERT_VALUES));
956a7e14dcfSSatish Balay         /*-Ai'*/
957a7e14dcfSSatish Balay         for (j=0;j<ncols;j++) {
958a7e14dcfSSatish Balay           newcol = i + c3;
959a7e14dcfSSatish Balay           newrow = cols[j];
960a7e14dcfSSatish Balay           newval = -vals[j];
961*9566063dSJacob Faibussowitsch           PetscCall(MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES));
962a7e14dcfSSatish Balay         }
963a7e14dcfSSatish Balay       }
964*9566063dSJacob Faibussowitsch       PetscCall(MatRestoreRow(ipmP->Ai,i,&ncols,&cols,&vals));
965a7e14dcfSSatish Balay     }
966a7e14dcfSSatish Balay 
967a7e14dcfSSatish Balay     /* -I */
968a7e14dcfSSatish Balay     for (i=kstart;i<kend;i++) {
969a7e14dcfSSatish Balay       if (i>=r2 && i<r3) {
970a7e14dcfSSatish Balay         newrow = i;
971a7e14dcfSSatish Balay         newcol = i-r2+c1;
972a7e14dcfSSatish Balay         newval = -1.0;
973*9566063dSJacob Faibussowitsch         PetscCall(MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES));
974a7e14dcfSSatish Balay       }
975a7e14dcfSSatish Balay     }
976a7e14dcfSSatish Balay 
977a7e14dcfSSatish Balay     /* Copy L,Y */
978*9566063dSJacob Faibussowitsch     PetscCall(VecGetOwnershipRange(ipmP->s,&sstart,&send));
979*9566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ipmP->lamdai,&l));
980*9566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(ipmP->s,&y));
981a7e14dcfSSatish Balay 
982a7e14dcfSSatish Balay     for (i=sstart;i<send;i++) {
983a7e14dcfSSatish Balay       newcols[0] = c1+i;
984a7e14dcfSSatish Balay       newcols[1] = c3+i;
985a7e14dcfSSatish Balay       newvals[0] = l[i-sstart];
986a7e14dcfSSatish Balay       newvals[1] = y[i-sstart];
987a7e14dcfSSatish Balay       newrow = r3+i;
988*9566063dSJacob Faibussowitsch       PetscCall(MatSetValues(ipmP->K,1,&newrow,2,newcols,newvals,INSERT_VALUES));
989a7e14dcfSSatish Balay     }
990a7e14dcfSSatish Balay 
991*9566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ipmP->lamdai,&l));
992*9566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(ipmP->s,&y));
993a7e14dcfSSatish Balay   }
994a7e14dcfSSatish Balay 
995*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(indices));
996*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(newvals));
997*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(ipmP->K,MAT_FINAL_ASSEMBLY));
998*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(ipmP->K,MAT_FINAL_ASSEMBLY));
999a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1000a7e14dcfSSatish Balay }
1001a7e14dcfSSatish Balay 
1002441846f8SBarry Smith PetscErrorCode IPMGatherRHS(Tao tao,Vec RHS,Vec X1,Vec X2,Vec X3,Vec X4)
1003a7e14dcfSSatish Balay {
1004a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM *)tao->data;
1005a7e14dcfSSatish Balay 
100647a47007SBarry Smith   PetscFunctionBegin;
1007a7e14dcfSSatish Balay   /* rhs = [x1      (n)
1008a7e14dcfSSatish Balay             x2     (me)
1009a7e14dcfSSatish Balay             x3     (nb)
1010a7e14dcfSSatish Balay             x4     (nb)] */
1011a7e14dcfSSatish Balay   if (X1) {
1012*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->rhs1,X1,RHS,INSERT_VALUES,SCATTER_FORWARD));
1013*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->rhs1,X1,RHS,INSERT_VALUES,SCATTER_FORWARD));
1014a7e14dcfSSatish Balay   }
1015a7e14dcfSSatish Balay   if (ipmP->me > 0 && X2) {
1016*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->rhs2,X2,RHS,INSERT_VALUES,SCATTER_FORWARD));
1017*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->rhs2,X2,RHS,INSERT_VALUES,SCATTER_FORWARD));
1018a7e14dcfSSatish Balay   }
1019a7e14dcfSSatish Balay   if (ipmP->nb > 0) {
1020a7e14dcfSSatish Balay     if (X3) {
1021*9566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(ipmP->rhs3,X3,RHS,INSERT_VALUES,SCATTER_FORWARD));
1022*9566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(ipmP->rhs3,X3,RHS,INSERT_VALUES,SCATTER_FORWARD));
1023a7e14dcfSSatish Balay     }
1024a7e14dcfSSatish Balay     if (X4) {
1025*9566063dSJacob Faibussowitsch       PetscCall(VecScatterBegin(ipmP->rhs4,X4,RHS,INSERT_VALUES,SCATTER_FORWARD));
1026*9566063dSJacob Faibussowitsch       PetscCall(VecScatterEnd(ipmP->rhs4,X4,RHS,INSERT_VALUES,SCATTER_FORWARD));
1027a7e14dcfSSatish Balay     }
1028a7e14dcfSSatish Balay   }
1029a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1030a7e14dcfSSatish Balay }
1031a7e14dcfSSatish Balay 
1032441846f8SBarry Smith PetscErrorCode IPMScatterStep(Tao tao, Vec STEP, Vec X1, Vec X2, Vec X3, Vec X4)
1033a7e14dcfSSatish Balay {
1034a7e14dcfSSatish Balay   TAO_IPM        *ipmP = (TAO_IPM *)tao->data;
103547a47007SBarry Smith 
1036a7e14dcfSSatish Balay   PetscFunctionBegin;
1037a7e14dcfSSatish Balay   CHKMEMQ;
1038a7e14dcfSSatish Balay   /*        [x1    (n)
1039a7e14dcfSSatish Balay              x2    (nb) may be 0
1040a7e14dcfSSatish Balay              x3    (me) may be 0
1041a7e14dcfSSatish Balay              x4    (nb) may be 0 */
1042a7e14dcfSSatish Balay   if (X1) {
1043*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->step1,STEP,X1,INSERT_VALUES,SCATTER_FORWARD));
1044*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->step1,STEP,X1,INSERT_VALUES,SCATTER_FORWARD));
1045a7e14dcfSSatish Balay   }
1046a7e14dcfSSatish Balay   if (X2 && ipmP->nb > 0) {
1047*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->step2,STEP,X2,INSERT_VALUES,SCATTER_FORWARD));
1048*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->step2,STEP,X2,INSERT_VALUES,SCATTER_FORWARD));
1049a7e14dcfSSatish Balay   }
1050a7e14dcfSSatish Balay   if (X3 && ipmP->me > 0) {
1051*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->step3,STEP,X3,INSERT_VALUES,SCATTER_FORWARD));
1052*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->step3,STEP,X3,INSERT_VALUES,SCATTER_FORWARD));
1053a7e14dcfSSatish Balay   }
1054a7e14dcfSSatish Balay   if (X4 && ipmP->nb > 0) {
1055*9566063dSJacob Faibussowitsch     PetscCall(VecScatterBegin(ipmP->step4,STEP,X4,INSERT_VALUES,SCATTER_FORWARD));
1056*9566063dSJacob Faibussowitsch     PetscCall(VecScatterEnd(ipmP->step4,STEP,X4,INSERT_VALUES,SCATTER_FORWARD));
1057a7e14dcfSSatish Balay   }
1058a7e14dcfSSatish Balay   CHKMEMQ;
1059a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1060a7e14dcfSSatish Balay }
1061a7e14dcfSSatish Balay 
10621522df2eSJason Sarich /*MC
10631522df2eSJason Sarich   TAOIPM - Interior point algorithm for generally constrained optimization.
10641522df2eSJason Sarich 
10651522df2eSJason Sarich   Option Database Keys:
10661522df2eSJason Sarich +   -tao_ipm_pushnu - parameter to push initial dual variables away from bounds
1067a2b725a8SWilliam Gropp -   -tao_ipm_pushs - parameter to push initial slack variables away from bounds
10681522df2eSJason Sarich 
106995452b02SPatrick Sanan   Notes:
107095452b02SPatrick Sanan     This algorithm is more of a place-holder for future constrained optimization algorithms and should not yet be used for large problems or production code.
10711eb8069cSJason Sarich   Level: beginner
10721eb8069cSJason Sarich 
10731522df2eSJason Sarich M*/
10741522df2eSJason Sarich 
1075728e0ed0SBarry Smith PETSC_EXTERN PetscErrorCode TaoCreate_IPM(Tao tao)
1076a7e14dcfSSatish Balay {
1077a7e14dcfSSatish Balay   TAO_IPM        *ipmP;
1078a7e14dcfSSatish Balay 
1079a7e14dcfSSatish Balay   PetscFunctionBegin;
1080a7e14dcfSSatish Balay   tao->ops->setup = TaoSetup_IPM;
1081a7e14dcfSSatish Balay   tao->ops->solve = TaoSolve_IPM;
1082a7e14dcfSSatish Balay   tao->ops->view = TaoView_IPM;
1083a7e14dcfSSatish Balay   tao->ops->setfromoptions = TaoSetFromOptions_IPM;
1084a7e14dcfSSatish Balay   tao->ops->destroy = TaoDestroy_IPM;
1085e9f9aeaeSSatish Balay   /* tao->ops->computedual = TaoComputeDual_IPM; */
1086a7e14dcfSSatish Balay 
1087*9566063dSJacob Faibussowitsch   PetscCall(PetscNewLog(tao,&ipmP));
1088a7e14dcfSSatish Balay   tao->data = (void*)ipmP;
10896552cf8aSJason Sarich 
10906552cf8aSJason Sarich   /* Override default settings (unless already changed) */
10916552cf8aSJason Sarich   if (!tao->max_it_changed) tao->max_it = 200;
10926552cf8aSJason Sarich   if (!tao->max_funcs_changed) tao->max_funcs = 500;
10936552cf8aSJason Sarich 
1094a7e14dcfSSatish Balay   ipmP->dec = 10000; /* line search critera */
1095a7e14dcfSSatish Balay   ipmP->taumin = 0.995;
1096a7e14dcfSSatish Balay   ipmP->monitorkkt = PETSC_FALSE;
1097a7e14dcfSSatish Balay   ipmP->pushs = 100;
1098a7e14dcfSSatish Balay   ipmP->pushnu = 100;
1099*9566063dSJacob Faibussowitsch   PetscCall(KSPCreate(((PetscObject)tao)->comm, &tao->ksp));
1100*9566063dSJacob Faibussowitsch   PetscCall(PetscObjectIncrementTabLevel((PetscObject)tao->ksp, (PetscObject)tao, 1));
1101*9566063dSJacob Faibussowitsch   PetscCall(KSPSetOptionsPrefix(tao->ksp, tao->hdr.prefix));
1102a7e14dcfSSatish Balay   PetscFunctionReturn(0);
1103a7e14dcfSSatish Balay }
1104