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