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