Actual source code: rvector.c

  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 "petscsystypes.h"
  7: #include <petsc/private/vecimpl.h>
  8: #if defined(PETSC_HAVE_CUDA)
  9: #include <../src/vec/vec/impls/dvecimpl.h>
 10: #include <petsc/private/cudavecimpl.h>
 11: #endif
 12: #if defined(PETSC_HAVE_HIP)
 13: #include <../src/vec/vec/impls/dvecimpl.h>
 14: #include <petsc/private/hipvecimpl.h>
 15: #endif
 16: PetscInt VecGetSubVectorSavedStateId = -1;

 18: #if PetscDefined(USE_DEBUG)
 19: // this is a no-op '0' macro in optimized builds
 20: PetscErrorCode VecValidValues_Internal(Vec vec, PetscInt argnum, PetscBool begin)
 21: {
 22:   if (vec->petscnative || vec->ops->getarray) {
 23:     PetscInt           n;
 24:     const PetscScalar *x;
 25:     PetscOffloadMask   mask;

 27:     VecGetOffloadMask(vec, &mask);
 28:     if (!PetscOffloadHost(mask)) return 0;
 29:     VecGetLocalSize(vec, &n);
 30:     VecGetArrayRead(vec, &x);
 31:     for (PetscInt i = 0; i < n; i++) {
 32:       if (begin) {
 34:       } else {
 36:       }
 37:     }
 38:     VecRestoreArrayRead(vec, &x);
 39:   }
 40:   return 0;
 41: }
 42: #endif

 44: /*@
 45:    VecMaxPointwiseDivide - Computes the maximum of the componentwise division max = max_i abs(x_i/y_i).

 47:    Logically Collective on Vec

 49:    Input Parameters:
 50: .  x, y  - the vectors

 52:    Output Parameter:
 53: .  max - the result

 55:    Level: advanced

 57:    Notes:
 58:     x and y may be the same vector
 59:           if a particular y_i is zero, it is treated as 1 in the above formula

 61: .seealso: `VecPointwiseDivide()`, `VecPointwiseMult()`, `VecPointwiseMax()`, `VecPointwiseMin()`, `VecPointwiseMaxAbs()`
 62: @*/
 63: PetscErrorCode VecMaxPointwiseDivide(Vec x, Vec y, PetscReal *max)
 64: {
 71:   VecCheckSameSize(x, 1, y, 2);
 72:   VecLockReadPush(x);
 73:   VecLockReadPush(y);
 74:   PetscUseTypeMethod(x, maxpointwisedivide, y, max);
 75:   VecLockReadPop(x);
 76:   VecLockReadPop(y);
 77:   return 0;
 78: }

 80: /*@
 81:    VecDot - Computes the vector dot product.

 83:    Collective on Vec

 85:    Input Parameters:
 86: .  x, y - the vectors

 88:    Output Parameter:
 89: .  val - the dot product

 91:    Performance Issues:
 92: $    per-processor memory bandwidth
 93: $    interprocessor latency
 94: $    work load imbalance that causes certain processes to arrive much earlier than others

 96:    Notes for Users of Complex Numbers:
 97:    For complex vectors, VecDot() computes
 98: $     val = (x,y) = y^H x,
 99:    where y^H denotes the conjugate transpose of y. Note that this corresponds to the usual "mathematicians" complex
100:    inner product where the SECOND argument gets the complex conjugate. Since the BLASdot() complex conjugates the first
101:    first argument we call the BLASdot() with the arguments reversed.

103:    Use VecTDot() for the indefinite form
104: $     val = (x,y) = y^T x,
105:    where y^T denotes the transpose of y.

107:    Level: intermediate

109: .seealso: `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDotRealPart()`
110: @*/
111: PetscErrorCode VecDot(Vec x, Vec y, PetscScalar *val)
112: {
119:   VecCheckSameSize(x, 1, y, 2);

121:   VecLockReadPush(x);
122:   VecLockReadPush(y);
123:   PetscLogEventBegin(VEC_Dot, x, y, 0, 0);
124:   PetscUseTypeMethod(x, dot, y, val);
125:   PetscLogEventEnd(VEC_Dot, x, y, 0, 0);
126:   VecLockReadPop(x);
127:   VecLockReadPop(y);
128:   return 0;
129: }

131: /*@
132:    VecDotRealPart - Computes the real part of the vector dot product.

134:    Collective on Vec

136:    Input Parameters:
137: .  x, y - the vectors

139:    Output Parameter:
140: .  val - the real part of the dot product;

142:    Performance Issues:
143: $    per-processor memory bandwidth
144: $    interprocessor latency
145: $    work load imbalance that causes certain processes to arrive much earlier than others

147:    Notes for Users of Complex Numbers:
148:      See VecDot() for more details on the definition of the dot product for complex numbers

150:      For real numbers this returns the same value as VecDot()

152:      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
153:      the space R^{2n} (that is a vector of 2n components with the real or imaginary part of the complex numbers for components)

155:    Developer Note: This is not currently optimized to compute only the real part of the dot product.

157:    Level: intermediate

159: .seealso: `VecMDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecDot()`, `VecDotNorm2()`
160: @*/
161: PetscErrorCode VecDotRealPart(Vec x, Vec y, PetscReal *val)
162: {
163:   PetscScalar fdot;

165:   VecDot(x, y, &fdot);
166:   *val = PetscRealPart(fdot);
167:   return 0;
168: }

170: /*@
171:    VecNorm  - Computes the vector norm.

173:    Collective on Vec

175:    Input Parameters:
176: +  x - the vector
177: -  type - the type of the norm requested

179:    Output Parameter:
180: .  val - the norm

182:    Values of NormType:
183: +     NORM_1 - sum_i |x_i|
184: .     NORM_2 - sqrt(sum_i |x_i|^2)
185: .     NORM_INFINITY - max_i |x_i|
186: -     NORM_1_AND_2 - computes efficiently both  NORM_1 and NORM_2 and stores them each in an output array

188:    Notes:
189:       For complex numbers NORM_1 will return the traditional 1 norm of the 2 norm of the complex numbers; that is the 1
190:       norm of the absolute values of the complex entries. In PETSc 3.6 and earlier releases it returned the 1 norm of
191:       the 1 norm of the complex entries (what is returned by the BLAS routine asum()). Both are valid norms but most
192:       people expect the former.

194:       This routine stashes the computed norm value, repeated calls before the vector entries are changed are then rapid since the
195:       precomputed value is immediately available. Certain vector operations such as VecSet() store the norms so the value is
196:       immediately available and does not need to be explicitly computed. VecScale() updates any stashed norm values, thus calls after VecScale()
197:       do not need to explicitly recompute the norm.

199:    Level: intermediate

201:    Performance Issues:
202: +    per-processor memory bandwidth - limits the speed of the computation of local portion of the norm
203: .    interprocessor latency - limits the accumulation of the result across ranks, .i.e. MPI_Allreduce() time
204: .    number of ranks - the time for the result will grow with the log base 2 of the number of ranks sharing the vector
205: -    work load imbalance - the rank with the largest number of vector entries will limit the speed up

207: .seealso: `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecNormAvailable()`,
208:           `VecNormBegin()`, `VecNormEnd()`, `NormType()`

210: @*/
211: PetscErrorCode VecNorm(Vec x, NormType type, PetscReal *val)
212: {

217:   /* Cached data? */
218:   if (type != NORM_1_AND_2) {
219:     PetscBool flg;

221:     PetscObjectComposedDataGetReal((PetscObject)x, NormIds[type], *val, flg);
222:     if (flg) return 0;
223:   }

225:   VecLockReadPush(x);
226:   PetscLogEventBegin(VEC_Norm, x, 0, 0, 0);
227:   PetscUseTypeMethod(x, norm, type, val);
228:   PetscLogEventEnd(VEC_Norm, x, 0, 0, 0);
229:   VecLockReadPop(x);

231:   if (type != NORM_1_AND_2) PetscObjectComposedDataSetReal((PetscObject)x, NormIds[type], *val);
232:   return 0;
233: }

235: /*@
236:    VecNormAvailable  - Returns the vector norm if it is already known.

238:    Not Collective

240:    Input Parameters:
241: +  x - the vector
242: -  type - one of NORM_1, NORM_2, NORM_INFINITY.  Also available
243:           NORM_1_AND_2, which computes both norms and stores them
244:           in a two element array.

246:    Output Parameters:
247: +  available - PETSC_TRUE if the val returned is valid
248: -  val - the norm

250:    Notes:
251: $     NORM_1 denotes sum_i |x_i|
252: $     NORM_2 denotes sqrt(sum_i (x_i)^2)
253: $     NORM_INFINITY denotes max_i |x_i|

255:    Level: intermediate

257:    Performance Issues:
258: $    per-processor memory bandwidth
259: $    interprocessor latency
260: $    work load imbalance that causes certain processes to arrive much earlier than others

262:    Compile Option:
263:    PETSC_HAVE_SLOW_BLAS_NORM2 will cause a C (loop unrolled) version of the norm to be used, rather
264:  than the BLAS. This should probably only be used when one is using the FORTRAN BLAS routines
265:  (as opposed to vendor provided) because the FORTRAN BLAS NRM2() routine is very slow.

267: .seealso: `VecDot()`, `VecTDot()`, `VecNorm()`, `VecDotBegin()`, `VecDotEnd()`, `VecNorm()`
268:           `VecNormBegin()`, `VecNormEnd()`

270: @*/
271: PetscErrorCode VecNormAvailable(Vec x, NormType type, PetscBool *available, PetscReal *val)
272: {

278:   if (type == NORM_1_AND_2) {
279:     *available = PETSC_FALSE;
280:   } else {
281:     PetscObjectComposedDataGetReal((PetscObject)x, NormIds[type], *val, *available);
282:   }
283:   return 0;
284: }

286: /*@
287:    VecNormalize - Normalizes a vector by 2-norm.

289:    Collective on Vec

291:    Input Parameter:
292: .  x - the vector

294:    Output Parameter:
295: .  val - the vector norm before normalization. May be `NULL` if the value is not needed.

297:    Level: intermediate

299: @*/
300: PetscErrorCode VecNormalize(Vec x, PetscReal *val)
301: {
302:   PetscReal norm;

306:   VecSetErrorIfLocked(x, 1);
308:   PetscLogEventBegin(VEC_Normalize, x, 0, 0, 0);
309:   VecNorm(x, NORM_2, &norm);
310:   if (norm == 0.0) {
311:     PetscInfo(x, "Vector of zero norm can not be normalized; Returning only the zero norm\n");
312:   } else if (norm != 1.0) {
313:     VecScale(x, 1.0 / norm);
314:   }
315:   PetscLogEventEnd(VEC_Normalize, x, 0, 0, 0);
316:   if (val) *val = norm;
317:   return 0;
318: }

320: /*@C
321:    VecMax - Determines the vector component with maximum real part and its location.

323:    Collective on Vec

325:    Input Parameter:
326: .  x - the vector

328:    Output Parameters:
329: +  p - the location of val (pass NULL if you don't want this)
330: -  val - the maximum component

332:    Notes:
333:    Returns the value PETSC_MIN_REAL and negative p if the vector is of length 0.

335:    Returns the smallest index with the maximum value
336:    Level: intermediate

338: .seealso: `VecNorm()`, `VecMin()`
339: @*/
340: PetscErrorCode VecMax(Vec x, PetscInt *p, PetscReal *val)
341: {
346:   VecLockReadPush(x);
347:   PetscLogEventBegin(VEC_Max, x, 0, 0, 0);
348:   PetscUseTypeMethod(x, max, p, val);
349:   PetscLogEventEnd(VEC_Max, x, 0, 0, 0);
350:   VecLockReadPop(x);
351:   return 0;
352: }

354: /*@C
355:    VecMin - Determines the vector component with minimum real part and its location.

357:    Collective on Vec

359:    Input Parameter:
360: .  x - the vector

362:    Output Parameters:
363: +  p - the location of val (pass NULL if you don't want this location)
364: -  val - the minimum component

366:    Level: intermediate

368:    Notes:
369:    Returns the value PETSC_MAX_REAL and negative p if the vector is of length 0.

371:    This returns the smallest index with the minumum value

373: .seealso: `VecMax()`
374: @*/
375: PetscErrorCode VecMin(Vec x, PetscInt *p, PetscReal *val)
376: {
381:   VecLockReadPush(x);
382:   PetscLogEventBegin(VEC_Min, x, 0, 0, 0);
383:   PetscUseTypeMethod(x, min, p, val);
384:   PetscLogEventEnd(VEC_Min, x, 0, 0, 0);
385:   VecLockReadPop(x);
386:   return 0;
387: }

389: /*@
390:    VecTDot - Computes an indefinite vector dot product. That is, this
391:    routine does NOT use the complex conjugate.

393:    Collective on Vec

395:    Input Parameters:
396: .  x, y - the vectors

398:    Output Parameter:
399: .  val - the dot product

401:    Notes for Users of Complex Numbers:
402:    For complex vectors, VecTDot() computes the indefinite form
403: $     val = (x,y) = y^T x,
404:    where y^T denotes the transpose of y.

406:    Use VecDot() for the inner product
407: $     val = (x,y) = y^H x,
408:    where y^H denotes the conjugate transpose of y.

410:    Level: intermediate

412: .seealso: `VecDot()`, `VecMTDot()`
413: @*/
414: PetscErrorCode VecTDot(Vec x, Vec y, PetscScalar *val)
415: {
422:   VecCheckSameSize(x, 1, y, 2);

424:   VecLockReadPush(x);
425:   VecLockReadPush(y);
426:   PetscLogEventBegin(VEC_TDot, x, y, 0, 0);
427:   PetscUseTypeMethod(x, tdot, y, val);
428:   PetscLogEventEnd(VEC_TDot, x, y, 0, 0);
429:   VecLockReadPop(x);
430:   VecLockReadPop(y);
431:   return 0;
432: }

434: /*@
435:    VecScale - Scales a vector.

437:    Not collective on Vec

439:    Input Parameters:
440: +  x - the vector
441: -  alpha - the scalar

443:    Note:
444:    For a vector with n components, VecScale() computes
445: $      x[i] = alpha * x[i], for i=1,...,n.

447:    Level: intermediate

449: @*/
450: PetscErrorCode VecScale(Vec x, PetscScalar alpha)
451: {
452:   PetscReal norms[4];
453:   PetscBool flgs[4];

458:   VecSetErrorIfLocked(x, 1);
459:   if (alpha == (PetscScalar)1.0) return 0;

461:   /* get current stashed norms */
462:   for (PetscInt i = 0; i < 4; i++) PetscObjectComposedDataGetReal((PetscObject)x, NormIds[i], norms[i], flgs[i]);

464:   PetscLogEventBegin(VEC_Scale, x, 0, 0, 0);
465:   PetscUseTypeMethod(x, scale, alpha);
466:   PetscLogEventEnd(VEC_Scale, x, 0, 0, 0);

468:   PetscObjectStateIncrease((PetscObject)x);
469:   /* put the scaled stashed norms back into the Vec */
470:   for (PetscInt i = 0; i < 4; i++) {
471:     if (flgs[i]) PetscObjectComposedDataSetReal((PetscObject)x, NormIds[i], PetscAbsScalar(alpha) * norms[i]);
472:   }
473:   return 0;
474: }

476: /*@
477:    VecSet - Sets all components of a vector to a single scalar value.

479:    Logically Collective on Vec

481:    Input Parameters:
482: +  x  - the vector
483: -  alpha - the scalar

485:    Output Parameter:
486: .  x  - the vector

488:    Note:
489:    For a vector of dimension n, VecSet() computes
490: $     x[i] = alpha, for i=1,...,n,
491:    so that all vector entries then equal the identical
492:    scalar value, alpha.  Use the more general routine
493:    VecSetValues() to set different vector entries.

495:    You CANNOT call this after you have called VecSetValues() but before you call
496:    VecAssemblyBegin/End().

498:    Level: beginner

500: .seealso `VecSetValues()`, `VecSetValuesBlocked()`, `VecSetRandom()`

502: @*/
503: PetscErrorCode VecSet(Vec x, PetscScalar alpha)
504: {
509:   VecSetErrorIfLocked(x, 1);

511:   PetscLogEventBegin(VEC_Set, x, 0, 0, 0);
512:   PetscUseTypeMethod(x, set, alpha);
513:   PetscLogEventEnd(VEC_Set, x, 0, 0, 0);
514:   PetscObjectStateIncrease((PetscObject)x);

516:   /*  norms can be simply set (if |alpha|*N not too large) */

518:   {
519:     PetscReal      val = PetscAbsScalar(alpha);
520:     const PetscInt N   = x->map->N;

522:     if (N == 0) {
523:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], 0.0l);
524:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], 0.0);
525:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], 0.0);
526:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], 0.0);
527:     } else if (val > PETSC_MAX_REAL / N) {
528:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val);
529:     } else {
530:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_1], N * val);
531:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_INFINITY], val);
532:       val = PetscSqrtReal((PetscReal)N) * val;
533:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_2], val);
534:       PetscObjectComposedDataSetReal((PetscObject)x, NormIds[NORM_FROBENIUS], val);
535:     }
536:   }
537:   return 0;
538: }

540: /*@
541:    VecAXPY - Computes y = alpha x + y.

543:    Logically Collective on Vec

545:    Input Parameters:
546: +  alpha - the scalar
547: -  x, y  - the vectors

549:    Output Parameter:
550: .  y - output vector

552:    Level: intermediate

554:    Notes:
555:     x and y MUST be different vectors
556:     This routine is optimized for alpha of 0.0, otherwise it calls the BLAS routine

558: $    VecAXPY(y,alpha,x)                   y = alpha x           +      y
559: $    VecAYPX(y,beta,x)                    y =       x           + beta y
560: $    VecAXPBY(y,alpha,beta,x)             y = alpha x           + beta y
561: $    VecWAXPY(w,alpha,x,y)                w = alpha x           +      y
562: $    VecAXPBYPCZ(w,alpha,beta,gamma,x,y)  z = alpha x           + beta y + gamma z
563: $    VecMAXPY(y,nv,alpha[],x[])           y = sum alpha[i] x[i] +      y

565: .seealso: `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
566: @*/
567: PetscErrorCode VecAXPY(Vec y, PetscScalar alpha, Vec x)
568: {
574:   VecCheckSameSize(x, 3, y, 1);
577:   if (alpha == (PetscScalar)0.0) return 0;

579:   VecSetErrorIfLocked(y, 1);
580:   VecLockReadPush(x);
581:   PetscLogEventBegin(VEC_AXPY, x, y, 0, 0);
582:   PetscUseTypeMethod(y, axpy, alpha, x);
583:   PetscLogEventEnd(VEC_AXPY, x, y, 0, 0);
584:   VecLockReadPop(x);
585:   PetscObjectStateIncrease((PetscObject)y);
586:   return 0;
587: }

