Actual source code: projection.c

petsc-dev 2014-02-02
Report Typos and Errors
  1: #include <petsc-private/vecimpl.h>    /*I   "petscvec.h"  I*/

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

  9:   Collective on Vec

 11:   Input Parameters:
 12: . Vec1, Vec2 - the two vectors to compare

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

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


 33:   VecGetOwnershipRange(Vec1, &low, &high);
 34:   VecGetOwnershipRange(Vec2, &low2, &high2);
 35:   if ( low != low2 || high != high2 ) SETERRQ(PETSC_COMM_SELF,1,"Vectors must have identical layout");

 37:   VecGetLocalSize(Vec1,&n);
 38:   if (n>0){
 39:     if (Vec1 == Vec2){
 40:       VecGetArray(Vec1,&v1);
 41:       v2=v1;
 42:     } else {
 43:       VecGetArray(Vec1,&v1);
 44:       VecGetArray(Vec2,&v2);
 45:     }

 47:     PetscMalloc1( n,&same );

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

 53:     if (Vec1 == Vec2){
 54:       VecRestoreArray(Vec1,&v1);
 55:     } else {
 56:       VecRestoreArray(Vec1,&v1);
 57:       VecRestoreArray(Vec2,&v2);
 58:     }
 59:   }
 60:   PetscObjectGetComm((PetscObject)Vec1,&comm);
 61:   ISCreateGeneral(comm,n_same,same,PETSC_OWN_POINTER,S);
 62:   return(0);
 63: }

 67: /*@
 68:   VecWhichLessThan - Creates an index set containing the indices
 69:   where the vectors Vec1 < Vec2

 71:   Collective on S

 73:   Input Parameters:
 74: . Vec1, Vec2 - the two vectors to compare

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

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


 95:   VecGetOwnershipRange(Vec1, &low, &high);
 96:   VecGetOwnershipRange(Vec2, &low2, &high2);
 97:   if ( low != low2 || high != high2 ) SETERRQ(PETSC_COMM_SELF,1,"Vectors must haveidentical layout");

 99:   VecGetLocalSize(Vec1,&n);
100:   if (n>0){
101:     if (Vec1 == Vec2){
102:       VecGetArray(Vec1,&v1);
103:       v2=v1;
104:     } else {
105:       VecGetArray(Vec1,&v1);
106:       VecGetArray(Vec2,&v2);
107:     }
108:     PetscMalloc1(n,&lt );

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

114:     if (Vec1 == Vec2){
115:       VecRestoreArray(Vec1,&v1);
116:     } else {
117:       VecRestoreArray(Vec1,&v1);
118:       VecRestoreArray(Vec2,&v2);
119:     }
120:   }
121:   PetscObjectGetComm((PetscObject)Vec1,&comm);
122:   ISCreateGeneral(comm,n_lt,lt,PETSC_OWN_POINTER,S);
123:   return(0);
124: }

128: /*@
129:   VecWhichGreaterThan - Creates an index set containing the indices
130:   where the vectors Vec1 > Vec2

132:   Collective on S

134:   Input Parameters:
135: . Vec1, Vec2 - the two vectors to compare

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

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


155:   VecGetOwnershipRange(Vec1, &low, &high);
156:   VecGetOwnershipRange(Vec2, &low2, &high2);
157:   if ( low != low2 || high != high2 ) SETERRQ(PETSC_COMM_SELF,1,"Vectors must be have identical layout");

159:   VecGetLocalSize(Vec1,&n);

161:   if (n>0){

163:     if (Vec1 == Vec2){
164:       VecGetArray(Vec1,&v1);
165:       v2=v1;
166:     } else {
167:       VecGetArray(Vec1,&v1);
168:       VecGetArray(Vec2,&v2);
169:     }

171:     PetscMalloc1(n, &gt );

173:     for (i=0; i<n; i++){
174:       if (PetscRealPart(v1[i]) > PetscRealPart(v2[i])) {gt[n_gt]=low+i; n_gt++;}
175:     }

177:     if (Vec1 == Vec2){
178:       VecRestoreArray(Vec1,&v1);
179:     } else {
180:       VecRestoreArray(Vec1,&v1);
181:       VecRestoreArray(Vec2,&v2);
182:     }
183:   }
184:   PetscObjectGetComm((PetscObject)Vec1,&comm);
185:   ISCreateGeneral(comm,n_gt,gt,PETSC_OWN_POINTER,S);
186:   return(0);
187: }

191: /*@
192:   VecWhichBetween - Creates an index set containing the indices
193:                where  VecLow < V < VecHigh

195:   Collective on S

197:   Input Parameters:
198: + VecLow - lower bound
199: . V - Vector to compare
200: - VecHigh - higher bound

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

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

211:   PetscInt       n,low,high,low2,high2,low3,high3,n_vm=0;
212:   PetscInt       *vm,i;
213:   PetscScalar    *v1,*v2,*vmiddle;
214:   MPI_Comm       comm;


219:   VecGetOwnershipRange(VecLow, &low, &high);
220:   VecGetOwnershipRange(VecHigh, &low2, &high2);
221:   VecGetOwnershipRange(V, &low3, &high3);
222:   if ( low!=low2 || high!=high2 || low!=low3 || high!=high3) SETERRQ(PETSC_COMM_SELF,1,"Vectors must have identical layout");

224:   VecGetLocalSize(VecLow,&n);
225:   if (n>0){
226:     VecGetArray(VecLow,&v1);
227:     if (VecLow != VecHigh){
228:       VecGetArray(VecHigh,&v2);
229:     } else {
230:       v2=v1;
231:     }
232:     if ( V != VecLow && V != VecHigh){
233:       VecGetArray(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:     VecRestoreArray(VecLow,&v1);
247:     if (VecLow != VecHigh){
248:       VecRestoreArray(VecHigh,&v2);
249:     }
250:     if ( V != VecLow && V != VecHigh){
251:       VecRestoreArray(V,&vmiddle);
252:     }
253:   }
254:   PetscObjectGetComm((PetscObject)V,&comm);
255:   ISCreateGeneral(comm,n_vm,vm,PETSC_OWN_POINTER,S);
256:   return(0);
257: }


262: /*@
263:   VecWhichBetweenOrEqual - Creates an index set containing the indices
264:   where  VecLow <= V <= VecHigh

266:   Collective on S

268:   Input Parameters:
269: + VecLow - lower bound
270: . V - Vector to compare
271: - VecHigh - higher bound

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

276:   Level: advanced
277: @*/

