Actual source code: ipm.c
petsc-dev 2014-02-02
1: #include <petsctaolinesearch.h>
2: #include <../src/tao/constrained/impls/ipm/ipm.h> /*I "ipm.h" I*/
3: /*
4: #define DEBUG_IPM
5: #define DEBUG_K
6: #define DEBUG_SCATTER
7: #define DEBUG_KKT
8: */
9: /*
10: x,d in R^n
11: f in R
12: nb = mi + nlb+nub
13: s in R^nb is slack vector CI(x) / x-XL / -x+XU
14: bin in R^mi (tao->constraints_inequality)
15: beq in R^me (tao->constraints_equality)
16: lamdai in R^nb (ipmP->lamdai)
17: lamdae in R^me (ipmP->lamdae)
18: Jeq in R^(me x n) (tao->jacobian_equality)
19: Jin in R^(mi x n) (tao->jacobian_inequality)
20: Ai in R^(nb x n) (ipmP->Ai)
21: H in R^(n x n) (tao->hessian)
22: min f=(1/2)*x'*H*x + d'*x
23: s.t. CE(x) == 0
24: CI(x) >= 0
25: x >= tao->XL
26: -x >= -tao->XU
27: */
29: static PetscErrorCode IPMComputeKKT(Tao tao);
30: static PetscErrorCode IPMPushInitialPoint(Tao tao);
31: static PetscErrorCode IPMEvaluate(Tao tao);
32: static PetscErrorCode IPMUpdateK(Tao tao);
33: static PetscErrorCode IPMUpdateAi(Tao tao);
34: static PetscErrorCode IPMGatherRHS(Tao tao,Vec,Vec,Vec,Vec,Vec);
35: static PetscErrorCode IPMScatterStep(Tao tao,Vec,Vec,Vec,Vec,Vec);
36: static PetscErrorCode IPMInitializeBounds(Tao tao);
40: static PetscErrorCode TaoSolve_IPM(Tao tao)
41: {
42: PetscErrorCode ierr;
43: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
44: TaoTerminationReason reason = TAO_CONTINUE_ITERATING;
45: PetscInt iter = 0,its,i;
46: PetscScalar stepsize=1.0;
47: PetscScalar step_s,step_l,alpha,tau,sigma,phi_target;
50: /* Push initial point away from bounds */
51: #if defined(DEBUG_IPM)
52: VecNorm(tao->solution,NORM_2,&tau);
53: VecView(tao->solution,0);
54: #endif
55: IPMInitializeBounds(tao);
56: IPMPushInitialPoint(tao);
57: #if defined(DEBUG_IPM)
58: VecNorm(tao->solution,NORM_2,&tau);
59: VecView(tao->solution,0);
60: /* PetscPrintf(PETSC_COMM_WORLD,"||x0|| = %g\n",(double)tau); */
61: #endif
62: VecCopy(tao->solution,ipmP->rhs_x);
63: IPMEvaluate(tao);
64: IPMComputeKKT(tao);
65: TaoMonitor(tao,iter++,ipmP->kkt_f,ipmP->phi,0.0,1.0,&reason);
67: while (reason == TAO_CONTINUE_ITERATING) {
68: IPMUpdateK(tao);
69: /*
70: rhs.x = -rd
71: rhs.lame = -rpe
72: rhs.lami = -rpi
73: rhs.com = -com
74: */
76: VecCopy(ipmP->rd,ipmP->rhs_x);
77: if (ipmP->me > 0) {
78: VecCopy(ipmP->rpe,ipmP->rhs_lamdae);
79: }
80: if (ipmP->nb > 0) {
81: VecCopy(ipmP->rpi,ipmP->rhs_lamdai);
82: VecCopy(ipmP->complementarity,ipmP->rhs_s);
83: }
84: IPMGatherRHS(tao,ipmP->bigrhs,ipmP->rhs_x,ipmP->rhs_lamdae,ipmP->rhs_lamdai,ipmP->rhs_s);
85: VecScale(ipmP->bigrhs,-1.0);
87: /* solve K * step = rhs */
88: KSPSetOperators(tao->ksp,ipmP->K,ipmP->K,DIFFERENT_NONZERO_PATTERN);
89: KSPSolve(tao->ksp,ipmP->bigrhs,ipmP->bigstep);
91: IPMScatterStep(tao,ipmP->bigstep,tao->stepdirection,ipmP->ds,ipmP->dlamdae,ipmP->dlamdai);
92: KSPGetIterationNumber(tao->ksp,&its);
93: tao->ksp_its += its;
94: #if defined DEBUG_KKT
95: PetscPrintf(PETSC_COMM_WORLD,"first solve.\n");
96: PetscPrintf(PETSC_COMM_WORLD,"rhs_lamdai\n");
97: /* VecView(ipmP->rhs_lamdai,0);
98: VecView(ipmP->bigrhs,0);
99: VecView(ipmP->bigstep,0); */
100: PetscScalar norm1,norm2;
101: VecNorm(ipmP->bigrhs,NORM_2,&norm1);
102: VecNorm(ipmP->bigstep,NORM_2,&norm2);
103: PetscPrintf(PETSC_COMM_WORLD,"||rhs|| = %g\t ||step|| = %g\n",(double)norm1,(double)norm2);
104: #endif
105: /* Find distance along step direction to closest bound */
106: if (ipmP->nb > 0) {
107: VecStepBoundInfo(ipmP->s,ipmP->ds,ipmP->Zero_nb,ipmP->Inf_nb,&step_s,NULL,NULL);
108: VecStepBoundInfo(ipmP->lamdai,ipmP->dlamdai,ipmP->Zero_nb,ipmP->Inf_nb,&step_l,NULL,NULL);
109: alpha = PetscMin(step_s,step_l);
110: alpha = PetscMin(alpha,1.0);
111: ipmP->alpha1 = alpha;
112: } else {
113: ipmP->alpha1 = alpha = 1.0;
114: }
116: /* x_aff = x + alpha*d */
117: VecCopy(tao->solution,ipmP->save_x);
118: if (ipmP->me > 0) {
119: VecCopy(ipmP->lamdae,ipmP->save_lamdae);
120: }
121: if (ipmP->nb > 0) {
122: VecCopy(ipmP->lamdai,ipmP->save_lamdai);
123: VecCopy(ipmP->s,ipmP->save_s);
124: }
126: VecAXPY(tao->solution,alpha,tao->stepdirection);
127: if (ipmP->me > 0) {
128: VecAXPY(ipmP->lamdae,alpha,ipmP->dlamdae);
129: }
130: if (ipmP->nb > 0) {
131: VecAXPY(ipmP->lamdai,alpha,ipmP->dlamdai);
132: VecAXPY(ipmP->s,alpha,ipmP->ds);
133: }
135: /* Recompute kkt to find centering parameter sigma = (new_mu/old_mu)^3 */
136: if (ipmP->mu == 0.0) {
137: sigma = 0.0;
138: } else {
139: sigma = 1.0/ipmP->mu;
140: }
141: IPMComputeKKT(tao);
142: sigma *= ipmP->mu;
143: sigma*=sigma*sigma;
145: /* revert kkt info */
146: VecCopy(ipmP->save_x,tao->solution);
147: if (ipmP->me > 0) {
148: VecCopy(ipmP->save_lamdae,ipmP->lamdae);
149: }
150: if (ipmP->nb > 0) {
151: VecCopy(ipmP->save_lamdai,ipmP->lamdai);
152: VecCopy(ipmP->save_s,ipmP->s);
153: }
154: IPMComputeKKT(tao);
156: /* update rhs with new complementarity vector */
157: if (ipmP->nb > 0) {
158: VecCopy(ipmP->complementarity,ipmP->rhs_s);
159: VecScale(ipmP->rhs_s,-1.0);
160: VecShift(ipmP->rhs_s,sigma*ipmP->mu);
161: }
162: IPMGatherRHS(tao,ipmP->bigrhs,NULL,NULL,NULL,ipmP->rhs_s);
164: /* solve K * step = rhs */
165: KSPSetOperators(tao->ksp,ipmP->K,ipmP->K,DIFFERENT_NONZERO_PATTERN);
166: KSPSolve(tao->ksp,ipmP->bigrhs,ipmP->bigstep);
168: IPMScatterStep(tao,ipmP->bigstep,tao->stepdirection,ipmP->ds,ipmP->dlamdae,ipmP->dlamdai);
169: KSPGetIterationNumber(tao->ksp,&its);
170: #if defined DEBUG_KKT2
171: PetscPrintf(PETSC_COMM_WORLD,"rhs_lamdai\n");
172: VecView(ipmP->rhs_lamdai,0);
173: VecView(ipmP->bigrhs,0);
174: VecView(ipmP->bigstep,0);
175: #endif
176: tao->ksp_its += its;
178: if (ipmP->nb > 0) {
179: /* Get max step size and apply frac-to-boundary */
180: tau = PetscMax(ipmP->taumin,1.0-ipmP->mu);
181: tau = PetscMin(tau,1.0);
182: if (tau != 1.0) {
183: VecScale(ipmP->s,tau);
184: VecScale(ipmP->lamdai,tau);
185: }
186: VecStepBoundInfo(ipmP->s,ipmP->ds,ipmP->Zero_nb,ipmP->Inf_nb,&step_s,NULL,NULL);
187: VecStepBoundInfo(ipmP->lamdai,ipmP->dlamdai,ipmP->Zero_nb,ipmP->Inf_nb,&step_l,NULL,NULL);
188: if (tau != 1.0) {
189: VecCopy(ipmP->save_s,ipmP->s);
190: VecCopy(ipmP->save_lamdai,ipmP->lamdai);
191: }
192: alpha = PetscMin(step_s,step_l);
193: alpha = PetscMin(alpha,1.0);
194: } else {
195: alpha = 1.0;
196: }
197: ipmP->alpha2 = alpha;
198: /* TODO make phi_target meaningful */
199: phi_target = ipmP->dec * ipmP->phi;
200: for (i=0; i<11;i++) {
201: #if defined DEBUG_KKT2
202: PetscPrintf(PETSC_COMM_WORLD,"alpha2=%g\n",(double)alpha);
203: PetscPrintf(PETSC_COMM_WORLD,"old point:\n");
204: VecView(tao->solution,0);
205: VecView(ipmP->lamdae,0);
206: VecView(ipmP->s,0);
207: VecView(ipmP->lamdai,0);
208: #endif
209: VecAXPY(tao->solution,alpha,tao->stepdirection);
210: if (ipmP->nb > 0) {
211: VecAXPY(ipmP->s,alpha,ipmP->ds);
212: VecAXPY(ipmP->lamdai,alpha,ipmP->dlamdai);
213: }
214: if (ipmP->me > 0) {
215: VecAXPY(ipmP->lamdae,alpha,ipmP->dlamdae);
216: }
217: #if defined DEBUG_KKT
218: PetscPrintf(PETSC_COMM_WORLD,"step direction:\n");
219: VecView(tao->stepdirection,0);
220: /* VecView(ipmP->dlamdae,0);
221: VecView(ipmP->ds,0);
222: VecView(ipmP->dlamdai,0);
224: PetscPrintf(PETSC_COMM_WORLD,"New iterate:\n");
225: VecView(tao->solution,0);
226: VecView(ipmP->lamdae,0);
227: VecView(ipmP->s,0);
228: VecView(ipmP->lamdai,0); */
229: #endif
230: /* update dual variables */
231: if (ipmP->me > 0) {
232: VecCopy(ipmP->lamdae,tao->DE);
233: }
234: /* TODO: fix
235: if (ipmP->nb > 0) {
236: VecScatterBegin
237: PetscInt lstart,lend;
239: VecGetOwnershipRange(ipmP->lamdai,&lstart,&lend);
240: VecGetArray(ipmP->lamdai,&li);
241: VecGetArray(tao->DI,&di);
242: for (j=lstart;j<lend;j++) {
243: if (j < ipmP->nilb) {
244: di[j] = li[j];
245: }
246: }
247: VecRestoreArray(ipmP->lamdai,&li);
248: VecRestoreArray(tao->DI,&di);
249: }
250: */
252: IPMEvaluate(tao);
253: IPMComputeKKT(tao);
254: if (ipmP->phi <= phi_target) break;
255: alpha /= 2.0;
256: }
258: TaoMonitor(tao,iter,ipmP->kkt_f,ipmP->phi,0.0,stepsize,&reason);
259: iter++;
260: }
261: return(0);
262: }
266: static PetscErrorCode TaoSetup_IPM(Tao tao)
267: {
268: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
272: ipmP->nb = ipmP->mi = ipmP->me = 0;
273: ipmP->K=0;
274: VecGetSize(tao->solution,&ipmP->n);
275: if (!tao->gradient) {
276: VecDuplicate(tao->solution, &tao->gradient);
277: VecDuplicate(tao->solution, &tao->stepdirection);
278: VecDuplicate(tao->solution, &ipmP->rd);
279: VecDuplicate(tao->solution, &ipmP->rhs_x);
280: VecDuplicate(tao->solution, &ipmP->work);
281: VecDuplicate(tao->solution, &ipmP->save_x);
282: }
283: if (tao->constraints_equality) {
284: VecGetSize(tao->constraints_equality,&ipmP->me);
285: VecDuplicate(tao->constraints_equality,&ipmP->lamdae);
286: VecDuplicate(tao->constraints_equality,&ipmP->dlamdae);
287: VecDuplicate(tao->constraints_equality,&ipmP->rhs_lamdae);
288: VecDuplicate(tao->constraints_equality,&ipmP->save_lamdae);
289: VecDuplicate(tao->constraints_equality,&ipmP->rpe);
290: VecDuplicate(tao->constraints_equality,&tao->DE);
291: }
292: if (tao->constraints_inequality) {
293: VecDuplicate(tao->constraints_inequality,&tao->DI);
294: }
295: return(0);
296: }
300: static PetscErrorCode IPMInitializeBounds(Tao tao)
301: {
302: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
303: Vec xtmp;
304: PetscInt xstart,xend;
305: PetscInt ucstart,ucend; /* user ci */
306: PetscInt ucestart,uceend; /* user ce */
307: PetscInt sstart,send;
308: PetscInt bigsize;
309: PetscInt i,counter,nloc;
310: PetscInt *cind,*xind,*ucind,*uceind,*stepind;
311: VecType vtype;
312: const PetscInt *xli,*xui;
313: PetscInt xl_offset,xu_offset;
314: IS bigxl,bigxu,isuc,isc,isx,sis,is1;
316: MPI_Comm comm;
319: cind=xind=ucind=uceind=stepind=0;
320: ipmP->mi=0;
321: ipmP->nxlb=0;
322: ipmP->nxub=0;
323: ipmP->nb=0;
324: ipmP->nslack=0;
326: VecDuplicate(tao->solution,&xtmp);
327: if (!tao->XL && !tao->XU && tao->ops->computebounds) {
328: TaoComputeVariableBounds(tao);
329: }
330: if (tao->XL) {
331: VecSet(xtmp,PETSC_NINFINITY);
332: VecWhichGreaterThan(tao->XL,xtmp,&ipmP->isxl);
333: ISGetSize(ipmP->isxl,&ipmP->nxlb);
334: } else {
335: ipmP->nxlb=0;
336: }
337: if (tao->XU) {
338: VecSet(xtmp,PETSC_INFINITY);
339: VecWhichLessThan(tao->XU,xtmp,&ipmP->isxu);
340: ISGetSize(ipmP->isxu,&ipmP->nxub);
341: } else {
342: ipmP->nxub=0;
343: }
344: VecDestroy(&xtmp);
345: if (tao->constraints_inequality) {
346: VecGetSize(tao->constraints_inequality,&ipmP->mi);
347: } else {
348: ipmP->mi = 0;
349: }
350: #if defined DEBUG_K
351: PetscPrintf(PETSC_COMM_WORLD,"isxl:\n");
352: if (ipmP->nxlb) {
353: ISView(ipmP->isxl,0);
354: }
355: PetscPrintf(PETSC_COMM_WORLD,"isxu:\n");
356: if (ipmP->nxub) {
357: ISView(ipmP->isxu,0);
358: }
360: #endif
361: ipmP->nb = ipmP->nxlb + ipmP->nxub + ipmP->mi;
363: comm = ((PetscObject)(tao->solution))->comm;
365: bigsize = ipmP->n+2*ipmP->nb+ipmP->me;
366: PetscMalloc1(bigsize,&stepind);
367: PetscMalloc1(ipmP->n,&xind);
368: PetscMalloc1(ipmP->me,&uceind);
369: VecGetOwnershipRange(tao->solution,&xstart,&xend);
371: if (ipmP->nb > 0) {
372: VecCreate(comm,&ipmP->s);
373: VecSetSizes(ipmP->s,PETSC_DECIDE,ipmP->nb);
374: VecSetFromOptions(ipmP->s);
375: VecDuplicate(ipmP->s,&ipmP->ds);
376: VecDuplicate(ipmP->s,&ipmP->rhs_s);
377: VecDuplicate(ipmP->s,&ipmP->complementarity);
378: VecDuplicate(ipmP->s,&ipmP->ci);
380: VecDuplicate(ipmP->s,&ipmP->lamdai);
381: VecDuplicate(ipmP->s,&ipmP->dlamdai);
382: VecDuplicate(ipmP->s,&ipmP->rhs_lamdai);
383: VecDuplicate(ipmP->s,&ipmP->save_lamdai);
385: VecDuplicate(ipmP->s,&ipmP->save_s);
386: VecDuplicate(ipmP->s,&ipmP->rpi);
387: VecDuplicate(ipmP->s,&ipmP->Zero_nb);
388: VecSet(ipmP->Zero_nb,0.0);
389: VecDuplicate(ipmP->s,&ipmP->One_nb);
390: VecSet(ipmP->One_nb,1.0);
391: VecDuplicate(ipmP->s,&ipmP->Inf_nb);
392: VecSet(ipmP->Inf_nb,PETSC_INFINITY);
394: PetscMalloc1(ipmP->nb,&cind);
395: PetscMalloc1(ipmP->mi,&ucind);
396: VecGetOwnershipRange(ipmP->s,&sstart,&send);
398: if (ipmP->mi > 0) {
399: VecGetOwnershipRange(tao->constraints_inequality,&ucstart,&ucend);
400: counter=0;
401: for (i=ucstart;i<ucend;i++) {
402: cind[counter++] = i;
403: }
404: ISCreateGeneral(comm,counter,cind,PETSC_COPY_VALUES,&isuc);
405: ISCreateGeneral(comm,counter,cind,PETSC_COPY_VALUES,&isc);
406: VecScatterCreate(tao->constraints_inequality,isuc,ipmP->ci,isc,&ipmP->ci_scat);
408: ISDestroy(&isuc);
409: ISDestroy(&isc);
410: }
411: /* need to know how may xbound indices are on each process */
412: /* TODO better way */
413: if (ipmP->nxlb) {
414: ISAllGather(ipmP->isxl,&bigxl);
415: ISGetIndices(bigxl,&xli);
416: /* find offsets for this processor */
417: xl_offset = ipmP->mi;
418: for (i=0;i<ipmP->nxlb;i++) {
419: if (xli[i] < xstart) {
420: xl_offset++;
421: } else break;
422: }
423: ISRestoreIndices(bigxl,&xli);
425: ISGetIndices(ipmP->isxl,&xli);
426: ISGetLocalSize(ipmP->isxl,&nloc);
427: for (i=0;i<nloc;i++) {
428: xind[i] = xli[i];
429: cind[i] = xl_offset+i;
430: }
432: ISCreateGeneral(comm,nloc,xind,PETSC_COPY_VALUES,&isx);
433: ISCreateGeneral(comm,nloc,cind,PETSC_COPY_VALUES,&isc);
434: VecScatterCreate(tao->XL,isx,ipmP->ci,isc,&ipmP->xl_scat);
435: ISDestroy(&isx);
436: ISDestroy(&isc);
437: ISDestroy(&bigxl);
438: }
440: if (ipmP->nxub) {
441: ISAllGather(ipmP->isxu,&bigxu);
442: ISGetIndices(bigxu,&xui);
443: /* find offsets for this processor */
444: xu_offset = ipmP->mi + ipmP->nxlb;
445: for (i=0;i<ipmP->nxub;i++) {
446: if (xui[i] < xstart) {
447: xu_offset++;
448: } else break;
449: }
450: ISRestoreIndices(bigxu,&xui);
452: ISGetIndices(ipmP->isxu,&xui);
453: ISGetLocalSize(ipmP->isxu,&nloc);
454: for (i=0;i<nloc;i++) {
455: xind[i] = xui[i];
456: cind[i] = xu_offset+i;
457: }
459: ISCreateGeneral(comm,nloc,xind,PETSC_COPY_VALUES,&isx);
460: ISCreateGeneral(comm,nloc,cind,PETSC_COPY_VALUES,&isc);
461: VecScatterCreate(tao->XU,isx,ipmP->ci,isc,&ipmP->xu_scat);
462: ISDestroy(&isx);
463: ISDestroy(&isc);
464: ISDestroy(&bigxu);
465: }
466: }
467: VecCreate(comm,&ipmP->bigrhs);
468: VecGetType(tao->solution,&vtype);
469: VecSetType(ipmP->bigrhs,vtype);
470: VecSetSizes(ipmP->bigrhs,PETSC_DECIDE,bigsize);
471: VecSetFromOptions(ipmP->bigrhs);
472: VecDuplicate(ipmP->bigrhs,&ipmP->bigstep);
474: /* create scatters for step->x and x->rhs */
475: for (i=xstart;i<xend;i++) {
476: stepind[i-xstart] = i;
477: xind[i-xstart] = i;
478: }
479: ISCreateGeneral(comm,xend-xstart,stepind,PETSC_COPY_VALUES,&sis);
480: ISCreateGeneral(comm,xend-xstart,xind,PETSC_COPY_VALUES,&is1);
481: VecScatterCreate(ipmP->bigstep,sis,tao->solution,is1,&ipmP->step1);
482: VecScatterCreate(tao->solution,is1,ipmP->bigrhs,sis,&ipmP->rhs1);
483: ISDestroy(&sis);
484: ISDestroy(&is1);
486: if (ipmP->nb > 0) {
487: for (i=sstart;i<send;i++) {
488: stepind[i-sstart] = i+ipmP->n;
489: cind[i-sstart] = i;
490: }
491: ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis);
492: ISCreateGeneral(comm,send-sstart,cind,PETSC_COPY_VALUES,&is1);
493: VecScatterCreate(ipmP->bigstep,sis,ipmP->s,is1,&ipmP->step2);
494: ISDestroy(&sis);
496: for (i=sstart;i<send;i++) {
497: stepind[i-sstart] = i+ipmP->n+ipmP->me;
498: cind[i-sstart] = i;
499: }
500: ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis);
501: VecScatterCreate(ipmP->s,is1,ipmP->bigrhs,sis,&ipmP->rhs3);
502: ISDestroy(&sis);
503: ISDestroy(&is1);
504: }
506: if (ipmP->me > 0) {
507: VecGetOwnershipRange(tao->constraints_equality,&ucestart,&uceend);
508: for (i=ucestart;i<uceend;i++) {
509: stepind[i-ucestart] = i + ipmP->n+ipmP->nb;
510: uceind[i-ucestart] = i;
511: }
513: ISCreateGeneral(comm,uceend-ucestart,stepind,PETSC_COPY_VALUES,&sis);
514: ISCreateGeneral(comm,uceend-ucestart,uceind,PETSC_COPY_VALUES,&is1);
515: VecScatterCreate(ipmP->bigstep,sis,tao->constraints_equality,is1,&ipmP->step3);
516: ISDestroy(&sis);
518: for (i=ucestart;i<uceend;i++) {
519: stepind[i-ucestart] = i + ipmP->n;
520: }
522: ISCreateGeneral(comm,uceend-ucestart,stepind,PETSC_COPY_VALUES,&sis);
523: VecScatterCreate(tao->constraints_equality,is1,ipmP->bigrhs,sis,&ipmP->rhs2);
524: ISDestroy(&sis);
525: ISDestroy(&is1);
526: }
528: if (ipmP->nb > 0) {
529: for (i=sstart;i<send;i++) {
530: stepind[i-sstart] = i + ipmP->n + ipmP->nb + ipmP->me;
531: cind[i-sstart] = i;
532: }
533: ISCreateGeneral(comm,send-sstart,cind,PETSC_COPY_VALUES,&is1);
534: ISCreateGeneral(comm,send-sstart,stepind,PETSC_COPY_VALUES,&sis);
535: VecScatterCreate(ipmP->bigstep,sis,ipmP->s,is1,&ipmP->step4);
536: VecScatterCreate(ipmP->s,is1,ipmP->bigrhs,sis,&ipmP->rhs4);
537: ISDestroy(&sis);
538: ISDestroy(&is1);
539: }
541: PetscFree(stepind);
542: PetscFree(cind);
543: PetscFree(ucind);
544: PetscFree(uceind);
545: PetscFree(xind);
546: return(0);
547: }
551: static PetscErrorCode TaoDestroy_IPM(Tao tao)
552: {
553: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
557: VecDestroy(&ipmP->rd);
558: VecDestroy(&ipmP->rpe);
559: VecDestroy(&ipmP->rpi);
560: VecDestroy(&ipmP->work);
561: VecDestroy(&ipmP->lamdae);
562: VecDestroy(&ipmP->lamdai);
563: VecDestroy(&ipmP->s);
564: VecDestroy(&ipmP->ds);
565: VecDestroy(&ipmP->ci);
567: VecDestroy(&ipmP->rhs_x);
568: VecDestroy(&ipmP->rhs_lamdae);
569: VecDestroy(&ipmP->rhs_lamdai);
570: VecDestroy(&ipmP->rhs_s);
572: VecDestroy(&ipmP->save_x);
573: VecDestroy(&ipmP->save_lamdae);
574: VecDestroy(&ipmP->save_lamdai);
575: VecDestroy(&ipmP->save_s);
577: VecScatterDestroy(&ipmP->step1);
578: VecScatterDestroy(&ipmP->step2);
579: VecScatterDestroy(&ipmP->step3);
580: VecScatterDestroy(&ipmP->step4);
582: VecScatterDestroy(&ipmP->rhs1);
583: VecScatterDestroy(&ipmP->rhs2);
584: VecScatterDestroy(&ipmP->rhs3);
585: VecScatterDestroy(&ipmP->rhs4);
587: VecScatterDestroy(&ipmP->ci_scat);
588: VecScatterDestroy(&ipmP->xl_scat);
589: VecScatterDestroy(&ipmP->xu_scat);
591: VecDestroy(&ipmP->dlamdai);
592: VecDestroy(&ipmP->dlamdae);
593: VecDestroy(&ipmP->Zero_nb);
594: VecDestroy(&ipmP->One_nb);
595: VecDestroy(&ipmP->Inf_nb);
596: VecDestroy(&ipmP->complementarity);
598: VecDestroy(&ipmP->bigrhs);
599: VecDestroy(&ipmP->bigstep);
600: MatDestroy(&ipmP->Ai);
601: MatDestroy(&ipmP->K);
602: ISDestroy(&ipmP->isxu);
603: ISDestroy(&ipmP->isxl);
604: PetscFree(tao->data);
605: return(0);
606: }
610: static PetscErrorCode TaoSetFromOptions_IPM(Tao tao)
611: {
612: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
614: PetscBool flg;
617: PetscOptionsHead("IPM method for constrained optimization");
618: PetscOptionsBool("-ipm_monitorkkt","monitor kkt status",NULL,ipmP->monitorkkt,&ipmP->monitorkkt,&flg);
619: PetscOptionsReal("-ipm_pushs","parameter to push initial slack variables away from bounds",NULL,ipmP->pushs,&ipmP->pushs,&flg);
620: PetscOptionsReal("-ipm_pushnu","parameter to push initial (inequality) dual variables away from bounds",NULL,ipmP->pushnu,&ipmP->pushnu,&flg);
621: PetscOptionsTail();
622: ierr =KSPSetFromOptions(tao->ksp);
623: return(0);
624: }
628: static PetscErrorCode TaoView_IPM(Tao tao, PetscViewer viewer)
629: {
630: return 0;
631: }
633: /* IPMObjectiveAndGradient()
634: f = d'x + 0.5 * x' * H * x
635: rd = H*x + d + Ae'*lame - Ai'*lami
636: rpe = Ae*x - be
637: rpi = Ai*x - yi - bi
638: mu = yi' * lami/mi;
639: com = yi.*lami
641: phi = ||rd|| + ||rpe|| + ||rpi|| + ||com||
642: */
643: /*
646: static PetscErrorCode IPMObjective(TaoLineSearch ls, Vec X, PetscReal *f, void *tptr)
647: {
648: Tao tao = (Tao)tptr;
649: TAO_IPM *ipmP = (TAO_IPM*)tao->data;
652: IPMComputeKKT(tao);
653: *f = ipmP->phi;
654: return(0);
655: }
656: */
658: /*
659: f = d'x + 0.5 * x' * H * x
660: rd = H*x + d + Ae'*lame - Ai'*lami
661: Ai = jac_ineq
662: I (w/lb)
663: -I (w/ub)
665: rpe = ce
666: rpi = ci - s;
667: com = s.*lami
668: mu = yi' * lami/mi;
670: phi = ||rd|| + ||rpe|| + ||rpi|| + ||com||
671: */
674: static PetscErrorCode IPMComputeKKT(Tao tao)
675: {
676: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
677: PetscScalar norm;
681: VecCopy(tao->gradient,ipmP->rd);
683: if (ipmP->me > 0) {
684: /* rd = gradient + Ae'*lamdae */
685: MatMultTranspose(tao->jacobian_equality,ipmP->lamdae,ipmP->work);
686: VecAXPY(ipmP->rd, 1.0, ipmP->work);
688: #if defined DEBUG_KKT
689: PetscPrintf(PETSC_COMM_WORLD,"\nAe.lamdae\n");
690: VecView(ipmP->work,0);
691: #endif
692: /* rpe = ce(x) */
693: VecCopy(tao->constraints_equality,ipmP->rpe);
694: }
695: if (ipmP->nb > 0) {
696: /* rd = rd - Ai'*lamdai */
697: MatMultTranspose(ipmP->Ai,ipmP->lamdai,ipmP->work);
698: VecAXPY(ipmP->rd, -1.0, ipmP->work);
699: #if defined DEBUG_KKT
700: PetscPrintf(PETSC_COMM_WORLD,"\nAi\n");
701: MatView(ipmP->Ai,0);
702: PetscPrintf(PETSC_COMM_WORLD,"\nAi.lamdai\n");
703: VecView(ipmP->work,0);
704: #endif
705: /* rpi = cin - s */
706: VecCopy(ipmP->ci,ipmP->rpi);
707: VecAXPY(ipmP->rpi, -1.0, ipmP->s);
709: /* com = s .* lami */
710: VecPointwiseMult(ipmP->complementarity, ipmP->s,ipmP->lamdai);
711: }
712: /* phi = ||rd; rpe; rpi; com|| */
713: VecDot(ipmP->rd,ipmP->rd,&norm);
714: ipmP->phi = norm;
715: if (ipmP->me > 0 ) {
716: VecDot(ipmP->rpe,ipmP->rpe,&norm);
717: ipmP->phi += norm;
718: }
719: if (ipmP->nb > 0) {
720: VecDot(ipmP->rpi,ipmP->rpi,&norm);
721: ipmP->phi += norm;
722: VecDot(ipmP->complementarity,ipmP->complementarity,&norm);
723: ipmP->phi += norm;
724: /* mu = s'*lami/nb */
725: VecDot(ipmP->s,ipmP->lamdai,&ipmP->mu);
726: ipmP->mu /= ipmP->nb;
727: } else {
728: ipmP->mu = 1.0;
729: }
731: ipmP->phi = PetscSqrtScalar(ipmP->phi);
732: #if defined DEBUG_KKT
733: if (ipmP->monitorkkt) {
734: PetscPrintf(PETSC_COMM_WORLD,"obj=%g,\tphi = %g,\tmu=%g\talpha1=%g\talpha2=%g\n",(double)ipmP->kkt_f,(double)ipmP->phi,(double)ipmP->mu,(double)ipmP->alpha1,(double)ipmP->alpha2);
735: }
736: PetscPrintf(PETSC_COMM_WORLD,"\ngradient\n");
737: VecView(tao->gradient,0);
738: PetscPrintf(PETSC_COMM_WORLD,"\nrd\n");
739: VecView(ipmP->rd,0);
740: PetscPrintf(PETSC_COMM_WORLD,"\nrpe\n");
741: VecView(ipmP->rpe,0);
742: PetscPrintf(PETSC_COMM_WORLD,"\nrpi\n");
743: VecView(ipmP->rpi,0);
744: PetscPrintf(PETSC_COMM_WORLD,"\ncomplementarity\n");
745: VecView(ipmP->complementarity,0);
746: #endif
747: return(0);
748: }
752: /* evaluate user info at current point */
753: PetscErrorCode IPMEvaluate(Tao tao)
754: {
755: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
759: TaoComputeObjectiveAndGradient(tao,tao->solution,&ipmP->kkt_f,tao->gradient);
760: TaoComputeHessian(tao,tao->solution,&tao->hessian,&tao->hessian_pre,&ipmP->Hflag);
761: if (ipmP->me > 0) {
762: TaoComputeEqualityConstraints(tao,tao->solution,tao->constraints_equality);
763: TaoComputeJacobianEquality(tao,tao->solution,&tao->jacobian_equality,&tao->jacobian_equality_pre,&ipmP->Aiflag);
764: }
765: if (ipmP->mi > 0) {
766: TaoComputeInequalityConstraints(tao,tao->solution,tao->constraints_inequality);
767: TaoComputeJacobianInequality(tao,tao->solution,&tao->jacobian_inequality,&tao->jacobian_inequality_pre,&ipmP->Aeflag);
768: }
769: if (ipmP->nb > 0) {
770: /* Ai' = jac_ineq | I (w/lb) | -I (w/ub) */
771: IPMUpdateAi(tao);
772: }
773: return(0);
774: }
778: /* Push initial point away from bounds */
779: PetscErrorCode IPMPushInitialPoint(Tao tao)
780: {
781: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
785: TaoComputeVariableBounds(tao);
786: if (tao->XL && tao->XU) {
787: VecMedian(tao->XL, tao->solution, tao->XU, tao->solution);
788: }
789: if (ipmP->nb > 0) {
790: VecSet(ipmP->s,ipmP->pushs);
791: VecSet(ipmP->lamdai,ipmP->pushnu);
792: if (ipmP->mi > 0) {
793: VecSet(tao->DI,ipmP->pushnu);
794: }
795: }
796: if (ipmP->me > 0) {
797: VecSet(tao->DE,1.0);
798: VecSet(ipmP->lamdae,1.0);
799: }
800: return(0);
801: }
805: PetscErrorCode IPMUpdateAi(Tao tao)
806: {
807: /* Ai = Ji
808: I (w/lb)
809: -I (w/ub) */
811: /* Ci = user->ci
812: Xi - lb (w/lb)
813: -Xi + ub (w/ub) */
815: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
816: MPI_Comm comm;
817: PetscInt i;
818: PetscScalar newval;
819: PetscInt newrow,newcol,ncols;
820: const PetscScalar *vals;
821: const PetscInt *cols;
822: PetscInt astart,aend,jstart,jend;
823: PetscInt *nonzeros;
824: PetscInt r2,r3,r4;
825: PetscMPIInt size;
826: PetscErrorCode ierr;
829: r2 = ipmP->mi;
830: r3 = r2 + ipmP->nxlb;
831: r4 = r3 + ipmP->nxub;
833: if (!ipmP->nb) return(0);
835: /* Create Ai matrix if it doesn't exist yet */
836: if (!ipmP->Ai) {
837: comm = ((PetscObject)(tao->solution))->comm;
838: PetscMalloc1(ipmP->nb,&nonzeros);
839: MPI_Comm_size(comm,&size);
840: if (size == 1) {
841: for (i=0;i<ipmP->mi;i++) {
842: MatGetRow(tao->jacobian_inequality,i,&ncols,NULL,NULL);
843: nonzeros[i] = ncols;
844: MatRestoreRow(tao->jacobian_inequality,i,&ncols,NULL,NULL);
845: }
846: for (i=r2;i<r4;i++) {
847: nonzeros[i] = 1;
848: }
849: }
850: MatCreate(comm,&ipmP->Ai);
851: MatSetType(ipmP->Ai,MATAIJ);
852: MatSetSizes(ipmP->Ai,PETSC_DECIDE,PETSC_DECIDE,ipmP->nb,ipmP->n);
853: MatSetFromOptions(ipmP->Ai);
854: MatMPIAIJSetPreallocation(ipmP->Ai,ipmP->nb,NULL,ipmP->nb,NULL);
855: MatSeqAIJSetPreallocation(ipmP->Ai,PETSC_DEFAULT,nonzeros);
856: if (size ==1) {
857: PetscFree(nonzeros);
858: }
859: }
861: /* Copy values from user jacobian to Ai */
862: MatGetOwnershipRange(ipmP->Ai,&astart,&aend);
864: /* Ai w/lb */
865: if (ipmP->mi) {
866: MatZeroEntries(ipmP->Ai);
867: MatGetOwnershipRange(tao->jacobian_inequality,&jstart,&jend);
868: for (i=jstart;i<jend;i++) {
869: MatGetRow(tao->jacobian_inequality,i,&ncols,&cols,&vals);
870: newrow = i;
871: MatSetValues(ipmP->Ai,1,&newrow,ncols,cols,vals,INSERT_VALUES);
872: MatRestoreRow(tao->jacobian_inequality,i,&ncols,&cols,&vals);
873: }
874: }
876: /* I w/ xlb */
877: if (ipmP->nxlb) {
878: for (i=0;i<ipmP->nxlb;i++) {
879: if (i>=astart && i<aend) {
880: newrow = i+r2;
881: newcol = i;
882: newval = 1.0;
883: MatSetValues(ipmP->Ai,1,&newrow,1,&newcol,&newval,INSERT_VALUES);
884: }
885: }
886: }
887: if (ipmP->nxub) {
888: /* I w/ xub */
889: for (i=0;i<ipmP->nxub;i++) {
890: if (i>=astart && i<aend) {
891: newrow = i+r3;
892: newcol = i;
893: newval = -1.0;
894: MatSetValues(ipmP->Ai,1,&newrow,1,&newcol,&newval,INSERT_VALUES);
895: }
896: }
897: }
899: MatAssemblyBegin(ipmP->Ai,MAT_FINAL_ASSEMBLY);
900: MatAssemblyEnd(ipmP->Ai,MAT_FINAL_ASSEMBLY);
901: CHKMEMQ;
903: VecSet(ipmP->ci,0.0);
905: /* user ci */
906: if (ipmP->mi > 0) {
907: VecScatterBegin(ipmP->ci_scat,tao->constraints_inequality,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
908: VecScatterEnd(ipmP->ci_scat,tao->constraints_inequality,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
909: }
910: if (!ipmP->work){
911: VecDuplicate(tao->solution,&ipmP->work);
912: }
913: VecCopy(tao->solution,ipmP->work);
914: if (tao->XL) {
915: VecAXPY(ipmP->work,-1.0,tao->XL);
917: /* lower bounds on variables */
918: if (ipmP->nxlb > 0) {
919: VecScatterBegin(ipmP->xl_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
920: VecScatterEnd(ipmP->xl_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
921: }
922: }
923: if (tao->XU) {
924: /* upper bounds on variables */
925: VecCopy(tao->solution,ipmP->work);
926: VecScale(ipmP->work,-1.0);
927: VecAXPY(ipmP->work,1.0,tao->XU);
928: if (ipmP->nxub > 0) {
929: VecScatterBegin(ipmP->xu_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
930: VecScatterEnd(ipmP->xu_scat,ipmP->work,ipmP->ci,INSERT_VALUES,SCATTER_FORWARD);
931: }
932: }
933: return(0);
934: }
938: /* create K = [ Hlag , 0 , Ae', -Ai'];
939: [Ae , 0, 0 , 0];
940: [Ai ,-I, 0 , 0];
941: [ 0 , S , 0, Y ]; */
942: PetscErrorCode IPMUpdateK(Tao tao)
943: {
944: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
945: MPI_Comm comm;
946: PetscMPIInt size;
947: PetscErrorCode ierr;
948: PetscInt i,j,row;
949: PetscInt ncols,newcol,newcols[2],newrow;
950: const PetscInt *cols;
951: const PetscReal *vals;
952: PetscReal *l,*y;
953: PetscReal *newvals;
954: PetscReal newval;
955: PetscInt subsize;
956: const PetscInt *indices;
957: PetscInt *nonzeros,*d_nonzeros,*o_nonzeros;
958: PetscInt bigsize;
959: PetscInt r1,r2,r3;
960: PetscInt c1,c2,c3;
961: PetscInt klocalsize;
962: PetscInt hstart,hend,kstart,kend;
963: PetscInt aistart,aiend,aestart,aeend;
964: PetscInt sstart,send;
967: comm = ((PetscObject)(tao->solution))->comm;
968: MPI_Comm_size(comm,&size);
969: IPMUpdateAi(tao);
970: #if defined DEBUG_K
971: PetscPrintf(PETSC_COMM_WORLD,"H\n"); MatView(tao->hessian,0);
972: if (ipmP->nb) {
973: PetscPrintf(PETSC_COMM_WORLD,"Ai\n"); MatView(ipmP->Ai,0);
974: }
975: if (ipmP->me) {
976: PetscPrintf(PETSC_COMM_WORLD,"Ae\n"); MatView(tao->jacobian_equality,0);
977: }
978: #endif
979: /* allocate workspace */
980: subsize = PetscMax(ipmP->n,ipmP->nb);
981: subsize = PetscMax(ipmP->me,subsize);
982: subsize = PetscMax(2,subsize);
983: PetscMalloc1(subsize,&indices);
984: PetscMalloc1(subsize,&newvals);
986: r1 = c1 = ipmP->n;
987: r2 = r1 + ipmP->me; c2 = c1 + ipmP->nb;
988: r3 = c3 = r2 + ipmP->nb;
990: bigsize = ipmP->n+2*ipmP->nb+ipmP->me;
991: VecGetOwnershipRange(ipmP->bigrhs,&kstart,&kend);
992: MatGetOwnershipRange(tao->hessian,&hstart,&hend);
993: klocalsize = kend-kstart;
994: if (!ipmP->K) {
995: if (size == 1) {
996: PetscMalloc1((kend-kstart),&nonzeros);
997: for (i=0;i<bigsize;i++) {
998: if (i<r1) {
999: MatGetRow(tao->hessian,i,&ncols,NULL,NULL);
1000: nonzeros[i] = ncols;
1001: MatRestoreRow(tao->hessian,i,&ncols,NULL,NULL);
1002: nonzeros[i] += ipmP->me+ipmP->nb;
1003: } else if (i<r2) {
1004: nonzeros[i-kstart] = ipmP->n;
1005: } else if (i<r3) {
1006: nonzeros[i-kstart] = ipmP->n+1;
1007: } else if (i<bigsize) {
1008: nonzeros[i-kstart] = 2;
1009: }
1010: }
1011: MatCreate(comm,&ipmP->K);
1012: MatSetType(ipmP->K,MATSEQAIJ);
1013: MatSetSizes(ipmP->K,klocalsize,klocalsize,PETSC_DETERMINE,PETSC_DETERMINE);
1014: MatSeqAIJSetPreallocation(ipmP->K,0,nonzeros);
1015: MatSetFromOptions(ipmP->K);
1016: PetscFree(nonzeros);
1017: } else {
1018: PetscMalloc1((kend-kstart),&d_nonzeros);
1019: PetscMalloc1((kend-kstart),&o_nonzeros);
1020: for (i=kstart;i<kend;i++) {
1021: if (i<r1) {
1022: /* TODO fix preallocation for mpi mats */
1023: d_nonzeros[i-kstart] = PetscMin(ipmP->n+ipmP->me+ipmP->nb,kend-kstart);
1024: o_nonzeros[i-kstart] = PetscMin(ipmP->n+ipmP->me+ipmP->nb,bigsize-(kend-kstart));
1025: } else if (i<r2) {
1026: d_nonzeros[i-kstart] = PetscMin(ipmP->n,kend-kstart);
1027: o_nonzeros[i-kstart] = PetscMin(ipmP->n,bigsize-(kend-kstart));
1028: } else if (i<r3) {
1029: d_nonzeros[i-kstart] = PetscMin(ipmP->n+2,kend-kstart);
1030: o_nonzeros[i-kstart] = PetscMin(ipmP->n+2,bigsize-(kend-kstart));
1031: } else {
1032: d_nonzeros[i-kstart] = PetscMin(2,kend-kstart);
1033: o_nonzeros[i-kstart] = PetscMin(2,bigsize-(kend-kstart));
1034: }
1035: }
1036: MatCreate(comm,&ipmP->K);
1037: MatSetType(ipmP->K,MATMPIAIJ);
1038: MatSetSizes(ipmP->K,klocalsize,klocalsize,PETSC_DETERMINE,PETSC_DETERMINE);
1039: MatMPIAIJSetPreallocation(ipmP->K,0,d_nonzeros,0,o_nonzeros);
1040: PetscFree(d_nonzeros);
1041: PetscFree(o_nonzeros);
1042: MatSetFromOptions(ipmP->K);
1043: }
1044: }
1046: MatZeroEntries(ipmP->K);
1047: /* Copy H */
1048: for (i=hstart;i<hend;i++) {
1049: MatGetRow(tao->hessian,i,&ncols,&cols,&vals);
1050: if (ncols > 0) {
1051: MatSetValues(ipmP->K,1,&i,ncols,cols,vals,INSERT_VALUES);
1052: }
1053: MatRestoreRow(tao->hessian,i,&ncols,&cols,&vals);
1054: }
1056: /* Copy Ae and Ae' */
1057: if (ipmP->me > 0) {
1058: MatGetOwnershipRange(tao->jacobian_equality,&aestart,&aeend);
1059: for (i=aestart;i<aeend;i++) {
1060: MatGetRow(tao->jacobian_equality,i,&ncols,&cols,&vals);
1061: if (ncols > 0) {
1062: /*Ae*/
1063: row = i+r1;
1064: MatSetValues(ipmP->K,1,&row,ncols,cols,vals,INSERT_VALUES);
1065: /*Ae'*/
1066: for (j=0;j<ncols;j++) {
1067: newcol = i + c2;
1068: newrow = cols[j];
1069: newval = vals[j];
1070: MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES);
1071: }
1072: }
1073: MatRestoreRow(tao->jacobian_equality,i,&ncols,&cols,&vals);
1074: }
1075: }
1077: if (ipmP->nb > 0) {
1078: MatGetOwnershipRange(ipmP->Ai,&aistart,&aiend);
1079: /* Copy Ai,and Ai' */
1080: for (i=aistart;i<aiend;i++) {
1081: row = i+r2;
1082: MatGetRow(ipmP->Ai,i,&ncols,&cols,&vals);
1083: if (ncols > 0) {
1084: /*Ai*/
1085: MatSetValues(ipmP->K,1,&row,ncols,cols,vals,INSERT_VALUES);
1086: /*-Ai'*/
1087: for (j=0;j<ncols;j++) {
1088: newcol = i + c3;
1089: newrow = cols[j];
1090: newval = -vals[j];
1091: MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES);
1092: }
1093: }
1094: MatRestoreRow(ipmP->Ai,i,&ncols,&cols,&vals);
1095: }
1097: /* -I */
1098: for (i=kstart;i<kend;i++) {
1099: if (i>=r2 && i<r3) {
1100: newrow = i;
1101: newcol = i-r2+c1;
1102: newval = -1.0;
1103: MatSetValues(ipmP->K,1,&newrow,1,&newcol,&newval,INSERT_VALUES);
1104: }
1105: }
1107: /* Copy L,Y */
1108: VecGetOwnershipRange(ipmP->s,&sstart,&send);
1109: VecGetArray(ipmP->lamdai,&l);
1110: VecGetArray(ipmP->s,&y);
1112: for (i=sstart;i<send;i++) {
1113: newcols[0] = c1+i;
1114: newcols[1] = c3+i;
1115: newvals[0] = l[i-sstart];
1116: newvals[1] = y[i-sstart];
1117: newrow = r3+i;
1118: MatSetValues(ipmP->K,1,&newrow,2,newcols,newvals,INSERT_VALUES);
1119: }
1121: VecRestoreArray(ipmP->lamdai,&l);
1122: VecRestoreArray(ipmP->s,&y);
1123: }
1125: PetscFree(indices);
1126: PetscFree(newvals);
1127: MatAssemblyBegin(ipmP->K,MAT_FINAL_ASSEMBLY);
1128: MatAssemblyEnd(ipmP->K,MAT_FINAL_ASSEMBLY);
1129: #if defined DEBUG_K
1130: PetscPrintf(PETSC_COMM_WORLD,"K\n"); MatView(ipmP->K,0);
1131: #endif
1132: return(0);
1133: }
1137: PetscErrorCode IPMGatherRHS(Tao tao,Vec RHS,Vec X1,Vec X2,Vec X3,Vec X4)
1138: {
1139: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
1143: /* rhs = [x1 (n)
1144: x2 (me)
1145: x3 (nb)
1146: x4 (nb)] */
1147: if (X1) {
1148: VecScatterBegin(ipmP->rhs1,X1,RHS,INSERT_VALUES,SCATTER_FORWARD);
1149: VecScatterEnd(ipmP->rhs1,X1,RHS,INSERT_VALUES,SCATTER_FORWARD);
1150: }
1151: if (ipmP->me > 0 && X2) {
1152: VecScatterBegin(ipmP->rhs2,X2,RHS,INSERT_VALUES,SCATTER_FORWARD);
1153: VecScatterEnd(ipmP->rhs2,X2,RHS,INSERT_VALUES,SCATTER_FORWARD);
1154: }
1155: if (ipmP->nb > 0) {
1156: if (X3) {
1157: VecScatterBegin(ipmP->rhs3,X3,RHS,INSERT_VALUES,SCATTER_FORWARD);
1158: VecScatterEnd(ipmP->rhs3,X3,RHS,INSERT_VALUES,SCATTER_FORWARD);
1159: }
1160: if (X4) {
1161: VecScatterBegin(ipmP->rhs4,X4,RHS,INSERT_VALUES,SCATTER_FORWARD);
1162: VecScatterEnd(ipmP->rhs4,X4,RHS,INSERT_VALUES,SCATTER_FORWARD);
1163: }
1164: }
1165: #if defined(DEBUG_SCATTER)
1166: PetscPrintf(PETSC_COMM_WORLD,"X1-X4\n");
1167: if (X1) {VecView(X1,0);}
1168: if (X2) {VecView(X2,0);}
1169: if (X3) {VecView(X3,0);}
1170: if (X4) {VecView(X4,0);}
1171: PetscPrintf(PETSC_COMM_WORLD,"RHS\n");
1172: VecView(RHS,0);
1173: #endif
1174: return(0);
1175: }
1179: PetscErrorCode IPMScatterStep(Tao tao, Vec STEP, Vec X1, Vec X2, Vec X3, Vec X4)
1180: {
1181: TAO_IPM *ipmP = (TAO_IPM *)tao->data;
1185: CHKMEMQ;
1186: /* [x1 (n)
1187: x2 (nb) may be 0
1188: x3 (me) may be 0
1189: x4 (nb) may be 0 */
1190: if (X1) {
1191: VecScatterBegin(ipmP->step1,STEP,X1,INSERT_VALUES,SCATTER_FORWARD);
1192: VecScatterEnd(ipmP->step1,STEP,X1,INSERT_VALUES,SCATTER_FORWARD);
1193: }
1194: if (X2 && ipmP->nb > 0) {
1195: VecScatterBegin(ipmP->step2,STEP,X2,INSERT_VALUES,SCATTER_FORWARD);
1196: VecScatterEnd(ipmP->step2,STEP,X2,INSERT_VALUES,SCATTER_FORWARD);
1197: }
1198: if (X3 && ipmP->me > 0) {
1199: VecScatterBegin(ipmP->step3,STEP,X3,INSERT_VALUES,SCATTER_FORWARD);
1200: VecScatterEnd(ipmP->step3,STEP,X3,INSERT_VALUES,SCATTER_FORWARD);
1201: }
1202: if (X4 && ipmP->nb > 0) {
1203: VecScatterBegin(ipmP->step4,STEP,X4,INSERT_VALUES,SCATTER_FORWARD);
1204: VecScatterEnd(ipmP->step4,STEP,X4,INSERT_VALUES,SCATTER_FORWARD);
1205: }
1206: CHKMEMQ;
1207: #if defined(DEBUG_SCATTER)
1208: PetscPrintf(PETSC_COMM_WORLD,"Step\n");
1209: VecView(STEP,0);
1210: PetscPrintf(PETSC_COMM_WORLD,"X1-X4\n");
1211: if (X1) {VecView(X1,0);}
1212: if (X2) {VecView(X2,0);}
1213: if (X3) {VecView(X3,0);}
1214: if (X4) {VecView(X4,0);}
1215: #endif
1216: return(0);
1217: }
1219: EXTERN_C_BEGIN
1222: PetscErrorCode TaoCreate_IPM(Tao tao)
1223: {
1224: TAO_IPM *ipmP;
1228: tao->ops->setup = TaoSetup_IPM;
1229: tao->ops->solve = TaoSolve_IPM;
1230: tao->ops->view = TaoView_IPM;
1231: tao->ops->setfromoptions = TaoSetFromOptions_IPM;
1232: tao->ops->destroy = TaoDestroy_IPM;
1233: /* tao->ops->computedual = TaoComputeDual_IPM; */
1235: PetscNewLog(tao,&ipmP);
1236: tao->data = (void*)ipmP;
1237: tao->max_it = 200;
1238: tao->max_funcs = 500;
1239: tao->fatol = 1e-4;
1240: tao->frtol = 1e-4;
1241: ipmP->dec = 10000; /* line search critera */
1242: ipmP->taumin = 0.995;
1243: ipmP->monitorkkt = PETSC_FALSE;
1244: ipmP->pushs = 100;
1245: ipmP->pushnu = 100;
1246: KSPCreate(((PetscObject)tao)->comm, &tao->ksp);
1247: return(0);
1248: }
1249: EXTERN_C_END