589: /*@
590:    VecAYPX - Computes y = x + beta y.

592:    Logically Collective on Vec

594:    Input Parameters:
595: +  beta - the scalar
596: -  x, y  - the vectors

598:    Output Parameter:
599: .  y - output vector

601:    Level: intermediate

603:    Notes:
604:     x and y MUST be different vectors
605:     The implementation is optimized for beta of -1.0, 0.0, and 1.0

607: .seealso: `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
608: @*/
609: PetscErrorCode VecAYPX(Vec y, PetscScalar beta, Vec x)
610: {
616:   VecCheckSameSize(x, 1, y, 3);
619:   VecSetErrorIfLocked(y, 1);
620:   VecLockReadPush(x);
621:   if (beta == (PetscScalar)0.0) {
622:     VecCopy(x, y);
623:   } else {
624:     PetscLogEventBegin(VEC_AYPX, x, y, 0, 0);
625:     PetscUseTypeMethod(y, aypx, beta, x);
626:     PetscLogEventEnd(VEC_AYPX, x, y, 0, 0);
627:     PetscObjectStateIncrease((PetscObject)y);
628:   }
629:   VecLockReadPop(x);
630:   return 0;
631: }

633: /*@
634:    VecAXPBY - Computes y = alpha x + beta y.

636:    Logically Collective on Vec

638:    Input Parameters:
639: +  alpha,beta - the scalars
640: -  x, y  - the vectors

642:    Output Parameter:
643: .  y - output vector

645:    Level: intermediate

647:    Notes:
648:     x and y MUST be different vectors
649:     The implementation is optimized for alpha and/or beta values of 0.0 and 1.0

651: .seealso: `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`
652: @*/
653: PetscErrorCode VecAXPBY(Vec y, PetscScalar alpha, PetscScalar beta, Vec x)
654: {
660:   VecCheckSameSize(y, 1, x, 4);
664:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)1.0) return 0;

666:   VecSetErrorIfLocked(y, 1);
667:   VecLockReadPush(x);
668:   PetscLogEventBegin(VEC_AXPY, y, x, 0, 0);
669:   PetscUseTypeMethod(y, axpby, alpha, beta, x);
670:   PetscLogEventEnd(VEC_AXPY, y, x, 0, 0);
671:   PetscObjectStateIncrease((PetscObject)y);
672:   VecLockReadPop(x);
673:   return 0;
674: }

676: /*@
677:    VecAXPBYPCZ - Computes z = alpha x + beta y + gamma z

679:    Logically Collective on Vec

681:    Input Parameters:
682: +  alpha,beta, gamma - the scalars
683: -  x, y, z  - the vectors

685:    Output Parameter:
686: .  z - output vector

688:    Level: intermediate

690:    Notes:
691:     x, y and z must be different vectors
692:     The implementation is optimized for alpha of 1.0 and gamma of 1.0 or 0.0

694: .seealso: `VecAYPX()`, `VecMAXPY()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBY()`
695: @*/
696: PetscErrorCode VecAXPBYPCZ(Vec z, PetscScalar alpha, PetscScalar beta, PetscScalar gamma, Vec x, Vec y)
697: {
706:   VecCheckSameSize(x, 1, y, 5);
707:   VecCheckSameSize(x, 1, z, 6);
713:   if (alpha == (PetscScalar)0.0 && beta == (PetscScalar)0.0 && gamma == (PetscScalar)1.0) return 0;

715:   VecSetErrorIfLocked(z, 1);
716:   VecLockReadPush(x);
717:   VecLockReadPush(y);
718:   PetscLogEventBegin(VEC_AXPBYPCZ, x, y, z, 0);
719:   PetscUseTypeMethod(z, axpbypcz, alpha, beta, gamma, x, y);
720:   PetscLogEventEnd(VEC_AXPBYPCZ, x, y, z, 0);
721:   PetscObjectStateIncrease((PetscObject)z);
722:   VecLockReadPop(x);
723:   VecLockReadPop(y);
724:   return 0;
725: }

727: /*@
728:    VecWAXPY - Computes w = alpha x + y.

730:    Logically Collective on Vec

732:    Input Parameters:
733: +  alpha - the scalar
734: -  x, y  - the vectors

736:    Output Parameter:
737: .  w - the result

739:    Level: intermediate

741:    Notes:
742:     w cannot be either x or y, but x and y can be the same
743:     The implementation is optimzed for alpha of -1.0, 0.0, and 1.0

745: .seealso: `VecAXPY()`, `VecAYPX()`, `VecAXPBY()`, `VecMAXPY()`, `VecAXPBYPCZ()`
746: @*/
747: PetscErrorCode VecWAXPY(Vec w, PetscScalar alpha, Vec x, Vec y)
748: {
757:   VecCheckSameSize(x, 3, y, 4);
758:   VecCheckSameSize(x, 3, w, 1);
762:   VecSetErrorIfLocked(w, 1);

764:   VecLockReadPush(x);
765:   VecLockReadPush(y);
766:   if (alpha == (PetscScalar)0.0) {
767:     VecCopy(y, w);
768:   } else {
769:     PetscLogEventBegin(VEC_WAXPY, x, y, w, 0);
770:     PetscUseTypeMethod(w, waxpy, alpha, x, y);
771:     PetscLogEventEnd(VEC_WAXPY, x, y, w, 0);
772:     PetscObjectStateIncrease((PetscObject)w);
773:   }
774:   VecLockReadPop(x);
775:   VecLockReadPop(y);
776:   return 0;
777: }

779: /*@C
780:    VecSetValues - Inserts or adds values into certain locations of a vector.

782:    Not Collective

784:    Input Parameters:
785: +  x - vector to insert in
786: .  ni - number of elements to add
787: .  ix - indices where to add
788: .  y - array of values
789: -  iora - either INSERT_VALUES or ADD_VALUES, where
790:    ADD_VALUES adds values to any existing entries, and
791:    INSERT_VALUES replaces existing entries with new values

793:    Notes:
794:    VecSetValues() sets x[ix[i]] = y[i], for i=0,...,ni-1.

796:    Calls to VecSetValues() with the INSERT_VALUES and ADD_VALUES
797:    options cannot be mixed without intervening calls to the assembly
798:    routines.

800:    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
801:    MUST be called after all calls to VecSetValues() have been completed.

803:    VecSetValues() uses 0-based indices in Fortran as well as in C.

805:    If you call VecSetOption(x, VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE),
806:    negative indices may be passed in ix. These rows are
807:    simply ignored. This allows easily inserting element load matrices
808:    with homogeneous Dirchlet boundary conditions that you don't want represented
809:    in the vector.

811:    Level: beginner

813: .seealso: `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesLocal()`,
814:           `VecSetValue()`, `VecSetValuesBlocked()`, `InsertMode`, `INSERT_VALUES`, `ADD_VALUES`, `VecGetValues()`
815: @*/
816: PetscErrorCode VecSetValues(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
817: {
820:   if (!ni) return 0;

825:   PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0);
826:   PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
827:   PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0);
828:   PetscObjectStateIncrease((PetscObject)x);
829:   return 0;
830: }

832: /*@C
833:    VecGetValues - Gets values from certain locations of a vector. Currently
834:           can only get values on the same processor

836:     Not Collective

838:    Input Parameters:
839: +  x - vector to get values from
840: .  ni - number of elements to get
841: -  ix - indices where to get them from (in global 1d numbering)

843:    Output Parameter:
844: .   y - array of values

846:    Notes:
847:    The user provides the allocated array y; it is NOT allocated in this routine

849:    VecGetValues() gets y[i] = x[ix[i]], for i=0,...,ni-1.

851:    VecAssemblyBegin() and VecAssemblyEnd()  MUST be called before calling this

853:    VecGetValues() uses 0-based indices in Fortran as well as in C.

855:    If you call VecSetOption(x, VEC_IGNORE_NEGATIVE_INDICES,PETSC_TRUE),
856:    negative indices may be passed in ix. These rows are
857:    simply ignored.

859:    Level: beginner

861: .seealso: `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`
862: @*/
863: PetscErrorCode VecGetValues(Vec x, PetscInt ni, const PetscInt ix[], PetscScalar y[])
864: {
866:   if (!ni) return 0;
870:   PetscUseTypeMethod(x, getvalues, ni, ix, y);
871:   return 0;
872: }

874: /*@C
875:    VecSetValuesBlocked - Inserts or adds blocks of values into certain locations of a vector.

877:    Not Collective

879:    Input Parameters:
880: +  x - vector to insert in
881: .  ni - number of blocks to add
882: .  ix - indices where to add in block count, rather than element count
883: .  y - array of values
884: -  iora - either INSERT_VALUES or ADD_VALUES, where
885:    ADD_VALUES adds values to any existing entries, and
886:    INSERT_VALUES replaces existing entries with new values

888:    Notes:
889:    VecSetValuesBlocked() sets x[bs*ix[i]+j] = y[bs*i+j],
890:    for j=0,...,bs-1, for i=0,...,ni-1. where bs was set with VecSetBlockSize().

892:    Calls to VecSetValuesBlocked() with the INSERT_VALUES and ADD_VALUES
893:    options cannot be mixed without intervening calls to the assembly
894:    routines.

896:    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
897:    MUST be called after all calls to VecSetValuesBlocked() have been completed.

899:    VecSetValuesBlocked() uses 0-based indices in Fortran as well as in C.

901:    Negative indices may be passed in ix, these rows are
902:    simply ignored. This allows easily inserting element load matrices
903:    with homogeneous Dirchlet boundary conditions that you don't want represented
904:    in the vector.

906:    Level: intermediate

908: .seealso: `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValuesBlockedLocal()`,
909:           `VecSetValues()`
910: @*/
911: PetscErrorCode VecSetValuesBlocked(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
912: {
915:   if (!ni) return 0;

920:   PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0);
921:   PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
922:   PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0);
923:   PetscObjectStateIncrease((PetscObject)x);
924:   return 0;
925: }

927: /*@C
928:    VecSetValuesLocal - Inserts or adds values into certain locations of a vector,
929:    using a local ordering of the nodes.

931:    Not Collective

933:    Input Parameters:
934: +  x - vector to insert in
935: .  ni - number of elements to add
936: .  ix - indices where to add
937: .  y - array of values
938: -  iora - either INSERT_VALUES or ADD_VALUES, where
939:    ADD_VALUES adds values to any existing entries, and
940:    INSERT_VALUES replaces existing entries with new values

942:    Level: intermediate

944:    Notes:
945:    VecSetValuesLocal() sets x[ix[i]] = y[i], for i=0,...,ni-1.

947:    Calls to VecSetValues() with the INSERT_VALUES and ADD_VALUES
948:    options cannot be mixed without intervening calls to the assembly
949:    routines.

951:    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
952:    MUST be called after all calls to VecSetValuesLocal() have been completed.

954:    VecSetValuesLocal() uses 0-based indices in Fortran as well as in C.

956: .seealso: `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetLocalToGlobalMapping()`,
957:           `VecSetValuesBlockedLocal()`
958: @*/
959: PetscErrorCode VecSetValuesLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
960: {
961:   PetscInt lixp[128], *lix = lixp;

965:   if (!ni) return 0;

970:   PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0);
971:   if (!x->ops->setvalueslocal) {
972:     if (x->map->mapping) {
973:       if (ni > 128) PetscMalloc1(ni, &lix);
974:       ISLocalToGlobalMappingApply(x->map->mapping, ni, (PetscInt *)ix, lix);
975:       PetscUseTypeMethod(x, setvalues, ni, lix, y, iora);
976:       if (ni > 128) PetscFree(lix);
977:     } else PetscUseTypeMethod(x, setvalues, ni, ix, y, iora);
978:   } else PetscUseTypeMethod(x, setvalueslocal, ni, ix, y, iora);
979:   PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0);
980:   PetscObjectStateIncrease((PetscObject)x);
981:   return 0;
982: }

984: /*@
985:    VecSetValuesBlockedLocal - Inserts or adds values into certain locations of a vector,
986:    using a local ordering of the nodes.

988:    Not Collective

990:    Input Parameters:
991: +  x - vector to insert in
992: .  ni - number of blocks to add
993: .  ix - indices where to add in block count, not element count
994: .  y - array of values
995: -  iora - either INSERT_VALUES or ADD_VALUES, where
996:    ADD_VALUES adds values to any existing entries, and
997:    INSERT_VALUES replaces existing entries with new values

999:    Level: intermediate

1001:    Notes:
1002:    VecSetValuesBlockedLocal() sets x[bs*ix[i]+j] = y[bs*i+j],
1003:    for j=0,..bs-1, for i=0,...,ni-1, where bs has been set with VecSetBlockSize().

1005:    Calls to VecSetValuesBlockedLocal() with the INSERT_VALUES and ADD_VALUES
1006:    options cannot be mixed without intervening calls to the assembly
1007:    routines.

1009:    These values may be cached, so VecAssemblyBegin() and VecAssemblyEnd()
1010:    MUST be called after all calls to VecSetValuesBlockedLocal() have been completed.

1012:    VecSetValuesBlockedLocal() uses 0-based indices in Fortran as well as in C.

1014: .seealso: `VecAssemblyBegin()`, `VecAssemblyEnd()`, `VecSetValues()`, `VecSetValuesBlocked()`,
1015:           `VecSetLocalToGlobalMapping()`
1016: @*/
1017: PetscErrorCode VecSetValuesBlockedLocal(Vec x, PetscInt ni, const PetscInt ix[], const PetscScalar y[], InsertMode iora)
1018: {
1019:   PetscInt lixp[128], *lix = lixp;

1023:   if (!ni) return 0;
1027:   PetscLogEventBegin(VEC_SetValues, x, 0, 0, 0);
1028:   if (x->map->mapping) {
1029:     if (ni > 128) PetscMalloc1(ni, &lix);
1030:     ISLocalToGlobalMappingApplyBlock(x->map->mapping, ni, (PetscInt *)ix, lix);
1031:     PetscUseTypeMethod(x, setvaluesblocked, ni, lix, y, iora);
1032:     if (ni > 128) PetscFree(lix);
1033:   } else {
1034:     PetscUseTypeMethod(x, setvaluesblocked, ni, ix, y, iora);
1035:   }
1036:   PetscLogEventEnd(VEC_SetValues, x, 0, 0, 0);
1037:   PetscObjectStateIncrease((PetscObject)x);
1038:   return 0;
1039: }

1041: /*@
1042:    VecMTDot - Computes indefinite vector multiple dot products.
1043:    That is, it does NOT use the complex conjugate.

1045:    Collective on Vec

1047:    Input Parameters:
1048: +  x - one vector
1049: .  nv - number of vectors
1050: -  y - array of vectors.  Note that vectors are pointers

1052:    Output Parameter:
1053: .  val - array of the dot products

1055:    Notes for Users of Complex Numbers:
1056:    For complex vectors, VecMTDot() computes the indefinite form
1057: $      val = (x,y) = y^T x,
1058:    where y^T denotes the transpose of y.

1060:    Use VecMDot() for the inner product
1061: $      val = (x,y) = y^H x,
1062:    where y^H denotes the conjugate transpose of y.

1064:    Level: intermediate

1066: .seealso: `VecMDot()`, `VecTDot()`
1067: @*/
1068: PetscErrorCode VecMTDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1069: {
1073:   if (!nv) return 0;
1075:   for (PetscInt i = 0; i < nv; ++i) {
1079:     VecCheckSameSize(x, 1, y[i], 3);
1080:     VecLockReadPush(y[i]);
1081:   }

1084:   VecLockReadPush(x);
1085:   PetscLogEventBegin(VEC_MTDot, x, *y, 0, 0);
1086:   PetscUseTypeMethod(x, mtdot, nv, y, val);
1087:   PetscLogEventEnd(VEC_MTDot, x, *y, 0, 0);
1088:   VecLockReadPop(x);
1089:   for (PetscInt i = 0; i < nv; ++i) VecLockReadPop(y[i]);
1090:   return 0;
1091: }

1093: /*@
1094:    VecMDot - Computes vector multiple dot products.

1096:    Collective on Vec

1098:    Input Parameters:
1099: +  x - one vector
1100: .  nv - number of vectors
1101: -  y - array of vectors.

1103:    Output Parameter:
1104: .  val - array of the dot products (does not allocate the array)

1106:    Notes for Users of Complex Numbers:
1107:    For complex vectors, VecMDot() computes
1108: $     val = (x,y) = y^H x,
1109:    where y^H denotes the conjugate transpose of y.

1111:    Use VecMTDot() for the indefinite form
1112: $     val = (x,y) = y^T x,
1113:    where y^T denotes the transpose of y.

1115:    Level: intermediate

1117: .seealso: `VecMTDot()`, `VecDot()`
1118: @*/
1119: PetscErrorCode VecMDot(Vec x, PetscInt nv, const Vec y[], PetscScalar val[])
1120: {
1124:   if (!nv) return 0;
1126:   for (PetscInt i = 0; i < nv; ++i) {
1130:     VecCheckSameSize(x, 1, y[i], 3);
1131:     VecLockReadPush(y[i]);
1132:   }

1135:   VecLockReadPush(x);
1136:   PetscLogEventBegin(VEC_MDot, x, *y, 0, 0);
1137:   PetscUseTypeMethod(x, mdot, nv, y, val);
1138:   PetscLogEventEnd(VEC_MDot, x, *y, 0, 0);
1139:   VecLockReadPop(x);
1140:   for (PetscInt i = 0; i < nv; ++i) VecLockReadPop(y[i]);
1141:   return 0;
1142: }

