Actual source code: projection.c
petsc-dev 2014-02-02
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,< );
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, > );
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: }