279: PetscErrorCode VecWhichBetweenOrEqual(Vec VecLow, Vec V, Vec VecHigh, IS * S)
280: {
282:   PetscInt       n,low,high,low2,high2,low3,high3,n_vm=0,i;
283:   PetscInt       *vm = NULL;
284:   PetscScalar    *v1,*v2,*vmiddle;
285:   MPI_Comm       comm;


290:   VecGetOwnershipRange(VecLow, &low, &high);
291:   VecGetOwnershipRange(VecHigh, &low2, &high2);
292:   VecGetOwnershipRange(V, &low3, &high3);
293:   if ( low!=low2 || high!=high2 || low!=low3 || high!=high3 ) SETERRQ(PETSC_COMM_SELF,1,"Vectors must have identical layout");

295:   VecGetLocalSize(VecLow,&n);

297:   if (n>0){
298:     VecGetArray(VecLow,&v1);
299:     if (VecLow != VecHigh){
300:       VecGetArray(VecHigh,&v2);
301:     } else {
302:       v2=v1;
303:     }
304:     if ( V != VecLow && V != VecHigh){
305:       VecGetArray(V,&vmiddle);
306:     } else if ( V==VecLow ){
307:       vmiddle=v1;
308:     } else {
309:       vmiddle =v2;
310:     }

312:     PetscMalloc1(n, &vm );

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

318:     VecRestoreArray(VecLow,&v1);
319:     if (VecLow != VecHigh){
320:       VecRestoreArray(VecHigh,&v2);
321:     }
322:     if ( V != VecLow && V != VecHigh){
323:       VecRestoreArray(V,&vmiddle);
324:     }
325:   }
326:   PetscObjectGetComm((PetscObject)V,&comm);
327:   ISCreateGeneral(comm,n_vm,vm,PETSC_OWN_POINTER,S);
328:   return(0);
329: }

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

