1 /*
2      Provides the interface functions for vector operations that have PetscScalar/PetscReal in the signature
3    These are the vector functions the user calls.
4 */
5 #include "petsc/private/sfimpl.h"
6 #include <petsc/private/vecimpl.h>       /*I  "petscvec.h"   I*/
7 #if defined(PETSC_HAVE_CUDA)
8 #include <../src/vec/vec/impls/dvecimpl.h>
9 #include <petsc/private/cudavecimpl.h>
10 #endif
11 static PetscInt VecGetSubVectorSavedStateId = -1;
12 
VecValidValues(Vec vec,PetscInt argnum,PetscBool begin)13 PETSC_EXTERN PetscErrorCode VecValidValues(Vec vec,PetscInt argnum,PetscBool begin)
14 {
15 #if defined(PETSC_USE_DEBUG)
16   PetscErrorCode    ierr;
17   PetscInt          n,i;
18   const PetscScalar *x;
19 
20   PetscFunctionBegin;
21 #if defined(PETSC_HAVE_CUDA) || defined(PETSC_HAVE_VIENNACL)
22   if ((vec->petscnative || vec->ops->getarray) && (vec->offloadmask & PETSC_OFFLOAD_CPU)) {
23 #else
24   if (vec->petscnative || vec->ops->getarray) {
25 #endif
26     ierr = VecGetLocalSize(vec,&n);CHKERRQ(ierr);
27     ierr = VecGetArrayRead(vec,&x);CHKERRQ(ierr);
28     for (i=0; i<n; i++) {
29       if (begin) {
30         if (PetscIsInfOrNanScalar(x[i])) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FP,"Vec entry at local location %D is not-a-number or infinite at beginning of function: Parameter number %D",i,argnum);
31       } else {
32         if (PetscIsInfOrNanScalar(x[i])) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_FP,"Vec entry at local location %D is not-a-number or infinite at end of function: Parameter number %D",i,argnum);
33       }
34     }
35     ierr = VecRestoreArrayRead(vec,&x);CHKERRQ(ierr);
36   }
37 #else
38   PetscFunctionBegin;
39 #endif
40   PetscFunctionReturn(0);
41 }
42 
43 /*@
44    VecMaxPointwiseDivide - Computes the maximum of the componentwise division max = max_i abs(x_i/y_i).
45 
46    Logically Collective on Vec
47 
48    Input Parameters:
49 .  x, y  - the vectors
50 
51    Output Parameter:
52 .  max - the result
53 
54    Level: advanced
55 
56    Notes:
57     x and y may be the same vector
58           if a particular y_i is zero, it is treated as 1 in the above formula
59 
60 .seealso: VecPointwiseDivide(), VecPointwiseMult(), VecPointwiseMax(), VecPointwiseMin(), VecPointwiseMaxAbs()
61 @*/
62 PetscErrorCode  VecMaxPointwiseDivide(Vec x,Vec y,PetscReal *max)
63 {
64   PetscErrorCode ierr;
65 
66   PetscFunctionBegin;
67   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
68   PetscValidHeaderSpecific(y,VEC_CLASSID,2);
69   PetscValidRealPointer(max,3);
70   PetscValidType(x,1);
71   PetscValidType(y,2);
72   PetscCheckSameTypeAndComm(x,1,y,2);
73   VecCheckSameSize(x,1,y,2);
74   ierr = (*x->ops->maxpointwisedivide)(x,y,max);CHKERRQ(ierr);
75   PetscFunctionReturn(0);
76 }
77 
78 /*@
79    VecDot - Computes the vector dot product.
80 
81    Collective on Vec
82 
83    Input Parameters:
84 .  x, y - the vectors
85 
86    Output Parameter:
87 .  val - the dot product
88 
89    Performance Issues:
90 $    per-processor memory bandwidth
91 $    interprocessor latency
92 $    work load inbalance that causes certain processes to arrive much earlier than others
93 
94    Notes for Users of Complex Numbers:
95    For complex vectors, VecDot() computes
96 $     val = (x,y) = y^H x,
97    where y^H denotes the conjugate transpose of y. Note that this corresponds to the usual "mathematicians" complex
98    inner product where the SECOND argument gets the complex conjugate. Since the BLASdot() complex conjugates the first
99    first argument we call the BLASdot() with the arguments reversed.
100 
101    Use VecTDot() for the indefinite form
102 $     val = (x,y) = y^T x,
103    where y^T denotes the transpose of y.
104 
105    Level: intermediate
106 
107 
108 .seealso: VecMDot(), VecTDot(), VecNorm(), VecDotBegin(), VecDotEnd(), VecDotRealPart()
109 @*/
110 PetscErrorCode  VecDot(Vec x,Vec y,PetscScalar *val)
111 {
112   PetscErrorCode ierr;
113 
114   PetscFunctionBegin;
115   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
116   PetscValidHeaderSpecific(y,VEC_CLASSID,2);
117   PetscValidScalarPointer(val,3);
118   PetscValidType(x,1);
119   PetscValidType(y,2);
120   PetscCheckSameTypeAndComm(x,1,y,2);
121   VecCheckSameSize(x,1,y,2);
122 
123   ierr = PetscLogEventBegin(VEC_Dot,x,y,0,0);CHKERRQ(ierr);
124   ierr = (*x->ops->dot)(x,y,val);CHKERRQ(ierr);
125   ierr = PetscLogEventEnd(VEC_Dot,x,y,0,0);CHKERRQ(ierr);
126   PetscFunctionReturn(0);
127 }
128 
129 /*@
130    VecDotRealPart - Computes the real part of the vector dot product.
131 
132    Collective on Vec
133 
134    Input Parameters:
135 .  x, y - the vectors
136 
137    Output Parameter:
138 .  val - the real part of the dot product;
139 
140    Performance Issues:
141 $    per-processor memory bandwidth
142 $    interprocessor latency
143 $    work load inbalance that causes certain processes to arrive much earlier than others
144 
145    Notes for Users of Complex Numbers:
146      See VecDot() for more details on the definition of the dot product for complex numbers
147 
148      For real numbers this returns the same value as VecDot()
149 
150      For complex numbers in C^n (that is a vector of n components with a complex number for each component) this is equal to the usual real dot product on the
151      the space R^{2n} (that is a vector of 2n components with the real or imaginary part of the complex numbers for components)
152 
153    Developer Note: This is not currently optimized to compute only the real part of the dot product.
154 
155    Level: intermediate
156 
157 
158 .seealso: VecMDot(), VecTDot(), VecNorm(), VecDotBegin(), VecDotEnd(), VecDot(), VecDotNorm2()
159 @*/
160 PetscErrorCode  VecDotRealPart(Vec x,Vec y,PetscReal *val)
161 {
162   PetscErrorCode ierr;
163   PetscScalar    fdot;
164 
165   PetscFunctionBegin;
166   ierr = VecDot(x,y,&fdot);CHKERRQ(ierr);
167   *val = PetscRealPart(fdot);
168   PetscFunctionReturn(0);
169 }
170 
171 /*@
172    VecNorm  - Computes the vector norm.
173 
174    Collective on Vec
175 
176    Input Parameters:
177 +  x - the vector
178 -  type - one of NORM_1, NORM_2, NORM_INFINITY.  Also available
179           NORM_1_AND_2, which computes both norms and stores them
180           in a two element array.
181 
182    Output Parameter:
183 .  val - the norm
184 
185    Notes:
186 $     NORM_1 denotes sum_i |x_i|
187 $     NORM_2 denotes sqrt(sum_i |x_i|^2)
188 $     NORM_INFINITY denotes max_i |x_i|
189 
190       For complex numbers NORM_1 will return the traditional 1 norm of the 2 norm of the complex numbers; that is the 1
191       norm of the absolutely values of the complex entries. In PETSc 3.6 and earlier releases it returned the 1 norm of
192       the 1 norm of the complex entries (what is returned by the BLAS routine asum()). Both are valid norms but most
193       people expect the former.
194 
195    Level: intermediate
196 
197    Performance Issues:
198 $    per-processor memory bandwidth
199 $    interprocessor latency
200 $    work load inbalance that causes certain processes to arrive much earlier than others
201 
202 
203 .seealso: VecDot(), VecTDot(), VecNorm(), VecDotBegin(), VecDotEnd(), VecNormAvailable(),
204           VecNormBegin(), VecNormEnd()
205 
206 @*/
207 
208 PetscErrorCode  VecNorm(Vec x,NormType type,PetscReal *val)
209 {
210   PetscBool      flg;
211   PetscErrorCode ierr;
212 
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
215   PetscValidRealPointer(val,3);
216   PetscValidType(x,1);
217 
218   /*
219    * Cached data?
220    */
221   if (type!=NORM_1_AND_2) {
222     ierr = PetscObjectComposedDataGetReal((PetscObject)x,NormIds[type],*val,flg);CHKERRQ(ierr);
223     if (flg) PetscFunctionReturn(0);
224   }
225   ierr = PetscLogEventBegin(VEC_Norm,x,0,0,0);CHKERRQ(ierr);
226   ierr = (*x->ops->norm)(x,type,val);CHKERRQ(ierr);
227   ierr = PetscLogEventEnd(VEC_Norm,x,0,0,0);CHKERRQ(ierr);
228   if (type!=NORM_1_AND_2) {
229     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[type],*val);CHKERRQ(ierr);
230   }
231   PetscFunctionReturn(0);
232 }
233 
234 /*@
235    VecNormAvailable  - Returns the vector norm if it is already known.
236 
237    Not Collective
238 
239    Input Parameters:
240 +  x - the vector
241 -  type - one of NORM_1, NORM_2, NORM_INFINITY.  Also available
242           NORM_1_AND_2, which computes both norms and stores them
243           in a two element array.
244 
245    Output Parameter:
246 +  available - PETSC_TRUE if the val returned is valid
247 -  val - the norm
248 
249    Notes:
250 $     NORM_1 denotes sum_i |x_i|
251 $     NORM_2 denotes sqrt(sum_i (x_i)^2)
252 $     NORM_INFINITY denotes max_i |x_i|
253 
254    Level: intermediate
255 
256    Performance Issues:
257 $    per-processor memory bandwidth
258 $    interprocessor latency
259 $    work load inbalance that causes certain processes to arrive much earlier than others
260 
261    Compile Option:
262    PETSC_HAVE_SLOW_BLAS_NORM2 will cause a C (loop unrolled) version of the norm to be used, rather
263  than the BLAS. This should probably only be used when one is using the FORTRAN BLAS routines
264  (as opposed to vendor provided) because the FORTRAN BLAS NRM2() routine is very slow.
265 
266 
267 .seealso: VecDot(), VecTDot(), VecNorm(), VecDotBegin(), VecDotEnd(), VecNorm()
268           VecNormBegin(), VecNormEnd()
269 
270 @*/
271 PetscErrorCode  VecNormAvailable(Vec x,NormType type,PetscBool  *available,PetscReal *val)
272 {
273   PetscErrorCode ierr;
274 
275   PetscFunctionBegin;
276   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
277   PetscValidRealPointer(val,3);
278   PetscValidType(x,1);
279 
280   *available = PETSC_FALSE;
281   if (type!=NORM_1_AND_2) {
282     ierr = PetscObjectComposedDataGetReal((PetscObject)x,NormIds[type],*val,*available);CHKERRQ(ierr);
283   }
284   PetscFunctionReturn(0);
285 }
286 
287 /*@
288    VecNormalize - Normalizes a vector by 2-norm.
289 
290    Collective on Vec
291 
292    Input Parameters:
293 +  x - the vector
294 
295    Output Parameter:
296 .  x - the normalized vector
297 -  val - the vector norm before normalization
298 
299    Level: intermediate
300 
301 
302 @*/
303 PetscErrorCode  VecNormalize(Vec x,PetscReal *val)
304 {
305   PetscErrorCode ierr;
306   PetscReal      norm;
307 
308   PetscFunctionBegin;
309   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
310   PetscValidType(x,1);
311   ierr = PetscLogEventBegin(VEC_Normalize,x,0,0,0);CHKERRQ(ierr);
312   ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr);
313   if (norm == 0.0) {
314     ierr = PetscInfo(x,"Vector of zero norm can not be normalized; Returning only the zero norm\n");CHKERRQ(ierr);
315   } else if (norm != 1.0) {
316     PetscScalar tmp = 1.0/norm;
317     ierr = VecScale(x,tmp);CHKERRQ(ierr);
318   }
319   if (val) *val = norm;
320   ierr = PetscLogEventEnd(VEC_Normalize,x,0,0,0);CHKERRQ(ierr);
321   PetscFunctionReturn(0);
322 }
323 
324 /*@C
325    VecMax - Determines the vector component with maximum real part and its location.
326 
327    Collective on Vec
328 
329    Input Parameter:
330 .  x - the vector
331 
332    Output Parameters:
333 +  p - the location of val (pass NULL if you don't want this)
334 -  val - the maximum component
335 
336    Notes:
337    Returns the value PETSC_MIN_REAL and p = -1 if the vector is of length 0.
338 
339    Returns the smallest index with the maximum value
340    Level: intermediate
341 
342 
343 .seealso: VecNorm(), VecMin()
344 @*/
345 PetscErrorCode  VecMax(Vec x,PetscInt *p,PetscReal *val)
346 {
347   PetscErrorCode ierr;
348 
349   PetscFunctionBegin;
350   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
351   PetscValidScalarPointer(val,3);
352   PetscValidType(x,1);
353   ierr = PetscLogEventBegin(VEC_Max,x,0,0,0);CHKERRQ(ierr);
354   ierr = (*x->ops->max)(x,p,val);CHKERRQ(ierr);
355   ierr = PetscLogEventEnd(VEC_Max,x,0,0,0);CHKERRQ(ierr);
356   PetscFunctionReturn(0);
357 }
358 
359 /*@C
360    VecMin - Determines the vector component with minimum real part and its location.
361 
362    Collective on Vec
363 
364    Input Parameters:
365 .  x - the vector
366 
367    Output Parameter:
368 +  p - the location of val (pass NULL if you don't want this location)
369 -  val - the minimum component
370 
371    Level: intermediate
372 
373    Notes:
374    Returns the value PETSC_MAX_REAL and p = -1 if the vector is of length 0.
375 
376    This returns the smallest index with the minumum value
377 
378 
379 .seealso: VecMax()
380 @*/
381 PetscErrorCode  VecMin(Vec x,PetscInt *p,PetscReal *val)
382 {
383   PetscErrorCode ierr;
384 
385   PetscFunctionBegin;
386   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
387   PetscValidScalarPointer(val,3);
388   PetscValidType(x,1);
389   ierr = PetscLogEventBegin(VEC_Min,x,0,0,0);CHKERRQ(ierr);
390   ierr = (*x->ops->min)(x,p,val);CHKERRQ(ierr);
391   ierr = PetscLogEventEnd(VEC_Min,x,0,0,0);CHKERRQ(ierr);
392   PetscFunctionReturn(0);
393 }
394 
395 /*@
396    VecTDot - Computes an indefinite vector dot product. That is, this
397    routine does NOT use the complex conjugate.
398 
399    Collective on Vec
400 
401    Input Parameters:
402 .  x, y - the vectors
403 
404    Output Parameter:
405 .  val - the dot product
406 
407    Notes for Users of Complex Numbers:
408    For complex vectors, VecTDot() computes the indefinite form
409 $     val = (x,y) = y^T x,
410    where y^T denotes the transpose of y.
411 
412    Use VecDot() for the inner product
413 $     val = (x,y) = y^H x,
414    where y^H denotes the conjugate transpose of y.
415 
416    Level: intermediate
417 
418 .seealso: VecDot(), VecMTDot()
419 @*/
420 PetscErrorCode  VecTDot(Vec x,Vec y,PetscScalar *val)
421 {
422   PetscErrorCode ierr;
423 
424   PetscFunctionBegin;
425   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
426   PetscValidHeaderSpecific(y,VEC_CLASSID,2);
427   PetscValidScalarPointer(val,3);
428   PetscValidType(x,1);
429   PetscValidType(y,2);
430   PetscCheckSameTypeAndComm(x,1,y,2);
431   VecCheckSameSize(x,1,y,2);
432 
433   ierr = PetscLogEventBegin(VEC_TDot,x,y,0,0);CHKERRQ(ierr);
434   ierr = (*x->ops->tdot)(x,y,val);CHKERRQ(ierr);
435   ierr = PetscLogEventEnd(VEC_TDot,x,y,0,0);CHKERRQ(ierr);
436   PetscFunctionReturn(0);
437 }
438 
439 /*@
440    VecScale - Scales a vector.
441 
442    Not collective on Vec
443 
444    Input Parameters:
445 +  x - the vector
446 -  alpha - the scalar
447 
448    Output Parameter:
449 .  x - the scaled vector
450 
451    Note:
452    For a vector with n components, VecScale() computes
453 $      x[i] = alpha * x[i], for i=1,...,n.
454 
455    Level: intermediate
456 
457 
458 @*/
459 PetscErrorCode  VecScale(Vec x, PetscScalar alpha)
460 {
461   PetscReal      norms[4] = {0.0,0.0,0.0, 0.0};
462   PetscBool      flgs[4];
463   PetscErrorCode ierr;
464   PetscInt       i;
465 
466   PetscFunctionBegin;
467   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
468   PetscValidType(x,1);
469   if (x->stash.insertmode != NOT_SET_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled vector");
470   ierr = PetscLogEventBegin(VEC_Scale,x,0,0,0);CHKERRQ(ierr);
471   if (alpha != (PetscScalar)1.0) {
472     ierr = VecSetErrorIfLocked(x,1);CHKERRQ(ierr);
473     /* get current stashed norms */
474     for (i=0; i<4; i++) {
475       ierr = PetscObjectComposedDataGetReal((PetscObject)x,NormIds[i],norms[i],flgs[i]);CHKERRQ(ierr);
476     }
477     ierr = (*x->ops->scale)(x,alpha);CHKERRQ(ierr);
478     ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
479     /* put the scaled stashed norms back into the Vec */
480     for (i=0; i<4; i++) {
481       if (flgs[i]) {
482         ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[i],PetscAbsScalar(alpha)*norms[i]);CHKERRQ(ierr);
483       }
484     }
485   }
486   ierr = PetscLogEventEnd(VEC_Scale,x,0,0,0);CHKERRQ(ierr);
487   PetscFunctionReturn(0);
488 }
489 
490 /*@
491    VecSet - Sets all components of a vector to a single scalar value.
492 
493    Logically Collective on Vec
494 
495    Input Parameters:
496 +  x  - the vector
497 -  alpha - the scalar
498 
499    Output Parameter:
500 .  x  - the vector
501 
502    Note:
503    For a vector of dimension n, VecSet() computes
504 $     x[i] = alpha, for i=1,...,n,
505    so that all vector entries then equal the identical
506    scalar value, alpha.  Use the more general routine
507    VecSetValues() to set different vector entries.
508 
509    You CANNOT call this after you have called VecSetValues() but before you call
510    VecAssemblyBegin/End().
511 
512    Level: beginner
513 
514 .seealso VecSetValues(), VecSetValuesBlocked(), VecSetRandom()
515 
516 @*/
517 PetscErrorCode  VecSet(Vec x,PetscScalar alpha)
518 {
519   PetscReal      val;
520   PetscErrorCode ierr;
521 
522   PetscFunctionBegin;
523   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
524   PetscValidType(x,1);
525   if (x->stash.insertmode != NOT_SET_VALUES) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"You cannot call this after you have called VecSetValues() but\n before you have called VecAssemblyBegin/End()");
526   PetscValidLogicalCollectiveScalar(x,alpha,2);
527   ierr = VecSetErrorIfLocked(x,1);CHKERRQ(ierr);
528 
529   ierr = PetscLogEventBegin(VEC_Set,x,0,0,0);CHKERRQ(ierr);
530   ierr = (*x->ops->set)(x,alpha);CHKERRQ(ierr);
531   ierr = PetscLogEventEnd(VEC_Set,x,0,0,0);CHKERRQ(ierr);
532   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
533 
534   /*  norms can be simply set (if |alpha|*N not too large) */
535   val  = PetscAbsScalar(alpha);
536   if (x->map->N == 0) {
537     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_1],0.0l);CHKERRQ(ierr);
538     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_INFINITY],0.0);CHKERRQ(ierr);
539     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_2],0.0);CHKERRQ(ierr);
540     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_FROBENIUS],0.0);CHKERRQ(ierr);
541   } else if (val > PETSC_MAX_REAL/x->map->N) {
542     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_INFINITY],val);CHKERRQ(ierr);
543   } else {
544     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_1],x->map->N * val);CHKERRQ(ierr);
545     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_INFINITY],val);CHKERRQ(ierr);
546     val  = PetscSqrtReal((PetscReal)x->map->N) * val;
547     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_2],val);CHKERRQ(ierr);
548     ierr = PetscObjectComposedDataSetReal((PetscObject)x,NormIds[NORM_FROBENIUS],val);CHKERRQ(ierr);
549   }
550   PetscFunctionReturn(0);
551 }
552 
553 
554 /*@
555    VecAXPY - Computes y = alpha x + y.
556 
557    Logically Collective on Vec
558 
559    Input Parameters:
560 +  alpha - the scalar
561 -  x, y  - the vectors
562 
563    Output Parameter:
564 .  y - output vector
565 
566    Level: intermediate
567 
568    Notes:
569     x and y MUST be different vectors
570     This routine is optimized for alpha of 0.0, otherwise it calls the BLAS routine
571 
572 $    VecAXPY(y,alpha,x)                   y = alpha x           +      y
573 $    VecAYPX(y,beta,x)                    y =       x           + beta y
574 $    VecAXPBY(y,alpha,beta,x)             y = alpha x           + beta y
575 $    VecWAXPY(w,alpha,x,y)                w = alpha x           +      y
576 $    VecAXPBYPCZ(w,alpha,beta,gamma,x,y)  z = alpha x           + beta y + gamma z
577 $    VecMAXPY(y,nv,alpha[],x[])           y = sum alpha[i] x[i] +      y
578 
579 
580 .seealso:  VecAYPX(), VecMAXPY(), VecWAXPY(), VecAXPBYPCZ(), VecAXPBY()
581 @*/
582 PetscErrorCode  VecAXPY(Vec y,PetscScalar alpha,Vec x)
583 {
584   PetscErrorCode ierr;
585 
586   PetscFunctionBegin;
587   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
588   PetscValidHeaderSpecific(y,VEC_CLASSID,1);
589   PetscValidType(x,3);
590   PetscValidType(y,1);
591   PetscCheckSameTypeAndComm(x,3,y,1);
592   VecCheckSameSize(x,1,y,3);
593   if (x == y) SETERRQ(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_IDN,"x and y cannot be the same vector");
594   PetscValidLogicalCollectiveScalar(y,alpha,2);
595   if (alpha == (PetscScalar)0.0) PetscFunctionReturn(0);
596   ierr = VecSetErrorIfLocked(y,1);CHKERRQ(ierr);
597 
598   ierr = VecLockReadPush(x);CHKERRQ(ierr);
599   ierr = PetscLogEventBegin(VEC_AXPY,x,y,0,0);CHKERRQ(ierr);
600   ierr = (*y->ops->axpy)(y,alpha,x);CHKERRQ(ierr);
601   ierr = PetscLogEventEnd(VEC_AXPY,x,y,0,0);CHKERRQ(ierr);
602   ierr = VecLockReadPop(x);CHKERRQ(ierr);
603   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
604   PetscFunctionReturn(0);
605 }
606 
607 /*@
608    VecAXPBY - Computes y = alpha x + beta y.
609 
610    Logically Collective on Vec
611 
612    Input Parameters:
613 +  alpha,beta - the scalars
614 -  x, y  - the vectors
615 
616    Output Parameter:
617 .  y - output vector
618 
619    Level: intermediate
620 
621    Notes:
622     x and y MUST be different vectors
623     The implementation is optimized for alpha and/or beta values of 0.0 and 1.0
624 
625 
626 .seealso: VecAYPX(), VecMAXPY(), VecWAXPY(), VecAXPY(), VecAXPBYPCZ()
627 @*/
628 PetscErrorCode  VecAXPBY(Vec y,PetscScalar alpha,PetscScalar beta,Vec x)
629 {
630   PetscErrorCode ierr;
631 
632   PetscFunctionBegin;
633   PetscValidHeaderSpecific(x,VEC_CLASSID,4);
634   PetscValidHeaderSpecific(y,VEC_CLASSID,1);
635   PetscValidType(x,4);
636   PetscValidType(y,1);
637   PetscCheckSameTypeAndComm(x,4,y,1);
638   VecCheckSameSize(y,1,x,4);
639   if (x == y) SETERRQ(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_IDN,"x and y cannot be the same vector");
640   PetscValidLogicalCollectiveScalar(y,alpha,2);
641   PetscValidLogicalCollectiveScalar(y,beta,3);
642   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) PetscFunctionReturn(0);
643   ierr = VecSetErrorIfLocked(y,1);CHKERRQ(ierr);
644   ierr = PetscLogEventBegin(VEC_AXPY,x,y,0,0);CHKERRQ(ierr);
645   ierr = (*y->ops->axpby)(y,alpha,beta,x);CHKERRQ(ierr);
646   ierr = PetscLogEventEnd(VEC_AXPY,x,y,0,0);CHKERRQ(ierr);
647   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
648   PetscFunctionReturn(0);
649 }
650 
651 /*@
652    VecAXPBYPCZ - Computes z = alpha x + beta y + gamma z
653 
654    Logically Collective on Vec
655 
656    Input Parameters:
657 +  alpha,beta, gamma - the scalars
658 -  x, y, z  - the vectors
659 
660    Output Parameter:
661 .  z - output vector
662 
663    Level: intermediate
664 
665    Notes:
666     x, y and z must be different vectors
667     The implementation is optimized for alpha of 1.0 and gamma of 1.0 or 0.0
668 
669 
670 .seealso:  VecAYPX(), VecMAXPY(), VecWAXPY(), VecAXPY(), VecAXPBY()
671 @*/
672 PetscErrorCode  VecAXPBYPCZ(Vec z,PetscScalar alpha,PetscScalar beta,PetscScalar gamma,Vec x,Vec y)
673 {
674   PetscErrorCode ierr;
675 
676   PetscFunctionBegin;
677   PetscValidHeaderSpecific(x,VEC_CLASSID,5);
678   PetscValidHeaderSpecific(y,VEC_CLASSID,6);
679   PetscValidHeaderSpecific(z,VEC_CLASSID,1);
680   PetscValidType(x,5);
681   PetscValidType(y,6);
682   PetscValidType(z,1);
683   PetscCheckSameTypeAndComm(x,5,y,6);
684   PetscCheckSameTypeAndComm(x,5,z,1);
685   VecCheckSameSize(x,1,y,5);
686   VecCheckSameSize(x,1,z,6);
687   if (x == y || x == z) SETERRQ(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_IDN,"x, y, and z must be different vectors");
688   if (y == z) SETERRQ(PetscObjectComm((PetscObject)y),PETSC_ERR_ARG_IDN,"x, y, and z must be different vectors");
689   PetscValidLogicalCollectiveScalar(z,alpha,2);
690   PetscValidLogicalCollectiveScalar(z,beta,3);
691   PetscValidLogicalCollectiveScalar(z,gamma,4);
692   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) PetscFunctionReturn(0);
693   ierr = VecSetErrorIfLocked(z,1);CHKERRQ(ierr);
694 
695   ierr = PetscLogEventBegin(VEC_AXPBYPCZ,x,y,z,0);CHKERRQ(ierr);
696   ierr = (*y->ops->axpbypcz)(z,alpha,beta,gamma,x,y);CHKERRQ(ierr);
697   ierr = PetscLogEventEnd(VEC_AXPBYPCZ,x,y,z,0);CHKERRQ(ierr);
698   ierr = PetscObjectStateIncrease((PetscObject)z);CHKERRQ(ierr);
699   PetscFunctionReturn(0);
700 }
701 
702 /*@
703    VecAYPX - Computes y = x + beta y.
704 
705    Logically Collective on Vec
706 
707    Input Parameters:
708 +  beta - the scalar
709 -  x, y  - the vectors
710 
711    Output Parameter:
712 .  y - output vector
713 
714    Level: intermediate
715 
716    Notes:
717     x and y MUST be different vectors
718     The implementation is optimized for beta of -1.0, 0.0, and 1.0
719 
720 
721 .seealso:  VecMAXPY(), VecWAXPY(), VecAXPY(), VecAXPBYPCZ(), VecAXPBY()
722 @*/
723 PetscErrorCode  VecAYPX(Vec y,PetscScalar beta,Vec x)
724 {
725   PetscErrorCode ierr;
726 
727   PetscFunctionBegin;
728   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
729   PetscValidHeaderSpecific(y,VEC_CLASSID,1);
730   PetscValidType(x,3);
731   PetscValidType(y,1);
732   PetscCheckSameTypeAndComm(x,3,y,1);
733   VecCheckSameSize(x,1,y,3);
734   if (x == y) SETERRQ(PetscObjectComm((PetscObject)x),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
735   PetscValidLogicalCollectiveScalar(y,beta,2);
736   ierr = VecSetErrorIfLocked(y,1);CHKERRQ(ierr);
737 
738   ierr = PetscLogEventBegin(VEC_AYPX,x,y,0,0);CHKERRQ(ierr);
739   ierr =  (*y->ops->aypx)(y,beta,x);CHKERRQ(ierr);
740   ierr = PetscLogEventEnd(VEC_AYPX,x,y,0,0);CHKERRQ(ierr);
741   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
742   PetscFunctionReturn(0);
743 }
744 
745 
746 /*@
747    VecWAXPY - Computes w = alpha x + y.
748 
749    Logically Collective on Vec
750 
751    Input Parameters:
752 +  alpha - the scalar
753 -  x, y  - the vectors
754 
755    Output Parameter:
756 .  w - the result
757 
758    Level: intermediate
759 
760    Notes:
761     w cannot be either x or y, but x and y can be the same
762     The implementation is optimzed for alpha of -1.0, 0.0, and 1.0
763 
764 
765 .seealso: VecAXPY(), VecAYPX(), VecAXPBY(), VecMAXPY(), VecAXPBYPCZ()
766 @*/
767 PetscErrorCode  VecWAXPY(Vec w,PetscScalar alpha,Vec x,Vec y)
768 {
769   PetscErrorCode ierr;
770 
771   PetscFunctionBegin;
772   PetscValidHeaderSpecific(w,VEC_CLASSID,1);
773   PetscValidHeaderSpecific(x,VEC_CLASSID,3);
774   PetscValidHeaderSpecific(y,VEC_CLASSID,4);
775   PetscValidType(w,1);
776   PetscValidType(x,3);
777   PetscValidType(y,4);
778   PetscCheckSameTypeAndComm(x,3,y,4);
779   PetscCheckSameTypeAndComm(y,4,w,1);
780   VecCheckSameSize(x,3,y,4);
781   VecCheckSameSize(x,3,w,1);
782   if (w == y) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Result vector w cannot be same as input vector y, suggest VecAXPY()");
783   if (w == x) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Result vector w cannot be same as input vector x, suggest VecAYPX()");
784   PetscValidLogicalCollectiveScalar(y,alpha,2);
785   ierr = VecSetErrorIfLocked(w,1);CHKERRQ(ierr);
786 
787   ierr = PetscLogEventBegin(VEC_WAXPY,x,y,w,0);CHKERRQ(ierr);
788   ierr =  (*w->ops->waxpy)(w,alpha,x,y);CHKERRQ(ierr);
789   ierr = PetscLogEventEnd(VEC_WAXPY,x,y,w,0);CHKERRQ(ierr);
790   ierr = PetscObjectStateIncrease((PetscObject)w);CHKERRQ(ierr);
791   PetscFunctionReturn(0);
792 }
793 
794 
795 /*@C
796    VecSetValues - Inserts or adds values into certain locations of a vector.
797 
798    Not Collective
799 
800    Input Parameters:
801 +  x - vector to insert in
802 .  ni - number of elements to add
803 .  ix - indices where to add
804 .  y - array of values
805 -  iora - either INSERT_VALUES or ADD_VALUES, where
806    ADD_VALUES adds values to any existing entries, and
807    INSERT_VALUES replaces existing entries with new values
808 
809    Notes:
810    VecSetValues() sets x[ix[i]] = y[i], for i=0,...,ni-1.
811 
812    Calls to VecSetValues() with the INSERT_VALUES and ADD_VALUES
813    options cannot be mixed without intervening calls to the assembly
814    routines.
815 
816    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
817    MUST be called after all calls to VecSetValues() have been completed.
818 
819    VecSetValues() uses 0-based indices in Fortran as well as in C.
820 
821    If you call VecSetOption(x, VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE),
822    negative indices may be passed in ix. These rows are
823    simply ignored. This allows easily inserting element load matrices
824    with homogeneous Dirchlet boundary conditions that you don't want represented
825    in the vector.
826 
827    Level: beginner
828 
829 .seealso:  VecAssemblyBegin(), VecAssemblyEnd(), VecSetValuesLocal(),
830            VecSetValue(), VecSetValuesBlocked(), InsertMode, INSERT_VALUES, ADD_VALUES, VecGetValues()
831 @*/
832 PetscErrorCode  VecSetValues(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)
833 {
834   PetscErrorCode ierr;
835 
836   PetscFunctionBeginHot;
837   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
838   if (!ni) PetscFunctionReturn(0);
839   PetscValidIntPointer(ix,3);
840   PetscValidScalarPointer(y,4);
841   PetscValidType(x,1);
842 
843   ierr = PetscLogEventBegin(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
844   ierr = (*x->ops->setvalues)(x,ni,ix,y,iora);CHKERRQ(ierr);
845   ierr = PetscLogEventEnd(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
846   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
847   PetscFunctionReturn(0);
848 }
849 
850 /*@C
851    VecGetValues - Gets values from certain locations of a vector. Currently
852           can only get values on the same processor
853 
854     Not Collective
855 
856    Input Parameters:
857 +  x - vector to get values from
858 .  ni - number of elements to get
859 -  ix - indices where to get them from (in global 1d numbering)
860 
861    Output Parameter:
862 .   y - array of values
863 
864    Notes:
865    The user provides the allocated array y; it is NOT allocated in this routine
866 
867    VecGetValues() gets y[i] = x[ix[i]], for i=0,...,ni-1.
868 
869    VecAssemblyBegin() and VecAssemblyEnd()  MUST be called before calling this
870 
871    VecGetValues() uses 0-based indices in Fortran as well as in C.
872 
873    If you call VecSetOption(x, VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE),
874    negative indices may be passed in ix. These rows are
875    simply ignored.
876 
877    Level: beginner
878 
879 .seealso:  VecAssemblyBegin(), VecAssemblyEnd(), VecSetValues()
880 @*/
881 PetscErrorCode  VecGetValues(Vec x,PetscInt ni,const PetscInt ix[],PetscScalar y[])
882 {
883   PetscErrorCode ierr;
884 
885   PetscFunctionBegin;
886   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
887   if (!ni) PetscFunctionReturn(0);
888   PetscValidIntPointer(ix,3);
889   PetscValidScalarPointer(y,4);
890   PetscValidType(x,1);
891   ierr = (*x->ops->getvalues)(x,ni,ix,y);CHKERRQ(ierr);
892   PetscFunctionReturn(0);
893 }
894 
895 /*@C
896    VecSetValuesBlocked - Inserts or adds blocks of values into certain locations of a vector.
897 
898    Not Collective
899 
900    Input Parameters:
901 +  x - vector to insert in
902 .  ni - number of blocks to add
903 .  ix - indices where to add in block count, rather than element count
904 .  y - array of values
905 -  iora - either INSERT_VALUES or ADD_VALUES, where
906    ADD_VALUES adds values to any existing entries, and
907    INSERT_VALUES replaces existing entries with new values
908 
909    Notes:
910    VecSetValuesBlocked() sets x[bs*ix[i]+j] = y[bs*i+j],
911    for j=0,...,bs-1, for i=0,...,ni-1. where bs was set with VecSetBlockSize().
912 
913    Calls to VecSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
914    options cannot be mixed without intervening calls to the assembly
915    routines.
916 
917    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
918    MUST be called after all calls to VecSetValuesBlocked() have been completed.
919 
920    VecSetValuesBlocked() uses 0-based indices in Fortran as well as in C.
921 
922    Negative indices may be passed in ix, these rows are
923    simply ignored. This allows easily inserting element load matrices
924    with homogeneous Dirchlet boundary conditions that you don't want represented
925    in the vector.
926 
927    Level: intermediate
928 
929 .seealso:  VecAssemblyBegin(), VecAssemblyEnd(), VecSetValuesBlockedLocal(),
930            VecSetValues()
931 @*/
932 PetscErrorCode  VecSetValuesBlocked(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)
933 {
934   PetscErrorCode ierr;
935 
936   PetscFunctionBeginHot;
937   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
938   if (!ni) PetscFunctionReturn(0);
939   PetscValidIntPointer(ix,3);
940   PetscValidScalarPointer(y,4);
941   PetscValidType(x,1);
942 
943   ierr = PetscLogEventBegin(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
944   ierr = (*x->ops->setvaluesblocked)(x,ni,ix,y,iora);CHKERRQ(ierr);
945   ierr = PetscLogEventEnd(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
946   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
947   PetscFunctionReturn(0);
948 }
949 
950 
951 /*@C
952    VecSetValuesLocal - Inserts or adds values into certain locations of a vector,
953    using a local ordering of the nodes.
954 
955    Not Collective
956 
957    Input Parameters:
958 +  x - vector to insert in
959 .  ni - number of elements to add
960 .  ix - indices where to add
961 .  y - array of values
962 -  iora - either INSERT_VALUES or ADD_VALUES, where
963    ADD_VALUES adds values to any existing entries, and
964    INSERT_VALUES replaces existing entries with new values
965 
966    Level: intermediate
967 
968    Notes:
969    VecSetValuesLocal() sets x[ix[i]] = y[i], for i=0,...,ni-1.
970 
971    Calls to VecSetValues() with the INSERT_VALUES and ADD_VALUES
972    options cannot be mixed without intervening calls to the assembly
973    routines.
974 
975    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
976    MUST be called after all calls to VecSetValuesLocal() have been completed.
977 
978    VecSetValuesLocal() uses 0-based indices in Fortran as well as in C.
979 
980 .seealso:  VecAssemblyBegin(), VecAssemblyEnd(), VecSetValues(), VecSetLocalToGlobalMapping(),
981            VecSetValuesBlockedLocal()
982 @*/
983 PetscErrorCode  VecSetValuesLocal(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)
984 {
985   PetscErrorCode ierr;
986   PetscInt       lixp[128],*lix = lixp;
987 
988   PetscFunctionBeginHot;
989   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
990   if (!ni) PetscFunctionReturn(0);
991   PetscValidIntPointer(ix,3);
992   PetscValidScalarPointer(y,4);
993   PetscValidType(x,1);
994 
995   ierr = PetscLogEventBegin(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
996   if (!x->ops->setvalueslocal) {
997     if (!x->map->mapping) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Local to global never set with VecSetLocalToGlobalMapping()");
998     if (ni > 128) {
999       ierr = PetscMalloc1(ni,&lix);CHKERRQ(ierr);
1000     }
1001     ierr = ISLocalToGlobalMappingApply(x->map->mapping,ni,(PetscInt*)ix,lix);CHKERRQ(ierr);
1002     ierr = (*x->ops->setvalues)(x,ni,lix,y,iora);CHKERRQ(ierr);
1003     if (ni > 128) {
1004       ierr = PetscFree(lix);CHKERRQ(ierr);
1005     }
1006   } else {
1007     ierr = (*x->ops->setvalueslocal)(x,ni,ix,y,iora);CHKERRQ(ierr);
1008   }
1009   ierr = PetscLogEventEnd(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
1010   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
1011   PetscFunctionReturn(0);
1012 }
1013 
1014 /*@
1015    VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
1016    using a local ordering of the nodes.
1017 
1018    Not Collective
1019 
1020    Input Parameters:
1021 +  x - vector to insert in
1022 .  ni - number of blocks to add
1023 .  ix - indices where to add in block count, not element count
1024 .  y - array of values
1025 -  iora - either INSERT_VALUES or ADD_VALUES, where
1026    ADD_VALUES adds values to any existing entries, and
1027    INSERT_VALUES replaces existing entries with new values
1028 
1029    Level: intermediate
1030 
1031    Notes:
1032    VecSetValuesBlockedLocal() sets x[bs*ix[i]+j] = y[bs*i+j],
1033    for j=0,..bs-1, for i=0,...,ni-1, where bs has been set with VecSetBlockSize().
1034 
1035    Calls to VecSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
1036    options cannot be mixed without intervening calls to the assembly
1037    routines.
1038 
1039    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
1040    MUST be called after all calls to VecSetValuesBlockedLocal() have been completed.
1041 
1042    VecSetValuesBlockedLocal() uses 0-based indices in Fortran as well as in C.
1043 
1044 
1045 .seealso:  VecAssemblyBegin(), VecAssemblyEnd(), VecSetValues(), VecSetValuesBlocked(),
1046            VecSetLocalToGlobalMapping()
1047 @*/
1048 PetscErrorCode  VecSetValuesBlockedLocal(Vec x,PetscInt ni,const PetscInt ix[],const PetscScalar y[],InsertMode iora)
1049 {
1050   PetscErrorCode ierr;
1051   PetscInt       lixp[128],*lix = lixp;
1052 
1053   PetscFunctionBeginHot;
1054   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1055   if (!ni) PetscFunctionReturn(0);
1056   PetscValidIntPointer(ix,3);
1057   PetscValidScalarPointer(y,4);
1058   PetscValidType(x,1);
1059   if (ni > 128) {
1060     ierr = PetscMalloc1(ni,&lix);CHKERRQ(ierr);
1061   }
1062 
1063   ierr = PetscLogEventBegin(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
1064   ierr = ISLocalToGlobalMappingApplyBlock(x->map->mapping,ni,(PetscInt*)ix,lix);CHKERRQ(ierr);
1065   ierr = (*x->ops->setvaluesblocked)(x,ni,lix,y,iora);CHKERRQ(ierr);
1066   ierr = PetscLogEventEnd(VEC_SetValues,x,0,0,0);CHKERRQ(ierr);
1067   if (ni > 128) {
1068     ierr = PetscFree(lix);CHKERRQ(ierr);
1069   }
1070   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
1071   PetscFunctionReturn(0);
1072 }
1073 
1074 /*@
1075    VecMTDot - Computes indefinite vector multiple dot products.
1076    That is, it does NOT use the complex conjugate.
1077 
1078    Collective on Vec
1079 
1080    Input Parameters:
1081 +  x - one vector
1082 .  nv - number of vectors
1083 -  y - array of vectors.  Note that vectors are pointers
1084 
1085    Output Parameter:
1086 .  val - array of the dot products
1087 
1088    Notes for Users of Complex Numbers:
1089    For complex vectors, VecMTDot() computes the indefinite form
1090 $      val = (x,y) = y^T x,
1091    where y^T denotes the transpose of y.
1092 
1093    Use VecMDot() for the inner product
1094 $      val = (x,y) = y^H x,
1095    where y^H denotes the conjugate transpose of y.
1096 
1097    Level: intermediate
1098 
1099 
1100 .seealso: VecMDot(), VecTDot()
1101 @*/
1102 PetscErrorCode  VecMTDot(Vec x,PetscInt nv,const Vec y[],PetscScalar val[])
1103 {
1104   PetscErrorCode ierr;
1105 
1106   PetscFunctionBegin;
1107   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1108   PetscValidLogicalCollectiveInt(x,nv,2);
1109   if (!nv) PetscFunctionReturn(0);
1110   PetscValidPointer(y,3);
1111   PetscValidHeaderSpecific(*y,VEC_CLASSID,3);
1112   PetscValidScalarPointer(val,4);
1113   PetscValidType(x,2);
1114   PetscValidType(*y,3);
1115   PetscCheckSameTypeAndComm(x,2,*y,3);
1116   VecCheckSameSize(x,1,*y,3);
1117 
1118   ierr = PetscLogEventBegin(VEC_MTDot,x,*y,0,0);CHKERRQ(ierr);
1119   ierr = (*x->ops->mtdot)(x,nv,y,val);CHKERRQ(ierr);
1120   ierr = PetscLogEventEnd(VEC_MTDot,x,*y,0,0);CHKERRQ(ierr);
1121   PetscFunctionReturn(0);
1122 }
1123 
1124 /*@
1125    VecMDot - Computes vector multiple dot products.
1126 
1127    Collective on Vec
1128 
1129    Input Parameters:
1130 +  x - one vector
1131 .  nv - number of vectors
1132 -  y - array of vectors.
1133 
1134    Output Parameter:
1135 .  val - array of the dot products (does not allocate the array)
1136 
1137    Notes for Users of Complex Numbers:
1138    For complex vectors, VecMDot() computes
1139 $     val = (x,y) = y^H x,
1140    where y^H denotes the conjugate transpose of y.
1141 
1142    Use VecMTDot() for the indefinite form
1143 $     val = (x,y) = y^T x,
1144    where y^T denotes the transpose of y.
1145 
1146    Level: intermediate
1147 
1148 
1149 .seealso: VecMTDot(), VecDot()
1150 @*/
1151 PetscErrorCode  VecMDot(Vec x,PetscInt nv,const Vec y[],PetscScalar val[])
1152 {
1153   PetscErrorCode ierr;
1154 
1155   PetscFunctionBegin;
1156   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1157   PetscValidLogicalCollectiveInt(x,nv,2);
1158   if (!nv) PetscFunctionReturn(0);
1159   if (nv < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",nv);
1160   PetscValidPointer(y,3);
1161   PetscValidHeaderSpecific(*y,VEC_CLASSID,3);
1162   PetscValidScalarPointer(val,4);
1163   PetscValidType(x,2);
1164   PetscValidType(*y,3);
1165   PetscCheckSameTypeAndComm(x,2,*y,3);
1166   VecCheckSameSize(x,1,*y,3);
1167 
1168   ierr = PetscLogEventBegin(VEC_MDot,x,*y,0,0);CHKERRQ(ierr);
1169   ierr = (*x->ops->mdot)(x,nv,y,val);CHKERRQ(ierr);
1170   ierr = PetscLogEventEnd(VEC_MDot,x,*y,0,0);CHKERRQ(ierr);
1171   PetscFunctionReturn(0);
1172 }
1173 
1174 /*@
1175    VecMAXPY - Computes y = y + sum alpha[i] x[i]
1176 
1177    Logically Collective on Vec
1178 
1179    Input Parameters:
1180 +  nv - number of scalars and x-vectors
1181 .  alpha - array of scalars
1182 .  y - one vector
1183 -  x - array of vectors
1184 
1185    Level: intermediate
1186 
1187    Notes:
1188     y cannot be any of the x vectors
1189 
1190 .seealso:  VecAYPX(), VecWAXPY(), VecAXPY(), VecAXPBYPCZ(), VecAXPBY()
1191 @*/
1192 PetscErrorCode  VecMAXPY(Vec y,PetscInt nv,const PetscScalar alpha[],Vec x[])
1193 {
1194   PetscErrorCode ierr;
1195   PetscInt       i;
1196   PetscBool      nonzero;
1197 
1198   PetscFunctionBegin;
1199   PetscValidHeaderSpecific(y,VEC_CLASSID,1);
1200   PetscValidLogicalCollectiveInt(y,nv,2);
1201   if (!nv) PetscFunctionReturn(0);
1202   if (nv < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Number of vectors (given %D) cannot be negative",nv);
1203   PetscValidScalarPointer(alpha,3);
1204   PetscValidPointer(x,4);
1205   PetscValidHeaderSpecific(*x,VEC_CLASSID,4);
1206   PetscValidType(y,1);
1207   PetscValidType(*x,4);
1208   PetscCheckSameTypeAndComm(y,1,*x,4);
1209   VecCheckSameSize(y,1,*x,4);
1210   for (i=0; i<nv; i++) PetscValidLogicalCollectiveScalar(y,alpha[i],3);
1211   for (i=0, nonzero = PETSC_FALSE; i<nv && !nonzero; i++) nonzero = (PetscBool)(nonzero || alpha[i] != (PetscScalar)0.0);
1212   if (!nonzero) PetscFunctionReturn(0);
1213   ierr = VecSetErrorIfLocked(y,1);CHKERRQ(ierr);
1214   ierr = PetscLogEventBegin(VEC_MAXPY,*x,y,0,0);CHKERRQ(ierr);
1215   ierr = (*y->ops->maxpy)(y,nv,alpha,x);CHKERRQ(ierr);
1216   ierr = PetscLogEventEnd(VEC_MAXPY,*x,y,0,0);CHKERRQ(ierr);
1217   ierr = PetscObjectStateIncrease((PetscObject)y);CHKERRQ(ierr);
1218   PetscFunctionReturn(0);
1219 }
1220 
1221 /*@
1222    VecGetSubVector - Gets a vector representing part of another vector
1223 
1224    Collective on X and IS
1225 
1226    Input Arguments:
1227 + X - vector from which to extract a subvector
1228 - is - index set representing portion of X to extract
1229 
1230    Output Arguments:
1231 . Y - subvector corresponding to is
1232 
1233    Level: advanced
1234 
1235    Notes:
1236    The subvector Y should be returned with VecRestoreSubVector().
1237    X and is must be defined on the same communicator
1238 
1239    This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1240    modifying the subvector.  Other non-overlapping subvectors can still be obtained from X using this function.
1241    The resulting subvector inherits the block size from the IS if greater than one. Otherwise, the block size is guessed from the block size of the original vec.
1242 
1243 .seealso: MatCreateSubMatrix()
1244 @*/
1245 PetscErrorCode  VecGetSubVector(Vec X,IS is,Vec *Y)
1246 {
1247   PetscErrorCode   ierr;
1248   Vec              Z;
1249 
1250   PetscFunctionBegin;
1251   PetscValidHeaderSpecific(X,VEC_CLASSID,1);
1252   PetscValidHeaderSpecific(is,IS_CLASSID,2);
1253   PetscCheckSameComm(X,1,is,2);
1254   PetscValidPointer(Y,3);
1255   if (X->ops->getsubvector) {
1256     ierr = (*X->ops->getsubvector)(X,is,&Z);CHKERRQ(ierr);
1257   } else { /* Default implementation currently does no caching */
1258     PetscInt  gstart,gend,start;
1259     PetscBool red[2] = { PETSC_TRUE, PETSC_TRUE };
1260     PetscInt  n,N,ibs,vbs,bs = -1;
1261 
1262     ierr = ISGetLocalSize(is,&n);CHKERRQ(ierr);
1263     ierr = ISGetSize(is,&N);CHKERRQ(ierr);
1264     ierr = ISGetBlockSize(is,&ibs);CHKERRQ(ierr);
1265     ierr = VecGetBlockSize(X,&vbs);CHKERRQ(ierr);
1266     ierr = VecGetOwnershipRange(X,&gstart,&gend);CHKERRQ(ierr);
1267     ierr = ISContiguousLocal(is,gstart,gend,&start,&red[0]);CHKERRQ(ierr);
1268     /* block size is given by IS if ibs > 1; otherwise, check the vector */
1269     if (ibs > 1) {
1270       ierr = MPIU_Allreduce(MPI_IN_PLACE,red,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)is));CHKERRQ(ierr);
1271       bs   = ibs;
1272     } else {
1273       if (n%vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1274       ierr = MPIU_Allreduce(MPI_IN_PLACE,red,2,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)is));CHKERRQ(ierr);
1275       if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1276     }
1277     if (red[0]) { /* We can do a no-copy implementation */
1278       const PetscScalar *x;
1279       PetscInt          state = 0;
1280       PetscBool         isstd;
1281 #if defined(PETSC_HAVE_CUDA)
1282       PetscBool         iscuda;
1283 #endif
1284 
1285       ierr = PetscObjectTypeCompareAny((PetscObject)X,&isstd,VECSEQ,VECMPI,VECSTANDARD,"");CHKERRQ(ierr);
1286 #if defined(PETSC_HAVE_CUDA)
1287       ierr = PetscObjectTypeCompareAny((PetscObject)X,&iscuda,VECSEQCUDA,VECMPICUDA,"");CHKERRQ(ierr);
1288       if (iscuda) {
1289         const PetscScalar *x_d;
1290         PetscMPIInt       size;
1291         PetscOffloadMask  flg;
1292 
1293         ierr = VecCUDAGetArrays_Private(X,&x,&x_d,&flg);CHKERRQ(ierr);
1294         if (flg == PETSC_OFFLOAD_UNALLOCATED) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for PETSC_OFFLOAD_UNALLOCATED");
1295         if (n && !x && !x_d) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Missing vector data");
1296         if (x) x += start;
1297         if (x_d) x_d += start;
1298         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)X),&size);CHKERRQ(ierr);
1299         if (size == 1) {
1300           ierr = VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X),bs,n,x,x_d,&Z);CHKERRQ(ierr);
1301         } else {
1302           ierr = VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X),bs,n,N,x,x_d,&Z);CHKERRQ(ierr);
1303         }
1304         Z->offloadmask = flg;
1305       } else if (isstd) {
1306 #else
1307       if (isstd) { /* standard CPU: use CreateWithArray pattern */
1308 #endif
1309         PetscMPIInt size;
1310 
1311         ierr = MPI_Comm_size(PetscObjectComm((PetscObject)X),&size);CHKERRQ(ierr);
1312         ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1313         if (x) x += start;
1314         if (size == 1) {
1315           ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)X),bs,n,x,&Z);CHKERRQ(ierr);
1316         } else {
1317           ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)X),bs,n,N,x,&Z);CHKERRQ(ierr);
1318         }
1319         ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1320       } else { /* default implementation: use place array */
1321         ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr);
1322         ierr = VecCreate(PetscObjectComm((PetscObject)X),&Z);CHKERRQ(ierr);
1323         ierr = VecSetType(Z,((PetscObject)X)->type_name);CHKERRQ(ierr);
1324         ierr = VecSetSizes(Z,n,N);CHKERRQ(ierr);
1325         ierr = VecSetBlockSize(Z,bs);CHKERRQ(ierr);
1326         ierr = VecPlaceArray(Z,x ? x+start : NULL);CHKERRQ(ierr);
1327         ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr);
1328       }
1329 
1330       /* this is relevant only in debug mode */
1331       ierr = VecLockGet(X,&state);CHKERRQ(ierr);
1332       if (state) {
1333         ierr = VecLockReadPush(Z);CHKERRQ(ierr);
1334       }
1335       Z->ops->placearray = NULL;
1336       Z->ops->replacearray = NULL;
1337     } else { /* Have to create a scatter and do a copy */
1338       VecScatter scatter;
1339 
1340       ierr = VecCreate(PetscObjectComm((PetscObject)is),&Z);CHKERRQ(ierr);
1341       ierr = VecSetSizes(Z,n,N);CHKERRQ(ierr);
1342       ierr = VecSetBlockSize(Z,bs);CHKERRQ(ierr);
1343       ierr = VecSetType(Z,((PetscObject)X)->type_name);CHKERRQ(ierr);
1344       ierr = VecScatterCreate(X,is,Z,NULL,&scatter);CHKERRQ(ierr);
1345       ierr = VecScatterBegin(scatter,X,Z,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1346       ierr = VecScatterEnd(scatter,X,Z,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
1347       ierr = PetscObjectCompose((PetscObject)Z,"VecGetSubVector_Scatter",(PetscObject)scatter);CHKERRQ(ierr);
1348       ierr = VecScatterDestroy(&scatter);CHKERRQ(ierr);
1349     }
1350   }
1351   /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1352   if (VecGetSubVectorSavedStateId < 0) {ierr = PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId);CHKERRQ(ierr);}
1353   ierr = PetscObjectComposedDataSetInt((PetscObject)Z,VecGetSubVectorSavedStateId,1);CHKERRQ(ierr);
1354   *Y   = Z;
1355   PetscFunctionReturn(0);
1356 }
1357 
1358 /*@
1359    VecRestoreSubVector - Restores a subvector extracted using VecGetSubVector()
1360 
1361    Collective on IS
1362 
1363    Input Arguments:
1364 + X - vector from which subvector was obtained
1365 . is - index set representing the subset of X
1366 - Y - subvector being restored
1367 
1368    Level: advanced
1369 
1370 .seealso: VecGetSubVector()
1371 @*/
1372 PetscErrorCode  VecRestoreSubVector(Vec X,IS is,Vec *Y)
1373 {
1374   PetscErrorCode ierr;
1375 
1376   PetscFunctionBegin;
1377   PetscValidHeaderSpecific(X,VEC_CLASSID,1);
1378   PetscValidHeaderSpecific(is,IS_CLASSID,2);
1379   PetscCheckSameComm(X,1,is,2);
1380   PetscValidPointer(Y,3);
1381   PetscValidHeaderSpecific(*Y,VEC_CLASSID,3);
1382   if (X->ops->restoresubvector) {
1383     ierr = (*X->ops->restoresubvector)(X,is,Y);CHKERRQ(ierr);
1384   } else {
1385     PETSC_UNUSED PetscObjectState dummystate = 0;
1386     PetscBool valid;
1387 
1388     ierr = PetscObjectComposedDataGetInt((PetscObject)*Y,VecGetSubVectorSavedStateId,dummystate,valid);CHKERRQ(ierr);
1389     if (!valid) {
1390       VecScatter scatter;
1391       PetscInt   state;
1392 
1393       ierr = VecLockGet(X,&state);CHKERRQ(ierr);
1394       if (state != 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vec X is locked for read-only or read/write access");
1395 
1396       ierr = PetscObjectQuery((PetscObject)*Y,"VecGetSubVector_Scatter",(PetscObject*)&scatter);CHKERRQ(ierr);
1397       if (scatter) {
1398         ierr = VecScatterBegin(scatter,*Y,X,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1399         ierr = VecScatterEnd(scatter,*Y,X,INSERT_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
1400       } else {
1401 #if defined(PETSC_HAVE_CUDA)
1402         PetscBool iscuda;
1403 
1404         ierr = PetscObjectTypeCompareAny((PetscObject)*Y,&iscuda,VECSEQCUDA,VECMPICUDA,"");CHKERRQ(ierr);
1405         if (iscuda) {
1406           PetscOffloadMask ymask = (*Y)->offloadmask;
1407 
1408           /* The offloadmask of X dictates where to move memory
1409              If X GPU data is valid, then move Y data on GPU if needed
1410              Otherwise, move back to the CPU */
1411           switch (X->offloadmask) {
1412           case PETSC_OFFLOAD_BOTH:
1413             if (ymask == PETSC_OFFLOAD_CPU) {
1414               ierr = VecCUDAResetArray(*Y);CHKERRQ(ierr);
1415             } else if (ymask == PETSC_OFFLOAD_GPU) {
1416               X->offloadmask = PETSC_OFFLOAD_GPU;
1417             }
1418             break;
1419           case PETSC_OFFLOAD_GPU:
1420             if (ymask == PETSC_OFFLOAD_CPU) {
1421               ierr = VecCUDAResetArray(*Y);CHKERRQ(ierr);
1422             }
1423             break;
1424           case PETSC_OFFLOAD_CPU:
1425             if (ymask == PETSC_OFFLOAD_GPU) {
1426               ierr = VecResetArray(*Y);CHKERRQ(ierr);
1427             }
1428             break;
1429           case PETSC_OFFLOAD_UNALLOCATED:
1430           case PETSC_OFFLOAD_VECKOKKOS:
1431             SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"This should not happen");
1432             break;
1433           }
1434         } else {
1435 #else
1436         {
1437 #endif
1438           /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1439           ierr = VecResetArray(*Y);CHKERRQ(ierr);
1440         }
1441         ierr = PetscObjectStateIncrease((PetscObject)X);CHKERRQ(ierr);
1442       }
1443     }
1444     ierr = VecDestroy(Y);CHKERRQ(ierr);
1445   }
1446   PetscFunctionReturn(0);
1447 }
1448 
1449 /*@
1450    VecGetLocalVectorRead - Maps the local portion of a vector into a
1451    vector.  You must call VecRestoreLocalVectorRead() when the local
1452    vector is no longer needed.
1453 
1454    Not collective.
1455 
1456    Input parameter:
1457 .  v - The vector for which the local vector is desired.
1458 
1459    Output parameter:
1460 .  w - Upon exit this contains the local vector.
1461 
1462    Level: beginner
1463 
1464    Notes:
1465    This function is similar to VecGetArrayRead() which maps the local
1466    portion into a raw pointer.  VecGetLocalVectorRead() is usually
1467    almost as efficient as VecGetArrayRead() but in certain circumstances
1468    VecGetLocalVectorRead() can be much more efficient than
1469    VecGetArrayRead().  This is because the construction of a contiguous
1470    array representing the vector data required by VecGetArrayRead() can
1471    be an expensive operation for certain vector types.  For example, for
1472    GPU vectors VecGetArrayRead() requires that the data between device
1473    and host is synchronized.
1474 
1475    Unlike VecGetLocalVector(), this routine is not collective and
1476    preserves cached information.
1477 
1478 .seealso: VecRestoreLocalVectorRead(), VecGetLocalVector(), VecGetArrayRead(), VecGetArray()
1479 @*/
1480 PetscErrorCode VecGetLocalVectorRead(Vec v,Vec w)
1481 {
1482   PetscErrorCode ierr;
1483   PetscScalar    *a;
1484 
1485   PetscFunctionBegin;
1486   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1487   PetscValidHeaderSpecific(w,VEC_CLASSID,2);
1488   VecCheckSameLocalSize(v,1,w,2);
1489   if (v->ops->getlocalvectorread) {
1490     ierr = (*v->ops->getlocalvectorread)(v,w);CHKERRQ(ierr);
1491   } else {
1492     ierr = VecGetArrayRead(v,(const PetscScalar**)&a);CHKERRQ(ierr);
1493     ierr = VecPlaceArray(w,a);CHKERRQ(ierr);
1494   }
1495   PetscFunctionReturn(0);
1496 }
1497 
1498 /*@
1499    VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1500    previously mapped into a vector using VecGetLocalVectorRead().
1501 
1502    Not collective.
1503 
1504    Input parameter:
1505 +  v - The local portion of this vector was previously mapped into w using VecGetLocalVectorRead().
1506 -  w - The vector into which the local portion of v was mapped.
1507 
1508    Level: beginner
1509 
1510 .seealso: VecGetLocalVectorRead(), VecGetLocalVector(), VecGetArrayRead(), VecGetArray()
1511 @*/
1512 PetscErrorCode VecRestoreLocalVectorRead(Vec v,Vec w)
1513 {
1514   PetscErrorCode ierr;
1515   PetscScalar    *a;
1516 
1517   PetscFunctionBegin;
1518   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1519   PetscValidHeaderSpecific(w,VEC_CLASSID,2);
1520   if (v->ops->restorelocalvectorread) {
1521     ierr = (*v->ops->restorelocalvectorread)(v,w);CHKERRQ(ierr);
1522   } else {
1523     ierr = VecGetArrayRead(w,(const PetscScalar**)&a);CHKERRQ(ierr);
1524     ierr = VecRestoreArrayRead(v,(const PetscScalar**)&a);CHKERRQ(ierr);
1525     ierr = VecResetArray(w);CHKERRQ(ierr);
1526   }
1527   PetscFunctionReturn(0);
1528 }
1529 
1530 /*@
1531    VecGetLocalVector - Maps the local portion of a vector into a
1532    vector.
1533 
1534    Collective on v, not collective on w.
1535 
1536    Input parameter:
1537 .  v - The vector for which the local vector is desired.
1538 
1539    Output parameter:
1540 .  w - Upon exit this contains the local vector.
1541 
1542    Level: beginner
1543 
1544    Notes:
1545    This function is similar to VecGetArray() which maps the local
1546    portion into a raw pointer.  VecGetLocalVector() is usually about as
1547    efficient as VecGetArray() but in certain circumstances
1548    VecGetLocalVector() can be much more efficient than VecGetArray().
1549    This is because the construction of a contiguous array representing
1550    the vector data required by VecGetArray() can be an expensive
1551    operation for certain vector types.  For example, for GPU vectors
1552    VecGetArray() requires that the data between device and host is
1553    synchronized.
1554 
1555 .seealso: VecRestoreLocalVector(), VecGetLocalVectorRead(), VecGetArrayRead(), VecGetArray()
1556 @*/
1557 PetscErrorCode VecGetLocalVector(Vec v,Vec w)
1558 {
1559   PetscErrorCode ierr;
1560   PetscScalar    *a;
1561 
1562   PetscFunctionBegin;
1563   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1564   PetscValidHeaderSpecific(w,VEC_CLASSID,2);
1565   VecCheckSameLocalSize(v,1,w,2);
1566   if (v->ops->getlocalvector) {
1567     ierr = (*v->ops->getlocalvector)(v,w);CHKERRQ(ierr);
1568   } else {
1569     ierr = VecGetArray(v,&a);CHKERRQ(ierr);
1570     ierr = VecPlaceArray(w,a);CHKERRQ(ierr);
1571   }
1572   PetscFunctionReturn(0);
1573 }
1574 
1575 /*@
1576    VecRestoreLocalVector - Unmaps the local portion of a vector
1577    previously mapped into a vector using VecGetLocalVector().
1578 
1579    Logically collective.
1580 
1581    Input parameter:
1582 +  v - The local portion of this vector was previously mapped into w using VecGetLocalVector().
1583 -  w - The vector into which the local portion of v was mapped.
1584 
1585    Level: beginner
1586 
1587 .seealso: VecGetLocalVector(), VecGetLocalVectorRead(), VecRestoreLocalVectorRead(), LocalVectorRead(), VecGetArrayRead(), VecGetArray()
1588 @*/
1589 PetscErrorCode VecRestoreLocalVector(Vec v,Vec w)
1590 {
1591   PetscErrorCode ierr;
1592   PetscScalar    *a;
1593 
1594   PetscFunctionBegin;
1595   PetscValidHeaderSpecific(v,VEC_CLASSID,1);
1596   PetscValidHeaderSpecific(w,VEC_CLASSID,2);
1597   if (v->ops->restorelocalvector) {
1598     ierr = (*v->ops->restorelocalvector)(v,w);CHKERRQ(ierr);
1599   } else {
1600     ierr = VecGetArray(w,&a);CHKERRQ(ierr);
1601     ierr = VecRestoreArray(v,&a);CHKERRQ(ierr);
1602     ierr = VecResetArray(w);CHKERRQ(ierr);
1603   }
1604   PetscFunctionReturn(0);
1605 }
1606 
1607 /*@C
1608    VecGetArray - Returns a pointer to a contiguous array that contains this
1609    processor's portion of the vector data. For the standard PETSc
1610    vectors, VecGetArray() returns a pointer to the local data array and
1611    does not use any copies. If the underlying vector data is not stored
1612    in a contiguous array this routine will copy the data to a contiguous
1613    array and return a pointer to that. You MUST call VecRestoreArray()
1614    when you no longer need access to the array.
1615 
1616    Logically Collective on Vec
1617 
1618    Input Parameter:
1619 .  x - the vector
1620 
1621    Output Parameter:
1622 .  a - location to put pointer to the array
1623 
1624    Fortran Note:
1625    This routine is used differently from Fortran 77
1626 $    Vec         x
1627 $    PetscScalar x_array(1)
1628 $    PetscOffset i_x
1629 $    PetscErrorCode ierr
1630 $       call VecGetArray(x,x_array,i_x,ierr)
1631 $
1632 $   Access first local entry in vector with
1633 $      value = x_array(i_x + 1)
1634 $
1635 $      ...... other code
1636 $       call VecRestoreArray(x,x_array,i_x,ierr)
1637    For Fortran 90 see VecGetArrayF90()
1638 
1639    See the Fortran chapter of the users manual and
1640    petsc/src/snes/tutorials/ex5f.F for details.
1641 
1642    Level: beginner
1643 
1644 .seealso: VecRestoreArray(), VecGetArrayRead(), VecGetArrays(), VecGetArrayF90(), VecGetArrayReadF90(), VecPlaceArray(), VecGetArray2d(),
1645           VecGetArrayPair(), VecRestoreArrayPair(), VecGetArrayWrite(), VecRestoreArrayWrite()
1646 @*/
1647 PetscErrorCode VecGetArray(Vec x,PetscScalar **a)
1648 {
1649   PetscErrorCode ierr;
1650 #if defined(PETSC_HAVE_VIENNACL)
1651   PetscBool      is_viennacltype = PETSC_FALSE;
1652 #endif
1653 
1654   PetscFunctionBegin;
1655   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1656   ierr = VecSetErrorIfLocked(x,1);CHKERRQ(ierr);
1657   if (x->petscnative) {
1658 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
1659     if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) { /* offloadmask here works as a tag quickly saying this is a VecKokkos */
1660       ierr = VecKokkosSyncHost(x);CHKERRQ(ierr);
1661       *a   = *((PetscScalar**)x->data);
1662       PetscFunctionReturn(0);
1663     }
1664 #endif
1665 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1666     if (x->offloadmask == PETSC_OFFLOAD_GPU) {
1667   #if defined(PETSC_HAVE_VIENNACL)
1668       ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_viennacltype,VECSEQVIENNACL,VECMPIVIENNACL,VECVIENNACL,"");CHKERRQ(ierr);
1669       if (is_viennacltype) {
1670         ierr = VecViennaCLCopyFromGPU(x);CHKERRQ(ierr);
1671       } else
1672   #endif
1673       {
1674   #if defined(PETSC_HAVE_CUDA)
1675         ierr = VecCUDACopyFromGPU(x);CHKERRQ(ierr);
1676   #endif
1677       }
1678     } else if (x->offloadmask == PETSC_OFFLOAD_UNALLOCATED) {
1679   #if defined(PETSC_HAVE_VIENNACL)
1680       ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_viennacltype,VECSEQVIENNACL,VECMPIVIENNACL,VECVIENNACL,"");CHKERRQ(ierr);
1681       if (is_viennacltype) {
1682         ierr = VecViennaCLAllocateCheckHost(x);CHKERRQ(ierr);
1683       } else
1684   #endif
1685       {
1686   #if defined(PETSC_HAVE_CUDA)
1687         ierr = VecCUDAAllocateCheckHost(x);CHKERRQ(ierr);
1688   #endif
1689       }
1690     }
1691 #endif
1692     *a = *((PetscScalar**)x->data);
1693   } else {
1694     if (x->ops->getarray) {
1695       ierr = (*x->ops->getarray)(x,a);CHKERRQ(ierr);
1696     } else SETERRQ1(PetscObjectComm((PetscObject)x),PETSC_ERR_SUP,"Cannot get array for vector type \"%s\"",((PetscObject)x)->type_name);
1697   }
1698   PetscFunctionReturn(0);
1699 }
1700 
1701 /*@C
1702    VecGetArrayInPlace_Internal - Like VecGetArray(), but if this is a CUDA vector and it is currently offloaded to GPU,
1703    the returned pointer will be a GPU pointer to the GPU memory that contains this processor's portion of the
1704    vector data. Otherwise, it functions as VecGetArray().
1705 
1706    Logically Collective on Vec
1707 
1708    Input Parameter:
1709 .  x - the vector
1710 
1711    Output Parameter:
1712 .  a - location to put pointer to the array
1713 
1714    Level: beginner
1715 
1716 .seealso: VecRestoreArrayInPlace(), VecRestoreArrayInPlace(), VecRestoreArray(), VecGetArrayRead(), VecGetArrays(), VecGetArrayF90(), VecGetArrayReadF90(),
1717           VecPlaceArray(), VecGetArray2d(), VecGetArrayPair(), VecRestoreArrayPair(), VecGetArrayWrite(), VecRestoreArrayWrite()
1718 @*/
1719 PetscErrorCode VecGetArrayInPlace(Vec x,PetscScalar **a)
1720 {
1721   PetscErrorCode ierr;
1722   PetscFunctionBegin;
1723   ierr = VecGetArrayInPlace_Internal(x,a,NULL);CHKERRQ(ierr);
1724   PetscFunctionReturn(0);
1725 }
1726 
1727 PetscErrorCode VecGetArrayInPlace_Internal(Vec x,PetscScalar **a,PetscMemType *mtype)
1728 {
1729   PetscErrorCode ierr;
1730 
1731   PetscFunctionBegin;
1732   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1733   ierr = VecSetErrorIfLocked(x,1);CHKERRQ(ierr);
1734   if (mtype) *mtype = PETSC_MEMTYPE_HOST;
1735 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
1736   if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {
1737     ierr = VecKokkosGetArrayInPlace_Internal(x,a,mtype);CHKERRQ(ierr);
1738     PetscFunctionReturn(0);
1739   }
1740 #endif
1741 
1742 #if defined(PETSC_HAVE_CUDA)
1743   if (x->petscnative && (x->offloadmask & PETSC_OFFLOAD_GPU)) { /* Prefer working on GPU when offloadmask is PETSC_OFFLOAD_BOTH */
1744     PetscBool is_cudatype = PETSC_FALSE;
1745     ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_cudatype,VECSEQCUDA,VECMPICUDA,VECCUDA,"");CHKERRQ(ierr);
1746     if (is_cudatype) {
1747       ierr = VecCUDAGetArray(x,a);CHKERRQ(ierr);
1748       x->offloadmask = PETSC_OFFLOAD_GPU; /* Change the mask once GPU gets write access, don't wait until restore array */
1749       if (mtype) *mtype = PETSC_MEMTYPE_DEVICE;
1750       PetscFunctionReturn(0);
1751     }
1752   }
1753 #endif
1754   ierr = VecGetArray(x,a);CHKERRQ(ierr);
1755   PetscFunctionReturn(0);
1756 }
1757 
1758 /*@C
1759    VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contains this
1760    processor's portion of the vector data. The values in this array are NOT valid, the routine calling this
1761    routine is responsible for putting values into the array; any values it does not set will be invalid
1762 
1763    Logically Collective on Vec
1764 
1765    Input Parameter:
1766 .  x - the vector
1767 
1768    Output Parameter:
1769 .  a - location to put pointer to the array
1770 
1771    Level: intermediate
1772 
1773    This is for vectors associate with GPUs, the vector is not copied up before giving access. If you need correct
1774    values in the array use VecGetArray()
1775 
1776    Concepts: vector^accessing local values
1777 
1778 .seealso: VecRestoreArray(), VecGetArrayRead(), VecGetArrays(), VecGetArrayF90(), VecGetArrayReadF90(), VecPlaceArray(), VecGetArray2d(),
1779           VecGetArrayPair(), VecRestoreArrayPair(), VecGetArray(), VecRestoreArrayWrite()
1780 @*/
1781 PetscErrorCode VecGetArrayWrite(Vec x,PetscScalar **a)
1782 {
1783   PetscErrorCode ierr;
1784 
1785   PetscFunctionBegin;
1786   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1787   ierr = VecSetErrorIfLocked(x,1);CHKERRQ(ierr);
1788   if (!x->ops->getarraywrite) {
1789     ierr = VecGetArray(x,a);CHKERRQ(ierr);
1790   } else {
1791     ierr = (*x->ops->getarraywrite)(x,a);CHKERRQ(ierr);
1792   }
1793   PetscFunctionReturn(0);
1794 }
1795 
1796 /*@C
1797    VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.
1798 
1799    Not Collective
1800 
1801    Input Parameters:
1802 .  x - the vector
1803 
1804    Output Parameter:
1805 .  a - the array
1806 
1807    Level: beginner
1808 
1809    Notes:
1810    The array must be returned using a matching call to VecRestoreArrayRead().
1811 
1812    Unlike VecGetArray(), this routine is not collective and preserves cached information like vector norms.
1813 
1814    Standard PETSc vectors use contiguous storage so that this routine does not perform a copy.  Other vector
1815    implementations may require a copy, but must such implementations should cache the contiguous representation so that
1816    only one copy is performed when this routine is called multiple times in sequence.
1817 
1818 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrayPair(), VecRestoreArrayPair()
1819 @*/
1820 PetscErrorCode VecGetArrayRead(Vec x,const PetscScalar **a)
1821 {
1822   PetscErrorCode ierr;
1823 #if defined(PETSC_HAVE_VIENNACL)
1824   PetscBool      is_viennacltype = PETSC_FALSE;
1825 #endif
1826 
1827   PetscFunctionBegin;
1828   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1829   if (x->petscnative) {
1830 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
1831     if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {
1832       ierr = VecKokkosSyncHost(x);CHKERRQ(ierr);
1833       *a   = *((PetscScalar **)x->data);
1834       PetscFunctionReturn(0);
1835     }
1836 #endif
1837 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
1838     if (x->offloadmask == PETSC_OFFLOAD_GPU) {
1839 #if defined(PETSC_HAVE_VIENNACL)
1840       ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_viennacltype,VECSEQVIENNACL,VECMPIVIENNACL,VECVIENNACL,"");CHKERRQ(ierr);
1841       if (is_viennacltype) {
1842         ierr = VecViennaCLCopyFromGPU(x);CHKERRQ(ierr);
1843       } else
1844 #endif
1845       {
1846 #if defined(PETSC_HAVE_CUDA)
1847         ierr = VecCUDACopyFromGPU(x);CHKERRQ(ierr);
1848 #endif
1849       }
1850     }
1851 #endif
1852     *a = *((PetscScalar **)x->data);
1853   } else if (x->ops->getarrayread) {
1854     ierr = (*x->ops->getarrayread)(x,a);CHKERRQ(ierr);
1855   } else {
1856     ierr = (*x->ops->getarray)(x,(PetscScalar**)a);CHKERRQ(ierr);
1857   }
1858   PetscFunctionReturn(0);
1859 }
1860 
1861 /*@C
1862    VecGetArrayReadInPlace - Like VecGetArrayRead(), but if this is a CUDA vector and it is currently offloaded to GPU,
1863    the returned pointer will be a GPU pointer to the GPU memory that contains this processor's portion of the
1864    vector data. Otherwise, it functions as VecGetArrayRead().
1865 
1866    Not Collective
1867 
1868    Input Parameters:
1869 .  x - the vector
1870 
1871    Output Parameter:
1872 .  a - the array
1873 
1874    Level: beginner
1875 
1876    Notes:
1877    The array must be returned using a matching call to VecRestoreArrayReadInPlace().
1878 
1879 
1880 .seealso: VecRestoreArrayReadInPlace(), VecGetArray(), VecRestoreArray(), VecGetArrayPair(), VecRestoreArrayPair(), VecGetArrayInPlace()
1881 @*/
1882 PetscErrorCode VecGetArrayReadInPlace(Vec x,const PetscScalar **a)
1883 {
1884   PetscErrorCode ierr;
1885   PetscFunctionBegin;
1886   ierr = VecGetArrayReadInPlace_Internal(x,a,NULL);CHKERRQ(ierr);
1887   PetscFunctionReturn(0);
1888 }
1889 
1890 PetscErrorCode VecGetArrayReadInPlace_Internal(Vec x,const PetscScalar **a,PetscMemType *mtype)
1891 {
1892   PetscErrorCode ierr;
1893 
1894   PetscFunctionBegin;
1895   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
1896   if (mtype) *mtype = PETSC_MEMTYPE_HOST;
1897 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
1898   if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {
1899     ierr = VecKokkosGetArrayReadInPlace_Internal(x,a,mtype);CHKERRQ(ierr);
1900     PetscFunctionReturn(0);
1901   }
1902 #endif
1903 
1904 #if defined(PETSC_HAVE_CUDA)
1905   if (x->petscnative && x->offloadmask & PETSC_OFFLOAD_GPU) {
1906     PetscBool is_cudatype = PETSC_FALSE;
1907     ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_cudatype,VECSEQCUDA,VECMPICUDA,VECCUDA,"");CHKERRQ(ierr);
1908     if (is_cudatype) {
1909       ierr = VecCUDAGetArrayRead(x,a);CHKERRQ(ierr);
1910       if (mtype) *mtype = PETSC_MEMTYPE_DEVICE;
1911       PetscFunctionReturn(0);
1912     }
1913   }
1914 #endif
1915   ierr = VecGetArrayRead(x,a);CHKERRQ(ierr);
1916   PetscFunctionReturn(0);
1917 }
1918 
1919 /*@C
1920    VecGetArrays - Returns a pointer to the arrays in a set of vectors
1921    that were created by a call to VecDuplicateVecs().  You MUST call
1922    VecRestoreArrays() when you no longer need access to the array.
1923 
1924    Logically Collective on Vec
1925 
1926    Input Parameter:
1927 +  x - the vectors
1928 -  n - the number of vectors
1929 
1930    Output Parameter:
1931 .  a - location to put pointer to the array
1932 
1933    Fortran Note:
1934    This routine is not supported in Fortran.
1935 
1936    Level: intermediate
1937 
1938 .seealso: VecGetArray(), VecRestoreArrays()
1939 @*/
1940 PetscErrorCode  VecGetArrays(const Vec x[],PetscInt n,PetscScalar **a[])
1941 {
1942   PetscErrorCode ierr;
1943   PetscInt       i;
1944   PetscScalar    **q;
1945 
1946   PetscFunctionBegin;
1947   PetscValidPointer(x,1);
1948   PetscValidHeaderSpecific(*x,VEC_CLASSID,1);
1949   PetscValidPointer(a,3);
1950   if (n <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must get at least one array n = %D",n);
1951   ierr = PetscMalloc1(n,&q);CHKERRQ(ierr);
1952   for (i=0; i<n; ++i) {
1953     ierr = VecGetArray(x[i],&q[i]);CHKERRQ(ierr);
1954   }
1955   *a = q;
1956   PetscFunctionReturn(0);
1957 }
1958 
1959 /*@C
1960    VecRestoreArrays - Restores a group of vectors after VecGetArrays()
1961    has been called.
1962 
1963    Logically Collective on Vec
1964 
1965    Input Parameters:
1966 +  x - the vector
1967 .  n - the number of vectors
1968 -  a - location of pointer to arrays obtained from VecGetArrays()
1969 
1970    Notes:
1971    For regular PETSc vectors this routine does not involve any copies. For
1972    any special vectors that do not store local vector data in a contiguous
1973    array, this routine will copy the data back into the underlying
1974    vector data structure from the arrays obtained with VecGetArrays().
1975 
1976    Fortran Note:
1977    This routine is not supported in Fortran.
1978 
1979    Level: intermediate
1980 
1981 .seealso: VecGetArrays(), VecRestoreArray()
1982 @*/
1983 PetscErrorCode  VecRestoreArrays(const Vec x[],PetscInt n,PetscScalar **a[])
1984 {
1985   PetscErrorCode ierr;
1986   PetscInt       i;
1987   PetscScalar    **q = *a;
1988 
1989   PetscFunctionBegin;
1990   PetscValidPointer(x,1);
1991   PetscValidHeaderSpecific(*x,VEC_CLASSID,1);
1992   PetscValidPointer(a,3);
1993 
1994   for (i=0; i<n; ++i) {
1995     ierr = VecRestoreArray(x[i],&q[i]);CHKERRQ(ierr);
1996   }
1997   ierr = PetscFree(q);CHKERRQ(ierr);
1998   PetscFunctionReturn(0);
1999 }
2000 
2001 /*@C
2002    VecRestoreArray - Restores a vector after VecGetArray() has been called.
2003 
2004    Logically Collective on Vec
2005 
2006    Input Parameters:
2007 +  x - the vector
2008 -  a - location of pointer to array obtained from VecGetArray()
2009 
2010    Level: beginner
2011 
2012 .seealso: VecGetArray(), VecRestoreArrayRead(), VecRestoreArrays(), VecRestoreArrayF90(), VecRestoreArrayReadF90(), VecPlaceArray(), VecRestoreArray2d(),
2013           VecGetArrayPair(), VecRestoreArrayPair()
2014 @*/
2015 PetscErrorCode VecRestoreArray(Vec x,PetscScalar **a)
2016 {
2017   PetscErrorCode ierr;
2018 
2019   PetscFunctionBegin;
2020   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2021   if (x->petscnative) {
2022    #if defined(PETSC_HAVE_KOKKOS_KERNELS)
2023     if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {ierr = VecKokkosModifyHost(x);CHKERRQ(ierr);}
2024     else
2025    #endif
2026     {
2027      #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2028       x->offloadmask = PETSC_OFFLOAD_CPU;
2029      #endif
2030     }
2031   } else {
2032     ierr = (*x->ops->restorearray)(x,a);CHKERRQ(ierr);
2033   }
2034   if (a) *a = NULL;
2035   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
2036   PetscFunctionReturn(0);
2037 }
2038 
2039 /*@C
2040    VecRestoreArrayInPlace - Restores a vector after VecGetArrayInPlace() has been called.
2041 
2042    Logically Collective on Vec
2043 
2044    Input Parameters:
2045 +  x - the vector
2046 -  a - location of pointer to array obtained from VecGetArrayInPlace()
2047 
2048    Level: beginner
2049 
2050 .seealso: VecGetArrayInPlace(), VecGetArray(), VecRestoreArrayRead(), VecRestoreArrays(), VecRestoreArrayF90(), VecRestoreArrayReadF90(),
2051           VecPlaceArray(), VecRestoreArray2d(), VecGetArrayPair(), VecRestoreArrayPair()
2052 @*/
2053 PetscErrorCode VecRestoreArrayInPlace(Vec x,PetscScalar **a)
2054 {
2055   PetscErrorCode ierr;
2056 
2057   PetscFunctionBegin;
2058   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2059 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
2060   if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {
2061     ierr = VecKokkosRestoreArrayInPlace(x,a);CHKERRQ(ierr);
2062     PetscFunctionReturn(0);
2063   }
2064 #endif
2065 
2066 #if defined(PETSC_HAVE_CUDA)
2067   if (x->petscnative && x->offloadmask == PETSC_OFFLOAD_GPU) {
2068     PetscBool is_cudatype = PETSC_FALSE;
2069     ierr = PetscObjectTypeCompareAny((PetscObject)x,&is_cudatype,VECSEQCUDA,VECMPICUDA,VECCUDA,"");CHKERRQ(ierr);
2070     if (is_cudatype) {
2071       ierr = VecCUDARestoreArray(x,a);CHKERRQ(ierr);
2072       PetscFunctionReturn(0);
2073     }
2074   }
2075 #endif
2076   ierr = VecRestoreArray(x,a);CHKERRQ(ierr);
2077   PetscFunctionReturn(0);
2078 }
2079 
2080 
2081 /*@C
2082    VecRestoreArrayWrite - Restores a vector after VecGetArrayWrite() has been called.
2083 
2084    Logically Collective on Vec
2085 
2086    Input Parameters:
2087 +  x - the vector
2088 -  a - location of pointer to array obtained from VecGetArray()
2089 
2090    Level: beginner
2091 
2092 .seealso: VecGetArray(), VecRestoreArrayRead(), VecRestoreArrays(), VecRestoreArrayF90(), VecRestoreArrayReadF90(), VecPlaceArray(), VecRestoreArray2d(),
2093           VecGetArrayPair(), VecRestoreArrayPair(), VecGetArrayWrite()
2094 @*/
2095 PetscErrorCode VecRestoreArrayWrite(Vec x,PetscScalar **a)
2096 {
2097   PetscErrorCode ierr;
2098 
2099   PetscFunctionBegin;
2100   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2101 
2102 #if defined(PETSC_HAVE_KOKKOS_KERNELS)
2103   if (x->offloadmask == PETSC_OFFLOAD_VECKOKKOS) {
2104     ierr = VecKokkosModifyHost(x);CHKERRQ(ierr);
2105   } else
2106 #endif
2107   if (x->petscnative) {
2108 #if defined(PETSC_HAVE_VIENNACL) || defined(PETSC_HAVE_CUDA)
2109     x->offloadmask = PETSC_OFFLOAD_CPU;
2110 #endif
2111   } else {
2112     if (x->ops->restorearraywrite) {
2113       ierr = (*x->ops->restorearraywrite)(x,a);CHKERRQ(ierr);
2114     } else {
2115       ierr = (*x->ops->restorearray)(x,a);CHKERRQ(ierr);
2116     }
2117   }
2118 
2119   if (a) *a = NULL;
2120   ierr = PetscObjectStateIncrease((PetscObject)x);CHKERRQ(ierr);
2121   PetscFunctionReturn(0);
2122 }
2123 
2124 /*@C
2125    VecRestoreArrayRead - Restore array obtained with VecGetArrayRead()
2126 
2127    Not Collective
2128 
2129    Input Parameters:
2130 +  vec - the vector
2131 -  array - the array
2132 
2133    Level: beginner
2134 
2135 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrayPair(), VecRestoreArrayPair()
2136 @*/
2137 PetscErrorCode VecRestoreArrayRead(Vec x,const PetscScalar **a)
2138 {
2139   PetscErrorCode ierr;
2140 
2141   PetscFunctionBegin;
2142   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2143   if (x->petscnative) {
2144     /* nothing */
2145   } else if (x->ops->restorearrayread) {
2146     ierr = (*x->ops->restorearrayread)(x,a);CHKERRQ(ierr);
2147   } else {
2148     ierr = (*x->ops->restorearray)(x,(PetscScalar**)a);CHKERRQ(ierr);
2149   }
2150   if (a) *a = NULL;
2151   PetscFunctionReturn(0);
2152 }
2153 
2154 /*@C
2155    VecRestoreArrayReadInPlace - Restore array obtained with VecGetArrayReadInPlace()
2156 
2157    Not Collective
2158 
2159    Input Parameters:
2160 +  vec - the vector
2161 -  array - the array
2162 
2163    Level: beginner
2164 
2165 .seealso: VecGetArrayReadInPlace(), VecRestoreArrayInPlace(), VecGetArray(), VecRestoreArray(), VecGetArrayPair(), VecRestoreArrayPair()
2166 @*/
2167 PetscErrorCode VecRestoreArrayReadInPlace(Vec x,const PetscScalar **a)
2168 {
2169   PetscErrorCode ierr;
2170 
2171   PetscFunctionBegin;
2172   ierr = VecRestoreArrayRead(x,a);CHKERRQ(ierr);
2173   PetscFunctionReturn(0);
2174 }
2175 
2176 /*@
2177    VecPlaceArray - Allows one to replace the array in a vector with an
2178    array provided by the user. This is useful to avoid copying an array
2179    into a vector.
2180 
2181    Not Collective
2182 
2183    Input Parameters:
2184 +  vec - the vector
2185 -  array - the array
2186 
2187    Notes:
2188    You can return to the original array with a call to VecResetArray()
2189 
2190    Level: developer
2191 
2192 .seealso: VecGetArray(), VecRestoreArray(), VecReplaceArray(), VecResetArray()
2193 
2194 @*/
2195 PetscErrorCode  VecPlaceArray(Vec vec,const PetscScalar array[])
2196 {
2197   PetscErrorCode ierr;
2198 
2199   PetscFunctionBegin;
2200   PetscValidHeaderSpecific(vec,VEC_CLASSID,1);
2201   PetscValidType(vec,1);
2202   if (array) PetscValidScalarPointer(array,2);
2203   if (vec->ops->placearray) {
2204     ierr = (*vec->ops->placearray)(vec,array);CHKERRQ(ierr);
2205   } else SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_SUP,"Cannot place array in this type of vector");
2206   ierr = PetscObjectStateIncrease((PetscObject)vec);CHKERRQ(ierr);
2207   PetscFunctionReturn(0);
2208 }
2209 
2210 /*@C
2211    VecReplaceArray - Allows one to replace the array in a vector with an
2212    array provided by the user. This is useful to avoid copying an array
2213    into a vector.
2214 
2215    Not Collective
2216 
2217    Input Parameters:
2218 +  vec - the vector
2219 -  array - the array
2220 
2221    Notes:
2222    This permanently replaces the array and frees the memory associated
2223    with the old array.
2224 
2225    The memory passed in MUST be obtained with PetscMalloc() and CANNOT be
2226    freed by the user. It will be freed when the vector is destroyed.
2227 
2228    Not supported from Fortran
2229 
2230    Level: developer
2231 
2232 .seealso: VecGetArray(), VecRestoreArray(), VecPlaceArray(), VecResetArray()
2233 
2234 @*/
2235 PetscErrorCode  VecReplaceArray(Vec vec,const PetscScalar array[])
2236 {
2237   PetscErrorCode ierr;
2238 
2239   PetscFunctionBegin;
2240   PetscValidHeaderSpecific(vec,VEC_CLASSID,1);
2241   PetscValidType(vec,1);
2242   if (vec->ops->replacearray) {
2243     ierr = (*vec->ops->replacearray)(vec,array);CHKERRQ(ierr);
2244   } else SETERRQ(PetscObjectComm((PetscObject)vec),PETSC_ERR_SUP,"Cannot replace array in this type of vector");
2245   ierr = PetscObjectStateIncrease((PetscObject)vec);CHKERRQ(ierr);
2246   PetscFunctionReturn(0);
2247 }
2248 
2249 
2250 /*@C
2251    VecCUDAGetArray - Provides access to the CUDA buffer inside a vector.
2252 
2253    This function has semantics similar to VecGetArray():  the pointer
2254    returned by this function points to a consistent view of the vector
2255    data.  This may involve a copy operation of data from the host to the
2256    device if the data on the device is out of date.  If the device
2257    memory hasn't been allocated previously it will be allocated as part
2258    of this function call.  VecCUDAGetArray() assumes that
2259    the user will modify the vector data.  This is similar to
2260    intent(inout) in fortran.
2261 
2262    The CUDA device pointer has to be released by calling
2263    VecCUDARestoreArray().  Upon restoring the vector data
2264    the data on the host will be marked as out of date.  A subsequent
2265    access of the host data will thus incur a data transfer from the
2266    device to the host.
2267 
2268 
2269    Input Parameter:
2270 .  v - the vector
2271 
2272    Output Parameter:
2273 .  a - the CUDA device pointer
2274 
2275    Fortran note:
2276    This function is not currently available from Fortran.
2277 
2278    Level: intermediate
2279 
2280 .seealso: VecCUDARestoreArray(), VecCUDAGetArrayRead(), VecCUDAGetArrayWrite(), VecGetArray(), VecGetArrayRead()
2281 @*/
2282 PETSC_EXTERN PetscErrorCode VecCUDAGetArray(Vec v, PetscScalar **a)
2283 {
2284 #if defined(PETSC_HAVE_CUDA)
2285   PetscErrorCode ierr;
2286 #endif
2287 
2288   PetscFunctionBegin;
2289   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2290 #if defined(PETSC_HAVE_CUDA)
2291   *a   = 0;
2292   ierr = VecCUDACopyToGPU(v);CHKERRQ(ierr);
2293   *a   = ((Vec_CUDA*)v->spptr)->GPUarray;
2294 #endif
2295   PetscFunctionReturn(0);
2296 }
2297 
2298 /*@C
2299    VecCUDARestoreArray - Restore a CUDA device pointer previously acquired with VecCUDAGetArray().
2300 
2301    This marks the host data as out of date.  Subsequent access to the
2302    vector data on the host side with for instance VecGetArray() incurs a
2303    data transfer.
2304 
2305    Input Parameter:
2306 +  v - the vector
2307 -  a - the CUDA device pointer.  This pointer is invalid after
2308        VecCUDARestoreArray() returns.
2309 
2310    Fortran note:
2311    This function is not currently available from Fortran.
2312 
2313    Level: intermediate
2314 
2315 .seealso: VecCUDAGetArray(), VecCUDAGetArrayRead(), VecCUDAGetArrayWrite(), VecGetArray(), VecRestoreArray(), VecGetArrayRead()
2316 @*/
2317 PETSC_EXTERN PetscErrorCode VecCUDARestoreArray(Vec v, PetscScalar **a)
2318 {
2319   PetscErrorCode ierr;
2320 
2321   PetscFunctionBegin;
2322   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2323 #if defined(PETSC_HAVE_CUDA)
2324   v->offloadmask = PETSC_OFFLOAD_GPU;
2325 #endif
2326 
2327   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
2328   PetscFunctionReturn(0);
2329 }
2330 
2331 /*@C
2332    VecCUDAGetArrayRead - Provides read access to the CUDA buffer inside a vector.
2333 
2334    This function is analogous to VecGetArrayRead():  The pointer
2335    returned by this function points to a consistent view of the vector
2336    data.  This may involve a copy operation of data from the host to the
2337    device if the data on the device is out of date.  If the device
2338    memory hasn't been allocated previously it will be allocated as part
2339    of this function call.  VecCUDAGetArrayRead() assumes that the
2340    user will not modify the vector data.  This is analgogous to
2341    intent(in) in Fortran.
2342 
2343    The CUDA device pointer has to be released by calling
2344    VecCUDARestoreArrayRead().  If the data on the host side was
2345    previously up to date it will remain so, i.e. data on both the device
2346    and the host is up to date.  Accessing data on the host side does not
2347    incur a device to host data transfer.
2348 
2349    Input Parameter:
2350 .  v - the vector
2351 
2352    Output Parameter:
2353 .  a - the CUDA pointer.
2354 
2355    Fortran note:
2356    This function is not currently available from Fortran.
2357 
2358    Level: intermediate
2359 
2360 .seealso: VecCUDARestoreArrayRead(), VecCUDAGetArray(), VecCUDAGetArrayWrite(), VecGetArray(), VecGetArrayRead()
2361 @*/
2362 PETSC_EXTERN PetscErrorCode VecCUDAGetArrayRead(Vec v, const PetscScalar **a)
2363 {
2364 #if defined(PETSC_HAVE_CUDA)
2365   PetscErrorCode ierr;
2366 #endif
2367 
2368   PetscFunctionBegin;
2369   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2370 #if defined(PETSC_HAVE_CUDA)
2371   *a   = 0;
2372   ierr = VecCUDACopyToGPU(v);CHKERRQ(ierr);
2373   *a   = ((Vec_CUDA*)v->spptr)->GPUarray;
2374 #endif
2375   PetscFunctionReturn(0);
2376 }
2377 
2378 /*@C
2379    VecCUDARestoreArrayRead - Restore a CUDA device pointer previously acquired with VecCUDAGetArrayRead().
2380 
2381    If the data on the host side was previously up to date it will remain
2382    so, i.e. data on both the device and the host is up to date.
2383    Accessing data on the host side e.g. with VecGetArray() does not
2384    incur a device to host data transfer.
2385 
2386    Input Parameter:
2387 +  v - the vector
2388 -  a - the CUDA device pointer.  This pointer is invalid after
2389        VecCUDARestoreArrayRead() returns.
2390 
2391    Fortran note:
2392    This function is not currently available from Fortran.
2393 
2394    Level: intermediate
2395 
2396 .seealso: VecCUDAGetArrayRead(), VecCUDAGetArrayWrite(), VecCUDAGetArray(), VecGetArray(), VecRestoreArray(), VecGetArrayRead()
2397 @*/
2398 PETSC_EXTERN PetscErrorCode VecCUDARestoreArrayRead(Vec v, const PetscScalar **a)
2399 {
2400   PetscFunctionBegin;
2401   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2402   *a = NULL;
2403   PetscFunctionReturn(0);
2404 }
2405 
2406 /*@C
2407    VecCUDAGetArrayWrite - Provides write access to the CUDA buffer inside a vector.
2408 
2409    The data pointed to by the device pointer is uninitialized.  The user
2410    may not read from this data.  Furthermore, the entire array needs to
2411    be filled by the user to obtain well-defined behaviour.  The device
2412    memory will be allocated by this function if it hasn't been allocated
2413    previously.  This is analogous to intent(out) in Fortran.
2414 
2415    The device pointer needs to be released with
2416    VecCUDARestoreArrayWrite().  When the pointer is released the
2417    host data of the vector is marked as out of data.  Subsequent access
2418    of the host data with e.g. VecGetArray() incurs a device to host data
2419    transfer.
2420 
2421 
2422    Input Parameter:
2423 .  v - the vector
2424 
2425    Output Parameter:
2426 .  a - the CUDA pointer
2427 
2428    Fortran note:
2429    This function is not currently available from Fortran.
2430 
2431    Level: advanced
2432 
2433 .seealso: VecCUDARestoreArrayWrite(), VecCUDAGetArray(), VecCUDAGetArrayRead(), VecCUDAGetArrayWrite(), VecGetArray(), VecGetArrayRead()
2434 @*/
2435 PETSC_EXTERN PetscErrorCode VecCUDAGetArrayWrite(Vec v, PetscScalar **a)
2436 {
2437 #if defined(PETSC_HAVE_CUDA)
2438   PetscErrorCode ierr;
2439 #endif
2440 
2441   PetscFunctionBegin;
2442   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2443 #if defined(PETSC_HAVE_CUDA)
2444   *a   = 0;
2445   ierr = VecCUDAAllocateCheck(v);CHKERRQ(ierr);
2446   *a   = ((Vec_CUDA*)v->spptr)->GPUarray;
2447 #endif
2448   PetscFunctionReturn(0);
2449 }
2450 
2451 /*@C
2452    VecCUDARestoreArrayWrite - Restore a CUDA device pointer previously acquired with VecCUDAGetArrayWrite().
2453 
2454    Data on the host will be marked as out of date.  Subsequent access of
2455    the data on the host side e.g. with VecGetArray() will incur a device
2456    to host data transfer.
2457 
2458    Input Parameter:
2459 +  v - the vector
2460 -  a - the CUDA device pointer.  This pointer is invalid after
2461        VecCUDARestoreArrayWrite() returns.
2462 
2463    Fortran note:
2464    This function is not currently available from Fortran.
2465 
2466    Level: intermediate
2467 
2468 .seealso: VecCUDAGetArrayWrite(), VecCUDAGetArray(), VecCUDAGetArrayRead(), VecCUDAGetArrayWrite(), VecGetArray(), VecRestoreArray(), VecGetArrayRead()
2469 @*/
2470 PETSC_EXTERN PetscErrorCode VecCUDARestoreArrayWrite(Vec v, PetscScalar **a)
2471 {
2472   PetscErrorCode ierr;
2473 
2474   PetscFunctionBegin;
2475   PetscCheckTypeNames(v,VECSEQCUDA,VECMPICUDA);
2476 #if defined(PETSC_HAVE_CUDA)
2477   v->offloadmask = PETSC_OFFLOAD_GPU;
2478 #endif
2479 
2480   ierr = PetscObjectStateIncrease((PetscObject)v);CHKERRQ(ierr);
2481   PetscFunctionReturn(0);
2482 }
2483 
2484 /*@C
2485    VecCUDAPlaceArray - Allows one to replace the GPU array in a vector with a
2486    GPU array provided by the user. This is useful to avoid copying an
2487    array into a vector.
2488 
2489    Not Collective
2490 
2491    Input Parameters:
2492 +  vec - the vector
2493 -  array - the GPU array
2494 
2495    Notes:
2496    You can return to the original GPU array with a call to VecCUDAResetArray()
2497    It is not possible to use VecCUDAPlaceArray() and VecPlaceArray() at the
2498    same time on the same vector.
2499 
2500    Level: developer
2501 
2502 .seealso: VecPlaceArray(), VecGetArray(), VecRestoreArray(), VecReplaceArray(), VecResetArray(), VecCUDAResetArray(), VecCUDAReplaceArray()
2503 
2504 @*/
2505 PetscErrorCode VecCUDAPlaceArray(Vec vin,const PetscScalar a[])
2506 {
2507   PetscErrorCode ierr;
2508 
2509   PetscFunctionBegin;
2510   PetscCheckTypeNames(vin,VECSEQCUDA,VECMPICUDA);
2511 #if defined(PETSC_HAVE_CUDA)
2512   ierr = VecCUDACopyToGPU(vin);CHKERRQ(ierr);
2513   if (((Vec_Seq*)vin->data)->unplacedarray) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"VecCUDAPlaceArray()/VecPlaceArray() was already called on this vector, without a call to VecCUDAResetArray()/VecResetArray()");
2514   ((Vec_Seq*)vin->data)->unplacedarray  = (PetscScalar *) ((Vec_CUDA*)vin->spptr)->GPUarray; /* save previous GPU array so reset can bring it back */
2515   ((Vec_CUDA*)vin->spptr)->GPUarray = (PetscScalar*)a;
2516   vin->offloadmask = PETSC_OFFLOAD_GPU;
2517 #endif
2518   ierr = PetscObjectStateIncrease((PetscObject)vin);CHKERRQ(ierr);
2519   PetscFunctionReturn(0);
2520 }
2521 
2522 /*@C
2523    VecCUDAReplaceArray - Allows one to replace the GPU array in a vector
2524    with a GPU array provided by the user. This is useful to avoid copying
2525    a GPU array into a vector.
2526 
2527    Not Collective
2528 
2529    Input Parameters:
2530 +  vec - the vector
2531 -  array - the GPU array
2532 
2533    Notes:
2534    This permanently replaces the GPU array and frees the memory associated
2535    with the old GPU array.
2536 
2537    The memory passed in CANNOT be freed by the user. It will be freed
2538    when the vector is destroyed.
2539 
2540    Not supported from Fortran
2541 
2542    Level: developer
2543 
2544 .seealso: VecGetArray(), VecRestoreArray(), VecPlaceArray(), VecResetArray(), VecCUDAResetArray(), VecCUDAPlaceArray(), VecReplaceArray()
2545 
2546 @*/
2547 PetscErrorCode VecCUDAReplaceArray(Vec vin,const PetscScalar a[])
2548 {
2549 #if defined(PETSC_HAVE_CUDA)
2550   cudaError_t err;
2551 #endif
2552   PetscErrorCode ierr;
2553 
2554   PetscFunctionBegin;
2555   PetscCheckTypeNames(vin,VECSEQCUDA,VECMPICUDA);
2556 #if defined(PETSC_HAVE_CUDA)
2557   err = cudaFree(((Vec_CUDA*)vin->spptr)->GPUarray);CHKERRCUDA(err);
2558   ((Vec_CUDA*)vin->spptr)->GPUarray = (PetscScalar*)a;
2559   vin->offloadmask = PETSC_OFFLOAD_GPU;
2560 #endif
2561   ierr = PetscObjectStateIncrease((PetscObject)vin);CHKERRQ(ierr);
2562   PetscFunctionReturn(0);
2563 }
2564 
2565 /*@C
2566    VecCUDAResetArray - Resets a vector to use its default memory. Call this
2567    after the use of VecCUDAPlaceArray().
2568 
2569    Not Collective
2570 
2571    Input Parameters:
2572 .  vec - the vector
2573 
2574    Level: developer
2575 
2576 .seealso: VecGetArray(), VecRestoreArray(), VecReplaceArray(), VecPlaceArray(), VecResetArray(), VecCUDAPlaceArray(), VecCUDAReplaceArray()
2577 
2578 @*/
2579 PetscErrorCode VecCUDAResetArray(Vec vin)
2580 {
2581   PetscErrorCode ierr;
2582 
2583   PetscFunctionBegin;
2584   PetscCheckTypeNames(vin,VECSEQCUDA,VECMPICUDA);
2585 #if defined(PETSC_HAVE_CUDA)
2586   ierr = VecCUDACopyToGPU(vin);CHKERRQ(ierr);
2587   ((Vec_CUDA*)vin->spptr)->GPUarray = (PetscScalar *) ((Vec_Seq*)vin->data)->unplacedarray;
2588   ((Vec_Seq*)vin->data)->unplacedarray = 0;
2589   vin->offloadmask = PETSC_OFFLOAD_GPU;
2590 #endif
2591   ierr = PetscObjectStateIncrease((PetscObject)vin);CHKERRQ(ierr);
2592   PetscFunctionReturn(0);
2593 }
2594 
2595 /*MC
2596     VecDuplicateVecsF90 - Creates several vectors of the same type as an existing vector
2597     and makes them accessible via a Fortran90 pointer.
2598 
2599     Synopsis:
2600     VecDuplicateVecsF90(Vec x,PetscInt n,{Vec, pointer :: y(:)},integer ierr)
2601 
2602     Collective on Vec
2603 
2604     Input Parameters:
2605 +   x - a vector to mimic
2606 -   n - the number of vectors to obtain
2607 
2608     Output Parameters:
2609 +   y - Fortran90 pointer to the array of vectors
2610 -   ierr - error code
2611 
2612     Example of Usage:
2613 .vb
2614 #include <petsc/finclude/petscvec.h>
2615     use petscvec
2616 
2617     Vec x
2618     Vec, pointer :: y(:)
2619     ....
2620     call VecDuplicateVecsF90(x,2,y,ierr)
2621     call VecSet(y(2),alpha,ierr)
2622     call VecSet(y(2),alpha,ierr)
2623     ....
2624     call VecDestroyVecsF90(2,y,ierr)
2625 .ve
2626 
2627     Notes:
2628     Not yet supported for all F90 compilers
2629 
2630     Use VecDestroyVecsF90() to free the space.
2631 
2632     Level: beginner
2633 
2634 .seealso:  VecDestroyVecsF90(), VecDuplicateVecs()
2635 
2636 M*/
2637 
2638 /*MC
2639     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
2640     VecGetArrayF90().
2641 
2642     Synopsis:
2643     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)
2644 
2645     Logically Collective on Vec
2646 
2647     Input Parameters:
2648 +   x - vector
2649 -   xx_v - the Fortran90 pointer to the array
2650 
2651     Output Parameter:
2652 .   ierr - error code
2653 
2654     Example of Usage:
2655 .vb
2656 #include <petsc/finclude/petscvec.h>
2657     use petscvec
2658 
2659     PetscScalar, pointer :: xx_v(:)
2660     ....
2661     call VecGetArrayF90(x,xx_v,ierr)
2662     xx_v(3) = a
2663     call VecRestoreArrayF90(x,xx_v,ierr)
2664 .ve
2665 
2666     Level: beginner
2667 
2668 .seealso:  VecGetArrayF90(), VecGetArray(), VecRestoreArray(), UsingFortran, VecRestoreArrayReadF90()
2669 
2670 M*/
2671 
2672 /*MC
2673     VecDestroyVecsF90 - Frees a block of vectors obtained with VecDuplicateVecsF90().
2674 
2675     Synopsis:
2676     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)
2677 
2678     Collective on Vec
2679 
2680     Input Parameters:
2681 +   n - the number of vectors previously obtained
2682 -   x - pointer to array of vector pointers
2683 
2684     Output Parameter:
2685 .   ierr - error code
2686 
2687     Notes:
2688     Not yet supported for all F90 compilers
2689 
2690     Level: beginner
2691 
2692 .seealso:  VecDestroyVecs(), VecDuplicateVecsF90()
2693 
2694 M*/
2695 
2696 /*MC
2697     VecGetArrayF90 - Accesses a vector array from Fortran90. For default PETSc
2698     vectors, VecGetArrayF90() returns a pointer to the local data array. Otherwise,
2699     this routine is implementation dependent. You MUST call VecRestoreArrayF90()
2700     when you no longer need access to the array.
2701 
2702     Synopsis:
2703     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)
2704 
2705     Logically Collective on Vec
2706 
2707     Input Parameter:
2708 .   x - vector
2709 
2710     Output Parameters:
2711 +   xx_v - the Fortran90 pointer to the array
2712 -   ierr - error code
2713 
2714     Example of Usage:
2715 .vb
2716 #include <petsc/finclude/petscvec.h>
2717     use petscvec
2718 
2719     PetscScalar, pointer :: xx_v(:)
2720     ....
2721     call VecGetArrayF90(x,xx_v,ierr)
2722     xx_v(3) = a
2723     call VecRestoreArrayF90(x,xx_v,ierr)
2724 .ve
2725 
2726     If you ONLY intend to read entries from the array and not change any entries you should use VecGetArrayReadF90().
2727 
2728     Level: beginner
2729 
2730 .seealso:  VecRestoreArrayF90(), VecGetArray(), VecRestoreArray(), VecGetArrayReadF90(), UsingFortran
2731 
2732 M*/
2733 
2734  /*MC
2735     VecGetArrayReadF90 - Accesses a read only array from Fortran90. For default PETSc
2736     vectors, VecGetArrayF90() returns a pointer to the local data array. Otherwise,
2737     this routine is implementation dependent. You MUST call VecRestoreArrayReadF90()
2738     when you no longer need access to the array.
2739 
2740     Synopsis:
2741     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)
2742 
2743     Logically Collective on Vec
2744 
2745     Input Parameter:
2746 .   x - vector
2747 
2748     Output Parameters:
2749 +   xx_v - the Fortran90 pointer to the array
2750 -   ierr - error code
2751 
2752     Example of Usage:
2753 .vb
2754 #include <petsc/finclude/petscvec.h>
2755     use petscvec
2756 
2757     PetscScalar, pointer :: xx_v(:)
2758     ....
2759     call VecGetArrayReadF90(x,xx_v,ierr)
2760     a = xx_v(3)
2761     call VecRestoreArrayReadF90(x,xx_v,ierr)
2762 .ve
2763 
2764     If you intend to write entries into the array you must use VecGetArrayF90().
2765 
2766     Level: beginner
2767 
2768 .seealso:  VecRestoreArrayReadF90(), VecGetArray(), VecRestoreArray(), VecGetArrayRead(), VecRestoreArrayRead(), VecGetArrayF90(), UsingFortran
2769 
2770 M*/
2771 
2772 /*MC
2773     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
2774     VecGetArrayReadF90().
2775 
2776     Synopsis:
2777     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)
2778 
2779     Logically Collective on Vec
2780 
2781     Input Parameters:
2782 +   x - vector
2783 -   xx_v - the Fortran90 pointer to the array
2784 
2785     Output Parameter:
2786 .   ierr - error code
2787 
2788     Example of Usage:
2789 .vb
2790 #include <petsc/finclude/petscvec.h>
2791     use petscvec
2792 
2793     PetscScalar, pointer :: xx_v(:)
2794     ....
2795     call VecGetArrayReadF90(x,xx_v,ierr)
2796     a = xx_v(3)
2797     call VecRestoreArrayReadF90(x,xx_v,ierr)
2798 .ve
2799 
2800     Level: beginner
2801 
2802 .seealso:  VecGetArrayReadF90(), VecGetArray(), VecRestoreArray(), VecGetArrayRead(), VecRestoreArrayRead(),UsingFortran, VecRestoreArrayF90()
2803 
2804 M*/
2805 
2806 /*@C
2807    VecGetArray2d - Returns a pointer to a 2d contiguous array that contains this
2808    processor's portion of the vector data.  You MUST call VecRestoreArray2d()
2809    when you no longer need access to the array.
2810 
2811    Logically Collective
2812 
2813    Input Parameter:
2814 +  x - the vector
2815 .  m - first dimension of two dimensional array
2816 .  n - second dimension of two dimensional array
2817 .  mstart - first index you will use in first coordinate direction (often 0)
2818 -  nstart - first index in the second coordinate direction (often 0)
2819 
2820    Output Parameter:
2821 .  a - location to put pointer to the array
2822 
2823    Level: developer
2824 
2825   Notes:
2826    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
2827    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
2828    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
2829    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().
2830 
2831    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2832 
2833 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
2834           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
2835           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
2836 @*/
2837 PetscErrorCode  VecGetArray2d(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
2838 {
2839   PetscErrorCode ierr;
2840   PetscInt       i,N;
2841   PetscScalar    *aa;
2842 
2843   PetscFunctionBegin;
2844   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2845   PetscValidPointer(a,6);
2846   PetscValidType(x,1);
2847   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
2848   if (m*n != N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 2d array dimensions %D by %D",N,m,n);
2849   ierr = VecGetArray(x,&aa);CHKERRQ(ierr);
2850 
2851   ierr = PetscMalloc1(m,a);CHKERRQ(ierr);
2852   for (i=0; i<m; i++) (*a)[i] = aa + i*n - nstart;
2853   *a -= mstart;
2854   PetscFunctionReturn(0);
2855 }
2856 
2857 /*@C
2858    VecGetArray2dWrite - Returns a pointer to a 2d contiguous array that will contain this
2859    processor's portion of the vector data.  You MUST call VecRestoreArray2dWrite()
2860    when you no longer need access to the array.
2861 
2862    Logically Collective
2863 
2864    Input Parameter:
2865 +  x - the vector
2866 .  m - first dimension of two dimensional array
2867 .  n - second dimension of two dimensional array
2868 .  mstart - first index you will use in first coordinate direction (often 0)
2869 -  nstart - first index in the second coordinate direction (often 0)
2870 
2871    Output Parameter:
2872 .  a - location to put pointer to the array
2873 
2874    Level: developer
2875 
2876   Notes:
2877    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
2878    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
2879    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
2880    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().
2881 
2882    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
2883 
2884    Concepts: vector^accessing local values as 2d array
2885 
2886 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
2887           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
2888           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
2889 @*/
2890 PetscErrorCode  VecGetArray2dWrite(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
2891 {
2892   PetscErrorCode ierr;
2893   PetscInt       i,N;
2894   PetscScalar    *aa;
2895 
2896   PetscFunctionBegin;
2897   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2898   PetscValidPointer(a,6);
2899   PetscValidType(x,1);
2900   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
2901   if (m*n != N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 2d array dimensions %D by %D",N,m,n);
2902   ierr = VecGetArrayWrite(x,&aa);CHKERRQ(ierr);
2903 
2904   ierr = PetscMalloc1(m,a);CHKERRQ(ierr);
2905   for (i=0; i<m; i++) (*a)[i] = aa + i*n - nstart;
2906   *a -= mstart;
2907   PetscFunctionReturn(0);
2908 }
2909 
2910 /*@C
2911    VecRestoreArray2d - Restores a vector after VecGetArray2d() has been called.
2912 
2913    Logically Collective
2914 
2915    Input Parameters:
2916 +  x - the vector
2917 .  m - first dimension of two dimensional array
2918 .  n - second dimension of the two dimensional array
2919 .  mstart - first index you will use in first coordinate direction (often 0)
2920 .  nstart - first index in the second coordinate direction (often 0)
2921 -  a - location of pointer to array obtained from VecGetArray2d()
2922 
2923    Level: developer
2924 
2925    Notes:
2926    For regular PETSc vectors this routine does not involve any copies. For
2927    any special vectors that do not store local vector data in a contiguous
2928    array, this routine will copy the data back into the underlying
2929    vector data structure from the array obtained with VecGetArray().
2930 
2931    This routine actually zeros out the a pointer.
2932 
2933 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
2934           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
2935           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
2936 @*/
2937 PetscErrorCode  VecRestoreArray2d(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
2938 {
2939   PetscErrorCode ierr;
2940   void           *dummy;
2941 
2942   PetscFunctionBegin;
2943   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2944   PetscValidPointer(a,6);
2945   PetscValidType(x,1);
2946   dummy = (void*)(*a + mstart);
2947   ierr  = PetscFree(dummy);CHKERRQ(ierr);
2948   ierr  = VecRestoreArray(x,NULL);CHKERRQ(ierr);
2949   PetscFunctionReturn(0);
2950 }
2951 
2952 /*@C
2953    VecRestoreArray2dWrite - Restores a vector after VecGetArray2dWrite() has been called.
2954 
2955    Logically Collective
2956 
2957    Input Parameters:
2958 +  x - the vector
2959 .  m - first dimension of two dimensional array
2960 .  n - second dimension of the two dimensional array
2961 .  mstart - first index you will use in first coordinate direction (often 0)
2962 .  nstart - first index in the second coordinate direction (often 0)
2963 -  a - location of pointer to array obtained from VecGetArray2d()
2964 
2965    Level: developer
2966 
2967    Notes:
2968    For regular PETSc vectors this routine does not involve any copies. For
2969    any special vectors that do not store local vector data in a contiguous
2970    array, this routine will copy the data back into the underlying
2971    vector data structure from the array obtained with VecGetArray().
2972 
2973    This routine actually zeros out the a pointer.
2974 
2975 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
2976           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
2977           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
2978 @*/
2979 PetscErrorCode  VecRestoreArray2dWrite(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
2980 {
2981   PetscErrorCode ierr;
2982   void           *dummy;
2983 
2984   PetscFunctionBegin;
2985   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
2986   PetscValidPointer(a,6);
2987   PetscValidType(x,1);
2988   dummy = (void*)(*a + mstart);
2989   ierr  = PetscFree(dummy);CHKERRQ(ierr);
2990   ierr  = VecRestoreArrayWrite(x,NULL);CHKERRQ(ierr);
2991   PetscFunctionReturn(0);
2992 }
2993 
2994 /*@C
2995    VecGetArray1d - Returns a pointer to a 1d contiguous array that contains this
2996    processor's portion of the vector data.  You MUST call VecRestoreArray1d()
2997    when you no longer need access to the array.
2998 
2999    Logically Collective
3000 
3001    Input Parameter:
3002 +  x - the vector
3003 .  m - first dimension of two dimensional array
3004 -  mstart - first index you will use in first coordinate direction (often 0)
3005 
3006    Output Parameter:
3007 .  a - location to put pointer to the array
3008 
3009    Level: developer
3010 
3011   Notes:
3012    For a vector obtained from DMCreateLocalVector() mstart are likely
3013    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3014    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().
3015 
3016    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3017 
3018 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3019           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3020           VecGetArray2d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3021 @*/
3022 PetscErrorCode  VecGetArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3023 {
3024   PetscErrorCode ierr;
3025   PetscInt       N;
3026 
3027   PetscFunctionBegin;
3028   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3029   PetscValidPointer(a,4);
3030   PetscValidType(x,1);
3031   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3032   if (m != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local array size %D does not match 1d array dimensions %D",N,m);
3033   ierr = VecGetArray(x,a);CHKERRQ(ierr);
3034   *a  -= mstart;
3035   PetscFunctionReturn(0);
3036 }
3037 
3038  /*@C
3039    VecGetArray1dWrite - Returns a pointer to a 1d contiguous array that will contain this
3040    processor's portion of the vector data.  You MUST call VecRestoreArray1dWrite()
3041    when you no longer need access to the array.
3042 
3043    Logically Collective
3044 
3045    Input Parameter:
3046 +  x - the vector
3047 .  m - first dimension of two dimensional array
3048 -  mstart - first index you will use in first coordinate direction (often 0)
3049 
3050    Output Parameter:
3051 .  a - location to put pointer to the array
3052 
3053    Level: developer
3054 
3055   Notes:
3056    For a vector obtained from DMCreateLocalVector() mstart are likely
3057    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3058    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().
3059 
3060    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3061 
3062 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3063           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3064           VecGetArray2d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3065 @*/
3066 PetscErrorCode  VecGetArray1dWrite(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3067 {
3068   PetscErrorCode ierr;
3069   PetscInt       N;
3070 
3071   PetscFunctionBegin;
3072   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3073   PetscValidPointer(a,4);
3074   PetscValidType(x,1);
3075   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3076   if (m != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local array size %D does not match 1d array dimensions %D",N,m);
3077   ierr = VecGetArrayWrite(x,a);CHKERRQ(ierr);
3078   *a  -= mstart;
3079   PetscFunctionReturn(0);
3080 }
3081 
3082 /*@C
3083    VecRestoreArray1d - Restores a vector after VecGetArray1d() has been called.
3084 
3085    Logically Collective
3086 
3087    Input Parameters:
3088 +  x - the vector
3089 .  m - first dimension of two dimensional array
3090 .  mstart - first index you will use in first coordinate direction (often 0)
3091 -  a - location of pointer to array obtained from VecGetArray21()
3092 
3093    Level: developer
3094 
3095    Notes:
3096    For regular PETSc vectors this routine does not involve any copies. For
3097    any special vectors that do not store local vector data in a contiguous
3098    array, this routine will copy the data back into the underlying
3099    vector data structure from the array obtained with VecGetArray1d().
3100 
3101    This routine actually zeros out the a pointer.
3102 
3103 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3104           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3105           VecGetArray1d(), VecRestoreArray2d(), VecGetArray4d(), VecRestoreArray4d()
3106 @*/
3107 PetscErrorCode  VecRestoreArray1d(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3108 {
3109   PetscErrorCode ierr;
3110 
3111   PetscFunctionBegin;
3112   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3113   PetscValidType(x,1);
3114   ierr = VecRestoreArray(x,NULL);CHKERRQ(ierr);
3115   PetscFunctionReturn(0);
3116 }
3117 
3118 /*@C
3119    VecRestoreArray1dWrite - Restores a vector after VecGetArray1dWrite() has been called.
3120 
3121    Logically Collective
3122 
3123    Input Parameters:
3124 +  x - the vector
3125 .  m - first dimension of two dimensional array
3126 .  mstart - first index you will use in first coordinate direction (often 0)
3127 -  a - location of pointer to array obtained from VecGetArray21()
3128 
3129    Level: developer
3130 
3131    Notes:
3132    For regular PETSc vectors this routine does not involve any copies. For
3133    any special vectors that do not store local vector data in a contiguous
3134    array, this routine will copy the data back into the underlying
3135    vector data structure from the array obtained with VecGetArray1d().
3136 
3137    This routine actually zeros out the a pointer.
3138 
3139    Concepts: vector^accessing local values as 1d array
3140 
3141 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3142           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3143           VecGetArray1d(), VecRestoreArray2d(), VecGetArray4d(), VecRestoreArray4d()
3144 @*/
3145 PetscErrorCode  VecRestoreArray1dWrite(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3146 {
3147   PetscErrorCode ierr;
3148 
3149   PetscFunctionBegin;
3150   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3151   PetscValidType(x,1);
3152   ierr = VecRestoreArrayWrite(x,NULL);CHKERRQ(ierr);
3153   PetscFunctionReturn(0);
3154 }
3155 
3156 /*@C
3157    VecGetArray3d - Returns a pointer to a 3d contiguous array that contains this
3158    processor's portion of the vector data.  You MUST call VecRestoreArray3d()
3159    when you no longer need access to the array.
3160 
3161    Logically Collective
3162 
3163    Input Parameter:
3164 +  x - the vector
3165 .  m - first dimension of three dimensional array
3166 .  n - second dimension of three dimensional array
3167 .  p - third dimension of three dimensional array
3168 .  mstart - first index you will use in first coordinate direction (often 0)
3169 .  nstart - first index in the second coordinate direction (often 0)
3170 -  pstart - first index in the third coordinate direction (often 0)
3171 
3172    Output Parameter:
3173 .  a - location to put pointer to the array
3174 
3175    Level: developer
3176 
3177   Notes:
3178    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3179    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3180    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3181    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().
3182 
3183    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3184 
3185 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3186           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3187           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3188 @*/
3189 PetscErrorCode  VecGetArray3d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3190 {
3191   PetscErrorCode ierr;
3192   PetscInt       i,N,j;
3193   PetscScalar    *aa,**b;
3194 
3195   PetscFunctionBegin;
3196   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3197   PetscValidPointer(a,8);
3198   PetscValidType(x,1);
3199   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3200   if (m*n*p != N) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 3d array dimensions %D by %D by %D",N,m,n,p);
3201   ierr = VecGetArray(x,&aa);CHKERRQ(ierr);
3202 
3203   ierr = PetscMalloc1(m*sizeof(PetscScalar**)+m*n,a);CHKERRQ(ierr);
3204   b    = (PetscScalar**)((*a) + m);
3205   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3206   for (i=0; i<m; i++)
3207     for (j=0; j<n; j++)
3208       b[i*n+j] = aa + i*n*p + j*p - pstart;
3209 
3210   *a -= mstart;
3211   PetscFunctionReturn(0);
3212 }
3213 
3214 /*@C
3215    VecGetArray3dWrite - Returns a pointer to a 3d contiguous array that will contain this
3216    processor's portion of the vector data.  You MUST call VecRestoreArray3dWrite()
3217    when you no longer need access to the array.
3218 
3219    Logically Collective
3220 
3221    Input Parameter:
3222 +  x - the vector
3223 .  m - first dimension of three dimensional array
3224 .  n - second dimension of three dimensional array
3225 .  p - third dimension of three dimensional array
3226 .  mstart - first index you will use in first coordinate direction (often 0)
3227 .  nstart - first index in the second coordinate direction (often 0)
3228 -  pstart - first index in the third coordinate direction (often 0)
3229 
3230    Output Parameter:
3231 .  a - location to put pointer to the array
3232 
3233    Level: developer
3234 
3235   Notes:
3236    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3237    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3238    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3239    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().
3240 
3241    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3242 
3243    Concepts: vector^accessing local values as 3d array
3244 
3245 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3246           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3247           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3248 @*/
3249 PetscErrorCode  VecGetArray3dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3250 {
3251   PetscErrorCode ierr;
3252   PetscInt       i,N,j;
3253   PetscScalar    *aa,**b;
3254 
3255   PetscFunctionBegin;
3256   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3257   PetscValidPointer(a,8);
3258   PetscValidType(x,1);
3259   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3260   if (m*n*p != N) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 3d array dimensions %D by %D by %D",N,m,n,p);
3261   ierr = VecGetArrayWrite(x,&aa);CHKERRQ(ierr);
3262 
3263   ierr = PetscMalloc1(m*sizeof(PetscScalar**)+m*n,a);CHKERRQ(ierr);
3264   b    = (PetscScalar**)((*a) + m);
3265   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3266   for (i=0; i<m; i++)
3267     for (j=0; j<n; j++)
3268       b[i*n+j] = aa + i*n*p + j*p - pstart;
3269 
3270   *a -= mstart;
3271   PetscFunctionReturn(0);
3272 }
3273 
3274 /*@C
3275    VecRestoreArray3d - Restores a vector after VecGetArray3d() has been called.
3276 
3277    Logically Collective
3278 
3279    Input Parameters:
3280 +  x - the vector
3281 .  m - first dimension of three dimensional array
3282 .  n - second dimension of the three dimensional array
3283 .  p - third dimension of the three dimensional array
3284 .  mstart - first index you will use in first coordinate direction (often 0)
3285 .  nstart - first index in the second coordinate direction (often 0)
3286 .  pstart - first index in the third coordinate direction (often 0)
3287 -  a - location of pointer to array obtained from VecGetArray3d()
3288 
3289    Level: developer
3290 
3291    Notes:
3292    For regular PETSc vectors this routine does not involve any copies. For
3293    any special vectors that do not store local vector data in a contiguous
3294    array, this routine will copy the data back into the underlying
3295    vector data structure from the array obtained with VecGetArray().
3296 
3297    This routine actually zeros out the a pointer.
3298 
3299 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3300           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3301           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3302 @*/
3303 PetscErrorCode  VecRestoreArray3d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3304 {
3305   PetscErrorCode ierr;
3306   void           *dummy;
3307 
3308   PetscFunctionBegin;
3309   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3310   PetscValidPointer(a,8);
3311   PetscValidType(x,1);
3312   dummy = (void*)(*a + mstart);
3313   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3314   ierr  = VecRestoreArray(x,NULL);CHKERRQ(ierr);
3315   PetscFunctionReturn(0);
3316 }
3317 
3318 /*@C
3319    VecRestoreArray3dWrite - Restores a vector after VecGetArray3dWrite() has been called.
3320 
3321    Logically Collective
3322 
3323    Input Parameters:
3324 +  x - the vector
3325 .  m - first dimension of three dimensional array
3326 .  n - second dimension of the three dimensional array
3327 .  p - third dimension of the three dimensional array
3328 .  mstart - first index you will use in first coordinate direction (often 0)
3329 .  nstart - first index in the second coordinate direction (often 0)
3330 .  pstart - first index in the third coordinate direction (often 0)
3331 -  a - location of pointer to array obtained from VecGetArray3d()
3332 
3333    Level: developer
3334 
3335    Notes:
3336    For regular PETSc vectors this routine does not involve any copies. For
3337    any special vectors that do not store local vector data in a contiguous
3338    array, this routine will copy the data back into the underlying
3339    vector data structure from the array obtained with VecGetArray().
3340 
3341    This routine actually zeros out the a pointer.
3342 
3343 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3344           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3345           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3346 @*/
3347 PetscErrorCode  VecRestoreArray3dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3348 {
3349   PetscErrorCode ierr;
3350   void           *dummy;
3351 
3352   PetscFunctionBegin;
3353   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3354   PetscValidPointer(a,8);
3355   PetscValidType(x,1);
3356   dummy = (void*)(*a + mstart);
3357   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3358   ierr  = VecRestoreArrayWrite(x,NULL);CHKERRQ(ierr);
3359   PetscFunctionReturn(0);
3360 }
3361 
3362 /*@C
3363    VecGetArray4d - Returns a pointer to a 4d contiguous array that contains this
3364    processor's portion of the vector data.  You MUST call VecRestoreArray4d()
3365    when you no longer need access to the array.
3366 
3367    Logically Collective
3368 
3369    Input Parameter:
3370 +  x - the vector
3371 .  m - first dimension of four dimensional array
3372 .  n - second dimension of four dimensional array
3373 .  p - third dimension of four dimensional array
3374 .  q - fourth dimension of four dimensional array
3375 .  mstart - first index you will use in first coordinate direction (often 0)
3376 .  nstart - first index in the second coordinate direction (often 0)
3377 .  pstart - first index in the third coordinate direction (often 0)
3378 -  qstart - first index in the fourth coordinate direction (often 0)
3379 
3380    Output Parameter:
3381 .  a - location to put pointer to the array
3382 
3383    Level: beginner
3384 
3385   Notes:
3386    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3387    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3388    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3389    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().
3390 
3391    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3392 
3393 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3394           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3395           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3396 @*/
3397 PetscErrorCode  VecGetArray4d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3398 {
3399   PetscErrorCode ierr;
3400   PetscInt       i,N,j,k;
3401   PetscScalar    *aa,***b,**c;
3402 
3403   PetscFunctionBegin;
3404   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3405   PetscValidPointer(a,10);
3406   PetscValidType(x,1);
3407   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3408   if (m*n*p*q != N) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 4d array dimensions %D by %D by %D by %D",N,m,n,p,q);
3409   ierr = VecGetArray(x,&aa);CHKERRQ(ierr);
3410 
3411   ierr = PetscMalloc1(m*sizeof(PetscScalar***)+m*n*sizeof(PetscScalar**)+m*n*p,a);CHKERRQ(ierr);
3412   b    = (PetscScalar***)((*a) + m);
3413   c    = (PetscScalar**)(b + m*n);
3414   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3415   for (i=0; i<m; i++)
3416     for (j=0; j<n; j++)
3417       b[i*n+j] = c + i*n*p + j*p - pstart;
3418   for (i=0; i<m; i++)
3419     for (j=0; j<n; j++)
3420       for (k=0; k<p; k++)
3421         c[i*n*p+j*p+k] = aa + i*n*p*q + j*p*q + k*q - qstart;
3422   *a -= mstart;
3423   PetscFunctionReturn(0);
3424 }
3425 
3426 /*@C
3427    VecGetArray4dWrite - Returns a pointer to a 4d contiguous array that will contain this
3428    processor's portion of the vector data.  You MUST call VecRestoreArray4dWrite()
3429    when you no longer need access to the array.
3430 
3431    Logically Collective
3432 
3433    Input Parameter:
3434 +  x - the vector
3435 .  m - first dimension of four dimensional array
3436 .  n - second dimension of four dimensional array
3437 .  p - third dimension of four dimensional array
3438 .  q - fourth dimension of four dimensional array
3439 .  mstart - first index you will use in first coordinate direction (often 0)
3440 .  nstart - first index in the second coordinate direction (often 0)
3441 .  pstart - first index in the third coordinate direction (often 0)
3442 -  qstart - first index in the fourth coordinate direction (often 0)
3443 
3444    Output Parameter:
3445 .  a - location to put pointer to the array
3446 
3447    Level: beginner
3448 
3449   Notes:
3450    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3451    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3452    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3453    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().
3454 
3455    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3456 
3457    Concepts: vector^accessing local values as 3d array
3458 
3459 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3460           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3461           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3462 @*/
3463 PetscErrorCode  VecGetArray4dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3464 {
3465   PetscErrorCode ierr;
3466   PetscInt       i,N,j,k;
3467   PetscScalar    *aa,***b,**c;
3468 
3469   PetscFunctionBegin;
3470   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3471   PetscValidPointer(a,10);
3472   PetscValidType(x,1);
3473   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3474   if (m*n*p*q != N) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 4d array dimensions %D by %D by %D by %D",N,m,n,p,q);
3475   ierr = VecGetArrayWrite(x,&aa);CHKERRQ(ierr);
3476 
3477   ierr = PetscMalloc1(m*sizeof(PetscScalar***)+m*n*sizeof(PetscScalar**)+m*n*p,a);CHKERRQ(ierr);
3478   b    = (PetscScalar***)((*a) + m);
3479   c    = (PetscScalar**)(b + m*n);
3480   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3481   for (i=0; i<m; i++)
3482     for (j=0; j<n; j++)
3483       b[i*n+j] = c + i*n*p + j*p - pstart;
3484   for (i=0; i<m; i++)
3485     for (j=0; j<n; j++)
3486       for (k=0; k<p; k++)
3487         c[i*n*p+j*p+k] = aa + i*n*p*q + j*p*q + k*q - qstart;
3488   *a -= mstart;
3489   PetscFunctionReturn(0);
3490 }
3491 
3492 /*@C
3493    VecRestoreArray4d - Restores a vector after VecGetArray3d() has been called.
3494 
3495    Logically Collective
3496 
3497    Input Parameters:
3498 +  x - the vector
3499 .  m - first dimension of four dimensional array
3500 .  n - second dimension of the four dimensional array
3501 .  p - third dimension of the four dimensional array
3502 .  q - fourth dimension of the four dimensional array
3503 .  mstart - first index you will use in first coordinate direction (often 0)
3504 .  nstart - first index in the second coordinate direction (often 0)
3505 .  pstart - first index in the third coordinate direction (often 0)
3506 .  qstart - first index in the fourth coordinate direction (often 0)
3507 -  a - location of pointer to array obtained from VecGetArray4d()
3508 
3509    Level: beginner
3510 
3511    Notes:
3512    For regular PETSc vectors this routine does not involve any copies. For
3513    any special vectors that do not store local vector data in a contiguous
3514    array, this routine will copy the data back into the underlying
3515    vector data structure from the array obtained with VecGetArray().
3516 
3517    This routine actually zeros out the a pointer.
3518 
3519 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3520           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3521           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3522 @*/
3523 PetscErrorCode  VecRestoreArray4d(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3524 {
3525   PetscErrorCode ierr;
3526   void           *dummy;
3527 
3528   PetscFunctionBegin;
3529   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3530   PetscValidPointer(a,8);
3531   PetscValidType(x,1);
3532   dummy = (void*)(*a + mstart);
3533   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3534   ierr  = VecRestoreArray(x,NULL);CHKERRQ(ierr);
3535   PetscFunctionReturn(0);
3536 }
3537 
3538 /*@C
3539    VecRestoreArray4dWrite - Restores a vector after VecGetArray3dWrite() has been called.
3540 
3541    Logically Collective
3542 
3543    Input Parameters:
3544 +  x - the vector
3545 .  m - first dimension of four dimensional array
3546 .  n - second dimension of the four dimensional array
3547 .  p - third dimension of the four dimensional array
3548 .  q - fourth dimension of the four dimensional array
3549 .  mstart - first index you will use in first coordinate direction (often 0)
3550 .  nstart - first index in the second coordinate direction (often 0)
3551 .  pstart - first index in the third coordinate direction (often 0)
3552 .  qstart - first index in the fourth coordinate direction (often 0)
3553 -  a - location of pointer to array obtained from VecGetArray4d()
3554 
3555    Level: beginner
3556 
3557    Notes:
3558    For regular PETSc vectors this routine does not involve any copies. For
3559    any special vectors that do not store local vector data in a contiguous
3560    array, this routine will copy the data back into the underlying
3561    vector data structure from the array obtained with VecGetArray().
3562 
3563    This routine actually zeros out the a pointer.
3564 
3565 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3566           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3567           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3568 @*/
3569 PetscErrorCode  VecRestoreArray4dWrite(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3570 {
3571   PetscErrorCode ierr;
3572   void           *dummy;
3573 
3574   PetscFunctionBegin;
3575   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3576   PetscValidPointer(a,8);
3577   PetscValidType(x,1);
3578   dummy = (void*)(*a + mstart);
3579   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3580   ierr  = VecRestoreArrayWrite(x,NULL);CHKERRQ(ierr);
3581   PetscFunctionReturn(0);
3582 }
3583 
3584 /*@C
3585    VecGetArray2dRead - Returns a pointer to a 2d contiguous array that contains this
3586    processor's portion of the vector data.  You MUST call VecRestoreArray2dRead()
3587    when you no longer need access to the array.
3588 
3589    Logically Collective
3590 
3591    Input Parameter:
3592 +  x - the vector
3593 .  m - first dimension of two dimensional array
3594 .  n - second dimension of two dimensional array
3595 .  mstart - first index you will use in first coordinate direction (often 0)
3596 -  nstart - first index in the second coordinate direction (often 0)
3597 
3598    Output Parameter:
3599 .  a - location to put pointer to the array
3600 
3601    Level: developer
3602 
3603   Notes:
3604    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
3605    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3606    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3607    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().
3608 
3609    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3610 
3611 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3612           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3613           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3614 @*/
3615 PetscErrorCode  VecGetArray2dRead(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
3616 {
3617   PetscErrorCode    ierr;
3618   PetscInt          i,N;
3619   const PetscScalar *aa;
3620 
3621   PetscFunctionBegin;
3622   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3623   PetscValidPointer(a,6);
3624   PetscValidType(x,1);
3625   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3626   if (m*n != N) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 2d array dimensions %D by %D",N,m,n);
3627   ierr = VecGetArrayRead(x,&aa);CHKERRQ(ierr);
3628 
3629   ierr = PetscMalloc1(m,a);CHKERRQ(ierr);
3630   for (i=0; i<m; i++) (*a)[i] = (PetscScalar*) aa + i*n - nstart;
3631   *a -= mstart;
3632   PetscFunctionReturn(0);
3633 }
3634 
3635 /*@C
3636    VecRestoreArray2dRead - Restores a vector after VecGetArray2dRead() has been called.
3637 
3638    Logically Collective
3639 
3640    Input Parameters:
3641 +  x - the vector
3642 .  m - first dimension of two dimensional array
3643 .  n - second dimension of the two dimensional array
3644 .  mstart - first index you will use in first coordinate direction (often 0)
3645 .  nstart - first index in the second coordinate direction (often 0)
3646 -  a - location of pointer to array obtained from VecGetArray2d()
3647 
3648    Level: developer
3649 
3650    Notes:
3651    For regular PETSc vectors this routine does not involve any copies. For
3652    any special vectors that do not store local vector data in a contiguous
3653    array, this routine will copy the data back into the underlying
3654    vector data structure from the array obtained with VecGetArray().
3655 
3656    This routine actually zeros out the a pointer.
3657 
3658 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3659           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3660           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3661 @*/
3662 PetscErrorCode  VecRestoreArray2dRead(Vec x,PetscInt m,PetscInt n,PetscInt mstart,PetscInt nstart,PetscScalar **a[])
3663 {
3664   PetscErrorCode ierr;
3665   void           *dummy;
3666 
3667   PetscFunctionBegin;
3668   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3669   PetscValidPointer(a,6);
3670   PetscValidType(x,1);
3671   dummy = (void*)(*a + mstart);
3672   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3673   ierr  = VecRestoreArrayRead(x,NULL);CHKERRQ(ierr);
3674   PetscFunctionReturn(0);
3675 }
3676 
3677 /*@C
3678    VecGetArray1dRead - Returns a pointer to a 1d contiguous array that contains this
3679    processor's portion of the vector data.  You MUST call VecRestoreArray1dRead()
3680    when you no longer need access to the array.
3681 
3682    Logically Collective
3683 
3684    Input Parameter:
3685 +  x - the vector
3686 .  m - first dimension of two dimensional array
3687 -  mstart - first index you will use in first coordinate direction (often 0)
3688 
3689    Output Parameter:
3690 .  a - location to put pointer to the array
3691 
3692    Level: developer
3693 
3694   Notes:
3695    For a vector obtained from DMCreateLocalVector() mstart are likely
3696    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3697    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().
3698 
3699    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3700 
3701 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3702           VecRestoreArray2d(), DMDAVecGetArray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3703           VecGetArray2d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3704 @*/
3705 PetscErrorCode  VecGetArray1dRead(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3706 {
3707   PetscErrorCode ierr;
3708   PetscInt       N;
3709 
3710   PetscFunctionBegin;
3711   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3712   PetscValidPointer(a,4);
3713   PetscValidType(x,1);
3714   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3715   if (m != N) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Local array size %D does not match 1d array dimensions %D",N,m);
3716   ierr = VecGetArrayRead(x,(const PetscScalar**)a);CHKERRQ(ierr);
3717   *a  -= mstart;
3718   PetscFunctionReturn(0);
3719 }
3720 
3721 /*@C
3722    VecRestoreArray1dRead - Restores a vector after VecGetArray1dRead() has been called.
3723 
3724    Logically Collective
3725 
3726    Input Parameters:
3727 +  x - the vector
3728 .  m - first dimension of two dimensional array
3729 .  mstart - first index you will use in first coordinate direction (often 0)
3730 -  a - location of pointer to array obtained from VecGetArray21()
3731 
3732    Level: developer
3733 
3734    Notes:
3735    For regular PETSc vectors this routine does not involve any copies. For
3736    any special vectors that do not store local vector data in a contiguous
3737    array, this routine will copy the data back into the underlying
3738    vector data structure from the array obtained with VecGetArray1dRead().
3739 
3740    This routine actually zeros out the a pointer.
3741 
3742 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3743           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3744           VecGetArray1d(), VecRestoreArray2d(), VecGetArray4d(), VecRestoreArray4d()
3745 @*/
3746 PetscErrorCode  VecRestoreArray1dRead(Vec x,PetscInt m,PetscInt mstart,PetscScalar *a[])
3747 {
3748   PetscErrorCode ierr;
3749 
3750   PetscFunctionBegin;
3751   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3752   PetscValidType(x,1);
3753   ierr = VecRestoreArrayRead(x,NULL);CHKERRQ(ierr);
3754   PetscFunctionReturn(0);
3755 }
3756 
3757 
3758 /*@C
3759    VecGetArray3dRead - Returns a pointer to a 3d contiguous array that contains this
3760    processor's portion of the vector data.  You MUST call VecRestoreArray3dRead()
3761    when you no longer need access to the array.
3762 
3763    Logically Collective
3764 
3765    Input Parameter:
3766 +  x - the vector
3767 .  m - first dimension of three dimensional array
3768 .  n - second dimension of three dimensional array
3769 .  p - third dimension of three dimensional array
3770 .  mstart - first index you will use in first coordinate direction (often 0)
3771 .  nstart - first index in the second coordinate direction (often 0)
3772 -  pstart - first index in the third coordinate direction (often 0)
3773 
3774    Output Parameter:
3775 .  a - location to put pointer to the array
3776 
3777    Level: developer
3778 
3779   Notes:
3780    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3781    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3782    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3783    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3dRead().
3784 
3785    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3786 
3787 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3788           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3789           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3790 @*/
3791 PetscErrorCode  VecGetArray3dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3792 {
3793   PetscErrorCode    ierr;
3794   PetscInt          i,N,j;
3795   const PetscScalar *aa;
3796   PetscScalar       **b;
3797 
3798   PetscFunctionBegin;
3799   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3800   PetscValidPointer(a,8);
3801   PetscValidType(x,1);
3802   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3803   if (m*n*p != N) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 3d array dimensions %D by %D by %D",N,m,n,p);
3804   ierr = VecGetArrayRead(x,&aa);CHKERRQ(ierr);
3805 
3806   ierr = PetscMalloc1(m*sizeof(PetscScalar**)+m*n,a);CHKERRQ(ierr);
3807   b    = (PetscScalar**)((*a) + m);
3808   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3809   for (i=0; i<m; i++)
3810     for (j=0; j<n; j++)
3811       b[i*n+j] = (PetscScalar *)aa + i*n*p + j*p - pstart;
3812 
3813   *a -= mstart;
3814   PetscFunctionReturn(0);
3815 }
3816 
3817 /*@C
3818    VecRestoreArray3dRead - Restores a vector after VecGetArray3dRead() has been called.
3819 
3820    Logically Collective
3821 
3822    Input Parameters:
3823 +  x - the vector
3824 .  m - first dimension of three dimensional array
3825 .  n - second dimension of the three dimensional array
3826 .  p - third dimension of the three dimensional array
3827 .  mstart - first index you will use in first coordinate direction (often 0)
3828 .  nstart - first index in the second coordinate direction (often 0)
3829 .  pstart - first index in the third coordinate direction (often 0)
3830 -  a - location of pointer to array obtained from VecGetArray3dRead()
3831 
3832    Level: developer
3833 
3834    Notes:
3835    For regular PETSc vectors this routine does not involve any copies. For
3836    any special vectors that do not store local vector data in a contiguous
3837    array, this routine will copy the data back into the underlying
3838    vector data structure from the array obtained with VecGetArray().
3839 
3840    This routine actually zeros out the a pointer.
3841 
3842 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3843           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3844           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3845 @*/
3846 PetscErrorCode  VecRestoreArray3dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscScalar ***a[])
3847 {
3848   PetscErrorCode ierr;
3849   void           *dummy;
3850 
3851   PetscFunctionBegin;
3852   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3853   PetscValidPointer(a,8);
3854   PetscValidType(x,1);
3855   dummy = (void*)(*a + mstart);
3856   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3857   ierr  = VecRestoreArrayRead(x,NULL);CHKERRQ(ierr);
3858   PetscFunctionReturn(0);
3859 }
3860 
3861 /*@C
3862    VecGetArray4dRead - Returns a pointer to a 4d contiguous array that contains this
3863    processor's portion of the vector data.  You MUST call VecRestoreArray4dRead()
3864    when you no longer need access to the array.
3865 
3866    Logically Collective
3867 
3868    Input Parameter:
3869 +  x - the vector
3870 .  m - first dimension of four dimensional array
3871 .  n - second dimension of four dimensional array
3872 .  p - third dimension of four dimensional array
3873 .  q - fourth dimension of four dimensional array
3874 .  mstart - first index you will use in first coordinate direction (often 0)
3875 .  nstart - first index in the second coordinate direction (often 0)
3876 .  pstart - first index in the third coordinate direction (often 0)
3877 -  qstart - first index in the fourth coordinate direction (often 0)
3878 
3879    Output Parameter:
3880 .  a - location to put pointer to the array
3881 
3882    Level: beginner
3883 
3884   Notes:
3885    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3886    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3887    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3888    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().
3889 
3890    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.
3891 
3892 .seealso: VecGetArray(), VecRestoreArray(), VecGetArrays(), VecGetArrayF90(), VecPlaceArray(),
3893           VecRestoreArray2d(), DMDAVecGetarray(), DMDAVecRestoreArray(), VecGetArray3d(), VecRestoreArray3d(),
3894           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d()
3895 @*/
3896 PetscErrorCode  VecGetArray4dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3897 {
3898   PetscErrorCode    ierr;
3899   PetscInt          i,N,j,k;
3900   const PetscScalar *aa;
3901   PetscScalar       ***b,**c;
3902 
3903   PetscFunctionBegin;
3904   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3905   PetscValidPointer(a,10);
3906   PetscValidType(x,1);
3907   ierr = VecGetLocalSize(x,&N);CHKERRQ(ierr);
3908   if (m*n*p*q != N) SETERRQ5(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Local array size %D does not match 4d array dimensions %D by %D by %D by %D",N,m,n,p,q);
3909   ierr = VecGetArrayRead(x,&aa);CHKERRQ(ierr);
3910 
3911   ierr = PetscMalloc1(m*sizeof(PetscScalar***)+m*n*sizeof(PetscScalar**)+m*n*p,a);CHKERRQ(ierr);
3912   b    = (PetscScalar***)((*a) + m);
3913   c    = (PetscScalar**)(b + m*n);
3914   for (i=0; i<m; i++) (*a)[i] = b + i*n - nstart;
3915   for (i=0; i<m; i++)
3916     for (j=0; j<n; j++)
3917       b[i*n+j] = c + i*n*p + j*p - pstart;
3918   for (i=0; i<m; i++)
3919     for (j=0; j<n; j++)
3920       for (k=0; k<p; k++)
3921         c[i*n*p+j*p+k] = (PetscScalar*) aa + i*n*p*q + j*p*q + k*q - qstart;
3922   *a -= mstart;
3923   PetscFunctionReturn(0);
3924 }
3925 
3926 /*@C
3927    VecRestoreArray4dRead - Restores a vector after VecGetArray3d() has been called.
3928 
3929    Logically Collective
3930 
3931    Input Parameters:
3932 +  x - the vector
3933 .  m - first dimension of four dimensional array
3934 .  n - second dimension of the four dimensional array
3935 .  p - third dimension of the four dimensional array
3936 .  q - fourth dimension of the four dimensional array
3937 .  mstart - first index you will use in first coordinate direction (often 0)
3938 .  nstart - first index in the second coordinate direction (often 0)
3939 .  pstart - first index in the third coordinate direction (often 0)
3940 .  qstart - first index in the fourth coordinate direction (often 0)
3941 -  a - location of pointer to array obtained from VecGetArray4dRead()
3942 
3943    Level: beginner
3944 
3945    Notes:
3946    For regular PETSc vectors this routine does not involve any copies. For
3947    any special vectors that do not store local vector data in a contiguous
3948    array, this routine will copy the data back into the underlying
3949    vector data structure from the array obtained with VecGetArray().
3950 
3951    This routine actually zeros out the a pointer.
3952 
3953 .seealso: VecGetArray(), VecRestoreArray(), VecRestoreArrays(), VecRestoreArrayF90(), VecPlaceArray(),
3954           VecGetArray2d(), VecGetArray3d(), VecRestoreArray3d(), DMDAVecGetArray(), DMDAVecRestoreArray()
3955           VecGetArray1d(), VecRestoreArray1d(), VecGetArray4d(), VecRestoreArray4d(), VecGet
3956 @*/
3957 PetscErrorCode  VecRestoreArray4dRead(Vec x,PetscInt m,PetscInt n,PetscInt p,PetscInt q,PetscInt mstart,PetscInt nstart,PetscInt pstart,PetscInt qstart,PetscScalar ****a[])
3958 {
3959   PetscErrorCode ierr;
3960   void           *dummy;
3961 
3962   PetscFunctionBegin;
3963   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3964   PetscValidPointer(a,8);
3965   PetscValidType(x,1);
3966   dummy = (void*)(*a + mstart);
3967   ierr  = PetscFree(dummy);CHKERRQ(ierr);
3968   ierr  = VecRestoreArrayRead(x,NULL);CHKERRQ(ierr);
3969   PetscFunctionReturn(0);
3970 }
3971 
3972 #if defined(PETSC_USE_DEBUG)
3973 
3974 /*@
3975    VecLockGet  - Gets the current lock status of a vector
3976 
3977    Logically Collective on Vec
3978 
3979    Input Parameter:
3980 .  x - the vector
3981 
3982    Output Parameter:
3983 .  state - greater than zero indicates the vector is locked for read; less then zero indicates the vector is
3984            locked for write; equal to zero means the vector is unlocked, that is, it is free to read or write.
3985 
3986    Level: beginner
3987 
3988 .seealso: VecRestoreArray(), VecGetArrayRead(), VecLockReadPush(), VecLockReadPop()
3989 @*/
3990 PetscErrorCode VecLockGet(Vec x,PetscInt *state)
3991 {
3992   PetscFunctionBegin;
3993   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
3994   *state = x->lock;
3995   PetscFunctionReturn(0);
3996 }
3997 
3998 /*@
3999    VecLockReadPush  - Pushes a read-only lock on a vector to prevent it from writing
4000 
4001    Logically Collective on Vec
4002 
4003    Input Parameter:
4004 .  x - the vector
4005 
4006    Notes:
4007     If this is set then calls to VecGetArray() or VecSetValues() or any other routines that change the vectors values will fail.
4008 
4009     The call can be nested, i.e., called multiple times on the same vector, but each VecLockReadPush(x) has to have one matching
4010     VecLockReadPop(x), which removes the latest read-only lock.
4011 
4012    Level: beginner
4013 
4014 .seealso: VecRestoreArray(), VecGetArrayRead(), VecLockReadPop(), VecLockGet()
4015 @*/
4016 PetscErrorCode VecLockReadPush(Vec x)
4017 {
4018   PetscFunctionBegin;
4019   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
4020   if (x->lock < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vector is already locked for exclusive write access but you want to read it");
4021   x->lock++;
4022   PetscFunctionReturn(0);
4023 }
4024 
4025 /*@
4026    VecLockReadPop  - Pops a read-only lock from a vector
4027 
4028    Logically Collective on Vec
4029 
4030    Input Parameter:
4031 .  x - the vector
4032 
4033    Level: beginner
4034 
4035 .seealso: VecRestoreArray(), VecGetArrayRead(), VecLockReadPush(), VecLockGet()
4036 @*/
4037 PetscErrorCode VecLockReadPop(Vec x)
4038 {
4039   PetscFunctionBegin;
4040   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
4041   x->lock--;
4042   if (x->lock < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vector has been unlocked from read-only access too many times");
4043   PetscFunctionReturn(0);
4044 }
4045 
4046 /*@C
4047    VecLockWriteSet_Private  - Lock or unlock a vector for exclusive read/write access
4048 
4049    Logically Collective on Vec
4050 
4051    Input Parameter:
4052 +  x   - the vector
4053 -  flg - PETSC_TRUE to lock the vector for writing; PETSC_FALSE to unlock it.
4054 
4055    Notes:
4056     The function is usefull in split-phase computations, which usually have a begin phase and an end phase.
4057     One can call VecLockWriteSet_Private(x,PETSC_TRUE) in the begin phase to lock a vector for exclusive
4058     access, and call VecLockWriteSet_Private(x,PETSC_FALSE) in the end phase to unlock the vector from exclusive
4059     access. In this way, one is ensured no other operations can access the vector in between. The code may like
4060 
4061 
4062        VecGetArray(x,&xdata); // begin phase
4063        VecLockWriteSet_Private(v,PETSC_TRUE);
4064 
4065        Other operations, which can not acceess x anymore (they can access xdata, of course)
4066 
4067        VecRestoreArray(x,&vdata); // end phase
4068        VecLockWriteSet_Private(v,PETSC_FALSE);
4069 
4070     The call can not be nested on the same vector, in other words, one can not call VecLockWriteSet_Private(x,PETSC_TRUE)
4071     again before calling VecLockWriteSet_Private(v,PETSC_FALSE).
4072 
4073    Level: beginner
4074 
4075 .seealso: VecRestoreArray(), VecGetArrayRead(), VecLockReadPush(), VecLockReadPop(), VecLockGet()
4076 @*/
4077 PetscErrorCode VecLockWriteSet_Private(Vec x,PetscBool flg)
4078 {
4079   PetscFunctionBegin;
4080   PetscValidHeaderSpecific(x,VEC_CLASSID,1);
4081   if (flg) {
4082     if (x->lock > 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vector is already locked for read-only access but you want to write it");
4083     else if (x->lock < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vector is already locked for exclusive write access but you want to write it");
4084     else x->lock = -1;
4085   } else {
4086     if (x->lock != -1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Vector is not locked for exclusive write access but you want to unlock it from that");
4087     x->lock = 0;
4088   }
4089   PetscFunctionReturn(0);
4090 }
4091 
4092 /*@
4093    VecLockPush  - Pushes a read-only lock on a vector to prevent it from writing
4094 
4095    Level: deprecated
4096 
4097 .seealso: VecLockReadPush()
4098 @*/
4099 PetscErrorCode VecLockPush(Vec x)
4100 {
4101   PetscErrorCode ierr;
4102   PetscFunctionBegin;
4103   ierr = VecLockReadPush(x);CHKERRQ(ierr);
4104   PetscFunctionReturn(0);
4105 }
4106 
4107 /*@
4108    VecLockPop  - Pops a read-only lock from a vector
4109 
4110    Level: deprecated
4111 
4112 .seealso: VecLockReadPop()
4113 @*/
4114 PetscErrorCode VecLockPop(Vec x)
4115 {
4116   PetscErrorCode ierr;
4117   PetscFunctionBegin;
4118   ierr = VecLockReadPop(x);CHKERRQ(ierr);
4119   PetscFunctionReturn(0);
4120 }
4121 
4122 #endif
4123