1144: /*@
1145:    VecMAXPY - Computes y = y + sum alpha[i] x[i]

1147:    Logically Collective on Vec

1149:    Input Parameters:
1150: +  nv - number of scalars and x-vectors
1151: .  alpha - array of scalars
1152: .  y - one vector
1153: -  x - array of vectors

1155:    Level: intermediate

1157:    Notes:
1158:     y cannot be any of the x vectors

1160: .seealso: `VecAYPX()`, `VecWAXPY()`, `VecAXPY()`, `VecAXPBYPCZ()`, `VecAXPBY()`
1161: @*/
1162: PetscErrorCode VecMAXPY(Vec y, PetscInt nv, const PetscScalar alpha[], Vec x[])
1163: {
1166:   VecSetErrorIfLocked(y, 1);
1168:   if (nv) {
1169:     PetscInt zeros = 0;

1173:     for (PetscInt i = 0; i < nv; ++i) {
1178:       VecCheckSameSize(y, 1, x[i], 4);
1180:       VecLockReadPush(x[i]);
1181:       zeros += alpha[i] == (PetscScalar)0.0;
1182:     }

1184:     if (zeros < nv) {
1185:       PetscLogEventBegin(VEC_MAXPY, y, *x, 0, 0);
1186:       PetscUseTypeMethod(y, maxpy, nv, alpha, x);
1187:       PetscLogEventEnd(VEC_MAXPY, y, *x, 0, 0);
1188:       PetscObjectStateIncrease((PetscObject)y);
1189:     }

1191:     for (PetscInt i = 0; i < nv; ++i) VecLockReadPop(x[i]);
1192:   }
1193:   return 0;
1194: }

1196: /*@
1197:    VecConcatenate - Creates a new vector that is a vertical concatenation of all the given array of vectors
1198:                     in the order they appear in the array. The concatenated vector resides on the same
1199:                     communicator and is the same type as the source vectors.

1201:    Collective on X

1203:    Input Parameters:
1204: +  nx   - number of vectors to be concatenated
1205: -  X    - array containing the vectors to be concatenated in the order of concatenation

1207:    Output Parameters:
1208: +  Y    - concatenated vector
1209: -  x_is - array of index sets corresponding to the concatenated components of Y (NULL if not needed)

1211:    Notes:
1212:    Concatenation is similar to the functionality of a VecNest object; they both represent combination of
1213:    different vector spaces. However, concatenated vectors do not store any information about their
1214:    sub-vectors and own their own data. Consequently, this function provides index sets to enable the
1215:    manipulation of data in the concatenated vector that corresponds to the original components at creation.

1217:    This is a useful tool for outer loop algorithms, particularly constrained optimizers, where the solver
1218:    has to operate on combined vector spaces and cannot utilize VecNest objects due to incompatibility with
1219:    bound projections.

1221:    Level: advanced

1223: .seealso: `VECNEST`, `VECSCATTER`, `VecScatterCreate()`
1224: @*/
1225: PetscErrorCode VecConcatenate(PetscInt nx, const Vec X[], Vec *Y, IS *x_is[])
1226: {
1227:   MPI_Comm comm;
1228:   VecType  vec_type;
1229:   Vec      Ytmp, Xtmp;
1230:   IS      *is_tmp;
1231:   PetscInt i, shift = 0, Xnl, Xng, Xbegin;


1238:   if ((*X)->ops->concatenate) {
1239:     /* use the dedicated concatenation function if available */
1240:     (*(*X)->ops->concatenate)(nx, X, Y, x_is);
1241:   } else {
1242:     /* loop over vectors and start creating IS */
1243:     comm = PetscObjectComm((PetscObject)(*X));
1244:     VecGetType(*X, &vec_type);
1245:     PetscMalloc1(nx, &is_tmp);
1246:     for (i = 0; i < nx; i++) {
1247:       VecGetSize(X[i], &Xng);
1248:       VecGetLocalSize(X[i], &Xnl);
1249:       VecGetOwnershipRange(X[i], &Xbegin, NULL);
1250:       ISCreateStride(comm, Xnl, shift + Xbegin, 1, &is_tmp[i]);
1251:       shift += Xng;
1252:     }
1253:     /* create the concatenated vector */
1254:     VecCreate(comm, &Ytmp);
1255:     VecSetType(Ytmp, vec_type);
1256:     VecSetSizes(Ytmp, PETSC_DECIDE, shift);
1257:     VecSetUp(Ytmp);
1258:     /* copy data from X array to Y and return */
1259:     for (i = 0; i < nx; i++) {
1260:       VecGetSubVector(Ytmp, is_tmp[i], &Xtmp);
1261:       VecCopy(X[i], Xtmp);
1262:       VecRestoreSubVector(Ytmp, is_tmp[i], &Xtmp);
1263:     }
1264:     *Y = Ytmp;
1265:     if (x_is) {
1266:       *x_is = is_tmp;
1267:     } else {
1268:       for (i = 0; i < nx; i++) ISDestroy(&is_tmp[i]);
1269:       PetscFree(is_tmp);
1270:     }
1271:   }
1272:   return 0;
1273: }

1275: /* A helper function for VecGetSubVector to check if we can implement it with no-copy (i.e. the subvector shares
1276:    memory with the original vector), and the block size of the subvector.

1278:     Input Parameters:
1279: +   X - the original vector
1280: -   is - the index set of the subvector

1282:     Output Parameters:
1283: +   contig - PETSC_TRUE if the index set refers to contiguous entries on this process, else PETSC_FALSE
1284: .   start  - start of contiguous block, as an offset from the start of the ownership range of the original vector
1285: -   blocksize - the block size of the subvector

1287: */
1288: PetscErrorCode VecGetSubVectorContiguityAndBS_Private(Vec X, IS is, PetscBool *contig, PetscInt *start, PetscInt *blocksize)
1289: {
1290:   PetscInt  gstart, gend, lstart;
1291:   PetscBool red[2] = {PETSC_TRUE /*contiguous*/, PETSC_TRUE /*validVBS*/};
1292:   PetscInt  n, N, ibs, vbs, bs = -1;

1294:   ISGetLocalSize(is, &n);
1295:   ISGetSize(is, &N);
1296:   ISGetBlockSize(is, &ibs);
1297:   VecGetBlockSize(X, &vbs);
1298:   VecGetOwnershipRange(X, &gstart, &gend);
1299:   ISContiguousLocal(is, gstart, gend, &lstart, &red[0]);
1300:   /* block size is given by IS if ibs > 1; otherwise, check the vector */
1301:   if (ibs > 1) {
1302:     MPIU_Allreduce(MPI_IN_PLACE, red, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is));
1303:     bs = ibs;
1304:   } else {
1305:     if (n % vbs || vbs == 1) red[1] = PETSC_FALSE; /* this process invalidate the collectiveness of block size */
1306:     MPIU_Allreduce(MPI_IN_PLACE, red, 2, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)is));
1307:     if (red[0] && red[1]) bs = vbs; /* all processes have a valid block size and the access will be contiguous */
1308:   }

1310:   *contig    = red[0];
1311:   *start     = lstart;
1312:   *blocksize = bs;
1313:   return 0;
1314: }

1316: /* A helper function for VecGetSubVector, to be used when we have to build a standalone subvector through VecScatter

1318:     Input Parameters:
1319: +   X - the original vector
1320: .   is - the index set of the subvector
1321: -   bs - the block size of the subvector, gotten from VecGetSubVectorContiguityAndBS_Private()

1323:     Output Parameters:
1324: .   Z  - the subvector, which will compose the VecScatter context on output
1325: */
1326: PetscErrorCode VecGetSubVectorThroughVecScatter_Private(Vec X, IS is, PetscInt bs, Vec *Z)
1327: {
1328:   PetscInt   n, N;
1329:   VecScatter vscat;
1330:   Vec        Y;

1332:   ISGetLocalSize(is, &n);
1333:   ISGetSize(is, &N);
1334:   VecCreate(PetscObjectComm((PetscObject)is), &Y);
1335:   VecSetSizes(Y, n, N);
1336:   VecSetBlockSize(Y, bs);
1337:   VecSetType(Y, ((PetscObject)X)->type_name);
1338:   VecScatterCreate(X, is, Y, NULL, &vscat);
1339:   VecScatterBegin(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD);
1340:   VecScatterEnd(vscat, X, Y, INSERT_VALUES, SCATTER_FORWARD);
1341:   PetscObjectCompose((PetscObject)Y, "VecGetSubVector_Scatter", (PetscObject)vscat);
1342:   VecScatterDestroy(&vscat);
1343:   *Z = Y;
1344:   return 0;
1345: }

1347: /*@
1348:    VecGetSubVector - Gets a vector representing part of another vector

1350:    Collective on X and IS

1352:    Input Parameters:
1353: + X - vector from which to extract a subvector
1354: - is - index set representing portion of X to extract

1356:    Output Parameter:
1357: . Y - subvector corresponding to is

1359:    Level: advanced

1361:    Notes:
1362:    The subvector Y should be returned with VecRestoreSubVector().
1363:    X and is must be defined on the same communicator

1365:    This function may return a subvector without making a copy, therefore it is not safe to use the original vector while
1366:    modifying the subvector.  Other non-overlapping subvectors can still be obtained from X using this function.
1367:    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.

1369: .seealso: `MatCreateSubMatrix()`
1370: @*/
1371: PetscErrorCode VecGetSubVector(Vec X, IS is, Vec *Y)
1372: {
1373:   Vec Z;

1379:   if (X->ops->getsubvector) {
1380:     PetscUseTypeMethod(X, getsubvector, is, &Z);
1381:   } else { /* Default implementation currently does no caching */
1382:     PetscBool contig;
1383:     PetscInt  n, N, start, bs;

1385:     ISGetLocalSize(is, &n);
1386:     ISGetSize(is, &N);
1387:     VecGetSubVectorContiguityAndBS_Private(X, is, &contig, &start, &bs);
1388:     if (contig) { /* We can do a no-copy implementation */
1389:       const PetscScalar *x;
1390:       PetscInt           state = 0;
1391:       PetscBool          isstd, iscuda, iship;

1393:       PetscObjectTypeCompareAny((PetscObject)X, &isstd, VECSEQ, VECMPI, VECSTANDARD, "");
1394:       PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, "");
1395:       PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, "");
1396:       if (iscuda) {
1397: #if defined(PETSC_HAVE_CUDA)
1398:         const PetscScalar *x_d;
1399:         PetscMPIInt        size;
1400:         PetscOffloadMask   flg;

1402:         VecCUDAGetArrays_Private(X, &x, &x_d, &flg);
1405:         if (x) x += start;
1406:         if (x_d) x_d += start;
1407:         MPI_Comm_size(PetscObjectComm((PetscObject)X), &size);
1408:         if (size == 1) {
1409:           VecCreateSeqCUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z);
1410:         } else {
1411:           VecCreateMPICUDAWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z);
1412:         }
1413:         Z->offloadmask = flg;
1414: #endif
1415:       } else if (iship) {
1416: #if defined(PETSC_HAVE_HIP)
1417:         const PetscScalar *x_d;
1418:         PetscMPIInt        size;
1419:         PetscOffloadMask   flg;

1421:         VecHIPGetArrays_Private(X, &x, &x_d, &flg);
1424:         if (x) x += start;
1425:         if (x_d) x_d += start;
1426:         MPI_Comm_size(PetscObjectComm((PetscObject)X), &size);
1427:         if (size == 1) {
1428:           VecCreateSeqHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, x, x_d, &Z);
1429:         } else {
1430:           VecCreateMPIHIPWithArrays(PetscObjectComm((PetscObject)X), bs, n, N, x, x_d, &Z);
1431:         }
1432:         Z->offloadmask = flg;
1433: #endif
1434:       } else if (isstd) {
1435:         PetscMPIInt size;

1437:         MPI_Comm_size(PetscObjectComm((PetscObject)X), &size);
1438:         VecGetArrayRead(X, &x);
1439:         if (x) x += start;
1440:         if (size == 1) {
1441:           VecCreateSeqWithArray(PetscObjectComm((PetscObject)X), bs, n, x, &Z);
1442:         } else {
1443:           VecCreateMPIWithArray(PetscObjectComm((PetscObject)X), bs, n, N, x, &Z);
1444:         }
1445:         VecRestoreArrayRead(X, &x);
1446:       } else { /* default implementation: use place array */
1447:         VecGetArrayRead(X, &x);
1448:         VecCreate(PetscObjectComm((PetscObject)X), &Z);
1449:         VecSetType(Z, ((PetscObject)X)->type_name);
1450:         VecSetSizes(Z, n, N);
1451:         VecSetBlockSize(Z, bs);
1452:         VecPlaceArray(Z, x ? x + start : NULL);
1453:         VecRestoreArrayRead(X, &x);
1454:       }

1456:       /* this is relevant only in debug mode */
1457:       VecLockGet(X, &state);
1458:       if (state) VecLockReadPush(Z);
1459:       Z->ops->placearray   = NULL;
1460:       Z->ops->replacearray = NULL;
1461:     } else { /* Have to create a scatter and do a copy */
1462:       VecGetSubVectorThroughVecScatter_Private(X, is, bs, &Z);
1463:     }
1464:   }
1465:   /* Record the state when the subvector was gotten so we know whether its values need to be put back */
1466:   if (VecGetSubVectorSavedStateId < 0) PetscObjectComposedDataRegister(&VecGetSubVectorSavedStateId);
1467:   PetscObjectComposedDataSetInt((PetscObject)Z, VecGetSubVectorSavedStateId, 1);
1468:   *Y = Z;
1469:   return 0;
1470: }

1472: /*@
1473:    VecRestoreSubVector - Restores a subvector extracted using VecGetSubVector()

1475:    Collective on IS

1477:    Input Parameters:
1478: + X - vector from which subvector was obtained
1479: . is - index set representing the subset of X
1480: - Y - subvector being restored

1482:    Level: advanced

1484: .seealso: `VecGetSubVector()`
1485: @*/
1486: PetscErrorCode VecRestoreSubVector(Vec X, IS is, Vec *Y)
1487: {
1488:   PETSC_UNUSED PetscObjectState dummystate = 0;
1489:   PetscBool                     unchanged;


1497:   if (X->ops->restoresubvector) PetscUseTypeMethod(X, restoresubvector, is, Y);
1498:   else {
1499:     PetscObjectComposedDataGetInt((PetscObject)*Y, VecGetSubVectorSavedStateId, dummystate, unchanged);
1500:     if (!unchanged) { /* If Y's state has not changed since VecGetSubVector(), we only need to destroy Y */
1501:       VecScatter scatter;
1502:       PetscInt   state;

1504:       VecLockGet(X, &state);

1507:       PetscObjectQuery((PetscObject)*Y, "VecGetSubVector_Scatter", (PetscObject *)&scatter);
1508:       if (scatter) {
1509:         VecScatterBegin(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE);
1510:         VecScatterEnd(scatter, *Y, X, INSERT_VALUES, SCATTER_REVERSE);
1511:       } else {
1512:         PetscBool iscuda, iship;
1513:         PetscObjectTypeCompareAny((PetscObject)X, &iscuda, VECSEQCUDA, VECMPICUDA, "");
1514:         PetscObjectTypeCompareAny((PetscObject)X, &iship, VECSEQHIP, VECMPIHIP, "");

1516:         if (iscuda) {
1517: #if defined(PETSC_HAVE_CUDA)
1518:           PetscOffloadMask ymask = (*Y)->offloadmask;

1520:           /* The offloadmask of X dictates where to move memory
1521:               If X GPU data is valid, then move Y data on GPU if needed
1522:               Otherwise, move back to the CPU */
1523:           switch (X->offloadmask) {
1524:           case PETSC_OFFLOAD_BOTH:
1525:             if (ymask == PETSC_OFFLOAD_CPU) {
1526:               VecCUDAResetArray(*Y);
1527:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1528:               X->offloadmask = PETSC_OFFLOAD_GPU;
1529:             }
1530:             break;
1531:           case PETSC_OFFLOAD_GPU:
1532:             if (ymask == PETSC_OFFLOAD_CPU) VecCUDAResetArray(*Y);
1533:             break;
1534:           case PETSC_OFFLOAD_CPU:
1535:             if (ymask == PETSC_OFFLOAD_GPU) VecResetArray(*Y);
1536:             break;
1537:           case PETSC_OFFLOAD_UNALLOCATED:
1538:           case PETSC_OFFLOAD_KOKKOS:
1539:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1540:           }
1541: #endif
1542:         } else if (iship) {
1543: #if defined(PETSC_HAVE_HIP)
1544:           PetscOffloadMask ymask = (*Y)->offloadmask;

1546:           /* The offloadmask of X dictates where to move memory
1547:               If X GPU data is valid, then move Y data on GPU if needed
1548:               Otherwise, move back to the CPU */
1549:           switch (X->offloadmask) {
1550:           case PETSC_OFFLOAD_BOTH:
1551:             if (ymask == PETSC_OFFLOAD_CPU) {
1552:               VecHIPResetArray(*Y);
1553:             } else if (ymask == PETSC_OFFLOAD_GPU) {
1554:               X->offloadmask = PETSC_OFFLOAD_GPU;
1555:             }
1556:             break;
1557:           case PETSC_OFFLOAD_GPU:
1558:             if (ymask == PETSC_OFFLOAD_CPU) VecHIPResetArray(*Y);
1559:             break;
1560:           case PETSC_OFFLOAD_CPU:
1561:             if (ymask == PETSC_OFFLOAD_GPU) VecResetArray(*Y);
1562:             break;
1563:           case PETSC_OFFLOAD_UNALLOCATED:
1564:           case PETSC_OFFLOAD_KOKKOS:
1565:             SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "This should not happen");
1566:           }
1567: #endif
1568:         } else {
1569:           /* If OpenCL vecs updated the device memory, this triggers a copy on the CPU */
1570:           VecResetArray(*Y);
1571:         }
1572:         PetscObjectStateIncrease((PetscObject)X);
1573:       }
1574:     }
1575:   }
1576:   VecDestroy(Y);
1577:   return 0;
1578: }

1580: /*@
1581:    VecCreateLocalVector - Creates a vector object suitable for use with VecGetLocalVector() and friends. You must call VecDestroy() when the
1582:    vector is no longer needed.

1584:    Not collective.

1586:    Input parameter:
1587: .  v - The vector for which the local vector is desired.

1589:    Output parameter:
1590: .  w - Upon exit this contains the local vector.

1592:    Level: beginner

1594: .seealso: `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecRestoreLocalVector()`
1595: @*/
1596: PetscErrorCode VecCreateLocalVector(Vec v, Vec *w)
1597: {
1598:   PetscMPIInt size;

1602:   MPI_Comm_size(PetscObjectComm((PetscObject)v), &size);
1603:   if (size == 1) VecDuplicate(v, w);
1604:   else if (v->ops->createlocalvector) PetscUseTypeMethod(v, createlocalvector, w);
1605:   else {
1606:     VecType  type;
1607:     PetscInt n;

1609:     VecCreate(PETSC_COMM_SELF, w);
1610:     VecGetLocalSize(v, &n);
1611:     VecSetSizes(*w, n, n);
1612:     VecGetBlockSize(v, &n);
1613:     VecSetBlockSize(*w, n);
1614:     VecGetType(v, &type);
1615:     VecSetType(*w, type);
1616:   }
1617:   return 0;
1618: }

