Actual source code: vinv.c
1: /*
2: Some useful vector utility functions.
3: */
4: #include vecimpl.h
11: /*@
12: VecStrideScale - Scales a subvector of a vector defined
13: by a starting point and a stride.
15: Collective on Vec
17: Input Parameter:
18: + v - the vector
19: . start - starting point of the subvector (defined by a stride)
20: - scale - value to multiply each subvector entry by
22: Notes:
23: One must call VecSetBlockSize() before this routine to set the stride
24: information, or use a vector created from a multicomponent DA.
26: This will only work if the desire subvector is a stride subvector
28: Level: advanced
30: Concepts: scale^on stride of vector
31: Concepts: stride^scale
33: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
34: @*/
35: PetscErrorCode VecStrideScale(Vec v,PetscInt start,PetscScalar *scale)
36: {
38: PetscInt i,n,bs;
39: PetscScalar *x,xscale = *scale;
44: VecGetLocalSize(v,&n);
45: VecGetArray(v,&x);
47: bs = v->bs;
48: if (start >= bs) {
49: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
50: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
51: }
52: x += start;
54: for (i=0; i<n; i+=bs) {
55: x[i] *= xscale;
56: }
57: x -= start;
58: VecRestoreArray(v,&x);
59: return(0);
60: }
64: /*@C
65: VecStrideNorm - Computes the norm of subvector of a vector defined
66: by a starting point and a stride.
68: Collective on Vec
70: Input Parameter:
71: + v - the vector
72: . start - starting point of the subvector (defined by a stride)
73: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
75: Output Parameter:
76: . norm - the norm
78: Notes:
79: One must call VecSetBlockSize() before this routine to set the stride
80: information, or use a vector created from a multicomponent DA.
82: If x is the array representing the vector x then this computes the norm
83: of the array (x[start],x[start+stride],x[start+2*stride], ....)
85: This is useful for computing, say the norm of the pressure variable when
86: the pressure is stored (interlaced) with other variables, say density etc.
88: This will only work if the desire subvector is a stride subvector
90: Level: advanced
92: Concepts: norm^on stride of vector
93: Concepts: stride^norm
95: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
96: @*/
97: PetscErrorCode VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
98: {
100: PetscInt i,n,bs;
101: PetscScalar *x;
102: PetscReal tnorm;
103: MPI_Comm comm;
108: VecGetLocalSize(v,&n);
109: VecGetArray(v,&x);
110: PetscObjectGetComm((PetscObject)v,&comm);
112: bs = v->bs;
113: if (start >= bs) {
114: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
115: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
116: }
117: x += start;
119: if (ntype == NORM_2) {
120: PetscScalar sum = 0.0;
121: for (i=0; i<n; i+=bs) {
122: sum += x[i]*(PetscConj(x[i]));
123: }
124: tnorm = PetscRealPart(sum);
125: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
126: *nrm = sqrt(*nrm);
127: } else if (ntype == NORM_1) {
128: tnorm = 0.0;
129: for (i=0; i<n; i+=bs) {
130: tnorm += PetscAbsScalar(x[i]);
131: }
132: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
133: } else if (ntype == NORM_INFINITY) {
134: PetscReal tmp;
135: tnorm = 0.0;
137: for (i=0; i<n; i+=bs) {
138: if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
139: /* check special case of tmp == NaN */
140: if (tmp != tmp) {tnorm = tmp; break;}
141: }
142: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);
143: } else {
144: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
145: }
147: VecRestoreArray(v,&x);
148: return(0);
149: }
153: /*@
154: VecStrideMax - Computes the maximum of subvector of a vector defined
155: by a starting point and a stride and optionally its location.
157: Collective on Vec
159: Input Parameter:
160: + v - the vector
161: - start - starting point of the subvector (defined by a stride)
163: Output Parameter:
164: + index - the location where the maximum occurred (pass PETSC_NULL if not required)
165: - nrm - the max
167: Notes:
168: One must call VecSetBlockSize() before this routine to set the stride
169: information, or use a vector created from a multicomponent DA.
171: If xa is the array representing the vector x, then this computes the max
172: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
174: This is useful for computing, say the maximum of the pressure variable when
175: the pressure is stored (interlaced) with other variables, e.g., density, etc.
176: This will only work if the desire subvector is a stride subvector.
178: Level: advanced
180: Concepts: maximum^on stride of vector
181: Concepts: stride^maximum
183: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
184: @*/
185: PetscErrorCode VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
186: {
188: PetscInt i,n,bs,id;
189: PetscScalar *x;
190: PetscReal max,tmp;
191: MPI_Comm comm;
197: VecGetLocalSize(v,&n);
198: VecGetArray(v,&x);
199: PetscObjectGetComm((PetscObject)v,&comm);
201: bs = v->bs;
202: if (start >= bs) {
203: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
204: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
205: }
206: x += start;
208: id = -1;
209: if (!n) {
210: max = PETSC_MIN;
211: } else {
212: #if defined(PETSC_USE_COMPLEX)
213: max = PetscRealPart(x[0]);
214: #else
215: max = x[0];
216: #endif
217: for (i=bs; i<n; i+=bs) {
218: #if defined(PETSC_USE_COMPLEX)
219: if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
220: #else
221: if ((tmp = x[i]) > max) { max = tmp; id = i;}
222: #endif
223: }
224: }
225: VecRestoreArray(v,&x);
227: if (!idex) {
228: MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);
229: } else {
230: PetscReal in[2],out[2];
231: PetscInt rstart;
233: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
234: in[0] = max;
235: in[1] = rstart+id;
236: MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,v->comm);
237: *nrm = out[0];
238: *idex = (PetscInt)out[1];
239: }
241: return(0);
242: }
246: /*@
247: VecStrideMin - Computes the minimum of subvector of a vector defined
248: by a starting point and a stride and optionally its location.
250: Collective on Vec
252: Input Parameter:
253: + v - the vector
254: - start - starting point of the subvector (defined by a stride)
256: Output Parameter:
257: + idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
258: - nrm - the min
260: Level: advanced
262: Notes:
263: One must call VecSetBlockSize() before this routine to set the stride
264: information, or use a vector created from a multicomponent DA.
266: If xa is the array representing the vector x, then this computes the min
267: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
269: This is useful for computing, say the minimum of the pressure variable when
270: the pressure is stored (interlaced) with other variables, e.g., density, etc.
271: This will only work if the desire subvector is a stride subvector.
273: Concepts: minimum^on stride of vector
274: Concepts: stride^minimum
276: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
277: @*/
278: PetscErrorCode VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
279: {
281: PetscInt i,n,bs,id;
282: PetscScalar *x;
283: PetscReal min,tmp;
284: MPI_Comm comm;
290: VecGetLocalSize(v,&n);
291: VecGetArray(v,&x);
292: PetscObjectGetComm((PetscObject)v,&comm);
294: bs = v->bs;
295: if (start >= bs) {
296: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
297: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
298: }
299: x += start;
301: id = -1;
302: if (!n) {
303: min = PETSC_MAX;
304: } else {
305: #if defined(PETSC_USE_COMPLEX)
306: min = PetscRealPart(x[0]);
307: #else
308: min = x[0];
309: #endif
310: for (i=bs; i<n; i+=bs) {
311: #if defined(PETSC_USE_COMPLEX)
312: if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
313: #else
314: if ((tmp = x[i]) < min) { min = tmp; id = i;}
315: #endif
316: }
317: }
318: VecRestoreArray(v,&x);
320: if (!idex) {
321: MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
322: } else {
323: PetscReal in[2],out[2];
324: PetscInt rstart;
326: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
327: in[0] = min;
328: in[1] = rstart+id;
329: MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,v->comm);
330: *nrm = out[0];
331: *idex = (PetscInt)out[1];
332: }
334: return(0);
335: }
339: /*@
340: VecStrideScaleAll - Scales the subvectors of a vector defined
341: by a starting point and a stride.
343: Collective on Vec
345: Input Parameter:
346: + v - the vector
347: - scales - values to multiply each subvector entry by
349: Notes:
350: One must call VecSetBlockSize() before this routine to set the stride
351: information, or use a vector created from a multicomponent DA.
354: Level: advanced
356: Concepts: scale^on stride of vector
357: Concepts: stride^scale
359: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
360: @*/
361: PetscErrorCode VecStrideScaleAll(Vec v,PetscScalar *scales)
362: {
364: PetscInt i,j,n,bs;
365: PetscScalar *x;
370: VecGetLocalSize(v,&n);
371: VecGetArray(v,&x);
373: bs = v->bs;
375: /* need to provide optimized code for each bs */
376: for (i=0; i<n; i+=bs) {
377: for (j=0; j<bs; j++) {
378: x[i+j] *= scales[j];
379: }
380: }
381: VecRestoreArray(v,&x);
382: return(0);
383: }
387: /*@
388: VecStrideNormAll - Computes the norms subvectors of a vector defined
389: by a starting point and a stride.
391: Collective on Vec
393: Input Parameter:
394: + v - the vector
395: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
397: Output Parameter:
398: . nrm - the norms
400: Notes:
401: One must call VecSetBlockSize() before this routine to set the stride
402: information, or use a vector created from a multicomponent DA.
404: If x is the array representing the vector x then this computes the norm
405: of the array (x[start],x[start+stride],x[start+2*stride], ....)
407: This is useful for computing, say the norm of the pressure variable when
408: the pressure is stored (interlaced) with other variables, say density etc.
410: This will only work if the desire subvector is a stride subvector
412: Level: advanced
414: Concepts: norm^on stride of vector
415: Concepts: stride^norm
417: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
418: @*/
419: PetscErrorCode VecStrideNormAll(Vec v,NormType ntype,PetscReal *nrm)
420: {
422: PetscInt i,j,n,bs;
423: PetscScalar *x;
424: PetscReal tnorm[128];
425: MPI_Comm comm;
430: VecGetLocalSize(v,&n);
431: VecGetArray(v,&x);
432: PetscObjectGetComm((PetscObject)v,&comm);
434: bs = v->bs;
435: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
437: if (ntype == NORM_2) {
438: PetscScalar sum[128];
439: for (j=0; j<bs; j++) sum[j] = 0.0;
440: for (i=0; i<n; i+=bs) {
441: for (j=0; j<bs; j++) {
442: sum[j] += x[i+j]*(PetscConj(x[i+j]));
443: }
444: }
445: for (j=0; j<bs; j++) {
446: tnorm[j] = PetscRealPart(sum[j]);
447: }
448: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
449: for (j=0; j<bs; j++) {
450: nrm[j] = sqrt(nrm[j]);
451: }
452: } else if (ntype == NORM_1) {
453: for (j=0; j<bs; j++) {
454: tnorm[j] = 0.0;
455: }
456: for (i=0; i<n; i+=bs) {
457: for (j=0; j<bs; j++) {
458: tnorm[j] += PetscAbsScalar(x[i+j]);
459: }
460: }
461: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
462: } else if (ntype == NORM_INFINITY) {
463: PetscReal tmp;
464: for (j=0; j<bs; j++) {
465: tnorm[j] = 0.0;
466: }
468: for (i=0; i<n; i+=bs) {
469: for (j=0; j<bs; j++) {
470: if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
471: /* check special case of tmp == NaN */
472: if (tmp != tmp) {tnorm[j] = tmp; break;}
473: }
474: }
475: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);
476: } else {
477: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
478: }
480: VecRestoreArray(v,&x);
481: return(0);
482: }
486: /*@
487: VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
488: by a starting point and a stride and optionally its location.
490: Collective on Vec
492: Input Parameter:
493: . v - the vector
495: Output Parameter:
496: + index - the location where the maximum occurred (not supported, pass PETSC_NULL,
497: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
498: - nrm - the maximums
500: Notes:
501: One must call VecSetBlockSize() before this routine to set the stride
502: information, or use a vector created from a multicomponent DA.
504: This is useful for computing, say the maximum of the pressure variable when
505: the pressure is stored (interlaced) with other variables, e.g., density, etc.
506: This will only work if the desire subvector is a stride subvector.
508: Level: advanced
510: Concepts: maximum^on stride of vector
511: Concepts: stride^maximum
513: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
514: @*/
515: PetscErrorCode VecStrideMaxAll(Vec v,PetscInt *idex,PetscReal *nrm)
516: {
518: PetscInt i,j,n,bs;
519: PetscScalar *x;
520: PetscReal max[128],tmp;
521: MPI_Comm comm;
526: if (idex) {
527: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
528: }
529: VecGetLocalSize(v,&n);
530: VecGetArray(v,&x);
531: PetscObjectGetComm((PetscObject)v,&comm);
533: bs = v->bs;
534: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
536: if (!n) {
537: for (j=0; j<bs; j++) {
538: max[j] = PETSC_MIN;
539: }
540: } else {
541: for (j=0; j<bs; j++) {
542: #if defined(PETSC_USE_COMPLEX)
543: max[j] = PetscRealPart(x[j]);
544: #else
545: max[j] = x[j];
546: #endif
547: }
548: for (i=bs; i<n; i+=bs) {
549: for (j=0; j<bs; j++) {
550: #if defined(PETSC_USE_COMPLEX)
551: if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
552: #else
553: if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
554: #endif
555: }
556: }
557: }
558: MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);
560: VecRestoreArray(v,&x);
561: return(0);
562: }
566: /*@
567: VecStrideMinAll - Computes the minimum of subvector of a vector defined
568: by a starting point and a stride and optionally its location.
570: Collective on Vec
572: Input Parameter:
573: . v - the vector
575: Output Parameter:
576: + idex - the location where the minimum occurred (not supported, pass PETSC_NULL,
577: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
578: - nrm - the minimums
580: Level: advanced
582: Notes:
583: One must call VecSetBlockSize() before this routine to set the stride
584: information, or use a vector created from a multicomponent DA.
586: This is useful for computing, say the minimum of the pressure variable when
587: the pressure is stored (interlaced) with other variables, e.g., density, etc.
588: This will only work if the desire subvector is a stride subvector.
590: Concepts: minimum^on stride of vector
591: Concepts: stride^minimum
593: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
594: @*/
595: PetscErrorCode VecStrideMinAll(Vec v,PetscInt *idex,PetscReal *nrm)
596: {
598: PetscInt i,n,bs,j;
599: PetscScalar *x;
600: PetscReal min[128],tmp;
601: MPI_Comm comm;
606: if (idex) {
607: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
608: }
609: VecGetLocalSize(v,&n);
610: VecGetArray(v,&x);
611: PetscObjectGetComm((PetscObject)v,&comm);
613: bs = v->bs;
614: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
616: if (!n) {
617: for (j=0; j<bs; j++) {
618: min[j] = PETSC_MAX;
619: }
620: } else {
621: for (j=0; j<bs; j++) {
622: #if defined(PETSC_USE_COMPLEX)
623: min[j] = PetscRealPart(x[j]);
624: #else
625: min[j] = x[j];
626: #endif
627: }
628: for (i=bs; i<n; i+=bs) {
629: for (j=0; j<bs; j++) {
630: #if defined(PETSC_USE_COMPLEX)
631: if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
632: #else
633: if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
634: #endif
635: }
636: }
637: }
638: MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);
640: VecRestoreArray(v,&x);
641: return(0);
642: }
644: /*----------------------------------------------------------------------------------------------*/
647: /*@
648: VecStrideGatherAll - Gathers all the single components from a multi-component vector into
649: seperate vectors.
651: Collective on Vec
653: Input Parameter:
654: + v - the vector
655: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
657: Output Parameter:
658: . s - the location where the subvectors are stored
660: Notes:
661: One must call VecSetBlockSize() before this routine to set the stride
662: information, or use a vector created from a multicomponent DA.
664: If x is the array representing the vector x then this gathers
665: the arrays (x[start],x[start+stride],x[start+2*stride], ....)
666: for start=0,1,2,...bs-1
668: The parallel layout of the vector and the subvector must be the same;
669: i.e., nlocal of v = stride*(nlocal of s)
671: Not optimized; could be easily
673: Level: advanced
675: Concepts: gather^into strided vector
677: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
678: VecStrideScatterAll()
679: @*/
680: PetscErrorCode VecStrideGatherAll(Vec v,Vec *s,InsertMode addv)
681: {
683: PetscInt i,n,bs,j,k,*bss,nv,jj,nvc;
684: PetscScalar *x,**y;
690: VecGetLocalSize(v,&n);
691: VecGetArray(v,&x);
692: bs = v->bs;
693: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
695: PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
696: nv = 0;
697: nvc = 0;
698: for (i=0; i<bs; i++) {
699: VecGetBlockSize(s[i],&bss[i]);
700: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
701: VecGetArray(s[i],&y[i]);
702: nvc += bss[i];
703: nv++;
704: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
705: if (nvc == bs) break;
706: }
708: n = n/bs;
710: jj = 0;
711: if (addv == INSERT_VALUES) {
712: for (j=0; j<nv; j++) {
713: for (k=0; k<bss[j]; k++) {
714: for (i=0; i<n; i++) {
715: y[j][i*bss[j] + k] = x[bs*i+jj+k];
716: }
717: }
718: jj += bss[j];
719: }
720: } else if (addv == ADD_VALUES) {
721: for (j=0; j<nv; j++) {
722: for (k=0; k<bss[j]; k++) {
723: for (i=0; i<n; i++) {
724: y[j][i*bss[j] + k] += x[bs*i+jj+k];
725: }
726: }
727: jj += bss[j];
728: }
729: #if !defined(PETSC_USE_COMPLEX)
730: } else if (addv == MAX_VALUES) {
731: for (j=0; j<nv; j++) {
732: for (k=0; k<bss[j]; k++) {
733: for (i=0; i<n; i++) {
734: y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
735: }
736: }
737: jj += bss[j];
738: }
739: #endif
740: } else {
741: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
742: }
744: VecRestoreArray(v,&x);
745: for (i=0; i<nv; i++) {
746: VecRestoreArray(s[i],&y[i]);
747: }
748: PetscFree2(y,bss);
749: return(0);
750: }
754: /*@
755: VecStrideScatterAll - Scatters all the single components from seperate vectors into
756: a multi-component vector.
758: Collective on Vec
760: Input Parameter:
761: + s - the location where the subvectors are stored
762: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
764: Output Parameter:
765: . v - the multicomponent vector
767: Notes:
768: One must call VecSetBlockSize() before this routine to set the stride
769: information, or use a vector created from a multicomponent DA.
771: The parallel layout of the vector and the subvector must be the same;
772: i.e., nlocal of v = stride*(nlocal of s)
774: Not optimized; could be easily
776: Level: advanced
778: Concepts: scatter^into strided vector
780: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
781: VecStrideScatterAll()
782: @*/
783: PetscErrorCode VecStrideScatterAll(Vec *s,Vec v,InsertMode addv)
784: {
786: PetscInt i,n,bs,j,jj,k,*bss,nv,nvc;
787: PetscScalar *x,**y;
793: VecGetLocalSize(v,&n);
794: VecGetArray(v,&x);
795: bs = v->bs;
796: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
798: PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
799: nv = 0;
800: nvc = 0;
801: for (i=0; i<bs; i++) {
802: VecGetBlockSize(s[i],&bss[i]);
803: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
804: VecGetArray(s[i],&y[i]);
805: nvc += bss[i];
806: nv++;
807: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
808: if (nvc == bs) break;
809: }
811: n = n/bs;
813: jj = 0;
814: if (addv == INSERT_VALUES) {
815: for (j=0; j<nv; j++) {
816: for (k=0; k<bss[j]; k++) {
817: for (i=0; i<n; i++) {
818: x[bs*i+jj+k] = y[j][i*bss[j] + k];
819: }
820: }
821: jj += bss[j];
822: }
823: } else if (addv == ADD_VALUES) {
824: for (j=0; j<nv; j++) {
825: for (k=0; k<bss[j]; k++) {
826: for (i=0; i<n; i++) {
827: x[bs*i+jj+k] += y[j][i*bss[j] + k];
828: }
829: }
830: jj += bss[j];
831: }
832: #if !defined(PETSC_USE_COMPLEX)
833: } else if (addv == MAX_VALUES) {
834: for (j=0; j<nv; j++) {
835: for (k=0; k<bss[j]; k++) {
836: for (i=0; i<n; i++) {
837: x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
838: }
839: }
840: jj += bss[j];
841: }
842: #endif
843: } else {
844: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
845: }
847: VecRestoreArray(v,&x);
848: for (i=0; i<nv; i++) {
849: VecRestoreArray(s[i],&y[i]);
850: }
851: PetscFree2(y,bss);
852: return(0);
853: }
857: /*@
858: VecStrideGather - Gathers a single component from a multi-component vector into
859: another vector.
861: Collective on Vec
863: Input Parameter:
864: + v - the vector
865: . start - starting point of the subvector (defined by a stride)
866: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
868: Output Parameter:
869: . s - the location where the subvector is stored
871: Notes:
872: One must call VecSetBlockSize() before this routine to set the stride
873: information, or use a vector created from a multicomponent DA.
875: If x is the array representing the vector x then this gathers
876: the array (x[start],x[start+stride],x[start+2*stride], ....)
878: The parallel layout of the vector and the subvector must be the same;
879: i.e., nlocal of v = stride*(nlocal of s)
881: Not optimized; could be easily
883: Level: advanced
885: Concepts: gather^into strided vector
887: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
888: VecStrideScatterAll()
889: @*/
890: PetscErrorCode VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
891: {
893: PetscInt i,n,bs,ns;
894: PetscScalar *x,*y;
899: VecGetLocalSize(v,&n);
900: VecGetLocalSize(s,&ns);
901: VecGetArray(v,&x);
902: VecGetArray(s,&y);
904: bs = v->bs;
905: if (start >= bs) {
906: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
907: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
908: }
909: if (n != ns*bs) {
910: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
911: }
912: x += start;
913: n = n/bs;
915: if (addv == INSERT_VALUES) {
916: for (i=0; i<n; i++) {
917: y[i] = x[bs*i];
918: }
919: } else if (addv == ADD_VALUES) {
920: for (i=0; i<n; i++) {
921: y[i] += x[bs*i];
922: }
923: #if !defined(PETSC_USE_COMPLEX)
924: } else if (addv == MAX_VALUES) {
925: for (i=0; i<n; i++) {
926: y[i] = PetscMax(y[i],x[bs*i]);
927: }
928: #endif
929: } else {
930: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
931: }
933: VecRestoreArray(v,&x);
934: VecRestoreArray(s,&y);
935: return(0);
936: }
940: /*@
941: VecStrideScatter - Scatters a single component from a vector into a multi-component vector.
943: Collective on Vec
945: Input Parameter:
946: + s - the single-component vector
947: . start - starting point of the subvector (defined by a stride)
948: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
950: Output Parameter:
951: . v - the location where the subvector is scattered (the multi-component vector)
953: Notes:
954: One must call VecSetBlockSize() on the multi-component vector before this
955: routine to set the stride information, or use a vector created from a multicomponent DA.
957: The parallel layout of the vector and the subvector must be the same;
958: i.e., nlocal of v = stride*(nlocal of s)
960: Not optimized; could be easily
962: Level: advanced
964: Concepts: scatter^into strided vector
966: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
967: VecStrideScatterAll()
968: @*/
969: PetscErrorCode VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
970: {
972: PetscInt i,n,bs,ns;
973: PetscScalar *x,*y;
978: VecGetLocalSize(v,&n);
979: VecGetLocalSize(s,&ns);
980: VecGetArray(v,&x);
981: VecGetArray(s,&y);
983: bs = v->bs;
984: if (start >= bs) {
985: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
986: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
987: }
988: if (n != ns*bs) {
989: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
990: }
991: x += start;
992: n = n/bs;
995: if (addv == INSERT_VALUES) {
996: for (i=0; i<n; i++) {
997: x[bs*i] = y[i];
998: }
999: } else if (addv == ADD_VALUES) {
1000: for (i=0; i<n; i++) {
1001: x[bs*i] += y[i];
1002: }
1003: #if !defined(PETSC_USE_COMPLEX)
1004: } else if (addv == MAX_VALUES) {
1005: for (i=0; i<n; i++) {
1006: x[bs*i] = PetscMax(y[i],x[bs*i]);
1007: }
1008: #endif
1009: } else {
1010: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1011: }
1014: VecRestoreArray(v,&x);
1015: VecRestoreArray(s,&y);
1016: return(0);
1017: }
1021: PetscErrorCode VecReciprocal_Default(Vec v)
1022: {
1024: PetscInt i,n;
1025: PetscScalar *x;
1028: VecGetLocalSize(v,&n);
1029: VecGetArray(v,&x);
1030: for (i=0; i<n; i++) {
1031: if (x[i] != 0.0) x[i] = 1.0/x[i];
1032: }
1033: VecRestoreArray(v,&x);
1034: return(0);
1035: }
1039: /*@
1040: VecSqrt - Replaces each component of a vector by the square root of its magnitude.
1042: Not collective
1044: Input Parameter:
1045: . v - The vector
1047: Output Parameter:
1048: . v - The vector square root
1050: Level: beginner
1052: Note: The actual function is sqrt(|x_i|)
1054: .keywords: vector, sqrt, square root
1055: @*/
1056: PetscErrorCode VecSqrt(Vec v)
1057: {
1058: PetscScalar *x;
1059: PetscInt i, n;
1064: VecGetLocalSize(v, &n);
1065: VecGetArray(v, &x);
1066: for(i = 0; i < n; i++) {
1067: x[i] = sqrt(PetscAbsScalar(x[i]));
1068: }
1069: VecRestoreArray(v, &x);
1070: return(0);
1071: }
1075: /*@
1076: VecSum - Computes the sum of all the components of a vector.
1078: Collective on Vec
1080: Input Parameter:
1081: . v - the vector
1083: Output Parameter:
1084: . sum - the result
1086: Level: beginner
1088: Concepts: sum^of vector entries
1090: .seealso: VecNorm()
1091: @*/
1092: PetscErrorCode VecSum(Vec v,PetscScalar *sum)
1093: {
1095: PetscInt i,n;
1096: PetscScalar *x,lsum = 0.0;
1101: VecGetLocalSize(v,&n);
1102: VecGetArray(v,&x);
1103: for (i=0; i<n; i++) {
1104: lsum += x[i];
1105: }
1106: MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,PetscSum_Op,v->comm);
1107: VecRestoreArray(v,&x);
1108: return(0);
1109: }
1113: /*@
1114: VecShift - Shifts all of the components of a vector by computing
1115: x[i] = x[i] + shift.
1117: Collective on Vec
1119: Input Parameters:
1120: + v - the vector
1121: - shift - the shift
1123: Output Parameter:
1124: . v - the shifted vector
1126: Level: intermediate
1128: Concepts: vector^adding constant
1130: @*/
1131: PetscErrorCode VecShift(const PetscScalar *shift,Vec v)
1132: {
1134: PetscInt i,n;
1135: PetscScalar *x,lsum = *shift;
1140: VecGetLocalSize(v,&n);
1141: VecGetArray(v,&x);
1142: for (i=0; i<n; i++) {
1143: x[i] += lsum;
1144: }
1145: VecRestoreArray(v,&x);
1146: return(0);
1147: }
1151: /*@
1152: VecAbs - Replaces every element in a vector with its absolute value.
1154: Collective on Vec
1156: Input Parameters:
1157: . v - the vector
1159: Level: intermediate
1161: Concepts: vector^absolute value
1163: @*/
1164: PetscErrorCode VecAbs(Vec v)
1165: {
1167: PetscInt i,n;
1168: PetscScalar *x;
1172: VecGetLocalSize(v,&n);
1173: VecGetArray(v,&x);
1174: for (i=0; i<n; i++) {
1175: x[i] = PetscAbsScalar(x[i]);
1176: }
1177: VecRestoreArray(v,&x);
1178: return(0);
1179: }
1183: /*@
1184: VecPermute - Permutes a vector in place using the given ordering.
1186: Input Parameters:
1187: + vec - The vector
1188: . order - The ordering
1189: - inv - The flag for inverting the permutation
1191: Level: beginner
1193: Note: This function does not yet support parallel Index Sets
1195: .seealso: MatPermute()
1196: .keywords: vec, permute
1197: @*/
1198: PetscErrorCode VecPermute(Vec x, IS row, PetscTruth inv)
1199: {
1200: PetscScalar *array, *newArray;
1201: PetscInt *idx;
1202: PetscInt i;
1206: ISGetIndices(row, &idx);
1207: VecGetArray(x, &array);
1208: PetscMalloc(x->n*sizeof(PetscScalar), &newArray);
1209: #ifdef PETSC_USE_BOPT_g
1210: for(i = 0; i < x->n; i++) {
1211: if ((idx[i] < 0) || (idx[i] >= x->n)) {
1212: SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1213: }
1214: }
1215: #endif
1216: if (inv == PETSC_FALSE) {
1217: for(i = 0; i < x->n; i++) newArray[i] = array[idx[i]];
1218: } else {
1219: for(i = 0; i < x->n; i++) newArray[idx[i]] = array[i];
1220: }
1221: VecRestoreArray(x, &array);
1222: ISRestoreIndices(row, &idx);
1223: VecReplaceArray(x, newArray);
1224: return(0);
1225: }
1229: /*@
1230: VecEqual - Compares two vectors.
1232: Collective on Vec
1234: Input Parameters:
1235: + vec1 - the first matrix
1236: - vec2 - the second matrix
1238: Output Parameter:
1239: . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.
1241: Level: intermediate
1243: Concepts: equal^two vectors
1244: Concepts: vector^equality
1246: @*/
1247: PetscErrorCode VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1248: {
1249: PetscScalar *v1,*v2;
1251: PetscInt n1,n2;
1252: PetscTruth flg1;
1255: VecGetSize(vec1,&n1);
1256: VecGetSize(vec2,&n2);
1257: if (vec1 == vec2) {
1258: flg1 = PETSC_TRUE;
1259: } else if (n1 != n2) {
1260: flg1 = PETSC_FALSE;
1261: } else {
1262: VecGetArray(vec1,&v1);
1263: VecGetArray(vec2,&v2);
1264: PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1265: VecRestoreArray(vec1,&v1);
1266: VecRestoreArray(vec2,&v2);
1267: }
1269: /* combine results from all processors */
1270: MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);
1271: return(0);
1272: }