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 VecStrideScale(Vec v,PetscInt start,PetscScalar scale)
38: {
40: PetscInt i,n,bs;
41: PetscScalar *x;
45: VecGetLocalSize(v,&n);
46: VecGetArray(v,&x);
48: bs = v->map->bs;
49: if (start < 0) {
50: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
51: } else if (start >= bs) {
52: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
53: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
54: }
55: x += start;
57: for (i=0; i<n; i+=bs) {
58: x[i] *= scale;
59: }
60: x -= start;
62: VecRestoreArray(v,&x);
63: return(0);
64: }
68: /*@
69: VecStrideNorm - Computes the norm of subvector of a vector defined
70: by a starting point and a stride.
72: Collective on Vec
74: Input Parameter:
75: + v - the vector
76: . start - starting point of the subvector (defined by a stride)
77: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
79: Output Parameter:
80: . norm - the norm
82: Notes:
83: One must call VecSetBlockSize() before this routine to set the stride
84: information, or use a vector created from a multicomponent DA.
86: If x is the array representing the vector x then this computes the norm
87: of the array (x[start],x[start+stride],x[start+2*stride], ....)
89: This is useful for computing, say the norm of the pressure variable when
90: the pressure is stored (interlaced) with other variables, say density etc.
92: This will only work if the desire subvector is a stride subvector
94: Level: advanced
96: Concepts: norm^on stride of vector
97: Concepts: stride^norm
99: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
100: @*/
101: PetscErrorCode VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
102: {
104: PetscInt i,n,bs;
105: PetscScalar *x;
106: PetscReal tnorm;
107: MPI_Comm comm;
112: VecGetLocalSize(v,&n);
113: VecGetArray(v,&x);
114: PetscObjectGetComm((PetscObject)v,&comm);
116: bs = v->map->bs;
117: if (start < 0) {
118: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
119: } else if (start >= bs) {
120: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
121: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
122: }
123: x += start;
125: if (ntype == NORM_2) {
126: PetscScalar sum = 0.0;
127: for (i=0; i<n; i+=bs) {
128: sum += x[i]*(PetscConj(x[i]));
129: }
130: tnorm = PetscRealPart(sum);
131: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
132: *nrm = sqrt(*nrm);
133: } else if (ntype == NORM_1) {
134: tnorm = 0.0;
135: for (i=0; i<n; i+=bs) {
136: tnorm += PetscAbsScalar(x[i]);
137: }
138: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);
139: } else if (ntype == NORM_INFINITY) {
140: PetscReal tmp;
141: tnorm = 0.0;
143: for (i=0; i<n; i+=bs) {
144: if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
145: /* check special case of tmp == NaN */
146: if (tmp != tmp) {tnorm = tmp; break;}
147: }
148: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);
149: } else {
150: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
151: }
153: VecRestoreArray(v,&x);
154: return(0);
155: }
159: /*@
160: VecStrideMax - Computes the maximum of subvector of a vector defined
161: by a starting point and a stride and optionally its location.
163: Collective on Vec
165: Input Parameter:
166: + v - the vector
167: - start - starting point of the subvector (defined by a stride)
169: Output Parameter:
170: + index - the location where the maximum occurred (pass PETSC_NULL if not required)
171: - nrm - the max
173: Notes:
174: One must call VecSetBlockSize() before this routine to set the stride
175: information, or use a vector created from a multicomponent DA.
177: If xa is the array representing the vector x, then this computes the max
178: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
180: This is useful for computing, say the maximum of the pressure variable when
181: the pressure is stored (interlaced) with other variables, e.g., density, etc.
182: This will only work if the desire subvector is a stride subvector.
184: Level: advanced
186: Concepts: maximum^on stride of vector
187: Concepts: stride^maximum
189: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
190: @*/
191: PetscErrorCode VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
192: {
194: PetscInt i,n,bs,id;
195: PetscScalar *x;
196: PetscReal max,tmp;
197: MPI_Comm comm;
203: VecGetLocalSize(v,&n);
204: VecGetArray(v,&x);
205: PetscObjectGetComm((PetscObject)v,&comm);
207: bs = v->map->bs;
208: if (start < 0) {
209: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
210: } else if (start >= bs) {
211: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
212: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
213: }
214: x += start;
216: id = -1;
217: if (!n) {
218: max = PETSC_MIN;
219: } else {
220: id = 0;
221: #if defined(PETSC_USE_COMPLEX)
222: max = PetscRealPart(x[0]);
223: #else
224: max = x[0];
225: #endif
226: for (i=bs; i<n; i+=bs) {
227: #if defined(PETSC_USE_COMPLEX)
228: if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
229: #else
230: if ((tmp = x[i]) > max) { max = tmp; id = i;}
231: #endif
232: }
233: }
234: VecRestoreArray(v,&x);
236: if (!idex) {
237: MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);
238: } else {
239: PetscReal in[2],out[2];
240: PetscInt rstart;
242: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
243: in[0] = max;
244: in[1] = rstart+id+start;
245: MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,((PetscObject)v)->comm);
246: *nrm = out[0];
247: *idex = (PetscInt)out[1];
248: }
250: return(0);
251: }
255: /*@
256: VecStrideMin - Computes the minimum of subvector of a vector defined
257: by a starting point and a stride and optionally its location.
259: Collective on Vec
261: Input Parameter:
262: + v - the vector
263: - start - starting point of the subvector (defined by a stride)
265: Output Parameter:
266: + idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
267: - nrm - the min
269: Level: advanced
271: Notes:
272: One must call VecSetBlockSize() before this routine to set the stride
273: information, or use a vector created from a multicomponent DA.
275: If xa is the array representing the vector x, then this computes the min
276: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
278: This is useful for computing, say the minimum of the pressure variable when
279: the pressure is stored (interlaced) with other variables, e.g., density, etc.
280: This will only work if the desire subvector is a stride subvector.
282: Concepts: minimum^on stride of vector
283: Concepts: stride^minimum
285: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
286: @*/
287: PetscErrorCode VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
288: {
290: PetscInt i,n,bs,id;
291: PetscScalar *x;
292: PetscReal min,tmp;
293: MPI_Comm comm;
299: VecGetLocalSize(v,&n);
300: VecGetArray(v,&x);
301: PetscObjectGetComm((PetscObject)v,&comm);
303: bs = v->map->bs;
304: if (start < 0) {
305: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
306: } else if (start >= bs) {
307: SETERRQ2(PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
308: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
309: }
310: x += start;
312: id = -1;
313: if (!n) {
314: min = PETSC_MAX;
315: } else {
316: id = 0;
317: #if defined(PETSC_USE_COMPLEX)
318: min = PetscRealPart(x[0]);
319: #else
320: min = x[0];
321: #endif
322: for (i=bs; i<n; i+=bs) {
323: #if defined(PETSC_USE_COMPLEX)
324: if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
325: #else
326: if ((tmp = x[i]) < min) { min = tmp; id = i;}
327: #endif
328: }
329: }
330: VecRestoreArray(v,&x);
332: if (!idex) {
333: MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);
334: } else {
335: PetscReal in[2],out[2];
336: PetscInt rstart;
338: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
339: in[0] = min;
340: in[1] = rstart+id;
341: MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,((PetscObject)v)->comm);
342: *nrm = out[0];
343: *idex = (PetscInt)out[1];
344: }
346: return(0);
347: }
351: /*@
352: VecStrideScaleAll - Scales the subvectors of a vector defined
353: by a starting point and a stride.
355: Collective on Vec
357: Input Parameter:
358: + v - the vector
359: - scales - values to multiply each subvector entry by
361: Notes:
362: One must call VecSetBlockSize() before this routine to set the stride
363: information, or use a vector created from a multicomponent DA.
366: Level: advanced
368: Concepts: scale^on stride of vector
369: Concepts: stride^scale
371: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
372: @*/
373: PetscErrorCode VecStrideScaleAll(Vec v,PetscScalar *scales)
374: {
376: PetscInt i,j,n,bs;
377: PetscScalar *x;
382: VecGetLocalSize(v,&n);
383: VecGetArray(v,&x);
385: bs = v->map->bs;
387: /* need to provide optimized code for each bs */
388: for (i=0; i<n; i+=bs) {
389: for (j=0; j<bs; j++) {
390: x[i+j] *= scales[j];
391: }
392: }
393: VecRestoreArray(v,&x);
394: return(0);
395: }
399: /*@
400: VecStrideNormAll - Computes the norms subvectors of a vector defined
401: by a starting point and a stride.
403: Collective on Vec
405: Input Parameter:
406: + v - the vector
407: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
409: Output Parameter:
410: . nrm - the norms
412: Notes:
413: One must call VecSetBlockSize() before this routine to set the stride
414: information, or use a vector created from a multicomponent DA.
416: If x is the array representing the vector x then this computes the norm
417: of the array (x[start],x[start+stride],x[start+2*stride], ....)
419: This is useful for computing, say the norm of the pressure variable when
420: the pressure is stored (interlaced) with other variables, say density etc.
422: This will only work if the desire subvector is a stride subvector
424: Level: advanced
426: Concepts: norm^on stride of vector
427: Concepts: stride^norm
429: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
430: @*/
431: PetscErrorCode VecStrideNormAll(Vec v,NormType ntype,PetscReal nrm[])
432: {
434: PetscInt i,j,n,bs;
435: PetscScalar *x;
436: PetscReal tnorm[128];
437: MPI_Comm comm;
442: VecGetLocalSize(v,&n);
443: VecGetArray(v,&x);
444: PetscObjectGetComm((PetscObject)v,&comm);
446: bs = v->map->bs;
447: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
449: if (ntype == NORM_2) {
450: PetscScalar sum[128];
451: for (j=0; j<bs; j++) sum[j] = 0.0;
452: for (i=0; i<n; i+=bs) {
453: for (j=0; j<bs; j++) {
454: sum[j] += x[i+j]*(PetscConj(x[i+j]));
455: }
456: }
457: for (j=0; j<bs; j++) {
458: tnorm[j] = PetscRealPart(sum[j]);
459: }
460: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
461: for (j=0; j<bs; j++) {
462: nrm[j] = sqrt(nrm[j]);
463: }
464: } else if (ntype == NORM_1) {
465: for (j=0; j<bs; j++) {
466: tnorm[j] = 0.0;
467: }
468: for (i=0; i<n; i+=bs) {
469: for (j=0; j<bs; j++) {
470: tnorm[j] += PetscAbsScalar(x[i+j]);
471: }
472: }
473: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);
474: } else if (ntype == NORM_INFINITY) {
475: PetscReal tmp;
476: for (j=0; j<bs; j++) {
477: tnorm[j] = 0.0;
478: }
480: for (i=0; i<n; i+=bs) {
481: for (j=0; j<bs; j++) {
482: if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
483: /* check special case of tmp == NaN */
484: if (tmp != tmp) {tnorm[j] = tmp; break;}
485: }
486: }
487: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);
488: } else {
489: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
490: }
492: VecRestoreArray(v,&x);
493: return(0);
494: }
498: /*@
499: VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
500: by a starting point and a stride and optionally its location.
502: Collective on Vec
504: Input Parameter:
505: . v - the vector
507: Output Parameter:
508: + index - the location where the maximum occurred (not supported, pass PETSC_NULL,
509: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
510: - nrm - the maximums
512: Notes:
513: One must call VecSetBlockSize() before this routine to set the stride
514: information, or use a vector created from a multicomponent DA.
516: This is useful for computing, say the maximum of the pressure variable when
517: the pressure is stored (interlaced) with other variables, e.g., density, etc.
518: This will only work if the desire subvector is a stride subvector.
520: Level: advanced
522: Concepts: maximum^on stride of vector
523: Concepts: stride^maximum
525: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
526: @*/
527: PetscErrorCode VecStrideMaxAll(Vec v,PetscInt idex[],PetscReal nrm[])
528: {
530: PetscInt i,j,n,bs;
531: PetscScalar *x;
532: PetscReal max[128],tmp;
533: MPI_Comm comm;
538: if (idex) {
539: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
540: }
541: VecGetLocalSize(v,&n);
542: VecGetArray(v,&x);
543: PetscObjectGetComm((PetscObject)v,&comm);
545: bs = v->map->bs;
546: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
548: if (!n) {
549: for (j=0; j<bs; j++) {
550: max[j] = PETSC_MIN;
551: }
552: } else {
553: for (j=0; j<bs; j++) {
554: #if defined(PETSC_USE_COMPLEX)
555: max[j] = PetscRealPart(x[j]);
556: #else
557: max[j] = x[j];
558: #endif
559: }
560: for (i=bs; i<n; i+=bs) {
561: for (j=0; j<bs; j++) {
562: #if defined(PETSC_USE_COMPLEX)
563: if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
564: #else
565: if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
566: #endif
567: }
568: }
569: }
570: MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);
572: VecRestoreArray(v,&x);
573: return(0);
574: }
578: /*@
579: VecStrideMinAll - Computes the minimum of subvector of a vector defined
580: by a starting point and a stride and optionally its location.
582: Collective on Vec
584: Input Parameter:
585: . v - the vector
587: Output Parameter:
588: + idex - the location where the minimum occurred (not supported, pass PETSC_NULL,
589: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
590: - nrm - the minimums
592: Level: advanced
594: Notes:
595: One must call VecSetBlockSize() before this routine to set the stride
596: information, or use a vector created from a multicomponent DA.
598: This is useful for computing, say the minimum of the pressure variable when
599: the pressure is stored (interlaced) with other variables, e.g., density, etc.
600: This will only work if the desire subvector is a stride subvector.
602: Concepts: minimum^on stride of vector
603: Concepts: stride^minimum
605: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
606: @*/
607: PetscErrorCode VecStrideMinAll(Vec v,PetscInt idex[],PetscReal nrm[])
608: {
610: PetscInt i,n,bs,j;
611: PetscScalar *x;
612: PetscReal min[128],tmp;
613: MPI_Comm comm;
618: if (idex) {
619: SETERRQ(PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
620: }
621: VecGetLocalSize(v,&n);
622: VecGetArray(v,&x);
623: PetscObjectGetComm((PetscObject)v,&comm);
625: bs = v->map->bs;
626: if (bs > 128) SETERRQ(PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
628: if (!n) {
629: for (j=0; j<bs; j++) {
630: min[j] = PETSC_MAX;
631: }
632: } else {
633: for (j=0; j<bs; j++) {
634: #if defined(PETSC_USE_COMPLEX)
635: min[j] = PetscRealPart(x[j]);
636: #else
637: min[j] = x[j];
638: #endif
639: }
640: for (i=bs; i<n; i+=bs) {
641: for (j=0; j<bs; j++) {
642: #if defined(PETSC_USE_COMPLEX)
643: if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
644: #else
645: if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
646: #endif
647: }
648: }
649: }
650: MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);
652: VecRestoreArray(v,&x);
653: return(0);
654: }
656: /*----------------------------------------------------------------------------------------------*/
659: /*@
660: VecStrideGatherAll - Gathers all the single components from a multi-component vector into
661: separate vectors.
663: Collective on Vec
665: Input Parameter:
666: + v - the vector
667: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
669: Output Parameter:
670: . s - the location where the subvectors are stored
672: Notes:
673: One must call VecSetBlockSize() before this routine to set the stride
674: information, or use a vector created from a multicomponent DA.
676: If x is the array representing the vector x then this gathers
677: the arrays (x[start],x[start+stride],x[start+2*stride], ....)
678: for start=0,1,2,...bs-1
680: The parallel layout of the vector and the subvector must be the same;
681: i.e., nlocal of v = stride*(nlocal of s)
683: Not optimized; could be easily
685: Level: advanced
687: Concepts: gather^into strided vector
689: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
690: VecStrideScatterAll()
691: @*/
692: PetscErrorCode VecStrideGatherAll(Vec v,Vec s[],InsertMode addv)
693: {
695: PetscInt i,n,n2,bs,j,k,*bss = PETSC_NULL,nv,jj,nvc;
696: PetscScalar *x,**y;
702: VecGetLocalSize(v,&n);
703: VecGetLocalSize(s[0],&n2);
704: VecGetArray(v,&x);
705: bs = v->map->bs;
706: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
708: PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
709: nv = 0;
710: nvc = 0;
711: for (i=0; i<bs; i++) {
712: VecGetBlockSize(s[i],&bss[i]);
713: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
714: VecGetArray(s[i],&y[i]);
715: nvc += bss[i];
716: nv++;
717: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
718: if (nvc == bs) break;
719: }
721: n = n/bs;
723: jj = 0;
724: if (addv == INSERT_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: } else if (addv == ADD_VALUES) {
734: for (j=0; j<nv; j++) {
735: for (k=0; k<bss[j]; k++) {
736: for (i=0; i<n; i++) {
737: y[j][i*bss[j] + k] += x[bs*i+jj+k];
738: }
739: }
740: jj += bss[j];
741: }
742: #if !defined(PETSC_USE_COMPLEX)
743: } else if (addv == MAX_VALUES) {
744: for (j=0; j<nv; j++) {
745: for (k=0; k<bss[j]; k++) {
746: for (i=0; i<n; i++) {
747: y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
748: }
749: }
750: jj += bss[j];
751: }
752: #endif
753: } else {
754: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
755: }
757: VecRestoreArray(v,&x);
758: for (i=0; i<nv; i++) {
759: VecRestoreArray(s[i],&y[i]);
760: }
762: PetscFree2(y,bss);
763: return(0);
764: }
768: /*@
769: VecStrideScatterAll - Scatters all the single components from separate vectors into
770: a multi-component vector.
772: Collective on Vec
774: Input Parameter:
775: + s - the location where the subvectors are stored
776: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
778: Output Parameter:
779: . v - the multicomponent vector
781: Notes:
782: One must call VecSetBlockSize() before this routine to set the stride
783: information, or use a vector created from a multicomponent DA.
785: The parallel layout of the vector and the subvector must be the same;
786: i.e., nlocal of v = stride*(nlocal of s)
788: Not optimized; could be easily
790: Level: advanced
792: Concepts: scatter^into strided vector
794: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
795: VecStrideScatterAll()
796: @*/
797: PetscErrorCode VecStrideScatterAll(Vec s[],Vec v,InsertMode addv)
798: {
800: PetscInt i,n,n2,bs,j,jj,k,*bss = PETSC_NULL,nv,nvc;
801: PetscScalar *x,**y;
807: VecGetLocalSize(v,&n);
808: VecGetLocalSize(s[0],&n2);
809: VecGetArray(v,&x);
810: bs = v->map->bs;
811: if (bs < 0) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
813: PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
814: nv = 0;
815: nvc = 0;
816: for (i=0; i<bs; i++) {
817: VecGetBlockSize(s[i],&bss[i]);
818: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
819: VecGetArray(s[i],&y[i]);
820: nvc += bss[i];
821: nv++;
822: if (nvc > bs) SETERRQ(PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
823: if (nvc == bs) break;
824: }
826: n = n/bs;
828: jj = 0;
829: if (addv == INSERT_VALUES) {
830: for (j=0; j<nv; j++) {
831: for (k=0; k<bss[j]; k++) {
832: for (i=0; i<n; i++) {
833: x[bs*i+jj+k] = y[j][i*bss[j] + k];
834: }
835: }
836: jj += bss[j];
837: }
838: } else if (addv == ADD_VALUES) {
839: for (j=0; j<nv; j++) {
840: for (k=0; k<bss[j]; k++) {
841: for (i=0; i<n; i++) {
842: x[bs*i+jj+k] += y[j][i*bss[j] + k];
843: }
844: }
845: jj += bss[j];
846: }
847: #if !defined(PETSC_USE_COMPLEX)
848: } else if (addv == MAX_VALUES) {
849: for (j=0; j<nv; j++) {
850: for (k=0; k<bss[j]; k++) {
851: for (i=0; i<n; i++) {
852: x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
853: }
854: }
855: jj += bss[j];
856: }
857: #endif
858: } else {
859: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
860: }
862: VecRestoreArray(v,&x);
863: for (i=0; i<nv; i++) {
864: VecRestoreArray(s[i],&y[i]);
865: }
866: PetscFree2(y,bss);
867: return(0);
868: }
872: /*@
873: VecStrideGather - Gathers a single component from a multi-component vector into
874: another vector.
876: Collective on Vec
878: Input Parameter:
879: + v - the vector
880: . start - starting point of the subvector (defined by a stride)
881: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
883: Output Parameter:
884: . s - the location where the subvector is stored
886: Notes:
887: One must call VecSetBlockSize() before this routine to set the stride
888: information, or use a vector created from a multicomponent DA.
890: If x is the array representing the vector x then this gathers
891: the array (x[start],x[start+stride],x[start+2*stride], ....)
893: The parallel layout of the vector and the subvector must be the same;
894: i.e., nlocal of v = stride*(nlocal of s)
896: Not optimized; could be easily
898: Level: advanced
900: Concepts: gather^into strided vector
902: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
903: VecStrideScatterAll()
904: @*/
905: PetscErrorCode VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
906: {
908: PetscInt i,n,bs,ns;
909: PetscScalar *x,*y;
914: VecGetLocalSize(v,&n);
915: VecGetLocalSize(s,&ns);
916: VecGetArray(v,&x);
917: VecGetArray(s,&y);
919: bs = v->map->bs;
920: if (start < 0) {
921: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
922: } else if (start >= bs) {
923: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
924: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
925: }
926: if (n != ns*bs) {
927: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
928: }
929: x += start;
930: n = n/bs;
932: if (addv == INSERT_VALUES) {
933: for (i=0; i<n; i++) {
934: y[i] = x[bs*i];
935: }
936: } else if (addv == ADD_VALUES) {
937: for (i=0; i<n; i++) {
938: y[i] += x[bs*i];
939: }
940: #if !defined(PETSC_USE_COMPLEX)
941: } else if (addv == MAX_VALUES) {
942: for (i=0; i<n; i++) {
943: y[i] = PetscMax(y[i],x[bs*i]);
944: }
945: #endif
946: } else {
947: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
948: }
950: VecRestoreArray(v,&x);
951: VecRestoreArray(s,&y);
952: return(0);
953: }
957: /*@
958: VecStrideScatter - Scatters a single component from a vector into a multi-component vector.
960: Collective on Vec
962: Input Parameter:
963: + s - the single-component vector
964: . start - starting point of the subvector (defined by a stride)
965: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
967: Output Parameter:
968: . v - the location where the subvector is scattered (the multi-component vector)
970: Notes:
971: One must call VecSetBlockSize() on the multi-component vector before this
972: routine to set the stride information, or use a vector created from a multicomponent DA.
974: The parallel layout of the vector and the subvector must be the same;
975: i.e., nlocal of v = stride*(nlocal of s)
977: Not optimized; could be easily
979: Level: advanced
981: Concepts: scatter^into strided vector
983: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
984: VecStrideScatterAll()
985: @*/
986: PetscErrorCode VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
987: {
989: PetscInt i,n,bs,ns;
990: PetscScalar *x,*y;
995: VecGetLocalSize(v,&n);
996: VecGetLocalSize(s,&ns);
997: VecGetArray(v,&x);
998: VecGetArray(s,&y);
1000: bs = v->map->bs;
1001: if (start < 0) {
1002: SETERRQ1(PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
1003: } else if (start >= bs) {
1004: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
1005: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
1006: }
1007: if (n != ns*bs) {
1008: SETERRQ2(PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
1009: }
1010: x += start;
1011: n = n/bs;
1014: if (addv == INSERT_VALUES) {
1015: for (i=0; i<n; i++) {
1016: x[bs*i] = y[i];
1017: }
1018: } else if (addv == ADD_VALUES) {
1019: for (i=0; i<n; i++) {
1020: x[bs*i] += y[i];
1021: }
1022: #if !defined(PETSC_USE_COMPLEX)
1023: } else if (addv == MAX_VALUES) {
1024: for (i=0; i<n; i++) {
1025: x[bs*i] = PetscMax(y[i],x[bs*i]);
1026: }
1027: #endif
1028: } else {
1029: SETERRQ(PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1030: }
1033: VecRestoreArray(v,&x);
1034: VecRestoreArray(s,&y);
1035: return(0);
1036: }
1040: PetscErrorCode VecReciprocal_Default(Vec v)
1041: {
1043: PetscInt i,n;
1044: PetscScalar *x;
1047: VecGetLocalSize(v,&n);
1048: VecGetArray(v,&x);
1049: for (i=0; i<n; i++) {
1050: if (x[i] != 0.0) x[i] = 1.0/x[i];
1051: }
1052: VecRestoreArray(v,&x);
1053: return(0);
1054: }
1058: /*@
1059: VecExp - Replaces each component of a vector by e^x_i
1061: Not collective
1063: Input Parameter:
1064: . v - The vector
1066: Output Parameter:
1067: . v - The vector of exponents
1069: Level: beginner
1071: .seealso: VecLog(), VecAbs(), VecSqrt()
1073: .keywords: vector, sqrt, square root
1074: @*/
1075: PetscErrorCode VecExp(Vec v)
1076: {
1077: PetscScalar *x;
1078: PetscInt i, n;
1083: if (v->ops->exp) {
1084: (*v->ops->exp)(v);
1085: } else {
1086: VecGetLocalSize(v, &n);
1087: VecGetArray(v, &x);
1088: for(i = 0; i < n; i++) {
1089: x[i] = PetscExpScalar(x[i]);
1090: }
1091: VecRestoreArray(v, &x);
1092: }
1093: return(0);
1094: }
1098: /*@
1099: VecLog - Replaces each component of a vector by log(x_i)
1101: Not collective
1103: Input Parameter:
1104: . v - The vector
1106: Output Parameter:
1107: . v - The vector of logs
1109: Level: beginner
1111: .seealso: VecExp(), VecAbs(), VecSqrt()
1113: .keywords: vector, sqrt, square root
1114: @*/
1115: PetscErrorCode VecLog(Vec v)
1116: {
1117: PetscScalar *x;
1118: PetscInt i, n;
1123: if (v->ops->log) {
1124: (*v->ops->log)(v);
1125: } else {
1126: VecGetLocalSize(v, &n);
1127: VecGetArray(v, &x);
1128: for(i = 0; i < n; i++) {
1129: x[i] = PetscLogScalar(x[i]);
1130: }
1131: VecRestoreArray(v, &x);
1132: }
1133: return(0);
1134: }
1138: /*@
1139: VecSqrt - Replaces each component of a vector by the square root of its magnitude.
1141: Not collective
1143: Input Parameter:
1144: . v - The vector
1146: Output Parameter:
1147: . v - The vector square root
1149: Level: beginner
1151: Note: The actual function is sqrt(|x_i|)
1153: .keywords: vector, sqrt, square root
1154: @*/
1155: PetscErrorCode VecSqrt(Vec v)
1156: {
1157: PetscScalar *x;
1158: PetscInt i, n;
1163: if (v->ops->sqrt) {
1164: (*v->ops->sqrt)(v);
1165: } else {
1166: VecGetLocalSize(v, &n);
1167: VecGetArray(v, &x);
1168: for(i = 0; i < n; i++) {
1169: x[i] = sqrt(PetscAbsScalar(x[i]));
1170: }
1171: VecRestoreArray(v, &x);
1172: }
1173: return(0);
1174: }
1178: /*@
1179: VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector
1181: Collective on Vec
1183: Input Parameter:
1184: + s - first vector
1185: - t - second vector
1187: Output Parameter:
1188: + dp - s't
1189: - nm - t't
1191: Level: advanced
1193: .seealso: VecDot(), VecNorm(), VecDotBegin(), VecNormBegin(), VecDotEnd(), VecNormEnd()
1195: .keywords: vector, sqrt, square root
1196: @*/
1197: PetscErrorCode VecDotNorm2(Vec s,Vec t,PetscScalar *dp, PetscScalar *nm)
1198: {
1199: PetscScalar *sx, *tx, dpx = 0.0, nmx = 0.0,work[2],sum[2];
1200: PetscInt i, n;
1207: PetscLogEventBarrierBegin(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1208: VecGetLocalSize(s, &n);
1209: VecGetArray(s, &sx);
1210: VecGetArray(t, &tx);
1212: for (i = 0; i<n; i++) {
1213: dpx += sx[i]*PetscConj(tx[i]);
1214: nmx += tx[i]*PetscConj(tx[i]);
1215: }
1216: work[0] = dpx;
1217: work[1] = nmx;
1218: MPI_Allreduce(&work,&sum,2,MPIU_SCALAR,MPIU_SUM,((PetscObject)s)->comm);
1219: *dp = sum[0];
1220: *nm = sum[1];
1221:
1222: VecRestoreArray(t, &tx);
1223: VecRestoreArray(s, &sx);
1224: PetscLogFlops(4.0*n);
1225: PetscLogEventBarrierEnd(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1226: return(0);
1227: }
1231: /*@
1232: VecSum - Computes the sum of all the components of a vector.
1234: Collective on Vec
1236: Input Parameter:
1237: . v - the vector
1239: Output Parameter:
1240: . sum - the result
1242: Level: beginner
1244: Concepts: sum^of vector entries
1246: .seealso: VecNorm()
1247: @*/
1248: PetscErrorCode VecSum(Vec v,PetscScalar *sum)
1249: {
1251: PetscInt i,n;
1252: PetscScalar *x,lsum = 0.0;
1257: VecGetLocalSize(v,&n);
1258: VecGetArray(v,&x);
1259: for (i=0; i<n; i++) {
1260: lsum += x[i];
1261: }
1262: MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,MPIU_SUM,((PetscObject)v)->comm);
1263: VecRestoreArray(v,&x);
1264: return(0);
1265: }
1269: /*@
1270: VecShift - Shifts all of the components of a vector by computing
1271: x[i] = x[i] + shift.
1273: Collective on Vec
1275: Input Parameters:
1276: + v - the vector
1277: - shift - the shift
1279: Output Parameter:
1280: . v - the shifted vector
1282: Level: intermediate
1284: Concepts: vector^adding constant
1286: @*/
1287: PetscErrorCode VecShift(Vec v,PetscScalar shift)
1288: {
1290: PetscInt i,n;
1291: PetscScalar *x;
1295: if (v->ops->shift) {
1296: (*v->ops->shift)(v);
1297: } else {
1298: VecGetLocalSize(v,&n);
1299: VecGetArray(v,&x);
1300: for (i=0; i<n; i++) {
1301: x[i] += shift;
1302: }
1303: VecRestoreArray(v,&x);
1304: }
1305: return(0);
1306: }
1310: /*@
1311: VecAbs - Replaces every element in a vector with its absolute value.
1313: Collective on Vec
1315: Input Parameters:
1316: . v - the vector
1318: Level: intermediate
1320: Concepts: vector^absolute value
1322: @*/
1323: PetscErrorCode VecAbs(Vec v)
1324: {
1326: PetscInt i,n;
1327: PetscScalar *x;
1331: if (v->ops->abs) {
1332: (*v->ops->abs)(v);
1333: } else {
1334: VecGetLocalSize(v,&n);
1335: VecGetArray(v,&x);
1336: for (i=0; i<n; i++) {
1337: x[i] = PetscAbsScalar(x[i]);
1338: }
1339: VecRestoreArray(v,&x);
1340: }
1341: return(0);
1342: }
1346: /*@
1347: VecPermute - Permutes a vector in place using the given ordering.
1349: Input Parameters:
1350: + vec - The vector
1351: . order - The ordering
1352: - inv - The flag for inverting the permutation
1354: Level: beginner
1356: Note: This function does not yet support parallel Index Sets
1358: .seealso: MatPermute()
1359: .keywords: vec, permute
1360: @*/
1361: PetscErrorCode VecPermute(Vec x, IS row, PetscTruth inv)
1362: {
1363: PetscScalar *array, *newArray;
1364: const PetscInt *idx;
1365: PetscInt i;
1369: ISGetIndices(row, &idx);
1370: VecGetArray(x, &array);
1371: PetscMalloc(x->map->n*sizeof(PetscScalar), &newArray);
1372: #ifdef PETSC_USE_DEBUG
1373: for(i = 0; i < x->map->n; i++) {
1374: if ((idx[i] < 0) || (idx[i] >= x->map->n)) {
1375: SETERRQ2(PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1376: }
1377: }
1378: #endif
1379: if (!inv) {
1380: for(i = 0; i < x->map->n; i++) newArray[i] = array[idx[i]];
1381: } else {
1382: for(i = 0; i < x->map->n; i++) newArray[idx[i]] = array[i];
1383: }
1384: VecRestoreArray(x, &array);
1385: ISRestoreIndices(row, &idx);
1386: VecReplaceArray(x, newArray);
1387: return(0);
1388: }
1392: /*@
1393: VecEqual - Compares two vectors.
1395: Collective on Vec
1397: Input Parameters:
1398: + vec1 - the first vector
1399: - vec2 - the second vector
1401: Output Parameter:
1402: . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.
1404: Level: intermediate
1406: Concepts: equal^two vectors
1407: Concepts: vector^equality
1409: @*/
1410: PetscErrorCode VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1411: {
1412: PetscScalar *v1,*v2;
1414: PetscInt n1,n2,N1,N2;
1415: PetscInt state1,state2;
1416: PetscTruth flg1;
1417:
1422: if (vec1 == vec2) {
1423: *flg = PETSC_TRUE;
1424: } else {
1425: VecGetSize(vec1,&N1);
1426: VecGetSize(vec2,&N2);
1427: if (N1 != N2) {
1428: flg1 = PETSC_FALSE;
1429: } else {
1430: VecGetLocalSize(vec1,&n1);
1431: VecGetLocalSize(vec2,&n2);
1432: if (n1 != n2) {
1433: flg1 = PETSC_FALSE;
1434: } else {
1435: PetscObjectStateQuery((PetscObject) vec1,&state1);
1436: PetscObjectStateQuery((PetscObject) vec2,&state2);
1437: VecGetArray(vec1,&v1);
1438: VecGetArray(vec2,&v2);
1439: #if defined(PETSC_USE_COMPLEX)
1440: PetscInt k;
1441: for (k=0; k<n1; k++){
1442: if (PetscRealPart(v1[k]) != PetscRealPart(v2[k]) || PetscImaginaryPart(v1[k]) != PetscImaginaryPart(v2[k])){
1443: flg1 = PETSC_FALSE;
1444: break;
1445: }
1446: }
1447: #else
1448: PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1449: #endif
1450: VecRestoreArray(vec1,&v1);
1451: VecRestoreArray(vec2,&v2);
1452: PetscObjectSetState((PetscObject) vec1,state1);
1453: PetscObjectSetState((PetscObject) vec2,state2);
1454: }
1455: }
1456: /* combine results from all processors */
1457: MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,((PetscObject)vec1)->comm);
1458: }
1459: return(0);
1460: }