Actual source code: isutil.c
petsc-3.10.5 2019-03-28
Report Typos and Errors

      1:  #include <petsctao.h>
      2:  #include <petsc/private/vecimpl.h>
      3:  #include <petsc/private/taoimpl.h>
      4:  #include <../src/tao/matrix/submatfree.h>

      6: /*@C
      7:   TaoVecGetSubVec - Gets a subvector using the IS

      9:   Input Parameters:
     10: + vfull - the full matrix
     11: . is - the index set for the subvector
     12: . reduced_type - the method TAO is using for subsetting (TAO_SUBSET_SUBVEC, TAO_SUBSET_MASK,  TAO_SUBSET_MATRIXFREE)
     13: - maskvalue - the value to set the unused vector elements to (for TAO_SUBSET_MASK or TAO_SUBSET_MATRIXFREE)

     15:   Output Parameters:
     16: . vreduced - the subvector

     18:   Notes:
     19:   maskvalue should usually be 0.0, unless a pointwise divide will be used.

     21: @*/
     22: PetscErrorCode TaoVecGetSubVec(Vec vfull, IS is, TaoSubsetType reduced_type, PetscReal maskvalue, Vec *vreduced)
     23: {
     25:   PetscInt       nfull,nreduced,nreduced_local,rlow,rhigh,flow,fhigh;
     26:   PetscInt       i,nlocal;
     27:   PetscReal      *fv,*rv;
     28:   const PetscInt *s;
     29:   IS             ident;
     30:   VecType        vtype;
     31:   VecScatter     scatter;
     32:   MPI_Comm       comm;

     38:   VecGetSize(vfull, &nfull);
     39:   ISGetSize(is, &nreduced);

     41:   if (nreduced == nfull) {
     42:     VecDestroy(vreduced);
     43:     VecDuplicate(vfull,vreduced);
     44:     VecCopy(vfull,*vreduced);
     45:   } else {
     46:     switch (reduced_type) {
     47:     case TAO_SUBSET_SUBVEC:
     48:       VecGetType(vfull,&vtype);
     49:       VecGetOwnershipRange(vfull,&flow,&fhigh);
     50:       ISGetLocalSize(is,&nreduced_local);
     51:       PetscObjectGetComm((PetscObject)vfull,&comm);
     52:       if (*vreduced) {
     53:         VecDestroy(vreduced);
     54:       }
     55:       VecCreate(comm,vreduced);
     56:       VecSetType(*vreduced,vtype);

     58:       VecSetSizes(*vreduced,nreduced_local,nreduced);
     59:       VecGetOwnershipRange(*vreduced,&rlow,&rhigh);
     60:       ISCreateStride(comm,nreduced_local,rlow,1,&ident);
     61:       VecScatterCreate(vfull,is,*vreduced,ident,&scatter);
     62:       VecScatterBegin(scatter,vfull,*vreduced,INSERT_VALUES,SCATTER_FORWARD);
     63:       VecScatterEnd(scatter,vfull,*vreduced,INSERT_VALUES,SCATTER_FORWARD);
     64:       VecScatterDestroy(&scatter);
     65:       ISDestroy(&ident);
     66:       break;

     68:     case TAO_SUBSET_MASK:
     69:     case TAO_SUBSET_MATRIXFREE:
     70:       /* vr[i] = vf[i]   if i in is
     71:        vr[i] = 0       otherwise */
     72:       if (!*vreduced) {
     73:         VecDuplicate(vfull,vreduced);
     74:       }

     76:       VecSet(*vreduced,maskvalue);
     77:       ISGetLocalSize(is,&nlocal);
     78:       VecGetOwnershipRange(vfull,&flow,&fhigh);
     79:       VecGetArray(vfull,&fv);
     80:       VecGetArray(*vreduced,&rv);
     81:       ISGetIndices(is,&s);
     82:       if (nlocal > (fhigh-flow)) SETERRQ2(PETSC_COMM_WORLD,1,"IS local size %d > Vec local size %d",nlocal,fhigh-flow);
     83:       for (i=0;i<nlocal;++i) {
     84:         rv[s[i]-flow] = fv[s[i]-flow];
     85:       }
     86:       ISRestoreIndices(is,&s);
     87:       VecRestoreArray(vfull,&fv);
     88:       VecRestoreArray(*vreduced,&rv);
     89:       break;
     90:     }
     91:   }
     92:   return(0);
     93: }

     95: /*@C
     96:   TaoMatGetSubMat - Gets a submatrix using the IS

     98:   Input Parameters:
     99: + M - the full matrix (n x n)
    100: . is - the index set for the submatrix (both row and column index sets need to be the same)
    101: . v1 - work vector of dimension n, needed for TAO_SUBSET_MASK option
    102: - subset_type - the method TAO is using for subsetting (TAO_SUBSET_SUBVEC, TAO_SUBSET_MASK,
    103:   TAO_SUBSET_MATRIXFREE)

    105:   Output Parameters:
    106: . Msub - the submatrix
    107: @*/
    108: PetscErrorCode TaoMatGetSubMat(Mat M, IS is, Vec v1, TaoSubsetType subset_type, Mat *Msub)
    109: {
    111:   IS             iscomp;
    112:   PetscBool      flg = PETSC_TRUE;

    117:   MatDestroy(Msub);
    118:   switch (subset_type) {
    119:   case TAO_SUBSET_SUBVEC:
    120:     MatCreateSubMatrix(M, is, is, MAT_INITIAL_MATRIX, Msub);
    121:     break;

    123:   case TAO_SUBSET_MASK:
    124:     /* Get Reduced Hessian
    125:      Msub[i,j] = M[i,j] if i,j in Free_Local or i==j
    126:      Msub[i,j] = 0      if i!=j and i or j not in Free_Local
    127:      */
    128:     PetscOptionsBegin(PetscObjectComm((PetscObject)M),NULL,NULL,NULL);
    129:     PetscOptionsBool("-overwrite_hessian","modify the existing hessian matrix when computing submatrices","TaoSubsetType",flg,&flg,NULL);
    130:     PetscOptionsEnd();
    131:     if (flg) {
    132:       MatDuplicate(M, MAT_COPY_VALUES, Msub);
    133:     } else {
    134:       /* Act on hessian directly (default) */
    135:       PetscObjectReference((PetscObject)M);
    136:       *Msub = M;
    137:     }
    138:     /* Save the diagonal to temporary vector */
    139:     MatGetDiagonal(*Msub,v1);

    141:     /* Zero out rows and columns */
    142:     ISComplementVec(is,v1,&iscomp);

    144:     /* Use v1 instead of 0 here because of PETSc bug */
    145:     MatZeroRowsColumnsIS(*Msub,iscomp,1.0,v1,v1);

    147:     ISDestroy(&iscomp);
    148:     break;
    149:   case TAO_SUBSET_MATRIXFREE:
    150:     ISComplementVec(is,v1,&iscomp);
    151:     MatCreateSubMatrixFree(M,iscomp,iscomp,Msub);
    152:     ISDestroy(&iscomp);
    153:     break;
    154:   }
    155:   return(0);
    156: }

    158: /*@C
    159:   TaoEstimateActiveBounds - Generates index sets for variables at the lower and upper
    160:   bounds, as well as fixed variables where lower and upper bounds equal each other.

    162:   Input Parameters:
    163: + X - solution vector
    164: . XL - lower bound vector
    165: . XU - upper bound vector
    166: . G - unprojected gradient
    167: . S - step direction with which the active bounds will be estimated
    168: - steplen - the step length at which the active bounds will be estimated (needs to be conservative)

    170:   Output Parameters:
    171: . bound_tol - tolerance for for the bound estimation
    172: . active_lower - index set for active variables at the lower bound
    173: . active_upper - index set for active variables at the upper bound
    174: . active_fixed - index set for fixed variables
    175: . active - index set for all active variables
    176: . inactive - complementary index set for inactive variables

    178:   Notes:
    179:   This estimation is based on Bertsekas' method, with a built in diagonal scaling value of 1.0e-3.
    180:
    181: @*/
    182: PetscErrorCode TaoEstimateActiveBounds(Vec X, Vec XL, Vec XU, Vec G, Vec S, Vec W, PetscReal steplen, PetscReal *bound_tol,
    183:                                        IS *active_lower, IS *active_upper, IS *active_fixed, IS *active, IS *inactive)
    184: {
    185:   PetscErrorCode               ierr;
    186:   PetscReal                    wnorm;
    187:   PetscReal                    zero = PetscPowReal(PETSC_MACHINE_EPSILON, 2.0/3.0);
    188:   PetscInt                     i, n_isl=0, n_isu=0, n_isf=0, n_isa=0, n_isi=0;
    189:   PetscInt                     N_isl, N_isu, N_isf, N_isa, N_isi;
    190:   PetscInt                     n, low, high, nDiff;
    191:   PetscInt                     *isl=NULL, *isu=NULL, *isf=NULL, *isa=NULL, *isi=NULL;
    192:   const PetscScalar            *xl, *xu, *x, *g;
    193:   MPI_Comm                     comm = PetscObjectComm((PetscObject)X);

    202:
    219:   VecCheckSameSize(X,1,XL,2);
    220:   VecCheckSameSize(X,1,XU,3);
    221:   VecCheckSameSize(X,1,G,4);
    222:   VecCheckSameSize(X,1,S,5);
    223:   VecCheckSameSize(X,1,W,6);
    224:
    225:   /* Update the tolerance for bound detection (this is based on Bertsekas' method) */
    226:   VecCopy(X, W);
    227:   VecAXPBY(W, steplen, 1.0, S);
    228:   TaoBoundSolution(W, XL, XU, 0.0, &nDiff, W);
    229:   VecAXPBY(W, 1.0, -1.0, X);
    230:   VecNorm(W, NORM_2, &wnorm);
    231:   *bound_tol = PetscMin(*bound_tol, wnorm);
    232:
    233:   VecGetOwnershipRange(X, &low, &high);
    234:   VecGetLocalSize(X, &n);
    235:   if (n>0){
    236:     VecGetArrayRead(X, &x);
    237:     VecGetArrayRead(XL, &xl);
    238:     VecGetArrayRead(XU, &xu);
    239:     VecGetArrayRead(G, &g);
    240:
    241:     /* Loop over variables and categorize the indexes */
    242:     PetscMalloc1(n, &isl);
    243:     PetscMalloc1(n, &isu);
    244:     PetscMalloc1(n, &isf);
    245:     PetscMalloc1(n, &isa);
    246:     PetscMalloc1(n, &isi);
    247:     for (i=0; i<n; ++i) {
    248:       if (xl[i] == xu[i]) {
    249:         /* Fixed variables */
    250:         isf[n_isf]=low+i; ++n_isf;
    251:         isa[n_isa]=low+i; ++n_isa;
    252:       } else if ((xl[i] > PETSC_NINFINITY) && (x[i] <= xl[i] + *bound_tol) && (g[i] > zero)) {
    253:         /* Lower bounded variables */
    254:         isl[n_isl]=low+i; ++n_isl;
    255:         isa[n_isa]=low+i; ++n_isa;
    256:       } else if ((xu[i] < PETSC_INFINITY) && (x[i] >= xu[i] - *bound_tol) && (g[i] < zero)) {
    257:         /* Upper bounded variables */
    258:         isu[n_isu]=low+i; ++n_isu;
    259:         isa[n_isa]=low+i; ++n_isa;
    260:       } else {
    261:         /* Inactive variables */
    262:         isi[n_isi]=low+i; ++n_isi;
    263:       }
    264:     }
    265:
    266:     VecRestoreArrayRead(X, &x);
    267:     VecRestoreArrayRead(XL, &xl);
    268:     VecRestoreArrayRead(XU, &xu);
    269:     VecRestoreArrayRead(G, &g);
    270:   }
    271:
    272:   /* Clear all index sets */
    273:   ISDestroy(active_lower);
    274:   ISDestroy(active_upper);
    275:   ISDestroy(active_fixed);
    276:   ISDestroy(active);
    277:   ISDestroy(inactive);
    278:
    279:   /* Collect global sizes */
    280:   MPIU_Allreduce(&n_isl, &N_isl, 1, MPIU_INT, MPI_SUM, comm);
    281:   MPIU_Allreduce(&n_isu, &N_isu, 1, MPIU_INT, MPI_SUM, comm);
    282:   MPIU_Allreduce(&n_isf, &N_isf, 1, MPIU_INT, MPI_SUM, comm);
    283:   MPIU_Allreduce(&n_isa, &N_isa, 1, MPIU_INT, MPI_SUM, comm);
    284:   MPIU_Allreduce(&n_isi, &N_isi, 1, MPIU_INT, MPI_SUM, comm);
    285:
    286:   /* Create index set for lower bounded variables */
    287:   if (N_isl > 0) {
    288:     ISCreateGeneral(comm, n_isl, isl, PETSC_OWN_POINTER, active_lower);
    289:   } else {
    290:     PetscFree(isl);
    291:   }
    292:   /* Create index set for upper bounded variables */
    293:   if (N_isu > 0) {
    294:     ISCreateGeneral(comm, n_isu, isu, PETSC_OWN_POINTER, active_upper);
    295:   } else {
    296:     PetscFree(isu);
    297:   }
    298:   /* Create index set for fixed variables */
    299:   if (N_isf > 0) {
    300:     ISCreateGeneral(comm, n_isf, isf, PETSC_OWN_POINTER, active_fixed);
    301:   } else {
    302:     PetscFree(isf);
    303:   }
    304:   /* Create index set for all actively bounded variables */
    305:   if (N_isa > 0) {
    306:     ISCreateGeneral(comm, n_isa, isa, PETSC_OWN_POINTER, active);
    307:   } else {
    308:     PetscFree(isa);
    309:   }
    310:   /* Create index set for all inactive variables */
    311:   if (N_isi > 0) {
    312:     ISCreateGeneral(comm, n_isi, isi, PETSC_OWN_POINTER, inactive);
    313:   } else {
    314:     PetscFree(isi);
    315:   }

    317:   /* Clean up and exit */
    318:   return(0);
    319: }

    321: /*@C
    322:   TaoBoundStep - Ensures the correct zero or adjusted step direction
    323:   values for active variables.

    325:   Input Parameters:
    326: + X - solution vector
    327: . XL - lower bound vector
    328: . XU - upper bound vector
    329: . active_lower - index set for lower bounded active variables
    330: . active_upper - index set for lower bounded active variables
    331: - active_fixed - index set for fixed active variables

    333:   Output Parameters:
    334: . S - step direction to be modified
    335: @*/
    336: PetscErrorCode TaoBoundStep(Vec X, Vec XL, Vec XU, IS active_lower, IS active_upper, IS active_fixed, PetscReal scale, Vec S)
    337: {
    338:   PetscErrorCode               ierr;
    339:
    340:   Vec                          step_lower, step_upper, step_fixed;
    341:   Vec                          x_lower, x_upper;
    342:   Vec                          bound_lower, bound_upper;
    343:
    345:   /* Adjust step for variables at the estimated lower bound */
    346:   if (active_lower) {
    347:     VecGetSubVector(S, active_lower, &step_lower);
    348:     VecGetSubVector(X, active_lower, &x_lower);
    349:     VecGetSubVector(XL, active_lower, &bound_lower);
    350:     VecCopy(bound_lower, step_lower);
    351:     VecAXPY(step_lower, -1.0, x_lower);
    352:     VecScale(step_lower, scale);
    353:     VecRestoreSubVector(S, active_lower, &step_lower);
    354:     VecRestoreSubVector(X, active_lower, &x_lower);
    355:     VecRestoreSubVector(XL, active_lower, &bound_lower);
    356:   }
    357:
    358:   /* Adjust step for the variables at the estimated upper bound */
    359:   if (active_upper) {
    360:     VecGetSubVector(S, active_upper, &step_upper);
    361:     VecGetSubVector(X, active_upper, &x_upper);
    362:     VecGetSubVector(XU, active_upper, &bound_upper);
    363:     VecCopy(bound_upper, step_upper);
    364:     VecAXPY(step_upper, -1.0, x_upper);
    365:     VecScale(step_upper, scale);
    366:     VecRestoreSubVector(S, active_upper, &step_upper);
    367:     VecRestoreSubVector(X, active_upper, &x_upper);
    368:     VecRestoreSubVector(XU, active_upper, &bound_upper);
    369:   }
    370:
    371:   /* Zero out step for fixed variables */
    372:   if (active_fixed) {
    373:     VecGetSubVector(S, active_fixed, &step_fixed);
    374:     VecSet(step_fixed, 0.0);
    375:     VecRestoreSubVector(S, active_fixed, &step_fixed);
    376:   }
    377:   return(0);
    378: }

    380: /*@C
    381:   TaoBoundSolution - Ensures that the solution vector is snapped into the bounds.

    383:   Input Parameters:
    384: + XL - lower bound vector
    385: . XU - upper bound vector
    386: . X - solution vector
    387: .
    388: -

    390:   Output Parameters:
    391: . X - modified solution vector
    392: @*/
    393: PetscErrorCode TaoBoundSolution(Vec X, Vec XL, Vec XU, PetscReal bound_tol, PetscInt *nDiff, Vec Xout)
    394: {
    395:   PetscErrorCode    ierr;
    396:   PetscInt          i,n,low,high,nDiff_loc=0;
    397:   PetscScalar       *xout;
    398:   const PetscScalar *x,*xl,*xu;

    416:   VecCheckSameSize(X,1,XL,2);
    417:   VecCheckSameSize(X,1,XU,3);
    418:   VecCheckSameSize(X,1,Xout,4);

    420:   VecGetOwnershipRange(X,&low,&high);
    421:   VecGetLocalSize(X,&n);
    422:   if (n>0){
    423:     VecGetArrayRead(X, &x);
    424:     VecGetArrayRead(XL, &xl);
    425:     VecGetArrayRead(XU, &xu);
    426:     VecGetArray(Xout, &xout);

    428:     for (i=0;i<n;++i){
    429:       if ((xl[i] > PETSC_NINFINITY) && (x[i] <= xl[i] + bound_tol)) {
    430:         xout[i] = xl[i]; ++nDiff_loc;
    431:       } else if ((xu[i] < PETSC_INFINITY) && (x[i] >= xu[i] - bound_tol)) {
    432:         xout[i] = xu[i]; ++nDiff_loc;
    433:       }
    434:     }

    436:     VecRestoreArrayRead(X, &x);
    437:     VecRestoreArrayRead(XL, &xl);
    438:     VecRestoreArrayRead(XU, &xu);
    439:     VecRestoreArray(Xout, &xout);
    440:   }
    441:   MPIU_Allreduce(&nDiff_loc, nDiff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject)X));
    442:   return(0);
    443: }