337:   Input Parameters:
338: + vfull - the full-space vector
339: . vreduced - the reduced-space vector
340: - is - the index set for the reduced space

342:   Output Parameters:
343: . vfull - the sum of the full-space vector and reduced-space vector

345: .seealso:  VecAXPY()
346: @*/
347: PetscErrorCode VecISAXPY(Vec vfull, IS is, PetscScalar alpha,Vec vreduced)
348: {
349:   PetscInt       nfull,nreduced;
350:   MPI_Comm       comm;

357:   VecGetSize(vfull,&nfull);
358:   VecGetSize(vreduced,&nreduced);

360:   if (nfull == nreduced) { /* Also takes care of masked vectors */
361:     VecAXPY(vfull,alpha,vreduced);
362:   } else {
363:     PetscScalar      *y;
364:     const PetscScalar *x;
365:     PetscInt          i,n,m,rstart;
366:     const PetscInt    *id;

368:     PetscObjectGetComm((PetscObject)vfull,&comm);
369:     VecGetArray(vfull,&y);
370:     VecGetArrayRead(vreduced,&x);
371:     ISGetIndices(is,&id);
372:     ISGetLocalSize(is,&n);
373:     VecGetLocalSize(vreduced,&m);
374:     if (m != n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"IS local length not equal to Vec local length");
375:     VecGetOwnershipRange(vfull,&rstart,NULL);
376:     y -= rstart;
377:     if (alpha == 1.0) {
378:       for (i=0; i<n; i++) {
379:         y[id[i]] += x[i];
380:       }
381:     } else {
382:       for (i=0; i<n; i++) {
383:         y[id[i]] += alpha*x[i];
384:       }
385:     }
386:     y += rstart;
387:     ISRestoreIndices(is,&id);
388:     VecRestoreArray(vfull,&y);
389:     VecRestoreArrayRead(vreduced,&x);
390:   }
391:   return(0);
392: }

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

399:    Collective on IS

401:    Input Parameter:
402: +  S -  a PETSc IS
403: -  V - the reference vector space

405:    Output Parameter:
406: .  T -  the complement of S

408: .seealso ISCreateGeneral()

410:    Level: advanced
411: @*/
412: PetscErrorCode ISComplementVec(IS S, Vec V, IS *T)
413: {
415:   PetscInt       start, end;

418:   VecGetOwnershipRange(V,&start,&end);
419:   ISComplement(S,start,end,T);
420:   return(0);
421: }

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

428:    Input Parameter:
429: +  V - the vector
430: .  S -  the locations in the vector
431: -  c - the constant

433: .seealso VecSet()

435:    Level: advanced
436: @*/
437: PetscErrorCode VecISSet(Vec V,IS S, PetscScalar c)
438: {
440:   PetscInt       nloc,low,high,i;
441:   const PetscInt *s;
442:   PetscScalar    *v;


450:   VecGetOwnershipRange(V, &low, &high);
451:   ISGetLocalSize(S,&nloc);
452:   ISGetIndices(S, &s);
453:   VecGetArray(V,&v);
454:   for (i=0; i<nloc; i++){
455:     v[s[i]-low] = c;
456:   }
457:   ISRestoreIndices(S, &s);
458:   VecRestoreArray(V,&v);
459:   return(0);
460: }

