Actual source code: vinv.c
2: /*
3: Some useful vector utility functions.
4: */
5: #include <private/vecimpl.h> /*I "petscvec.h" I*/
12: /*@
13: VecStrideSet - Sets a subvector of a vector defined
14: by a starting point and a stride with a given value
16: Logically Collective on Vec
18: Input Parameter:
19: + v - the vector
20: . start - starting point of the subvector (defined by a stride)
21: - s - value to multiply each subvector entry by
23: Notes:
24: One must call VecSetBlockSize() before this routine to set the stride
25: information, or use a vector created from a multicomponent DMDA.
27: This will only work if the desire subvector is a stride subvector
29: Level: advanced
31: Concepts: scale^on stride of vector
32: Concepts: stride^scale
34: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
35: @*/
36: PetscErrorCode VecStrideSet(Vec v,PetscInt start,PetscScalar s)
37: {
39: PetscInt i,n,bs;
40: PetscScalar *x;
47: VecGetLocalSize(v,&n);
48: VecGetArray(v,&x);
49: bs = v->map->bs;
50: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
51: else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
52: x += start;
54: for (i=0; i<n; i+=bs) {
55: x[i] = s;
56: }
57: x -= start;
59: VecRestoreArray(v,&x);
60: return(0);
61: }
65: /*@
66: VecStrideScale - Scales a subvector of a vector defined
67: by a starting point and a stride.
69: Logically Collective on Vec
71: Input Parameter:
72: + v - the vector
73: . start - starting point of the subvector (defined by a stride)
74: - scale - value to multiply each subvector entry by
76: Notes:
77: One must call VecSetBlockSize() before this routine to set the stride
78: information, or use a vector created from a multicomponent DMDA.
80: This will only work if the desire subvector is a stride subvector
82: Level: advanced
84: Concepts: scale^on stride of vector
85: Concepts: stride^scale
87: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
88: @*/
89: PetscErrorCode VecStrideScale(Vec v,PetscInt start,PetscScalar scale)
90: {
92: PetscInt i,n,bs;
93: PetscScalar *x;
100: VecGetLocalSize(v,&n);
101: VecGetArray(v,&x);
102: bs = v->map->bs;
103: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
104: else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
105: x += start;
107: for (i=0; i<n; i+=bs) {
108: x[i] *= scale;
109: }
110: x -= start;
112: VecRestoreArray(v,&x);
113: return(0);
114: }
118: /*@
119: VecStrideNorm - Computes the norm of subvector of a vector defined
120: by a starting point and a stride.
122: Collective on Vec
124: Input Parameter:
125: + v - the vector
126: . start - starting point of the subvector (defined by a stride)
127: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
129: Output Parameter:
130: . norm - the norm
132: Notes:
133: One must call VecSetBlockSize() before this routine to set the stride
134: information, or use a vector created from a multicomponent DMDA.
136: If x is the array representing the vector x then this computes the norm
137: of the array (x[start],x[start+stride],x[start+2*stride], ....)
139: This is useful for computing, say the norm of the pressure variable when
140: the pressure is stored (interlaced) with other variables, say density etc.
142: This will only work if the desire subvector is a stride subvector
144: Level: advanced
146: Concepts: norm^on stride of vector
147: Concepts: stride^norm
149: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
150: @*/
151: PetscErrorCode VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
152: {
154: PetscInt i,n,bs;
155: PetscScalar *x;
156: PetscReal tnorm;
157: MPI_Comm comm;
162: VecGetLocalSize(v,&n);
163: VecGetArray(v,&x);
164: PetscObjectGetComm((PetscObject)v,&comm);
166: bs = v->map->bs;
167: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
168: else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
169: x += start;
171: if (ntype == NORM_2) {
172: PetscScalar sum = 0.0;
173: for (i=0; i<n; i+=bs) {
174: sum += x[i]*(PetscConj(x[i]));
175: }
176: tnorm = PetscRealPart(sum);
177: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_SUM,comm);
178: *nrm = sqrt(*nrm);
179: } else if (ntype == NORM_1) {
180: tnorm = 0.0;
181: for (i=0; i<n; i+=bs) {
182: tnorm += PetscAbsScalar(x[i]);
183: }
184: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_SUM,comm);
185: } else if (ntype == NORM_INFINITY) {
186: PetscReal tmp;
187: tnorm = 0.0;
189: for (i=0; i<n; i+=bs) {
190: if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
191: /* check special case of tmp == NaN */
192: if (tmp != tmp) {tnorm = tmp; break;}
193: }
194: MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPIU_MAX,comm);
195: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
196: VecRestoreArray(v,&x);
197: return(0);
198: }
202: /*@
203: VecStrideMax - Computes the maximum of subvector of a vector defined
204: by a starting point and a stride and optionally its location.
206: Collective on Vec
208: Input Parameter:
209: + v - the vector
210: - start - starting point of the subvector (defined by a stride)
212: Output Parameter:
213: + index - the location where the maximum occurred (pass PETSC_NULL if not required)
214: - nrm - the max
216: Notes:
217: One must call VecSetBlockSize() before this routine to set the stride
218: information, or use a vector created from a multicomponent DMDA.
220: If xa is the array representing the vector x, then this computes the max
221: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
223: This is useful for computing, say the maximum of the pressure variable when
224: the pressure is stored (interlaced) with other variables, e.g., density, etc.
225: This will only work if the desire subvector is a stride subvector.
227: Level: advanced
229: Concepts: maximum^on stride of vector
230: Concepts: stride^maximum
232: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
233: @*/
234: PetscErrorCode VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
235: {
237: PetscInt i,n,bs,id;
238: PetscScalar *x;
239: PetscReal max,tmp;
240: MPI_Comm comm;
246: VecGetLocalSize(v,&n);
247: VecGetArray(v,&x);
248: PetscObjectGetComm((PetscObject)v,&comm);
250: bs = v->map->bs;
251: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
252: else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
253: x += start;
255: id = -1;
256: if (!n) {
257: max = PETSC_MIN_REAL;
258: } else {
259: id = 0;
260: #if defined(PETSC_USE_COMPLEX)
261: max = PetscRealPart(x[0]);
262: #else
263: max = x[0];
264: #endif
265: for (i=bs; i<n; i+=bs) {
266: #if defined(PETSC_USE_COMPLEX)
267: if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
268: #else
269: if ((tmp = x[i]) > max) { max = tmp; id = i;}
270: #endif
271: }
272: }
273: VecRestoreArray(v,&x);
275: if (!idex) {
276: MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPIU_MAX,comm);
277: } else {
278: PetscReal in[2],out[2];
279: PetscInt rstart;
281: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
282: in[0] = max;
283: in[1] = rstart+id+start;
284: MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,((PetscObject)v)->comm);
285: *nrm = out[0];
286: *idex = (PetscInt)out[1];
287: }
289: return(0);
290: }
294: /*@
295: VecStrideMin - Computes the minimum of subvector of a vector defined
296: by a starting point and a stride and optionally its location.
298: Collective on Vec
300: Input Parameter:
301: + v - the vector
302: - start - starting point of the subvector (defined by a stride)
304: Output Parameter:
305: + idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
306: - nrm - the min
308: Level: advanced
310: Notes:
311: One must call VecSetBlockSize() before this routine to set the stride
312: information, or use a vector created from a multicomponent DMDA.
314: If xa is the array representing the vector x, then this computes the min
315: of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
317: This is useful for computing, say the minimum of the pressure variable when
318: the pressure is stored (interlaced) with other variables, e.g., density, etc.
319: This will only work if the desire subvector is a stride subvector.
321: Concepts: minimum^on stride of vector
322: Concepts: stride^minimum
324: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
325: @*/
326: PetscErrorCode VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
327: {
329: PetscInt i,n,bs,id;
330: PetscScalar *x;
331: PetscReal min,tmp;
332: MPI_Comm comm;
338: VecGetLocalSize(v,&n);
339: VecGetArray(v,&x);
340: PetscObjectGetComm((PetscObject)v,&comm);
342: bs = v->map->bs;
343: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
344: else if (start >= bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\nHave you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
345: x += start;
347: id = -1;
348: if (!n) {
349: min = PETSC_MAX_REAL;
350: } else {
351: id = 0;
352: #if defined(PETSC_USE_COMPLEX)
353: min = PetscRealPart(x[0]);
354: #else
355: min = x[0];
356: #endif
357: for (i=bs; i<n; i+=bs) {
358: #if defined(PETSC_USE_COMPLEX)
359: if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
360: #else
361: if ((tmp = x[i]) < min) { min = tmp; id = i;}
362: #endif
363: }
364: }
365: VecRestoreArray(v,&x);
367: if (!idex) {
368: MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPIU_MIN,comm);
369: } else {
370: PetscReal in[2],out[2];
371: PetscInt rstart;
373: VecGetOwnershipRange(v,&rstart,PETSC_NULL);
374: in[0] = min;
375: in[1] = rstart+id;
376: MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,((PetscObject)v)->comm);
377: *nrm = out[0];
378: *idex = (PetscInt)out[1];
379: }
381: return(0);
382: }
386: /*@
387: VecStrideScaleAll - Scales the subvectors of a vector defined
388: by a starting point and a stride.
390: Logically Collective on Vec
392: Input Parameter:
393: + v - the vector
394: - scales - values to multiply each subvector entry by
396: Notes:
397: One must call VecSetBlockSize() before this routine to set the stride
398: information, or use a vector created from a multicomponent DMDA.
401: Level: advanced
403: Concepts: scale^on stride of vector
404: Concepts: stride^scale
406: .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
407: @*/
408: PetscErrorCode VecStrideScaleAll(Vec v,const PetscScalar *scales)
409: {
411: PetscInt i,j,n,bs;
412: PetscScalar *x;
417: VecGetLocalSize(v,&n);
418: VecGetArray(v,&x);
420: bs = v->map->bs;
422: /* need to provide optimized code for each bs */
423: for (i=0; i<n; i+=bs) {
424: for (j=0; j<bs; j++) {
425: x[i+j] *= scales[j];
426: }
427: }
428: VecRestoreArray(v,&x);
429: return(0);
430: }
434: /*@
435: VecStrideNormAll - Computes the norms subvectors of a vector defined
436: by a starting point and a stride.
438: Collective on Vec
440: Input Parameter:
441: + v - the vector
442: - ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
444: Output Parameter:
445: . nrm - the norms
447: Notes:
448: One must call VecSetBlockSize() before this routine to set the stride
449: information, or use a vector created from a multicomponent DMDA.
451: If x is the array representing the vector x then this computes the norm
452: of the array (x[start],x[start+stride],x[start+2*stride], ....)
454: This is useful for computing, say the norm of the pressure variable when
455: the pressure is stored (interlaced) with other variables, say density etc.
457: This will only work if the desire subvector is a stride subvector
459: Level: advanced
461: Concepts: norm^on stride of vector
462: Concepts: stride^norm
464: .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
465: @*/
466: PetscErrorCode VecStrideNormAll(Vec v,NormType ntype,PetscReal nrm[])
467: {
469: PetscInt i,j,n,bs;
470: PetscScalar *x;
471: PetscReal tnorm[128];
472: MPI_Comm comm;
477: VecGetLocalSize(v,&n);
478: VecGetArray(v,&x);
479: PetscObjectGetComm((PetscObject)v,&comm);
481: bs = v->map->bs;
482: if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
484: if (ntype == NORM_2) {
485: PetscScalar sum[128];
486: for (j=0; j<bs; j++) sum[j] = 0.0;
487: for (i=0; i<n; i+=bs) {
488: for (j=0; j<bs; j++) {
489: sum[j] += x[i+j]*(PetscConj(x[i+j]));
490: }
491: }
492: for (j=0; j<bs; j++) {
493: tnorm[j] = PetscRealPart(sum[j]);
494: }
495: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_SUM,comm);
496: for (j=0; j<bs; j++) {
497: nrm[j] = sqrt(nrm[j]);
498: }
499: } else if (ntype == NORM_1) {
500: for (j=0; j<bs; j++) {
501: tnorm[j] = 0.0;
502: }
503: for (i=0; i<n; i+=bs) {
504: for (j=0; j<bs; j++) {
505: tnorm[j] += PetscAbsScalar(x[i+j]);
506: }
507: }
508: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_SUM,comm);
509: } else if (ntype == NORM_INFINITY) {
510: PetscReal tmp;
511: for (j=0; j<bs; j++) {
512: tnorm[j] = 0.0;
513: }
515: for (i=0; i<n; i+=bs) {
516: for (j=0; j<bs; j++) {
517: if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
518: /* check special case of tmp == NaN */
519: if (tmp != tmp) {tnorm[j] = tmp; break;}
520: }
521: }
522: MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPIU_MAX,comm);
523: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
524: VecRestoreArray(v,&x);
525: return(0);
526: }
530: /*@
531: VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
532: by a starting point and a stride and optionally its location.
534: Collective on Vec
536: Input Parameter:
537: . v - the vector
539: Output Parameter:
540: + index - the location where the maximum occurred (not supported, pass PETSC_NULL,
541: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
542: - nrm - the maximums
544: Notes:
545: One must call VecSetBlockSize() before this routine to set the stride
546: information, or use a vector created from a multicomponent DMDA.
548: This is useful for computing, say the maximum of the pressure variable when
549: the pressure is stored (interlaced) with other variables, e.g., density, etc.
550: This will only work if the desire subvector is a stride subvector.
552: Level: advanced
554: Concepts: maximum^on stride of vector
555: Concepts: stride^maximum
557: .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
558: @*/
559: PetscErrorCode VecStrideMaxAll(Vec v,PetscInt idex[],PetscReal nrm[])
560: {
562: PetscInt i,j,n,bs;
563: PetscScalar *x;
564: PetscReal max[128],tmp;
565: MPI_Comm comm;
570: if (idex) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
571: VecGetLocalSize(v,&n);
572: VecGetArray(v,&x);
573: PetscObjectGetComm((PetscObject)v,&comm);
575: bs = v->map->bs;
576: if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
578: if (!n) {
579: for (j=0; j<bs; j++) {
580: max[j] = PETSC_MIN_REAL;
581: }
582: } else {
583: for (j=0; j<bs; j++) {
584: #if defined(PETSC_USE_COMPLEX)
585: max[j] = PetscRealPart(x[j]);
586: #else
587: max[j] = x[j];
588: #endif
589: }
590: for (i=bs; i<n; i+=bs) {
591: for (j=0; j<bs; j++) {
592: #if defined(PETSC_USE_COMPLEX)
593: if ((tmp = PetscRealPart(x[i+j])) > max[j]) { max[j] = tmp;}
594: #else
595: if ((tmp = x[i+j]) > max[j]) { max[j] = tmp; }
596: #endif
597: }
598: }
599: }
600: MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPIU_MAX,comm);
602: VecRestoreArray(v,&x);
603: return(0);
604: }
608: /*@
609: VecStrideMinAll - Computes the minimum of subvector of a vector defined
610: by a starting point and a stride and optionally its location.
612: Collective on Vec
614: Input Parameter:
615: . v - the vector
617: Output Parameter:
618: + idex - the location where the minimum occurred (not supported, pass PETSC_NULL,
619: if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
620: - nrm - the minimums
622: Level: advanced
624: Notes:
625: One must call VecSetBlockSize() before this routine to set the stride
626: information, or use a vector created from a multicomponent DMDA.
628: This is useful for computing, say the minimum of the pressure variable when
629: the pressure is stored (interlaced) with other variables, e.g., density, etc.
630: This will only work if the desire subvector is a stride subvector.
632: Concepts: minimum^on stride of vector
633: Concepts: stride^minimum
635: .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
636: @*/
637: PetscErrorCode VecStrideMinAll(Vec v,PetscInt idex[],PetscReal nrm[])
638: {
640: PetscInt i,n,bs,j;
641: PetscScalar *x;
642: PetscReal min[128],tmp;
643: MPI_Comm comm;
648: if (idex) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"No support yet for returning index; send mail to petsc-maint@mcs.anl.gov asking for it");
649: VecGetLocalSize(v,&n);
650: VecGetArray(v,&x);
651: PetscObjectGetComm((PetscObject)v,&comm);
653: bs = v->map->bs;
654: if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
656: if (!n) {
657: for (j=0; j<bs; j++) {
658: min[j] = PETSC_MAX_REAL;
659: }
660: } else {
661: for (j=0; j<bs; j++) {
662: #if defined(PETSC_USE_COMPLEX)
663: min[j] = PetscRealPart(x[j]);
664: #else
665: min[j] = x[j];
666: #endif
667: }
668: for (i=bs; i<n; i+=bs) {
669: for (j=0; j<bs; j++) {
670: #if defined(PETSC_USE_COMPLEX)
671: if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
672: #else
673: if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
674: #endif
675: }
676: }
677: }
678: MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPIU_MIN,comm);
680: VecRestoreArray(v,&x);
681: return(0);
682: }
684: /*----------------------------------------------------------------------------------------------*/
687: /*@
688: VecStrideGatherAll - Gathers all the single components from a multi-component vector into
689: separate vectors.
691: Collective on Vec
693: Input Parameter:
694: + v - the vector
695: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
697: Output Parameter:
698: . s - the location where the subvectors are stored
700: Notes:
701: One must call VecSetBlockSize() before this routine to set the stride
702: information, or use a vector created from a multicomponent DMDA.
704: If x is the array representing the vector x then this gathers
705: the arrays (x[start],x[start+stride],x[start+2*stride], ....)
706: for start=0,1,2,...bs-1
708: The parallel layout of the vector and the subvector must be the same;
709: i.e., nlocal of v = stride*(nlocal of s)
711: Not optimized; could be easily
713: Level: advanced
715: Concepts: gather^into strided vector
717: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
718: VecStrideScatterAll()
719: @*/
720: PetscErrorCode VecStrideGatherAll(Vec v,Vec s[],InsertMode addv)
721: {
723: PetscInt i,n,n2,bs,j,k,*bss = PETSC_NULL,nv,jj,nvc;
724: PetscScalar *x,**y;
730: VecGetLocalSize(v,&n);
731: VecGetLocalSize(s[0],&n2);
732: VecGetArray(v,&x);
733: bs = v->map->bs;
734: if (bs < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
736: PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);
737: nv = 0;
738: nvc = 0;
739: for (i=0; i<bs; i++) {
740: VecGetBlockSize(s[i],&bss[i]);
741: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
742: VecGetArray(s[i],&y[i]);
743: nvc += bss[i];
744: nv++;
745: if (nvc > bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
746: if (nvc == bs) break;
747: }
749: n = n/bs;
751: jj = 0;
752: if (addv == INSERT_VALUES) {
753: for (j=0; j<nv; j++) {
754: for (k=0; k<bss[j]; k++) {
755: for (i=0; i<n; i++) {
756: y[j][i*bss[j] + k] = x[bs*i+jj+k];
757: }
758: }
759: jj += bss[j];
760: }
761: } else if (addv == ADD_VALUES) {
762: for (j=0; j<nv; j++) {
763: for (k=0; k<bss[j]; k++) {
764: for (i=0; i<n; i++) {
765: y[j][i*bss[j] + k] += x[bs*i+jj+k];
766: }
767: }
768: jj += bss[j];
769: }
770: #if !defined(PETSC_USE_COMPLEX)
771: } else if (addv == MAX_VALUES) {
772: for (j=0; j<nv; j++) {
773: for (k=0; k<bss[j]; k++) {
774: for (i=0; i<n; i++) {
775: y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
776: }
777: }
778: jj += bss[j];
779: }
780: #endif
781: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
783: VecRestoreArray(v,&x);
784: for (i=0; i<nv; i++) {
785: VecRestoreArray(s[i],&y[i]);
786: }
788: PetscFree2(y,bss);
789: return(0);
790: }
794: /*@
795: VecStrideScatterAll - Scatters all the single components from separate vectors into
796: a multi-component vector.
798: Collective on Vec
800: Input Parameter:
801: + s - the location where the subvectors are stored
802: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
804: Output Parameter:
805: . v - the multicomponent vector
807: Notes:
808: One must call VecSetBlockSize() before this routine to set the stride
809: information, or use a vector created from a multicomponent DMDA.
811: The parallel layout of the vector and the subvector must be the same;
812: i.e., nlocal of v = stride*(nlocal of s)
814: Not optimized; could be easily
816: Level: advanced
818: Concepts: scatter^into strided vector
820: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
821: VecStrideScatterAll()
822: @*/
823: PetscErrorCode VecStrideScatterAll(Vec s[],Vec v,InsertMode addv)
824: {
826: PetscInt i,n,n2,bs,j,jj,k,*bss = PETSC_NULL,nv,nvc;
827: PetscScalar *x,**y;
833: VecGetLocalSize(v,&n);
834: VecGetLocalSize(s[0],&n2);
835: VecGetArray(v,&x);
836: bs = v->map->bs;
837: if (bs < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
839: PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);
840: nv = 0;
841: nvc = 0;
842: for (i=0; i<bs; i++) {
843: VecGetBlockSize(s[i],&bss[i]);
844: if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1 Re: [PETSC #8241] VecStrideGatherAll */
845: VecGetArray(s[i],&y[i]);
846: nvc += bss[i];
847: nv++;
848: if (nvc > bs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
849: if (nvc == bs) break;
850: }
852: n = n/bs;
854: jj = 0;
855: if (addv == INSERT_VALUES) {
856: for (j=0; j<nv; j++) {
857: for (k=0; k<bss[j]; k++) {
858: for (i=0; i<n; i++) {
859: x[bs*i+jj+k] = y[j][i*bss[j] + k];
860: }
861: }
862: jj += bss[j];
863: }
864: } else if (addv == ADD_VALUES) {
865: for (j=0; j<nv; j++) {
866: for (k=0; k<bss[j]; k++) {
867: for (i=0; i<n; i++) {
868: x[bs*i+jj+k] += y[j][i*bss[j] + k];
869: }
870: }
871: jj += bss[j];
872: }
873: #if !defined(PETSC_USE_COMPLEX)
874: } else if (addv == MAX_VALUES) {
875: for (j=0; j<nv; j++) {
876: for (k=0; k<bss[j]; k++) {
877: for (i=0; i<n; i++) {
878: x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
879: }
880: }
881: jj += bss[j];
882: }
883: #endif
884: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
886: VecRestoreArray(v,&x);
887: for (i=0; i<nv; i++) {
888: VecRestoreArray(s[i],&y[i]);
889: }
890: PetscFree2(y,bss);
891: return(0);
892: }
896: /*@
897: VecStrideGather - Gathers a single component from a multi-component vector into
898: another vector.
900: Collective on Vec
902: Input Parameter:
903: + v - the vector
904: . start - starting point of the subvector (defined by a stride)
905: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
907: Output Parameter:
908: . s - the location where the subvector is stored
910: Notes:
911: One must call VecSetBlockSize() before this routine to set the stride
912: information, or use a vector created from a multicomponent DMDA.
914: If x is the array representing the vector x then this gathers
915: the array (x[start],x[start+stride],x[start+2*stride], ....)
917: The parallel layout of the vector and the subvector must be the same;
918: i.e., nlocal of v = stride*(nlocal of s)
920: Not optimized; could be easily
922: Level: advanced
924: Concepts: gather^into strided vector
926: .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
927: VecStrideScatterAll()
928: @*/
929: PetscErrorCode VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
930: {
936: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
937: if (start >= v->map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
938: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
939: if (!v->ops->stridegather) SETERRQ(((PetscObject)s)->comm,PETSC_ERR_SUP,"Not implemented for this Vec class");
940: (*v->ops->stridegather)(v,start,s,addv);
941: return(0);
942: }
946: /*@
947: VecStrideScatter - Scatters a single component from a vector into a multi-component vector.
949: Collective on Vec
951: Input Parameter:
952: + s - the single-component vector
953: . start - starting point of the subvector (defined by a stride)
954: - addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
956: Output Parameter:
957: . v - the location where the subvector is scattered (the multi-component vector)
959: Notes:
960: One must call VecSetBlockSize() on the multi-component vector before this
961: routine to set the stride information, or use a vector created from a multicomponent DMDA.
963: The parallel layout of the vector and the subvector must be the same;
964: i.e., nlocal of v = stride*(nlocal of s)
966: Not optimized; could be easily
968: Level: advanced
970: Concepts: scatter^into strided vector
972: .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
973: VecStrideScatterAll()
974: @*/
975: PetscErrorCode VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
976: {
982: if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
983: if (start >= v->map->bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
984: Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
985: if (!v->ops->stridescatter) SETERRQ(((PetscObject)s)->comm,PETSC_ERR_SUP,"Not implemented for this Vec class");
986: (*v->ops->stridescatter)(s,start,v,addv);
987: return(0);
988: }
992: PetscErrorCode VecStrideGather_Default(Vec v,PetscInt start,Vec s,InsertMode addv)
993: {
995: PetscInt i,n,bs,ns;
996: PetscScalar *x,*y;
999: VecGetLocalSize(v,&n);
1000: VecGetLocalSize(s,&ns);
1001: VecGetArray(v,&x);
1002: VecGetArray(s,&y);
1004: bs = v->map->bs;
1005: if (n != ns*bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for gather from original vector %D",ns*bs,n);
1006: x += start;
1007: n = n/bs;
1009: if (addv == INSERT_VALUES) {
1010: for (i=0; i<n; i++) {
1011: y[i] = x[bs*i];
1012: }
1013: } else if (addv == ADD_VALUES) {
1014: for (i=0; i<n; i++) {
1015: y[i] += x[bs*i];
1016: }
1017: #if !defined(PETSC_USE_COMPLEX)
1018: } else if (addv == MAX_VALUES) {
1019: for (i=0; i<n; i++) {
1020: y[i] = PetscMax(y[i],x[bs*i]);
1021: }
1022: #endif
1023: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1025: VecRestoreArray(v,&x);
1026: VecRestoreArray(s,&y);
1027: return(0);
1028: }
1032: PetscErrorCode VecStrideScatter_Default(Vec s,PetscInt start,Vec v,InsertMode addv)
1033: {
1035: PetscInt i,n,bs,ns;
1036: PetscScalar *x,*y;
1039: VecGetLocalSize(v,&n);
1040: VecGetLocalSize(s,&ns);
1041: VecGetArray(v,&x);
1042: VecGetArray(s,&y);
1044: bs = v->map->bs;
1045: if (n != ns*bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Subvector length * blocksize %D not correct for scatter to multicomponent vector %D",ns*bs,n);
1046: x += start;
1047: n = n/bs;
1049: if (addv == INSERT_VALUES) {
1050: for (i=0; i<n; i++) {
1051: x[bs*i] = y[i];
1052: }
1053: } else if (addv == ADD_VALUES) {
1054: for (i=0; i<n; i++) {
1055: x[bs*i] += y[i];
1056: }
1057: #if !defined(PETSC_USE_COMPLEX)
1058: } else if (addv == MAX_VALUES) {
1059: for (i=0; i<n; i++) {
1060: x[bs*i] = PetscMax(y[i],x[bs*i]);
1061: }
1062: #endif
1063: } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1065: VecRestoreArray(v,&x);
1066: VecRestoreArray(s,&y);
1067: return(0);
1068: }
1072: PetscErrorCode VecReciprocal_Default(Vec v)
1073: {
1075: PetscInt i,n;
1076: PetscScalar *x;
1079: VecGetLocalSize(v,&n);
1080: VecGetArray(v,&x);
1081: for (i=0; i<n; i++) {
1082: if (x[i] != (PetscScalar)0.0) x[i] = (PetscScalar)1.0/x[i];
1083: }
1084: VecRestoreArray(v,&x);
1085: return(0);
1086: }
1090: /*@
1091: VecExp - Replaces each component of a vector by e^x_i
1093: Not collective
1095: Input Parameter:
1096: . v - The vector
1098: Output Parameter:
1099: . v - The vector of exponents
1101: Level: beginner
1103: .seealso: VecLog(), VecAbs(), VecSqrtAbs(), VecReciprocal()
1105: .keywords: vector, sqrt, square root
1106: @*/
1107: PetscErrorCode VecExp(Vec v)
1108: {
1109: PetscScalar *x;
1110: PetscInt i, n;
1115: if (v->ops->exp) {
1116: (*v->ops->exp)(v);
1117: } else {
1118: VecGetLocalSize(v, &n);
1119: VecGetArray(v, &x);
1120: for(i = 0; i < n; i++) {
1121: x[i] = PetscExpScalar(x[i]);
1122: }
1123: VecRestoreArray(v, &x);
1124: }
1125: return(0);
1126: }
1130: /*@
1131: VecLog - Replaces each component of a vector by log(x_i), the natural logarithm
1133: Not collective
1135: Input Parameter:
1136: . v - The vector
1138: Output Parameter:
1139: . v - The vector of logs
1141: Level: beginner
1143: .seealso: VecExp(), VecAbs(), VecSqrtAbs(), VecReciprocal()
1145: .keywords: vector, sqrt, square root
1146: @*/
1147: PetscErrorCode VecLog(Vec v)
1148: {
1149: PetscScalar *x;
1150: PetscInt i, n;
1155: if (v->ops->log) {
1156: (*v->ops->log)(v);
1157: } else {
1158: VecGetLocalSize(v, &n);
1159: VecGetArray(v, &x);
1160: for(i = 0; i < n; i++) {
1161: x[i] = PetscLogScalar(x[i]);
1162: }
1163: VecRestoreArray(v, &x);
1164: }
1165: return(0);
1166: }
1170: /*@
1171: VecSqrtAbs - Replaces each component of a vector by the square root of its magnitude.
1173: Not collective
1175: Input Parameter:
1176: . v - The vector
1178: Output Parameter:
1179: . v - The vector square root
1181: Level: beginner
1183: Note: The actual function is sqrt(|x_i|)
1185: .seealso: VecLog(), VecExp(), VecReciprocal(), VecAbs()
1187: .keywords: vector, sqrt, square root
1188: @*/
1189: PetscErrorCode VecSqrtAbs(Vec v)
1190: {
1191: PetscScalar *x;
1192: PetscInt i, n;
1197: if (v->ops->sqrt) {
1198: (*v->ops->sqrt)(v);
1199: } else {
1200: VecGetLocalSize(v, &n);
1201: VecGetArray(v, &x);
1202: for(i = 0; i < n; i++) {
1203: x[i] = sqrt(PetscAbsScalar(x[i]));
1204: }
1205: VecRestoreArray(v, &x);
1206: }
1207: return(0);
1208: }
1212: /*@
1213: VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector
1215: Collective on Vec
1217: Input Parameter:
1218: + s - first vector
1219: - t - second vector
1221: Output Parameter:
1222: + dp - s't
1223: - nm - t't
1225: Level: advanced
1227: Developer Notes: Even though the second return argument is a norm and hence could be a PetscReal value it is returned as PetscScalar
1229: .seealso: VecDot(), VecNorm(), VecDotBegin(), VecNormBegin(), VecDotEnd(), VecNormEnd()
1231: .keywords: vector, sqrt, square root
1232: @*/
1233: PetscErrorCode VecDotNorm2(Vec s,Vec t,PetscScalar *dp, PetscScalar *nm)
1234: {
1235: PetscScalar *sx, *tx, dpx = 0.0, nmx = 0.0,work[2],sum[2];
1236: PetscInt i, n;
1247: if (s->map->N != t->map->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector global lengths");
1248: if (s->map->n != t->map->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector local lengths");
1250: PetscLogEventBarrierBegin(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1251: if (s->ops->dotnorm2) {
1252: (*s->ops->dotnorm2)(s,t,dp,nm);
1253: } else {
1254: VecGetLocalSize(s, &n);
1255: VecGetArray(s, &sx);
1256: VecGetArray(t, &tx);
1258: for (i = 0; i<n; i++) {
1259: dpx += sx[i]*PetscConj(tx[i]);
1260: nmx += tx[i]*PetscConj(tx[i]);
1261: }
1262: work[0] = dpx;
1263: work[1] = nmx;
1264: MPI_Allreduce(&work,&sum,2,MPIU_SCALAR,MPIU_SUM,((PetscObject)s)->comm);
1265: *dp = sum[0];
1266: *nm = sum[1];
1268: VecRestoreArray(t, &tx);
1269: VecRestoreArray(s, &sx);
1270: PetscLogFlops(4.0*n);
1271: }
1272: PetscLogEventBarrierEnd(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);
1273: return(0);
1274: }
1278: /*@
1279: VecSum - Computes the sum of all the components of a vector.
1281: Collective on Vec
1283: Input Parameter:
1284: . v - the vector
1286: Output Parameter:
1287: . sum - the result
1289: Level: beginner
1291: Concepts: sum^of vector entries
1293: .seealso: VecNorm()
1294: @*/
1295: PetscErrorCode VecSum(Vec v,PetscScalar *sum)
1296: {
1298: PetscInt i,n;
1299: PetscScalar *x,lsum = 0.0;
1304: VecGetLocalSize(v,&n);
1305: VecGetArray(v,&x);
1306: for (i=0; i<n; i++) {
1307: lsum += x[i];
1308: }
1309: MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,MPIU_SUM,((PetscObject)v)->comm);
1310: VecRestoreArray(v,&x);
1311: return(0);
1312: }
1316: /*@
1317: VecShift - Shifts all of the components of a vector by computing
1318: x[i] = x[i] + shift.
1320: Logically Collective on Vec
1322: Input Parameters:
1323: + v - the vector
1324: - shift - the shift
1326: Output Parameter:
1327: . v - the shifted vector
1329: Level: intermediate
1331: Concepts: vector^adding constant
1333: @*/
1334: PetscErrorCode VecShift(Vec v,PetscScalar shift)
1335: {
1337: PetscInt i,n;
1338: PetscScalar *x;
1343: if (v->ops->shift) {
1344: (*v->ops->shift)(v);
1345: } else {
1346: VecGetLocalSize(v,&n);
1347: VecGetArray(v,&x);
1348: for (i=0; i<n; i++) {
1349: x[i] += shift;
1350: }
1351: VecRestoreArray(v,&x);
1352: }
1353: return(0);
1354: }
1358: /*@
1359: VecAbs - Replaces every element in a vector with its absolute value.
1361: Logically Collective on Vec
1363: Input Parameters:
1364: . v - the vector
1366: Level: intermediate
1368: Concepts: vector^absolute value
1370: @*/
1371: PetscErrorCode VecAbs(Vec v)
1372: {
1374: PetscInt i,n;
1375: PetscScalar *x;
1379: if (v->ops->abs) {
1380: (*v->ops->abs)(v);
1381: } else {
1382: VecGetLocalSize(v,&n);
1383: VecGetArray(v,&x);
1384: for (i=0; i<n; i++) {
1385: x[i] = PetscAbsScalar(x[i]);
1386: }
1387: VecRestoreArray(v,&x);
1388: }
1389: return(0);
1390: }
1394: /*@
1395: VecPermute - Permutes a vector in place using the given ordering.
1397: Input Parameters:
1398: + vec - The vector
1399: . order - The ordering
1400: - inv - The flag for inverting the permutation
1402: Level: beginner
1404: Note: This function does not yet support parallel Index Sets
1406: .seealso: MatPermute()
1407: .keywords: vec, permute
1408: @*/
1409: PetscErrorCode VecPermute(Vec x, IS row, PetscBool inv)
1410: {
1411: PetscScalar *array, *newArray;
1412: const PetscInt *idx;
1413: PetscInt i;
1417: ISGetIndices(row, &idx);
1418: VecGetArray(x, &array);
1419: PetscMalloc(x->map->n*sizeof(PetscScalar), &newArray);
1420: #ifdef PETSC_USE_DEBUG
1421: for(i = 0; i < x->map->n; i++) {
1422: if ((idx[i] < 0) || (idx[i] >= x->map->n)) {
1423: SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1424: }
1425: }
1426: #endif
1427: if (!inv) {
1428: for(i = 0; i < x->map->n; i++) newArray[i] = array[idx[i]];
1429: } else {
1430: for(i = 0; i < x->map->n; i++) newArray[idx[i]] = array[i];
1431: }
1432: VecRestoreArray(x, &array);
1433: ISRestoreIndices(row, &idx);
1434: VecReplaceArray(x, newArray);
1435: return(0);
1436: }
1440: /*@
1441: VecEqual - Compares two vectors.
1443: Collective on Vec
1445: Input Parameters:
1446: + vec1 - the first vector
1447: - vec2 - the second vector
1449: Output Parameter:
1450: . flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.
1452: Level: intermediate
1454: Concepts: equal^two vectors
1455: Concepts: vector^equality
1457: @*/
1458: PetscErrorCode VecEqual(Vec vec1,Vec vec2,PetscBool *flg)
1459: {
1460: PetscScalar *v1,*v2;
1462: PetscInt n1,n2,N1,N2;
1463: PetscInt state1,state2;
1464: PetscBool flg1;
1465:
1470: if (vec1 == vec2) {
1471: *flg = PETSC_TRUE;
1472: } else {
1473: VecGetSize(vec1,&N1);
1474: VecGetSize(vec2,&N2);
1475: if (N1 != N2) {
1476: flg1 = PETSC_FALSE;
1477: } else {
1478: VecGetLocalSize(vec1,&n1);
1479: VecGetLocalSize(vec2,&n2);
1480: if (n1 != n2) {
1481: flg1 = PETSC_FALSE;
1482: } else {
1483: PetscObjectStateQuery((PetscObject) vec1,&state1);
1484: PetscObjectStateQuery((PetscObject) vec2,&state2);
1485: VecGetArray(vec1,&v1);
1486: VecGetArray(vec2,&v2);
1487: #if defined(PETSC_USE_COMPLEX)
1488: {
1489: PetscInt k;
1490: flg1 = PETSC_TRUE;
1491: for (k=0; k<n1; k++){
1492: if (PetscRealPart(v1[k]) != PetscRealPart(v2[k]) || PetscImaginaryPart(v1[k]) != PetscImaginaryPart(v2[k])){
1493: flg1 = PETSC_FALSE;
1494: break;
1495: }
1496: }
1497: }
1498: #else
1499: PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);
1500: #endif
1501: VecRestoreArray(vec1,&v1);
1502: VecRestoreArray(vec2,&v2);
1503: PetscObjectSetState((PetscObject) vec1,state1);
1504: PetscObjectSetState((PetscObject) vec2,state2);
1505: }
1506: }
1507: /* combine results from all processors */
1508: MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,((PetscObject)vec1)->comm);
1509: }
1510: return(0);
1511: }