1620: /*@
1621:    VecGetLocalVectorRead - Maps the local portion of a vector into a
1622:    vector.  You must call VecRestoreLocalVectorRead() when the local
1623:    vector is no longer needed.

1625:    Not collective.

1627:    Input parameter:
1628: .  v - The vector for which the local vector is desired.

1630:    Output parameter:
1631: .  w - Upon exit this contains the local vector.

1633:    Level: beginner

1635:    Notes:
1636:    This function is similar to VecGetArrayRead() which maps the local
1637:    portion into a raw pointer.  VecGetLocalVectorRead() is usually
1638:    almost as efficient as VecGetArrayRead() but in certain circumstances
1639:    VecGetLocalVectorRead() can be much more efficient than
1640:    VecGetArrayRead().  This is because the construction of a contiguous
1641:    array representing the vector data required by VecGetArrayRead() can
1642:    be an expensive operation for certain vector types.  For example, for
1643:    GPU vectors VecGetArrayRead() requires that the data between device
1644:    and host is synchronized.

1646:    Unlike VecGetLocalVector(), this routine is not collective and
1647:    preserves cached information.

1649: .seealso: `VecCreateLocalVector()`, `VecRestoreLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1650: @*/
1651: PetscErrorCode VecGetLocalVectorRead(Vec v, Vec w)
1652: {
1655:   VecCheckSameLocalSize(v, 1, w, 2);
1656:   if (v->ops->getlocalvectorread) {
1657:     PetscUseTypeMethod(v, getlocalvectorread, w);
1658:   } else {
1659:     PetscScalar *a;

1661:     VecGetArrayRead(v, (const PetscScalar **)&a);
1662:     VecPlaceArray(w, a);
1663:   }
1664:   PetscObjectStateIncrease((PetscObject)w);
1665:   VecLockReadPush(v);
1666:   VecLockReadPush(w);
1667:   return 0;
1668: }

1670: /*@
1671:    VecRestoreLocalVectorRead - Unmaps the local portion of a vector
1672:    previously mapped into a vector using VecGetLocalVectorRead().

1674:    Not collective.

1676:    Input parameter:
1677: +  v - The local portion of this vector was previously mapped into w using VecGetLocalVectorRead().
1678: -  w - The vector into which the local portion of v was mapped.

1680:    Level: beginner

1682: .seealso: `VecCreateLocalVector()`, `VecGetLocalVectorRead()`, `VecGetLocalVector()`, `VecGetArrayRead()`, `VecGetArray()`
1683: @*/
1684: PetscErrorCode VecRestoreLocalVectorRead(Vec v, Vec w)
1685: {
1688:   if (v->ops->restorelocalvectorread) {
1689:     PetscUseTypeMethod(v, restorelocalvectorread, w);
1690:   } else {
1691:     const PetscScalar *a;

1693:     VecGetArrayRead(w, &a);
1694:     VecRestoreArrayRead(v, &a);
1695:     VecResetArray(w);
1696:   }
1697:   VecLockReadPop(v);
1698:   VecLockReadPop(w);
1699:   PetscObjectStateIncrease((PetscObject)w);
1700:   return 0;
1701: }

1703: /*@
1704:    VecGetLocalVector - Maps the local portion of a vector into a
1705:    vector.

1707:    Collective on v, not collective on w.

1709:    Input parameter:
1710: .  v - The vector for which the local vector is desired.

1712:    Output parameter:
1713: .  w - Upon exit this contains the local vector.

1715:    Level: beginner

1717:    Notes:
1718:    This function is similar to VecGetArray() which maps the local
1719:    portion into a raw pointer.  VecGetLocalVector() is usually about as
1720:    efficient as VecGetArray() but in certain circumstances
1721:    VecGetLocalVector() can be much more efficient than VecGetArray().
1722:    This is because the construction of a contiguous array representing
1723:    the vector data required by VecGetArray() can be an expensive
1724:    operation for certain vector types.  For example, for GPU vectors
1725:    VecGetArray() requires that the data between device and host is
1726:    synchronized.

1728: .seealso: `VecCreateLocalVector()`, `VecRestoreLocalVector()`, `VecGetLocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1729: @*/
1730: PetscErrorCode VecGetLocalVector(Vec v, Vec w)
1731: {
1734:   VecCheckSameLocalSize(v, 1, w, 2);
1735:   if (v->ops->getlocalvector) {
1736:     PetscUseTypeMethod(v, getlocalvector, w);
1737:   } else {
1738:     PetscScalar *a;

1740:     VecGetArray(v, &a);
1741:     VecPlaceArray(w, a);
1742:   }
1743:   PetscObjectStateIncrease((PetscObject)w);
1744:   return 0;
1745: }

1747: /*@
1748:    VecRestoreLocalVector - Unmaps the local portion of a vector
1749:    previously mapped into a vector using VecGetLocalVector().

1751:    Logically collective.

1753:    Input parameter:
1754: +  v - The local portion of this vector was previously mapped into w using VecGetLocalVector().
1755: -  w - The vector into which the local portion of v was mapped.

1757:    Level: beginner

1759: .seealso: `VecCreateLocalVector()`, `VecGetLocalVector()`, `VecGetLocalVectorRead()`, `VecRestoreLocalVectorRead()`, `LocalVectorRead()`, `VecGetArrayRead()`, `VecGetArray()`
1760: @*/
1761: PetscErrorCode VecRestoreLocalVector(Vec v, Vec w)
1762: {
1765:   if (v->ops->restorelocalvector) {
1766:     PetscUseTypeMethod(v, restorelocalvector, w);
1767:   } else {
1768:     PetscScalar *a;
1769:     VecGetArray(w, &a);
1770:     VecRestoreArray(v, &a);
1771:     VecResetArray(w);
1772:   }
1773:   PetscObjectStateIncrease((PetscObject)w);
1774:   PetscObjectStateIncrease((PetscObject)v);
1775:   return 0;
1776: }

1778: /*@C
1779:    VecGetArray - Returns a pointer to a contiguous array that contains this
1780:    processor's portion of the vector data. For the standard PETSc
1781:    vectors, VecGetArray() returns a pointer to the local data array and
1782:    does not use any copies. If the underlying vector data is not stored
1783:    in a contiguous array this routine will copy the data to a contiguous
1784:    array and return a pointer to that. You MUST call VecRestoreArray()
1785:    when you no longer need access to the array.

1787:    Logically Collective on Vec

1789:    Input Parameter:
1790: .  x - the vector

1792:    Output Parameter:
1793: .  a - location to put pointer to the array

1795:    Fortran Note:
1796:    This routine is used differently from Fortran 77
1797: $    Vec         x
1798: $    PetscScalar x_array(1)
1799: $    PetscOffset i_x
1800: $    PetscErrorCode ierr
1801: $       call VecGetArray(x,x_array,i_x,ierr)
1802: $
1803: $   Access first local entry in vector with
1804: $      value = x_array(i_x + 1)
1805: $
1806: $      ...... other code
1807: $       call VecRestoreArray(x,x_array,i_x,ierr)
1808:    For Fortran 90 see VecGetArrayF90()

1810:    See the Fortran chapter of the users manual and
1811:    petsc/src/snes/tutorials/ex5f.F for details.

1813:    Level: beginner

1815: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
1816:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
1817: @*/
1818: PetscErrorCode VecGetArray(Vec x, PetscScalar **a)
1819: {
1821:   VecSetErrorIfLocked(x, 1);
1822:   if (x->ops->getarray) { /* The if-else order matters! VECNEST, VECCUDA etc should have ops->getarray while VECCUDA etc are petscnative */
1823:     PetscUseTypeMethod(x, getarray, a);
1824:   } else if (x->petscnative) { /* VECSTANDARD */
1825:     *a = *((PetscScalar **)x->data);
1826:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array for vector type \"%s\"", ((PetscObject)x)->type_name);
1827:   return 0;
1828: }

