Date: 2022-03-04T17:39:51+00:00

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: }