Actual source code: ipm.c

petsc-dev 2014-02-02
Report Typos and Errors
  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