Actual source code: vinv.c
1: #define PETSCVEC_DLL
3: /*
4: Some useful vector utility functions.
5: */
6: #include private/vecimpl.h
13: /*@
14: VecStrideScale - Scales a subvector of a vector defined
15: by a starting point and a stride.
17: Collective on Vec
19: Input Parameter:
20: + v - the vector
21: . start - starting point of the subvector (defined by a stride)
22: - scale - value to multiply each subvector entry by
24: Notes:
25: One must call VecSetBlockSize() before this routine to set the stride
26: information, or use a vector created from a multicomponent DA.
28: This will only work if the desire subvector is a stride subvector
30: Level: advanced
32: Concepts: scale^on stride of vector
33: Concepts: stride^scale
35: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
36: @*/
37: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScale(Vec v,PetscInt start,PetscScalar *scale)
38: {
40: PetscInt i,n,bs;
41: PetscScalar *x,xscale = *scale;
46: VecGetLocalSize(v,&n);
47: VecGetArray(v,&x);
49: bs = v->map.bs;
50: if (start >= bs) {
51: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
52: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
53: }
54: x += start;
56: for (i=0; i<n; i+=bs) {
57: x[i] *= xscale;
58: }
59: x -= start;
60: VecRestoreArray(v,&x);
61: return(0);
62: }
66: /*@
67: VecStrideNorm - Computes the norm of subvector of a vector defined
68: by a starting point and a stride.
70: Collective on Vec
72: Input Parameter:
73: + v - the vector
74: . start - starting point of the subvector (defined by a stride)
75: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
77: Output Parameter:
78: . norm - the norm
80: Notes:
81: One must call VecSetBlockSize() before this routine to set the stride
82: information, or use a vector created from a multicomponent DA.
84: If x is the array representing the vector x then this computes the norm
85: of the array (x[start],x[start+stride],x[start+2*stride], ....)
87: This is useful for computing, say the norm of the pressure variable when
88: the pressure is stored (interlaced) with other variables, say density etc.
90: This will only work if the desire subvector is a stride subvector
92: Level: advanced
94: Concepts: norm^on stride of vector
95: Concepts: stride^norm
97: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
98: @*/
99: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
100: {
102: PetscInt i,n,bs;
103: PetscScalar *x;
104: PetscReal tnorm;
105: MPI_Comm comm;
110: VecGetLocalSize(v,&n);
111: VecGetArray(v,&x);
112: PetscObjectGetComm((PetscObject)v,&comm);
114: bs = v->map.bs;
115: if (start >= bs) {
116: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
117: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
118: }
119: x += start;
121: if (ntype == NORM_2) {
122: PetscScalar sum = 0.0;
123: for (i=0; i<n; i+=bs) {
124: sum += x[i]*(PetscConj(x[i]));
125: }
126: tnorm = PetscRealPart(sum);
127: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
128: *nrm = sqrt(*nrm);
129: } else if (ntype == NORM_1) {
130: tnorm = 0.0;
131: for (i=0; i<n; i+=bs) {
132: tnorm += PetscAbsScalar(x[i]);
133: }
134: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
135: } else if (ntype == NORM_INFINITY) {
136: PetscReal tmp;
137: tnorm = 0.0;
139: for (i=0; i<n; i+=bs) {
140: if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
141: /* check special case of tmp == NaN */
142: if (tmp != tmp) {tnorm = tmp; break;}
143: }
144: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);
145: } else {
146: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
147: }
149: VecRestoreArray(v,&x);
150: return(0);
151: }
155: /*@
156: VecStrideMax - Computes the maximum of subvector of a vector defined
157: by a starting point and a stride and optionally its location.
159: Collective on Vec
161: Input Parameter:
162: + v - the vector
163: - start - starting point of the subvector (defined by a stride)
165: Output Parameter:
166: + index - the location where the maximum occurred (pass PETSC_NULL if not required)
167: - nrm - the max
169: Notes:
170: One must call VecSetBlockSize() before this routine to set the stride
171: information, or use a vector created from a multicomponent DA.
173: If xa is the array representing the vector x, then this computes the max
174: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
176: This is useful for computing, say the maximum of the pressure variable when
177: the pressure is stored (interlaced) with other variables, e.g., density, etc.
178: This will only work if the desire subvector is a stride subvector.
180: Level: advanced
182: Concepts: maximum^on stride of vector
183: Concepts: stride^maximum
185: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
186: @*/
187: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
188: {
190: PetscInt i,n,bs,id;
191: PetscScalar *x;
192: PetscReal max,tmp;
193: MPI_Comm comm;
199: VecGetLocalSize(v,&n);
200: VecGetArray(v,&x);
201: PetscObjectGetComm((PetscObject)v,&comm);
203: bs = v->map.bs;
204: if (start >= bs) {
205: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
206: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
207: }
208: x += start;
210: id = -1;
211: if (!n) {
212: max = PETSC_MIN;
213: } else {
214: id = 0;
215: #if defined(PETSC_USE_COMPLEX)
216: max = PetscRealPart(x[0]);
217: #else
218: max = x[0];
219: #endif
220: for (i=bs; i<n; i+=bs) {
221: #if defined(PETSC_USE_COMPLEX)
222: if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
223: #else
224: if ((tmp = x[i]) > max) { max = tmp; id = i;}
225: #endif
226: }
227: }
228: VecRestoreArray(v,&x);
230: if (!idex) {
231: MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);
232: } else {
233: PetscReal in[2],out[2];
234: PetscInt rstart;
236: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
237: in[0] = max;
238: in[1] = rstart+id;
239: MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,v->comm);
240: *nrm = out[0];
241: *idex = (PetscInt)out[1];
242: }
244: return(0);
245: }
249: /*@
250: VecStrideMin - Computes the minimum of subvector of a vector defined
251: by a starting point and a stride and optionally its location.
253: Collective on Vec
255: Input Parameter:
256: + v - the vector
257: - start - starting point of the subvector (defined by a stride)
259: Output Parameter:
260: + idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
261: - nrm - the min
263: Level: advanced
265: Notes:
266: One must call VecSetBlockSize() before this routine to set the stride
267: information, or use a vector created from a multicomponent DA.
269: If xa is the array representing the vector x, then this computes the min
270: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
272: This is useful for computing, say the minimum of the pressure variable when
273: the pressure is stored (interlaced) with other variables, e.g., density, etc.
274: This will only work if the desire subvector is a stride subvector.
276: Concepts: minimum^on stride of vector
277: Concepts: stride^minimum
279: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
280: @*/
281: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
282: {
284: PetscInt i,n,bs,id;
285: PetscScalar *x;
286: PetscReal min,tmp;
287: MPI_Comm comm;
293: VecGetLocalSize(v,&n);
294: VecGetArray(v,&x);
295: PetscObjectGetComm((PetscObject)v,&comm);
297: bs = v->map.bs;
298: if (start >= bs) {
299: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
300: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
301: }
302: x += start;
304: id = -1;
305: if (!n) {
306: min = PETSC_MAX;
307: } else {
308: id = 0;
309: #if defined(PETSC_USE_COMPLEX)
310: min = PetscRealPart(x[0]);
311: #else
312: min = x[0];
313: #endif
314: for (i=bs; i<n; i+=bs) {
315: #if defined(PETSC_USE_COMPLEX)
316: if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
317: #else
318: if ((tmp = x[i]) < min) { min = tmp; id = i;}
319: #endif
320: }
321: }
322: VecRestoreArray(v,&x);
324: if (!idex) {
325: MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
326: } else {
327: PetscReal in[2],out[2];
328: PetscInt rstart;
330: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
331: in[0] = min;
332: in[1] = rstart+id;
333: MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,v->comm);
334: *nrm = out[0];
335: *idex = (PetscInt)out[1];
336: }
338: return(0);
339: }
343: /*@
344: VecStrideScaleAll - Scales the subvectors of a vector defined
345: by a starting point and a stride.
347: Collective on Vec
349: Input Parameter:
350: + v - the vector
351: - scales - values to multiply each subvector entry by
353: Notes:
354: One must call VecSetBlockSize() before this routine to set the stride
355: information, or use a vector created from a multicomponent DA.
358: Level: advanced
360: Concepts: scale^on stride of vector
361: Concepts: stride^scale
363: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
364: @*/
365: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScaleAll(Vec v,PetscScalar *scales)
366: {
368: PetscInt i,j,n,bs;
369: PetscScalar *x;
374: VecGetLocalSize(v,&n);
375: VecGetArray(v,&x);
377: bs = v->map.bs;
379: /* need to provide optimized code for each bs */
380: for (i=0; i<n; i+=bs) {
381: for (j=0; j<bs; j++) {
382: x[i+j] *= scales[j];
383: }
384: }
385: VecRestoreArray(v,&x);
386: return(0);
387: }
391: /*@
392: VecStrideNormAll - Computes the norms subvectors of a vector defined
393: by a starting point and a stride.
395: Collective on Vec
397: Input Parameter:
398: + v - the vector
399: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
401: Output Parameter:
402: . nrm - the norms
404: Notes:
405: One must call VecSetBlockSize() before this routine to set the stride
406: information, or use a vector created from a multicomponent DA.
408: If x is the array representing the vector x then this computes the norm
409: of the array (x[start],x[start+stride],x[start+2*stride], ....)
411: This is useful for computing, say the norm of the pressure variable when
412: the pressure is stored (interlaced) with other variables, say density etc.
414: This will only work if the desire subvector is a stride subvector
416: Level: advanced
418: Concepts: norm^on stride of vector
419: Concepts: stride^norm
421: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
422: @*/
423: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNormAll(Vec v,NormType ntype,PetscReal *nrm)
424: {
426: PetscInt i,j,n,bs;
427: PetscScalar *x;
428: PetscReal tnorm[128];
429: MPI_Comm comm;
434: VecGetLocalSize(v,&n);
435: VecGetArray(v,&x);
436: PetscObjectGetComm((PetscObject)v,&comm);
438: bs = v->map.bs;
439: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
441: if (ntype == NORM_2) {
442: PetscScalar sum[128];
443: for (j=0; j<bs; j++) sum[j] = 0.0;
444: for (i=0; i<n; i+=bs) {
445: for (j=0; j<bs; j++) {
446: sum[j] += x[i+j]*(PetscConj(x[i+j]));
447: }
448: }
449: for (j=0; j<bs; j++) {
450: tnorm[j] = PetscRealPart(sum[j]);
451: }
452: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
453: for (j=0; j<bs; j++) {
454: nrm[j] = sqrt(nrm[j]);
455: }
456: } else if (ntype == NORM_1) {
457: for (j=0; j<bs; j++) {
458: tnorm[j] = 0.0;
459: }
460: for (i=0; i<n; i+=bs) {
461: for (j=0; j<bs; j++) {
462: tnorm[j] += PetscAbsScalar(x[i+j]);
463: }
464: }
465: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
466: } else if (ntype == NORM_INFINITY) {
467: PetscReal tmp;
468: for (j=0; j<bs; j++) {
469: tnorm[j] = 0.0;
470: }
472: for (i=0; i<n; i+=bs) {
473: for (j=0; j<bs; j++) {
474: if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
475: /* check special case of tmp == NaN */
476: if (tmp != tmp) {tnorm[j] = tmp; break;}
477: }
478: }
479: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);
480: } else {
481: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
482: }
484: VecRestoreArray(v,&x);
485: return(0);
486: }
490: /*@
491: VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
492: by a starting point and a stride and optionally its location.
494: Collective on Vec
496: Input Parameter:
497: . v - the vector
499: Output Parameter:
500: + index - the location where the maximum occurred (not supported, pass PETSC_NULL,
501: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
502: - nrm - the maximums
504: Notes:
505: One must call VecSetBlockSize() before this routine to set the stride
506: information, or use a vector created from a multicomponent DA.
508: This is useful for computing, say the maximum of the pressure variable when
509: the pressure is stored (interlaced) with other variables, e.g., density, etc.
510: This will only work if the desire subvector is a stride subvector.
512: Level: advanced
514: Concepts: maximum^on stride of vector
515: Concepts: stride^maximum
517: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
518: @*/
519: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMaxAll(Vec v,PetscInt *idex,PetscReal *nrm)
520: {
522: PetscInt i,j,n,bs;
523: PetscScalar *x;
524: PetscReal max[128],tmp;
525: MPI_Comm comm;
530: if (idex) {
531: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
532: }
533: VecGetLocalSize(v,&n);
534: VecGetArray(v,&x);
535: PetscObjectGetComm((PetscObject)v,&comm);
537: bs = v->map.bs;
538: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
540: if (!n) {
541: for (j=0; j<bs; j++) {
542: max[j] = PETSC_MIN;
543: }
544: } else {
545: for (j=0; j<bs; j++) {
546: #if defined(PETSC_USE_COMPLEX)
547: max[j] = PetscRealPart(x[j]);
548: #else
549: max[j] = x[j];
550: #endif
551: }
552: for (i=bs; i<n; i+=bs) {
553: for (j=0; j<bs; j++) {
554: #if defined(PETSC_USE_COMPLEX)
555: if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
556: #else
557: if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
558: #endif
559: }
560: }
561: }
562: MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);
564: VecRestoreArray(v,&x);
565: return(0);
566: }
570: /*@
571: VecStrideMinAll - Computes the minimum of subvector of a vector defined
572: by a starting point and a stride and optionally its location.
574: Collective on Vec
576: Input Parameter:
577: . v - the vector
579: Output Parameter:
580: + idex - the location where the minimum occurred (not supported, pass PETSC_NULL,
581: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
582: - nrm - the minimums
584: Level: advanced
586: Notes:
587: One must call VecSetBlockSize() before this routine to set the stride
588: information, or use a vector created from a multicomponent DA.
590: This is useful for computing, say the minimum of the pressure variable when
591: the pressure is stored (interlaced) with other variables, e.g., density, etc.
592: This will only work if the desire subvector is a stride subvector.
594: Concepts: minimum^on stride of vector
595: Concepts: stride^minimum
597: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
598: @*/
599: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMinAll(Vec v,PetscInt *idex,PetscReal *nrm)
600: {
602: PetscInt i,n,bs,j;
603: PetscScalar *x;
604: PetscReal min[128],tmp;
605: MPI_Comm comm;
610: if (idex) {
611: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
612: }
613: VecGetLocalSize(v,&n);
614: VecGetArray(v,&x);
615: PetscObjectGetComm((PetscObject)v,&comm);
617: bs = v->map.bs;
618: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
620: if (!n) {
621: for (j=0; j<bs; j++) {
622: min[j] = PETSC_MAX;
623: }
624: } else {
625: for (j=0; j<bs; j++) {
626: #if defined(PETSC_USE_COMPLEX)
627: min[j] = PetscRealPart(x[j]);
628: #else
629: min[j] = x[j];
630: #endif
631: }
632: for (i=bs; i<n; i+=bs) {
633: for (j=0; j<bs; j++) {
634: #if defined(PETSC_USE_COMPLEX)
635: if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
636: #else
637: if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
638: #endif
639: }
640: }
641: }
642: MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);
644: VecRestoreArray(v,&x);
645: return(0);
646: }
648: /*----------------------------------------------------------------------------------------------*/
651: /*@
652: VecStrideGatherAll - Gathers all the single components from a multi-component vector into
653: separate vectors.
655: Collective on Vec
657: Input Parameter:
658: + v - the vector
659: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
661: Output Parameter:
662: . s - the location where the subvectors are stored
664: Notes:
665: One must call VecSetBlockSize() before this routine to set the stride
666: information, or use a vector created from a multicomponent DA.
668: If x is the array representing the vector x then this gathers
669: the arrays (x[start],x[start+stride],x[start+2*stride], ....)
670: for start=0,1,2,...bs-1
672: The parallel layout of the vector and the subvector must be the same;
673: i.e., nlocal of v = stride*(nlocal of s)
675: Not optimized; could be easily
677: Level: advanced
679: Concepts: gather^into strided vector
681: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
682: VecStrideScatterAll()
683: @*/
684: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGatherAll(Vec v,Vec *s,InsertMode addv)
685: {
687: PetscInt i,n,bs,j,k,*bss,nv,jj,nvc;
688: PetscScalar *x,**y;
694: VecGetLocalSize(v,&n);
695: VecGetArray(v,&x);
696: bs = v->map.bs;
697: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
699: PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
700: nv = 0;
701: nvc = 0;
702: for (i=0; i<bs; i++) {
703: VecGetBlockSize(s[i],&bss[i]);
704: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
705: VecGetArray(s[i],&y[i]);
706: nvc += bss[i];
707: nv++;
708: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
709: if (nvc == bs) break;
710: }
712: n = n/bs;
714: jj = 0;
715: if (addv == INSERT_VALUES) {
716: for (j=0; j<nv; j++) {
717: for (k=0; k<bss[j]; k++) {
718: for (i=0; i<n; i++) {
719: y[j][i*bss[j] + k] = x[bs*i+jj+k];
720: }
721: }
722: jj += bss[j];
723: }
724: } else if (addv == ADD_VALUES) {
725: for (j=0; j<nv; j++) {
726: for (k=0; k<bss[j]; k++) {
727: for (i=0; i<n; i++) {
728: y[j][i*bss[j] + k] += x[bs*i+jj+k];
729: }
730: }
731: jj += bss[j];
732: }
733: #if !defined(PETSC_USE_COMPLEX)
734: } else if (addv == MAX_VALUES) {
735: for (j=0; j<nv; j++) {
736: for (k=0; k<bss[j]; k++) {
737: for (i=0; i<n; i++) {
738: y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
739: }
740: }
741: jj += bss[j];
742: }
743: #endif
744: } else {
745: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
746: }
748: VecRestoreArray(v,&x);
749: for (i=0; i<nv; i++) {
750: VecRestoreArray(s[i],&y[i]);
751: }
752: PetscFree2(y,bss);
753: return(0);
754: }
758: /*@
759: VecStrideScatterAll - Scatters all the single components from separate vectors into
760: a multi-component vector.
762: Collective on Vec
764: Input Parameter:
765: + s - the location where the subvectors are stored
766: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
768: Output Parameter:
769: . v - the multicomponent vector
771: Notes:
772: One must call VecSetBlockSize() before this routine to set the stride
773: information, or use a vector created from a multicomponent DA.
775: The parallel layout of the vector and the subvector must be the same;
776: i.e., nlocal of v = stride*(nlocal of s)
778: Not optimized; could be easily
780: Level: advanced
782: Concepts: scatter^into strided vector
784: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
785: VecStrideScatterAll()
786: @*/
787: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatterAll(Vec *s,Vec v,InsertMode addv)
788: {
790: PetscInt i,n,bs,j,jj,k,*bss,nv,nvc;
791: PetscScalar *x,**y;
797: VecGetLocalSize(v,&n);
798: VecGetArray(v,&x);
799: bs = v->map.bs;
800: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
802: PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
803: nv = 0;
804: nvc = 0;
805: for (i=0; i<bs; i++) {
806: VecGetBlockSize(s[i],&bss[i]);
807: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
808: VecGetArray(s[i],&y[i]);
809: nvc += bss[i];
810: nv++;
811: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
812: if (nvc == bs) break;
813: }
815: n = n/bs;
817: jj = 0;
818: if (addv == INSERT_VALUES) {
819: for (j=0; j<nv; j++) {
820: for (k=0; k<bss[j]; k++) {
821: for (i=0; i<n; i++) {
822: x[bs*i+jj+k] = y[j][i*bss[j] + k];
823: }
824: }
825: jj += bss[j];
826: }
827: } else if (addv == ADD_VALUES) {
828: for (j=0; j<nv; j++) {
829: for (k=0; k<bss[j]; k++) {
830: for (i=0; i<n; i++) {
831: x[bs*i+jj+k] += y[j][i*bss[j] + k];
832: }
833: }
834: jj += bss[j];
835: }
836: #if !defined(PETSC_USE_COMPLEX)
837: } else if (addv == MAX_VALUES) {
838: for (j=0; j<nv; j++) {
839: for (k=0; k<bss[j]; k++) {
840: for (i=0; i<n; i++) {
841: x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
842: }
843: }
844: jj += bss[j];
845: }
846: #endif
847: } else {
848: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
849: }
851: VecRestoreArray(v,&x);
852: for (i=0; i<nv; i++) {
853: VecRestoreArray(s[i],&y[i]);
854: }
855: PetscFree2(y,bss);
856: return(0);
857: }
861: /*@
862: VecStrideGather - Gathers a single component from a multi-component vector into
863: another vector.
865: Collective on Vec
867: Input Parameter:
868: + v - the vector
869: . start - starting point of the subvector (defined by a stride)
870: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
872: Output Parameter:
873: . s - the location where the subvector is stored
875: Notes:
876: One must call VecSetBlockSize() before this routine to set the stride
877: information, or use a vector created from a multicomponent DA.
879: If x is the array representing the vector x then this gathers
880: the array (x[start],x[start+stride],x[start+2*stride], ....)
882: The parallel layout of the vector and the subvector must be the same;
883: i.e., nlocal of v = stride*(nlocal of s)
885: Not optimized; could be easily
887: Level: advanced
889: Concepts: gather^into strided vector
891: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
892: VecStrideScatterAll()
893: @*/
894: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
895: {
897: PetscInt i,n,bs,ns;
898: PetscScalar *x,*y;
903: VecGetLocalSize(v,&n);
904: VecGetLocalSize(s,&ns);
905: VecGetArray(v,&x);
906: VecGetArray(s,&y);
908: bs = v->map.bs;
909: if (start >= bs) {
910: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
911: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
912: }
913: if (n != ns*bs) {
914: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
915: }
916: x += start;
917: n = n/bs;
919: if (addv == INSERT_VALUES) {
920: for (i=0; i<n; i++) {
921: y[i] = x[bs*i];
922: }
923: } else if (addv == ADD_VALUES) {
924: for (i=0; i<n; i++) {
925: y[i] += x[bs*i];
926: }
927: #if !defined(PETSC_USE_COMPLEX)
928: } else if (addv == MAX_VALUES) {
929: for (i=0; i<n; i++) {
930: y[i] = PetscMax(y[i],x[bs*i]);
931: }
932: #endif
933: } else {
934: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
935: }
937: VecRestoreArray(v,&x);
938: VecRestoreArray(s,&y);
939: return(0);
940: }
944: /*@
945: VecStrideScatter - Scatters a single component from a vector into a multi-component vector.
947: Collective on Vec
949: Input Parameter:
950: + s - the single-component vector
951: . start - starting point of the subvector (defined by a stride)
952: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
954: Output Parameter:
955: . v - the location where the subvector is scattered (the multi-component vector)
957: Notes:
958: One must call VecSetBlockSize() on the multi-component vector before this
959: routine to set the stride information, or use a vector created from a multicomponent DA.
961: The parallel layout of the vector and the subvector must be the same;
962: i.e., nlocal of v = stride*(nlocal of s)
964: Not optimized; could be easily
966: Level: advanced
968: Concepts: scatter^into strided vector
970: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
971: VecStrideScatterAll()
972: @*/
973: PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
974: {
976: PetscInt i,n,bs,ns;
977: PetscScalar *x,*y;
982: VecGetLocalSize(v,&n);
983: VecGetLocalSize(s,&ns);
984: VecGetArray(v,&x);
985: VecGetArray(s,&y);
987: bs = v->map.bs;
988: if (start >= bs) {
989: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
990: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
991: }
992: if (n != ns*bs) {
993: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
994: }
995: x += start;
996: n = n/bs;
999: if (addv == INSERT_VALUES) {
1000: for (i=0; i<n; i++) {
1001: x[bs*i] = y[i];
1002: }
1003: } else if (addv == ADD_VALUES) {
1004: for (i=0; i<n; i++) {
1005: x[bs*i] += y[i];
1006: }
1007: #if !defined(PETSC_USE_COMPLEX)
1008: } else if (addv == MAX_VALUES) {
1009: for (i=0; i<n; i++) {
1010: x[bs*i] = PetscMax(y[i],x[bs*i]);
1011: }
1012: #endif
1013: } else {
1014: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1015: }
1018: VecRestoreArray(v,&x);
1019: VecRestoreArray(s,&y);
1020: return(0);
1021: }
1025: PetscErrorCode VecReciprocal_Default(Vec v)
1026: {
1028: PetscInt i,n;
1029: PetscScalar *x;
1032: VecGetLocalSize(v,&n);
1033: VecGetArray(v,&x);
1034: for (i=0; i<n; i++) {
1035: if (x[i] != 0.0) x[i] = 1.0/x[i];
1036: }
1037: VecRestoreArray(v,&x);
1038: return(0);
1039: }
1043: /*@
1044: VecSqrt - Replaces each component of a vector by the square root of its magnitude.
1046: Not collective
1048: Input Parameter:
1049: . v - The vector
1051: Output Parameter:
1052: . v - The vector square root
1054: Level: beginner
1056: Note: The actual function is sqrt(|x_i|)
1058: .keywords: vector, sqrt, square root
1059: @*/
1060: PetscErrorCode PETSCVEC_DLLEXPORT VecSqrt(Vec v)
1061: {
1062: PetscScalar *x;
1063: PetscInt i, n;
1068: VecGetLocalSize(v, &n);
1069: VecGetArray(v, &x);
1070: for(i = 0; i < n; i++) {
1071: x[i] = sqrt(PetscAbsScalar(x[i]));
1072: }
1073: VecRestoreArray(v, &x);
1074: return(0);
1075: }
1079: /*@
1080: VecSum - Computes the sum of all the components of a vector.
1082: Collective on Vec
1084: Input Parameter:
1085: . v - the vector
1087: Output Parameter:
1088: . sum - the result
1090: Level: beginner
1092: Concepts: sum^of vector entries
1094: .seealso: VecNorm()
1095: @*/
1096: PetscErrorCode PETSCVEC_DLLEXPORT VecSum(Vec v,PetscScalar *sum)
1097: {
1099: PetscInt i,n;
1100: PetscScalar *x,lsum = 0.0;
1105: VecGetLocalSize(v,&n);
1106: VecGetArray(v,&x);
1107: for (i=0; i<n; i++) {
1108: lsum += x[i];
1109: }
1110: MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,PetscSum_Op,v->comm);
1111: VecRestoreArray(v,&x);
1112: return(0);
1113: }
1117: /*@
1118: VecShift - Shifts all of the components of a vector by computing
1119: x[i] = x[i] + shift.
1121: Collective on Vec
1123: Input Parameters:
1124: + v - the vector
1125: - shift - the shift
1127: Output Parameter:
1128: . v - the shifted vector
1130: Level: intermediate
1132: Concepts: vector^adding constant
1134: @*/
1135: PetscErrorCode PETSCVEC_DLLEXPORT VecShift(Vec v,PetscScalar shift)
1136: {
1138: PetscInt i,n;
1139: PetscScalar *x;
1143: VecGetLocalSize(v,&n);
1144: VecGetArray(v,&x);
1145: for (i=0; i<n; i++) {
1146: x[i] += shift;
1147: }
1148: VecRestoreArray(v,&x);
1149: return(0);
1150: }
1154: /*@
1155: VecAbs - Replaces every element in a vector with its absolute value.
1157: Collective on Vec
1159: Input Parameters:
1160: . v - the vector
1162: Level: intermediate
1164: Concepts: vector^absolute value
1166: @*/
1167: PetscErrorCode PETSCVEC_DLLEXPORT VecAbs(Vec v)
1168: {
1170: PetscInt i,n;
1171: PetscScalar *x;
1175: VecGetLocalSize(v,&n);
1176: VecGetArray(v,&x);
1177: for (i=0; i<n; i++) {
1178: x[i] = PetscAbsScalar(x[i]);
1179: }
1180: VecRestoreArray(v,&x);
1181: return(0);
1182: }
1186: /*@
1187: VecPermute - Permutes a vector in place using the given ordering.
1189: Input Parameters:
1190: + vec - The vector
1191: . order - The ordering
1192: - inv - The flag for inverting the permutation
1194: Level: beginner
1196: Note: This function does not yet support parallel Index Sets
1198: .seealso: MatPermute()
1199: .keywords: vec, permute
1200: @*/
1201: PetscErrorCode PETSCVEC_DLLEXPORT VecPermute(Vec x, IS row, PetscTruth inv)
1202: {
1203: PetscScalar *array, *newArray;
1204: PetscInt *idx;
1205: PetscInt i;
1209: ISGetIndices(row, &idx);
1210: VecGetArray(x, &array);
1211: PetscMalloc(x->map.n*sizeof(PetscScalar), &newArray);
1212: #ifdef PETSC_USE_DEBUG
1213: for(i = 0; i < x->map.n; i++) {
1214: if ((idx[i] < 0) || (idx[i] >= x->map.n)) {
1215: SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1216: }
1217: }
1218: #endif
1219: if (!inv) {
1220: for(i = 0; i < x->map.n; i++) newArray[i] = array[idx[i]];
1221: } else {
1222: for(i = 0; i < x->map.n; i++) newArray[idx[i]] = array[i];
1223: }
1224: VecRestoreArray(x, &array);
1225: ISRestoreIndices(row, &idx);
1226: VecReplaceArray(x, newArray);
1227: return(0);
1228: }
1232: /*@
1233: VecEqual - Compares two vectors.
1235: Collective on Vec
1237: Input Parameters:
1238: + vec1 - the first matrix
1239: - vec2 - the second matrix
1241: Output Parameter:
1242: . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.
1244: Level: intermediate
1246: Concepts: equal^two vectors
1247: Concepts: vector^equality
1249: @*/
1250: PetscErrorCode PETSCVEC_DLLEXPORT VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1251: {
1252: PetscScalar *v1,*v2;
1254: PetscInt n1,n2,N1,N2;
1255: PetscInt state1,state2;
1256: PetscTruth flg1;
1257:
1262: if (vec1 == vec2) {
1263: *flg = PETSC_TRUE;
1264: } else {
1265: VecGetSize(vec1,&N1);
1266: VecGetSize(vec2,&N2);
1267: if (N1 != N2) {
1268: flg1 = PETSC_FALSE;
1269: } else {
1270: VecGetLocalSize(vec1,&n1);
1271: VecGetLocalSize(vec2,&n2);
1272: if (n1 != n2) {
1273: flg1 = PETSC_FALSE;
1274: } else {
1275: PetscObjectStateQuery((PetscObject) vec1,&state1);
1276: PetscObjectStateQuery((PetscObject) vec2,&state2);
1277: VecGetArray(vec1,&v1);
1278: VecGetArray(vec2,&v2);
1279: PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1280: VecRestoreArray(vec1,&v1);
1281: VecRestoreArray(vec2,&v2);
1282: PetscObjectSetState((PetscObject) vec1,state1);
1283: PetscObjectSetState((PetscObject) vec2,state2);
1284: }
1285: }
1286: /* combine results from all processors */
1287: MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,vec1->comm);
1288: }
1289: return(0);
1290: }