xref: /petsc/src/vec/vec/utils/vinv.c (revision 7c93a85d6d4254fee34d99f3e5bd9e4999a6ce2c)
1 #define PETSCVEC_DLL
2 
3 /*
4      Some useful vector utility functions.
5 */
6 #include "private/vecimpl.h"          /*I "petscvec.h" I*/
7 
8 extern MPI_Op VecMax_Local_Op;
9 extern MPI_Op VecMin_Local_Op;
10 
11 #undef __FUNCT__
12 #define __FUNCT__ "VecStrideScale"
13 /*@
14    VecStrideScale - Scales a subvector of a vector defined
15    by a starting point and a stride.
16 
17    Logically Collective on Vec
18 
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
23 
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.
27 
28    This will only work if the desire subvector is a stride subvector
29 
30    Level: advanced
31 
32    Concepts: scale^on stride of vector
33    Concepts: stride^scale
34 
35 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideScale()
36 @*/
37 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScale(Vec v,PetscInt start,PetscScalar scale)
38 {
39   PetscErrorCode ierr;
40   PetscInt       i,n,bs;
41   PetscScalar    *x;
42 
43   PetscFunctionBegin;
44   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
45   PetscValidLogicalCollectiveInt(v,start,2);
46   PetscValidLogicalCollectiveScalar(v,scale,3);
47 
48   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
49   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
50   bs   = v->map->bs;
51   if (start < 0) {
52     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
53   } else if (start >= bs) {
54     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
55             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
56   }
57   x += start;
58 
59   for (i=0; i<n; i+=bs) {
60     x[i] *= scale;
61   }
62   x -= start;
63 
64   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
65   PetscFunctionReturn(0);
66 }
67 
68 #undef __FUNCT__
69 #define __FUNCT__ "VecStrideNorm"
70 /*@
71    VecStrideNorm - Computes the norm of subvector of a vector defined
72    by a starting point and a stride.
73 
74    Collective on Vec
75 
76    Input Parameter:
77 +  v - the vector
78 .  start - starting point of the subvector (defined by a stride)
79 -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
80 
81    Output Parameter:
82 .  norm - the norm
83 
84    Notes:
85    One must call VecSetBlockSize() before this routine to set the stride
86    information, or use a vector created from a multicomponent DA.
87 
88    If x is the array representing the vector x then this computes the norm
89    of the array (x[start],x[start+stride],x[start+2*stride], ....)
90 
91    This is useful for computing, say the norm of the pressure variable when
92    the pressure is stored (interlaced) with other variables, say density etc.
93 
94    This will only work if the desire subvector is a stride subvector
95 
96    Level: advanced
97 
98    Concepts: norm^on stride of vector
99    Concepts: stride^norm
100 
101 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
102 @*/
103 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNorm(Vec v,PetscInt start,NormType ntype,PetscReal *nrm)
104 {
105   PetscErrorCode ierr;
106   PetscInt       i,n,bs;
107   PetscScalar    *x;
108   PetscReal      tnorm;
109   MPI_Comm       comm;
110 
111   PetscFunctionBegin;
112   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
113   PetscValidDoublePointer(nrm,3);
114   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
115   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
116   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
117 
118   bs   = v->map->bs;
119   if (start < 0) {
120     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
121   } else if (start >= bs) {
122     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
123             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
124   }
125   x += start;
126 
127   if (ntype == NORM_2) {
128     PetscScalar sum = 0.0;
129     for (i=0; i<n; i+=bs) {
130       sum += x[i]*(PetscConj(x[i]));
131     }
132     tnorm  = PetscRealPart(sum);
133     ierr   = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr);
134     *nrm = sqrt(*nrm);
135   } else if (ntype == NORM_1) {
136     tnorm = 0.0;
137     for (i=0; i<n; i+=bs) {
138       tnorm += PetscAbsScalar(x[i]);
139     }
140     ierr   = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr);
141   } else if (ntype == NORM_INFINITY) {
142     PetscReal tmp;
143     tnorm = 0.0;
144 
145     for (i=0; i<n; i+=bs) {
146       if ((tmp = PetscAbsScalar(x[i])) > tnorm) tnorm = tmp;
147       /* check special case of tmp == NaN */
148       if (tmp != tmp) {tnorm = tmp; break;}
149     }
150     ierr   = MPI_Allreduce(&tnorm,nrm,1,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr);
151   } else {
152     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
153   }
154 
155   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
156   PetscFunctionReturn(0);
157 }
158 
159 #undef __FUNCT__
160 #define __FUNCT__ "VecStrideMax"
161 /*@
162    VecStrideMax - Computes the maximum of subvector of a vector defined
163    by a starting point and a stride and optionally its location.
164 
165    Collective on Vec
166 
167    Input Parameter:
168 +  v - the vector
169 -  start - starting point of the subvector (defined by a stride)
170 
171    Output Parameter:
172 +  index - the location where the maximum occurred  (pass PETSC_NULL if not required)
173 -  nrm - the max
174 
175    Notes:
176    One must call VecSetBlockSize() before this routine to set the stride
177    information, or use a vector created from a multicomponent DA.
178 
179    If xa is the array representing the vector x, then this computes the max
180    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
181 
182    This is useful for computing, say the maximum of the pressure variable when
183    the pressure is stored (interlaced) with other variables, e.g., density, etc.
184    This will only work if the desire subvector is a stride subvector.
185 
186    Level: advanced
187 
188    Concepts: maximum^on stride of vector
189    Concepts: stride^maximum
190 
191 .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
192 @*/
193 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMax(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
194 {
195   PetscErrorCode ierr;
196   PetscInt       i,n,bs,id;
197   PetscScalar    *x;
198   PetscReal      max,tmp;
199   MPI_Comm       comm;
200 
201   PetscFunctionBegin;
202   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
203   PetscValidDoublePointer(nrm,3);
204 
205   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
206   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
207   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
208 
209   bs   = v->map->bs;
210   if (start < 0) {
211     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
212   } else if (start >= bs) {
213     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
214             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
215   }
216   x += start;
217 
218   id = -1;
219   if (!n) {
220     max = PETSC_MIN;
221   } else {
222     id  = 0;
223 #if defined(PETSC_USE_COMPLEX)
224     max = PetscRealPart(x[0]);
225 #else
226     max = x[0];
227 #endif
228     for (i=bs; i<n; i+=bs) {
229 #if defined(PETSC_USE_COMPLEX)
230       if ((tmp = PetscRealPart(x[i])) > max) { max = tmp; id = i;}
231 #else
232       if ((tmp = x[i]) > max) { max = tmp; id = i;}
233 #endif
234     }
235   }
236   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
237 
238   if (!idex) {
239     ierr   = MPI_Allreduce(&max,nrm,1,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr);
240   } else {
241     PetscReal in[2],out[2];
242     PetscInt  rstart;
243 
244     ierr  = VecGetOwnershipRange(v,&rstart,PETSC_NULL);CHKERRQ(ierr);
245     in[0] = max;
246     in[1] = rstart+id+start;
247     ierr  = MPI_Allreduce(in,out,2,MPIU_REAL,VecMax_Local_Op,((PetscObject)v)->comm);CHKERRQ(ierr);
248     *nrm  = out[0];
249     *idex = (PetscInt)out[1];
250   }
251 
252   PetscFunctionReturn(0);
253 }
254 
255 #undef __FUNCT__
256 #define __FUNCT__ "VecStrideMin"
257 /*@
258    VecStrideMin - Computes the minimum of subvector of a vector defined
259    by a starting point and a stride and optionally its location.
260 
261    Collective on Vec
262 
263    Input Parameter:
264 +  v - the vector
265 -  start - starting point of the subvector (defined by a stride)
266 
267    Output Parameter:
268 +  idex - the location where the minimum occurred. (pass PETSC_NULL if not required)
269 -  nrm - the min
270 
271    Level: advanced
272 
273    Notes:
274    One must call VecSetBlockSize() before this routine to set the stride
275    information, or use a vector created from a multicomponent DA.
276 
277    If xa is the array representing the vector x, then this computes the min
278    of the array (xa[start],xa[start+stride],xa[start+2*stride], ....)
279 
280    This is useful for computing, say the minimum of the pressure variable when
281    the pressure is stored (interlaced) with other variables, e.g., density, etc.
282    This will only work if the desire subvector is a stride subvector.
283 
284    Concepts: minimum^on stride of vector
285    Concepts: stride^minimum
286 
287 .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
288 @*/
289 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMin(Vec v,PetscInt start,PetscInt *idex,PetscReal *nrm)
290 {
291   PetscErrorCode ierr;
292   PetscInt       i,n,bs,id;
293   PetscScalar    *x;
294   PetscReal      min,tmp;
295   MPI_Comm       comm;
296 
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
299   PetscValidDoublePointer(nrm,4);
300 
301   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
302   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
303   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
304 
305   bs   = v->map->bs;
306   if (start < 0) {
307     SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
308   } else if (start >= bs) {
309     SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Start of stride subvector (%D) is too large for stride\n\
310             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,bs);
311   }
312   x += start;
313 
314   id = -1;
315   if (!n) {
316     min = PETSC_MAX;
317   } else {
318     id = 0;
319 #if defined(PETSC_USE_COMPLEX)
320     min = PetscRealPart(x[0]);
321 #else
322     min = x[0];
323 #endif
324     for (i=bs; i<n; i+=bs) {
325 #if defined(PETSC_USE_COMPLEX)
326       if ((tmp = PetscRealPart(x[i])) < min) { min = tmp; id = i;}
327 #else
328       if ((tmp = x[i]) < min) { min = tmp; id = i;}
329 #endif
330     }
331   }
332   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
333 
334   if (!idex) {
335     ierr   = MPI_Allreduce(&min,nrm,1,MPIU_REAL,MPI_MIN,comm);CHKERRQ(ierr);
336   } else {
337     PetscReal in[2],out[2];
338     PetscInt  rstart;
339 
340     ierr  = VecGetOwnershipRange(v,&rstart,PETSC_NULL);CHKERRQ(ierr);
341     in[0] = min;
342     in[1] = rstart+id;
343     ierr  = MPI_Allreduce(in,out,2,MPIU_REAL,VecMin_Local_Op,((PetscObject)v)->comm);CHKERRQ(ierr);
344     *nrm  = out[0];
345     *idex = (PetscInt)out[1];
346   }
347 
348   PetscFunctionReturn(0);
349 }
350 
351 #undef __FUNCT__
352 #define __FUNCT__ "VecStrideScaleAll"
353 /*@
354    VecStrideScaleAll - Scales the subvectors of a vector defined
355    by a starting point and a stride.
356 
357    Logically Collective on Vec
358 
359    Input Parameter:
360 +  v - the vector
361 -  scales - values to multiply each subvector entry by
362 
363    Notes:
364    One must call VecSetBlockSize() before this routine to set the stride
365    information, or use a vector created from a multicomponent DA.
366 
367 
368    Level: advanced
369 
370    Concepts: scale^on stride of vector
371    Concepts: stride^scale
372 
373 .seealso: VecNorm(), VecStrideScale(), VecScale(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
374 @*/
375 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScaleAll(Vec v,PetscScalar *scales)
376 {
377   PetscErrorCode ierr;
378   PetscInt       i,j,n,bs;
379   PetscScalar    *x;
380 
381   PetscFunctionBegin;
382   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
383   PetscValidScalarPointer(scales,2);
384   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
385   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
386 
387   bs   = v->map->bs;
388 
389   /* need to provide optimized code for each bs */
390   for (i=0; i<n; i+=bs) {
391     for (j=0; j<bs; j++) {
392       x[i+j] *= scales[j];
393     }
394   }
395   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
396   PetscFunctionReturn(0);
397 }
398 
399 #undef __FUNCT__
400 #define __FUNCT__ "VecStrideNormAll"
401 /*@
402    VecStrideNormAll - Computes the norms  subvectors of a vector defined
403    by a starting point and a stride.
404 
405    Collective on Vec
406 
407    Input Parameter:
408 +  v - the vector
409 -  ntype - type of norm, one of NORM_1, NORM_2, NORM_INFINITY
410 
411    Output Parameter:
412 .  nrm - the norms
413 
414    Notes:
415    One must call VecSetBlockSize() before this routine to set the stride
416    information, or use a vector created from a multicomponent DA.
417 
418    If x is the array representing the vector x then this computes the norm
419    of the array (x[start],x[start+stride],x[start+2*stride], ....)
420 
421    This is useful for computing, say the norm of the pressure variable when
422    the pressure is stored (interlaced) with other variables, say density etc.
423 
424    This will only work if the desire subvector is a stride subvector
425 
426    Level: advanced
427 
428    Concepts: norm^on stride of vector
429    Concepts: stride^norm
430 
431 .seealso: VecNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin(), VecStrideMax()
432 @*/
433 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideNormAll(Vec v,NormType ntype,PetscReal nrm[])
434 {
435   PetscErrorCode ierr;
436   PetscInt       i,j,n,bs;
437   PetscScalar    *x;
438   PetscReal      tnorm[128];
439   MPI_Comm       comm;
440 
441   PetscFunctionBegin;
442   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
443   PetscValidDoublePointer(nrm,3);
444   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
445   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
446   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
447 
448   bs   = v->map->bs;
449   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
450 
451   if (ntype == NORM_2) {
452     PetscScalar sum[128];
453     for (j=0; j<bs; j++) sum[j] = 0.0;
454     for (i=0; i<n; i+=bs) {
455       for (j=0; j<bs; j++) {
456 	sum[j] += x[i+j]*(PetscConj(x[i+j]));
457       }
458     }
459     for (j=0; j<bs; j++) {
460       tnorm[j]  = PetscRealPart(sum[j]);
461     }
462     ierr   = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr);
463     for (j=0; j<bs; j++) {
464       nrm[j] = sqrt(nrm[j]);
465     }
466   } else if (ntype == NORM_1) {
467     for (j=0; j<bs; j++) {
468       tnorm[j] = 0.0;
469     }
470     for (i=0; i<n; i+=bs) {
471       for (j=0; j<bs; j++) {
472 	tnorm[j] += PetscAbsScalar(x[i+j]);
473       }
474     }
475     ierr   = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_SUM,comm);CHKERRQ(ierr);
476   } else if (ntype == NORM_INFINITY) {
477     PetscReal tmp;
478     for (j=0; j<bs; j++) {
479       tnorm[j] = 0.0;
480     }
481 
482     for (i=0; i<n; i+=bs) {
483       for (j=0; j<bs; j++) {
484 	if ((tmp = PetscAbsScalar(x[i+j])) > tnorm[j]) tnorm[j] = tmp;
485 	/* check special case of tmp == NaN */
486 	if (tmp != tmp) {tnorm[j] = tmp; break;}
487       }
488     }
489     ierr   = MPI_Allreduce(tnorm,nrm,bs,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr);
490   } else {
491     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown norm type");
492   }
493 
494   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
495   PetscFunctionReturn(0);
496 }
497 
498 #undef __FUNCT__
499 #define __FUNCT__ "VecStrideMaxAll"
500 /*@
501    VecStrideMaxAll - Computes the maximums of subvectors of a vector defined
502    by a starting point and a stride and optionally its location.
503 
504    Collective on Vec
505 
506    Input Parameter:
507 .  v - the vector
508 
509    Output Parameter:
510 +  index - the location where the maximum occurred (not supported, pass PETSC_NULL,
511            if you need this, send mail to petsc-maint@mcs.anl.gov to request it)
512 -  nrm - the maximums
513 
514    Notes:
515    One must call VecSetBlockSize() before this routine to set the stride
516    information, or use a vector created from a multicomponent DA.
517 
518    This is useful for computing, say the maximum of the pressure variable when
519    the pressure is stored (interlaced) with other variables, e.g., density, etc.
520    This will only work if the desire subvector is a stride subvector.
521 
522    Level: advanced
523 
524    Concepts: maximum^on stride of vector
525    Concepts: stride^maximum
526 
527 .seealso: VecMax(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMin()
528 @*/
529 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMaxAll(Vec v,PetscInt idex[],PetscReal nrm[])
530 {
531   PetscErrorCode ierr;
532   PetscInt       i,j,n,bs;
533   PetscScalar    *x;
534   PetscReal      max[128],tmp;
535   MPI_Comm       comm;
536 
537   PetscFunctionBegin;
538   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
539   PetscValidDoublePointer(nrm,3);
540   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");
541   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
542   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
543   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
544 
545   bs   = v->map->bs;
546   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
547 
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   ierr   = MPI_Allreduce(max,nrm,bs,MPIU_REAL,MPI_MAX,comm);CHKERRQ(ierr);
571 
572   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
573   PetscFunctionReturn(0);
574 }
575 
576 #undef __FUNCT__
577 #define __FUNCT__ "VecStrideMinAll"
578 /*@
579    VecStrideMinAll - Computes the minimum of subvector of a vector defined
580    by a starting point and a stride and optionally its location.
581 
582    Collective on Vec
583 
584    Input Parameter:
585 .  v - the vector
586 
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
591 
592    Level: advanced
593 
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.
597 
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.
601 
602    Concepts: minimum^on stride of vector
603    Concepts: stride^minimum
604 
605 .seealso: VecMin(), VecStrideNorm(), VecStrideGather(), VecStrideScatter(), VecStrideMax()
606 @*/
607 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideMinAll(Vec v,PetscInt idex[],PetscReal nrm[])
608 {
609   PetscErrorCode ierr;
610   PetscInt       i,n,bs,j;
611   PetscScalar    *x;
612   PetscReal      min[128],tmp;
613   MPI_Comm       comm;
614 
615   PetscFunctionBegin;
616   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
617   PetscValidDoublePointer(nrm,3);
618   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");
619   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
620   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
621   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
622 
623   bs   = v->map->bs;
624   if (bs > 128) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Currently supports only blocksize up to 128");
625 
626   if (!n) {
627     for (j=0; j<bs; j++) {
628       min[j] = PETSC_MAX;
629     }
630   } else {
631     for (j=0; j<bs; j++) {
632 #if defined(PETSC_USE_COMPLEX)
633       min[j] = PetscRealPart(x[j]);
634 #else
635       min[j] = x[j];
636 #endif
637     }
638     for (i=bs; i<n; i+=bs) {
639       for (j=0; j<bs; j++) {
640 #if defined(PETSC_USE_COMPLEX)
641 	if ((tmp = PetscRealPart(x[i+j])) < min[j]) { min[j] = tmp;}
642 #else
643 	if ((tmp = x[i+j]) < min[j]) { min[j] = tmp; }
644 #endif
645       }
646     }
647   }
648   ierr   = MPI_Allreduce(min,nrm,bs,MPIU_REAL,MPI_MIN,comm);CHKERRQ(ierr);
649 
650   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
651   PetscFunctionReturn(0);
652 }
653 
654 /*----------------------------------------------------------------------------------------------*/
655 #undef __FUNCT__
656 #define __FUNCT__ "VecStrideGatherAll"
657 /*@
658    VecStrideGatherAll - Gathers all the single components from a multi-component vector into
659    separate vectors.
660 
661    Collective on Vec
662 
663    Input Parameter:
664 +  v - the vector
665 -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
666 
667    Output Parameter:
668 .  s - the location where the subvectors are stored
669 
670    Notes:
671    One must call VecSetBlockSize() before this routine to set the stride
672    information, or use a vector created from a multicomponent DA.
673 
674    If x is the array representing the vector x then this gathers
675    the arrays (x[start],x[start+stride],x[start+2*stride], ....)
676    for start=0,1,2,...bs-1
677 
678    The parallel layout of the vector and the subvector must be the same;
679    i.e., nlocal of v = stride*(nlocal of s)
680 
681    Not optimized; could be easily
682 
683    Level: advanced
684 
685    Concepts: gather^into strided vector
686 
687 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
688           VecStrideScatterAll()
689 @*/
690 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGatherAll(Vec v,Vec s[],InsertMode addv)
691 {
692   PetscErrorCode ierr;
693   PetscInt       i,n,n2,bs,j,k,*bss = PETSC_NULL,nv,jj,nvc;
694   PetscScalar    *x,**y;
695 
696   PetscFunctionBegin;
697   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
698   PetscValidPointer(s,2);
699   PetscValidHeaderSpecific(*s,VEC_CLASSID,2);
700   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
701   ierr = VecGetLocalSize(s[0],&n2);CHKERRQ(ierr);
702   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
703   bs   = v->map->bs;
704   if (bs < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
705 
706   ierr = PetscMalloc2(bs,PetscReal*,&y,bs,PetscInt,&bss);CHKERRQ(ierr);
707   nv   = 0;
708   nvc  = 0;
709   for (i=0; i<bs; i++) {
710     ierr = VecGetBlockSize(s[i],&bss[i]);CHKERRQ(ierr);
711     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
712     ierr = VecGetArray(s[i],&y[i]);CHKERRQ(ierr);
713     nvc  += bss[i];
714     nv++;
715     if (nvc > bs)  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
716     if (nvc == bs) break;
717   }
718 
719   n =  n/bs;
720 
721   jj = 0;
722   if (addv == INSERT_VALUES) {
723     for (j=0; j<nv; j++) {
724       for (k=0; k<bss[j]; k++) {
725 	for (i=0; i<n; i++) {
726 	  y[j][i*bss[j] + k] = x[bs*i+jj+k];
727         }
728       }
729       jj += bss[j];
730     }
731   } else if (addv == ADD_VALUES) {
732     for (j=0; j<nv; j++) {
733       for (k=0; k<bss[j]; k++) {
734 	for (i=0; i<n; i++) {
735 	  y[j][i*bss[j] + k] += x[bs*i+jj+k];
736         }
737       }
738       jj += bss[j];
739     }
740 #if !defined(PETSC_USE_COMPLEX)
741   } else if (addv == MAX_VALUES) {
742     for (j=0; j<nv; j++) {
743       for (k=0; k<bss[j]; k++) {
744 	for (i=0; i<n; i++) {
745 	  y[j][i*bss[j] + k] = PetscMax(y[j][i*bss[j] + k],x[bs*i+jj+k]);
746         }
747       }
748       jj += bss[j];
749     }
750 #endif
751   } else {
752     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
753   }
754 
755   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
756   for (i=0; i<nv; i++) {
757     ierr = VecRestoreArray(s[i],&y[i]);CHKERRQ(ierr);
758   }
759 
760   ierr = PetscFree2(y,bss);CHKERRQ(ierr);
761   PetscFunctionReturn(0);
762 }
763 
764 #undef __FUNCT__
765 #define __FUNCT__ "VecStrideScatterAll"
766 /*@
767    VecStrideScatterAll - Scatters all the single components from separate vectors into
768      a multi-component vector.
769 
770    Collective on Vec
771 
772    Input Parameter:
773 +  s - the location where the subvectors are stored
774 -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
775 
776    Output Parameter:
777 .  v - the multicomponent vector
778 
779    Notes:
780    One must call VecSetBlockSize() before this routine to set the stride
781    information, or use a vector created from a multicomponent DA.
782 
783    The parallel layout of the vector and the subvector must be the same;
784    i.e., nlocal of v = stride*(nlocal of s)
785 
786    Not optimized; could be easily
787 
788    Level: advanced
789 
790    Concepts:  scatter^into strided vector
791 
792 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGather(),
793           VecStrideScatterAll()
794 @*/
795 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatterAll(Vec s[],Vec v,InsertMode addv)
796 {
797   PetscErrorCode ierr;
798   PetscInt        i,n,n2,bs,j,jj,k,*bss = PETSC_NULL,nv,nvc;
799   PetscScalar     *x,**y;
800 
801   PetscFunctionBegin;
802   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
803   PetscValidPointer(s,2);
804   PetscValidHeaderSpecific(*s,VEC_CLASSID,2);
805   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
806   ierr = VecGetLocalSize(s[0],&n2);CHKERRQ(ierr);
807   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
808   bs   = v->map->bs;
809   if (bs < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Input vector does not have a valid blocksize set");
810 
811   ierr = PetscMalloc2(bs,PetscScalar**,&y,bs,PetscInt,&bss);CHKERRQ(ierr);
812   nv  = 0;
813   nvc = 0;
814   for (i=0; i<bs; i++) {
815     ierr = VecGetBlockSize(s[i],&bss[i]);CHKERRQ(ierr);
816     if (bss[i] < 1) bss[i] = 1; /* if user never set it then assume 1  Re: [PETSC #8241] VecStrideGatherAll */
817     ierr = VecGetArray(s[i],&y[i]);CHKERRQ(ierr);
818     nvc  += bss[i];
819     nv++;
820     if (nvc > bs)  SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Number of subvectors in subvectors > number of vectors in main vector");
821     if (nvc == bs) break;
822   }
823 
824   n =  n/bs;
825 
826   jj = 0;
827   if (addv == INSERT_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   } else if (addv == ADD_VALUES) {
837     for (j=0; j<nv; j++) {
838       for (k=0; k<bss[j]; k++) {
839 	for (i=0; i<n; i++) {
840 	  x[bs*i+jj+k] += y[j][i*bss[j] + k];
841         }
842       }
843       jj += bss[j];
844     }
845 #if !defined(PETSC_USE_COMPLEX)
846   } else if (addv == MAX_VALUES) {
847     for (j=0; j<nv; j++) {
848       for (k=0; k<bss[j]; k++) {
849 	for (i=0; i<n; i++) {
850 	  x[bs*i+jj+k] = PetscMax(x[bs*i+jj+k],y[j][i*bss[j] + k]);
851         }
852       }
853       jj += bss[j];
854     }
855 #endif
856   } else {
857     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
858   }
859 
860   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
861   for (i=0; i<nv; i++) {
862     ierr = VecRestoreArray(s[i],&y[i]);CHKERRQ(ierr);
863   }
864   ierr = PetscFree2(y,bss);CHKERRQ(ierr);
865   PetscFunctionReturn(0);
866 }
867 
868 #undef __FUNCT__
869 #define __FUNCT__ "VecStrideGather"
870 /*@
871    VecStrideGather - Gathers a single component from a multi-component vector into
872    another vector.
873 
874    Collective on Vec
875 
876    Input Parameter:
877 +  v - the vector
878 .  start - starting point of the subvector (defined by a stride)
879 -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
880 
881    Output Parameter:
882 .  s - the location where the subvector is stored
883 
884    Notes:
885    One must call VecSetBlockSize() before this routine to set the stride
886    information, or use a vector created from a multicomponent DA.
887 
888    If x is the array representing the vector x then this gathers
889    the array (x[start],x[start+stride],x[start+2*stride], ....)
890 
891    The parallel layout of the vector and the subvector must be the same;
892    i.e., nlocal of v = stride*(nlocal of s)
893 
894    Not optimized; could be easily
895 
896    Level: advanced
897 
898    Concepts: gather^into strided vector
899 
900 .seealso: VecStrideNorm(), VecStrideScatter(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
901           VecStrideScatterAll()
902 @*/
903 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGather(Vec v,PetscInt start,Vec s,InsertMode addv)
904 {
905   PetscErrorCode ierr;
906 
907   PetscFunctionBegin;
908   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
909   PetscValidHeaderSpecific(s,VEC_CLASSID,3);
910   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
911   if (start >= v->map->bs)  SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
912             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
913   if (!v->ops->stridegather) SETERRQ(((PetscObject)s)->comm,PETSC_ERR_SUP,"Not implemented for this Vec class");
914   ierr = (*v->ops->stridegather)(v,start,s,addv);CHKERRQ(ierr);
915   PetscFunctionReturn(0);
916 }
917 
918 #undef __FUNCT__
919 #define __FUNCT__ "VecStrideScatter"
920 /*@
921    VecStrideScatter - Scatters a single component from a vector into a multi-component vector.
922 
923    Collective on Vec
924 
925    Input Parameter:
926 +  s - the single-component vector
927 .  start - starting point of the subvector (defined by a stride)
928 -  addv - one of ADD_VALUES,INSERT_VALUES,MAX_VALUES
929 
930    Output Parameter:
931 .  v - the location where the subvector is scattered (the multi-component vector)
932 
933    Notes:
934    One must call VecSetBlockSize() on the multi-component vector before this
935    routine to set the stride  information, or use a vector created from a multicomponent DA.
936 
937    The parallel layout of the vector and the subvector must be the same;
938    i.e., nlocal of v = stride*(nlocal of s)
939 
940    Not optimized; could be easily
941 
942    Level: advanced
943 
944    Concepts: scatter^into strided vector
945 
946 .seealso: VecStrideNorm(), VecStrideGather(), VecStrideMin(), VecStrideMax(), VecStrideGatherAll(),
947           VecStrideScatterAll()
948 @*/
949 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatter(Vec s,PetscInt start,Vec v,InsertMode addv)
950 {
951   PetscErrorCode ierr;
952 
953   PetscFunctionBegin;
954   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
955   PetscValidHeaderSpecific(s,VEC_CLASSID,3);
956   if (start < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Negative start %D",start);
957   if (start >= v->map->bs)  SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Start of stride subvector (%D) is too large for stride\n\
958             Have you set the vector blocksize (%D) correctly with VecSetBlockSize()?",start,v->map->bs);
959   if (!v->ops->stridescatter) SETERRQ(((PetscObject)s)->comm,PETSC_ERR_SUP,"Not implemented for this Vec class");
960   ierr = (*v->ops->stridescatter)(s,start,v,addv);CHKERRQ(ierr);
961   PetscFunctionReturn(0);
962 }
963 
964 #undef __FUNCT__
965 #define __FUNCT__ "VecStrideGather_Default"
966 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideGather_Default(Vec v,PetscInt start,Vec s,InsertMode addv)
967 {
968   PetscErrorCode ierr;
969   PetscInt       i,n,bs,ns;
970   PetscScalar    *x,*y;
971 
972   PetscFunctionBegin;
973   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
974   ierr = VecGetLocalSize(s,&ns);CHKERRQ(ierr);
975   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
976   ierr = VecGetArray(s,&y);CHKERRQ(ierr);
977 
978   bs   = v->map->bs;
979   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);
980   x += start;
981   n =  n/bs;
982 
983   if (addv == INSERT_VALUES) {
984     for (i=0; i<n; i++) {
985       y[i] = x[bs*i];
986     }
987   } else if (addv == ADD_VALUES) {
988     for (i=0; i<n; i++) {
989       y[i] += x[bs*i];
990     }
991 #if !defined(PETSC_USE_COMPLEX)
992   } else if (addv == MAX_VALUES) {
993     for (i=0; i<n; i++) {
994       y[i] = PetscMax(y[i],x[bs*i]);
995     }
996 #endif
997   } else {
998     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
999   }
1000 
1001   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1002   ierr = VecRestoreArray(s,&y);CHKERRQ(ierr);
1003   PetscFunctionReturn(0);
1004 }
1005 
1006 #undef __FUNCT__
1007 #define __FUNCT__ "VecStrideScatter_Default"
1008 PetscErrorCode PETSCVEC_DLLEXPORT VecStrideScatter_Default(Vec s,PetscInt start,Vec v,InsertMode addv)
1009 {
1010   PetscErrorCode ierr;
1011   PetscInt       i,n,bs,ns;
1012   PetscScalar    *x,*y;
1013 
1014   PetscFunctionBegin;
1015   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1016   ierr = VecGetLocalSize(s,&ns);CHKERRQ(ierr);
1017   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1018   ierr = VecGetArray(s,&y);CHKERRQ(ierr);
1019 
1020   bs   = v->map->bs;
1021   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);
1022   x += start;
1023   n =  n/bs;
1024 
1025   if (addv == INSERT_VALUES) {
1026     for (i=0; i<n; i++) {
1027       x[bs*i] = y[i];
1028     }
1029   } else if (addv == ADD_VALUES) {
1030     for (i=0; i<n; i++) {
1031       x[bs*i] += y[i];
1032     }
1033 #if !defined(PETSC_USE_COMPLEX)
1034   } else if (addv == MAX_VALUES) {
1035     for (i=0; i<n; i++) {
1036       x[bs*i] = PetscMax(y[i],x[bs*i]);
1037     }
1038 #endif
1039   } else {
1040     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown insert type");
1041   }
1042 
1043   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1044   ierr = VecRestoreArray(s,&y);CHKERRQ(ierr);
1045   PetscFunctionReturn(0);
1046 }
1047 
1048 #undef __FUNCT__
1049 #define __FUNCT__ "VecReciprocal_Default"
1050 PetscErrorCode VecReciprocal_Default(Vec v)
1051 {
1052   PetscErrorCode ierr;
1053   PetscInt       i,n;
1054   PetscScalar    *x;
1055 
1056   PetscFunctionBegin;
1057   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1058   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1059   for (i=0; i<n; i++) {
1060     if (x[i] != 0.0) x[i] = 1.0/x[i];
1061   }
1062   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1063   PetscFunctionReturn(0);
1064 }
1065 
1066 #undef __FUNCT__
1067 #define __FUNCT__ "VecExp"
1068 /*@
1069   VecExp - Replaces each component of a vector by e^x_i
1070 
1071   Not collective
1072 
1073   Input Parameter:
1074 . v - The vector
1075 
1076   Output Parameter:
1077 . v - The vector of exponents
1078 
1079   Level: beginner
1080 
1081 .seealso:  VecLog(), VecAbs(), VecSqrtAbs(), VecReciprocal()
1082 
1083 .keywords: vector, sqrt, square root
1084 @*/
1085 PetscErrorCode PETSCVEC_DLLEXPORT VecExp(Vec v)
1086 {
1087   PetscScalar    *x;
1088   PetscInt       i, n;
1089   PetscErrorCode ierr;
1090 
1091   PetscFunctionBegin;
1092   PetscValidHeaderSpecific(v, VEC_CLASSID,1);
1093   if (v->ops->exp) {
1094     ierr = (*v->ops->exp)(v);CHKERRQ(ierr);
1095   } else {
1096     ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
1097     ierr = VecGetArray(v, &x);CHKERRQ(ierr);
1098     for(i = 0; i < n; i++) {
1099       x[i] = PetscExpScalar(x[i]);
1100     }
1101     ierr = VecRestoreArray(v, &x);CHKERRQ(ierr);
1102   }
1103   PetscFunctionReturn(0);
1104 }
1105 
1106 #undef __FUNCT__
1107 #define __FUNCT__ "VecLog"
1108 /*@
1109   VecLog - Replaces each component of a vector by log(x_i), the natural logarithm
1110 
1111   Not collective
1112 
1113   Input Parameter:
1114 . v - The vector
1115 
1116   Output Parameter:
1117 . v - The vector of logs
1118 
1119   Level: beginner
1120 
1121 .seealso:  VecExp(), VecAbs(), VecSqrtAbs(), VecReciprocal()
1122 
1123 .keywords: vector, sqrt, square root
1124 @*/
1125 PetscErrorCode PETSCVEC_DLLEXPORT VecLog(Vec v)
1126 {
1127   PetscScalar    *x;
1128   PetscInt       i, n;
1129   PetscErrorCode ierr;
1130 
1131   PetscFunctionBegin;
1132   PetscValidHeaderSpecific(v, VEC_CLASSID,1);
1133   if (v->ops->log) {
1134     ierr = (*v->ops->log)(v);CHKERRQ(ierr);
1135   } else {
1136     ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
1137     ierr = VecGetArray(v, &x);CHKERRQ(ierr);
1138     for(i = 0; i < n; i++) {
1139       x[i] = PetscLogScalar(x[i]);
1140     }
1141     ierr = VecRestoreArray(v, &x);CHKERRQ(ierr);
1142   }
1143   PetscFunctionReturn(0);
1144 }
1145 
1146 #undef __FUNCT__
1147 #define __FUNCT__ "VecSqrtAbs"
1148 /*@
1149   VecSqrtAbs - Replaces each component of a vector by the square root of its magnitude.
1150 
1151   Not collective
1152 
1153   Input Parameter:
1154 . v - The vector
1155 
1156   Output Parameter:
1157 . v - The vector square root
1158 
1159   Level: beginner
1160 
1161   Note: The actual function is sqrt(|x_i|)
1162 
1163 .seealso: VecLog(), VecExp(), VecReciprocal(), VecAbs()
1164 
1165 .keywords: vector, sqrt, square root
1166 @*/
1167 PetscErrorCode PETSCVEC_DLLEXPORT VecSqrtAbs(Vec v)
1168 {
1169   PetscScalar    *x;
1170   PetscInt       i, n;
1171   PetscErrorCode ierr;
1172 
1173   PetscFunctionBegin;
1174   PetscValidHeaderSpecific(v, VEC_CLASSID,1);
1175   if (v->ops->sqrt) {
1176     ierr = (*v->ops->sqrt)(v);CHKERRQ(ierr);
1177   } else {
1178     ierr = VecGetLocalSize(v, &n);CHKERRQ(ierr);
1179     ierr = VecGetArray(v, &x);CHKERRQ(ierr);
1180     for(i = 0; i < n; i++) {
1181       x[i] = sqrt(PetscAbsScalar(x[i]));
1182     }
1183     ierr = VecRestoreArray(v, &x);CHKERRQ(ierr);
1184   }
1185   PetscFunctionReturn(0);
1186 }
1187 
1188 #undef __FUNCT__
1189 #define __FUNCT__ "VecDotNorm2"
1190 /*@
1191   VecDotNorm2 - computes the inner product of two vectors and the 2-norm squared of the second vector
1192 
1193   Collective on Vec
1194 
1195   Input Parameter:
1196 + s - first vector
1197 - t - second vector
1198 
1199   Output Parameter:
1200 + dp - s't
1201 - nm - t't
1202 
1203   Level: advanced
1204 
1205 .seealso:   VecDot(), VecNorm(), VecDotBegin(), VecNormBegin(), VecDotEnd(), VecNormEnd()
1206 
1207 .keywords: vector, sqrt, square root
1208 @*/
1209 PetscErrorCode PETSCVEC_DLLEXPORT VecDotNorm2(Vec s,Vec t,PetscScalar *dp, PetscScalar *nm)
1210 {
1211   PetscScalar    *sx, *tx, dpx = 0.0, nmx = 0.0,work[2],sum[2];
1212   PetscInt       i, n;
1213   PetscErrorCode ierr;
1214 
1215   PetscFunctionBegin;
1216   PetscValidHeaderSpecific(s, VEC_CLASSID,1);
1217   PetscValidHeaderSpecific(t, VEC_CLASSID,2);
1218   PetscValidScalarPointer(dp,3);
1219   PetscValidScalarPointer(nm,4);
1220   PetscValidType(s,1);
1221   PetscValidType(t,2);
1222   PetscCheckSameTypeAndComm(s,1,t,2);
1223   if (s->map->N != t->map->N) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector global lengths");
1224   if (s->map->n != t->map->n) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Incompatible vector local lengths");
1225 
1226   ierr = PetscLogEventBarrierBegin(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);CHKERRQ(ierr);
1227   if (s->ops->dotnorm2) {
1228     ierr = (*s->ops->dotnorm2)(s,t,dp,nm);CHKERRQ(ierr);
1229   } else {
1230     ierr = VecGetLocalSize(s, &n);CHKERRQ(ierr);
1231     ierr = VecGetArray(s, &sx);CHKERRQ(ierr);
1232     ierr = VecGetArray(t, &tx);CHKERRQ(ierr);
1233 
1234     for (i = 0; i<n; i++) {
1235       dpx += sx[i]*PetscConj(tx[i]);
1236       nmx += tx[i]*PetscConj(tx[i]);
1237     }
1238     work[0] = dpx;
1239     work[1] = nmx;
1240     ierr = MPI_Allreduce(&work,&sum,2,MPIU_SCALAR,MPIU_SUM,((PetscObject)s)->comm);CHKERRQ(ierr);
1241     *dp  = sum[0];
1242     *nm  = sum[1];
1243 
1244     ierr = VecRestoreArray(t, &tx);CHKERRQ(ierr);
1245     ierr = VecRestoreArray(s, &sx);CHKERRQ(ierr);
1246     ierr = PetscLogFlops(4.0*n);CHKERRQ(ierr);
1247   }
1248   ierr = PetscLogEventBarrierEnd(VEC_DotNormBarrier,s,t,0,0,((PetscObject)s)->comm);CHKERRQ(ierr);
1249   PetscFunctionReturn(0);
1250 }
1251 
1252 #undef __FUNCT__
1253 #define __FUNCT__ "VecSum"
1254 /*@
1255    VecSum - Computes the sum of all the components of a vector.
1256 
1257    Collective on Vec
1258 
1259    Input Parameter:
1260 .  v - the vector
1261 
1262    Output Parameter:
1263 .  sum - the result
1264 
1265    Level: beginner
1266 
1267    Concepts: sum^of vector entries
1268 
1269 .seealso: VecNorm()
1270 @*/
1271 PetscErrorCode PETSCVEC_DLLEXPORT VecSum(Vec v,PetscScalar *sum)
1272 {
1273   PetscErrorCode ierr;
1274   PetscInt       i,n;
1275   PetscScalar    *x,lsum = 0.0;
1276 
1277   PetscFunctionBegin;
1278   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1279   PetscValidScalarPointer(sum,2);
1280   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1281   ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1282   for (i=0; i<n; i++) {
1283     lsum += x[i];
1284   }
1285   ierr = MPI_Allreduce(&lsum,sum,1,MPIU_SCALAR,MPIU_SUM,((PetscObject)v)->comm);CHKERRQ(ierr);
1286   ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1287   PetscFunctionReturn(0);
1288 }
1289 
1290 #undef __FUNCT__
1291 #define __FUNCT__ "VecShift"
1292 /*@
1293    VecShift - Shifts all of the components of a vector by computing
1294    x[i] = x[i] + shift.
1295 
1296    Logically Collective on Vec
1297 
1298    Input Parameters:
1299 +  v - the vector
1300 -  shift - the shift
1301 
1302    Output Parameter:
1303 .  v - the shifted vector
1304 
1305    Level: intermediate
1306 
1307    Concepts: vector^adding constant
1308 
1309 @*/
1310 PetscErrorCode PETSCVEC_DLLEXPORT VecShift(Vec v,PetscScalar shift)
1311 {
1312   PetscErrorCode ierr;
1313   PetscInt       i,n;
1314   PetscScalar    *x;
1315 
1316   PetscFunctionBegin;
1317   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1318   PetscValidLogicalCollectiveScalar(v,shift,2);
1319   if (v->ops->shift) {
1320     ierr = (*v->ops->shift)(v);CHKERRQ(ierr);
1321   } else {
1322     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1323     ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1324     for (i=0; i<n; i++) {
1325       x[i] += shift;
1326     }
1327     ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1328   }
1329   PetscFunctionReturn(0);
1330 }
1331 
1332 #undef __FUNCT__
1333 #define __FUNCT__ "VecAbs"
1334 /*@
1335    VecAbs - Replaces every element in a vector with its absolute value.
1336 
1337    Logically Collective on Vec
1338 
1339    Input Parameters:
1340 .  v - the vector
1341 
1342    Level: intermediate
1343 
1344    Concepts: vector^absolute value
1345 
1346 @*/
1347 PetscErrorCode PETSCVEC_DLLEXPORT VecAbs(Vec v)
1348 {
1349   PetscErrorCode ierr;
1350   PetscInt       i,n;
1351   PetscScalar    *x;
1352 
1353   PetscFunctionBegin;
1354   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1355   if (v->ops->abs) {
1356     ierr = (*v->ops->abs)(v);CHKERRQ(ierr);
1357   } else {
1358     ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1359     ierr = VecGetArray(v,&x);CHKERRQ(ierr);
1360     for (i=0; i<n; i++) {
1361       x[i] = PetscAbsScalar(x[i]);
1362     }
1363     ierr = VecRestoreArray(v,&x);CHKERRQ(ierr);
1364   }
1365   PetscFunctionReturn(0);
1366 }
1367 
1368 #undef __FUNCT__
1369 #define __FUNCT__ "VecPermute"
1370 /*@
1371   VecPermute - Permutes a vector in place using the given ordering.
1372 
1373   Input Parameters:
1374 + vec   - The vector
1375 . order - The ordering
1376 - inv   - The flag for inverting the permutation
1377 
1378   Level: beginner
1379 
1380   Note: This function does not yet support parallel Index Sets
1381 
1382 .seealso: MatPermute()
1383 .keywords: vec, permute
1384 @*/
1385 PetscErrorCode PETSCVEC_DLLEXPORT VecPermute(Vec x, IS row, PetscTruth inv)
1386 {
1387   PetscScalar    *array, *newArray;
1388   const PetscInt *idx;
1389   PetscInt       i;
1390   PetscErrorCode ierr;
1391 
1392   PetscFunctionBegin;
1393   ierr = ISGetIndices(row, &idx);CHKERRQ(ierr);
1394   ierr = VecGetArray(x, &array);CHKERRQ(ierr);
1395   ierr = PetscMalloc(x->map->n*sizeof(PetscScalar), &newArray);CHKERRQ(ierr);
1396 #ifdef PETSC_USE_DEBUG
1397   for(i = 0; i < x->map->n; i++) {
1398     if ((idx[i] < 0) || (idx[i] >= x->map->n)) {
1399       SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_CORRUPT, "Permutation index %D is out of bounds: %D", i, idx[i]);
1400     }
1401   }
1402 #endif
1403   if (!inv) {
1404     for(i = 0; i < x->map->n; i++) newArray[i]      = array[idx[i]];
1405   } else {
1406     for(i = 0; i < x->map->n; i++) newArray[idx[i]] = array[i];
1407   }
1408   ierr = VecRestoreArray(x, &array);CHKERRQ(ierr);
1409   ierr = ISRestoreIndices(row, &idx);CHKERRQ(ierr);
1410   ierr = VecReplaceArray(x, newArray);CHKERRQ(ierr);
1411   PetscFunctionReturn(0);
1412 }
1413 
1414 #undef __FUNCT__
1415 #define __FUNCT__ "VecEqual"
1416 /*@
1417    VecEqual - Compares two vectors.
1418 
1419    Collective on Vec
1420 
1421    Input Parameters:
1422 +  vec1 - the first vector
1423 -  vec2 - the second vector
1424 
1425    Output Parameter:
1426 .  flg - PETSC_TRUE if the vectors are equal; PETSC_FALSE otherwise.
1427 
1428    Level: intermediate
1429 
1430    Concepts: equal^two vectors
1431    Concepts: vector^equality
1432 
1433 @*/
1434 PetscErrorCode PETSCVEC_DLLEXPORT VecEqual(Vec vec1,Vec vec2,PetscTruth *flg)
1435 {
1436   PetscScalar    *v1,*v2;
1437   PetscErrorCode ierr;
1438   PetscInt       n1,n2,N1,N2;
1439   PetscInt       state1,state2;
1440   PetscTruth     flg1;
1441 
1442   PetscFunctionBegin;
1443   PetscValidHeaderSpecific(vec1,VEC_CLASSID,1);
1444   PetscValidHeaderSpecific(vec2,VEC_CLASSID,2);
1445   PetscValidPointer(flg,3);
1446   if (vec1 == vec2) {
1447     *flg = PETSC_TRUE;
1448   } else {
1449     ierr = VecGetSize(vec1,&N1);CHKERRQ(ierr);
1450     ierr = VecGetSize(vec2,&N2);CHKERRQ(ierr);
1451     if (N1 != N2) {
1452       flg1 = PETSC_FALSE;
1453     } else {
1454       ierr = VecGetLocalSize(vec1,&n1);CHKERRQ(ierr);
1455       ierr = VecGetLocalSize(vec2,&n2);CHKERRQ(ierr);
1456       if (n1 != n2) {
1457         flg1 = PETSC_FALSE;
1458       } else {
1459         ierr = PetscObjectStateQuery((PetscObject) vec1,&state1);CHKERRQ(ierr);
1460         ierr = PetscObjectStateQuery((PetscObject) vec2,&state2);CHKERRQ(ierr);
1461         ierr = VecGetArray(vec1,&v1);CHKERRQ(ierr);
1462         ierr = VecGetArray(vec2,&v2);CHKERRQ(ierr);
1463 #if defined(PETSC_USE_COMPLEX)
1464         PetscInt k;
1465         for (k=0; k<n1; k++){
1466           if (PetscRealPart(v1[k]) != PetscRealPart(v2[k]) || PetscImaginaryPart(v1[k]) != PetscImaginaryPart(v2[k])){
1467             flg1 = PETSC_FALSE;
1468             break;
1469           }
1470         }
1471 #else
1472         ierr = PetscMemcmp(v1,v2,n1*sizeof(PetscScalar),&flg1);CHKERRQ(ierr);
1473 #endif
1474         ierr = VecRestoreArray(vec1,&v1);CHKERRQ(ierr);
1475         ierr = VecRestoreArray(vec2,&v2);CHKERRQ(ierr);
1476         ierr = PetscObjectSetState((PetscObject) vec1,state1);CHKERRQ(ierr);
1477         ierr = PetscObjectSetState((PetscObject) vec2,state2);CHKERRQ(ierr);
1478       }
1479     }
1480     /* combine results from all processors */
1481     ierr = MPI_Allreduce(&flg1,flg,1,MPI_INT,MPI_MIN,((PetscObject)vec1)->comm);CHKERRQ(ierr);
1482   }
1483   PetscFunctionReturn(0);
1484 }
1485 
1486 
1487 
1488