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

      1:  #include <petsc/private/vecimpl.h>

      3: /*@
      4:   VecWhichEqual - Creates an index set containing the indices
      5:              where the vectors Vec1 and Vec2 have identical elements.

      7:   Collective on Vec

      9:   Input Parameters:
     10: . Vec1, Vec2 - the two vectors to compare

     12:   OutputParameter:
     13: . S - The index set containing the indices i where vec1[i] == vec2[i]

     15:   Notes:
     16:     the two vectors must have the same parallel layout

     18:   Level: advanced
     19: @*/
     20: PetscErrorCode VecWhichEqual(Vec Vec1, Vec Vec2, IS *S)
     21: {
     22:   PetscErrorCode    ierr;
     23:   PetscInt          i,n_same=0;
     24:   PetscInt          n,low,high;
     25:   PetscInt          *same=NULL;
     26:   const PetscScalar *v1,*v2;

     32:   VecCheckSameSize(Vec1,1,Vec2,2);

     34:   VecGetOwnershipRange(Vec1,&low,&high);
     35:   VecGetLocalSize(Vec1,&n);
     36:   if (n>0){
     37:     if (Vec1 == Vec2){
     38:       VecGetArrayRead(Vec1,&v1);
     39:       v2=v1;
     40:     } else {
     41:       VecGetArrayRead(Vec1,&v1);
     42:       VecGetArrayRead(Vec2,&v2);
     43:     }

     45:     PetscMalloc1(n,&same);

     47:     for (i=0; i<n; ++i){
     48:       if (v1[i] == v2[i]) {same[n_same]=low+i; ++n_same;}
     49:     }

     51:     if (Vec1 == Vec2){
     52:       VecRestoreArrayRead(Vec1,&v1);
     53:     } else {
     54:       VecRestoreArrayRead(Vec1,&v1);
     55:       VecRestoreArrayRead(Vec2,&v2);
     56:     }
     57:   }
     58:   ISCreateGeneral(PetscObjectComm((PetscObject)Vec1),n_same,same,PETSC_OWN_POINTER,S);
     59:   return(0);
     60: }

     62: /*@
     63:   VecWhichLessThan - Creates an index set containing the indices
     64:   where the vectors Vec1 < Vec2

     66:   Collective on S

     68:   Input Parameters:
     69: . Vec1, Vec2 - the two vectors to compare

     71:   OutputParameter:
     72: . S - The index set containing the indices i where vec1[i] < vec2[i]

     74:   Notes:
     75:   The two vectors must have the same parallel layout

     77:   For complex numbers this only compares the real part

     79:   Level: advanced
     80: @*/
     81: PetscErrorCode VecWhichLessThan(Vec Vec1, Vec Vec2, IS *S)
     82: {
     83:   PetscErrorCode    ierr;
     84:   PetscInt          i,n_lt=0;
     85:   PetscInt          n,low,high;
     86:   PetscInt          *lt=NULL;
     87:   const PetscScalar *v1,*v2;

     93:   VecCheckSameSize(Vec1,1,Vec2,2);

     95:   VecGetOwnershipRange(Vec1,&low,&high);
     96:   VecGetLocalSize(Vec1,&n);
     97:   if (n>0){
     98:     if (Vec1 == Vec2){
     99:       VecGetArrayRead(Vec1,&v1);
    100:       v2=v1;
    101:     } else {
    102:       VecGetArrayRead(Vec1,&v1);
    103:       VecGetArrayRead(Vec2,&v2);
    104:     }

    106:     PetscMalloc1(n,&lt);

    108:     for (i=0; i<n; ++i){
    109:       if (PetscRealPart(v1[i]) < PetscRealPart(v2[i])) {lt[n_lt]=low+i; ++n_lt;}
    110:     }

    112:     if (Vec1 == Vec2){
    113:       VecRestoreArrayRead(Vec1,&v1);
    114:     } else {
    115:       VecRestoreArrayRead(Vec1,&v1);
    116:       VecRestoreArrayRead(Vec2,&v2);
    117:     }
    118:   }
    119:   ISCreateGeneral(PetscObjectComm((PetscObject)Vec1),n_lt,lt,PETSC_OWN_POINTER,S);
    120:   return(0);
    121: }

    123: /*@
    124:   VecWhichGreaterThan - Creates an index set containing the indices
    125:   where the vectors Vec1 > Vec2

    127:   Collective on S

    129:   Input Parameters:
    130: . Vec1, Vec2 - the two vectors to compare

    132:   OutputParameter:
    133: . S - The index set containing the indices i where vec1[i] > vec2[i]

    135:   Notes:
    136:   The two vectors must have the same parallel layout

    138:   For complex numbers this only compares the real part

    140:   Level: advanced
    141: @*/
    142: PetscErrorCode VecWhichGreaterThan(Vec Vec1, Vec Vec2, IS *S)
    143: {
    144:   PetscErrorCode    ierr;
    145:   PetscInt          i,n_gt=0;
    146:   PetscInt          n,low,high;
    147:   PetscInt          *gt=NULL;
    148:   const PetscScalar *v1,*v2;

    154:   VecCheckSameSize(Vec1,1,Vec2,2);

    156:   VecGetOwnershipRange(Vec1,&low,&high);
    157:   VecGetLocalSize(Vec1,&n);
    158:   if (n>0){
    159:     if (Vec1 == Vec2){
    160:       VecGetArrayRead(Vec1,&v1);
    161:       v2=v1;
    162:     } else {
    163:       VecGetArrayRead(Vec1,&v1);
    164:       VecGetArrayRead(Vec2,&v2);
    165:     }

    167:     PetscMalloc1(n,&gt);

    169:     for (i=0; i<n; ++i){
    170:       if (PetscRealPart(v1[i]) > PetscRealPart(v2[i])) {gt[n_gt]=low+i; ++n_gt;}
    171:     }

    173:     if (Vec1 == Vec2){
    174:       VecRestoreArrayRead(Vec1,&v1);
    175:     } else {
    176:       VecRestoreArrayRead(Vec1,&v1);
    177:       VecRestoreArrayRead(Vec2,&v2);
    178:     }
    179:   }
    180:   ISCreateGeneral(PetscObjectComm((PetscObject)Vec1),n_gt,gt,PETSC_OWN_POINTER,S);
    181:   return(0);
    182: }

    184: /*@
    185:   VecWhichBetween - Creates an index set containing the indices
    186:                where  VecLow < V < VecHigh

    188:   Collective on S

    190:   Input Parameters:
    191: + VecLow - lower bound
    192: . V - Vector to compare
    193: - VecHigh - higher bound

    195:   OutputParameter:
    196: . S - The index set containing the indices i where veclow[i] < v[i] < vechigh[i]

    198:   Notes:
    199:   The vectors must have the same parallel layout

    201:   For complex numbers this only compares the real part

    203:   Level: advanced
    204: @*/
    205: PetscErrorCode VecWhichBetween(Vec VecLow, Vec V, Vec VecHigh, IS *S)
    206: {

    208:   PetscErrorCode    ierr;
    209:   PetscInt          i,n_vm=0;
    210:   PetscInt          n,low,high;
    211:   PetscInt          *vm=NULL;
    212:   const PetscScalar *v1,*v2,*vmiddle;

    220:   VecCheckSameSize(V,2,VecLow,1);
    221:   VecCheckSameSize(V,2,VecHigh,3);

    223:   VecGetOwnershipRange(VecLow,&low,&high);
    224:   VecGetLocalSize(VecLow,&n);
    225:   if (n>0){
    226:     VecGetArrayRead(VecLow,&v1);
    227:     if (VecLow != VecHigh){
    228:       VecGetArrayRead(VecHigh,&v2);
    229:     } else {
    230:       v2=v1;
    231:     }
    232:     if (V != VecLow && V != VecHigh){
    233:       VecGetArrayRead(V,&vmiddle);
    234:     } else if (V==VecLow){
    235:       vmiddle=v1;
    236:     } else {
    237:       vmiddle=v2;
    238:     }

    240:     PetscMalloc1(n,&vm);

    242:     for (i=0; i<n; ++i){
    243:       if (PetscRealPart(v1[i]) < PetscRealPart(vmiddle[i]) && PetscRealPart(vmiddle[i]) < PetscRealPart(v2[i])) {vm[n_vm]=low+i; ++n_vm;}
    244:     }

    246:     VecRestoreArrayRead(VecLow,&v1);
    247:     if (VecLow != VecHigh){
    248:       VecRestoreArrayRead(VecHigh,&v2);
    249:     }
    250:     if (V != VecLow && V != VecHigh){
    251:       VecRestoreArrayRead(V,&vmiddle);
    252:     }
    253:   }
    254:   ISCreateGeneral(PetscObjectComm((PetscObject)V),n_vm,vm,PETSC_OWN_POINTER,S);
    255:   return(0);
    256: }

    259: /*@
    260:   VecWhichBetweenOrEqual - Creates an index set containing the indices
    261:   where  VecLow <= V <= VecHigh

    263:   Collective on S

    265:   Input Parameters:
    266: + VecLow - lower bound
    267: . V - Vector to compare
    268: - VecHigh - higher bound

    270:   OutputParameter:
    271: . S - The index set containing the indices i where veclow[i] <= v[i] <= vechigh[i]

    273:   Level: advanced
    274: @*/

    276: PetscErrorCode VecWhichBetweenOrEqual(Vec VecLow, Vec V, Vec VecHigh, IS * S)
    277: {
    278:   PetscErrorCode    ierr;
    279:   PetscInt          i,n_vm=0;
    280:   PetscInt          n,low,high;
    281:   PetscInt          *vm=NULL;
    282:   const PetscScalar *v1,*v2,*vmiddle;

    290:   VecCheckSameSize(V,2,VecLow,1);
    291:   VecCheckSameSize(V,2,VecHigh,3);

    293:   VecGetOwnershipRange(VecLow,&low,&high);
    294:   VecGetLocalSize(VecLow,&n);
    295:   if (n>0){
    296:     VecGetArrayRead(VecLow,&v1);
    297:     if (VecLow != VecHigh){
    298:       VecGetArrayRead(VecHigh,&v2);
    299:     } else {
    300:       v2=v1;
    301:     }
    302:     if (V != VecLow && V != VecHigh){
    303:       VecGetArrayRead(V,&vmiddle);
    304:     } else if (V==VecLow){
    305:       vmiddle=v1;
    306:     } else {
    307:       vmiddle =v2;
    308:     }

    310:     PetscMalloc1(n,&vm);

    312:     for (i=0; i<n; ++i){
    313:       if (PetscRealPart(v1[i]) <= PetscRealPart(vmiddle[i]) && PetscRealPart(vmiddle[i]) <= PetscRealPart(v2[i])) {vm[n_vm]=low+i; ++n_vm;}
    314:     }

    316:     VecRestoreArrayRead(VecLow,&v1);
    317:     if (VecLow != VecHigh){
    318:       VecRestoreArrayRead(VecHigh,&v2);
    319:     }
    320:     if (V != VecLow && V != VecHigh){
    321:       VecRestoreArrayRead(V,&vmiddle);
    322:     }
    323:   }
    324:   ISCreateGeneral(PetscObjectComm((PetscObject)V),n_vm,vm,PETSC_OWN_POINTER,S);
    325:   return(0);
    326: }

    328: /*@
    329:    VecWhichInactive - Creates an index set containing the indices
    330:   where one of the following holds:
    331:     a) VecLow(i)  < V(i) < VecHigh(i)
    332:     b) VecLow(i)  = V(i) and D(i) <= 0 (< 0 when Strong is true)
    333:     c) VecHigh(i) = V(i) and D(i) >= 0 (> 0 when Strong is true)

    335:   Collective on S

    337:   Input Parameters:
    338: + VecLow - lower bound
    339: . V - Vector to compare
    340: . D - Direction to compare
    341: . VecHigh - higher bound
    342: - Strong - indicator for applying strongly inactive test

    344:   OutputParameter:
    345: . S - The index set containing the indices i where the bound is inactive

    347:   Level: advanced
    348: @*/

    350: PetscErrorCode VecWhichInactive(Vec VecLow, Vec V, Vec D, Vec VecHigh, PetscBool Strong, IS * S)
    351: {
    352:   PetscErrorCode    ierr;
    353:   PetscInt          i,n_vm=0;
    354:   PetscInt          n,low,high;
    355:   PetscInt          *vm=NULL;
    356:   const PetscScalar *v1,*v2,*v,*d;

    366:   VecCheckSameSize(V,2,VecLow,1);
    367:   VecCheckSameSize(V,2,D,3);
    368:   VecCheckSameSize(V,2,VecHigh,4);

    370:   VecGetOwnershipRange(VecLow,&low,&high);
    371:   VecGetLocalSize(VecLow,&n);
    372:   if (n>0){
    373:     VecGetArrayRead(VecLow,&v1);
    374:     if (VecLow != VecHigh){
    375:       VecGetArrayRead(VecHigh,&v2);
    376:     } else {
    377:       v2=v1;
    378:     }
    379:     if (V != VecLow && V != VecHigh){
    380:       VecGetArrayRead(V,&v);
    381:     } else if (V==VecLow){
    382:       v = v1;
    383:     } else {
    384:       v = v2;
    385:     }
    386:     if (D != VecLow && D != VecHigh && D != V){
    387:       VecGetArrayRead(D,&d);
    388:     } else if (D==VecLow){
    389:       d = v1;
    390:     } else if (D==VecHigh){
    391:       d = v2;
    392:     } else {
    393:       d = v;
    394:     }

    396:     PetscMalloc1(n,&vm);

    398:     if (Strong){
    399:       for (i=0; i<n; ++i) {
    400:         if (PetscRealPart(v1[i]) < PetscRealPart(v[i]) && PetscRealPart(v[i]) < PetscRealPart(v2[i])){
    401:           vm[n_vm]=low+i; ++n_vm;
    402:         } else if (PetscRealPart(v1[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) < 0){
    403:           vm[n_vm]=low+i; ++n_vm;
    404:         } else if (PetscRealPart(v2[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) > 0){
    405:           vm[n_vm]=low+i; ++n_vm;
    406:         }
    407:       }
    408:     } else {
    409:       for (i=0; i<n; ++i) {
    410:         if (PetscRealPart(v1[i]) < PetscRealPart(v[i]) && PetscRealPart(v[i]) < PetscRealPart(v2[i])){
    411:           vm[n_vm]=low+i; ++n_vm;
    412:         } else if (PetscRealPart(v1[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) <= 0){
    413:           vm[n_vm]=low+i; ++n_vm;
    414:         } else if (PetscRealPart(v2[i]) == PetscRealPart(v[i]) && PetscRealPart(d[i]) >= 0){
    415:           vm[n_vm]=low+i; ++n_vm;
    416:         }
    417:       }
    418:     }

    420:     VecRestoreArrayRead(VecLow,&v1);
    421:     if (VecLow != VecHigh){
    422:       VecRestoreArrayRead(VecHigh,&v2);
    423:     }
    424:     if (V != VecLow && V != VecHigh){
    425:       VecRestoreArrayRead(V,&v);
    426:     }
    427:     if (D != VecLow && D != VecHigh && D != V){
    428:       VecRestoreArrayRead(D,&d);
    429:     }
    430:   }
    431:   ISCreateGeneral(PetscObjectComm((PetscObject)V),n_vm,vm,PETSC_OWN_POINTER,S);
    432:   return(0);
    433: }

    436: /*@
    437:   VecISAXPY - Adds a reduced vector to the appropriate elements of a full-space vector.
    438:                   vfull[is[i]] += alpha*vreduced[i]

    440:   Input Parameters:
    441: + vfull    - the full-space vector
    442: . is       - the index set for the reduced space
    443: . alpha    - the scalar coefficient
    444: - vreduced - the reduced-space vector

    446:   Output Parameters:
    447: . vfull    - the sum of the full-space vector and reduced-space vector

    449:   Level: advanced

    451: .seealso:  VecAXPY()
    452: @*/
    453: PetscErrorCode VecISAXPY(Vec vfull, IS is, PetscScalar alpha, Vec vreduced)
    454: {
    455:   PetscInt       nfull,nreduced;

    462:   VecGetSize(vfull,&nfull);
    463:   VecGetSize(vreduced,&nreduced);

    465:   if (nfull == nreduced) { /* Also takes care of masked vectors */
    466:     VecAXPY(vfull,alpha,vreduced);
    467:   } else {
    468:     PetscScalar      *y;
    469:     const PetscScalar *x;
    470:     PetscInt          i,n,m,rstart;
    471:     const PetscInt    *id;

    473:     VecGetArray(vfull,&y);
    474:     VecGetArrayRead(vreduced,&x);
    475:     ISGetIndices(is,&id);
    476:     ISGetLocalSize(is,&n);
    477:     VecGetLocalSize(vreduced,&m);
    478:     if (m != n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS local length not equal to Vec local length");
    479:     VecGetOwnershipRange(vfull,&rstart,NULL);
    480:     y -= rstart;
    481:     if (alpha == 1.0) {
    482:       for (i=0; i<n; ++i) {
    483:         y[id[i]] += x[i];
    484:       }
    485:     } else {
    486:       for (i=0; i<n; ++i) {
    487:         y[id[i]] += alpha*x[i];
    488:       }
    489:     }
    490:     y += rstart;
    491:     ISRestoreIndices(is,&id);
    492:     VecRestoreArray(vfull,&y);
    493:     VecRestoreArrayRead(vreduced,&x);
    494:   }
    495:   return(0);
    496: }

    498: /*@
    499:   VecISCopy - Copies between a reduced vector and the appropriate elements of a full-space vector.
    500:               vfull[is[i]] = vreduced[i]

    502:   Input Parameters:
    503: + vfull    - the full-space vector
    504: . is       - the index set for the reduced space
    505: . mode     - the direction of copying, SCATTER_FORWARD or SCATTER_REVERSE
    506: - vreduced - the reduced-space vector

    508:   Output Parameters:
    509: . vfull    - the sum of the full-space vector and reduced-space vector

    511:   Level: advanced

    513: .seealso:  VecAXPY()
    514: @*/
    515: PetscErrorCode VecISCopy(Vec vfull, IS is, ScatterMode mode, Vec vreduced)
    516: {
    517:   PetscInt       nfull, nreduced;

    524:   VecGetSize(vfull, &nfull);
    525:   VecGetSize(vreduced, &nreduced);

    527:   if (nfull == nreduced) { /* Also takes care of masked vectors */
    528:     VecCopy(vreduced, vfull);
    529:   } else {
    530:     const PetscInt *id;
    531:     PetscInt        i, n, m, rstart;

    533:     ISGetIndices(is, &id);
    534:     ISGetLocalSize(is, &n);
    535:     VecGetLocalSize(vreduced, &m);
    536:     VecGetOwnershipRange(vfull, &rstart, NULL);
    537:     if (m != n) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_SUP, "IS local length %D not equal to Vec local length %D", n, m);
    538:     if (mode == SCATTER_FORWARD) {
    539:       PetscScalar       *y;
    540:       const PetscScalar *x;

    542:       VecGetArray(vfull, &y);
    543:       VecGetArrayRead(vreduced, &x);
    544:       y   -= rstart;
    545:       for (i = 0; i < n; ++i) {
    546:         y[id[i]] = x[i];
    547:       }
    548:       y   += rstart;
    549:       VecRestoreArrayRead(vreduced, &x);
    550:       VecRestoreArray(vfull, &y);
    551:     } else if (mode == SCATTER_REVERSE) {
    552:       PetscScalar       *x;
    553:       const PetscScalar *y;

    555:       VecGetArrayRead(vfull, &y);
    556:       VecGetArray(vreduced, &x);
    557:       for (i = 0; i < n; ++i) {
    558:         x[i] = y[id[i]-rstart];
    559:       }
    560:       VecRestoreArray(vreduced, &x);
    561:       VecRestoreArrayRead(vfull, &y);
    562:     } else SETERRQ(PetscObjectComm((PetscObject) vfull), PETSC_ERR_ARG_WRONG, "Only forward or reverse modes are legal");
    563:     ISRestoreIndices(is, &id);
    564:   }
    565:   return(0);
    566: }

    568: /*@
    569:    ISComplementVec - Creates the complement of the index set relative to a layout defined by a Vec

    571:    Collective on IS

    573:    Input Parameter:
    574: +  S -  a PETSc IS
    575: -  V - the reference vector space

    577:    Output Parameter:
    578: .  T -  the complement of S

    580: .seealso ISCreateGeneral()

    582:    Level: advanced
    583: @*/
    584: PetscErrorCode ISComplementVec(IS S, Vec V, IS *T)
    585: {
    587:   PetscInt       start, end;

    590:   VecGetOwnershipRange(V,&start,&end);
    591:   ISComplement(S,start,end,T);
    592:   return(0);
    593: }

    595: /*@
    596:    VecISSet - Sets the elements of a vector, specified by an index set, to a constant

    598:    Input Parameter:
    599: +  V - the vector
    600: .  S -  the locations in the vector
    601: -  c - the constant

    603: .seealso VecSet()

    605:    Level: advanced
    606: @*/
    607: PetscErrorCode VecISSet(Vec V,IS S, PetscScalar c)
    608: {
    610:   PetscInt       nloc,low,high,i;
    611:   const PetscInt *s;
    612:   PetscScalar    *v;

    615:   if (!S) return(0); /* simply return with no-op if the index set is NULL */

    621:   VecGetOwnershipRange(V,&low,&high);
    622:   ISGetLocalSize(S,&nloc);
    623:   ISGetIndices(S,&s);
    624:   VecGetArray(V,&v);
    625:   for (i=0; i<nloc; ++i){
    626:     v[s[i]-low] = c;
    627:   }
    628:   ISRestoreIndices(S,&s);
    629:   VecRestoreArray(V,&v);
    630:   return(0);
    631: }

    633: #if !defined(PETSC_USE_COMPLEX)
    634: /*@C
    635:   VecBoundGradientProjection - Projects  vector according to this definition.
    636:   If XL[i] < X[i] < XU[i], then GP[i] = G[i];
    637:   If X[i] <= XL[i], then GP[i] = min(G[i],0);
    638:   If X[i] >= XU[i], then GP[i] = max(G[i],0);

    640:   Input Parameters:
    641: + G - current gradient vector
    642: . X - current solution vector with XL[i] <= X[i] <= XU[i]
    643: . XL - lower bounds
    644: - XU - upper bounds

    646:   Output Parameter:
    647: . GP - gradient projection vector

    649:   Notes:
    650:     GP may be the same vector as G

    652:   Level: advanced
    653: @*/
    654: PetscErrorCode VecBoundGradientProjection(Vec G, Vec X, Vec XL, Vec XU, Vec GP)
    655: {

    657:   PetscErrorCode  ierr;
    658:   PetscInt        n,i;
    659:   const PetscReal *xptr,*xlptr,*xuptr;
    660:   PetscReal       *gptr,*gpptr;
    661:   PetscReal       xval,gpval;

    663:   /* Project variables at the lower and upper bound */

    671:   VecGetLocalSize(X,&n);

    673:   VecGetArrayRead(X,&xptr);
    674:   VecGetArrayRead(XL,&xlptr);
    675:   VecGetArrayRead(XU,&xuptr);
    676:   VecGetArrayPair(G,GP,&gptr,&gpptr);

    678:   for (i=0; i<n; ++i){
    679:     gpval = gptr[i]; xval = xptr[i];
    680:     if (gpval>0.0 && xval<=xlptr[i]){
    681:       gpval = 0.0;
    682:     } else if (gpval<0.0 && xval>=xuptr[i]){
    683:       gpval = 0.0;
    684:     }
    685:     gpptr[i] = gpval;
    686:   }

    688:   VecRestoreArrayRead(X,&xptr);
    689:   VecRestoreArrayRead(XL,&xlptr);
    690:   VecRestoreArrayRead(XU,&xuptr);
    691:   VecRestoreArrayPair(G,GP,&gptr,&gpptr);
    692:   return(0);
    693: }
    694: #endif

    696: /*@
    697:      VecStepMaxBounded - See below

    699:      Collective on Vec

    701:      Input Parameters:
    702: +      X  - vector with no negative entries
    703: .      XL - lower bounds
    704: .      XU - upper bounds
    705: -      DX  - step direction, can have negative, positive or zero entries

    707:      Output Parameter:
    708: .     stepmax -   minimum value so that X[i] + stepmax*DX[i] <= XL[i]  or  XU[i] <= X[i] + stepmax*DX[i]

    710:   Level: intermediate

    712: @*/
    713: PetscErrorCode VecStepMaxBounded(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *stepmax)
    714: {
    715:   PetscErrorCode    ierr;
    716:   PetscInt          i,nn;
    717:   const PetscScalar *xx,*dx,*xl,*xu;
    718:   PetscReal         localmax=0;

    726:   VecGetArrayRead(X,&xx);
    727:   VecGetArrayRead(XL,&xl);
    728:   VecGetArrayRead(XU,&xu);
    729:   VecGetArrayRead(DX,&dx);
    730:   VecGetLocalSize(X,&nn);
    731:   for (i=0;i<nn;i++){
    732:     if (PetscRealPart(dx[i]) > 0){
    733:       localmax=PetscMax(localmax,PetscRealPart((xu[i]-xx[i])/dx[i]));
    734:     } else if (PetscRealPart(dx[i])<0){
    735:       localmax=PetscMax(localmax,PetscRealPart((xl[i]-xx[i])/dx[i]));
    736:     }
    737:   }
    738:   VecRestoreArrayRead(X,&xx);
    739:   VecRestoreArrayRead(XL,&xl);
    740:   VecRestoreArrayRead(XU,&xu);
    741:   VecRestoreArrayRead(DX,&dx);
    742:   MPIU_Allreduce(&localmax,stepmax,1,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)X));
    743:   return(0);
    744: }

    746: /*@
    747:      VecStepBoundInfo - See below

    749:      Collective on Vec

    751:      Input Parameters:
    752: +      X  - vector with no negative entries
    753: .      XL - lower bounds
    754: .      XU - upper bounds
    755: -      DX  - step direction, can have negative, positive or zero entries

    757:      Output Parameter:
    758: +     boundmin -  (may be NULL this it is not computed) maximum value so that   XL[i] <= X[i] + boundmax*DX[i] <= XU[i]
    759: .     wolfemin -  (may be NULL this it is not computed)
    760: -     boundmax -   (may be NULL this it is not computed) minimum value so that X[i] + boundmax*DX[i] <= XL[i]  or  XU[i] <= X[i] + boundmax*DX[i]

    762:      Notes:
    763:     For complex numbers only compares the real part

    765:   Level: advanced
    766: @*/
    767: PetscErrorCode VecStepBoundInfo(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *boundmin, PetscReal *wolfemin, PetscReal *boundmax)
    768: {
    769:   PetscErrorCode    ierr;
    770:   PetscInt          n,i;
    771:   const PetscScalar *x,*xl,*xu,*dx;
    772:   PetscReal         t;
    773:   PetscReal         localmin=PETSC_INFINITY,localwolfemin=PETSC_INFINITY,localmax=-1;
    774:   MPI_Comm          comm;

    782:   VecGetArrayRead(X,&x);
    783:   VecGetArrayRead(XL,&xl);
    784:   VecGetArrayRead(XU,&xu);
    785:   VecGetArrayRead(DX,&dx);
    786:   VecGetLocalSize(X,&n);
    787:   for (i=0; i<n; ++i){
    788:     if (PetscRealPart(dx[i])>0 && PetscRealPart(xu[i]) < PETSC_INFINITY) {
    789:       t=PetscRealPart((xu[i]-x[i])/dx[i]);
    790:       localmin=PetscMin(t,localmin);
    791:       if (localmin>0){
    792:         localwolfemin = PetscMin(t,localwolfemin);
    793:       }
    794:       localmax = PetscMax(t,localmax);
    795:     } else if (PetscRealPart(dx[i])<0 && PetscRealPart(xl[i]) > PETSC_NINFINITY) {
    796:       t=PetscRealPart((xl[i]-x[i])/dx[i]);
    797:       localmin = PetscMin(t,localmin);
    798:       if (localmin>0){
    799:         localwolfemin = PetscMin(t,localwolfemin);
    800:       }
    801:       localmax = PetscMax(t,localmax);
    802:     }
    803:   }

    805:   VecRestoreArrayRead(X,&x);
    806:   VecRestoreArrayRead(XL,&xl);
    807:   VecRestoreArrayRead(XU,&xu);
    808:   VecRestoreArrayRead(DX,&dx);
    809:   ierr=PetscObjectGetComm((PetscObject)X,&comm);

    811:   if (boundmin){
    812:     MPIU_Allreduce(&localmin,boundmin,1,MPIU_REAL,MPIU_MIN,comm);
    813:     PetscInfo1(X,"Step Bound Info: Closest Bound: %20.19e\n",(double)*boundmin);
    814:   }
    815:   if (wolfemin){
    816:     MPIU_Allreduce(&localwolfemin,wolfemin,1,MPIU_REAL,MPIU_MIN,comm);
    817:     PetscInfo1(X,"Step Bound Info: Wolfe: %20.19e\n",(double)*wolfemin);
    818:   }
    819:   if (boundmax) {
    820:     MPIU_Allreduce(&localmax,boundmax,1,MPIU_REAL,MPIU_MAX,comm);
    821:     if (*boundmax < 0) *boundmax=PETSC_INFINITY;
    822:     PetscInfo1(X,"Step Bound Info: Max: %20.19e\n",(double)*boundmax);
    823:   }
    824:   return(0);
    825: }

    827: /*@
    828:      VecStepMax - Returns the largest value so that x[i] + step*DX[i] >= 0 for all i

    830:      Collective on Vec

    832:      Input Parameters:
    833: +      X  - vector with no negative entries
    834: -      DX  - a step direction, can have negative, positive or zero entries

    836:      Output Parameter:
    837: .    step - largest value such that x[i] + step*DX[i] >= 0 for all i

    839:      Notes:
    840:     For complex numbers only compares the real part

    842:   Level: advanced
    843:  @*/
    844: PetscErrorCode VecStepMax(Vec X, Vec DX, PetscReal *step)
    845: {
    846:   PetscErrorCode    ierr;
    847:   PetscInt          i,nn;
    848:   PetscReal         stepmax=PETSC_INFINITY;
    849:   const PetscScalar *xx,*dx;

    855:   VecGetLocalSize(X,&nn);
    856:   VecGetArrayRead(X,&xx);
    857:   VecGetArrayRead(DX,&dx);
    858:   for (i=0;i<nn;++i){
    859:     if (PetscRealPart(xx[i]) < 0) SETERRQ(PETSC_COMM_SELF,1,"Vector must be positive");
    860:     else if (PetscRealPart(dx[i])<0) stepmax=PetscMin(stepmax,PetscRealPart(-xx[i]/dx[i]));
    861:   }
    862:   VecRestoreArrayRead(X,&xx);
    863:   VecRestoreArrayRead(DX,&dx);
    864:   MPIU_Allreduce(&stepmax,step,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)X));
    865:   return(0);
    866: }

    868: /*@
    869:   VecPow - Replaces each component of a vector by x_i^p

    871:   Logically Collective on v

    873:   Input Parameter:
    874: + v - the vector
    875: - p - the exponent to use on each element

    877:   Output Parameter:
    878: . v - the vector

    880:   Level: intermediate

    882: @*/
    883: PetscErrorCode VecPow(Vec v, PetscScalar p)
    884: {
    886:   PetscInt       n,i;
    887:   PetscScalar    *v1;

    892:   VecGetArray(v,&v1);
    893:   VecGetLocalSize(v,&n);

    895:   if (1.0 == p) {
    896:   } else if (-1.0 == p) {
    897:     for (i = 0; i < n; ++i){
    898:       v1[i] = 1.0 / v1[i];
    899:     }
    900:   } else if (0.0 == p) {
    901:     for (i = 0; i < n; ++i){
    902:       /*  Not-a-number left alone
    903:           Infinity set to one  */
    904:       if (v1[i] == v1[i]) {
    905:         v1[i] = 1.0;
    906:       }
    907:     }
    908:   } else if (0.5 == p) {
    909:     for (i = 0; i < n; ++i) {
    910:       if (PetscRealPart(v1[i]) >= 0) {
    911:         v1[i] = PetscSqrtScalar(v1[i]);
    912:       } else {
    913:         v1[i] = PETSC_INFINITY;
    914:       }
    915:     }
    916:   } else if (-0.5 == p) {
    917:     for (i = 0; i < n; ++i) {
    918:       if (PetscRealPart(v1[i]) >= 0) {
    919:         v1[i] = 1.0 / PetscSqrtScalar(v1[i]);
    920:       } else {
    921:         v1[i] = PETSC_INFINITY;
    922:       }
    923:     }
    924:   } else if (2.0 == p) {
    925:     for (i = 0; i < n; ++i){
    926:       v1[i] *= v1[i];
    927:     }
    928:   } else if (-2.0 == p) {
    929:     for (i = 0; i < n; ++i){
    930:       v1[i] = 1.0 / (v1[i] * v1[i]);
    931:     }
    932:   } else {
    933:     for (i = 0; i < n; ++i) {
    934:       if (PetscRealPart(v1[i]) >= 0) {
    935:         v1[i] = PetscPowScalar(v1[i],p);
    936:       } else {
    937:         v1[i] = PETSC_INFINITY;
    938:       }
    939:     }
    940:   }
    941:   VecRestoreArray(v,&v1);
    942:   return(0);
    943: }

    945: /*@
    946:   VecMedian - Computes the componentwise median of three vectors
    947:   and stores the result in this vector.  Used primarily for projecting
    948:   a vector within upper and lower bounds.

    950:   Logically Collective

    952:   Input Parameters:
    953: . Vec1, Vec2, Vec3 - The three vectors

    955:   Output Parameter:
    956: . VMedian - The median vector (this can be any one of the input vectors)

    958:   Level: advanced
    959: @*/
    960: PetscErrorCode VecMedian(Vec Vec1, Vec Vec2, Vec Vec3, Vec VMedian)
    961: {
    962:   PetscErrorCode    ierr;
    963:   PetscInt          i,n,low1,high1;
    964:   const PetscScalar *v1,*v2,*v3;
    965:   PetscScalar       *vmed;

    973:   if (Vec1==Vec2 || Vec1==Vec3){
    974:     VecCopy(Vec1,VMedian);
    975:     return(0);
    976:   }
    977:   if (Vec2==Vec3){
    978:     VecCopy(Vec2,VMedian);
    979:     return(0);
    980:   }

    982:   /* Assert that Vec1 != Vec2 and Vec2 != Vec3 */
    993:   VecCheckSameSize(Vec1,1,Vec2,2);
    994:   VecCheckSameSize(Vec1,1,Vec3,3);
    995:   VecCheckSameSize(Vec1,1,VMedian,4);

    997:   VecGetOwnershipRange(Vec1,&low1,&high1);
    998:   VecGetLocalSize(Vec1,&n);
    999:   if (n>0){
    1000:     VecGetArray(VMedian,&vmed);
    1001:     if (Vec1 != VMedian){
    1002:       VecGetArrayRead(Vec1,&v1);
    1003:     } else {
    1004:       v1=vmed;
    1005:     }
    1006:     if (Vec2 != VMedian){
    1007:       VecGetArrayRead(Vec2,&v2);
    1008:     } else {
    1009:       v2=vmed;
    1010:     }
    1011:     if (Vec3 != VMedian){
    1012:       VecGetArrayRead(Vec3,&v3);
    1013:     } else {
    1014:       v3=vmed;
    1015:     }

    1017:     for (i=0;i<n;++i){
    1018:       vmed[i]=PetscMax(PetscMax(PetscMin(PetscRealPart(v1[i]),PetscRealPart(v2[i])),PetscMin(PetscRealPart(v1[i]),PetscRealPart(v3[i]))),PetscMin(PetscRealPart(v2[i]),PetscRealPart(v3[i])));
    1019:     }

    1021:     VecRestoreArray(VMedian,&vmed);
    1022:     if (VMedian != Vec1){
    1023:       VecRestoreArrayRead(Vec1,&v1);
    1024:     }
    1025:     if (VMedian != Vec2){
    1026:       VecRestoreArrayRead(Vec2,&v2);
    1027:     }
    1028:     if (VMedian != Vec3){
    1029:       VecRestoreArrayRead(Vec3,&v3);
    1030:     }
    1031:   }
    1032:   return(0);
    1033: }