462: #if !defined(PETSC_USE_COMPLEX)
465: /*@C
466:   VecBoundGradientProjection - Projects  vector according to this definition.
467:   If XL[i] < X[i] < XU[i], then GP[i] = G[i];
468:   If X[i]<=XL[i], then GP[i] = min(G[i],0);
469:   If X[i]>=XU[i], then GP[i] = max(G[i],0);

471:   Input Parameters:
472: + G - current gradient vector
473: . X - current solution vector
474: . XL - lower bounds
475: - XU - upper bounds

477:   Output Parameter:
478: . GP - gradient projection vector

480:   Level: advanced
481: C@*/
482: PetscErrorCode VecBoundGradientProjection(Vec G, Vec X, Vec XL, Vec XU, Vec GP)
483: {

486:   PetscInt       n,i;
487:   PetscReal      *xptr,*xlptr,*xuptr,*gptr,*gpptr;
488:   PetscReal      xval,gpval;

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

498:   VecGetLocalSize(X,&n);

500:   ierr=VecGetArray(X,&xptr);
501:   ierr=VecGetArray(XL,&xlptr);
502:   ierr=VecGetArray(XU,&xuptr);
503:   ierr=VecGetArray(G,&gptr);
504:   if (G!=GP){
505:     ierr=VecGetArray(GP,&gpptr);
506:   } else { gpptr=gptr; }

508:   for (i=0; i<n; ++i){
509:     gpval = gptr[i]; xval = xptr[i];

511:     if (gpval>0 && xval<=xlptr[i]){
512:       gpval = 0;
513:     } else if (gpval<0 && xval>=xuptr[i]){
514:       gpval = 0;
515:     }
516:     gpptr[i] = gpval;
517:   }

519:   ierr=VecRestoreArray(X,&xptr);
520:   ierr=VecRestoreArray(XL,&xlptr);
521:   ierr=VecRestoreArray(XU,&xuptr);
522:   ierr=VecRestoreArray(G,&gptr);
523:   if (G!=GP){
524:     ierr=VecRestoreArray(GP,&gpptr);
525:   }
526:   return(0);
527: }
528: #endif

532: /*@
533:      VecStepMaxBounded - See below

535:      Collective on Vec

537:      Input Parameters:
538: +      X  - vector with no negative entries
539: .      XL - lower bounds
540: .      XU - upper bounds
541: -      DX  - step direction, can have negative, positive or zero entries

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

546: @*/
547: PetscErrorCode VecStepMaxBounded(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *stepmax)
548: {
550:   PetscInt       i,nn;
551:   PetscScalar    *xx,*dx,*xl,*xu;
552:   PetscReal      localmax=0;
553:   MPI_Comm       comm;


561:   VecGetArray(X,&xx);
562:   VecGetArray(XL,&xl);
563:   VecGetArray(XU,&xu);
564:   VecGetArray(DX,&dx);
565:   VecGetLocalSize(X,&nn);
566:   for (i=0;i<nn;i++){
567:     if (PetscRealPart(dx[i]) > 0){
568:       localmax=PetscMax(localmax,PetscRealPart((xu[i]-xx[i])/dx[i]));
569:     } else if (PetscRealPart(dx[i])<0){
570:       localmax=PetscMax(localmax,PetscRealPart((xl[i]-xx[i])/dx[i]));
571:     }
572:   }
573:   VecRestoreArray(X,&xx);
574:   VecRestoreArray(XL,&xl);
575:   VecRestoreArray(XU,&xu);
576:   VecRestoreArray(DX,&dx);
577:   PetscObjectGetComm((PetscObject)X,&comm);
578:   MPI_Allreduce(&localmax,stepmax,1,MPIU_REAL,MPIU_MAX,comm);
579:   return(0);
580: }