1830: /*@C
1831:    VecRestoreArray - Restores a vector after VecGetArray() has been called.

1833:    Logically Collective on Vec

1835:    Input Parameters:
1836: +  x - the vector
1837: -  a - location of pointer to array obtained from VecGetArray()

1839:    Level: beginner

1841: .seealso: `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
1842:           `VecGetArrayPair()`, `VecRestoreArrayPair()`
1843: @*/
1844: PetscErrorCode VecRestoreArray(Vec x, PetscScalar **a)
1845: {
1848:   if (x->ops->restorearray) {
1849:     PetscUseTypeMethod(x, restorearray, a);
1851:   if (a) *a = NULL;
1852:   PetscObjectStateIncrease((PetscObject)x);
1853:   return 0;
1854: }
1855: /*@C
1856:    VecGetArrayRead - Get read-only pointer to contiguous array containing this processor's portion of the vector data.

1858:    Not Collective

1860:    Input Parameter:
1861: .  x - the vector

1863:    Output Parameter:
1864: .  a - the array

1866:    Level: beginner

1868:    Notes:
1869:    The array must be returned using a matching call to VecRestoreArrayRead().

1871:    Unlike VecGetArray(), this routine is not collective and preserves cached information like vector norms.

1873:    Standard PETSc vectors use contiguous storage so that this routine does not perform a copy.  Other vector
1874:    implementations may require a copy, but must such implementations should cache the contiguous representation so that
1875:    only one copy is performed when this routine is called multiple times in sequence.

1877: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1878: @*/
1879: PetscErrorCode VecGetArrayRead(Vec x, const PetscScalar **a)
1880: {
1883:   if (x->ops->getarrayread) {
1884:     PetscUseTypeMethod(x, getarrayread, a);
1885:   } else if (x->ops->getarray) {
1886:     /* VECNEST, VECCUDA, VECKOKKOS etc */
1887:     PetscUseTypeMethod(x, getarray, (PetscScalar **)a);
1888:   } else if (x->petscnative) {
1889:     /* VECSTANDARD */
1890:     *a = *((PetscScalar **)x->data);
1891:   } else SETERRQ(PetscObjectComm((PetscObject)x), PETSC_ERR_SUP, "Cannot get array read for vector type \"%s\"", ((PetscObject)x)->type_name);
1892:   return 0;
1893: }

1895: /*@C
1896:    VecRestoreArrayRead - Restore array obtained with VecGetArrayRead()

1898:    Not Collective

1900:    Input Parameters:
1901: +  vec - the vector
1902: -  array - the array

1904:    Level: beginner

1906: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
1907: @*/
1908: PetscErrorCode VecRestoreArrayRead(Vec x, const PetscScalar **a)
1909: {
1912:   if (x->petscnative) { /* VECSTANDARD, VECCUDA, VECKOKKOS etc */
1913:     /* nothing */
1914:   } else if (x->ops->restorearrayread) { /* VECNEST */
1915:     PetscUseTypeMethod(x, restorearrayread, a);
1916:   } else { /* No one? */
1917:     PetscUseTypeMethod(x, restorearray, (PetscScalar **)a);
1918:   }
1919:   if (a) *a = NULL;
1920:   return 0;
1921: }

1923: /*@C
1924:    VecGetArrayWrite - Returns a pointer to a contiguous array that WILL contains this
1925:    processor's portion of the vector data. The values in this array are NOT valid, the routine calling this
1926:    routine is responsible for putting values into the array; any values it does not set will be invalid

1928:    Logically Collective on Vec

1930:    Input Parameter:
1931: .  x - the vector

1933:    Output Parameter:
1934: .  a - location to put pointer to the array

1936:    Level: intermediate

1938:    This is for vectors associate with GPUs, the vector is not copied up before giving access. If you need correct
1939:    values in the array use VecGetArray()

1941: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`, `VecPlaceArray()`, `VecGetArray2d()`,
1942:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArray()`, `VecRestoreArrayWrite()`
1943: @*/
1944: PetscErrorCode VecGetArrayWrite(Vec x, PetscScalar **a)
1945: {
1948:   VecSetErrorIfLocked(x, 1);
1949:   if (x->ops->getarraywrite) {
1950:     PetscUseTypeMethod(x, getarraywrite, a);
1951:   } else {
1952:     VecGetArray(x, a);
1953:   }
1954:   return 0;
1955: }

1957: /*@C
1958:    VecRestoreArrayWrite - Restores a vector after VecGetArrayWrite() has been called.

1960:    Logically Collective on Vec

1962:    Input Parameters:
1963: +  x - the vector
1964: -  a - location of pointer to array obtained from VecGetArray()

1966:    Level: beginner

1968: .seealso: `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`, `VecPlaceArray()`, `VecRestoreArray2d()`,
1969:           `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`
1970: @*/
1971: PetscErrorCode VecRestoreArrayWrite(Vec x, PetscScalar **a)
1972: {
1975:   if (x->ops->restorearraywrite) {
1976:     PetscUseTypeMethod(x, restorearraywrite, a);
1977:   } else if (x->ops->restorearray) {
1978:     PetscUseTypeMethod(x, restorearray, a);
1979:   }
1980:   if (a) *a = NULL;
1981:   PetscObjectStateIncrease((PetscObject)x);
1982:   return 0;
1983: }

1985: /*@C
1986:    VecGetArrays - Returns a pointer to the arrays in a set of vectors
1987:    that were created by a call to VecDuplicateVecs().  You MUST call
1988:    VecRestoreArrays() when you no longer need access to the array.

1990:    Logically Collective on Vec

1992:    Input Parameters:
1993: +  x - the vectors
1994: -  n - the number of vectors

1996:    Output Parameter:
1997: .  a - location to put pointer to the array

1999:    Fortran Note:
2000:    This routine is not supported in Fortran.

2002:    Level: intermediate

2004: .seealso: `VecGetArray()`, `VecRestoreArrays()`
2005: @*/
2006: PetscErrorCode VecGetArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2007: {
2008:   PetscInt      i;
2009:   PetscScalar **q;

2015:   PetscMalloc1(n, &q);
2016:   for (i = 0; i < n; ++i) VecGetArray(x[i], &q[i]);
2017:   *a = q;
2018:   return 0;
2019: }

2021: /*@C
2022:    VecRestoreArrays - Restores a group of vectors after VecGetArrays()
2023:    has been called.

2025:    Logically Collective on Vec

2027:    Input Parameters:
2028: +  x - the vector
2029: .  n - the number of vectors
2030: -  a - location of pointer to arrays obtained from VecGetArrays()

2032:    Notes:
2033:    For regular PETSc vectors this routine does not involve any copies. For
2034:    any special vectors that do not store local vector data in a contiguous
2035:    array, this routine will copy the data back into the underlying
2036:    vector data structure from the arrays obtained with VecGetArrays().

2038:    Fortran Note:
2039:    This routine is not supported in Fortran.

2041:    Level: intermediate

2043: .seealso: `VecGetArrays()`, `VecRestoreArray()`
2044: @*/
2045: PetscErrorCode VecRestoreArrays(const Vec x[], PetscInt n, PetscScalar **a[])
2046: {
2047:   PetscInt      i;
2048:   PetscScalar **q = *a;


2054:   for (i = 0; i < n; ++i) VecRestoreArray(x[i], &q[i]);
2055:   PetscFree(q);
2056:   return 0;
2057: }

2059: /*@C
2060:    VecGetArrayAndMemType - Like VecGetArray(), but if this is a standard device vector (e.g., VECCUDA), the returned pointer will be a device
2061:    pointer to the device memory that contains this processor's portion of the vector data. Device data is guaranteed to have the latest value.
2062:    Otherwise, when this is a host vector (e.g., VECMPI), this routine functions the same as VecGetArray() and returns a host pointer.

2064:    For VECKOKKOS, if Kokkos is configured without device (e.g., use serial or openmp), per this function, the vector works like VECSEQ/VECMPI;
2065:    otherwise, it works like VECCUDA or VECHIP etc.

2067:    Logically Collective on Vec

2069:    Input Parameter:
2070: .  x - the vector

2072:    Output Parameters:
2073: +  a - location to put pointer to the array
2074: -  mtype - memory type of the array

2076:    Level: beginner

2078: .seealso: `VecRestoreArrayAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecGetArrayReadF90()`,
2079:           `VecPlaceArray()`, `VecGetArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayWrite()`, `VecRestoreArrayWrite()`
2080: @*/
2081: PetscErrorCode VecGetArrayAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2082: {
2087:   VecSetErrorIfLocked(x, 1);
2088:   if (x->ops->getarrayandmemtype) {
2089:     /* VECCUDA, VECKOKKOS etc */
2090:     PetscUseTypeMethod(x, getarrayandmemtype, a, mtype);
2091:   } else {
2092:     /* VECSTANDARD, VECNEST, VECVIENNACL */
2093:     VecGetArray(x, a);
2094:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2095:   }
2096:   return 0;
2097: }

2099: /*@C
2100:    VecRestoreArrayAndMemType - Restores a vector after VecGetArrayAndMemType() has been called.

2102:    Logically Collective on Vec

2104:    Input Parameters:
2105: +  x - the vector
2106: -  a - location of pointer to array obtained from VecGetArrayAndMemType()

2108:    Level: beginner

2110: .seealso: `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArrayRead()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecRestoreArrayReadF90()`,
2111:           `VecPlaceArray()`, `VecRestoreArray2d()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2112: @*/
2113: PetscErrorCode VecRestoreArrayAndMemType(Vec x, PetscScalar **a)
2114: {
2118:   if (x->ops->restorearrayandmemtype) {
2119:     /* VECCUDA, VECKOKKOS etc */
2120:     PetscUseTypeMethod(x, restorearrayandmemtype, a);
2121:   } else {
2122:     /* VECNEST, VECVIENNACL */
2123:     VecRestoreArray(x, a);
2124:   } /* VECSTANDARD does nothing */
2125:   if (a) *a = NULL;
2126:   PetscObjectStateIncrease((PetscObject)x);
2127:   return 0;
2128: }

2130: /*@C
2131:    VecGetArrayReadAndMemType - Like VecGetArrayRead(), but if the input vector is a device vector, it will return a read-only device pointer. The returned pointer is guarenteed to point to up-to-date data. For host vectors, it functions as VecGetArrayRead().

2133:    Not Collective

2135:    Input Parameter:
2136: .  x - the vector

2138:    Output Parameters:
2139: +  a - the array
2140: -  mtype - memory type of the array

2142:    Level: beginner

2144:    Notes:
2145:    The array must be returned using a matching call to VecRestoreArrayReadAndMemType().

2147: .seealso: `VecRestoreArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`, `VecGetArrayAndMemType()`
2148: @*/
2149: PetscErrorCode VecGetArrayReadAndMemType(Vec x, const PetscScalar **a, PetscMemType *mtype)
2150: {
2155:   if (x->ops->getarrayreadandmemtype) {
2156:     /* VECCUDA/VECHIP though they are also petscnative */
2157:     PetscUseTypeMethod(x, getarrayreadandmemtype, a, mtype);
2158:   } else if (x->ops->getarrayandmemtype) {
2159:     /* VECKOKKOS */
2160:     PetscUseTypeMethod(x, getarrayandmemtype, (PetscScalar **)a, mtype);
2161:   } else {
2162:     VecGetArrayRead(x, a);
2163:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2164:   }
2165:   return 0;
2166:   return 0;
2167: }

2169: /*@C
2170:    VecRestoreArrayReadAndMemType - Restore array obtained with VecGetArrayReadAndMemType()

2172:    Not Collective

2174:    Input Parameters:
2175: +  vec - the vector
2176: -  array - the array

2178:    Level: beginner

2180: .seealso: `VecGetArrayReadAndMemType()`, `VecRestoreArrayAndMemType()`, `VecRestoreArrayWriteAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2181: @*/
2182: PetscErrorCode VecRestoreArrayReadAndMemType(Vec x, const PetscScalar **a)
2183: {
2187:   if (x->ops->restorearrayreadandmemtype) {
2188:     /* VECCUDA/VECHIP */
2189:     PetscUseTypeMethod(x, restorearrayreadandmemtype, a);
2190:   } else if (!x->petscnative) {
2191:     /* VECNEST */
2192:     VecRestoreArrayRead(x, a);
2193:   }
2194:   if (a) *a = NULL;
2195:   return 0;
2196: }

2198: /*@C
2199:    VecGetArrayWriteAndMemType - Like VecGetArrayWrite(), but if this is a device vector it will aways return
2200:     a device pointer to the device memory that contains this processor's portion of the vector data.

2202:    Not Collective

2204:    Input Parameter:
2205: .  x - the vector

2207:    Output Parameters:
2208: +  a - the array
2209: -  mtype - memory type of the array

2211:    Level: beginner

2213:    Notes:
2214:    The array must be returned using a matching call to VecRestoreArrayWriteAndMemType(), where it will label the device memory as most recent.

2216: .seealso: `VecRestoreArrayWriteAndMemType()`, `VecGetArrayReadAndMemType()`, `VecGetArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`,
2217: @*/
2218: PetscErrorCode VecGetArrayWriteAndMemType(Vec x, PetscScalar **a, PetscMemType *mtype)
2219: {
2222:   VecSetErrorIfLocked(x, 1);
2225:   if (x->ops->getarraywriteandmemtype) {
2226:     /* VECCUDA, VECHIP, VECKOKKOS etc, though they are also petscnative */
2227:     PetscUseTypeMethod(x, getarraywriteandmemtype, a, mtype);
2228:   } else if (x->ops->getarrayandmemtype) {
2229:     VecGetArrayAndMemType(x, a, mtype);
2230:   } else {
2231:     /* VECNEST, VECVIENNACL */
2232:     VecGetArrayWrite(x, a);
2233:     if (mtype) *mtype = PETSC_MEMTYPE_HOST;
2234:   }
2235:   return 0;
2236: }

2238: /*@C
2239:    VecRestoreArrayWriteAndMemType - Restore array obtained with VecGetArrayWriteAndMemType()

2241:    Not Collective

2243:    Input Parameters:
2244: +  vec - the vector
2245: -  array - the array

2247:    Level: beginner

2249: .seealso: `VecGetArrayWriteAndMemType()`, `VecRestoreArrayAndMemType()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayPair()`, `VecRestoreArrayPair()`
2250: @*/
2251: PetscErrorCode VecRestoreArrayWriteAndMemType(Vec x, PetscScalar **a)
2252: {
2255:   VecSetErrorIfLocked(x, 1);
2257:   if (x->ops->restorearraywriteandmemtype) {
2258:     /* VECCUDA/VECHIP */
2259:     PetscMemType PETSC_UNUSED mtype; // since this function doesn't accept a memtype?
2260:     PetscUseTypeMethod(x, restorearraywriteandmemtype, a, &mtype);
2261:   } else if (x->ops->restorearrayandmemtype) {
2262:     VecRestoreArrayAndMemType(x, a);
2263:   } else {
2264:     VecRestoreArray(x, a);
2265:   }
2266:   if (a) *a = NULL;
2267:   return 0;
2268: }

2270: /*@
2271:    VecPlaceArray - Allows one to replace the array in a vector with an
2272:    array provided by the user. This is useful to avoid copying an array
2273:    into a vector.

2275:    Not Collective

2277:    Input Parameters:
2278: +  vec - the vector
2279: -  array - the array

2281:    Notes:
2282:    You can return to the original array with a call to `VecResetArray()`. `vec` does not take
2283:    ownership of `array` in any way. The user must free `array` themselves but be careful not to
2284:    do so before the vector has either been destroyed, had its original array restored with
2285:    `VecResetArray()` or permanently replaced with `VecReplaceArray()`.

2287:    Level: developer

2289: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`

2291: @*/
2292: PetscErrorCode VecPlaceArray(Vec vec, const PetscScalar array[])
2293: {
2297:   PetscUseTypeMethod(vec, placearray, array);
2298:   PetscObjectStateIncrease((PetscObject)vec);
2299:   return 0;
2300: }

2302: /*@C
2303:    VecReplaceArray - Allows one to replace the array in a vector with an
2304:    array provided by the user. This is useful to avoid copying an array
2305:    into a vector.

2307:    Not Collective

2309:    Input Parameters:
2310: +  vec - the vector
2311: -  array - the array

2313:    Notes:
2314:    This permanently replaces the array and frees the memory associated
2315:    with the old array.

2317:    The memory passed in MUST be obtained with PetscMalloc() and CANNOT be
2318:    freed by the user. It will be freed when the vector is destroyed.

2320:    Not supported from Fortran

2322:    Level: developer

2324: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`

2326: @*/
2327: PetscErrorCode VecReplaceArray(Vec vec, const PetscScalar array[])
2328: {
2331:   PetscUseTypeMethod(vec, replacearray, array);
2332:   PetscObjectStateIncrease((PetscObject)vec);
2333:   return 0;
2334: }

2336: /*@C
2337:    VecCUDAGetArray - Provides access to the CUDA buffer inside a vector.

2339:    This function has semantics similar to VecGetArray():  the pointer
2340:    returned by this function points to a consistent view of the vector
2341:    data.  This may involve a copy operation of data from the host to the
2342:    device if the data on the device is out of date.  If the device
2343:    memory hasn't been allocated previously it will be allocated as part
2344:    of this function call.  VecCUDAGetArray() assumes that
2345:    the user will modify the vector data.  This is similar to
2346:    intent(inout) in fortran.

2348:    The CUDA device pointer has to be released by calling
2349:    VecCUDARestoreArray().  Upon restoring the vector data
2350:    the data on the host will be marked as out of date.  A subsequent
2351:    access of the host data will thus incur a data transfer from the
2352:    device to the host.

2354:    Input Parameter:
2355: .  v - the vector

2357:    Output Parameter:
2358: .  a - the CUDA device pointer

2360:    Fortran note:
2361:    This function is not currently available from Fortran.

2363:    Level: intermediate

2365: .seealso: `VecCUDARestoreArray()`, `VecCUDAGetArrayRead()`, `VecCUDAGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2366: @*/
2367: PETSC_EXTERN PetscErrorCode VecCUDAGetArray(Vec v, PetscScalar **a)
2368: {
2370: #if defined(PETSC_HAVE_CUDA)
2371:   {
2372:     VecCUDACopyToGPU(v);
2373:     *a = ((Vec_CUDA *)v->spptr)->GPUarray;
2374:   }
2375: #endif
2376:   return 0;
2377: }

2379: /*@C
2380:    VecCUDARestoreArray - Restore a CUDA device pointer previously acquired with VecCUDAGetArray().

2382:    This marks the host data as out of date.  Subsequent access to the
2383:    vector data on the host side with for instance VecGetArray() incurs a
2384:    data transfer.

2386:    Input Parameters:
2387: +  v - the vector
2388: -  a - the CUDA device pointer.  This pointer is invalid after
2389:        VecCUDARestoreArray() returns.

2391:    Fortran note:
2392:    This function is not currently available from Fortran.

2394:    Level: intermediate

2396: .seealso: `VecCUDAGetArray()`, `VecCUDAGetArrayRead()`, `VecCUDAGetArrayWrite()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2397: @*/
2398: PETSC_EXTERN PetscErrorCode VecCUDARestoreArray(Vec v, PetscScalar **a)
2399: {
2401: #if defined(PETSC_HAVE_CUDA)
2402:   v->offloadmask = PETSC_OFFLOAD_GPU;
2403: #endif
2404:   PetscObjectStateIncrease((PetscObject)v);
2405:   return 0;
2406: }

2408: /*@C
2409:    VecCUDAGetArrayRead - Provides read access to the CUDA buffer inside a vector.

2411:    This function is analogous to VecGetArrayRead():  The pointer
2412:    returned by this function points to a consistent view of the vector
2413:    data.  This may involve a copy operation of data from the host to the
2414:    device if the data on the device is out of date.  If the device
2415:    memory hasn't been allocated previously it will be allocated as part
2416:    of this function call.  VecCUDAGetArrayRead() assumes that the
2417:    user will not modify the vector data.  This is analgogous to
2418:    intent(in) in Fortran.

2420:    The CUDA device pointer has to be released by calling
2421:    VecCUDARestoreArrayRead().  If the data on the host side was
2422:    previously up to date it will remain so, i.e. data on both the device
2423:    and the host is up to date.  Accessing data on the host side does not
2424:    incur a device to host data transfer.

2426:    Input Parameter:
2427: .  v - the vector

2429:    Output Parameter:
2430: .  a - the CUDA pointer.

2432:    Fortran note:
2433:    This function is not currently available from Fortran.

2435:    Level: intermediate

2437: .seealso: `VecCUDARestoreArrayRead()`, `VecCUDAGetArray()`, `VecCUDAGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2438: @*/
2439: PETSC_EXTERN PetscErrorCode VecCUDAGetArrayRead(Vec v, const PetscScalar **a)
2440: {
2441:   VecCUDAGetArray(v, (PetscScalar **)a);
2442:   return 0;
2443: }

2445: /*@C
2446:    VecCUDARestoreArrayRead - Restore a CUDA device pointer previously acquired with VecCUDAGetArrayRead().

2448:    If the data on the host side was previously up to date it will remain
2449:    so, i.e. data on both the device and the host is up to date.
2450:    Accessing data on the host side e.g. with VecGetArray() does not
2451:    incur a device to host data transfer.

2453:    Input Parameters:
2454: +  v - the vector
2455: -  a - the CUDA device pointer.  This pointer is invalid after
2456:        VecCUDARestoreArrayRead() returns.

2458:    Fortran note:
2459:    This function is not currently available from Fortran.

2461:    Level: intermediate

2463: .seealso: `VecCUDAGetArrayRead()`, `VecCUDAGetArrayWrite()`, `VecCUDAGetArray()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2464: @*/
2465: PETSC_EXTERN PetscErrorCode VecCUDARestoreArrayRead(Vec v, const PetscScalar **a)
2466: {
2468:   *a = NULL;
2469:   return 0;
2470: }

2472: /*@C
2473:    VecCUDAGetArrayWrite - Provides write access to the CUDA buffer inside a vector.

2475:    The data pointed to by the device pointer is uninitialized.  The user
2476:    may not read from this data.  Furthermore, the entire array needs to
2477:    be filled by the user to obtain well-defined behaviour.  The device
2478:    memory will be allocated by this function if it hasn't been allocated
2479:    previously.  This is analogous to intent(out) in Fortran.

2481:    The device pointer needs to be released with
2482:    VecCUDARestoreArrayWrite().  When the pointer is released the
2483:    host data of the vector is marked as out of data.  Subsequent access
2484:    of the host data with e.g. VecGetArray() incurs a device to host data
2485:    transfer.

2487:    Input Parameter:
2488: .  v - the vector

2490:    Output Parameter:
2491: .  a - the CUDA pointer

2493:    Fortran note:
2494:    This function is not currently available from Fortran.

2496:    Level: advanced

2498: .seealso: `VecCUDARestoreArrayWrite()`, `VecCUDAGetArray()`, `VecCUDAGetArrayRead()`, `VecCUDAGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2499: @*/
2500: PETSC_EXTERN PetscErrorCode VecCUDAGetArrayWrite(Vec v, PetscScalar **a)
2501: {
2503: #if defined(PETSC_HAVE_CUDA)
2504:   {
2505:     VecCUDAAllocateCheck(v);
2506:     *a = ((Vec_CUDA *)v->spptr)->GPUarray;
2507:   }
2508: #endif
2509:   return 0;
2510: }

2512: /*@C
2513:    VecCUDARestoreArrayWrite - Restore a CUDA device pointer previously acquired with VecCUDAGetArrayWrite().

2515:    Data on the host will be marked as out of date.  Subsequent access of
2516:    the data on the host side e.g. with VecGetArray() will incur a device
2517:    to host data transfer.

2519:    Input Parameters:
2520: +  v - the vector
2521: -  a - the CUDA device pointer.  This pointer is invalid after
2522:        VecCUDARestoreArrayWrite() returns.

2524:    Fortran note:
2525:    This function is not currently available from Fortran.

2527:    Level: intermediate

2529: .seealso: `VecCUDAGetArrayWrite()`, `VecCUDAGetArray()`, `VecCUDAGetArrayRead()`, `VecCUDAGetArrayWrite()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2530: @*/
2531: PETSC_EXTERN PetscErrorCode VecCUDARestoreArrayWrite(Vec v, PetscScalar **a)
2532: {
2534: #if defined(PETSC_HAVE_CUDA)
2535:   v->offloadmask = PETSC_OFFLOAD_GPU;
2536:   if (a) *a = NULL;
2537: #endif
2538:   PetscObjectStateIncrease((PetscObject)v);
2539:   return 0;
2540: }

2542: /*@C
2543:    VecCUDAPlaceArray - Allows one to replace the GPU array in a vector with a
2544:    GPU array provided by the user. This is useful to avoid copying an
2545:    array into a vector.

2547:    Not Collective

2549:    Input Parameters:
2550: +  vec - the vector
2551: -  array - the GPU array

2553:    Notes:
2554:    You can return to the original GPU array with a call to VecCUDAResetArray()
2555:    It is not possible to use VecCUDAPlaceArray() and VecPlaceArray() at the
2556:    same time on the same vector.

2558:    `vec` does not take ownership of `array` in any way. The user must free `array` themselves
2559:    but be careful not to do so before the vector has either been destroyed, had its original
2560:    array restored with `VecCUDAResetArray()` or permanently replaced with
2561:    `VecCUDAReplaceArray()`.

2563:    Level: developer

2565: .seealso: `VecPlaceArray()`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`, `VecCUDAResetArray()`, `VecCUDAReplaceArray()`

2567: @*/
2568: PetscErrorCode VecCUDAPlaceArray(Vec vin, const PetscScalar a[])
2569: {
2571: #if defined(PETSC_HAVE_CUDA)
2572:   VecCUDACopyToGPU(vin);
2574:   ((Vec_Seq *)vin->data)->unplacedarray = (PetscScalar *)((Vec_CUDA *)vin->spptr)->GPUarray; /* save previous GPU array so reset can bring it back */
2575:   ((Vec_CUDA *)vin->spptr)->GPUarray    = (PetscScalar *)a;
2576:   vin->offloadmask                      = PETSC_OFFLOAD_GPU;
2577: #endif
2578:   PetscObjectStateIncrease((PetscObject)vin);
2579:   return 0;
2580: }

2582: /*@C
2583:    VecCUDAReplaceArray - Allows one to replace the GPU array in a vector
2584:    with a GPU array provided by the user. This is useful to avoid copying
2585:    a GPU array into a vector.

2587:    Not Collective

2589:    Input Parameters:
2590: +  vec - the vector
2591: -  array - the GPU array

2593:    Notes:
2594:    This permanently replaces the GPU array and frees the memory associated
2595:    with the old GPU array.

2597:    The memory passed in CANNOT be freed by the user. It will be freed
2598:    when the vector is destroyed.

2600:    Not supported from Fortran

2602:    Level: developer

2604: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`, `VecCUDAResetArray()`, `VecCUDAPlaceArray()`, `VecReplaceArray()`

2606: @*/
2607: PetscErrorCode VecCUDAReplaceArray(Vec vin, const PetscScalar a[])
2608: {
2609: #if defined(PETSC_HAVE_CUDA)
2610: #endif

2613: #if defined(PETSC_HAVE_CUDA)
2614:   if (((Vec_CUDA *)vin->spptr)->GPUarray_allocated) cudaFree(((Vec_CUDA *)vin->spptr)->GPUarray_allocated);
2615:   ((Vec_CUDA *)vin->spptr)->GPUarray_allocated = ((Vec_CUDA *)vin->spptr)->GPUarray = (PetscScalar *)a;
2616:   vin->offloadmask                                                                  = PETSC_OFFLOAD_GPU;
2617: #endif
2618:   PetscObjectStateIncrease((PetscObject)vin);
2619:   return 0;
2620: }

2622: /*@C
2623:    VecCUDAResetArray - Resets a vector to use its default memory. Call this
2624:    after the use of VecCUDAPlaceArray().

2626:    Not Collective

2628:    Input Parameters:
2629: .  vec - the vector

2631:    Level: developer

2633: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecPlaceArray()`, `VecResetArray()`, `VecCUDAPlaceArray()`, `VecCUDAReplaceArray()`

2635: @*/
2636: PetscErrorCode VecCUDAResetArray(Vec vin)
2637: {
2639: #if defined(PETSC_HAVE_CUDA)
2640:   VecCUDACopyToGPU(vin);
2641:   ((Vec_CUDA *)vin->spptr)->GPUarray    = (PetscScalar *)((Vec_Seq *)vin->data)->unplacedarray;
2642:   ((Vec_Seq *)vin->data)->unplacedarray = 0;
2643:   vin->offloadmask                      = PETSC_OFFLOAD_GPU;
2644: #endif
2645:   PetscObjectStateIncrease((PetscObject)vin);
2646:   return 0;
2647: }

2649: /*@C
2650:    VecHIPGetArray - Provides access to the HIP buffer inside a vector.

2652:    This function has semantics similar to VecGetArray():  the pointer
2653:    returned by this function points to a consistent view of the vector
2654:    data.  This may involve a copy operation of data from the host to the
2655:    device if the data on the device is out of date.  If the device
2656:    memory hasn't been allocated previously it will be allocated as part
2657:    of this function call.  VecHIPGetArray() assumes that
2658:    the user will modify the vector data.  This is similar to
2659:    intent(inout) in fortran.

2661:    The HIP device pointer has to be released by calling
2662:    VecHIPRestoreArray().  Upon restoring the vector data
2663:    the data on the host will be marked as out of date.  A subsequent
2664:    access of the host data will thus incur a data transfer from the
2665:    device to the host.

2667:    Input Parameter:
2668: .  v - the vector

2670:    Output Parameter:
2671: .  a - the HIP device pointer

2673:    Fortran note:
2674:    This function is not currently available from Fortran.

2676:    Level: intermediate

2678: .seealso: `VecHIPRestoreArray()`, `VecHIPGetArrayRead()`, `VecHIPGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2679: @*/
2680: PETSC_EXTERN PetscErrorCode VecHIPGetArray(Vec v, PetscScalar **a)
2681: {
2683: #if defined(PETSC_HAVE_HIP)
2684:   *a = 0;
2685:   VecHIPCopyToGPU(v);
2686:   *a = ((Vec_HIP *)v->spptr)->GPUarray;
2687: #endif
2688:   return 0;
2689: }

2691: /*@C
2692:    VecHIPRestoreArray - Restore a HIP device pointer previously acquired with VecHIPGetArray().

2694:    This marks the host data as out of date.  Subsequent access to the
2695:    vector data on the host side with for instance VecGetArray() incurs a
2696:    data transfer.

2698:    Input Parameters:
2699: +  v - the vector
2700: -  a - the HIP device pointer.  This pointer is invalid after
2701:        VecHIPRestoreArray() returns.

2703:    Fortran note:
2704:    This function is not currently available from Fortran.

2706:    Level: intermediate

2708: .seealso: `VecHIPGetArray()`, `VecHIPGetArrayRead()`, `VecHIPGetArrayWrite()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2709: @*/
2710: PETSC_EXTERN PetscErrorCode VecHIPRestoreArray(Vec v, PetscScalar **a)
2711: {
2713: #if defined(PETSC_HAVE_HIP)
2714:   v->offloadmask = PETSC_OFFLOAD_GPU;
2715: #endif

2717:   PetscObjectStateIncrease((PetscObject)v);
2718:   return 0;
2719: }

2721: /*@C
2722:    VecHIPGetArrayRead - Provides read access to the HIP buffer inside a vector.

2724:    This function is analogous to VecGetArrayRead():  The pointer
2725:    returned by this function points to a consistent view of the vector
2726:    data.  This may involve a copy operation of data from the host to the
2727:    device if the data on the device is out of date.  If the device
2728:    memory hasn't been allocated previously it will be allocated as part
2729:    of this function call.  VecHIPGetArrayRead() assumes that the
2730:    user will not modify the vector data.  This is analgogous to
2731:    intent(in) in Fortran.

2733:    The HIP device pointer has to be released by calling
2734:    VecHIPRestoreArrayRead().  If the data on the host side was
2735:    previously up to date it will remain so, i.e. data on both the device
2736:    and the host is up to date.  Accessing data on the host side does not
2737:    incur a device to host data transfer.

2739:    Input Parameter:
2740: .  v - the vector

2742:    Output Parameter:
2743: .  a - the HIP pointer.

2745:    Fortran note:
2746:    This function is not currently available from Fortran.

2748:    Level: intermediate

2750: .seealso: `VecHIPRestoreArrayRead()`, `VecHIPGetArray()`, `VecHIPGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2751: @*/
2752: PETSC_EXTERN PetscErrorCode VecHIPGetArrayRead(Vec v, const PetscScalar **a)
2753: {
2755: #if defined(PETSC_HAVE_HIP)
2756:   *a = 0;
2757:   VecHIPCopyToGPU(v);
2758:   *a = ((Vec_HIP *)v->spptr)->GPUarray;
2759: #endif
2760:   return 0;
2761: }

2763: /*@C
2764:    VecHIPRestoreArrayRead - Restore a HIP device pointer previously acquired with VecHIPGetArrayRead().

2766:    If the data on the host side was previously up to date it will remain
2767:    so, i.e. data on both the device and the host is up to date.
2768:    Accessing data on the host side e.g. with VecGetArray() does not
2769:    incur a device to host data transfer.

2771:    Input Parameters:
2772: +  v - the vector
2773: -  a - the HIP device pointer.  This pointer is invalid after
2774:        VecHIPRestoreArrayRead() returns.

2776:    Fortran note:
2777:    This function is not currently available from Fortran.

2779:    Level: intermediate

2781: .seealso: `VecHIPGetArrayRead()`, `VecHIPGetArrayWrite()`, `VecHIPGetArray()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2782: @*/
2783: PETSC_EXTERN PetscErrorCode VecHIPRestoreArrayRead(Vec v, const PetscScalar **a)
2784: {
2786:   *a = NULL;
2787:   return 0;
2788: }

2790: /*@C
2791:    VecHIPGetArrayWrite - Provides write access to the HIP buffer inside a vector.

2793:    The data pointed to by the device pointer is uninitialized.  The user
2794:    may not read from this data.  Furthermore, the entire array needs to
2795:    be filled by the user to obtain well-defined behaviour.  The device
2796:    memory will be allocated by this function if it hasn't been allocated
2797:    previously.  This is analogous to intent(out) in Fortran.

2799:    The device pointer needs to be released with
2800:    VecHIPRestoreArrayWrite().  When the pointer is released the
2801:    host data of the vector is marked as out of data.  Subsequent access
2802:    of the host data with e.g. VecGetArray() incurs a device to host data
2803:    transfer.

2805:    Input Parameter:
2806: .  v - the vector

2808:    Output Parameter:
2809: .  a - the HIP pointer

2811:    Fortran note:
2812:    This function is not currently available from Fortran.

2814:    Level: advanced

2816: .seealso: `VecHIPRestoreArrayWrite()`, `VecHIPGetArray()`, `VecHIPGetArrayRead()`, `VecHIPGetArrayWrite()`, `VecGetArray()`, `VecGetArrayRead()`
2817: @*/
2818: PETSC_EXTERN PetscErrorCode VecHIPGetArrayWrite(Vec v, PetscScalar **a)
2819: {
2821: #if defined(PETSC_HAVE_HIP)
2822:   *a = 0;
2823:   VecHIPAllocateCheck(v);
2824:   *a = ((Vec_HIP *)v->spptr)->GPUarray;
2825: #endif
2826:   return 0;
2827: }

2829: /*@C
2830:    VecHIPRestoreArrayWrite - Restore a HIP device pointer previously acquired with VecHIPGetArrayWrite().

2832:    Data on the host will be marked as out of date.  Subsequent access of
2833:    the data on the host side e.g. with VecGetArray() will incur a device
2834:    to host data transfer.

2836:    Input Parameters:
2837: +  v - the vector
2838: -  a - the HIP device pointer.  This pointer is invalid after
2839:        VecHIPRestoreArrayWrite() returns.

2841:    Fortran note:
2842:    This function is not currently available from Fortran.

2844:    Level: intermediate

2846: .seealso: `VecHIPGetArrayWrite()`, `VecHIPGetArray()`, `VecHIPGetArrayRead()`, `VecHIPGetArrayWrite()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`
2847: @*/
2848: PETSC_EXTERN PetscErrorCode VecHIPRestoreArrayWrite(Vec v, PetscScalar **a)
2849: {
2851: #if defined(PETSC_HAVE_HIP)
2852:   v->offloadmask = PETSC_OFFLOAD_GPU;
2853: #endif

2855:   PetscObjectStateIncrease((PetscObject)v);
2856:   return 0;
2857: }

2859: /*@C
2860:    VecHIPPlaceArray - Allows one to replace the GPU array in a vector with a
2861:    GPU array provided by the user. This is useful to avoid copying an
2862:    array into a vector.

2864:    Not Collective

2866:    Input Parameters:
2867: +  vec - the vector
2868: -  array - the GPU array

2870:    Notes:
2871:    You can return to the original GPU array with a call to VecHIPResetArray()
2872:    It is not possible to use VecHIPPlaceArray() and VecPlaceArray() at the
2873:    same time on the same vector.

2875:    `vec` does not take ownership of `array` in any way. The user must free `array` themselves
2876:    but be careful not to do so before the vector has either been destroyed, had its original
2877:    array restored with `VecHIPResetArray()` or permanently replaced with
2878:    `VecHIPReplaceArray()`.

2880:    Level: developer

2882: .seealso: `VecPlaceArray()`, `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecResetArray()`, `VecHIPResetArray()`, `VecHIPReplaceArray()`

2884: @*/
2885: PetscErrorCode VecHIPPlaceArray(Vec vin, const PetscScalar a[])
2886: {
2888: #if defined(PETSC_HAVE_HIP)
2889:   VecHIPCopyToGPU(vin);
2891:   ((Vec_Seq *)vin->data)->unplacedarray = (PetscScalar *)((Vec_HIP *)vin->spptr)->GPUarray; /* save previous GPU array so reset can bring it back */
2892:   ((Vec_HIP *)vin->spptr)->GPUarray     = (PetscScalar *)a;
2893:   vin->offloadmask                      = PETSC_OFFLOAD_GPU;
2894: #endif
2895:   PetscObjectStateIncrease((PetscObject)vin);
2896:   return 0;
2897: }

2899: /*@C
2900:    VecHIPReplaceArray - Allows one to replace the GPU array in a vector
2901:    with a GPU array provided by the user. This is useful to avoid copying
2902:    a GPU array into a vector.

2904:    Not Collective

2906:    Input Parameters:
2907: +  vec - the vector
2908: -  array - the GPU array

2910:    Notes:
2911:    This permanently replaces the GPU array and frees the memory associated
2912:    with the old GPU array.

2914:    The memory passed in CANNOT be freed by the user. It will be freed
2915:    when the vector is destroyed.

2917:    Not supported from Fortran

2919:    Level: developer

2921: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecPlaceArray()`, `VecResetArray()`, `VecHIPResetArray()`, `VecHIPPlaceArray()`, `VecReplaceArray()`

2923: @*/
2924: PetscErrorCode VecHIPReplaceArray(Vec vin, const PetscScalar a[])
2925: {
2927: #if defined(PETSC_HAVE_HIP)
2928:   hipFree(((Vec_HIP *)vin->spptr)->GPUarray);
2929:   ((Vec_HIP *)vin->spptr)->GPUarray = (PetscScalar *)a;
2930:   vin->offloadmask                  = PETSC_OFFLOAD_GPU;
2931: #endif
2932:   PetscObjectStateIncrease((PetscObject)vin);
2933:   return 0;
2934: }

2936: /*@C
2937:    VecHIPResetArray - Resets a vector to use its default memory. Call this
2938:    after the use of VecHIPPlaceArray().

2940:    Not Collective

2942:    Input Parameters:
2943: .  vec - the vector

2945:    Level: developer

2947: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecReplaceArray()`, `VecPlaceArray()`, `VecResetArray()`, `VecHIPPlaceArray()`, `VecHIPReplaceArray()`

2949: @*/
2950: PetscErrorCode VecHIPResetArray(Vec vin)
2951: {
2953: #if defined(PETSC_HAVE_HIP)
2954:   VecHIPCopyToGPU(vin);
2955:   ((Vec_HIP *)vin->spptr)->GPUarray     = (PetscScalar *)((Vec_Seq *)vin->data)->unplacedarray;
2956:   ((Vec_Seq *)vin->data)->unplacedarray = 0;
2957:   vin->offloadmask                      = PETSC_OFFLOAD_GPU;
2958: #endif
2959:   PetscObjectStateIncrease((PetscObject)vin);
2960:   return 0;
2961: }

2963: /*MC
2964:     VecDuplicateVecsF90 - Creates several vectors of the same type as an existing vector
2965:     and makes them accessible via a Fortran90 pointer.

2967:     Synopsis:
2968:     VecDuplicateVecsF90(Vec x,PetscInt n,{Vec, pointer :: y(:)},integer ierr)

2970:     Collective on Vec

2972:     Input Parameters:
2973: +   x - a vector to mimic
2974: -   n - the number of vectors to obtain

2976:     Output Parameters:
2977: +   y - Fortran90 pointer to the array of vectors
2978: -   ierr - error code

2980:     Example of Usage:
2981: .vb
2982: #include <petsc/finclude/petscvec.h>
2983:     use petscvec

2985:     Vec x
2986:     Vec, pointer :: y(:)
2987:     ....
2988:     call VecDuplicateVecsF90(x,2,y,ierr)
2989:     call VecSet(y(2),alpha,ierr)
2990:     call VecSet(y(2),alpha,ierr)
2991:     ....
2992:     call VecDestroyVecsF90(2,y,ierr)
2993: .ve

2995:     Notes:
2996:     Not yet supported for all F90 compilers

2998:     Use VecDestroyVecsF90() to free the space.

3000:     Level: beginner

3002: .seealso: `VecDestroyVecsF90()`, `VecDuplicateVecs()`

3004: M*/

3006: /*MC
3007:     VecRestoreArrayF90 - Restores a vector to a usable state after a call to
3008:     VecGetArrayF90().

3010:     Synopsis:
3011:     VecRestoreArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

3013:     Logically Collective on Vec

3015:     Input Parameters:
3016: +   x - vector
3017: -   xx_v - the Fortran90 pointer to the array

3019:     Output Parameter:
3020: .   ierr - error code

3022:     Example of Usage:
3023: .vb
3024: #include <petsc/finclude/petscvec.h>
3025:     use petscvec

3027:     PetscScalar, pointer :: xx_v(:)
3028:     ....
3029:     call VecGetArrayF90(x,xx_v,ierr)
3030:     xx_v(3) = a
3031:     call VecRestoreArrayF90(x,xx_v,ierr)
3032: .ve

3034:     Level: beginner

3036: .seealso: `VecGetArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrayReadF90()`

3038: M*/

3040: /*MC
3041:     VecDestroyVecsF90 - Frees a block of vectors obtained with VecDuplicateVecsF90().

3043:     Synopsis:
3044:     VecDestroyVecsF90(PetscInt n,{Vec, pointer :: x(:)},PetscErrorCode ierr)

3046:     Collective on Vec

3048:     Input Parameters:
3049: +   n - the number of vectors previously obtained
3050: -   x - pointer to array of vector pointers

3052:     Output Parameter:
3053: .   ierr - error code

3055:     Notes:
3056:     Not yet supported for all F90 compilers

3058:     Level: beginner

3060: .seealso: `VecDestroyVecs()`, `VecDuplicateVecsF90()`

3062: M*/

3064: /*MC
3065:     VecGetArrayF90 - Accesses a vector array from Fortran90. For default PETSc
3066:     vectors, VecGetArrayF90() returns a pointer to the local data array. Otherwise,
3067:     this routine is implementation dependent. You MUST call VecRestoreArrayF90()
3068:     when you no longer need access to the array.

3070:     Synopsis:
3071:     VecGetArrayF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

3073:     Logically Collective on Vec

3075:     Input Parameter:
3076: .   x - vector

3078:     Output Parameters:
3079: +   xx_v - the Fortran90 pointer to the array
3080: -   ierr - error code

3082:     Example of Usage:
3083: .vb
3084: #include <petsc/finclude/petscvec.h>
3085:     use petscvec

3087:     PetscScalar, pointer :: xx_v(:)
3088:     ....
3089:     call VecGetArrayF90(x,xx_v,ierr)
3090:     xx_v(3) = a
3091:     call VecRestoreArrayF90(x,xx_v,ierr)
3092: .ve

3094:     If you ONLY intend to read entries from the array and not change any entries you should use VecGetArrayReadF90().

3096:     Level: beginner

3098: .seealso: `VecRestoreArrayF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayReadF90()`

3100: M*/

3102: /*MC
3103:     VecGetArrayReadF90 - Accesses a read only array from Fortran90. For default PETSc
3104:     vectors, VecGetArrayF90() returns a pointer to the local data array. Otherwise,
3105:     this routine is implementation dependent. You MUST call VecRestoreArrayReadF90()
3106:     when you no longer need access to the array.

3108:     Synopsis:
3109:     VecGetArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

3111:     Logically Collective on Vec

3113:     Input Parameter:
3114: .   x - vector

3116:     Output Parameters:
3117: +   xx_v - the Fortran90 pointer to the array
3118: -   ierr - error code

3120:     Example of Usage:
3121: .vb
3122: #include <petsc/finclude/petscvec.h>
3123:     use petscvec

3125:     PetscScalar, pointer :: xx_v(:)
3126:     ....
3127:     call VecGetArrayReadF90(x,xx_v,ierr)
3128:     a = xx_v(3)
3129:     call VecRestoreArrayReadF90(x,xx_v,ierr)
3130: .ve

3132:     If you intend to write entries into the array you must use VecGetArrayF90().

3134:     Level: beginner

3136: .seealso: `VecRestoreArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecGetArrayF90()`

3138: M*/

3140: /*MC
3141:     VecRestoreArrayReadF90 - Restores a readonly vector to a usable state after a call to
3142:     VecGetArrayReadF90().

3144:     Synopsis:
3145:     VecRestoreArrayReadF90(Vec x,{Scalar, pointer :: xx_v(:)},integer ierr)

3147:     Logically Collective on Vec

3149:     Input Parameters:
3150: +   x - vector
3151: -   xx_v - the Fortran90 pointer to the array

3153:     Output Parameter:
3154: .   ierr - error code

3156:     Example of Usage:
3157: .vb
3158: #include <petsc/finclude/petscvec.h>
3159:     use petscvec

3161:     PetscScalar, pointer :: xx_v(:)
3162:     ....
3163:     call VecGetArrayReadF90(x,xx_v,ierr)
3164:     a = xx_v(3)
3165:     call VecRestoreArrayReadF90(x,xx_v,ierr)
3166: .ve

3168:     Level: beginner

3170: .seealso: `VecGetArrayReadF90()`, `VecGetArray()`, `VecRestoreArray()`, `VecGetArrayRead()`, `VecRestoreArrayRead()`, `VecRestoreArrayF90()`

3172: M*/

3174: /*@C
3175:    VecGetArray2d - Returns a pointer to a 2d contiguous array that contains this
3176:    processor's portion of the vector data.  You MUST call VecRestoreArray2d()
3177:    when you no longer need access to the array.

3179:    Logically Collective

3181:    Input Parameters:
3182: +  x - the vector
3183: .  m - first dimension of two dimensional array
3184: .  n - second dimension of two dimensional array
3185: .  mstart - first index you will use in first coordinate direction (often 0)
3186: -  nstart - first index in the second coordinate direction (often 0)

3188:    Output Parameter:
3189: .  a - location to put pointer to the array

3191:    Level: developer

3193:   Notes:
3194:    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
3195:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3196:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3197:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().

3199:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3201: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3202:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3203:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3204: @*/
3205: PetscErrorCode VecGetArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3206: {
3207:   PetscInt     i, N;
3208:   PetscScalar *aa;

3213:   VecGetLocalSize(x, &N);
3215:   VecGetArray(x, &aa);

3217:   PetscMalloc1(m, a);
3218:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
3219:   *a -= mstart;
3220:   return 0;
3221: }

3223: /*@C
3224:    VecGetArray2dWrite - Returns a pointer to a 2d contiguous array that will contain this
3225:    processor's portion of the vector data.  You MUST call VecRestoreArray2dWrite()
3226:    when you no longer need access to the array.

3228:    Logically Collective

3230:    Input Parameters:
3231: +  x - the vector
3232: .  m - first dimension of two dimensional array
3233: .  n - second dimension of two dimensional array
3234: .  mstart - first index you will use in first coordinate direction (often 0)
3235: -  nstart - first index in the second coordinate direction (often 0)

3237:    Output Parameter:
3238: .  a - location to put pointer to the array

3240:    Level: developer

3242:   Notes:
3243:    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
3244:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3245:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3246:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().

3248:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3250: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3251:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3252:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3253: @*/
3254: PetscErrorCode VecGetArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3255: {
3256:   PetscInt     i, N;
3257:   PetscScalar *aa;

3262:   VecGetLocalSize(x, &N);
3264:   VecGetArrayWrite(x, &aa);

3266:   PetscMalloc1(m, a);
3267:   for (i = 0; i < m; i++) (*a)[i] = aa + i * n - nstart;
3268:   *a -= mstart;
3269:   return 0;
3270: }

3272: /*@C
3273:    VecRestoreArray2d - Restores a vector after VecGetArray2d() has been called.

3275:    Logically Collective

3277:    Input Parameters:
3278: +  x - the vector
3279: .  m - first dimension of two dimensional array
3280: .  n - second dimension of the two dimensional array
3281: .  mstart - first index you will use in first coordinate direction (often 0)
3282: .  nstart - first index in the second coordinate direction (often 0)
3283: -  a - location of pointer to array obtained from VecGetArray2d()

3285:    Level: developer

3287:    Notes:
3288:    For regular PETSc vectors this routine does not involve any copies. For
3289:    any special vectors that do not store local vector data in a contiguous
3290:    array, this routine will copy the data back into the underlying
3291:    vector data structure from the array obtained with VecGetArray().

3293:    This routine actually zeros out the a pointer.

3295: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3296:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3297:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3298: @*/
3299: PetscErrorCode VecRestoreArray2d(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3300: {
3301:   void *dummy;

3306:   dummy = (void *)(*a + mstart);
3307:   PetscFree(dummy);
3308:   VecRestoreArray(x, NULL);
3309:   return 0;
3310: }

3312: /*@C
3313:    VecRestoreArray2dWrite - Restores a vector after VecGetArray2dWrite() has been called.

3315:    Logically Collective

3317:    Input Parameters:
3318: +  x - the vector
3319: .  m - first dimension of two dimensional array
3320: .  n - second dimension of the two dimensional array
3321: .  mstart - first index you will use in first coordinate direction (often 0)
3322: .  nstart - first index in the second coordinate direction (often 0)
3323: -  a - location of pointer to array obtained from VecGetArray2d()

3325:    Level: developer

3327:    Notes:
3328:    For regular PETSc vectors this routine does not involve any copies. For
3329:    any special vectors that do not store local vector data in a contiguous
3330:    array, this routine will copy the data back into the underlying
3331:    vector data structure from the array obtained with VecGetArray().

3333:    This routine actually zeros out the a pointer.

3335: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3336:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3337:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3338: @*/
3339: PetscErrorCode VecRestoreArray2dWrite(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3340: {
3341:   void *dummy;

3346:   dummy = (void *)(*a + mstart);
3347:   PetscFree(dummy);
3348:   VecRestoreArrayWrite(x, NULL);
3349:   return 0;
3350: }

3352: /*@C
3353:    VecGetArray1d - Returns a pointer to a 1d contiguous array that contains this
3354:    processor's portion of the vector data.  You MUST call VecRestoreArray1d()
3355:    when you no longer need access to the array.

3357:    Logically Collective

3359:    Input Parameters:
3360: +  x - the vector
3361: .  m - first dimension of two dimensional array
3362: -  mstart - first index you will use in first coordinate direction (often 0)

3364:    Output Parameter:
3365: .  a - location to put pointer to the array

3367:    Level: developer

3369:   Notes:
3370:    For a vector obtained from DMCreateLocalVector() mstart are likely
3371:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3372:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().

3374:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3376: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3377:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3378:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3379: @*/
3380: PetscErrorCode VecGetArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3381: {
3382:   PetscInt N;

3387:   VecGetLocalSize(x, &N);
3389:   VecGetArray(x, a);
3390:   *a -= mstart;
3391:   return 0;
3392: }

3394: /*@C
3395:    VecGetArray1dWrite - Returns a pointer to a 1d contiguous array that will contain this
3396:    processor's portion of the vector data.  You MUST call VecRestoreArray1dWrite()
3397:    when you no longer need access to the array.

3399:    Logically Collective

3401:    Input Parameters:
3402: +  x - the vector
3403: .  m - first dimension of two dimensional array
3404: -  mstart - first index you will use in first coordinate direction (often 0)

3406:    Output Parameter:
3407: .  a - location to put pointer to the array

3409:    Level: developer

3411:   Notes:
3412:    For a vector obtained from DMCreateLocalVector() mstart are likely
3413:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3414:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().

3416:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3418: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3419:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3420:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3421: @*/
3422: PetscErrorCode VecGetArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3423: {
3424:   PetscInt N;

3429:   VecGetLocalSize(x, &N);
3431:   VecGetArrayWrite(x, a);
3432:   *a -= mstart;
3433:   return 0;
3434: }

3436: /*@C
3437:    VecRestoreArray1d - Restores a vector after VecGetArray1d() has been called.

3439:    Logically Collective

3441:    Input Parameters:
3442: +  x - the vector
3443: .  m - first dimension of two dimensional array
3444: .  mstart - first index you will use in first coordinate direction (often 0)
3445: -  a - location of pointer to array obtained from VecGetArray21()

3447:    Level: developer

3449:    Notes:
3450:    For regular PETSc vectors this routine does not involve any copies. For
3451:    any special vectors that do not store local vector data in a contiguous
3452:    array, this routine will copy the data back into the underlying
3453:    vector data structure from the array obtained with VecGetArray1d().

3455:    This routine actually zeros out the a pointer.

3457: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3458:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3459:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3460: @*/
3461: PetscErrorCode VecRestoreArray1d(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3462: {
3465:   VecRestoreArray(x, NULL);
3466:   return 0;
3467: }

3469: /*@C
3470:    VecRestoreArray1dWrite - Restores a vector after VecGetArray1dWrite() has been called.

3472:    Logically Collective

3474:    Input Parameters:
3475: +  x - the vector
3476: .  m - first dimension of two dimensional array
3477: .  mstart - first index you will use in first coordinate direction (often 0)
3478: -  a - location of pointer to array obtained from VecGetArray21()

3480:    Level: developer

3482:    Notes:
3483:    For regular PETSc vectors this routine does not involve any copies. For
3484:    any special vectors that do not store local vector data in a contiguous
3485:    array, this routine will copy the data back into the underlying
3486:    vector data structure from the array obtained with VecGetArray1d().

3488:    This routine actually zeros out the a pointer.

3490: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3491:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3492:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3493: @*/
3494: PetscErrorCode VecRestoreArray1dWrite(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
3495: {
3498:   VecRestoreArrayWrite(x, NULL);
3499:   return 0;
3500: }

3502: /*@C
3503:    VecGetArray3d - Returns a pointer to a 3d contiguous array that contains this
3504:    processor's portion of the vector data.  You MUST call VecRestoreArray3d()
3505:    when you no longer need access to the array.

3507:    Logically Collective

3509:    Input Parameters:
3510: +  x - the vector
3511: .  m - first dimension of three dimensional array
3512: .  n - second dimension of three dimensional array
3513: .  p - third dimension of three dimensional array
3514: .  mstart - first index you will use in first coordinate direction (often 0)
3515: .  nstart - first index in the second coordinate direction (often 0)
3516: -  pstart - first index in the third coordinate direction (often 0)

3518:    Output Parameter:
3519: .  a - location to put pointer to the array

3521:    Level: developer

3523:   Notes:
3524:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3525:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3526:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3527:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().

3529:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3531: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3532:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3533:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3534: @*/
3535: PetscErrorCode VecGetArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3536: {
3537:   PetscInt     i, N, j;
3538:   PetscScalar *aa, **b;

3543:   VecGetLocalSize(x, &N);
3545:   VecGetArray(x, &aa);

3547:   PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a);
3548:   b = (PetscScalar **)((*a) + m);
3549:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3550:   for (i = 0; i < m; i++)
3551:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;
3552:   *a -= mstart;
3553:   return 0;
3554: }

3556: /*@C
3557:    VecGetArray3dWrite - Returns a pointer to a 3d contiguous array that will contain this
3558:    processor's portion of the vector data.  You MUST call VecRestoreArray3dWrite()
3559:    when you no longer need access to the array.

3561:    Logically Collective

3563:    Input Parameters:
3564: +  x - the vector
3565: .  m - first dimension of three dimensional array
3566: .  n - second dimension of three dimensional array
3567: .  p - third dimension of three dimensional array
3568: .  mstart - first index you will use in first coordinate direction (often 0)
3569: .  nstart - first index in the second coordinate direction (often 0)
3570: -  pstart - first index in the third coordinate direction (often 0)

3572:    Output Parameter:
3573: .  a - location to put pointer to the array

3575:    Level: developer

3577:   Notes:
3578:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3579:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3580:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3581:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().

3583:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3585: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3586:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3587:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3588: @*/
3589: PetscErrorCode VecGetArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3590: {
3591:   PetscInt     i, N, j;
3592:   PetscScalar *aa, **b;

3597:   VecGetLocalSize(x, &N);
3599:   VecGetArrayWrite(x, &aa);

3601:   PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a);
3602:   b = (PetscScalar **)((*a) + m);
3603:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3604:   for (i = 0; i < m; i++)
3605:     for (j = 0; j < n; j++) b[i * n + j] = aa + i * n * p + j * p - pstart;

3607:   *a -= mstart;
3608:   return 0;
3609: }

3611: /*@C
3612:    VecRestoreArray3d - Restores a vector after VecGetArray3d() has been called.

3614:    Logically Collective

3616:    Input Parameters:
3617: +  x - the vector
3618: .  m - first dimension of three dimensional array
3619: .  n - second dimension of the three dimensional array
3620: .  p - third dimension of the three dimensional array
3621: .  mstart - first index you will use in first coordinate direction (often 0)
3622: .  nstart - first index in the second coordinate direction (often 0)
3623: .  pstart - first index in the third coordinate direction (often 0)
3624: -  a - location of pointer to array obtained from VecGetArray3d()

3626:    Level: developer

3628:    Notes:
3629:    For regular PETSc vectors this routine does not involve any copies. For
3630:    any special vectors that do not store local vector data in a contiguous
3631:    array, this routine will copy the data back into the underlying
3632:    vector data structure from the array obtained with VecGetArray().

3634:    This routine actually zeros out the a pointer.

3636: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3637:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3638:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3639: @*/
3640: PetscErrorCode VecRestoreArray3d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3641: {
3642:   void *dummy;

3647:   dummy = (void *)(*a + mstart);
3648:   PetscFree(dummy);
3649:   VecRestoreArray(x, NULL);
3650:   return 0;
3651: }

3653: /*@C
3654:    VecRestoreArray3dWrite - Restores a vector after VecGetArray3dWrite() has been called.

3656:    Logically Collective

3658:    Input Parameters:
3659: +  x - the vector
3660: .  m - first dimension of three dimensional array
3661: .  n - second dimension of the three dimensional array
3662: .  p - third dimension of the three dimensional array
3663: .  mstart - first index you will use in first coordinate direction (often 0)
3664: .  nstart - first index in the second coordinate direction (often 0)
3665: .  pstart - first index in the third coordinate direction (often 0)
3666: -  a - location of pointer to array obtained from VecGetArray3d()

3668:    Level: developer

3670:    Notes:
3671:    For regular PETSc vectors this routine does not involve any copies. For
3672:    any special vectors that do not store local vector data in a contiguous
3673:    array, this routine will copy the data back into the underlying
3674:    vector data structure from the array obtained with VecGetArray().

3676:    This routine actually zeros out the a pointer.

3678: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3679:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3680:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3681: @*/
3682: PetscErrorCode VecRestoreArray3dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
3683: {
3684:   void *dummy;

3689:   dummy = (void *)(*a + mstart);
3690:   PetscFree(dummy);
3691:   VecRestoreArrayWrite(x, NULL);
3692:   return 0;
3693: }

3695: /*@C
3696:    VecGetArray4d - Returns a pointer to a 4d contiguous array that contains this
3697:    processor's portion of the vector data.  You MUST call VecRestoreArray4d()
3698:    when you no longer need access to the array.

3700:    Logically Collective

3702:    Input Parameters:
3703: +  x - the vector
3704: .  m - first dimension of four dimensional array
3705: .  n - second dimension of four dimensional array
3706: .  p - third dimension of four dimensional array
3707: .  q - fourth dimension of four dimensional array
3708: .  mstart - first index you will use in first coordinate direction (often 0)
3709: .  nstart - first index in the second coordinate direction (often 0)
3710: .  pstart - first index in the third coordinate direction (often 0)
3711: -  qstart - first index in the fourth coordinate direction (often 0)

3713:    Output Parameter:
3714: .  a - location to put pointer to the array

3716:    Level: beginner

3718:   Notes:
3719:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3720:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3721:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3722:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().

3724:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3726: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3727:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3728:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3729: @*/
3730: PetscErrorCode VecGetArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3731: {
3732:   PetscInt     i, N, j, k;
3733:   PetscScalar *aa, ***b, **c;

3738:   VecGetLocalSize(x, &N);
3740:   VecGetArray(x, &aa);

3742:   PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a);
3743:   b = (PetscScalar ***)((*a) + m);
3744:   c = (PetscScalar **)(b + m * n);
3745:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3746:   for (i = 0; i < m; i++)
3747:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3748:   for (i = 0; i < m; i++)
3749:     for (j = 0; j < n; j++)
3750:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3751:   *a -= mstart;
3752:   return 0;
3753: }

3755: /*@C
3756:    VecGetArray4dWrite - Returns a pointer to a 4d contiguous array that will contain this
3757:    processor's portion of the vector data.  You MUST call VecRestoreArray4dWrite()
3758:    when you no longer need access to the array.

3760:    Logically Collective

3762:    Input Parameters:
3763: +  x - the vector
3764: .  m - first dimension of four dimensional array
3765: .  n - second dimension of four dimensional array
3766: .  p - third dimension of four dimensional array
3767: .  q - fourth dimension of four dimensional array
3768: .  mstart - first index you will use in first coordinate direction (often 0)
3769: .  nstart - first index in the second coordinate direction (often 0)
3770: .  pstart - first index in the third coordinate direction (often 0)
3771: -  qstart - first index in the fourth coordinate direction (often 0)

3773:    Output Parameter:
3774: .  a - location to put pointer to the array

3776:    Level: beginner

3778:   Notes:
3779:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
3780:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3781:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3782:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().

3784:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3786: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3787:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3788:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3789: @*/
3790: PetscErrorCode VecGetArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3791: {
3792:   PetscInt     i, N, j, k;
3793:   PetscScalar *aa, ***b, **c;

3798:   VecGetLocalSize(x, &N);
3800:   VecGetArrayWrite(x, &aa);

3802:   PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a);
3803:   b = (PetscScalar ***)((*a) + m);
3804:   c = (PetscScalar **)(b + m * n);
3805:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
3806:   for (i = 0; i < m; i++)
3807:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
3808:   for (i = 0; i < m; i++)
3809:     for (j = 0; j < n; j++)
3810:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = aa + i * n * p * q + j * p * q + k * q - qstart;
3811:   *a -= mstart;
3812:   return 0;
3813: }

3815: /*@C
3816:    VecRestoreArray4d - Restores a vector after VecGetArray3d() has been called.

3818:    Logically Collective

3820:    Input Parameters:
3821: +  x - the vector
3822: .  m - first dimension of four dimensional array
3823: .  n - second dimension of the four dimensional array
3824: .  p - third dimension of the four dimensional array
3825: .  q - fourth dimension of the four dimensional array
3826: .  mstart - first index you will use in first coordinate direction (often 0)
3827: .  nstart - first index in the second coordinate direction (often 0)
3828: .  pstart - first index in the third coordinate direction (often 0)
3829: .  qstart - first index in the fourth coordinate direction (often 0)
3830: -  a - location of pointer to array obtained from VecGetArray4d()

3832:    Level: beginner

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().

3840:    This routine actually zeros out the a pointer.

3842: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3843:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3844:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3845: @*/
3846: PetscErrorCode VecRestoreArray4d(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3847: {
3848:   void *dummy;

3853:   dummy = (void *)(*a + mstart);
3854:   PetscFree(dummy);
3855:   VecRestoreArray(x, NULL);
3856:   return 0;
3857: }

3859: /*@C
3860:    VecRestoreArray4dWrite - Restores a vector after VecGetArray3dWrite() has been called.

3862:    Logically Collective

3864:    Input Parameters:
3865: +  x - the vector
3866: .  m - first dimension of four dimensional array
3867: .  n - second dimension of the four dimensional array
3868: .  p - third dimension of the four dimensional array
3869: .  q - fourth dimension of the four dimensional array
3870: .  mstart - first index you will use in first coordinate direction (often 0)
3871: .  nstart - first index in the second coordinate direction (often 0)
3872: .  pstart - first index in the third coordinate direction (often 0)
3873: .  qstart - first index in the fourth coordinate direction (often 0)
3874: -  a - location of pointer to array obtained from VecGetArray4d()

3876:    Level: beginner

3878:    Notes:
3879:    For regular PETSc vectors this routine does not involve any copies. For
3880:    any special vectors that do not store local vector data in a contiguous
3881:    array, this routine will copy the data back into the underlying
3882:    vector data structure from the array obtained with VecGetArray().

3884:    This routine actually zeros out the a pointer.

3886: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3887:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3888:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
3889: @*/
3890: PetscErrorCode VecRestoreArray4dWrite(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
3891: {
3892:   void *dummy;

3897:   dummy = (void *)(*a + mstart);
3898:   PetscFree(dummy);
3899:   VecRestoreArrayWrite(x, NULL);
3900:   return 0;
3901: }

3903: /*@C
3904:    VecGetArray2dRead - Returns a pointer to a 2d contiguous array that contains this
3905:    processor's portion of the vector data.  You MUST call VecRestoreArray2dRead()
3906:    when you no longer need access to the array.

3908:    Logically Collective

3910:    Input Parameters:
3911: +  x - the vector
3912: .  m - first dimension of two dimensional array
3913: .  n - second dimension of two dimensional array
3914: .  mstart - first index you will use in first coordinate direction (often 0)
3915: -  nstart - first index in the second coordinate direction (often 0)

3917:    Output Parameter:
3918: .  a - location to put pointer to the array

3920:    Level: developer

3922:   Notes:
3923:    For a vector obtained from DMCreateLocalVector() mstart and nstart are likely
3924:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
3925:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
3926:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray2d().

3928:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

3930: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
3931:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
3932:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3933: @*/
3934: PetscErrorCode VecGetArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3935: {
3936:   PetscInt           i, N;
3937:   const PetscScalar *aa;

3942:   VecGetLocalSize(x, &N);
3944:   VecGetArrayRead(x, &aa);

3946:   PetscMalloc1(m, a);
3947:   for (i = 0; i < m; i++) (*a)[i] = (PetscScalar *)aa + i * n - nstart;
3948:   *a -= mstart;
3949:   return 0;
3950: }

3952: /*@C
3953:    VecRestoreArray2dRead - Restores a vector after VecGetArray2dRead() has been called.

3955:    Logically Collective

3957:    Input Parameters:
3958: +  x - the vector
3959: .  m - first dimension of two dimensional array
3960: .  n - second dimension of the two dimensional array
3961: .  mstart - first index you will use in first coordinate direction (often 0)
3962: .  nstart - first index in the second coordinate direction (often 0)
3963: -  a - location of pointer to array obtained from VecGetArray2d()

3965:    Level: developer

3967:    Notes:
3968:    For regular PETSc vectors this routine does not involve any copies. For
3969:    any special vectors that do not store local vector data in a contiguous
3970:    array, this routine will copy the data back into the underlying
3971:    vector data structure from the array obtained with VecGetArray().

3973:    This routine actually zeros out the a pointer.

3975: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
3976:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
3977:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
3978: @*/
3979: PetscErrorCode VecRestoreArray2dRead(Vec x, PetscInt m, PetscInt n, PetscInt mstart, PetscInt nstart, PetscScalar **a[])
3980: {
3981:   void *dummy;

3986:   dummy = (void *)(*a + mstart);
3987:   PetscFree(dummy);
3988:   VecRestoreArrayRead(x, NULL);
3989:   return 0;
3990: }

3992: /*@C
3993:    VecGetArray1dRead - Returns a pointer to a 1d contiguous array that contains this
3994:    processor's portion of the vector data.  You MUST call VecRestoreArray1dRead()
3995:    when you no longer need access to the array.

3997:    Logically Collective

3999:    Input Parameters:
4000: +  x - the vector
4001: .  m - first dimension of two dimensional array
4002: -  mstart - first index you will use in first coordinate direction (often 0)

4004:    Output Parameter:
4005: .  a - location to put pointer to the array

4007:    Level: developer

4009:   Notes:
4010:    For a vector obtained from DMCreateLocalVector() mstart are likely
4011:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
4012:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners().

4014:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

4016: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
4017:           `VecRestoreArray2d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
4018:           `VecGetArray2d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
4019: @*/
4020: PetscErrorCode VecGetArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
4021: {
4022:   PetscInt N;

4027:   VecGetLocalSize(x, &N);
4029:   VecGetArrayRead(x, (const PetscScalar **)a);
4030:   *a -= mstart;
4031:   return 0;
4032: }

4034: /*@C
4035:    VecRestoreArray1dRead - Restores a vector after VecGetArray1dRead() has been called.

4037:    Logically Collective

4039:    Input Parameters:
4040: +  x - the vector
4041: .  m - first dimension of two dimensional array
4042: .  mstart - first index you will use in first coordinate direction (often 0)
4043: -  a - location of pointer to array obtained from VecGetArray21()

4045:    Level: developer

4047:    Notes:
4048:    For regular PETSc vectors this routine does not involve any copies. For
4049:    any special vectors that do not store local vector data in a contiguous
4050:    array, this routine will copy the data back into the underlying
4051:    vector data structure from the array obtained with VecGetArray1dRead().

4053:    This routine actually zeros out the a pointer.

4055: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
4056:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
4057:           `VecGetArray1d()`, `VecRestoreArray2d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
4058: @*/
4059: PetscErrorCode VecRestoreArray1dRead(Vec x, PetscInt m, PetscInt mstart, PetscScalar *a[])
4060: {
4063:   VecRestoreArrayRead(x, NULL);
4064:   return 0;
4065: }

4067: /*@C
4068:    VecGetArray3dRead - Returns a pointer to a 3d contiguous array that contains this
4069:    processor's portion of the vector data.  You MUST call VecRestoreArray3dRead()
4070:    when you no longer need access to the array.

4072:    Logically Collective

4074:    Input Parameters:
4075: +  x - the vector
4076: .  m - first dimension of three dimensional array
4077: .  n - second dimension of three dimensional array
4078: .  p - third dimension of three dimensional array
4079: .  mstart - first index you will use in first coordinate direction (often 0)
4080: .  nstart - first index in the second coordinate direction (often 0)
4081: -  pstart - first index in the third coordinate direction (often 0)

4083:    Output Parameter:
4084: .  a - location to put pointer to the array

4086:    Level: developer

4088:   Notes:
4089:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
4090:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
4091:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
4092:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3dRead().

4094:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

4096: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
4097:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
4098:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
4099: @*/
4100: PetscErrorCode VecGetArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
4101: {
4102:   PetscInt           i, N, j;
4103:   const PetscScalar *aa;
4104:   PetscScalar      **b;

4109:   VecGetLocalSize(x, &N);
4111:   VecGetArrayRead(x, &aa);

4113:   PetscMalloc(m * sizeof(PetscScalar **) + m * n * sizeof(PetscScalar *), a);
4114:   b = (PetscScalar **)((*a) + m);
4115:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
4116:   for (i = 0; i < m; i++)
4117:     for (j = 0; j < n; j++) b[i * n + j] = (PetscScalar *)aa + i * n * p + j * p - pstart;
4118:   *a -= mstart;
4119:   return 0;
4120: }

4122: /*@C
4123:    VecRestoreArray3dRead - Restores a vector after VecGetArray3dRead() has been called.

4125:    Logically Collective

4127:    Input Parameters:
4128: +  x - the vector
4129: .  m - first dimension of three dimensional array
4130: .  n - second dimension of the three dimensional array
4131: .  p - third dimension of the three dimensional array
4132: .  mstart - first index you will use in first coordinate direction (often 0)
4133: .  nstart - first index in the second coordinate direction (often 0)
4134: .  pstart - first index in the third coordinate direction (often 0)
4135: -  a - location of pointer to array obtained from VecGetArray3dRead()

4137:    Level: developer

4139:    Notes:
4140:    For regular PETSc vectors this routine does not involve any copies. For
4141:    any special vectors that do not store local vector data in a contiguous
4142:    array, this routine will copy the data back into the underlying
4143:    vector data structure from the array obtained with VecGetArray().

4145:    This routine actually zeros out the a pointer.

4147: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
4148:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
4149:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
4150: @*/
4151: PetscErrorCode VecRestoreArray3dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscScalar ***a[])
4152: {
4153:   void *dummy;

4158:   dummy = (void *)(*a + mstart);
4159:   PetscFree(dummy);
4160:   VecRestoreArrayRead(x, NULL);
4161:   return 0;
4162: }

4164: /*@C
4165:    VecGetArray4dRead - Returns a pointer to a 4d contiguous array that contains this
4166:    processor's portion of the vector data.  You MUST call VecRestoreArray4dRead()
4167:    when you no longer need access to the array.

4169:    Logically Collective

4171:    Input Parameters:
4172: +  x - the vector
4173: .  m - first dimension of four dimensional array
4174: .  n - second dimension of four dimensional array
4175: .  p - third dimension of four dimensional array
4176: .  q - fourth dimension of four dimensional array
4177: .  mstart - first index you will use in first coordinate direction (often 0)
4178: .  nstart - first index in the second coordinate direction (often 0)
4179: .  pstart - first index in the third coordinate direction (often 0)
4180: -  qstart - first index in the fourth coordinate direction (often 0)

4182:    Output Parameter:
4183: .  a - location to put pointer to the array

4185:    Level: beginner

4187:   Notes:
4188:    For a vector obtained from DMCreateLocalVector() mstart, nstart, and pstart are likely
4189:    obtained from the corner indices obtained from DMDAGetGhostCorners() while for
4190:    DMCreateGlobalVector() they are the corner indices from DMDAGetCorners(). In both cases
4191:    the arguments from DMDAGet[Ghost]Corners() are reversed in the call to VecGetArray3d().

4193:    For standard PETSc vectors this is an inexpensive call; it does not copy the vector values.

4195: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecGetArrays()`, `VecGetArrayF90()`, `VecPlaceArray()`,
4196:           `VecRestoreArray2d()`, `DMDAVecGetarray()`, `DMDAVecRestoreArray()`, `VecGetArray3d()`, `VecRestoreArray3d()`,
4197:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`
4198: @*/
4199: PetscErrorCode VecGetArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
4200: {
4201:   PetscInt           i, N, j, k;
4202:   const PetscScalar *aa;
4203:   PetscScalar     ***b, **c;

4208:   VecGetLocalSize(x, &N);
4210:   VecGetArrayRead(x, &aa);

4212:   PetscMalloc(m * sizeof(PetscScalar ***) + m * n * sizeof(PetscScalar **) + m * n * p * sizeof(PetscScalar *), a);
4213:   b = (PetscScalar ***)((*a) + m);
4214:   c = (PetscScalar **)(b + m * n);
4215:   for (i = 0; i < m; i++) (*a)[i] = b + i * n - nstart;
4216:   for (i = 0; i < m; i++)
4217:     for (j = 0; j < n; j++) b[i * n + j] = c + i * n * p + j * p - pstart;
4218:   for (i = 0; i < m; i++)
4219:     for (j = 0; j < n; j++)
4220:       for (k = 0; k < p; k++) c[i * n * p + j * p + k] = (PetscScalar *)aa + i * n * p * q + j * p * q + k * q - qstart;
4221:   *a -= mstart;
4222:   return 0;
4223: }

4225: /*@C
4226:    VecRestoreArray4dRead - Restores a vector after VecGetArray3d() has been called.

4228:    Logically Collective

4230:    Input Parameters:
4231: +  x - the vector
4232: .  m - first dimension of four dimensional array
4233: .  n - second dimension of the four dimensional array
4234: .  p - third dimension of the four dimensional array
4235: .  q - fourth dimension of the four dimensional array
4236: .  mstart - first index you will use in first coordinate direction (often 0)
4237: .  nstart - first index in the second coordinate direction (often 0)
4238: .  pstart - first index in the third coordinate direction (often 0)
4239: .  qstart - first index in the fourth coordinate direction (often 0)
4240: -  a - location of pointer to array obtained from VecGetArray4dRead()

4242:    Level: beginner

4244:    Notes:
4245:    For regular PETSc vectors this routine does not involve any copies. For
4246:    any special vectors that do not store local vector data in a contiguous
4247:    array, this routine will copy the data back into the underlying
4248:    vector data structure from the array obtained with VecGetArray().

4250:    This routine actually zeros out the a pointer.

4252: .seealso: `VecGetArray()`, `VecRestoreArray()`, `VecRestoreArrays()`, `VecRestoreArrayF90()`, `VecPlaceArray()`,
4253:           `VecGetArray2d()`, `VecGetArray3d()`, `VecRestoreArray3d()`, `DMDAVecGetArray()`, `DMDAVecRestoreArray()`
4254:           `VecGetArray1d()`, `VecRestoreArray1d()`, `VecGetArray4d()`, `VecRestoreArray4d()`, `VecGet`
4255: @*/
4256: PetscErrorCode VecRestoreArray4dRead(Vec x, PetscInt m, PetscInt n, PetscInt p, PetscInt q, PetscInt mstart, PetscInt nstart, PetscInt pstart, PetscInt qstart, PetscScalar ****a[])
4257: {
4258:   void *dummy;

4263:   dummy = (void *)(*a + mstart);
4264:   PetscFree(dummy);
4265:   VecRestoreArrayRead(x, NULL);
4266:   return 0;
4267: }

4269: #if defined(PETSC_USE_DEBUG)

4271: /*@
4272:    VecLockGet  - Gets the current lock status of a vector

4274:    Logically Collective on Vec

4276:    Input Parameter:
4277: .  x - the vector

4279:    Output Parameter:
4280: .  state - greater than zero indicates the vector is locked for read; less then zero indicates the vector is
4281:            locked for write; equal to zero means the vector is unlocked, that is, it is free to read or write.

4283:    Level: beginner

4285: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`
4286: @*/
4287: PetscErrorCode VecLockGet(Vec x, PetscInt *state)
4288: {
4290:   *state = x->lock;
4291:   return 0;
4292: }

4294: PetscErrorCode VecLockGetLocation(Vec x, const char *file[], const char *func[], int *line)
4295: {
4300:   {
4301:     const int index = x->lockstack.currentsize - 1;

4304:     *file = x->lockstack.file[index];
4305:     *func = x->lockstack.function[index];
4306:     *line = x->lockstack.line[index];
4307:   }
4308:   return 0;
4309: }

4311: /*@
4312:    VecLockReadPush  - Pushes a read-only lock on a vector to prevent it from writing

4314:    Logically Collective on Vec

4316:    Input Parameter:
4317: .  x - the vector

4319:    Notes:
4320:     If this is set then calls to VecGetArray() or VecSetValues() or any other routines that change the vectors values will fail.

4322:     The call can be nested, i.e., called multiple times on the same vector, but each VecLockReadPush(x) has to have one matching
4323:     VecLockReadPop(x), which removes the latest read-only lock.

4325:    Level: beginner

4327: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPop()`, `VecLockGet()`
4328: @*/
4329: PetscErrorCode VecLockReadPush(Vec x)
4330: {
4331:   const char *file, *func;
4332:   int         index, line;

4336:   if ((index = petscstack.currentsize - 2) == -1) {
4337:     // vec was locked "outside" of petsc, either in user-land or main. the error message will
4338:     // now show this function as the culprit, but it will include the stacktrace
4339:     file = "unknown user-file";
4340:     func = "unknown_user_function";
4341:     line = 0;
4342:   } else {
4344:     file = petscstack.file[index];
4345:     func = petscstack.function[index];
4346:     line = petscstack.line[index];
4347:   }
4348:   PetscStackPush_Private(x->lockstack, file, func, line, petscstack.petscroutine[index], PETSC_FALSE);
4349:   return 0;
4350: }

4352: /*@
4353:    VecLockReadPop  - Pops a read-only lock from a vector

4355:    Logically Collective on Vec

4357:    Input Parameter:
4358: .  x - the vector

4360:    Level: beginner

4362: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockGet()`
4363: @*/
4364: PetscErrorCode VecLockReadPop(Vec x)
4365: {
4368:   {
4369:     const char *previous = x->lockstack.function[x->lockstack.currentsize - 1];

4371:     PetscStackPop_Private(x->lockstack, previous);
4372:   }
4373:   return 0;
4374: }

4376: /*@C
4377:    VecLockWriteSet  - Lock or unlock a vector for exclusive read/write access

4379:    Logically Collective on Vec

4381:    Input Parameters:
4382: +  x   - the vector
4383: -  flg - PETSC_TRUE to lock the vector for exclusive read/write access; PETSC_FALSE to unlock it.

4385:    Notes:
4386:     The function is usefull in split-phase computations, which usually have a begin phase and an end phase.
4387:     One can call VecLockWriteSet(x,PETSC_TRUE) in the begin phase to lock a vector for exclusive
4388:     access, and call VecLockWriteSet(x,PETSC_FALSE) in the end phase to unlock the vector from exclusive
4389:     access. In this way, one is ensured no other operations can access the vector in between. The code may like

4391:        VecGetArray(x,&xdata); // begin phase
4392:        VecLockWriteSet(v,PETSC_TRUE);

4394:        Other operations, which can not acceess x anymore (they can access xdata, of course)

4396:        VecRestoreArray(x,&vdata); // end phase
4397:        VecLockWriteSet(v,PETSC_FALSE);

4399:     The call can not be nested on the same vector, in other words, one can not call VecLockWriteSet(x,PETSC_TRUE)
4400:     again before calling VecLockWriteSet(v,PETSC_FALSE).

4402:    Level: beginner

4404: .seealso: `VecRestoreArray()`, `VecGetArrayRead()`, `VecLockReadPush()`, `VecLockReadPop()`, `VecLockGet()`
4405: @*/
4406: PetscErrorCode VecLockWriteSet(Vec x, PetscBool flg)
4407: {
4409:   if (flg) {
4412:     x->lock = -1;
4413:   } else {
4415:     x->lock = 0;
4416:   }
4417:   return 0;
4418: }

4420: /*@
4421:    VecLockPush  - Pushes a read-only lock on a vector to prevent it from writing

4423:    Level: deprecated

4425: .seealso: `VecLockReadPush()`
4426: @*/
4427: PetscErrorCode VecLockPush(Vec x)
4428: {
4429:   VecLockReadPush(x);
4430:   return 0;
4431: }

4433: /*@
4434:    VecLockPop  - Pops a read-only lock from a vector

4436:    Level: deprecated

4438: .seealso: `VecLockReadPop()`
4439: @*/
4440: PetscErrorCode VecLockPop(Vec x)
4441: {
4442:   VecLockReadPop(x);
4443:   return 0;
4444: }

4446: #endif