584: /*@
585:      VecStepBoundInfo - See below

587:      Collective on Vec

589:      Input Parameters:
590: +      X  - vector with no negative entries
591: .      XL - lower bounds
592: .      XU - upper bounds
593: -      DX  - step direction, can have negative, positive or zero entries

595:      Output Parameter:
596: +     boundmin -  maximum value so that   XL[i] <= X[i] + boundmax*DX[i] <= XU[i]
597: .     wolfemin -
598: -     boundmax -   minimum value so that X[i] + boundmax*DX[i] <= XL[i]  or  XU[i] <= X[i] + boundmax*DX[i]

600: @*/
601: PetscErrorCode VecStepBoundInfo(Vec X, Vec DX, Vec XL, Vec XU, PetscReal *boundmin, PetscReal *wolfemin, PetscReal *boundmax)
602: {
604:   PetscInt       n,i;
605:   PetscScalar    *x,*xl,*xu,*dx;
606:   PetscReal      t;
607:   PetscReal      localmin=PETSC_INFINITY,localwolfemin=PETSC_INFINITY,localmax=0;
608:   MPI_Comm       comm;


616:   ierr=VecGetArray(X,&x);
617:   ierr=VecGetArray(XL,&xl);
618:   ierr=VecGetArray(XU,&xu);
619:   ierr=VecGetArray(DX,&dx);
620:   VecGetLocalSize(X,&n);
621:   for (i=0;i<n;i++){
622:     if (PetscRealPart(dx[i])>0){
623:       t=PetscRealPart((xu[i]-x[i])/dx[i]);
624:       localmin=PetscMin(t,localmin);
625:       if (localmin>0){
626:         localwolfemin = PetscMin(t,localwolfemin);
627:       }
628:       localmax = PetscMax(t,localmax);
629:     } else if (PetscRealPart(dx[i])<0){
630:       t=PetscRealPart((xl[i]-x[i])/dx[i]);
631:       localmin = PetscMin(t,localmin);
632:       if (localmin>0){
633:         localwolfemin = PetscMin(t,localwolfemin);
634:       }
635:       localmax = PetscMax(t,localmax);
636:     }
637:   }
638:   ierr=VecRestoreArray(X,&x);
639:   ierr=VecRestoreArray(XL,&xl);
640:   ierr=VecRestoreArray(XU,&xu);
641:   ierr=VecRestoreArray(DX,&dx);
642:   ierr=PetscObjectGetComm((PetscObject)X,&comm);

644:   if (boundmin){
645:     MPI_Allreduce(&localmin,boundmin,1,MPIU_REAL,MPIU_MIN,comm);
646:     PetscInfo1(X,"Step Bound Info: Closest Bound: %g \n",(double)*boundmin);
647:   }
648:   if (wolfemin){
649:     MPI_Allreduce(&localwolfemin,wolfemin,1,MPIU_REAL,MPIU_MIN,comm);
650:     PetscInfo1(X,"Step Bound Info: Wolfe: %g \n",(double)*wolfemin);
651:   }
652:   if (boundmax) {
653:     MPI_Allreduce(&localmax,boundmax,1,MPIU_REAL,MPIU_MAX,comm);
654:     PetscInfo1(X,"Step Bound Info: Max: %g \n",(double)*boundmax);
655:   }
656:   return(0);
657: }

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

664:      Collective on Vec

666:      Input Parameters:
667: +      X  - vector with no negative entries
668: -      DX  - a step direction, can have negative, positive or zero entries

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

673:  @*/
674: PetscErrorCode VecStepMax(Vec X, Vec DX, PetscReal *step)
675: {
677:   PetscInt       i, nn;
678:   PetscReal      stepmax=PETSC_INFINITY;
679:   PetscScalar    *xx, *dx;
680:   MPI_Comm       comm;


686:   VecGetLocalSize(X,&nn);
687:   VecGetArray(X,&xx);
688:   VecGetArray(DX,&dx);
689:   for (i=0;i<nn;i++){
690:     if (PetscRealPart(xx[i]) < 0) SETERRQ(PETSC_COMM_SELF,1,"Vector must be positive");
691:     else if (PetscRealPart(dx[i])<0) stepmax=PetscMin(stepmax,PetscRealPart(-xx[i]/dx[i]));
692:   }
693:   VecRestoreArray(X,&xx);
694:   VecRestoreArray(DX,&dx);
695:   PetscObjectGetComm((PetscObject)X,&comm);
696:   MPI_Allreduce(&stepmax,step,1,MPIU_REAL,MPIU_MIN,comm);
697:   return(0);
698: }

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

705:   Logically Collective on v

707:   Input Parameter:
708: + v - the vector
709: - p - the exponent to use on each element

711:   Output Parameter:
712: . v - the vector

714:   Level: intermediate

716: @*/
717: PetscErrorCode VecPow(Vec v, PetscScalar p)
718: {
720:   PetscInt       n,i;
721:   PetscScalar    *v1;


726:   VecGetArray(v, &v1);
727:   VecGetLocalSize(v, &n);

729:   if (1.0 == p) {
730:   } else if (-1.0 == p) {
731:     for (i = 0; i < n; ++i){
732:       v1[i] = 1.0 / v1[i];
733:     }
734:   } else if (0.0 == p) {
735:     for (i = 0; i < n; ++i){
736:       /*  Not-a-number left alone
737:           Infinity set to one  */
738:       if (v1[i] == v1[i]) {
739:         v1[i] = 1.0;
740:       }
741:     }
742:   } else if (0.5 == p) {
743:     for (i = 0; i < n; ++i) {
744:       if (PetscRealPart(v1[i]) >= 0) {
745:         v1[i] = PetscSqrtScalar(v1[i]);
746:       } else {
747:         v1[i] = PETSC_INFINITY;
748:       }
749:     }
750:   } else if (-0.5 == p) {
751:     for (i = 0; i < n; ++i) {
752:       if (PetscRealPart(v1[i]) >= 0) {
753:         v1[i] = 1.0 / PetscSqrtScalar(v1[i]);
754:       } else {
755:         v1[i] = PETSC_INFINITY;
756:       }
757:     }
758:   } else if (2.0 == p) {
759:     for (i = 0; i < n; ++i){
760:       v1[i] *= v1[i];
761:     }
762:   } else if (-2.0 == p) {
763:     for (i = 0; i < n; ++i){
764:       v1[i] = 1.0 / (v1[i] * v1[i]);
765:     }
766:   } else {
767:     for (i = 0; i < n; ++i) {
768:       if (PetscRealPart(v1[i]) >= 0) {
769:         v1[i] = PetscPowScalar(v1[i], p);
770:       } else {
771:         v1[i] = PETSC_INFINITY;
772:       }
773:     }
774:   }
775:   VecRestoreArray(v,&v1);
776:   return(0);
777: }

781: /*@
782:   VecMedian - Computes the componentwise median of three vectors
783:   and stores the result in this vector.  Used primarily for projecting
784:   a vector within upper and lower bounds.

786:   Logically Collective

788:   Input Parameters:
789: . Vec1, Vec2, Vec3 - The three vectors

791:   Output Parameter:
792: . VMedian - The median vector

794:   Level: advanced
795: @*/
796: PetscErrorCode VecMedian(Vec Vec1, Vec Vec2, Vec Vec3, Vec VMedian)
797: {
799:   PetscInt       i,n,low1,low2,low3,low4,high1,high2,high3,high4;
800:   PetscScalar    *v1,*v2,*v3,*vmed;


808:   if (Vec1==Vec2 || Vec1==Vec3){
809:     ierr=VecCopy(Vec1,VMedian);
810:     return(0);
811:   }
812:   if (Vec2==Vec3){
813:     ierr=VecCopy(Vec2,VMedian);
814:     return(0);
815:   }


823:   VecGetOwnershipRange(Vec1, &low1, &high1);
824:   VecGetOwnershipRange(Vec2, &low2, &high2);
825:   VecGetOwnershipRange(Vec3, &low3, &high3);
826:   VecGetOwnershipRange(VMedian, &low4, &high4);
827:   if ( low1!= low2 || low1!= low3 || low1!= low4 || high1!= high2 || high1!= high3 || high1!= high4) SETERRQ(PETSC_COMM_SELF,1,"InCompatible vector local lengths");

829:   VecGetArray(Vec1,&v1);
830:   VecGetArray(Vec2,&v2);
831:   VecGetArray(Vec3,&v3);

833:   if ( VMedian != Vec1 && VMedian != Vec2 && VMedian != Vec3){
834:     VecGetArray(VMedian,&vmed);
835:   } else if ( VMedian==Vec1 ){
836:     vmed=v1;
837:   } else if ( VMedian==Vec2 ){
838:     vmed=v2;
839:   } else {
840:     vmed=v3;
841:   }

843:   ierr=VecGetLocalSize(Vec1,&n);

845:   for (i=0;i<n;i++){
846:     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])));
847:   }

849:   VecRestoreArray(Vec1,&v1);
850:   VecRestoreArray(Vec2,&v2);
851:   VecRestoreArray(Vec3,&v2);

853:   if (VMedian!=Vec1 && VMedian != Vec2 && VMedian != Vec3){
854:     VecRestoreArray(VMedian,&vmed);
855:   }
856:   return(0);
857: }